@odoo/o-spreadsheet 18.2.0-alpha.2 → 18.2.0-alpha.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 +697 -526
- package/dist/o-spreadsheet.d.ts +59 -13
- package/dist/o-spreadsheet.esm.js +697 -526
- package/dist/o-spreadsheet.iife.js +697 -526
- package/dist/o-spreadsheet.iife.min.js +261 -258
- package/dist/o_spreadsheet.xml +55 -43
- 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.2.0-alpha.
|
|
6
|
-
* @date 2025-01-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.2.0-alpha.4
|
|
6
|
+
* @date 2025-01-29T06:30:12.773Z
|
|
7
|
+
* @hash 6838c26
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -4391,15 +4391,18 @@ function dichotomicSearch(data, target, mode, sortOrder, rangeLength, getValueIn
|
|
|
4391
4391
|
let currentIndex;
|
|
4392
4392
|
let currentVal;
|
|
4393
4393
|
let currentType;
|
|
4394
|
+
const getValue = sortOrder === "desc"
|
|
4395
|
+
? (i) => normalizeValue(getValueInData(data, rangeLength - i - 1))
|
|
4396
|
+
: (i) => normalizeValue(getValueInData(data, i));
|
|
4394
4397
|
while (indexRight - indexLeft >= 0) {
|
|
4395
4398
|
indexMedian = Math.floor((indexLeft + indexRight) / 2);
|
|
4396
4399
|
currentIndex = indexMedian;
|
|
4397
|
-
currentVal =
|
|
4400
|
+
currentVal = getValue(currentIndex);
|
|
4398
4401
|
currentType = typeof currentVal;
|
|
4399
4402
|
// 1 - linear search to find value with the same type
|
|
4400
4403
|
while (indexLeft < currentIndex && targetType !== currentType) {
|
|
4401
4404
|
currentIndex--;
|
|
4402
|
-
currentVal =
|
|
4405
|
+
currentVal = getValue(currentIndex);
|
|
4403
4406
|
currentType = typeof currentVal;
|
|
4404
4407
|
}
|
|
4405
4408
|
if (currentType !== targetType || currentVal === undefined || currentVal === null) {
|
|
@@ -4415,8 +4418,7 @@ function dichotomicSearch(data, target, mode, sortOrder, rangeLength, getValueIn
|
|
|
4415
4418
|
if (matchVal === undefined ||
|
|
4416
4419
|
matchVal === null ||
|
|
4417
4420
|
matchVal < currentVal ||
|
|
4418
|
-
(matchVal === currentVal &&
|
|
4419
|
-
(matchVal === currentVal && sortOrder === "desc" && matchValIndex > currentIndex)) {
|
|
4421
|
+
(matchVal === currentVal && matchValIndex < currentIndex)) {
|
|
4420
4422
|
matchVal = currentVal;
|
|
4421
4423
|
matchValIndex = currentIndex;
|
|
4422
4424
|
}
|
|
@@ -4424,15 +4426,13 @@ function dichotomicSearch(data, target, mode, sortOrder, rangeLength, getValueIn
|
|
|
4424
4426
|
else if (mode === "nextGreater" && currentVal >= _target) {
|
|
4425
4427
|
if (matchVal === undefined ||
|
|
4426
4428
|
matchVal > currentVal ||
|
|
4427
|
-
(matchVal === currentVal &&
|
|
4428
|
-
(matchVal === currentVal && sortOrder === "desc" && matchValIndex > currentIndex)) {
|
|
4429
|
+
(matchVal === currentVal && matchValIndex < currentIndex)) {
|
|
4429
4430
|
matchVal = currentVal;
|
|
4430
4431
|
matchValIndex = currentIndex;
|
|
4431
4432
|
}
|
|
4432
4433
|
}
|
|
4433
4434
|
// 3 - give new indexes for the Binary search
|
|
4434
|
-
if ((
|
|
4435
|
-
(sortOrder === "desc" && currentVal <= _target)) {
|
|
4435
|
+
if (currentVal > _target || (mode === "strict" && currentVal === _target)) {
|
|
4436
4436
|
indexRight = currentIndex - 1;
|
|
4437
4437
|
}
|
|
4438
4438
|
else {
|
|
@@ -4440,7 +4440,10 @@ function dichotomicSearch(data, target, mode, sortOrder, rangeLength, getValueIn
|
|
|
4440
4440
|
}
|
|
4441
4441
|
}
|
|
4442
4442
|
// note that valMinIndex could be 0
|
|
4443
|
-
|
|
4443
|
+
if (matchValIndex === undefined) {
|
|
4444
|
+
return -1;
|
|
4445
|
+
}
|
|
4446
|
+
return sortOrder === "desc" ? rangeLength - matchValIndex - 1 : matchValIndex;
|
|
4444
4447
|
}
|
|
4445
4448
|
/**
|
|
4446
4449
|
* Perform a linear search and return the index of the match.
|
|
@@ -8005,6 +8008,7 @@ const AGGREGATORS_BY_FIELD_TYPE = {
|
|
|
8005
8008
|
integer: NUMBER_CHAR_AGGREGATORS,
|
|
8006
8009
|
char: NUMBER_CHAR_AGGREGATORS,
|
|
8007
8010
|
boolean: ["count_distinct", "count", "bool_and", "bool_or"],
|
|
8011
|
+
datetime: ["max", "min", "count_distinct", "count"],
|
|
8008
8012
|
};
|
|
8009
8013
|
const AGGREGATORS = {};
|
|
8010
8014
|
for (const type in AGGREGATORS_BY_FIELD_TYPE) {
|
|
@@ -9810,13 +9814,13 @@ function toExcelDataset(getters, ds) {
|
|
|
9810
9814
|
else if (ds.labelCell) {
|
|
9811
9815
|
label = {
|
|
9812
9816
|
reference: getters.getRangeString(ds.labelCell, "forceSheetReference", {
|
|
9813
|
-
|
|
9817
|
+
useBoundedReference: true,
|
|
9814
9818
|
}),
|
|
9815
9819
|
};
|
|
9816
9820
|
}
|
|
9817
9821
|
return {
|
|
9818
9822
|
label,
|
|
9819
|
-
range: getters.getRangeString(dataRange, "forceSheetReference", {
|
|
9823
|
+
range: getters.getRangeString(dataRange, "forceSheetReference", { useBoundedReference: true }),
|
|
9820
9824
|
backgroundColor: ds.backgroundColor,
|
|
9821
9825
|
rightYAxis: ds.rightYAxis,
|
|
9822
9826
|
};
|
|
@@ -9831,7 +9835,7 @@ function toExcelLabelRange(getters, labelRange, shouldRemoveFirstLabel) {
|
|
|
9831
9835
|
zone.top = zone.top + 1;
|
|
9832
9836
|
}
|
|
9833
9837
|
const range = labelRange.clone({ zone });
|
|
9834
|
-
return getters.getRangeString(range, "forceSheetReference", {
|
|
9838
|
+
return getters.getRangeString(range, "forceSheetReference", { useBoundedReference: true });
|
|
9835
9839
|
}
|
|
9836
9840
|
/**
|
|
9837
9841
|
* Transform a chart definition which supports dataSets (dataSets and LabelRange)
|
|
@@ -29581,11 +29585,14 @@ const templates = /* xml */ `
|
|
|
29581
29585
|
</t>
|
|
29582
29586
|
</templates>
|
|
29583
29587
|
`;
|
|
29584
|
-
|
|
29588
|
+
let app;
|
|
29585
29589
|
function renderToString(templateName, context = {}) {
|
|
29586
29590
|
return render(templateName, context).innerHTML;
|
|
29587
29591
|
}
|
|
29588
29592
|
function render(templateName, context = {}) {
|
|
29593
|
+
if (!app) {
|
|
29594
|
+
app = new owl.App(owl.Component, { templates, translateFn: _t });
|
|
29595
|
+
}
|
|
29589
29596
|
const templateFn = app.getTemplate(templateName);
|
|
29590
29597
|
const bdom = templateFn(context, {});
|
|
29591
29598
|
const div = document.createElement("div");
|
|
@@ -29814,6 +29821,7 @@ var CHART_RUNTIME_HELPERS = /*#__PURE__*/Object.freeze({
|
|
|
29814
29821
|
getBarChartLegend: getBarChartLegend,
|
|
29815
29822
|
getBarChartScales: getBarChartScales,
|
|
29816
29823
|
getBarChartTooltip: getBarChartTooltip,
|
|
29824
|
+
getChartColorsGenerator: getChartColorsGenerator,
|
|
29817
29825
|
getChartLabelFormat: getChartLabelFormat,
|
|
29818
29826
|
getChartLayout: getChartLayout,
|
|
29819
29827
|
getChartShowValues: getChartShowValues,
|
|
@@ -32346,6 +32354,10 @@ class Popover extends owl.Component {
|
|
|
32346
32354
|
this.currentDisplayValue = newDisplay;
|
|
32347
32355
|
if (!anchor)
|
|
32348
32356
|
return;
|
|
32357
|
+
el.style.top = "";
|
|
32358
|
+
el.style.left = "";
|
|
32359
|
+
el.style["max-height"] = "";
|
|
32360
|
+
el.style["max-width"] = "";
|
|
32349
32361
|
const propsMaxSize = { width: this.props.maxWidth, height: this.props.maxHeight };
|
|
32350
32362
|
let elDims = {
|
|
32351
32363
|
width: el.getBoundingClientRect().width,
|
|
@@ -36982,6 +36994,440 @@ class Section extends owl.Component {
|
|
|
36982
36994
|
};
|
|
36983
36995
|
}
|
|
36984
36996
|
|
|
36997
|
+
/**
|
|
36998
|
+
* Start listening to pointer events and apply the given callbacks.
|
|
36999
|
+
*
|
|
37000
|
+
* @returns A function to remove the listeners.
|
|
37001
|
+
*/
|
|
37002
|
+
function startDnd(onMouseMove, onMouseUp, onMouseDown = () => { }) {
|
|
37003
|
+
const removeListeners = () => {
|
|
37004
|
+
window.removeEventListener("pointerdown", onMouseDown);
|
|
37005
|
+
window.removeEventListener("pointerup", _onMouseUp);
|
|
37006
|
+
window.removeEventListener("dragstart", _onDragStart);
|
|
37007
|
+
window.removeEventListener("pointermove", onMouseMove);
|
|
37008
|
+
window.removeEventListener("wheel", onMouseMove);
|
|
37009
|
+
};
|
|
37010
|
+
const _onMouseUp = (ev) => {
|
|
37011
|
+
onMouseUp(ev);
|
|
37012
|
+
removeListeners();
|
|
37013
|
+
};
|
|
37014
|
+
function _onDragStart(ev) {
|
|
37015
|
+
ev.preventDefault();
|
|
37016
|
+
}
|
|
37017
|
+
window.addEventListener("pointerdown", onMouseDown);
|
|
37018
|
+
window.addEventListener("pointerup", _onMouseUp);
|
|
37019
|
+
window.addEventListener("dragstart", _onDragStart);
|
|
37020
|
+
window.addEventListener("pointermove", onMouseMove);
|
|
37021
|
+
// mouse wheel on window is by default a passive event.
|
|
37022
|
+
// preventDefault() is not allowed in passive event handler.
|
|
37023
|
+
// https://chromestatus.com/feature/6662647093133312
|
|
37024
|
+
window.addEventListener("wheel", onMouseMove, { passive: false });
|
|
37025
|
+
return removeListeners;
|
|
37026
|
+
}
|
|
37027
|
+
/**
|
|
37028
|
+
* Function to be used during a pointerdown event, this function allows to
|
|
37029
|
+
* perform actions related to the pointermove and pointerup events and adjusts the viewport
|
|
37030
|
+
* when the new position related to the pointermove event is outside of it.
|
|
37031
|
+
* Among inputs are two callback functions. First intended for actions performed during
|
|
37032
|
+
* the pointermove event, it receives as parameters the current position of the pointermove
|
|
37033
|
+
* (occurrence of the current column and the current row). Second intended for actions
|
|
37034
|
+
* performed during the pointerup event.
|
|
37035
|
+
*/
|
|
37036
|
+
function dragAndDropBeyondTheViewport(env, cbMouseMove, cbMouseUp, only = false) {
|
|
37037
|
+
let timeOutId = null;
|
|
37038
|
+
let currentEv;
|
|
37039
|
+
let previousEv;
|
|
37040
|
+
let startingEv;
|
|
37041
|
+
let startingX;
|
|
37042
|
+
let startingY;
|
|
37043
|
+
const getters = env.model.getters;
|
|
37044
|
+
const sheetId = getters.getActiveSheetId();
|
|
37045
|
+
const position = gridOverlayPosition();
|
|
37046
|
+
let colIndex;
|
|
37047
|
+
let rowIndex;
|
|
37048
|
+
const onMouseDown = (ev) => {
|
|
37049
|
+
previousEv = ev;
|
|
37050
|
+
startingEv = ev;
|
|
37051
|
+
startingX = startingEv.clientX - position.left;
|
|
37052
|
+
startingY = startingEv.clientY - position.top;
|
|
37053
|
+
};
|
|
37054
|
+
const onMouseMove = (ev) => {
|
|
37055
|
+
currentEv = ev;
|
|
37056
|
+
if (timeOutId) {
|
|
37057
|
+
return;
|
|
37058
|
+
}
|
|
37059
|
+
const { x: offsetCorrectionX, y: offsetCorrectionY } = getters.getMainViewportCoordinates();
|
|
37060
|
+
let { top, left, bottom, right } = getters.getActiveMainViewport();
|
|
37061
|
+
let { scrollX, scrollY } = getters.getActiveSheetDOMScrollInfo();
|
|
37062
|
+
const { xSplit, ySplit } = getters.getPaneDivisions(sheetId);
|
|
37063
|
+
let canEdgeScroll = false;
|
|
37064
|
+
let timeoutDelay = MAX_DELAY;
|
|
37065
|
+
const x = currentEv.clientX - position.left;
|
|
37066
|
+
colIndex = getters.getColIndex(x);
|
|
37067
|
+
if (only !== "vertical") {
|
|
37068
|
+
const previousX = previousEv.clientX - position.left;
|
|
37069
|
+
const edgeScrollInfoX = getters.getEdgeScrollCol(x, previousX, startingX);
|
|
37070
|
+
if (edgeScrollInfoX.canEdgeScroll) {
|
|
37071
|
+
canEdgeScroll = true;
|
|
37072
|
+
timeoutDelay = Math.min(timeoutDelay, edgeScrollInfoX.delay);
|
|
37073
|
+
let newTarget;
|
|
37074
|
+
switch (edgeScrollInfoX.direction) {
|
|
37075
|
+
case "reset":
|
|
37076
|
+
colIndex = xSplit;
|
|
37077
|
+
newTarget = xSplit;
|
|
37078
|
+
break;
|
|
37079
|
+
case 1:
|
|
37080
|
+
colIndex = right;
|
|
37081
|
+
newTarget = left + 1;
|
|
37082
|
+
break;
|
|
37083
|
+
case -1:
|
|
37084
|
+
colIndex = left - 1;
|
|
37085
|
+
while (env.model.getters.isColHidden(sheetId, colIndex)) {
|
|
37086
|
+
colIndex--;
|
|
37087
|
+
}
|
|
37088
|
+
newTarget = colIndex;
|
|
37089
|
+
break;
|
|
37090
|
+
}
|
|
37091
|
+
scrollX = getters.getColDimensions(sheetId, newTarget).start - offsetCorrectionX;
|
|
37092
|
+
}
|
|
37093
|
+
}
|
|
37094
|
+
const y = currentEv.clientY - position.top;
|
|
37095
|
+
rowIndex = getters.getRowIndex(y);
|
|
37096
|
+
if (only !== "horizontal") {
|
|
37097
|
+
const previousY = previousEv.clientY - position.top;
|
|
37098
|
+
const edgeScrollInfoY = getters.getEdgeScrollRow(y, previousY, startingY);
|
|
37099
|
+
if (edgeScrollInfoY.canEdgeScroll) {
|
|
37100
|
+
canEdgeScroll = true;
|
|
37101
|
+
timeoutDelay = Math.min(timeoutDelay, edgeScrollInfoY.delay);
|
|
37102
|
+
let newTarget;
|
|
37103
|
+
switch (edgeScrollInfoY.direction) {
|
|
37104
|
+
case "reset":
|
|
37105
|
+
rowIndex = ySplit;
|
|
37106
|
+
newTarget = ySplit;
|
|
37107
|
+
break;
|
|
37108
|
+
case 1:
|
|
37109
|
+
rowIndex = bottom;
|
|
37110
|
+
newTarget = top + edgeScrollInfoY.direction;
|
|
37111
|
+
break;
|
|
37112
|
+
case -1:
|
|
37113
|
+
rowIndex = top - 1;
|
|
37114
|
+
while (env.model.getters.isRowHidden(sheetId, rowIndex)) {
|
|
37115
|
+
rowIndex--;
|
|
37116
|
+
}
|
|
37117
|
+
newTarget = rowIndex;
|
|
37118
|
+
break;
|
|
37119
|
+
}
|
|
37120
|
+
scrollY = env.model.getters.getRowDimensions(sheetId, newTarget).start - offsetCorrectionY;
|
|
37121
|
+
}
|
|
37122
|
+
}
|
|
37123
|
+
if (!canEdgeScroll) {
|
|
37124
|
+
if (rowIndex === -1) {
|
|
37125
|
+
rowIndex = y < 0 ? 0 : getters.getNumberRows(sheetId) - 1;
|
|
37126
|
+
}
|
|
37127
|
+
if (colIndex === -1 && x < 0) {
|
|
37128
|
+
colIndex = x < 0 ? 0 : getters.getNumberCols(sheetId) - 1;
|
|
37129
|
+
}
|
|
37130
|
+
}
|
|
37131
|
+
cbMouseMove(colIndex, rowIndex, currentEv);
|
|
37132
|
+
if (canEdgeScroll) {
|
|
37133
|
+
env.model.dispatch("SET_VIEWPORT_OFFSET", { offsetX: scrollX, offsetY: scrollY });
|
|
37134
|
+
timeOutId = setTimeout(() => {
|
|
37135
|
+
timeOutId = null;
|
|
37136
|
+
onMouseMove(currentEv);
|
|
37137
|
+
}, Math.round(timeoutDelay));
|
|
37138
|
+
}
|
|
37139
|
+
previousEv = currentEv;
|
|
37140
|
+
};
|
|
37141
|
+
const onMouseUp = () => {
|
|
37142
|
+
clearTimeout(timeOutId);
|
|
37143
|
+
cbMouseUp();
|
|
37144
|
+
};
|
|
37145
|
+
startDnd(onMouseMove, onMouseUp, onMouseDown);
|
|
37146
|
+
}
|
|
37147
|
+
|
|
37148
|
+
function useDragAndDropListItems() {
|
|
37149
|
+
let dndHelper;
|
|
37150
|
+
const previousCursor = document.body.style.cursor;
|
|
37151
|
+
let cleanupFns = [];
|
|
37152
|
+
const cleanUp = () => {
|
|
37153
|
+
dndHelper = undefined;
|
|
37154
|
+
document.body.style.cursor = previousCursor;
|
|
37155
|
+
cleanupFns.forEach((fn) => fn());
|
|
37156
|
+
cleanupFns = [];
|
|
37157
|
+
};
|
|
37158
|
+
const start = (direction, args) => {
|
|
37159
|
+
const onChange = () => {
|
|
37160
|
+
document.body.style.cursor = "move";
|
|
37161
|
+
if (!dndHelper)
|
|
37162
|
+
return;
|
|
37163
|
+
Object.assign(state.itemsStyle, dndHelper.getItemStyles());
|
|
37164
|
+
args.onChange?.();
|
|
37165
|
+
};
|
|
37166
|
+
state.cancel = () => {
|
|
37167
|
+
state.draggedItemId = undefined;
|
|
37168
|
+
state.itemsStyle = {};
|
|
37169
|
+
document.body.style.cursor = previousCursor;
|
|
37170
|
+
args.onCancel?.();
|
|
37171
|
+
cleanUp();
|
|
37172
|
+
};
|
|
37173
|
+
const onDragEnd = (itemId, indexAtEnd) => {
|
|
37174
|
+
state.draggedItemId = undefined;
|
|
37175
|
+
state.itemsStyle = {};
|
|
37176
|
+
document.body.style.cursor = previousCursor;
|
|
37177
|
+
args.onDragEnd?.(itemId, indexAtEnd);
|
|
37178
|
+
cleanUp();
|
|
37179
|
+
};
|
|
37180
|
+
document.body.style.cursor = "move";
|
|
37181
|
+
state.draggedItemId = args.draggedItemId;
|
|
37182
|
+
const container = direction === "horizontal"
|
|
37183
|
+
? new HorizontalContainer(args.containerEl)
|
|
37184
|
+
: new VerticalContainer(args.containerEl);
|
|
37185
|
+
dndHelper = new DOMDndHelper({
|
|
37186
|
+
...args,
|
|
37187
|
+
container,
|
|
37188
|
+
onChange,
|
|
37189
|
+
onDragEnd,
|
|
37190
|
+
onCancel: state.cancel,
|
|
37191
|
+
});
|
|
37192
|
+
const stopListening = startDnd(dndHelper.onMouseMove.bind(dndHelper), dndHelper.onMouseUp.bind(dndHelper));
|
|
37193
|
+
cleanupFns.push(stopListening);
|
|
37194
|
+
const onScroll = dndHelper.onScroll.bind(dndHelper);
|
|
37195
|
+
args.containerEl.addEventListener("scroll", onScroll);
|
|
37196
|
+
cleanupFns.push(() => args.containerEl.removeEventListener("scroll", onScroll));
|
|
37197
|
+
cleanupFns.push(dndHelper.destroy.bind(dndHelper));
|
|
37198
|
+
};
|
|
37199
|
+
owl.onWillUnmount(() => {
|
|
37200
|
+
cleanUp();
|
|
37201
|
+
});
|
|
37202
|
+
const state = owl.useState({
|
|
37203
|
+
itemsStyle: {},
|
|
37204
|
+
draggedItemId: undefined,
|
|
37205
|
+
start,
|
|
37206
|
+
cancel: () => { },
|
|
37207
|
+
});
|
|
37208
|
+
return state;
|
|
37209
|
+
}
|
|
37210
|
+
class DOMDndHelper {
|
|
37211
|
+
draggedItemId;
|
|
37212
|
+
items;
|
|
37213
|
+
container;
|
|
37214
|
+
initialMousePosition;
|
|
37215
|
+
currentMousePosition;
|
|
37216
|
+
initialScroll;
|
|
37217
|
+
minPosition;
|
|
37218
|
+
maxPosition;
|
|
37219
|
+
edgeScrollIntervalId;
|
|
37220
|
+
onChange;
|
|
37221
|
+
onCancel;
|
|
37222
|
+
onDragEnd;
|
|
37223
|
+
/**
|
|
37224
|
+
* The dead zone is an area in which the pointermove events are ignored.
|
|
37225
|
+
*
|
|
37226
|
+
* This is useful when swapping the dragged item with a larger item. After the swap,
|
|
37227
|
+
* the mouse is still hovering on the item we just swapped with. In this case, we don't want
|
|
37228
|
+
* a mouse move to trigger another swap the other way around, so we create a dead zone. We will clear
|
|
37229
|
+
* the dead zone when the mouse leaves the swapped item.
|
|
37230
|
+
*/
|
|
37231
|
+
deadZone;
|
|
37232
|
+
constructor(args) {
|
|
37233
|
+
this.items = args.items.map((item) => ({ ...item, positionAtStart: item.position }));
|
|
37234
|
+
this.draggedItemId = args.draggedItemId;
|
|
37235
|
+
this.container = args.container;
|
|
37236
|
+
this.onChange = args.onChange;
|
|
37237
|
+
this.onCancel = args.onCancel;
|
|
37238
|
+
this.onDragEnd = args.onDragEnd;
|
|
37239
|
+
this.initialMousePosition = args.initialMousePosition;
|
|
37240
|
+
this.currentMousePosition = args.initialMousePosition;
|
|
37241
|
+
this.initialScroll = this.container.scroll;
|
|
37242
|
+
this.minPosition = this.items[0].position;
|
|
37243
|
+
this.maxPosition =
|
|
37244
|
+
this.items[this.items.length - 1].position + this.items[this.items.length - 1].size;
|
|
37245
|
+
}
|
|
37246
|
+
getItemStyles() {
|
|
37247
|
+
const styles = {};
|
|
37248
|
+
for (let item of this.items) {
|
|
37249
|
+
styles[item.id] = this.getItemStyle(item.id);
|
|
37250
|
+
}
|
|
37251
|
+
return styles;
|
|
37252
|
+
}
|
|
37253
|
+
getItemStyle(itemId) {
|
|
37254
|
+
const position = this.container.cssPositionProperty;
|
|
37255
|
+
const style = {};
|
|
37256
|
+
style.position = "relative";
|
|
37257
|
+
style[position] = (this.getItemsPositions()[itemId] || 0) + "px";
|
|
37258
|
+
style.transition = `${position} 0.5s`;
|
|
37259
|
+
style["pointer-events"] = "none";
|
|
37260
|
+
if (this.draggedItemId === itemId) {
|
|
37261
|
+
style.transition = `${position} 0s`;
|
|
37262
|
+
style["z-index"] = "1000";
|
|
37263
|
+
}
|
|
37264
|
+
return cssPropertiesToCss(style);
|
|
37265
|
+
}
|
|
37266
|
+
onScroll() {
|
|
37267
|
+
this.moveDraggedItemToPosition(this.currentMousePosition + this.scrollOffset);
|
|
37268
|
+
}
|
|
37269
|
+
onMouseMove(ev) {
|
|
37270
|
+
if (ev.button > 1) {
|
|
37271
|
+
this.onCancel();
|
|
37272
|
+
return;
|
|
37273
|
+
}
|
|
37274
|
+
const mousePosition = this.container.getMousePosition(ev);
|
|
37275
|
+
this.currentMousePosition = mousePosition;
|
|
37276
|
+
if (mousePosition < this.container.start || mousePosition > this.container.end) {
|
|
37277
|
+
this.startEdgeScroll(mousePosition < this.container.start ? -1 : 1);
|
|
37278
|
+
return;
|
|
37279
|
+
}
|
|
37280
|
+
else {
|
|
37281
|
+
this.stopEdgeScroll();
|
|
37282
|
+
}
|
|
37283
|
+
this.moveDraggedItemToPosition(mousePosition + this.scrollOffset);
|
|
37284
|
+
}
|
|
37285
|
+
moveDraggedItemToPosition(position) {
|
|
37286
|
+
const hoveredItemIndex = this.getHoveredItemIndex(position, this.items);
|
|
37287
|
+
const draggedItemIndex = this.items.findIndex((item) => item.id === this.draggedItemId);
|
|
37288
|
+
const draggedItem = this.items[draggedItemIndex];
|
|
37289
|
+
if (this.deadZone && this.isInZone(position, this.deadZone)) {
|
|
37290
|
+
this.onChange(this.getItemsPositions());
|
|
37291
|
+
return;
|
|
37292
|
+
}
|
|
37293
|
+
else if (this.isInZone(position, {
|
|
37294
|
+
start: draggedItem.position,
|
|
37295
|
+
end: draggedItem.position + draggedItem.size,
|
|
37296
|
+
})) {
|
|
37297
|
+
this.deadZone = undefined;
|
|
37298
|
+
}
|
|
37299
|
+
if (draggedItemIndex === hoveredItemIndex) {
|
|
37300
|
+
this.onChange(this.getItemsPositions());
|
|
37301
|
+
return;
|
|
37302
|
+
}
|
|
37303
|
+
const startIndex = Math.min(draggedItemIndex, hoveredItemIndex);
|
|
37304
|
+
const endIndex = Math.max(draggedItemIndex, hoveredItemIndex);
|
|
37305
|
+
const direction = Math.sign(hoveredItemIndex - draggedItemIndex);
|
|
37306
|
+
let draggedItemMoveSize = 0;
|
|
37307
|
+
for (let i = startIndex; i <= endIndex; i++) {
|
|
37308
|
+
if (i === draggedItemIndex) {
|
|
37309
|
+
continue;
|
|
37310
|
+
}
|
|
37311
|
+
this.items[i].position -= direction * draggedItem.size;
|
|
37312
|
+
draggedItemMoveSize += this.items[i].size;
|
|
37313
|
+
}
|
|
37314
|
+
draggedItem.position += direction * draggedItemMoveSize;
|
|
37315
|
+
this.items.sort((item1, item2) => item1.position - item2.position);
|
|
37316
|
+
this.deadZone =
|
|
37317
|
+
direction > 0
|
|
37318
|
+
? { start: position, end: draggedItem.position }
|
|
37319
|
+
: { start: draggedItem.position + draggedItem.size, end: position };
|
|
37320
|
+
this.onChange(this.getItemsPositions());
|
|
37321
|
+
}
|
|
37322
|
+
onMouseUp(ev) {
|
|
37323
|
+
if (ev.button !== 0) {
|
|
37324
|
+
this.onCancel();
|
|
37325
|
+
}
|
|
37326
|
+
ev.stopPropagation();
|
|
37327
|
+
ev.preventDefault();
|
|
37328
|
+
const targetItemIndex = this.items.findIndex((item) => item.id === this.draggedItemId);
|
|
37329
|
+
this.onDragEnd(this.draggedItemId, targetItemIndex);
|
|
37330
|
+
this.stopEdgeScroll();
|
|
37331
|
+
return false;
|
|
37332
|
+
}
|
|
37333
|
+
startEdgeScroll(direction) {
|
|
37334
|
+
if (this.edgeScrollIntervalId)
|
|
37335
|
+
return;
|
|
37336
|
+
this.edgeScrollIntervalId = window.setInterval(() => {
|
|
37337
|
+
const offset = direction * 3;
|
|
37338
|
+
this.container.scroll += offset;
|
|
37339
|
+
}, 5);
|
|
37340
|
+
}
|
|
37341
|
+
stopEdgeScroll() {
|
|
37342
|
+
window.clearInterval(this.edgeScrollIntervalId);
|
|
37343
|
+
this.edgeScrollIntervalId = undefined;
|
|
37344
|
+
}
|
|
37345
|
+
/**
|
|
37346
|
+
* Get the index of the item the given mouse position is inside.
|
|
37347
|
+
* If the mouse is outside the container, return the first or last item index.
|
|
37348
|
+
*/
|
|
37349
|
+
getHoveredItemIndex(mousePosition, items) {
|
|
37350
|
+
if (mousePosition <= this.minPosition)
|
|
37351
|
+
return 0;
|
|
37352
|
+
if (mousePosition >= this.maxPosition)
|
|
37353
|
+
return items.length - 1;
|
|
37354
|
+
return items.findIndex((item) => item.position + item.size >= mousePosition);
|
|
37355
|
+
}
|
|
37356
|
+
getItemsPositions() {
|
|
37357
|
+
const positions = {};
|
|
37358
|
+
for (let item of this.items) {
|
|
37359
|
+
if (item.id !== this.draggedItemId) {
|
|
37360
|
+
positions[item.id] = item.position - item.positionAtStart;
|
|
37361
|
+
continue;
|
|
37362
|
+
}
|
|
37363
|
+
const mouseOffset = this.currentMousePosition - this.initialMousePosition;
|
|
37364
|
+
let start = mouseOffset + this.scrollOffset;
|
|
37365
|
+
start = Math.max(this.minPosition - item.positionAtStart, start);
|
|
37366
|
+
start = Math.min(this.maxPosition - item.positionAtStart - item.size, start);
|
|
37367
|
+
positions[item.id] = start;
|
|
37368
|
+
}
|
|
37369
|
+
return positions;
|
|
37370
|
+
}
|
|
37371
|
+
isInZone(position, zone) {
|
|
37372
|
+
return position >= zone.start && position <= zone.end;
|
|
37373
|
+
}
|
|
37374
|
+
get scrollOffset() {
|
|
37375
|
+
return this.container.scroll - this.initialScroll;
|
|
37376
|
+
}
|
|
37377
|
+
destroy() {
|
|
37378
|
+
this.stopEdgeScroll();
|
|
37379
|
+
}
|
|
37380
|
+
}
|
|
37381
|
+
class ContainerWrapper {
|
|
37382
|
+
el;
|
|
37383
|
+
constructor(el) {
|
|
37384
|
+
this.el = el;
|
|
37385
|
+
}
|
|
37386
|
+
get containerRect() {
|
|
37387
|
+
return this.el.getBoundingClientRect();
|
|
37388
|
+
}
|
|
37389
|
+
}
|
|
37390
|
+
class VerticalContainer extends ContainerWrapper {
|
|
37391
|
+
get start() {
|
|
37392
|
+
return this.containerRect.top;
|
|
37393
|
+
}
|
|
37394
|
+
get end() {
|
|
37395
|
+
return this.containerRect.bottom;
|
|
37396
|
+
}
|
|
37397
|
+
get cssPositionProperty() {
|
|
37398
|
+
return "top";
|
|
37399
|
+
}
|
|
37400
|
+
get scroll() {
|
|
37401
|
+
return this.el.scrollTop;
|
|
37402
|
+
}
|
|
37403
|
+
set scroll(scroll) {
|
|
37404
|
+
this.el.scrollTop = scroll;
|
|
37405
|
+
}
|
|
37406
|
+
getMousePosition(ev) {
|
|
37407
|
+
return ev.clientY;
|
|
37408
|
+
}
|
|
37409
|
+
}
|
|
37410
|
+
class HorizontalContainer extends ContainerWrapper {
|
|
37411
|
+
get start() {
|
|
37412
|
+
return this.containerRect.left;
|
|
37413
|
+
}
|
|
37414
|
+
get end() {
|
|
37415
|
+
return this.containerRect.right;
|
|
37416
|
+
}
|
|
37417
|
+
get cssPositionProperty() {
|
|
37418
|
+
return "left";
|
|
37419
|
+
}
|
|
37420
|
+
get scroll() {
|
|
37421
|
+
return this.el.scrollLeft;
|
|
37422
|
+
}
|
|
37423
|
+
set scroll(scroll) {
|
|
37424
|
+
this.el.scrollLeft = scroll;
|
|
37425
|
+
}
|
|
37426
|
+
getMousePosition(ev) {
|
|
37427
|
+
return ev.clientX;
|
|
37428
|
+
}
|
|
37429
|
+
}
|
|
37430
|
+
|
|
36985
37431
|
const arrowMap = {
|
|
36986
37432
|
ArrowDown: "down",
|
|
36987
37433
|
ArrowLeft: "left",
|
|
@@ -37032,6 +37478,7 @@ class SelectionInputStore extends SpreadsheetStore {
|
|
|
37032
37478
|
"changeRange",
|
|
37033
37479
|
"reset",
|
|
37034
37480
|
"confirm",
|
|
37481
|
+
"updateColors",
|
|
37035
37482
|
];
|
|
37036
37483
|
ranges = [];
|
|
37037
37484
|
focusedRangeIndex = null;
|
|
@@ -37151,6 +37598,9 @@ class SelectionInputStore extends SpreadsheetStore {
|
|
|
37151
37598
|
this.removeRangeByIndex(index);
|
|
37152
37599
|
}
|
|
37153
37600
|
}
|
|
37601
|
+
updateColors(colors) {
|
|
37602
|
+
this.colors = colors;
|
|
37603
|
+
}
|
|
37154
37604
|
confirm() {
|
|
37155
37605
|
for (const range of this.selectionInputs) {
|
|
37156
37606
|
if (range.xc === "") {
|
|
@@ -37361,6 +37811,9 @@ css /* scss */ `
|
|
|
37361
37811
|
right: 7px;
|
|
37362
37812
|
top: 4px;
|
|
37363
37813
|
}
|
|
37814
|
+
.o-drag-handle {
|
|
37815
|
+
cursor: move;
|
|
37816
|
+
}
|
|
37364
37817
|
}
|
|
37365
37818
|
.o-button {
|
|
37366
37819
|
height: 28px;
|
|
@@ -37392,13 +37845,17 @@ class SelectionInput extends owl.Component {
|
|
|
37392
37845
|
class: { type: String, optional: true },
|
|
37393
37846
|
onSelectionChanged: { type: Function, optional: true },
|
|
37394
37847
|
onSelectionConfirmed: { type: Function, optional: true },
|
|
37848
|
+
onSelectionReordered: { type: Function, optional: true },
|
|
37849
|
+
onSelectionRemoved: { type: Function, optional: true },
|
|
37395
37850
|
colors: { type: Array, optional: true, default: [] },
|
|
37396
37851
|
};
|
|
37397
37852
|
state = owl.useState({
|
|
37398
37853
|
isMissing: false,
|
|
37399
37854
|
mode: "select-range",
|
|
37400
37855
|
});
|
|
37856
|
+
dragAndDrop = useDragAndDropListItems();
|
|
37401
37857
|
focusedInput = owl.useRef("focusedInput");
|
|
37858
|
+
selectionRef = owl.useRef("o-selection");
|
|
37402
37859
|
store;
|
|
37403
37860
|
get ranges() {
|
|
37404
37861
|
return this.store.selectionInputs;
|
|
@@ -37426,8 +37883,45 @@ class SelectionInput extends owl.Component {
|
|
|
37426
37883
|
nextProps.ranges.join() !== this.store.selectionInputValues.join()) {
|
|
37427
37884
|
this.store.resetWithRanges(nextProps.ranges);
|
|
37428
37885
|
}
|
|
37886
|
+
if (nextProps.colors?.join() !== this.props.colors?.join() &&
|
|
37887
|
+
nextProps.colors?.join() !== this.store.colors.join()) {
|
|
37888
|
+
this.store.updateColors(nextProps.colors || []);
|
|
37889
|
+
}
|
|
37429
37890
|
});
|
|
37430
37891
|
}
|
|
37892
|
+
startDragAndDrop(rangeId, event) {
|
|
37893
|
+
if (event.button !== 0 || event.target.tagName === "SELECT") {
|
|
37894
|
+
return;
|
|
37895
|
+
}
|
|
37896
|
+
const rects = this.getRangeElementsRects();
|
|
37897
|
+
const draggableIds = this.ranges.map((range) => range.id);
|
|
37898
|
+
const draggableItems = draggableIds.map((id, index) => ({
|
|
37899
|
+
id: id.toString(),
|
|
37900
|
+
size: rects[index].height,
|
|
37901
|
+
position: rects[index].y,
|
|
37902
|
+
}));
|
|
37903
|
+
this.dragAndDrop.start("vertical", {
|
|
37904
|
+
draggedItemId: rangeId.toString(),
|
|
37905
|
+
initialMousePosition: event.clientY,
|
|
37906
|
+
items: draggableItems,
|
|
37907
|
+
containerEl: this.selectionRef.el,
|
|
37908
|
+
onDragEnd: (dimensionName, finalIndex) => {
|
|
37909
|
+
const originalIndex = draggableIds.findIndex((id) => id === rangeId);
|
|
37910
|
+
if (originalIndex === finalIndex) {
|
|
37911
|
+
return;
|
|
37912
|
+
}
|
|
37913
|
+
const draggedItems = [...draggableIds];
|
|
37914
|
+
draggedItems.splice(originalIndex, 1);
|
|
37915
|
+
draggedItems.splice(finalIndex, 0, rangeId);
|
|
37916
|
+
this.props.onSelectionReordered?.(this.store.selectionInputs.map((range) => draggedItems.indexOf(range.id)));
|
|
37917
|
+
this.props.onSelectionConfirmed?.();
|
|
37918
|
+
this.store.confirm();
|
|
37919
|
+
},
|
|
37920
|
+
});
|
|
37921
|
+
}
|
|
37922
|
+
getRangeElementsRects() {
|
|
37923
|
+
return Array.from(this.selectionRef.el.children).map((el) => el.getBoundingClientRect());
|
|
37924
|
+
}
|
|
37431
37925
|
getColor(range) {
|
|
37432
37926
|
if (!range.color) {
|
|
37433
37927
|
return "";
|
|
@@ -37469,8 +37963,8 @@ class SelectionInput extends owl.Component {
|
|
|
37469
37963
|
this.store.addEmptyRange();
|
|
37470
37964
|
}
|
|
37471
37965
|
removeInput(rangeId) {
|
|
37472
|
-
this.store.
|
|
37473
|
-
this.
|
|
37966
|
+
const index = this.store.selectionInputs.findIndex((range) => range.id === rangeId);
|
|
37967
|
+
this.props.onSelectionRemoved?.(index);
|
|
37474
37968
|
this.props.onSelectionConfirmed?.();
|
|
37475
37969
|
}
|
|
37476
37970
|
onInputChanged(rangeId, ev) {
|
|
@@ -37501,6 +37995,8 @@ class ChartDataSeries extends owl.Component {
|
|
|
37501
37995
|
ranges: Array,
|
|
37502
37996
|
hasSingleRange: { type: Boolean, optional: true },
|
|
37503
37997
|
onSelectionChanged: Function,
|
|
37998
|
+
onSelectionReordered: { type: Function, optional: true },
|
|
37999
|
+
onSelectionRemoved: { type: Function, optional: true },
|
|
37504
38000
|
onSelectionConfirmed: Function,
|
|
37505
38001
|
};
|
|
37506
38002
|
get ranges() {
|
|
@@ -37609,11 +38105,11 @@ class GenericChartConfigPanel extends owl.Component {
|
|
|
37609
38105
|
datasetDispatchResult: undefined,
|
|
37610
38106
|
labelsDispatchResult: undefined,
|
|
37611
38107
|
});
|
|
37612
|
-
|
|
38108
|
+
dataSets = [];
|
|
37613
38109
|
labelRange;
|
|
37614
38110
|
chartTerms = ChartTerms;
|
|
37615
38111
|
setup() {
|
|
37616
|
-
this.
|
|
38112
|
+
this.dataSets = this.props.definition.dataSets;
|
|
37617
38113
|
this.labelRange = this.props.definition.labelRange;
|
|
37618
38114
|
}
|
|
37619
38115
|
get errorMessages() {
|
|
@@ -37658,22 +38154,46 @@ class GenericChartConfigPanel extends owl.Component {
|
|
|
37658
38154
|
* button "confirm" is clicked
|
|
37659
38155
|
*/
|
|
37660
38156
|
onDataSeriesRangesChanged(ranges) {
|
|
37661
|
-
this.
|
|
37662
|
-
...this.
|
|
38157
|
+
this.dataSets = ranges.map((dataRange, i) => ({
|
|
38158
|
+
...this.dataSets?.[i],
|
|
37663
38159
|
dataRange,
|
|
37664
38160
|
}));
|
|
37665
38161
|
this.state.datasetDispatchResult = this.props.canUpdateChart(this.props.figureId, {
|
|
37666
|
-
dataSets: this.
|
|
38162
|
+
dataSets: this.dataSets,
|
|
38163
|
+
});
|
|
38164
|
+
}
|
|
38165
|
+
onDataSeriesReordered(indexes) {
|
|
38166
|
+
const colorGenerator = getChartColorsGenerator({ dataSets: this.dataSets }, this.dataSets.length);
|
|
38167
|
+
const colors = this.dataSets.map((ds) => colorGenerator.next());
|
|
38168
|
+
this.dataSets = indexes.map((i) => ({
|
|
38169
|
+
backgroundColor: colors[i],
|
|
38170
|
+
...this.dataSets[i],
|
|
38171
|
+
}));
|
|
38172
|
+
this.state.datasetDispatchResult = this.props.updateChart(this.props.figureId, {
|
|
38173
|
+
dataSets: this.dataSets,
|
|
38174
|
+
});
|
|
38175
|
+
}
|
|
38176
|
+
onDataSeriesRemoved(index) {
|
|
38177
|
+
const colorGenerator = getChartColorsGenerator({ dataSets: this.dataSets }, this.dataSets.length);
|
|
38178
|
+
const colors = this.dataSets.map((ds) => colorGenerator.next());
|
|
38179
|
+
this.dataSets = this.dataSets
|
|
38180
|
+
.map((ds, i) => ({
|
|
38181
|
+
backgroundColor: colors[i],
|
|
38182
|
+
...ds,
|
|
38183
|
+
}))
|
|
38184
|
+
.filter((_, i) => i !== index);
|
|
38185
|
+
this.state.datasetDispatchResult = this.props.updateChart(this.props.figureId, {
|
|
38186
|
+
dataSets: this.dataSets,
|
|
37667
38187
|
});
|
|
37668
38188
|
}
|
|
37669
38189
|
onDataSeriesConfirmed() {
|
|
37670
|
-
this.
|
|
38190
|
+
this.dataSets = spreadRange(this.env.model.getters, this.dataSets);
|
|
37671
38191
|
this.state.datasetDispatchResult = this.props.updateChart(this.props.figureId, {
|
|
37672
|
-
dataSets: this.
|
|
38192
|
+
dataSets: this.dataSets,
|
|
37673
38193
|
});
|
|
37674
38194
|
}
|
|
37675
38195
|
getDataSeriesRanges() {
|
|
37676
|
-
return this.
|
|
38196
|
+
return this.dataSets;
|
|
37677
38197
|
}
|
|
37678
38198
|
/**
|
|
37679
38199
|
* Change the local labelRange. The model should be updated when the
|
|
@@ -37705,7 +38225,7 @@ class GenericChartConfigPanel extends owl.Component {
|
|
|
37705
38225
|
const getters = this.env.model.getters;
|
|
37706
38226
|
const sheetId = getters.getActiveSheetId();
|
|
37707
38227
|
const labelRange = createValidRange(getters, sheetId, this.labelRange);
|
|
37708
|
-
const dataSets = createDataSets(getters, this.
|
|
38228
|
+
const dataSets = createDataSets(getters, this.dataSets, sheetId, this.props.definition.dataSetsHaveTitle);
|
|
37709
38229
|
if (dataSets.length) {
|
|
37710
38230
|
return dataSets[0].dataRange.zone.top + 1;
|
|
37711
38231
|
}
|
|
@@ -37807,157 +38327,6 @@ class BadgeSelection extends owl.Component {
|
|
|
37807
38327
|
};
|
|
37808
38328
|
}
|
|
37809
38329
|
|
|
37810
|
-
/**
|
|
37811
|
-
* Start listening to pointer events and apply the given callbacks.
|
|
37812
|
-
*
|
|
37813
|
-
* @returns A function to remove the listeners.
|
|
37814
|
-
*/
|
|
37815
|
-
function startDnd(onMouseMove, onMouseUp, onMouseDown = () => { }) {
|
|
37816
|
-
const removeListeners = () => {
|
|
37817
|
-
window.removeEventListener("pointerdown", onMouseDown);
|
|
37818
|
-
window.removeEventListener("pointerup", _onMouseUp);
|
|
37819
|
-
window.removeEventListener("dragstart", _onDragStart);
|
|
37820
|
-
window.removeEventListener("pointermove", onMouseMove);
|
|
37821
|
-
window.removeEventListener("wheel", onMouseMove);
|
|
37822
|
-
};
|
|
37823
|
-
const _onMouseUp = (ev) => {
|
|
37824
|
-
onMouseUp(ev);
|
|
37825
|
-
removeListeners();
|
|
37826
|
-
};
|
|
37827
|
-
function _onDragStart(ev) {
|
|
37828
|
-
ev.preventDefault();
|
|
37829
|
-
}
|
|
37830
|
-
window.addEventListener("pointerdown", onMouseDown);
|
|
37831
|
-
window.addEventListener("pointerup", _onMouseUp);
|
|
37832
|
-
window.addEventListener("dragstart", _onDragStart);
|
|
37833
|
-
window.addEventListener("pointermove", onMouseMove);
|
|
37834
|
-
// mouse wheel on window is by default a passive event.
|
|
37835
|
-
// preventDefault() is not allowed in passive event handler.
|
|
37836
|
-
// https://chromestatus.com/feature/6662647093133312
|
|
37837
|
-
window.addEventListener("wheel", onMouseMove, { passive: false });
|
|
37838
|
-
return removeListeners;
|
|
37839
|
-
}
|
|
37840
|
-
/**
|
|
37841
|
-
* Function to be used during a pointerdown event, this function allows to
|
|
37842
|
-
* perform actions related to the pointermove and pointerup events and adjusts the viewport
|
|
37843
|
-
* when the new position related to the pointermove event is outside of it.
|
|
37844
|
-
* Among inputs are two callback functions. First intended for actions performed during
|
|
37845
|
-
* the pointermove event, it receives as parameters the current position of the pointermove
|
|
37846
|
-
* (occurrence of the current column and the current row). Second intended for actions
|
|
37847
|
-
* performed during the pointerup event.
|
|
37848
|
-
*/
|
|
37849
|
-
function dragAndDropBeyondTheViewport(env, cbMouseMove, cbMouseUp, only = false) {
|
|
37850
|
-
let timeOutId = null;
|
|
37851
|
-
let currentEv;
|
|
37852
|
-
let previousEv;
|
|
37853
|
-
let startingEv;
|
|
37854
|
-
let startingX;
|
|
37855
|
-
let startingY;
|
|
37856
|
-
const getters = env.model.getters;
|
|
37857
|
-
const sheetId = getters.getActiveSheetId();
|
|
37858
|
-
const position = gridOverlayPosition();
|
|
37859
|
-
let colIndex;
|
|
37860
|
-
let rowIndex;
|
|
37861
|
-
const onMouseDown = (ev) => {
|
|
37862
|
-
previousEv = ev;
|
|
37863
|
-
startingEv = ev;
|
|
37864
|
-
startingX = startingEv.clientX - position.left;
|
|
37865
|
-
startingY = startingEv.clientY - position.top;
|
|
37866
|
-
};
|
|
37867
|
-
const onMouseMove = (ev) => {
|
|
37868
|
-
currentEv = ev;
|
|
37869
|
-
if (timeOutId) {
|
|
37870
|
-
return;
|
|
37871
|
-
}
|
|
37872
|
-
const { x: offsetCorrectionX, y: offsetCorrectionY } = getters.getMainViewportCoordinates();
|
|
37873
|
-
let { top, left, bottom, right } = getters.getActiveMainViewport();
|
|
37874
|
-
let { scrollX, scrollY } = getters.getActiveSheetDOMScrollInfo();
|
|
37875
|
-
const { xSplit, ySplit } = getters.getPaneDivisions(sheetId);
|
|
37876
|
-
let canEdgeScroll = false;
|
|
37877
|
-
let timeoutDelay = MAX_DELAY;
|
|
37878
|
-
const x = currentEv.clientX - position.left;
|
|
37879
|
-
colIndex = getters.getColIndex(x);
|
|
37880
|
-
if (only !== "vertical") {
|
|
37881
|
-
const previousX = previousEv.clientX - position.left;
|
|
37882
|
-
const edgeScrollInfoX = getters.getEdgeScrollCol(x, previousX, startingX);
|
|
37883
|
-
if (edgeScrollInfoX.canEdgeScroll) {
|
|
37884
|
-
canEdgeScroll = true;
|
|
37885
|
-
timeoutDelay = Math.min(timeoutDelay, edgeScrollInfoX.delay);
|
|
37886
|
-
let newTarget;
|
|
37887
|
-
switch (edgeScrollInfoX.direction) {
|
|
37888
|
-
case "reset":
|
|
37889
|
-
colIndex = xSplit;
|
|
37890
|
-
newTarget = xSplit;
|
|
37891
|
-
break;
|
|
37892
|
-
case 1:
|
|
37893
|
-
colIndex = right;
|
|
37894
|
-
newTarget = left + 1;
|
|
37895
|
-
break;
|
|
37896
|
-
case -1:
|
|
37897
|
-
colIndex = left - 1;
|
|
37898
|
-
while (env.model.getters.isColHidden(sheetId, colIndex)) {
|
|
37899
|
-
colIndex--;
|
|
37900
|
-
}
|
|
37901
|
-
newTarget = colIndex;
|
|
37902
|
-
break;
|
|
37903
|
-
}
|
|
37904
|
-
scrollX = getters.getColDimensions(sheetId, newTarget).start - offsetCorrectionX;
|
|
37905
|
-
}
|
|
37906
|
-
}
|
|
37907
|
-
const y = currentEv.clientY - position.top;
|
|
37908
|
-
rowIndex = getters.getRowIndex(y);
|
|
37909
|
-
if (only !== "horizontal") {
|
|
37910
|
-
const previousY = previousEv.clientY - position.top;
|
|
37911
|
-
const edgeScrollInfoY = getters.getEdgeScrollRow(y, previousY, startingY);
|
|
37912
|
-
if (edgeScrollInfoY.canEdgeScroll) {
|
|
37913
|
-
canEdgeScroll = true;
|
|
37914
|
-
timeoutDelay = Math.min(timeoutDelay, edgeScrollInfoY.delay);
|
|
37915
|
-
let newTarget;
|
|
37916
|
-
switch (edgeScrollInfoY.direction) {
|
|
37917
|
-
case "reset":
|
|
37918
|
-
rowIndex = ySplit;
|
|
37919
|
-
newTarget = ySplit;
|
|
37920
|
-
break;
|
|
37921
|
-
case 1:
|
|
37922
|
-
rowIndex = bottom;
|
|
37923
|
-
newTarget = top + edgeScrollInfoY.direction;
|
|
37924
|
-
break;
|
|
37925
|
-
case -1:
|
|
37926
|
-
rowIndex = top - 1;
|
|
37927
|
-
while (env.model.getters.isRowHidden(sheetId, rowIndex)) {
|
|
37928
|
-
rowIndex--;
|
|
37929
|
-
}
|
|
37930
|
-
newTarget = rowIndex;
|
|
37931
|
-
break;
|
|
37932
|
-
}
|
|
37933
|
-
scrollY = env.model.getters.getRowDimensions(sheetId, newTarget).start - offsetCorrectionY;
|
|
37934
|
-
}
|
|
37935
|
-
}
|
|
37936
|
-
if (!canEdgeScroll) {
|
|
37937
|
-
if (rowIndex === -1) {
|
|
37938
|
-
rowIndex = y < 0 ? 0 : getters.getNumberRows(sheetId) - 1;
|
|
37939
|
-
}
|
|
37940
|
-
if (colIndex === -1 && x < 0) {
|
|
37941
|
-
colIndex = x < 0 ? 0 : getters.getNumberCols(sheetId) - 1;
|
|
37942
|
-
}
|
|
37943
|
-
}
|
|
37944
|
-
cbMouseMove(colIndex, rowIndex, currentEv);
|
|
37945
|
-
if (canEdgeScroll) {
|
|
37946
|
-
env.model.dispatch("SET_VIEWPORT_OFFSET", { offsetX: scrollX, offsetY: scrollY });
|
|
37947
|
-
timeOutId = setTimeout(() => {
|
|
37948
|
-
timeOutId = null;
|
|
37949
|
-
onMouseMove(currentEv);
|
|
37950
|
-
}, Math.round(timeoutDelay));
|
|
37951
|
-
}
|
|
37952
|
-
previousEv = currentEv;
|
|
37953
|
-
};
|
|
37954
|
-
const onMouseUp = () => {
|
|
37955
|
-
clearTimeout(timeOutId);
|
|
37956
|
-
cbMouseUp();
|
|
37957
|
-
};
|
|
37958
|
-
startDnd(onMouseMove, onMouseUp, onMouseDown);
|
|
37959
|
-
}
|
|
37960
|
-
|
|
37961
38330
|
const LINE_VERTICAL_PADDING = 1;
|
|
37962
38331
|
const PICKER_PADDING = 8;
|
|
37963
38332
|
const ITEM_BORDER_WIDTH = 1;
|
|
@@ -39239,9 +39608,9 @@ class GeoChartConfigPanel extends GenericChartConfigPanel {
|
|
|
39239
39608
|
return this.getDataSeriesRanges().slice(0, 1);
|
|
39240
39609
|
}
|
|
39241
39610
|
onDataSeriesConfirmed() {
|
|
39242
|
-
this.
|
|
39611
|
+
this.dataSets = spreadRange(this.env.model.getters, this.dataSets).slice(0, 1);
|
|
39243
39612
|
this.state.datasetDispatchResult = this.props.updateChart(this.props.figureId, {
|
|
39244
|
-
dataSets: this.
|
|
39613
|
+
dataSets: this.dataSets,
|
|
39245
39614
|
});
|
|
39246
39615
|
}
|
|
39247
39616
|
getLabelRangeOptions() {
|
|
@@ -39727,14 +40096,21 @@ class ChartTypePicker extends owl.Component {
|
|
|
39727
40096
|
class MainChartPanelStore extends SpreadsheetStore {
|
|
39728
40097
|
mutators = ["activatePanel", "changeChartType"];
|
|
39729
40098
|
panel = "configuration";
|
|
39730
|
-
|
|
40099
|
+
creationContexts = {};
|
|
39731
40100
|
activatePanel(panel) {
|
|
39732
40101
|
this.panel = panel;
|
|
39733
40102
|
}
|
|
39734
40103
|
changeChartType(figureId, newDisplayType) {
|
|
39735
|
-
|
|
39736
|
-
|
|
39737
|
-
|
|
40104
|
+
const currentCreationContext = this.getters.getContextCreationChart(figureId);
|
|
40105
|
+
const savedCreationContext = this.creationContexts[figureId] || {};
|
|
40106
|
+
let newRanges = currentCreationContext?.range;
|
|
40107
|
+
if (newRanges?.every((range, i) => deepEquals(range, savedCreationContext.range?.[i]))) {
|
|
40108
|
+
newRanges = Object.assign([], savedCreationContext.range, currentCreationContext?.range);
|
|
40109
|
+
}
|
|
40110
|
+
this.creationContexts[figureId] = {
|
|
40111
|
+
...savedCreationContext,
|
|
40112
|
+
...currentCreationContext,
|
|
40113
|
+
range: newRanges,
|
|
39738
40114
|
};
|
|
39739
40115
|
const sheetId = this.getters.getFigureSheetId(figureId);
|
|
39740
40116
|
if (!sheetId) {
|
|
@@ -39750,12 +40126,8 @@ class MainChartPanelStore extends SpreadsheetStore {
|
|
|
39750
40126
|
getChartDefinitionFromContextCreation(figureId, newDisplayType) {
|
|
39751
40127
|
const newChartInfo = chartSubtypeRegistry.get(newDisplayType);
|
|
39752
40128
|
const ChartClass = chartRegistry.get(newChartInfo.chartType);
|
|
39753
|
-
const contextCreation = {
|
|
39754
|
-
...this.creationContext,
|
|
39755
|
-
...this.getters.getContextCreationChart(figureId),
|
|
39756
|
-
};
|
|
39757
40129
|
return {
|
|
39758
|
-
...ChartClass.getChartDefinitionFromContextCreation(
|
|
40130
|
+
...ChartClass.getChartDefinitionFromContextCreation(this.creationContexts[figureId]),
|
|
39759
40131
|
...newChartInfo.subtypeDefinition,
|
|
39760
40132
|
};
|
|
39761
40133
|
}
|
|
@@ -41099,289 +41471,6 @@ class IconPicker extends owl.Component {
|
|
|
41099
41471
|
}
|
|
41100
41472
|
}
|
|
41101
41473
|
|
|
41102
|
-
function useDragAndDropListItems() {
|
|
41103
|
-
let dndHelper;
|
|
41104
|
-
const previousCursor = document.body.style.cursor;
|
|
41105
|
-
let cleanupFns = [];
|
|
41106
|
-
const cleanUp = () => {
|
|
41107
|
-
dndHelper = undefined;
|
|
41108
|
-
document.body.style.cursor = previousCursor;
|
|
41109
|
-
cleanupFns.forEach((fn) => fn());
|
|
41110
|
-
cleanupFns = [];
|
|
41111
|
-
};
|
|
41112
|
-
const start = (direction, args) => {
|
|
41113
|
-
const onChange = () => {
|
|
41114
|
-
document.body.style.cursor = "move";
|
|
41115
|
-
if (!dndHelper)
|
|
41116
|
-
return;
|
|
41117
|
-
Object.assign(state.itemsStyle, dndHelper.getItemStyles());
|
|
41118
|
-
args.onChange?.();
|
|
41119
|
-
};
|
|
41120
|
-
state.cancel = () => {
|
|
41121
|
-
state.draggedItemId = undefined;
|
|
41122
|
-
state.itemsStyle = {};
|
|
41123
|
-
document.body.style.cursor = previousCursor;
|
|
41124
|
-
args.onCancel?.();
|
|
41125
|
-
cleanUp();
|
|
41126
|
-
};
|
|
41127
|
-
const onDragEnd = (itemId, indexAtEnd) => {
|
|
41128
|
-
state.draggedItemId = undefined;
|
|
41129
|
-
state.itemsStyle = {};
|
|
41130
|
-
document.body.style.cursor = previousCursor;
|
|
41131
|
-
args.onDragEnd?.(itemId, indexAtEnd);
|
|
41132
|
-
cleanUp();
|
|
41133
|
-
};
|
|
41134
|
-
document.body.style.cursor = "move";
|
|
41135
|
-
state.draggedItemId = args.draggedItemId;
|
|
41136
|
-
const container = direction === "horizontal"
|
|
41137
|
-
? new HorizontalContainer(args.containerEl)
|
|
41138
|
-
: new VerticalContainer(args.containerEl);
|
|
41139
|
-
dndHelper = new DOMDndHelper({
|
|
41140
|
-
...args,
|
|
41141
|
-
container,
|
|
41142
|
-
onChange,
|
|
41143
|
-
onDragEnd,
|
|
41144
|
-
onCancel: state.cancel,
|
|
41145
|
-
});
|
|
41146
|
-
const stopListening = startDnd(dndHelper.onMouseMove.bind(dndHelper), dndHelper.onMouseUp.bind(dndHelper));
|
|
41147
|
-
cleanupFns.push(stopListening);
|
|
41148
|
-
const onScroll = dndHelper.onScroll.bind(dndHelper);
|
|
41149
|
-
args.containerEl.addEventListener("scroll", onScroll);
|
|
41150
|
-
cleanupFns.push(() => args.containerEl.removeEventListener("scroll", onScroll));
|
|
41151
|
-
cleanupFns.push(dndHelper.destroy.bind(dndHelper));
|
|
41152
|
-
};
|
|
41153
|
-
owl.onWillUnmount(() => {
|
|
41154
|
-
cleanUp();
|
|
41155
|
-
});
|
|
41156
|
-
const state = owl.useState({
|
|
41157
|
-
itemsStyle: {},
|
|
41158
|
-
draggedItemId: undefined,
|
|
41159
|
-
start,
|
|
41160
|
-
cancel: () => { },
|
|
41161
|
-
});
|
|
41162
|
-
return state;
|
|
41163
|
-
}
|
|
41164
|
-
class DOMDndHelper {
|
|
41165
|
-
draggedItemId;
|
|
41166
|
-
items;
|
|
41167
|
-
container;
|
|
41168
|
-
initialMousePosition;
|
|
41169
|
-
currentMousePosition;
|
|
41170
|
-
initialScroll;
|
|
41171
|
-
minPosition;
|
|
41172
|
-
maxPosition;
|
|
41173
|
-
edgeScrollIntervalId;
|
|
41174
|
-
onChange;
|
|
41175
|
-
onCancel;
|
|
41176
|
-
onDragEnd;
|
|
41177
|
-
/**
|
|
41178
|
-
* The dead zone is an area in which the pointermove events are ignored.
|
|
41179
|
-
*
|
|
41180
|
-
* This is useful when swapping the dragged item with a larger item. After the swap,
|
|
41181
|
-
* the mouse is still hovering on the item we just swapped with. In this case, we don't want
|
|
41182
|
-
* a mouse move to trigger another swap the other way around, so we create a dead zone. We will clear
|
|
41183
|
-
* the dead zone when the mouse leaves the swapped item.
|
|
41184
|
-
*/
|
|
41185
|
-
deadZone;
|
|
41186
|
-
constructor(args) {
|
|
41187
|
-
this.items = args.items.map((item) => ({ ...item, positionAtStart: item.position }));
|
|
41188
|
-
this.draggedItemId = args.draggedItemId;
|
|
41189
|
-
this.container = args.container;
|
|
41190
|
-
this.onChange = args.onChange;
|
|
41191
|
-
this.onCancel = args.onCancel;
|
|
41192
|
-
this.onDragEnd = args.onDragEnd;
|
|
41193
|
-
this.initialMousePosition = args.initialMousePosition;
|
|
41194
|
-
this.currentMousePosition = args.initialMousePosition;
|
|
41195
|
-
this.initialScroll = this.container.scroll;
|
|
41196
|
-
this.minPosition = this.items[0].position;
|
|
41197
|
-
this.maxPosition =
|
|
41198
|
-
this.items[this.items.length - 1].position + this.items[this.items.length - 1].size;
|
|
41199
|
-
}
|
|
41200
|
-
getItemStyles() {
|
|
41201
|
-
const styles = {};
|
|
41202
|
-
for (let item of this.items) {
|
|
41203
|
-
styles[item.id] = this.getItemStyle(item.id);
|
|
41204
|
-
}
|
|
41205
|
-
return styles;
|
|
41206
|
-
}
|
|
41207
|
-
getItemStyle(itemId) {
|
|
41208
|
-
const position = this.container.cssPositionProperty;
|
|
41209
|
-
const style = {};
|
|
41210
|
-
style.position = "relative";
|
|
41211
|
-
style[position] = (this.getItemsPositions()[itemId] || 0) + "px";
|
|
41212
|
-
style.transition = `${position} 0.5s`;
|
|
41213
|
-
style["pointer-events"] = "none";
|
|
41214
|
-
if (this.draggedItemId === itemId) {
|
|
41215
|
-
style.transition = `${position} 0s`;
|
|
41216
|
-
style["z-index"] = "1000";
|
|
41217
|
-
}
|
|
41218
|
-
return cssPropertiesToCss(style);
|
|
41219
|
-
}
|
|
41220
|
-
onScroll() {
|
|
41221
|
-
this.moveDraggedItemToPosition(this.currentMousePosition + this.scrollOffset);
|
|
41222
|
-
}
|
|
41223
|
-
onMouseMove(ev) {
|
|
41224
|
-
if (ev.button > 1) {
|
|
41225
|
-
this.onCancel();
|
|
41226
|
-
return;
|
|
41227
|
-
}
|
|
41228
|
-
const mousePosition = this.container.getMousePosition(ev);
|
|
41229
|
-
this.currentMousePosition = mousePosition;
|
|
41230
|
-
if (mousePosition < this.container.start || mousePosition > this.container.end) {
|
|
41231
|
-
this.startEdgeScroll(mousePosition < this.container.start ? -1 : 1);
|
|
41232
|
-
return;
|
|
41233
|
-
}
|
|
41234
|
-
else {
|
|
41235
|
-
this.stopEdgeScroll();
|
|
41236
|
-
}
|
|
41237
|
-
this.moveDraggedItemToPosition(mousePosition + this.scrollOffset);
|
|
41238
|
-
}
|
|
41239
|
-
moveDraggedItemToPosition(position) {
|
|
41240
|
-
const hoveredItemIndex = this.getHoveredItemIndex(position, this.items);
|
|
41241
|
-
const draggedItemIndex = this.items.findIndex((item) => item.id === this.draggedItemId);
|
|
41242
|
-
const draggedItem = this.items[draggedItemIndex];
|
|
41243
|
-
if (this.deadZone && this.isInZone(position, this.deadZone)) {
|
|
41244
|
-
this.onChange(this.getItemsPositions());
|
|
41245
|
-
return;
|
|
41246
|
-
}
|
|
41247
|
-
else if (this.isInZone(position, {
|
|
41248
|
-
start: draggedItem.position,
|
|
41249
|
-
end: draggedItem.position + draggedItem.size,
|
|
41250
|
-
})) {
|
|
41251
|
-
this.deadZone = undefined;
|
|
41252
|
-
}
|
|
41253
|
-
if (draggedItemIndex === hoveredItemIndex) {
|
|
41254
|
-
this.onChange(this.getItemsPositions());
|
|
41255
|
-
return;
|
|
41256
|
-
}
|
|
41257
|
-
const startIndex = Math.min(draggedItemIndex, hoveredItemIndex);
|
|
41258
|
-
const endIndex = Math.max(draggedItemIndex, hoveredItemIndex);
|
|
41259
|
-
const direction = Math.sign(hoveredItemIndex - draggedItemIndex);
|
|
41260
|
-
let draggedItemMoveSize = 0;
|
|
41261
|
-
for (let i = startIndex; i <= endIndex; i++) {
|
|
41262
|
-
if (i === draggedItemIndex) {
|
|
41263
|
-
continue;
|
|
41264
|
-
}
|
|
41265
|
-
this.items[i].position -= direction * draggedItem.size;
|
|
41266
|
-
draggedItemMoveSize += this.items[i].size;
|
|
41267
|
-
}
|
|
41268
|
-
draggedItem.position += direction * draggedItemMoveSize;
|
|
41269
|
-
this.items.sort((item1, item2) => item1.position - item2.position);
|
|
41270
|
-
this.deadZone =
|
|
41271
|
-
direction > 0
|
|
41272
|
-
? { start: position, end: draggedItem.position }
|
|
41273
|
-
: { start: draggedItem.position + draggedItem.size, end: position };
|
|
41274
|
-
this.onChange(this.getItemsPositions());
|
|
41275
|
-
}
|
|
41276
|
-
onMouseUp(ev) {
|
|
41277
|
-
if (ev.button !== 0) {
|
|
41278
|
-
this.onCancel();
|
|
41279
|
-
}
|
|
41280
|
-
ev.stopPropagation();
|
|
41281
|
-
ev.preventDefault();
|
|
41282
|
-
const targetItemIndex = this.items.findIndex((item) => item.id === this.draggedItemId);
|
|
41283
|
-
this.onDragEnd(this.draggedItemId, targetItemIndex);
|
|
41284
|
-
this.stopEdgeScroll();
|
|
41285
|
-
return false;
|
|
41286
|
-
}
|
|
41287
|
-
startEdgeScroll(direction) {
|
|
41288
|
-
if (this.edgeScrollIntervalId)
|
|
41289
|
-
return;
|
|
41290
|
-
this.edgeScrollIntervalId = window.setInterval(() => {
|
|
41291
|
-
const offset = direction * 3;
|
|
41292
|
-
this.container.scroll += offset;
|
|
41293
|
-
}, 5);
|
|
41294
|
-
}
|
|
41295
|
-
stopEdgeScroll() {
|
|
41296
|
-
window.clearInterval(this.edgeScrollIntervalId);
|
|
41297
|
-
this.edgeScrollIntervalId = undefined;
|
|
41298
|
-
}
|
|
41299
|
-
/**
|
|
41300
|
-
* Get the index of the item the given mouse position is inside.
|
|
41301
|
-
* If the mouse is outside the container, return the first or last item index.
|
|
41302
|
-
*/
|
|
41303
|
-
getHoveredItemIndex(mousePosition, items) {
|
|
41304
|
-
if (mousePosition <= this.minPosition)
|
|
41305
|
-
return 0;
|
|
41306
|
-
if (mousePosition >= this.maxPosition)
|
|
41307
|
-
return items.length - 1;
|
|
41308
|
-
return items.findIndex((item) => item.position + item.size >= mousePosition);
|
|
41309
|
-
}
|
|
41310
|
-
getItemsPositions() {
|
|
41311
|
-
const positions = {};
|
|
41312
|
-
for (let item of this.items) {
|
|
41313
|
-
if (item.id !== this.draggedItemId) {
|
|
41314
|
-
positions[item.id] = item.position - item.positionAtStart;
|
|
41315
|
-
continue;
|
|
41316
|
-
}
|
|
41317
|
-
const mouseOffset = this.currentMousePosition - this.initialMousePosition;
|
|
41318
|
-
let start = mouseOffset + this.scrollOffset;
|
|
41319
|
-
start = Math.max(this.minPosition - item.positionAtStart, start);
|
|
41320
|
-
start = Math.min(this.maxPosition - item.positionAtStart - item.size, start);
|
|
41321
|
-
positions[item.id] = start;
|
|
41322
|
-
}
|
|
41323
|
-
return positions;
|
|
41324
|
-
}
|
|
41325
|
-
isInZone(position, zone) {
|
|
41326
|
-
return position >= zone.start && position <= zone.end;
|
|
41327
|
-
}
|
|
41328
|
-
get scrollOffset() {
|
|
41329
|
-
return this.container.scroll - this.initialScroll;
|
|
41330
|
-
}
|
|
41331
|
-
destroy() {
|
|
41332
|
-
this.stopEdgeScroll();
|
|
41333
|
-
}
|
|
41334
|
-
}
|
|
41335
|
-
class ContainerWrapper {
|
|
41336
|
-
el;
|
|
41337
|
-
constructor(el) {
|
|
41338
|
-
this.el = el;
|
|
41339
|
-
}
|
|
41340
|
-
get containerRect() {
|
|
41341
|
-
return this.el.getBoundingClientRect();
|
|
41342
|
-
}
|
|
41343
|
-
}
|
|
41344
|
-
class VerticalContainer extends ContainerWrapper {
|
|
41345
|
-
get start() {
|
|
41346
|
-
return this.containerRect.top;
|
|
41347
|
-
}
|
|
41348
|
-
get end() {
|
|
41349
|
-
return this.containerRect.bottom;
|
|
41350
|
-
}
|
|
41351
|
-
get cssPositionProperty() {
|
|
41352
|
-
return "top";
|
|
41353
|
-
}
|
|
41354
|
-
get scroll() {
|
|
41355
|
-
return this.el.scrollTop;
|
|
41356
|
-
}
|
|
41357
|
-
set scroll(scroll) {
|
|
41358
|
-
this.el.scrollTop = scroll;
|
|
41359
|
-
}
|
|
41360
|
-
getMousePosition(ev) {
|
|
41361
|
-
return ev.clientY;
|
|
41362
|
-
}
|
|
41363
|
-
}
|
|
41364
|
-
class HorizontalContainer extends ContainerWrapper {
|
|
41365
|
-
get start() {
|
|
41366
|
-
return this.containerRect.left;
|
|
41367
|
-
}
|
|
41368
|
-
get end() {
|
|
41369
|
-
return this.containerRect.right;
|
|
41370
|
-
}
|
|
41371
|
-
get cssPositionProperty() {
|
|
41372
|
-
return "left";
|
|
41373
|
-
}
|
|
41374
|
-
get scroll() {
|
|
41375
|
-
return this.el.scrollLeft;
|
|
41376
|
-
}
|
|
41377
|
-
set scroll(scroll) {
|
|
41378
|
-
this.el.scrollLeft = scroll;
|
|
41379
|
-
}
|
|
41380
|
-
getMousePosition(ev) {
|
|
41381
|
-
return ev.clientX;
|
|
41382
|
-
}
|
|
41383
|
-
}
|
|
41384
|
-
|
|
41385
41474
|
/**
|
|
41386
41475
|
* Manages an event listener on a ref. Useful for hooks that want to manage
|
|
41387
41476
|
* event listeners, especially more than one. Prefer using t-on directly in
|
|
@@ -46285,7 +46374,7 @@ pivotRegistry.add("SPREADSHEET", {
|
|
|
46285
46374
|
onIterationEndEvaluation: (pivot) => pivot.markAsDirtyForEvaluation(),
|
|
46286
46375
|
dateGranularities: [...dateGranularities],
|
|
46287
46376
|
datetimeGranularities: [...dateGranularities, "hour_number", "minute_number", "second_number"],
|
|
46288
|
-
isMeasureCandidate: (field) =>
|
|
46377
|
+
isMeasureCandidate: (field) => field.type !== "boolean",
|
|
46289
46378
|
isGroupable: () => true,
|
|
46290
46379
|
});
|
|
46291
46380
|
|
|
@@ -46503,8 +46592,11 @@ class PivotSidePanelStore extends SpreadsheetStore {
|
|
|
46503
46592
|
};
|
|
46504
46593
|
}
|
|
46505
46594
|
getUnusedGranularities(fields, definition) {
|
|
46506
|
-
const { columns, rows } = definition;
|
|
46507
|
-
const dateFields = columns
|
|
46595
|
+
const { columns, rows, measures } = definition;
|
|
46596
|
+
const dateFields = columns
|
|
46597
|
+
.concat(rows)
|
|
46598
|
+
.concat(measures)
|
|
46599
|
+
.filter((dimension) => {
|
|
46508
46600
|
const fieldType = fields[dimension.fieldName]?.type;
|
|
46509
46601
|
return fieldType === "date" || fieldType === "datetime";
|
|
46510
46602
|
});
|
|
@@ -48776,7 +48868,7 @@ class GridComposer extends owl.Component {
|
|
|
48776
48868
|
return;
|
|
48777
48869
|
}
|
|
48778
48870
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
48779
|
-
const zone = this.env.model.getters.
|
|
48871
|
+
const zone = positionToZone(this.env.model.getters.getSelection().anchor.cell);
|
|
48780
48872
|
const rect = this.env.model.getters.getVisibleRect(zone);
|
|
48781
48873
|
if (!deepEquals(rect, this.rect) || sheetId !== this.composerStore.currentEditedCell.sheetId) {
|
|
48782
48874
|
this.isCellReferenceVisible = true;
|
|
@@ -50612,13 +50704,23 @@ class GridRenderer {
|
|
|
50612
50704
|
drawLayer(renderingContext, layer) {
|
|
50613
50705
|
switch (layer) {
|
|
50614
50706
|
case "Background":
|
|
50615
|
-
|
|
50616
|
-
this.
|
|
50617
|
-
|
|
50618
|
-
|
|
50619
|
-
|
|
50620
|
-
|
|
50621
|
-
|
|
50707
|
+
this.drawGlobalBackground(renderingContext);
|
|
50708
|
+
for (const zone of this.getters.getAllActiveViewportsZones()) {
|
|
50709
|
+
const { ctx } = renderingContext;
|
|
50710
|
+
ctx.save();
|
|
50711
|
+
ctx.beginPath();
|
|
50712
|
+
const rect = this.getters.getVisibleRect(zone);
|
|
50713
|
+
ctx.rect(rect.x, rect.y, rect.width, rect.height);
|
|
50714
|
+
ctx.clip();
|
|
50715
|
+
const boxes = this.getGridBoxes(zone);
|
|
50716
|
+
this.drawBackground(renderingContext, boxes);
|
|
50717
|
+
this.drawOverflowingCellBackground(renderingContext, boxes);
|
|
50718
|
+
this.drawCellBackground(renderingContext, boxes);
|
|
50719
|
+
this.drawBorders(renderingContext, boxes);
|
|
50720
|
+
this.drawTexts(renderingContext, boxes);
|
|
50721
|
+
this.drawIcon(renderingContext, boxes);
|
|
50722
|
+
ctx.restore();
|
|
50723
|
+
}
|
|
50622
50724
|
this.drawFrozenPanes(renderingContext);
|
|
50623
50725
|
break;
|
|
50624
50726
|
case "Headers":
|
|
@@ -50629,12 +50731,15 @@ class GridRenderer {
|
|
|
50629
50731
|
break;
|
|
50630
50732
|
}
|
|
50631
50733
|
}
|
|
50632
|
-
|
|
50633
|
-
const { ctx
|
|
50734
|
+
drawGlobalBackground(renderingContext) {
|
|
50735
|
+
const { ctx } = renderingContext;
|
|
50634
50736
|
const { width, height } = this.getters.getSheetViewDimensionWithHeaders();
|
|
50635
50737
|
// white background
|
|
50636
50738
|
ctx.fillStyle = "#ffffff";
|
|
50637
50739
|
ctx.fillRect(0, 0, width + CANVAS_SHIFT, height + CANVAS_SHIFT);
|
|
50740
|
+
}
|
|
50741
|
+
drawBackground(renderingContext, boxes) {
|
|
50742
|
+
const { ctx, thinLineWidth } = renderingContext;
|
|
50638
50743
|
const areGridLinesVisible = !this.getters.isDashboard() &&
|
|
50639
50744
|
this.getters.getGridLinesVisibility(this.getters.getActiveSheetId());
|
|
50640
50745
|
const inset = areGridLinesVisible ? 0.1 * thinLineWidth : 0;
|
|
@@ -51065,7 +51170,7 @@ class GridRenderer {
|
|
|
51065
51170
|
const position = { sheetId, col, row };
|
|
51066
51171
|
const cell = this.getters.getEvaluatedCell(position);
|
|
51067
51172
|
const showFormula = this.getters.shouldShowFormulas();
|
|
51068
|
-
const { x, y, width, height } = this.getters.
|
|
51173
|
+
const { x, y, width, height } = this.getters.getRect(zone);
|
|
51069
51174
|
const { verticalAlign } = this.getters.getCellStyle(position);
|
|
51070
51175
|
let style = this.getters.getCellComputedStyle(position);
|
|
51071
51176
|
if (this.fingerprints.isEnabled) {
|
|
@@ -51190,12 +51295,16 @@ class GridRenderer {
|
|
|
51190
51295
|
}
|
|
51191
51296
|
return box;
|
|
51192
51297
|
}
|
|
51193
|
-
getGridBoxes() {
|
|
51298
|
+
getGridBoxes(zone) {
|
|
51194
51299
|
const boxes = [];
|
|
51195
|
-
const visibleCols = this.getters
|
|
51300
|
+
const visibleCols = this.getters
|
|
51301
|
+
.getSheetViewVisibleCols()
|
|
51302
|
+
.filter((col) => col >= zone.left && col <= zone.right);
|
|
51196
51303
|
const left = visibleCols[0];
|
|
51197
51304
|
const right = visibleCols[visibleCols.length - 1];
|
|
51198
|
-
const visibleRows = this.getters
|
|
51305
|
+
const visibleRows = this.getters
|
|
51306
|
+
.getSheetViewVisibleRows()
|
|
51307
|
+
.filter((row) => row >= zone.top && row <= zone.bottom);
|
|
51199
51308
|
const top = visibleRows[0];
|
|
51200
51309
|
const bottom = visibleRows[visibleRows.length - 1];
|
|
51201
51310
|
const viewport = { left, right, top, bottom };
|
|
@@ -53427,7 +53536,7 @@ class CellPlugin extends CorePlugin {
|
|
|
53427
53536
|
/*
|
|
53428
53537
|
* Reconstructs the original formula string based on new dependencies
|
|
53429
53538
|
*/
|
|
53430
|
-
getFormulaString(sheetId, tokens, dependencies,
|
|
53539
|
+
getFormulaString(sheetId, tokens, dependencies, useBoundedReference = false) {
|
|
53431
53540
|
if (!dependencies.length) {
|
|
53432
53541
|
return concat(tokens.map((token) => token.value));
|
|
53433
53542
|
}
|
|
@@ -53435,7 +53544,7 @@ class CellPlugin extends CorePlugin {
|
|
|
53435
53544
|
return concat(tokens.map((token) => {
|
|
53436
53545
|
if (token.type === "REFERENCE") {
|
|
53437
53546
|
const range = dependencies[rangeIndex++];
|
|
53438
|
-
return this.getters.getRangeString(range, sheetId, {
|
|
53547
|
+
return this.getters.getRangeString(range, sheetId, { useBoundedReference });
|
|
53439
53548
|
}
|
|
53440
53549
|
return token.value;
|
|
53441
53550
|
}));
|
|
@@ -53715,7 +53824,7 @@ class FormulaCellWithDependencies {
|
|
|
53715
53824
|
if (token.type === "REFERENCE") {
|
|
53716
53825
|
const index = rangeIndex++;
|
|
53717
53826
|
return this.getRangeString(this.compiledFormula.dependencies[index], this.sheetId, {
|
|
53718
|
-
|
|
53827
|
+
useBoundedReference: true,
|
|
53719
53828
|
});
|
|
53720
53829
|
}
|
|
53721
53830
|
return token.value;
|
|
@@ -54052,7 +54161,7 @@ class ConditionalFormatPlugin extends CorePlugin {
|
|
|
54052
54161
|
if (data.sheets) {
|
|
54053
54162
|
for (let sheet of data.sheets) {
|
|
54054
54163
|
if (this.cfRules[sheet.id]) {
|
|
54055
|
-
sheet.conditionalFormats = this.cfRules[sheet.id].map((rule) => this.mapToConditionalFormat(sheet.id, rule, {
|
|
54164
|
+
sheet.conditionalFormats = this.cfRules[sheet.id].map((rule) => this.mapToConditionalFormat(sheet.id, rule, { useBoundedReference: true }));
|
|
54056
54165
|
}
|
|
54057
54166
|
}
|
|
54058
54167
|
}
|
|
@@ -54121,9 +54230,9 @@ class ConditionalFormatPlugin extends CorePlugin {
|
|
|
54121
54230
|
// ---------------------------------------------------------------------------
|
|
54122
54231
|
// Private
|
|
54123
54232
|
// ---------------------------------------------------------------------------
|
|
54124
|
-
mapToConditionalFormat(sheetId, cf, {
|
|
54233
|
+
mapToConditionalFormat(sheetId, cf, { useBoundedReference } = { useBoundedReference: false }) {
|
|
54125
54234
|
const ranges = cf.ranges.map((range) => {
|
|
54126
|
-
return this.getters.getRangeString(range, sheetId, {
|
|
54235
|
+
return this.getters.getRangeString(range, sheetId, { useBoundedReference });
|
|
54127
54236
|
});
|
|
54128
54237
|
if (cf.rule.type !== "DataBarRule") {
|
|
54129
54238
|
return {
|
|
@@ -54138,7 +54247,7 @@ class ConditionalFormatPlugin extends CorePlugin {
|
|
|
54138
54247
|
...cf.rule,
|
|
54139
54248
|
rangeValues: cf.rule.rangeValues &&
|
|
54140
54249
|
this.getters.getRangeString(cf.rule.rangeValues, sheetId, {
|
|
54141
|
-
|
|
54250
|
+
useBoundedReference,
|
|
54142
54251
|
}),
|
|
54143
54252
|
},
|
|
54144
54253
|
ranges,
|
|
@@ -54579,10 +54688,20 @@ class DataValidationPlugin extends CorePlugin {
|
|
|
54579
54688
|
for (const sheet of data.sheets) {
|
|
54580
54689
|
sheet.dataValidationRules = [];
|
|
54581
54690
|
for (const rule of this.rules[sheet.id]) {
|
|
54582
|
-
|
|
54583
|
-
...rule,
|
|
54584
|
-
ranges: rule.ranges.map((range) => this.getters.getRangeString(range, sheet.id, {
|
|
54585
|
-
}
|
|
54691
|
+
const excelRule = {
|
|
54692
|
+
...deepCopy(rule),
|
|
54693
|
+
ranges: rule.ranges.map((range) => this.getters.getRangeString(range, sheet.id, { useBoundedReference: true })),
|
|
54694
|
+
};
|
|
54695
|
+
if (rule.criterion.type === "isValueInRange") {
|
|
54696
|
+
excelRule.criterion.values = rule.criterion.values.map((value) => {
|
|
54697
|
+
const range = this.getters.getRangeFromSheetXC(sheet.id, value);
|
|
54698
|
+
return this.getters.getRangeString(range, sheet.id, {
|
|
54699
|
+
useBoundedReference: true,
|
|
54700
|
+
useFixedReference: true,
|
|
54701
|
+
});
|
|
54702
|
+
});
|
|
54703
|
+
}
|
|
54704
|
+
sheet.dataValidationRules.push(excelRule);
|
|
54586
54705
|
}
|
|
54587
54706
|
}
|
|
54588
54707
|
}
|
|
@@ -56003,9 +56122,10 @@ class RangeAdapter {
|
|
|
56003
56122
|
* @param range the range (received from getRangeFromXC or getRangeFromZone)
|
|
56004
56123
|
* @param forSheetId the id of the sheet where the range string is supposed to be used.
|
|
56005
56124
|
* @param options
|
|
56125
|
+
* @param options.useBoundedReference if true, the range will be returned with bounded row and column
|
|
56006
56126
|
* @param options.useFixedReference if true, the range will be returned with fixed row and column
|
|
56007
56127
|
*/
|
|
56008
|
-
getRangeString(range, forSheetId, options = { useFixedReference: false }) {
|
|
56128
|
+
getRangeString(range, forSheetId, options = { useBoundedReference: false, useFixedReference: false }) {
|
|
56009
56129
|
if (!range) {
|
|
56010
56130
|
return CellErrorType.InvalidReference;
|
|
56011
56131
|
}
|
|
@@ -56108,13 +56228,13 @@ class RangeAdapter {
|
|
|
56108
56228
|
/**
|
|
56109
56229
|
* Get a Xc string that represent a part of a range
|
|
56110
56230
|
*/
|
|
56111
|
-
getRangePartString(range, part, options = { useFixedReference: false }) {
|
|
56112
|
-
const colFixed = range.parts
|
|
56231
|
+
getRangePartString(range, part, options = { useBoundedReference: false, useFixedReference: false }) {
|
|
56232
|
+
const colFixed = range.parts[part]?.colFixed || options.useFixedReference ? "$" : "";
|
|
56113
56233
|
const col = part === 0 ? numberToLetters(range.zone.left) : numberToLetters(range.zone.right);
|
|
56114
|
-
const rowFixed = range.parts
|
|
56234
|
+
const rowFixed = range.parts[part]?.rowFixed || options.useFixedReference ? "$" : "";
|
|
56115
56235
|
const row = part === 0 ? String(range.zone.top + 1) : String(range.zone.bottom + 1);
|
|
56116
56236
|
let str = "";
|
|
56117
|
-
if (range.isFullCol && !options.
|
|
56237
|
+
if (range.isFullCol && !options.useBoundedReference) {
|
|
56118
56238
|
if (part === 0 && range.unboundedZone.hasHeader) {
|
|
56119
56239
|
str = colFixed + col + rowFixed + row;
|
|
56120
56240
|
}
|
|
@@ -56122,7 +56242,7 @@ class RangeAdapter {
|
|
|
56122
56242
|
str = colFixed + col;
|
|
56123
56243
|
}
|
|
56124
56244
|
}
|
|
56125
|
-
else if (range.isFullRow && !options.
|
|
56245
|
+
else if (range.isFullRow && !options.useBoundedReference) {
|
|
56126
56246
|
if (part === 0 && range.unboundedZone.hasHeader) {
|
|
56127
56247
|
str = colFixed + col + rowFixed + row;
|
|
56128
56248
|
}
|
|
@@ -63297,6 +63417,7 @@ class Session extends EventBus {
|
|
|
63297
63417
|
waitingUndoRedoAck = false;
|
|
63298
63418
|
isReplayingInitialRevisions = false;
|
|
63299
63419
|
processedRevisions = new Set();
|
|
63420
|
+
lastRevisionMessage = undefined;
|
|
63300
63421
|
uuidGenerator = new UuidGenerator();
|
|
63301
63422
|
lastLocalOperation;
|
|
63302
63423
|
/**
|
|
@@ -63397,7 +63518,10 @@ class Session extends EventBus {
|
|
|
63397
63518
|
* Notify the server that the user client left the collaborative session
|
|
63398
63519
|
*/
|
|
63399
63520
|
async leave(data) {
|
|
63400
|
-
if (data &&
|
|
63521
|
+
if (data &&
|
|
63522
|
+
Object.keys(this.clients).length === 1 &&
|
|
63523
|
+
this.lastRevisionMessage &&
|
|
63524
|
+
this.lastRevisionMessage?.type !== "SNAPSHOT_CREATED") {
|
|
63401
63525
|
await this.snapshot(data());
|
|
63402
63526
|
}
|
|
63403
63527
|
delete this.clients[this.clientId];
|
|
@@ -63618,6 +63742,7 @@ class Session extends EventBus {
|
|
|
63618
63742
|
this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
|
|
63619
63743
|
this.serverRevisionId = message.nextRevisionId;
|
|
63620
63744
|
this.processedRevisions.add(message.nextRevisionId);
|
|
63745
|
+
this.lastRevisionMessage = message;
|
|
63621
63746
|
this.sendPendingMessage();
|
|
63622
63747
|
break;
|
|
63623
63748
|
}
|
|
@@ -66848,8 +66973,12 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
66848
66973
|
},
|
|
66849
66974
|
];
|
|
66850
66975
|
handler.paste({ zones: pasteTarget, sheetId }, data, { isCutOperation: true });
|
|
66976
|
+
const selection = pasteTarget[0];
|
|
66977
|
+
const col = selection.left;
|
|
66978
|
+
const row = selection.top;
|
|
66979
|
+
this.setSelectionMixin({ zone: selection, cell: { col, row } }, [selection]);
|
|
66851
66980
|
const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
|
|
66852
|
-
let currentIndex = cmd.base;
|
|
66981
|
+
let currentIndex = isBasedBefore ? cmd.base : cmd.base + 1;
|
|
66853
66982
|
const resizingGroups = {};
|
|
66854
66983
|
for (const element of toRemove) {
|
|
66855
66984
|
const size = this.getters.getHeaderSize(cmd.sheetId, cmd.dimension, element);
|
|
@@ -67140,22 +67269,33 @@ class InternalViewport {
|
|
|
67140
67269
|
}
|
|
67141
67270
|
/**
|
|
67142
67271
|
*
|
|
67143
|
-
*
|
|
67144
|
-
*
|
|
67272
|
+
* Computes the visible coordinates & dimensions of a given zone inside the viewport
|
|
67273
|
+
*
|
|
67145
67274
|
*/
|
|
67146
|
-
|
|
67275
|
+
getVisibleRect(zone) {
|
|
67147
67276
|
const targetZone = intersection(zone, this);
|
|
67148
67277
|
if (targetZone) {
|
|
67149
67278
|
const x = this.getters.getColRowOffset("COL", this.left, targetZone.left) + this.offsetCorrectionX;
|
|
67150
67279
|
const y = this.getters.getColRowOffset("ROW", this.top, targetZone.top) + this.offsetCorrectionY;
|
|
67151
67280
|
const width = Math.min(this.getters.getColRowOffset("COL", targetZone.left, targetZone.right + 1), this.viewportWidth);
|
|
67152
67281
|
const height = Math.min(this.getters.getColRowOffset("ROW", targetZone.top, targetZone.bottom + 1), this.viewportHeight);
|
|
67153
|
-
return {
|
|
67154
|
-
|
|
67155
|
-
|
|
67156
|
-
|
|
67157
|
-
|
|
67158
|
-
|
|
67282
|
+
return { x, y, width, height };
|
|
67283
|
+
}
|
|
67284
|
+
return undefined;
|
|
67285
|
+
}
|
|
67286
|
+
/**
|
|
67287
|
+
*
|
|
67288
|
+
* @returns Computes the absolute coordinates & dimensions of a given zone inside the viewport
|
|
67289
|
+
*
|
|
67290
|
+
*/
|
|
67291
|
+
getFullRect(zone) {
|
|
67292
|
+
const targetZone = intersection(zone, this);
|
|
67293
|
+
if (targetZone) {
|
|
67294
|
+
const x = this.getters.getColRowOffset("COL", this.left, zone.left) + this.offsetCorrectionX;
|
|
67295
|
+
const y = this.getters.getColRowOffset("ROW", this.top, zone.top) + this.offsetCorrectionY;
|
|
67296
|
+
const width = this.getters.getColRowOffset("COL", zone.left, zone.right + 1);
|
|
67297
|
+
const height = this.getters.getColRowOffset("ROW", zone.top, zone.bottom + 1);
|
|
67298
|
+
return { x, y, width, height };
|
|
67159
67299
|
}
|
|
67160
67300
|
return undefined;
|
|
67161
67301
|
}
|
|
@@ -67325,6 +67465,8 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67325
67465
|
"isPositionVisible",
|
|
67326
67466
|
"getColDimensionsInViewport",
|
|
67327
67467
|
"getRowDimensionsInViewport",
|
|
67468
|
+
"getAllActiveViewportsZones",
|
|
67469
|
+
"getRect",
|
|
67328
67470
|
];
|
|
67329
67471
|
viewports = {};
|
|
67330
67472
|
/**
|
|
@@ -67708,16 +67850,27 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67708
67850
|
getVisibleRectWithoutHeaders(zone) {
|
|
67709
67851
|
const sheetId = this.getters.getActiveSheetId();
|
|
67710
67852
|
const viewportRects = this.getSubViewports(sheetId)
|
|
67711
|
-
.map((viewport) => viewport.
|
|
67853
|
+
.map((viewport) => viewport.getVisibleRect(zone))
|
|
67712
67854
|
.filter(isDefined);
|
|
67713
67855
|
if (viewportRects.length === 0) {
|
|
67714
67856
|
return { x: 0, y: 0, width: 0, height: 0 };
|
|
67715
67857
|
}
|
|
67716
|
-
|
|
67717
|
-
|
|
67718
|
-
|
|
67719
|
-
|
|
67720
|
-
|
|
67858
|
+
return this.recomposeRect(viewportRects);
|
|
67859
|
+
}
|
|
67860
|
+
/**
|
|
67861
|
+
* Computes the actual size and position (:Rect) of the zone on the canvas
|
|
67862
|
+
* regardless of the viewport dimensions.
|
|
67863
|
+
*/
|
|
67864
|
+
getRect(zone) {
|
|
67865
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
67866
|
+
const viewportRects = this.getSubViewports(sheetId)
|
|
67867
|
+
.map((viewport) => viewport.getFullRect(zone))
|
|
67868
|
+
.filter(isDefined);
|
|
67869
|
+
if (viewportRects.length === 0) {
|
|
67870
|
+
return { x: 0, y: 0, width: 0, height: 0 };
|
|
67871
|
+
}
|
|
67872
|
+
const rect = this.recomposeRect(viewportRects);
|
|
67873
|
+
return { ...rect, x: rect.x + this.gridOffsetX, y: rect.y + this.gridOffsetY };
|
|
67721
67874
|
}
|
|
67722
67875
|
/**
|
|
67723
67876
|
* Returns the position of the MainViewport relatively to the start of the grid (without headers)
|
|
@@ -67761,6 +67914,10 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67761
67914
|
end: start + (isRowHidden ? 0 : size),
|
|
67762
67915
|
};
|
|
67763
67916
|
}
|
|
67917
|
+
getAllActiveViewportsZones() {
|
|
67918
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
67919
|
+
return this.getSubViewports(sheetId);
|
|
67920
|
+
}
|
|
67764
67921
|
// ---------------------------------------------------------------------------
|
|
67765
67922
|
// Private
|
|
67766
67923
|
// ---------------------------------------------------------------------------
|
|
@@ -67951,6 +68108,13 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67951
68108
|
const height = this.sheetViewHeight + this.gridOffsetY;
|
|
67952
68109
|
return { xRatio: offsetCorrectionX / width, yRatio: offsetCorrectionY / height };
|
|
67953
68110
|
}
|
|
68111
|
+
recomposeRect(viewportRects) {
|
|
68112
|
+
const x = Math.min(...viewportRects.map((rect) => rect.x));
|
|
68113
|
+
const y = Math.min(...viewportRects.map((rect) => rect.y));
|
|
68114
|
+
const width = Math.max(...viewportRects.map((rect) => rect.x + rect.width)) - x;
|
|
68115
|
+
const height = Math.max(...viewportRects.map((rect) => rect.y + rect.height)) - y;
|
|
68116
|
+
return { x, y, width, height };
|
|
68117
|
+
}
|
|
67954
68118
|
}
|
|
67955
68119
|
|
|
67956
68120
|
class HeaderPositionsUIPlugin extends UIPlugin {
|
|
@@ -69792,6 +69956,13 @@ class BorderEditorWidget extends owl.Component {
|
|
|
69792
69956
|
currentStyle: DEFAULT_BORDER_DESC.style,
|
|
69793
69957
|
currentPosition: undefined,
|
|
69794
69958
|
});
|
|
69959
|
+
setup() {
|
|
69960
|
+
owl.onWillUpdateProps((newProps) => {
|
|
69961
|
+
if (!newProps.showBorderEditor) {
|
|
69962
|
+
this.state.currentPosition = undefined;
|
|
69963
|
+
}
|
|
69964
|
+
});
|
|
69965
|
+
}
|
|
69795
69966
|
get borderEditorAnchorRect() {
|
|
69796
69967
|
const button = this.borderEditorButtonRef.el;
|
|
69797
69968
|
const buttonRect = button.getBoundingClientRect();
|
|
@@ -75103,6 +75274,6 @@ exports.tokenColors = tokenColors;
|
|
|
75103
75274
|
exports.tokenize = tokenize;
|
|
75104
75275
|
|
|
75105
75276
|
|
|
75106
|
-
__info__.version = "18.2.0-alpha.
|
|
75107
|
-
__info__.date = "2025-01-
|
|
75108
|
-
__info__.hash = "
|
|
75277
|
+
__info__.version = "18.2.0-alpha.4";
|
|
75278
|
+
__info__.date = "2025-01-29T06:30:12.773Z";
|
|
75279
|
+
__info__.hash = "6838c26";
|