@odoo/o-spreadsheet 16.4.21 → 16.4.24
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 +257 -154
- package/dist/o-spreadsheet.d.ts +28 -14
- package/dist/o-spreadsheet.esm.js +257 -154
- package/dist/o-spreadsheet.iife.js +257 -154
- package/dist/o-spreadsheet.iife.min.js +103 -103
- package/dist/o_spreadsheet.xml +15 -33
- package/package.json +1 -1
|
@@ -705,18 +705,18 @@ function isConsecutive(iterable) {
|
|
|
705
705
|
return true;
|
|
706
706
|
}
|
|
707
707
|
class JetSet extends Set {
|
|
708
|
-
|
|
708
|
+
addMany(iterable) {
|
|
709
709
|
for (const element of iterable) {
|
|
710
710
|
super.add(element);
|
|
711
711
|
}
|
|
712
712
|
return this;
|
|
713
713
|
}
|
|
714
|
-
|
|
715
|
-
let
|
|
714
|
+
deleteMany(iterable) {
|
|
715
|
+
let wasDeleted = false;
|
|
716
716
|
for (const element of iterable) {
|
|
717
|
-
|
|
717
|
+
wasDeleted ||= super.delete(element);
|
|
718
718
|
}
|
|
719
|
-
return
|
|
719
|
+
return wasDeleted;
|
|
720
720
|
}
|
|
721
721
|
}
|
|
722
722
|
/**
|
|
@@ -1842,6 +1842,9 @@ function parseFormat(formatString) {
|
|
|
1842
1842
|
function formatValue(value, { format, locale }) {
|
|
1843
1843
|
switch (typeof value) {
|
|
1844
1844
|
case "string":
|
|
1845
|
+
if (value.includes('\\"')) {
|
|
1846
|
+
return value.replace(/\\"/g, '"');
|
|
1847
|
+
}
|
|
1845
1848
|
return value;
|
|
1846
1849
|
case "boolean":
|
|
1847
1850
|
return value ? "TRUE" : "FALSE";
|
|
@@ -15239,6 +15242,9 @@ function isValidLocale(locale) {
|
|
|
15239
15242
|
if (locale.formulaArgSeparator === locale.decimalSeparator) {
|
|
15240
15243
|
return false;
|
|
15241
15244
|
}
|
|
15245
|
+
if (locale.thousandsSeparator === locale.decimalSeparator) {
|
|
15246
|
+
return false;
|
|
15247
|
+
}
|
|
15242
15248
|
try {
|
|
15243
15249
|
formatValue(1, { locale, format: "#,##0.00" });
|
|
15244
15250
|
formatValue(1, { locale, format: locale.dateFormat });
|
|
@@ -15329,7 +15335,7 @@ function canonicalizeNumberLiteral(content, locale) {
|
|
|
15329
15335
|
if (locale.decimalSeparator === "." || !isNumber(content, locale)) {
|
|
15330
15336
|
return content;
|
|
15331
15337
|
}
|
|
15332
|
-
return content.replace(locale.decimalSeparator, ".");
|
|
15338
|
+
return content.replace(locale.thousandsSeparator, "").replace(locale.decimalSeparator, ".");
|
|
15333
15339
|
}
|
|
15334
15340
|
/**
|
|
15335
15341
|
* Change a content string from the given locale to its canonical form (en_US locale). Also convert date string.
|
|
@@ -18631,6 +18637,12 @@ const INSERT_LINK = (env) => {
|
|
|
18631
18637
|
let { col, row } = env.model.getters.getActivePosition();
|
|
18632
18638
|
env.model.dispatch("OPEN_CELL_POPOVER", { col, row, popoverType: "LinkEditor" });
|
|
18633
18639
|
};
|
|
18640
|
+
const INSERT_LINK_NAME = (env) => {
|
|
18641
|
+
const sheetId = env.model.getters.getActiveSheetId();
|
|
18642
|
+
const { col, row } = env.model.getters.getActivePosition();
|
|
18643
|
+
const cell = env.model.getters.getEvaluatedCell({ sheetId, col, row });
|
|
18644
|
+
return cell && cell.link ? _lt("Edit link") : _lt("Insert link");
|
|
18645
|
+
};
|
|
18634
18646
|
//------------------------------------------------------------------------------
|
|
18635
18647
|
// Filters action
|
|
18636
18648
|
//------------------------------------------------------------------------------
|
|
@@ -19171,7 +19183,7 @@ cellMenuRegistry
|
|
|
19171
19183
|
})
|
|
19172
19184
|
.add("insert_link", {
|
|
19173
19185
|
...insertLink,
|
|
19174
|
-
name:
|
|
19186
|
+
name: INSERT_LINK_NAME,
|
|
19175
19187
|
sequence: 150,
|
|
19176
19188
|
separator: true,
|
|
19177
19189
|
});
|
|
@@ -20659,7 +20671,7 @@ class SelectionInput extends owl.Component {
|
|
|
20659
20671
|
: this.props.ranges()
|
|
20660
20672
|
? this.props.ranges().map((xc, id) => ({
|
|
20661
20673
|
xc,
|
|
20662
|
-
id,
|
|
20674
|
+
id: id + 1,
|
|
20663
20675
|
isFocused: false,
|
|
20664
20676
|
}))
|
|
20665
20677
|
: [];
|
|
@@ -24082,6 +24094,7 @@ class Composer extends owl.Component {
|
|
|
24082
24094
|
static components = { TextValueProvider, FunctionDescriptionProvider };
|
|
24083
24095
|
static defaultProps = {
|
|
24084
24096
|
inputStyle: "",
|
|
24097
|
+
isDefaultFocus: false,
|
|
24085
24098
|
};
|
|
24086
24099
|
composerRef = owl.useRef("o_composer");
|
|
24087
24100
|
contentHelper = new ContentEditableHelper(this.composerRef.el);
|
|
@@ -24134,7 +24147,6 @@ class Composer extends owl.Component {
|
|
|
24134
24147
|
F2: () => console.warn("Not implemented"),
|
|
24135
24148
|
F4: this.processF4Key,
|
|
24136
24149
|
Tab: (ev) => this.processTabKey(ev),
|
|
24137
|
-
" ": (ev) => this.processSpaceKey(ev),
|
|
24138
24150
|
};
|
|
24139
24151
|
keyCodeMapping = {
|
|
24140
24152
|
NumpadDecimal: this.processNumpadDecimal,
|
|
@@ -24142,11 +24154,11 @@ class Composer extends owl.Component {
|
|
|
24142
24154
|
setup() {
|
|
24143
24155
|
owl.onMounted(() => {
|
|
24144
24156
|
const el = this.composerRef.el;
|
|
24157
|
+
if (this.props.isDefaultFocus) {
|
|
24158
|
+
this.env.focusableElement.setFocusableElement(el);
|
|
24159
|
+
}
|
|
24145
24160
|
this.contentHelper.updateEl(el);
|
|
24146
24161
|
});
|
|
24147
|
-
owl.onWillUnmount(() => {
|
|
24148
|
-
this.props.onComposerUnmounted?.();
|
|
24149
|
-
});
|
|
24150
24162
|
owl.useEffect(() => {
|
|
24151
24163
|
this.processContent();
|
|
24152
24164
|
});
|
|
@@ -24155,7 +24167,8 @@ class Composer extends owl.Component {
|
|
|
24155
24167
|
// Handlers
|
|
24156
24168
|
// ---------------------------------------------------------------------------
|
|
24157
24169
|
processArrowKeys(ev) {
|
|
24158
|
-
if (this.env.model.getters.isSelectingForComposer()
|
|
24170
|
+
if (this.env.model.getters.isSelectingForComposer() ||
|
|
24171
|
+
this.env.model.getters.getEditionMode() === "inactive") {
|
|
24159
24172
|
this.functionDescriptionState.showDescription = false;
|
|
24160
24173
|
// Prevent the default content editable behavior which moves the cursor
|
|
24161
24174
|
ev.preventDefault();
|
|
@@ -24194,25 +24207,19 @@ class Composer extends owl.Component {
|
|
|
24194
24207
|
processTabKey(ev) {
|
|
24195
24208
|
ev.preventDefault();
|
|
24196
24209
|
ev.stopPropagation();
|
|
24197
|
-
if (this.
|
|
24198
|
-
|
|
24199
|
-
|
|
24200
|
-
|
|
24201
|
-
|
|
24210
|
+
if (this.env.model.getters.getEditionMode() !== "inactive") {
|
|
24211
|
+
if (this.autoCompleteState.showProvider) {
|
|
24212
|
+
const autoCompleteValue = this.autoCompleteState.values[this.autoCompleteState.selectedIndex]?.text;
|
|
24213
|
+
if (autoCompleteValue) {
|
|
24214
|
+
this.autoComplete(autoCompleteValue);
|
|
24215
|
+
return;
|
|
24216
|
+
}
|
|
24202
24217
|
}
|
|
24218
|
+
this.env.model.dispatch("STOP_EDITION");
|
|
24203
24219
|
}
|
|
24204
24220
|
const direction = ev.shiftKey ? "left" : "right";
|
|
24205
|
-
this.env.model.dispatch("STOP_EDITION");
|
|
24206
24221
|
this.env.model.selection.moveAnchorCell(direction, 1);
|
|
24207
24222
|
}
|
|
24208
|
-
processSpaceKey(ev) {
|
|
24209
|
-
if (ev.ctrlKey) {
|
|
24210
|
-
ev.preventDefault();
|
|
24211
|
-
ev.stopPropagation();
|
|
24212
|
-
this.showAutocomplete("");
|
|
24213
|
-
this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
|
|
24214
|
-
}
|
|
24215
|
-
}
|
|
24216
24223
|
processEnterKey(ev) {
|
|
24217
24224
|
ev.preventDefault();
|
|
24218
24225
|
ev.stopPropagation();
|
|
@@ -24264,6 +24271,9 @@ class Composer extends owl.Component {
|
|
|
24264
24271
|
this.compositionActive = false;
|
|
24265
24272
|
}
|
|
24266
24273
|
onKeydown(ev) {
|
|
24274
|
+
if (this.env.model.getters.getEditionMode() === "inactive") {
|
|
24275
|
+
return;
|
|
24276
|
+
}
|
|
24267
24277
|
let handler = this.keyMapping[ev.key] || this.keyCodeMapping[ev.code];
|
|
24268
24278
|
if (handler) {
|
|
24269
24279
|
handler.call(this, ev);
|
|
@@ -24272,14 +24282,33 @@ class Composer extends owl.Component {
|
|
|
24272
24282
|
ev.stopPropagation();
|
|
24273
24283
|
}
|
|
24274
24284
|
}
|
|
24285
|
+
onPaste(ev) {
|
|
24286
|
+
if (this.env.model.getters.getEditionMode() !== "inactive") {
|
|
24287
|
+
ev.stopPropagation();
|
|
24288
|
+
}
|
|
24289
|
+
}
|
|
24275
24290
|
/*
|
|
24276
24291
|
* Triggered automatically by the content-editable between the keydown and key up
|
|
24277
24292
|
* */
|
|
24278
24293
|
onInput(ev) {
|
|
24279
|
-
if (
|
|
24294
|
+
if (!this.shouldProcessInputEvents) {
|
|
24280
24295
|
return;
|
|
24281
24296
|
}
|
|
24282
|
-
|
|
24297
|
+
if (ev.inputType === "insertFromPaste" &&
|
|
24298
|
+
this.env.model.getters.getEditionMode() === "inactive") {
|
|
24299
|
+
return;
|
|
24300
|
+
}
|
|
24301
|
+
ev.stopPropagation();
|
|
24302
|
+
let content;
|
|
24303
|
+
if (this.env.model.getters.getEditionMode() === "inactive") {
|
|
24304
|
+
content = ev.data || "";
|
|
24305
|
+
}
|
|
24306
|
+
else {
|
|
24307
|
+
content = this.contentHelper.getText();
|
|
24308
|
+
}
|
|
24309
|
+
if (this.props.focus === "inactive") {
|
|
24310
|
+
return this.props.onComposerCellFocused?.(content);
|
|
24311
|
+
}
|
|
24283
24312
|
let selection = this.contentHelper.getCurrentSelection();
|
|
24284
24313
|
if (ev.inputType === "insertParagraph") {
|
|
24285
24314
|
const start = Math.min(selection.start, selection.end);
|
|
@@ -24357,9 +24386,8 @@ class Composer extends owl.Component {
|
|
|
24357
24386
|
}
|
|
24358
24387
|
const newSelection = this.contentHelper.getCurrentSelection();
|
|
24359
24388
|
this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
|
|
24360
|
-
|
|
24361
|
-
|
|
24362
|
-
}
|
|
24389
|
+
this.props.onComposerContentFocused();
|
|
24390
|
+
if (this.props.focus === "inactive") ;
|
|
24363
24391
|
this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", newSelection);
|
|
24364
24392
|
this.processTokenAtCursor();
|
|
24365
24393
|
}
|
|
@@ -24526,7 +24554,7 @@ class Composer extends owl.Component {
|
|
|
24526
24554
|
const highlights = this.env.model.getters.getHighlights();
|
|
24527
24555
|
const refSheet = sheetName
|
|
24528
24556
|
? this.env.model.getters.getSheetIdByName(sheetName)
|
|
24529
|
-
: this.env.model.getters.getCurrentEditedCell()
|
|
24557
|
+
: this.env.model.getters.getCurrentEditedCell()?.sheetId;
|
|
24530
24558
|
const highlight = highlights.find((highlight) => {
|
|
24531
24559
|
if (highlight.sheetId !== refSheet)
|
|
24532
24560
|
return false;
|
|
@@ -24606,12 +24634,13 @@ class Composer extends owl.Component {
|
|
|
24606
24634
|
}
|
|
24607
24635
|
}
|
|
24608
24636
|
Composer.props = {
|
|
24609
|
-
focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
|
|
24610
|
-
onComposerContentFocused: Function,
|
|
24611
24637
|
inputStyle: { type: String, optional: true },
|
|
24612
24638
|
rect: { type: Object, optional: true },
|
|
24613
24639
|
delimitation: { type: Object, optional: true },
|
|
24614
|
-
|
|
24640
|
+
focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
|
|
24641
|
+
onComposerCellFocused: { type: Function, optional: true },
|
|
24642
|
+
onComposerContentFocused: Function,
|
|
24643
|
+
isDefaultFocus: { type: Boolean, optional: true },
|
|
24615
24644
|
};
|
|
24616
24645
|
|
|
24617
24646
|
const COMPOSER_BORDER_WIDTH = 3 * 0.4 * window.devicePixelRatio || 1;
|
|
@@ -24645,51 +24674,26 @@ css /* scss */ `
|
|
|
24645
24674
|
class GridComposer extends owl.Component {
|
|
24646
24675
|
static template = "o-spreadsheet-GridComposer";
|
|
24647
24676
|
static components = { Composer };
|
|
24648
|
-
|
|
24649
|
-
|
|
24650
|
-
|
|
24677
|
+
// TODORAR see if we can keep it undefined
|
|
24678
|
+
rect = this.defaultRect;
|
|
24679
|
+
isEditing = false;
|
|
24651
24680
|
isCellReferenceVisible;
|
|
24652
|
-
|
|
24681
|
+
get defaultRect() {
|
|
24682
|
+
return { x: 0, y: 0, width: 0, height: 0 };
|
|
24683
|
+
}
|
|
24653
24684
|
setup() {
|
|
24654
|
-
this.gridComposerRef = owl.useRef("gridComposer");
|
|
24655
|
-
this.composerState = owl.useState({
|
|
24656
|
-
rect: undefined,
|
|
24657
|
-
delimitation: undefined,
|
|
24658
|
-
});
|
|
24659
|
-
const { sheetId, col, row } = this.env.model.getters.getActivePosition();
|
|
24660
|
-
this.zone = this.env.model.getters.expandZone(sheetId, positionToZone({ col, row }));
|
|
24661
|
-
this.rect = this.env.model.getters.getVisibleRect(this.zone);
|
|
24662
|
-
this.isCellReferenceVisible = false;
|
|
24663
|
-
owl.onMounted(() => {
|
|
24664
|
-
const el = this.gridComposerRef.el;
|
|
24665
|
-
this.composerState.rect = {
|
|
24666
|
-
x: this.rect.x,
|
|
24667
|
-
y: this.rect.y,
|
|
24668
|
-
width: el.clientWidth,
|
|
24669
|
-
height: el.clientHeight,
|
|
24670
|
-
};
|
|
24671
|
-
this.composerState.delimitation = {
|
|
24672
|
-
width: this.props.gridDims.width,
|
|
24673
|
-
height: this.props.gridDims.height,
|
|
24674
|
-
};
|
|
24675
|
-
});
|
|
24676
24685
|
owl.onWillUpdateProps(() => {
|
|
24677
|
-
|
|
24678
|
-
|
|
24679
|
-
}
|
|
24680
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
24681
|
-
const zone = this.env.model.getters.getSelectedZone();
|
|
24682
|
-
const rect = this.env.model.getters.getVisibleRect(zone);
|
|
24683
|
-
if (!deepEquals(rect, this.rect) ||
|
|
24684
|
-
sheetId !== this.env.model.getters.getCurrentEditedCell().sheetId) {
|
|
24685
|
-
this.isCellReferenceVisible = true;
|
|
24686
|
-
}
|
|
24686
|
+
this.updateComponentPosition();
|
|
24687
|
+
this.updateCellReferenceVisibility();
|
|
24687
24688
|
});
|
|
24688
24689
|
}
|
|
24689
24690
|
get shouldDisplayCellReference() {
|
|
24690
24691
|
return this.isCellReferenceVisible;
|
|
24691
24692
|
}
|
|
24692
24693
|
get cellReference() {
|
|
24694
|
+
if (!this.env.model.getters.getCurrentEditedCell()) {
|
|
24695
|
+
return "";
|
|
24696
|
+
}
|
|
24693
24697
|
const { col, row, sheetId } = this.env.model.getters.getCurrentEditedCell();
|
|
24694
24698
|
const prefixSheet = sheetId !== this.env.model.getters.getActiveSheetId();
|
|
24695
24699
|
return `${prefixSheet ? getCanonicalSheetName(this.env.model.getters.getSheetName(sheetId)) + "!" : ""}${toXC(col, row)}`;
|
|
@@ -24701,7 +24705,27 @@ class GridComposer extends owl.Component {
|
|
|
24701
24705
|
top: `${top - GRID_CELL_REFERENCE_TOP_OFFSET}px`,
|
|
24702
24706
|
});
|
|
24703
24707
|
}
|
|
24708
|
+
get composerProps() {
|
|
24709
|
+
const { width, height } = this.env.model.getters.getSheetViewDimensionWithHeaders();
|
|
24710
|
+
return {
|
|
24711
|
+
rect: { ...this.rect },
|
|
24712
|
+
delimitation: {
|
|
24713
|
+
width,
|
|
24714
|
+
height,
|
|
24715
|
+
},
|
|
24716
|
+
focus: this.props.focus,
|
|
24717
|
+
isDefaultFocus: true,
|
|
24718
|
+
onComposerContentFocused: this.props.onComposerContentFocused,
|
|
24719
|
+
onComposerCellFocused: this.props.onComposerCellFocused,
|
|
24720
|
+
};
|
|
24721
|
+
}
|
|
24704
24722
|
get containerStyle() {
|
|
24723
|
+
if (this.env.model.getters.getEditionMode() === "inactive" || !this.rect) {
|
|
24724
|
+
return `
|
|
24725
|
+
position: absolute;
|
|
24726
|
+
z-index: -1000;
|
|
24727
|
+
`;
|
|
24728
|
+
}
|
|
24705
24729
|
const isFormula = this.env.model.getters.getCurrentContent().startsWith("=");
|
|
24706
24730
|
const cell = this.env.model.getters.getActiveCell();
|
|
24707
24731
|
const position = this.env.model.getters.getActivePosition();
|
|
@@ -24721,6 +24745,8 @@ class GridComposer extends owl.Component {
|
|
|
24721
24745
|
if (!isFormula) {
|
|
24722
24746
|
textAlign = style.align || cell.defaultAlign;
|
|
24723
24747
|
}
|
|
24748
|
+
const maxHeight = this.props.gridDims.height - this.rect.y;
|
|
24749
|
+
const maxWidth = this.props.gridDims.width - this.rect.x;
|
|
24724
24750
|
/**
|
|
24725
24751
|
* min-size is on the container, not the composer element, because we want to have the same size as the cell by default,
|
|
24726
24752
|
* including all the paddings/margins of the composer
|
|
@@ -24732,6 +24758,8 @@ class GridComposer extends owl.Component {
|
|
|
24732
24758
|
top: `${top}px`,
|
|
24733
24759
|
"min-width": `${width + 1}px`,
|
|
24734
24760
|
"min-height": `${height + 1}px`,
|
|
24761
|
+
"max-width": `${maxWidth}px`,
|
|
24762
|
+
"max-height": `${maxHeight}px`,
|
|
24735
24763
|
background,
|
|
24736
24764
|
color,
|
|
24737
24765
|
"font-size": `${fontSizeInPixels(fontSize)}px`,
|
|
@@ -24741,20 +24769,38 @@ class GridComposer extends owl.Component {
|
|
|
24741
24769
|
"text-align": textAlign,
|
|
24742
24770
|
});
|
|
24743
24771
|
}
|
|
24744
|
-
|
|
24745
|
-
const
|
|
24746
|
-
|
|
24747
|
-
|
|
24748
|
-
|
|
24749
|
-
|
|
24750
|
-
|
|
24772
|
+
updateComponentPosition() {
|
|
24773
|
+
const isEditing = this.env.model.getters.getEditionMode() !== "inactive";
|
|
24774
|
+
if (this.isEditing !== isEditing) {
|
|
24775
|
+
this.isEditing = isEditing;
|
|
24776
|
+
if (!isEditing) {
|
|
24777
|
+
this.rect = this.defaultRect;
|
|
24778
|
+
this.env.focusableElement.focus();
|
|
24779
|
+
return;
|
|
24780
|
+
}
|
|
24781
|
+
const position = this.env.model.getters.getActivePosition();
|
|
24782
|
+
const zone = this.env.model.getters.expandZone(position.sheetId, positionToZone(position));
|
|
24783
|
+
this.rect = this.env.model.getters.getVisibleRect(zone);
|
|
24784
|
+
}
|
|
24785
|
+
}
|
|
24786
|
+
updateCellReferenceVisibility() {
|
|
24787
|
+
if (this.isCellReferenceVisible || this.env.model.getters.getEditionMode() === "inactive") {
|
|
24788
|
+
return;
|
|
24789
|
+
}
|
|
24790
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
24791
|
+
const zone = this.env.model.getters.getSelectedZone();
|
|
24792
|
+
const rect = this.env.model.getters.getVisibleRect(zone);
|
|
24793
|
+
if (!deepEquals(rect, this.rect) ||
|
|
24794
|
+
sheetId !== this.env.model.getters.getCurrentEditedCell().sheetId) {
|
|
24795
|
+
this.isCellReferenceVisible = true;
|
|
24796
|
+
}
|
|
24751
24797
|
}
|
|
24752
24798
|
}
|
|
24753
24799
|
GridComposer.props = {
|
|
24754
24800
|
focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
|
|
24755
|
-
onComposerUnmounted: Function,
|
|
24756
24801
|
onComposerContentFocused: Function,
|
|
24757
24802
|
gridDims: Object,
|
|
24803
|
+
onComposerCellFocused: Function,
|
|
24758
24804
|
};
|
|
24759
24805
|
|
|
24760
24806
|
const CSS$1 = css /* scss */ `
|
|
@@ -25635,7 +25681,6 @@ class GridOverlay extends owl.Component {
|
|
|
25635
25681
|
this.props.onCellDoubleClicked(col, row);
|
|
25636
25682
|
}
|
|
25637
25683
|
onContextMenu(ev) {
|
|
25638
|
-
ev.preventDefault();
|
|
25639
25684
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
25640
25685
|
this.props.onCellRightClicked(col, row, { x: ev.clientX, y: ev.clientY });
|
|
25641
25686
|
}
|
|
@@ -26728,7 +26773,6 @@ class Grid extends owl.Component {
|
|
|
26728
26773
|
HEADER_WIDTH = HEADER_WIDTH;
|
|
26729
26774
|
menuState;
|
|
26730
26775
|
gridRef;
|
|
26731
|
-
hiddenInput;
|
|
26732
26776
|
onMouseWheel;
|
|
26733
26777
|
canvasPosition;
|
|
26734
26778
|
hoveredCell;
|
|
@@ -26739,17 +26783,16 @@ class Grid extends owl.Component {
|
|
|
26739
26783
|
menuItems: [],
|
|
26740
26784
|
});
|
|
26741
26785
|
this.gridRef = owl.useRef("grid");
|
|
26742
|
-
this.hiddenInput = owl.useRef("hiddenInput");
|
|
26743
26786
|
this.canvasPosition = useAbsoluteBoundingRect(this.gridRef);
|
|
26744
26787
|
this.hoveredCell = owl.useState({ col: undefined, row: undefined });
|
|
26745
26788
|
owl.useChildSubEnv({ getPopoverContainerRect: () => this.getGridRect() });
|
|
26746
26789
|
owl.useExternalListener(document.body, "cut", this.copy.bind(this, true));
|
|
26747
26790
|
owl.useExternalListener(document.body, "copy", this.copy.bind(this, false));
|
|
26748
26791
|
owl.useExternalListener(document.body, "paste", this.paste);
|
|
26749
|
-
owl.onMounted(() => this.
|
|
26750
|
-
this.props.exposeFocus(() => this.
|
|
26792
|
+
owl.onMounted(() => this.focusDefaultElement());
|
|
26793
|
+
this.props.exposeFocus(() => this.focusDefaultElement());
|
|
26751
26794
|
useGridDrawing("canvas", this.env.model, () => this.env.model.getters.getSheetViewDimensionWithHeaders());
|
|
26752
|
-
owl.useEffect(() => this.
|
|
26795
|
+
owl.useEffect(() => this.focusDefaultElement(), () => [this.env.model.getters.getActiveSheetId()]);
|
|
26753
26796
|
this.onMouseWheel = useWheelHandler((deltaX, deltaY) => {
|
|
26754
26797
|
this.moveCanvas(deltaX, deltaY);
|
|
26755
26798
|
this.hoveredCell.col = undefined;
|
|
@@ -26772,7 +26815,7 @@ class Grid extends owl.Component {
|
|
|
26772
26815
|
if (this.env.model.getters.hasOpenedPopover()) {
|
|
26773
26816
|
this.closeOpenedPopover();
|
|
26774
26817
|
}
|
|
26775
|
-
this.
|
|
26818
|
+
this.focusDefaultElement();
|
|
26776
26819
|
}
|
|
26777
26820
|
// this map will handle most of the actions that should happen on key down. The arrow keys are managed in the key
|
|
26778
26821
|
// down itself
|
|
@@ -26945,10 +26988,10 @@ class Grid extends owl.Component {
|
|
|
26945
26988
|
PAGEUP: () => this.env.model.dispatch("SHIFT_VIEWPORT_UP"),
|
|
26946
26989
|
"CTRL+K": () => INSERT_LINK(this.env),
|
|
26947
26990
|
};
|
|
26948
|
-
|
|
26991
|
+
focusDefaultElement() {
|
|
26949
26992
|
if (!this.env.model.getters.getSelectedFigureId() &&
|
|
26950
26993
|
this.env.model.getters.getEditionMode() === "inactive") {
|
|
26951
|
-
this.
|
|
26994
|
+
this.env.focusableElement.focus();
|
|
26952
26995
|
}
|
|
26953
26996
|
}
|
|
26954
26997
|
get gridEl() {
|
|
@@ -27092,19 +27135,6 @@ class Grid extends owl.Component {
|
|
|
27092
27135
|
return;
|
|
27093
27136
|
}
|
|
27094
27137
|
}
|
|
27095
|
-
onInput(ev) {
|
|
27096
|
-
// the user meant to paste in the sheet, not open the composer with the pasted content
|
|
27097
|
-
if (!ev.isComposing && ev.inputType === "insertFromPaste") {
|
|
27098
|
-
return;
|
|
27099
|
-
}
|
|
27100
|
-
if (ev.data) {
|
|
27101
|
-
// if the user types a character on the grid, it means he wants to start composing the selected cell with that
|
|
27102
|
-
// character
|
|
27103
|
-
ev.preventDefault();
|
|
27104
|
-
ev.stopPropagation();
|
|
27105
|
-
this.props.onGridComposerCellFocused(ev.data);
|
|
27106
|
-
}
|
|
27107
|
-
}
|
|
27108
27138
|
// ---------------------------------------------------------------------------
|
|
27109
27139
|
// Context Menu
|
|
27110
27140
|
// ---------------------------------------------------------------------------
|
|
@@ -27217,7 +27247,7 @@ class Grid extends owl.Component {
|
|
|
27217
27247
|
}
|
|
27218
27248
|
closeMenu() {
|
|
27219
27249
|
this.menuState.isOpen = false;
|
|
27220
|
-
this.
|
|
27250
|
+
this.focusDefaultElement();
|
|
27221
27251
|
}
|
|
27222
27252
|
}
|
|
27223
27253
|
Grid.props = {
|
|
@@ -30878,8 +30908,16 @@ const MIGRATIONS = [
|
|
|
30878
30908
|
},
|
|
30879
30909
|
},
|
|
30880
30910
|
{
|
|
30881
|
-
description: "
|
|
30911
|
+
description: "Fix datafilter duplication",
|
|
30882
30912
|
from: 12,
|
|
30913
|
+
to: 12.5,
|
|
30914
|
+
applyMigration(data) {
|
|
30915
|
+
return fixOverlappingFilters(data);
|
|
30916
|
+
},
|
|
30917
|
+
},
|
|
30918
|
+
{
|
|
30919
|
+
description: "Change Border description structure",
|
|
30920
|
+
from: 12.5,
|
|
30883
30921
|
to: 13,
|
|
30884
30922
|
applyMigration(data) {
|
|
30885
30923
|
for (const borderId in data.borders) {
|
|
@@ -30910,6 +30948,14 @@ const MIGRATIONS = [
|
|
|
30910
30948
|
return data;
|
|
30911
30949
|
},
|
|
30912
30950
|
},
|
|
30951
|
+
{
|
|
30952
|
+
description: "Fix datafilter duplication (post saas-16.4)",
|
|
30953
|
+
from: 14,
|
|
30954
|
+
to: 14.5,
|
|
30955
|
+
applyMigration(data) {
|
|
30956
|
+
return fixOverlappingFilters(data);
|
|
30957
|
+
},
|
|
30958
|
+
},
|
|
30913
30959
|
];
|
|
30914
30960
|
/**
|
|
30915
30961
|
* This function is used to repair faulty data independently of the migration.
|
|
@@ -31067,6 +31113,26 @@ function fixChartDefinitions(data, initialMessages) {
|
|
|
31067
31113
|
}
|
|
31068
31114
|
return messages;
|
|
31069
31115
|
}
|
|
31116
|
+
function fixOverlappingFilters(data) {
|
|
31117
|
+
for (let sheet of data.sheets || []) {
|
|
31118
|
+
let knownDataFilterZones = [];
|
|
31119
|
+
for (let filterTable of sheet.filterTables || []) {
|
|
31120
|
+
const zone = toZone(filterTable.range);
|
|
31121
|
+
// See commit message of https://github.com/odoo/o-spreadsheet/pull/3632 of more details
|
|
31122
|
+
const intersectZoneIndex = knownDataFilterZones.findIndex((knownZone) => overlap(knownZone, zone));
|
|
31123
|
+
if (intersectZoneIndex !== -1) {
|
|
31124
|
+
knownDataFilterZones[intersectZoneIndex] = zone;
|
|
31125
|
+
}
|
|
31126
|
+
else {
|
|
31127
|
+
knownDataFilterZones.push(zone);
|
|
31128
|
+
}
|
|
31129
|
+
}
|
|
31130
|
+
sheet.filterTables = knownDataFilterZones.map((zone) => ({
|
|
31131
|
+
range: zoneToXc(zone),
|
|
31132
|
+
}));
|
|
31133
|
+
}
|
|
31134
|
+
return data;
|
|
31135
|
+
}
|
|
31070
31136
|
// -----------------------------------------------------------------------------
|
|
31071
31137
|
// Helpers
|
|
31072
31138
|
// -----------------------------------------------------------------------------
|
|
@@ -31796,9 +31862,9 @@ class CellPlugin extends CorePlugin {
|
|
|
31796
31862
|
allowDispatch(cmd) {
|
|
31797
31863
|
switch (cmd.type) {
|
|
31798
31864
|
case "UPDATE_CELL":
|
|
31799
|
-
return this.
|
|
31865
|
+
return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessUpdateCell);
|
|
31800
31866
|
case "CLEAR_CELL":
|
|
31801
|
-
return this.checkValidations(cmd, this.
|
|
31867
|
+
return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessClearCell);
|
|
31802
31868
|
default:
|
|
31803
31869
|
return 0 /* CommandResult.Success */;
|
|
31804
31870
|
}
|
|
@@ -31930,10 +31996,6 @@ class CellPlugin extends CorePlugin {
|
|
|
31930
31996
|
format: cell.format ? getItemId(cell.format, formats) : undefined,
|
|
31931
31997
|
content: cell.content || undefined,
|
|
31932
31998
|
};
|
|
31933
|
-
// if there is a formula but no dependencies (maybe because the cell is in error), no need to recompute the formula text
|
|
31934
|
-
if (cell.isFormula && cell.dependencies.length) {
|
|
31935
|
-
cells[xc].content = this.buildFormulaContent(_sheet.id, cell, cell.dependencies, true);
|
|
31936
|
-
}
|
|
31937
31999
|
}
|
|
31938
32000
|
_sheet.cells = cells;
|
|
31939
32001
|
}
|
|
@@ -32096,10 +32158,7 @@ class CellPlugin extends CorePlugin {
|
|
|
32096
32158
|
else {
|
|
32097
32159
|
style = before ? before.style : undefined;
|
|
32098
32160
|
}
|
|
32099
|
-
const
|
|
32100
|
-
let format = ("format" in after ? after.format : before && before.format) ||
|
|
32101
|
-
detectDateFormat(afterContent, locale) ||
|
|
32102
|
-
detectNumberFormat(afterContent);
|
|
32161
|
+
const format = "format" in after ? after.format : before && before.format;
|
|
32103
32162
|
/* Read the following IF as:
|
|
32104
32163
|
* we need to remove the cell if it is completely empty, but we can know if it completely empty if:
|
|
32105
32164
|
* - the command says the new content is empty and has no border/format/style
|
|
@@ -32140,12 +32199,11 @@ class CellPlugin extends CorePlugin {
|
|
|
32140
32199
|
}
|
|
32141
32200
|
createLiteralCell(id, content, format, style) {
|
|
32142
32201
|
const locale = this.getters.getLocale();
|
|
32143
|
-
content = parseLiteral(content, locale).toString();
|
|
32144
32202
|
return {
|
|
32145
32203
|
id,
|
|
32146
|
-
content,
|
|
32204
|
+
content: parseLiteral(content, locale).toString(),
|
|
32147
32205
|
style,
|
|
32148
|
-
format,
|
|
32206
|
+
format: format || detectDateFormat(content, locale) || detectNumberFormat(content),
|
|
32149
32207
|
isFormula: false,
|
|
32150
32208
|
};
|
|
32151
32209
|
}
|
|
@@ -32206,6 +32264,18 @@ class CellPlugin extends CorePlugin {
|
|
|
32206
32264
|
}
|
|
32207
32265
|
return 0 /* CommandResult.Success */;
|
|
32208
32266
|
}
|
|
32267
|
+
checkUselessUpdateCell(cmd) {
|
|
32268
|
+
const cell = this.getters.getCell(cmd);
|
|
32269
|
+
const hasContent = "content" in cmd || "formula" in cmd;
|
|
32270
|
+
const hasStyle = "style" in cmd;
|
|
32271
|
+
const hasFormat = "format" in cmd;
|
|
32272
|
+
if ((!hasContent || cell?.content === cmd.content) &&
|
|
32273
|
+
(!hasStyle || deepEquals(cell?.style, cmd.style)) &&
|
|
32274
|
+
(!hasFormat || cell?.format === cmd.format)) {
|
|
32275
|
+
return 98 /* CommandResult.NoChanges */;
|
|
32276
|
+
}
|
|
32277
|
+
return 0 /* CommandResult.Success */;
|
|
32278
|
+
}
|
|
32209
32279
|
}
|
|
32210
32280
|
class FormulaCellWithDependencies {
|
|
32211
32281
|
id;
|
|
@@ -36346,7 +36416,15 @@ class SpreadsheetRTree {
|
|
|
36346
36416
|
if (!this.rTrees[sheetId]) {
|
|
36347
36417
|
return;
|
|
36348
36418
|
}
|
|
36349
|
-
this.rTrees[sheetId].remove(item,
|
|
36419
|
+
this.rTrees[sheetId].remove(item, this.rtreeItemComparer);
|
|
36420
|
+
}
|
|
36421
|
+
rtreeItemComparer(left, right) {
|
|
36422
|
+
return (left.data == right.data &&
|
|
36423
|
+
left.boundingBox.sheetId === right.boundingBox.sheetId &&
|
|
36424
|
+
left.boundingBox?.zone.left === right.boundingBox.zone.left &&
|
|
36425
|
+
left.boundingBox?.zone.top === right.boundingBox.zone.top &&
|
|
36426
|
+
left.boundingBox?.zone.right === right.boundingBox.zone.right &&
|
|
36427
|
+
left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom);
|
|
36350
36428
|
}
|
|
36351
36429
|
}
|
|
36352
36430
|
/**
|
|
@@ -36424,7 +36502,7 @@ class FormulaDependencyGraph {
|
|
|
36424
36502
|
const queue = Array.from(ranges).reverse();
|
|
36425
36503
|
while (queue.length > 0) {
|
|
36426
36504
|
const range = queue.pop();
|
|
36427
|
-
visited.
|
|
36505
|
+
visited.addMany(this.encoder.encodeBoundingBox(range));
|
|
36428
36506
|
const impactedPositionIds = this.rTree.search(range).map((dep) => dep.data);
|
|
36429
36507
|
for (const positionId of impactedPositionIds) {
|
|
36430
36508
|
if (!visited.has(positionId)) {
|
|
@@ -36432,7 +36510,7 @@ class FormulaDependencyGraph {
|
|
|
36432
36510
|
}
|
|
36433
36511
|
}
|
|
36434
36512
|
}
|
|
36435
|
-
visited.
|
|
36513
|
+
visited.deleteMany(ranges.flatMap((r) => this.encoder.encodeBoundingBox(r)));
|
|
36436
36514
|
return visited;
|
|
36437
36515
|
}
|
|
36438
36516
|
}
|
|
@@ -36563,9 +36641,9 @@ class Evaluator {
|
|
|
36563
36641
|
const cells = positions.map((p) => this.encoder.encode(p));
|
|
36564
36642
|
const cellsToCompute = new JetSet(cells);
|
|
36565
36643
|
const arrayFormulasPositionIds = this.getArrayFormulasImpactedByChangesOf(cells);
|
|
36566
|
-
cellsToCompute.
|
|
36567
|
-
cellsToCompute.
|
|
36568
|
-
cellsToCompute.
|
|
36644
|
+
cellsToCompute.addMany(this.getCellsDependingOn(cells));
|
|
36645
|
+
cellsToCompute.addMany(arrayFormulasPositionIds);
|
|
36646
|
+
cellsToCompute.addMany(this.getCellsDependingOn(arrayFormulasPositionIds));
|
|
36569
36647
|
this.evaluate(cellsToCompute);
|
|
36570
36648
|
}
|
|
36571
36649
|
getArrayFormulasImpactedByChangesOf(positionIds) {
|
|
@@ -36579,7 +36657,7 @@ class Evaluator {
|
|
|
36579
36657
|
}
|
|
36580
36658
|
if (!content) {
|
|
36581
36659
|
// The previous content could have blocked some array formulas
|
|
36582
|
-
impactedPositionIds.
|
|
36660
|
+
impactedPositionIds.addMany(this.getArrayFormulasBlockedByOrSpreadingOn(positionId));
|
|
36583
36661
|
}
|
|
36584
36662
|
}
|
|
36585
36663
|
return impactedPositionIds;
|
|
@@ -36627,7 +36705,7 @@ class Evaluator {
|
|
|
36627
36705
|
}
|
|
36628
36706
|
const arrayFormulas = this.spreadingRelations.getFormulaPositionsSpreadingOn(positionId);
|
|
36629
36707
|
const cells = new JetSet(arrayFormulas);
|
|
36630
|
-
cells.
|
|
36708
|
+
cells.addMany(this.getCellsDependingOn(arrayFormulas));
|
|
36631
36709
|
return cells;
|
|
36632
36710
|
}
|
|
36633
36711
|
nextPositionsToUpdate = new JetSet();
|
|
@@ -36778,7 +36856,7 @@ class Evaluator {
|
|
|
36778
36856
|
this.setEvaluatedCell(positionId, evaluatedCell);
|
|
36779
36857
|
// check if formula dependencies present in the spread zone
|
|
36780
36858
|
// if so, they need to be recomputed
|
|
36781
|
-
this.nextPositionsToUpdate.
|
|
36859
|
+
this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([positionId]));
|
|
36782
36860
|
};
|
|
36783
36861
|
}
|
|
36784
36862
|
invalidateSpreading(positionId) {
|
|
@@ -36793,8 +36871,8 @@ class Evaluator {
|
|
|
36793
36871
|
continue;
|
|
36794
36872
|
}
|
|
36795
36873
|
this.evaluatedCells.delete(child);
|
|
36796
|
-
this.nextPositionsToUpdate.
|
|
36797
|
-
this.nextPositionsToUpdate.
|
|
36874
|
+
this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([child]));
|
|
36875
|
+
this.nextPositionsToUpdate.addMany(this.getArrayFormulasBlockedByOrSpreadingOn(child));
|
|
36798
36876
|
}
|
|
36799
36877
|
this.spreadingRelations.removeNode(positionId);
|
|
36800
36878
|
}
|
|
@@ -37154,7 +37232,13 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
37154
37232
|
const format = newFormat
|
|
37155
37233
|
? getItemId(newFormat, data.formats)
|
|
37156
37234
|
: exportedCellData.format;
|
|
37157
|
-
|
|
37235
|
+
let content;
|
|
37236
|
+
if (formulaCell instanceof FormulaCellWithDependencies) {
|
|
37237
|
+
content = this.getters.buildFormulaContent(exportedSheetData.id, formulaCell, formulaCell.dependencies, true);
|
|
37238
|
+
}
|
|
37239
|
+
else {
|
|
37240
|
+
content = !isExported ? newContent : exportedCellData.content;
|
|
37241
|
+
}
|
|
37158
37242
|
exportedSheetData.cells[xc] = { ...exportedCellData, value, isFormula, content, format };
|
|
37159
37243
|
}
|
|
37160
37244
|
}
|
|
@@ -40977,14 +41061,12 @@ class SelectionInputsManagerPlugin extends UIPlugin {
|
|
|
40977
41061
|
break;
|
|
40978
41062
|
case "FOCUS_RANGE":
|
|
40979
41063
|
case "CHANGE_RANGE":
|
|
40980
|
-
|
|
40981
|
-
|
|
40982
|
-
|
|
40983
|
-
|
|
40984
|
-
|
|
40985
|
-
|
|
40986
|
-
this.selection.capture(input, { cell: { col: zone.left, row: zone.top }, zone }, { handleEvent: input.handleEvent.bind(input) });
|
|
40987
|
-
}
|
|
41064
|
+
const input = this.inputs[cmd.id];
|
|
41065
|
+
const range = input.ranges.find((range) => range.id === cmd.rangeId);
|
|
41066
|
+
if (range) {
|
|
41067
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
41068
|
+
const zone = this.getters.getRangeFromSheetXC(sheetId, range?.xc || "A1").zone;
|
|
41069
|
+
this.selection.capture(input, { cell: { col: zone.left, row: zone.top }, zone }, { handleEvent: input.handleEvent.bind(input) });
|
|
40988
41070
|
this.focusedInputId = cmd.id;
|
|
40989
41071
|
}
|
|
40990
41072
|
break;
|
|
@@ -43673,7 +43755,7 @@ class EditionPlugin extends UIPlugin {
|
|
|
43673
43755
|
this.replaceText(ref, this.selectionInitialStart, this.selectionEnd);
|
|
43674
43756
|
}
|
|
43675
43757
|
getZoneReference(zone) {
|
|
43676
|
-
const inputSheetId = this.getters.getCurrentEditedCell().
|
|
43758
|
+
const inputSheetId = this.getters.getCurrentEditedCell()?.sheetId || this.getters.getActiveSheetId();
|
|
43677
43759
|
const sheetId = this.getters.getActiveSheetId();
|
|
43678
43760
|
const range = this.getters.getRangeFromZone(sheetId, zone);
|
|
43679
43761
|
return this.getters.getSelectionRangeString(range, inputSheetId);
|
|
@@ -43687,7 +43769,7 @@ class EditionPlugin extends UIPlugin {
|
|
|
43687
43769
|
_fixedParts.pop();
|
|
43688
43770
|
}
|
|
43689
43771
|
const newRange = range.clone({ parts: _fixedParts });
|
|
43690
|
-
return this.getters.getSelectionRangeString(newRange, this.getters.getCurrentEditedCell().
|
|
43772
|
+
return this.getters.getSelectionRangeString(newRange, this.getters.getCurrentEditedCell()?.sheetId || this.getters.getActiveSheetId());
|
|
43691
43773
|
}
|
|
43692
43774
|
/**
|
|
43693
43775
|
* Replace the current selection by a new text.
|
|
@@ -43720,7 +43802,7 @@ class EditionPlugin extends UIPlugin {
|
|
|
43720
43802
|
if (!this.currentContent.startsWith("=") || this.mode === "inactive") {
|
|
43721
43803
|
return;
|
|
43722
43804
|
}
|
|
43723
|
-
const editionSheetId = this.getters.getCurrentEditedCell().
|
|
43805
|
+
const editionSheetId = this.getters.getCurrentEditedCell()?.sheetId || this.getters.getActiveSheetId();
|
|
43724
43806
|
const XCs = this.getReferencedRanges().map((range) => this.getters.getRangeString(range, editionSheetId));
|
|
43725
43807
|
const colorsToKeep = {};
|
|
43726
43808
|
for (const xc of XCs) {
|
|
@@ -43749,7 +43831,7 @@ class EditionPlugin extends UIPlugin {
|
|
|
43749
43831
|
if (!this.currentContent.startsWith("=") || this.mode === "inactive") {
|
|
43750
43832
|
return [];
|
|
43751
43833
|
}
|
|
43752
|
-
const editionSheetId = this.getters.getCurrentEditedCell().
|
|
43834
|
+
const editionSheetId = this.getters.getCurrentEditedCell()?.sheetId || this.getters.getActiveSheetId();
|
|
43753
43835
|
const rangeColor = (rangeString) => {
|
|
43754
43836
|
const colorIndex = this.colorIndexByRange[rangeString];
|
|
43755
43837
|
return colors$1[colorIndex % colors$1.length];
|
|
@@ -43767,7 +43849,7 @@ class EditionPlugin extends UIPlugin {
|
|
|
43767
43849
|
* Return ranges currently referenced in the composer
|
|
43768
43850
|
*/
|
|
43769
43851
|
getReferencedRanges() {
|
|
43770
|
-
const editionSheetId = this.getters.getCurrentEditedCell().
|
|
43852
|
+
const editionSheetId = this.getters.getCurrentEditedCell()?.sheetId || this.getters.getActiveSheetId();
|
|
43771
43853
|
const referenceRanges = this.currentTokens
|
|
43772
43854
|
.filter((token) => token.type === "REFERENCE")
|
|
43773
43855
|
.map((token) => this.getters.getRangeFromSheetXC(editionSheetId, token.value));
|
|
@@ -45731,6 +45813,16 @@ class ImageProvider {
|
|
|
45731
45813
|
}
|
|
45732
45814
|
}
|
|
45733
45815
|
|
|
45816
|
+
class FocusableElement {
|
|
45817
|
+
focusableElement = undefined;
|
|
45818
|
+
setFocusableElement(element) {
|
|
45819
|
+
this.focusableElement = element;
|
|
45820
|
+
}
|
|
45821
|
+
focus() {
|
|
45822
|
+
this.focusableElement?.focus();
|
|
45823
|
+
}
|
|
45824
|
+
}
|
|
45825
|
+
|
|
45734
45826
|
const RIPPLE_KEY_FRAMES = [
|
|
45735
45827
|
{ transform: "scale(0)" },
|
|
45736
45828
|
{ transform: "scale(0.8)", offset: 0.33 },
|
|
@@ -47773,6 +47865,7 @@ class Spreadsheet extends owl.Component {
|
|
|
47773
47865
|
_t: Spreadsheet._t,
|
|
47774
47866
|
clipboard: this.env.clipboard || instantiateClipboard(),
|
|
47775
47867
|
startCellEdition: (content) => this.onGridComposerCellFocused(content),
|
|
47868
|
+
focusableElement: new FocusableElement(),
|
|
47776
47869
|
});
|
|
47777
47870
|
owl.useExternalListener(window, "resize", () => this.render(true));
|
|
47778
47871
|
owl.useExternalListener(window, "beforeunload", this.unbindModelEvents.bind(this));
|
|
@@ -47879,17 +47972,18 @@ class Spreadsheet extends owl.Component {
|
|
|
47879
47972
|
this.model.dispatch("UNFOCUS_SELECTION_INPUT");
|
|
47880
47973
|
this.composer.topBarFocus = "contentFocus";
|
|
47881
47974
|
this.composer.gridFocusMode = "inactive";
|
|
47882
|
-
this.setComposerContent({ selection }
|
|
47975
|
+
this.setComposerContent({ selection });
|
|
47883
47976
|
}
|
|
47884
|
-
onGridComposerContentFocused() {
|
|
47977
|
+
onGridComposerContentFocused(selection) {
|
|
47885
47978
|
if (this.model.getters.isReadonly()) {
|
|
47886
47979
|
return;
|
|
47887
47980
|
}
|
|
47888
47981
|
this.model.dispatch("UNFOCUS_SELECTION_INPUT");
|
|
47889
47982
|
this.composer.topBarFocus = "inactive";
|
|
47890
47983
|
this.composer.gridFocusMode = "contentFocus";
|
|
47891
|
-
this.setComposerContent({});
|
|
47984
|
+
this.setComposerContent({ selection });
|
|
47892
47985
|
}
|
|
47986
|
+
// TODO: either both are defined or none of them. change those args to an object
|
|
47893
47987
|
onGridComposerCellFocused(content, selection) {
|
|
47894
47988
|
if (this.model.getters.isReadonly()) {
|
|
47895
47989
|
return;
|
|
@@ -49301,11 +49395,10 @@ class SelectionStreamProcessorImpl {
|
|
|
49301
49395
|
* next cluster if the given cell is outside a cluster or at the border of a cluster in the given direction.
|
|
49302
49396
|
*/
|
|
49303
49397
|
getEndOfCluster(startPosition, dim, dir) {
|
|
49304
|
-
const sheet = this.getters.getActiveSheet();
|
|
49305
49398
|
let currentPosition = startPosition;
|
|
49306
49399
|
// If both the current cell and the next cell are not empty, we want to go to the end of the cluster
|
|
49307
49400
|
const nextCellPosition = this.getNextCellPosition(startPosition, dim, dir);
|
|
49308
|
-
let mode = !this.
|
|
49401
|
+
let mode = !this.isEvaluatedCellEmpty(currentPosition) && !this.isEvaluatedCellEmpty(nextCellPosition)
|
|
49309
49402
|
? "endOfCluster"
|
|
49310
49403
|
: "nextCluster";
|
|
49311
49404
|
while (true) {
|
|
@@ -49315,7 +49408,7 @@ class SelectionStreamProcessorImpl {
|
|
|
49315
49408
|
currentPosition.row === nextCellPosition.row) {
|
|
49316
49409
|
break;
|
|
49317
49410
|
}
|
|
49318
|
-
const isNextCellEmpty = this.
|
|
49411
|
+
const isNextCellEmpty = this.isEvaluatedCellEmpty(nextCellPosition);
|
|
49319
49412
|
if (mode === "endOfCluster" && isNextCellEmpty) {
|
|
49320
49413
|
break;
|
|
49321
49414
|
}
|
|
@@ -49329,10 +49422,20 @@ class SelectionStreamProcessorImpl {
|
|
|
49329
49422
|
return dim === "cols" ? currentPosition.col : currentPosition.row;
|
|
49330
49423
|
}
|
|
49331
49424
|
/**
|
|
49332
|
-
*
|
|
49333
|
-
* check
|
|
49425
|
+
* Checks if a cell is empty (i.e. does not have a content). If the cell is part of a merge,
|
|
49426
|
+
* the check applies to the main cell of the merge.
|
|
49427
|
+
*/
|
|
49428
|
+
isCellEmpty({ col, row }) {
|
|
49429
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
49430
|
+
const position = this.getters.getMainCellPosition({ sheetId, col, row });
|
|
49431
|
+
return !(this.getters.getCorrespondingFormulaCell(position) || this.getters.getCell(position)?.content);
|
|
49432
|
+
}
|
|
49433
|
+
/**
|
|
49434
|
+
* Checks if a cell evaluated value is empty. If the cell is part of a merge,
|
|
49435
|
+
* the check applies to the main cell of the merge.
|
|
49334
49436
|
*/
|
|
49335
|
-
|
|
49437
|
+
isEvaluatedCellEmpty({ col, row }) {
|
|
49438
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
49336
49439
|
const position = this.getters.getMainCellPosition({ sheetId, col, row });
|
|
49337
49440
|
const cell = this.getters.getEvaluatedCell(position);
|
|
49338
49441
|
return cell.type === CellValueType.empty;
|
|
@@ -51613,6 +51716,6 @@ exports.setTranslationMethod = setTranslationMethod;
|
|
|
51613
51716
|
exports.tokenize = tokenize;
|
|
51614
51717
|
|
|
51615
51718
|
|
|
51616
|
-
__info__.version = '16.4.
|
|
51617
|
-
__info__.date = '2024-02-
|
|
51618
|
-
__info__.hash = '
|
|
51719
|
+
__info__.version = '16.4.24';
|
|
51720
|
+
__info__.date = '2024-02-28T12:27:32.683Z';
|
|
51721
|
+
__info__.hash = '90c74d1';
|