@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
|
@@ -701,18 +701,18 @@ function isConsecutive(iterable) {
|
|
|
701
701
|
return true;
|
|
702
702
|
}
|
|
703
703
|
class JetSet extends Set {
|
|
704
|
-
|
|
704
|
+
addMany(iterable) {
|
|
705
705
|
for (const element of iterable) {
|
|
706
706
|
super.add(element);
|
|
707
707
|
}
|
|
708
708
|
return this;
|
|
709
709
|
}
|
|
710
|
-
|
|
711
|
-
let
|
|
710
|
+
deleteMany(iterable) {
|
|
711
|
+
let wasDeleted = false;
|
|
712
712
|
for (const element of iterable) {
|
|
713
|
-
|
|
713
|
+
wasDeleted ||= super.delete(element);
|
|
714
714
|
}
|
|
715
|
-
return
|
|
715
|
+
return wasDeleted;
|
|
716
716
|
}
|
|
717
717
|
}
|
|
718
718
|
/**
|
|
@@ -1838,6 +1838,9 @@ function parseFormat(formatString) {
|
|
|
1838
1838
|
function formatValue(value, { format, locale }) {
|
|
1839
1839
|
switch (typeof value) {
|
|
1840
1840
|
case "string":
|
|
1841
|
+
if (value.includes('\\"')) {
|
|
1842
|
+
return value.replace(/\\"/g, '"');
|
|
1843
|
+
}
|
|
1841
1844
|
return value;
|
|
1842
1845
|
case "boolean":
|
|
1843
1846
|
return value ? "TRUE" : "FALSE";
|
|
@@ -15235,6 +15238,9 @@ function isValidLocale(locale) {
|
|
|
15235
15238
|
if (locale.formulaArgSeparator === locale.decimalSeparator) {
|
|
15236
15239
|
return false;
|
|
15237
15240
|
}
|
|
15241
|
+
if (locale.thousandsSeparator === locale.decimalSeparator) {
|
|
15242
|
+
return false;
|
|
15243
|
+
}
|
|
15238
15244
|
try {
|
|
15239
15245
|
formatValue(1, { locale, format: "#,##0.00" });
|
|
15240
15246
|
formatValue(1, { locale, format: locale.dateFormat });
|
|
@@ -15325,7 +15331,7 @@ function canonicalizeNumberLiteral(content, locale) {
|
|
|
15325
15331
|
if (locale.decimalSeparator === "." || !isNumber(content, locale)) {
|
|
15326
15332
|
return content;
|
|
15327
15333
|
}
|
|
15328
|
-
return content.replace(locale.decimalSeparator, ".");
|
|
15334
|
+
return content.replace(locale.thousandsSeparator, "").replace(locale.decimalSeparator, ".");
|
|
15329
15335
|
}
|
|
15330
15336
|
/**
|
|
15331
15337
|
* Change a content string from the given locale to its canonical form (en_US locale). Also convert date string.
|
|
@@ -18627,6 +18633,12 @@ const INSERT_LINK = (env) => {
|
|
|
18627
18633
|
let { col, row } = env.model.getters.getActivePosition();
|
|
18628
18634
|
env.model.dispatch("OPEN_CELL_POPOVER", { col, row, popoverType: "LinkEditor" });
|
|
18629
18635
|
};
|
|
18636
|
+
const INSERT_LINK_NAME = (env) => {
|
|
18637
|
+
const sheetId = env.model.getters.getActiveSheetId();
|
|
18638
|
+
const { col, row } = env.model.getters.getActivePosition();
|
|
18639
|
+
const cell = env.model.getters.getEvaluatedCell({ sheetId, col, row });
|
|
18640
|
+
return cell && cell.link ? _lt("Edit link") : _lt("Insert link");
|
|
18641
|
+
};
|
|
18630
18642
|
//------------------------------------------------------------------------------
|
|
18631
18643
|
// Filters action
|
|
18632
18644
|
//------------------------------------------------------------------------------
|
|
@@ -19167,7 +19179,7 @@ cellMenuRegistry
|
|
|
19167
19179
|
})
|
|
19168
19180
|
.add("insert_link", {
|
|
19169
19181
|
...insertLink,
|
|
19170
|
-
name:
|
|
19182
|
+
name: INSERT_LINK_NAME,
|
|
19171
19183
|
sequence: 150,
|
|
19172
19184
|
separator: true,
|
|
19173
19185
|
});
|
|
@@ -20655,7 +20667,7 @@ class SelectionInput extends Component {
|
|
|
20655
20667
|
: this.props.ranges()
|
|
20656
20668
|
? this.props.ranges().map((xc, id) => ({
|
|
20657
20669
|
xc,
|
|
20658
|
-
id,
|
|
20670
|
+
id: id + 1,
|
|
20659
20671
|
isFocused: false,
|
|
20660
20672
|
}))
|
|
20661
20673
|
: [];
|
|
@@ -24078,6 +24090,7 @@ class Composer extends Component {
|
|
|
24078
24090
|
static components = { TextValueProvider, FunctionDescriptionProvider };
|
|
24079
24091
|
static defaultProps = {
|
|
24080
24092
|
inputStyle: "",
|
|
24093
|
+
isDefaultFocus: false,
|
|
24081
24094
|
};
|
|
24082
24095
|
composerRef = useRef("o_composer");
|
|
24083
24096
|
contentHelper = new ContentEditableHelper(this.composerRef.el);
|
|
@@ -24130,7 +24143,6 @@ class Composer extends Component {
|
|
|
24130
24143
|
F2: () => console.warn("Not implemented"),
|
|
24131
24144
|
F4: this.processF4Key,
|
|
24132
24145
|
Tab: (ev) => this.processTabKey(ev),
|
|
24133
|
-
" ": (ev) => this.processSpaceKey(ev),
|
|
24134
24146
|
};
|
|
24135
24147
|
keyCodeMapping = {
|
|
24136
24148
|
NumpadDecimal: this.processNumpadDecimal,
|
|
@@ -24138,11 +24150,11 @@ class Composer extends Component {
|
|
|
24138
24150
|
setup() {
|
|
24139
24151
|
onMounted(() => {
|
|
24140
24152
|
const el = this.composerRef.el;
|
|
24153
|
+
if (this.props.isDefaultFocus) {
|
|
24154
|
+
this.env.focusableElement.setFocusableElement(el);
|
|
24155
|
+
}
|
|
24141
24156
|
this.contentHelper.updateEl(el);
|
|
24142
24157
|
});
|
|
24143
|
-
onWillUnmount(() => {
|
|
24144
|
-
this.props.onComposerUnmounted?.();
|
|
24145
|
-
});
|
|
24146
24158
|
useEffect(() => {
|
|
24147
24159
|
this.processContent();
|
|
24148
24160
|
});
|
|
@@ -24151,7 +24163,8 @@ class Composer extends Component {
|
|
|
24151
24163
|
// Handlers
|
|
24152
24164
|
// ---------------------------------------------------------------------------
|
|
24153
24165
|
processArrowKeys(ev) {
|
|
24154
|
-
if (this.env.model.getters.isSelectingForComposer()
|
|
24166
|
+
if (this.env.model.getters.isSelectingForComposer() ||
|
|
24167
|
+
this.env.model.getters.getEditionMode() === "inactive") {
|
|
24155
24168
|
this.functionDescriptionState.showDescription = false;
|
|
24156
24169
|
// Prevent the default content editable behavior which moves the cursor
|
|
24157
24170
|
ev.preventDefault();
|
|
@@ -24190,25 +24203,19 @@ class Composer extends Component {
|
|
|
24190
24203
|
processTabKey(ev) {
|
|
24191
24204
|
ev.preventDefault();
|
|
24192
24205
|
ev.stopPropagation();
|
|
24193
|
-
if (this.
|
|
24194
|
-
|
|
24195
|
-
|
|
24196
|
-
|
|
24197
|
-
|
|
24206
|
+
if (this.env.model.getters.getEditionMode() !== "inactive") {
|
|
24207
|
+
if (this.autoCompleteState.showProvider) {
|
|
24208
|
+
const autoCompleteValue = this.autoCompleteState.values[this.autoCompleteState.selectedIndex]?.text;
|
|
24209
|
+
if (autoCompleteValue) {
|
|
24210
|
+
this.autoComplete(autoCompleteValue);
|
|
24211
|
+
return;
|
|
24212
|
+
}
|
|
24198
24213
|
}
|
|
24214
|
+
this.env.model.dispatch("STOP_EDITION");
|
|
24199
24215
|
}
|
|
24200
24216
|
const direction = ev.shiftKey ? "left" : "right";
|
|
24201
|
-
this.env.model.dispatch("STOP_EDITION");
|
|
24202
24217
|
this.env.model.selection.moveAnchorCell(direction, 1);
|
|
24203
24218
|
}
|
|
24204
|
-
processSpaceKey(ev) {
|
|
24205
|
-
if (ev.ctrlKey) {
|
|
24206
|
-
ev.preventDefault();
|
|
24207
|
-
ev.stopPropagation();
|
|
24208
|
-
this.showAutocomplete("");
|
|
24209
|
-
this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
|
|
24210
|
-
}
|
|
24211
|
-
}
|
|
24212
24219
|
processEnterKey(ev) {
|
|
24213
24220
|
ev.preventDefault();
|
|
24214
24221
|
ev.stopPropagation();
|
|
@@ -24260,6 +24267,9 @@ class Composer extends Component {
|
|
|
24260
24267
|
this.compositionActive = false;
|
|
24261
24268
|
}
|
|
24262
24269
|
onKeydown(ev) {
|
|
24270
|
+
if (this.env.model.getters.getEditionMode() === "inactive") {
|
|
24271
|
+
return;
|
|
24272
|
+
}
|
|
24263
24273
|
let handler = this.keyMapping[ev.key] || this.keyCodeMapping[ev.code];
|
|
24264
24274
|
if (handler) {
|
|
24265
24275
|
handler.call(this, ev);
|
|
@@ -24268,14 +24278,33 @@ class Composer extends Component {
|
|
|
24268
24278
|
ev.stopPropagation();
|
|
24269
24279
|
}
|
|
24270
24280
|
}
|
|
24281
|
+
onPaste(ev) {
|
|
24282
|
+
if (this.env.model.getters.getEditionMode() !== "inactive") {
|
|
24283
|
+
ev.stopPropagation();
|
|
24284
|
+
}
|
|
24285
|
+
}
|
|
24271
24286
|
/*
|
|
24272
24287
|
* Triggered automatically by the content-editable between the keydown and key up
|
|
24273
24288
|
* */
|
|
24274
24289
|
onInput(ev) {
|
|
24275
|
-
if (
|
|
24290
|
+
if (!this.shouldProcessInputEvents) {
|
|
24276
24291
|
return;
|
|
24277
24292
|
}
|
|
24278
|
-
|
|
24293
|
+
if (ev.inputType === "insertFromPaste" &&
|
|
24294
|
+
this.env.model.getters.getEditionMode() === "inactive") {
|
|
24295
|
+
return;
|
|
24296
|
+
}
|
|
24297
|
+
ev.stopPropagation();
|
|
24298
|
+
let content;
|
|
24299
|
+
if (this.env.model.getters.getEditionMode() === "inactive") {
|
|
24300
|
+
content = ev.data || "";
|
|
24301
|
+
}
|
|
24302
|
+
else {
|
|
24303
|
+
content = this.contentHelper.getText();
|
|
24304
|
+
}
|
|
24305
|
+
if (this.props.focus === "inactive") {
|
|
24306
|
+
return this.props.onComposerCellFocused?.(content);
|
|
24307
|
+
}
|
|
24279
24308
|
let selection = this.contentHelper.getCurrentSelection();
|
|
24280
24309
|
if (ev.inputType === "insertParagraph") {
|
|
24281
24310
|
const start = Math.min(selection.start, selection.end);
|
|
@@ -24353,9 +24382,8 @@ class Composer extends Component {
|
|
|
24353
24382
|
}
|
|
24354
24383
|
const newSelection = this.contentHelper.getCurrentSelection();
|
|
24355
24384
|
this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
|
|
24356
|
-
|
|
24357
|
-
|
|
24358
|
-
}
|
|
24385
|
+
this.props.onComposerContentFocused();
|
|
24386
|
+
if (this.props.focus === "inactive") ;
|
|
24359
24387
|
this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", newSelection);
|
|
24360
24388
|
this.processTokenAtCursor();
|
|
24361
24389
|
}
|
|
@@ -24522,7 +24550,7 @@ class Composer extends Component {
|
|
|
24522
24550
|
const highlights = this.env.model.getters.getHighlights();
|
|
24523
24551
|
const refSheet = sheetName
|
|
24524
24552
|
? this.env.model.getters.getSheetIdByName(sheetName)
|
|
24525
|
-
: this.env.model.getters.getCurrentEditedCell()
|
|
24553
|
+
: this.env.model.getters.getCurrentEditedCell()?.sheetId;
|
|
24526
24554
|
const highlight = highlights.find((highlight) => {
|
|
24527
24555
|
if (highlight.sheetId !== refSheet)
|
|
24528
24556
|
return false;
|
|
@@ -24602,12 +24630,13 @@ class Composer extends Component {
|
|
|
24602
24630
|
}
|
|
24603
24631
|
}
|
|
24604
24632
|
Composer.props = {
|
|
24605
|
-
focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
|
|
24606
|
-
onComposerContentFocused: Function,
|
|
24607
24633
|
inputStyle: { type: String, optional: true },
|
|
24608
24634
|
rect: { type: Object, optional: true },
|
|
24609
24635
|
delimitation: { type: Object, optional: true },
|
|
24610
|
-
|
|
24636
|
+
focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
|
|
24637
|
+
onComposerCellFocused: { type: Function, optional: true },
|
|
24638
|
+
onComposerContentFocused: Function,
|
|
24639
|
+
isDefaultFocus: { type: Boolean, optional: true },
|
|
24611
24640
|
};
|
|
24612
24641
|
|
|
24613
24642
|
const COMPOSER_BORDER_WIDTH = 3 * 0.4 * window.devicePixelRatio || 1;
|
|
@@ -24641,51 +24670,26 @@ css /* scss */ `
|
|
|
24641
24670
|
class GridComposer extends Component {
|
|
24642
24671
|
static template = "o-spreadsheet-GridComposer";
|
|
24643
24672
|
static components = { Composer };
|
|
24644
|
-
|
|
24645
|
-
|
|
24646
|
-
|
|
24673
|
+
// TODORAR see if we can keep it undefined
|
|
24674
|
+
rect = this.defaultRect;
|
|
24675
|
+
isEditing = false;
|
|
24647
24676
|
isCellReferenceVisible;
|
|
24648
|
-
|
|
24677
|
+
get defaultRect() {
|
|
24678
|
+
return { x: 0, y: 0, width: 0, height: 0 };
|
|
24679
|
+
}
|
|
24649
24680
|
setup() {
|
|
24650
|
-
this.gridComposerRef = useRef("gridComposer");
|
|
24651
|
-
this.composerState = useState({
|
|
24652
|
-
rect: undefined,
|
|
24653
|
-
delimitation: undefined,
|
|
24654
|
-
});
|
|
24655
|
-
const { sheetId, col, row } = this.env.model.getters.getActivePosition();
|
|
24656
|
-
this.zone = this.env.model.getters.expandZone(sheetId, positionToZone({ col, row }));
|
|
24657
|
-
this.rect = this.env.model.getters.getVisibleRect(this.zone);
|
|
24658
|
-
this.isCellReferenceVisible = false;
|
|
24659
|
-
onMounted(() => {
|
|
24660
|
-
const el = this.gridComposerRef.el;
|
|
24661
|
-
this.composerState.rect = {
|
|
24662
|
-
x: this.rect.x,
|
|
24663
|
-
y: this.rect.y,
|
|
24664
|
-
width: el.clientWidth,
|
|
24665
|
-
height: el.clientHeight,
|
|
24666
|
-
};
|
|
24667
|
-
this.composerState.delimitation = {
|
|
24668
|
-
width: this.props.gridDims.width,
|
|
24669
|
-
height: this.props.gridDims.height,
|
|
24670
|
-
};
|
|
24671
|
-
});
|
|
24672
24681
|
onWillUpdateProps(() => {
|
|
24673
|
-
|
|
24674
|
-
|
|
24675
|
-
}
|
|
24676
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
24677
|
-
const zone = this.env.model.getters.getSelectedZone();
|
|
24678
|
-
const rect = this.env.model.getters.getVisibleRect(zone);
|
|
24679
|
-
if (!deepEquals(rect, this.rect) ||
|
|
24680
|
-
sheetId !== this.env.model.getters.getCurrentEditedCell().sheetId) {
|
|
24681
|
-
this.isCellReferenceVisible = true;
|
|
24682
|
-
}
|
|
24682
|
+
this.updateComponentPosition();
|
|
24683
|
+
this.updateCellReferenceVisibility();
|
|
24683
24684
|
});
|
|
24684
24685
|
}
|
|
24685
24686
|
get shouldDisplayCellReference() {
|
|
24686
24687
|
return this.isCellReferenceVisible;
|
|
24687
24688
|
}
|
|
24688
24689
|
get cellReference() {
|
|
24690
|
+
if (!this.env.model.getters.getCurrentEditedCell()) {
|
|
24691
|
+
return "";
|
|
24692
|
+
}
|
|
24689
24693
|
const { col, row, sheetId } = this.env.model.getters.getCurrentEditedCell();
|
|
24690
24694
|
const prefixSheet = sheetId !== this.env.model.getters.getActiveSheetId();
|
|
24691
24695
|
return `${prefixSheet ? getCanonicalSheetName(this.env.model.getters.getSheetName(sheetId)) + "!" : ""}${toXC(col, row)}`;
|
|
@@ -24697,7 +24701,27 @@ class GridComposer extends Component {
|
|
|
24697
24701
|
top: `${top - GRID_CELL_REFERENCE_TOP_OFFSET}px`,
|
|
24698
24702
|
});
|
|
24699
24703
|
}
|
|
24704
|
+
get composerProps() {
|
|
24705
|
+
const { width, height } = this.env.model.getters.getSheetViewDimensionWithHeaders();
|
|
24706
|
+
return {
|
|
24707
|
+
rect: { ...this.rect },
|
|
24708
|
+
delimitation: {
|
|
24709
|
+
width,
|
|
24710
|
+
height,
|
|
24711
|
+
},
|
|
24712
|
+
focus: this.props.focus,
|
|
24713
|
+
isDefaultFocus: true,
|
|
24714
|
+
onComposerContentFocused: this.props.onComposerContentFocused,
|
|
24715
|
+
onComposerCellFocused: this.props.onComposerCellFocused,
|
|
24716
|
+
};
|
|
24717
|
+
}
|
|
24700
24718
|
get containerStyle() {
|
|
24719
|
+
if (this.env.model.getters.getEditionMode() === "inactive" || !this.rect) {
|
|
24720
|
+
return `
|
|
24721
|
+
position: absolute;
|
|
24722
|
+
z-index: -1000;
|
|
24723
|
+
`;
|
|
24724
|
+
}
|
|
24701
24725
|
const isFormula = this.env.model.getters.getCurrentContent().startsWith("=");
|
|
24702
24726
|
const cell = this.env.model.getters.getActiveCell();
|
|
24703
24727
|
const position = this.env.model.getters.getActivePosition();
|
|
@@ -24717,6 +24741,8 @@ class GridComposer extends Component {
|
|
|
24717
24741
|
if (!isFormula) {
|
|
24718
24742
|
textAlign = style.align || cell.defaultAlign;
|
|
24719
24743
|
}
|
|
24744
|
+
const maxHeight = this.props.gridDims.height - this.rect.y;
|
|
24745
|
+
const maxWidth = this.props.gridDims.width - this.rect.x;
|
|
24720
24746
|
/**
|
|
24721
24747
|
* min-size is on the container, not the composer element, because we want to have the same size as the cell by default,
|
|
24722
24748
|
* including all the paddings/margins of the composer
|
|
@@ -24728,6 +24754,8 @@ class GridComposer extends Component {
|
|
|
24728
24754
|
top: `${top}px`,
|
|
24729
24755
|
"min-width": `${width + 1}px`,
|
|
24730
24756
|
"min-height": `${height + 1}px`,
|
|
24757
|
+
"max-width": `${maxWidth}px`,
|
|
24758
|
+
"max-height": `${maxHeight}px`,
|
|
24731
24759
|
background,
|
|
24732
24760
|
color,
|
|
24733
24761
|
"font-size": `${fontSizeInPixels(fontSize)}px`,
|
|
@@ -24737,20 +24765,38 @@ class GridComposer extends Component {
|
|
|
24737
24765
|
"text-align": textAlign,
|
|
24738
24766
|
});
|
|
24739
24767
|
}
|
|
24740
|
-
|
|
24741
|
-
const
|
|
24742
|
-
|
|
24743
|
-
|
|
24744
|
-
|
|
24745
|
-
|
|
24746
|
-
|
|
24768
|
+
updateComponentPosition() {
|
|
24769
|
+
const isEditing = this.env.model.getters.getEditionMode() !== "inactive";
|
|
24770
|
+
if (this.isEditing !== isEditing) {
|
|
24771
|
+
this.isEditing = isEditing;
|
|
24772
|
+
if (!isEditing) {
|
|
24773
|
+
this.rect = this.defaultRect;
|
|
24774
|
+
this.env.focusableElement.focus();
|
|
24775
|
+
return;
|
|
24776
|
+
}
|
|
24777
|
+
const position = this.env.model.getters.getActivePosition();
|
|
24778
|
+
const zone = this.env.model.getters.expandZone(position.sheetId, positionToZone(position));
|
|
24779
|
+
this.rect = this.env.model.getters.getVisibleRect(zone);
|
|
24780
|
+
}
|
|
24781
|
+
}
|
|
24782
|
+
updateCellReferenceVisibility() {
|
|
24783
|
+
if (this.isCellReferenceVisible || this.env.model.getters.getEditionMode() === "inactive") {
|
|
24784
|
+
return;
|
|
24785
|
+
}
|
|
24786
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
24787
|
+
const zone = this.env.model.getters.getSelectedZone();
|
|
24788
|
+
const rect = this.env.model.getters.getVisibleRect(zone);
|
|
24789
|
+
if (!deepEquals(rect, this.rect) ||
|
|
24790
|
+
sheetId !== this.env.model.getters.getCurrentEditedCell().sheetId) {
|
|
24791
|
+
this.isCellReferenceVisible = true;
|
|
24792
|
+
}
|
|
24747
24793
|
}
|
|
24748
24794
|
}
|
|
24749
24795
|
GridComposer.props = {
|
|
24750
24796
|
focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
|
|
24751
|
-
onComposerUnmounted: Function,
|
|
24752
24797
|
onComposerContentFocused: Function,
|
|
24753
24798
|
gridDims: Object,
|
|
24799
|
+
onComposerCellFocused: Function,
|
|
24754
24800
|
};
|
|
24755
24801
|
|
|
24756
24802
|
const CSS$1 = css /* scss */ `
|
|
@@ -25631,7 +25677,6 @@ class GridOverlay extends Component {
|
|
|
25631
25677
|
this.props.onCellDoubleClicked(col, row);
|
|
25632
25678
|
}
|
|
25633
25679
|
onContextMenu(ev) {
|
|
25634
|
-
ev.preventDefault();
|
|
25635
25680
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
25636
25681
|
this.props.onCellRightClicked(col, row, { x: ev.clientX, y: ev.clientY });
|
|
25637
25682
|
}
|
|
@@ -26724,7 +26769,6 @@ class Grid extends Component {
|
|
|
26724
26769
|
HEADER_WIDTH = HEADER_WIDTH;
|
|
26725
26770
|
menuState;
|
|
26726
26771
|
gridRef;
|
|
26727
|
-
hiddenInput;
|
|
26728
26772
|
onMouseWheel;
|
|
26729
26773
|
canvasPosition;
|
|
26730
26774
|
hoveredCell;
|
|
@@ -26735,17 +26779,16 @@ class Grid extends Component {
|
|
|
26735
26779
|
menuItems: [],
|
|
26736
26780
|
});
|
|
26737
26781
|
this.gridRef = useRef("grid");
|
|
26738
|
-
this.hiddenInput = useRef("hiddenInput");
|
|
26739
26782
|
this.canvasPosition = useAbsoluteBoundingRect(this.gridRef);
|
|
26740
26783
|
this.hoveredCell = useState({ col: undefined, row: undefined });
|
|
26741
26784
|
useChildSubEnv({ getPopoverContainerRect: () => this.getGridRect() });
|
|
26742
26785
|
useExternalListener(document.body, "cut", this.copy.bind(this, true));
|
|
26743
26786
|
useExternalListener(document.body, "copy", this.copy.bind(this, false));
|
|
26744
26787
|
useExternalListener(document.body, "paste", this.paste);
|
|
26745
|
-
onMounted(() => this.
|
|
26746
|
-
this.props.exposeFocus(() => this.
|
|
26788
|
+
onMounted(() => this.focusDefaultElement());
|
|
26789
|
+
this.props.exposeFocus(() => this.focusDefaultElement());
|
|
26747
26790
|
useGridDrawing("canvas", this.env.model, () => this.env.model.getters.getSheetViewDimensionWithHeaders());
|
|
26748
|
-
useEffect(() => this.
|
|
26791
|
+
useEffect(() => this.focusDefaultElement(), () => [this.env.model.getters.getActiveSheetId()]);
|
|
26749
26792
|
this.onMouseWheel = useWheelHandler((deltaX, deltaY) => {
|
|
26750
26793
|
this.moveCanvas(deltaX, deltaY);
|
|
26751
26794
|
this.hoveredCell.col = undefined;
|
|
@@ -26768,7 +26811,7 @@ class Grid extends Component {
|
|
|
26768
26811
|
if (this.env.model.getters.hasOpenedPopover()) {
|
|
26769
26812
|
this.closeOpenedPopover();
|
|
26770
26813
|
}
|
|
26771
|
-
this.
|
|
26814
|
+
this.focusDefaultElement();
|
|
26772
26815
|
}
|
|
26773
26816
|
// this map will handle most of the actions that should happen on key down. The arrow keys are managed in the key
|
|
26774
26817
|
// down itself
|
|
@@ -26941,10 +26984,10 @@ class Grid extends Component {
|
|
|
26941
26984
|
PAGEUP: () => this.env.model.dispatch("SHIFT_VIEWPORT_UP"),
|
|
26942
26985
|
"CTRL+K": () => INSERT_LINK(this.env),
|
|
26943
26986
|
};
|
|
26944
|
-
|
|
26987
|
+
focusDefaultElement() {
|
|
26945
26988
|
if (!this.env.model.getters.getSelectedFigureId() &&
|
|
26946
26989
|
this.env.model.getters.getEditionMode() === "inactive") {
|
|
26947
|
-
this.
|
|
26990
|
+
this.env.focusableElement.focus();
|
|
26948
26991
|
}
|
|
26949
26992
|
}
|
|
26950
26993
|
get gridEl() {
|
|
@@ -27088,19 +27131,6 @@ class Grid extends Component {
|
|
|
27088
27131
|
return;
|
|
27089
27132
|
}
|
|
27090
27133
|
}
|
|
27091
|
-
onInput(ev) {
|
|
27092
|
-
// the user meant to paste in the sheet, not open the composer with the pasted content
|
|
27093
|
-
if (!ev.isComposing && ev.inputType === "insertFromPaste") {
|
|
27094
|
-
return;
|
|
27095
|
-
}
|
|
27096
|
-
if (ev.data) {
|
|
27097
|
-
// if the user types a character on the grid, it means he wants to start composing the selected cell with that
|
|
27098
|
-
// character
|
|
27099
|
-
ev.preventDefault();
|
|
27100
|
-
ev.stopPropagation();
|
|
27101
|
-
this.props.onGridComposerCellFocused(ev.data);
|
|
27102
|
-
}
|
|
27103
|
-
}
|
|
27104
27134
|
// ---------------------------------------------------------------------------
|
|
27105
27135
|
// Context Menu
|
|
27106
27136
|
// ---------------------------------------------------------------------------
|
|
@@ -27213,7 +27243,7 @@ class Grid extends Component {
|
|
|
27213
27243
|
}
|
|
27214
27244
|
closeMenu() {
|
|
27215
27245
|
this.menuState.isOpen = false;
|
|
27216
|
-
this.
|
|
27246
|
+
this.focusDefaultElement();
|
|
27217
27247
|
}
|
|
27218
27248
|
}
|
|
27219
27249
|
Grid.props = {
|
|
@@ -30874,8 +30904,16 @@ const MIGRATIONS = [
|
|
|
30874
30904
|
},
|
|
30875
30905
|
},
|
|
30876
30906
|
{
|
|
30877
|
-
description: "
|
|
30907
|
+
description: "Fix datafilter duplication",
|
|
30878
30908
|
from: 12,
|
|
30909
|
+
to: 12.5,
|
|
30910
|
+
applyMigration(data) {
|
|
30911
|
+
return fixOverlappingFilters(data);
|
|
30912
|
+
},
|
|
30913
|
+
},
|
|
30914
|
+
{
|
|
30915
|
+
description: "Change Border description structure",
|
|
30916
|
+
from: 12.5,
|
|
30879
30917
|
to: 13,
|
|
30880
30918
|
applyMigration(data) {
|
|
30881
30919
|
for (const borderId in data.borders) {
|
|
@@ -30906,6 +30944,14 @@ const MIGRATIONS = [
|
|
|
30906
30944
|
return data;
|
|
30907
30945
|
},
|
|
30908
30946
|
},
|
|
30947
|
+
{
|
|
30948
|
+
description: "Fix datafilter duplication (post saas-16.4)",
|
|
30949
|
+
from: 14,
|
|
30950
|
+
to: 14.5,
|
|
30951
|
+
applyMigration(data) {
|
|
30952
|
+
return fixOverlappingFilters(data);
|
|
30953
|
+
},
|
|
30954
|
+
},
|
|
30909
30955
|
];
|
|
30910
30956
|
/**
|
|
30911
30957
|
* This function is used to repair faulty data independently of the migration.
|
|
@@ -31063,6 +31109,26 @@ function fixChartDefinitions(data, initialMessages) {
|
|
|
31063
31109
|
}
|
|
31064
31110
|
return messages;
|
|
31065
31111
|
}
|
|
31112
|
+
function fixOverlappingFilters(data) {
|
|
31113
|
+
for (let sheet of data.sheets || []) {
|
|
31114
|
+
let knownDataFilterZones = [];
|
|
31115
|
+
for (let filterTable of sheet.filterTables || []) {
|
|
31116
|
+
const zone = toZone(filterTable.range);
|
|
31117
|
+
// See commit message of https://github.com/odoo/o-spreadsheet/pull/3632 of more details
|
|
31118
|
+
const intersectZoneIndex = knownDataFilterZones.findIndex((knownZone) => overlap(knownZone, zone));
|
|
31119
|
+
if (intersectZoneIndex !== -1) {
|
|
31120
|
+
knownDataFilterZones[intersectZoneIndex] = zone;
|
|
31121
|
+
}
|
|
31122
|
+
else {
|
|
31123
|
+
knownDataFilterZones.push(zone);
|
|
31124
|
+
}
|
|
31125
|
+
}
|
|
31126
|
+
sheet.filterTables = knownDataFilterZones.map((zone) => ({
|
|
31127
|
+
range: zoneToXc(zone),
|
|
31128
|
+
}));
|
|
31129
|
+
}
|
|
31130
|
+
return data;
|
|
31131
|
+
}
|
|
31066
31132
|
// -----------------------------------------------------------------------------
|
|
31067
31133
|
// Helpers
|
|
31068
31134
|
// -----------------------------------------------------------------------------
|
|
@@ -31792,9 +31858,9 @@ class CellPlugin extends CorePlugin {
|
|
|
31792
31858
|
allowDispatch(cmd) {
|
|
31793
31859
|
switch (cmd.type) {
|
|
31794
31860
|
case "UPDATE_CELL":
|
|
31795
|
-
return this.
|
|
31861
|
+
return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessUpdateCell);
|
|
31796
31862
|
case "CLEAR_CELL":
|
|
31797
|
-
return this.checkValidations(cmd, this.
|
|
31863
|
+
return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessClearCell);
|
|
31798
31864
|
default:
|
|
31799
31865
|
return 0 /* CommandResult.Success */;
|
|
31800
31866
|
}
|
|
@@ -31926,10 +31992,6 @@ class CellPlugin extends CorePlugin {
|
|
|
31926
31992
|
format: cell.format ? getItemId(cell.format, formats) : undefined,
|
|
31927
31993
|
content: cell.content || undefined,
|
|
31928
31994
|
};
|
|
31929
|
-
// if there is a formula but no dependencies (maybe because the cell is in error), no need to recompute the formula text
|
|
31930
|
-
if (cell.isFormula && cell.dependencies.length) {
|
|
31931
|
-
cells[xc].content = this.buildFormulaContent(_sheet.id, cell, cell.dependencies, true);
|
|
31932
|
-
}
|
|
31933
31995
|
}
|
|
31934
31996
|
_sheet.cells = cells;
|
|
31935
31997
|
}
|
|
@@ -32092,10 +32154,7 @@ class CellPlugin extends CorePlugin {
|
|
|
32092
32154
|
else {
|
|
32093
32155
|
style = before ? before.style : undefined;
|
|
32094
32156
|
}
|
|
32095
|
-
const
|
|
32096
|
-
let format = ("format" in after ? after.format : before && before.format) ||
|
|
32097
|
-
detectDateFormat(afterContent, locale) ||
|
|
32098
|
-
detectNumberFormat(afterContent);
|
|
32157
|
+
const format = "format" in after ? after.format : before && before.format;
|
|
32099
32158
|
/* Read the following IF as:
|
|
32100
32159
|
* we need to remove the cell if it is completely empty, but we can know if it completely empty if:
|
|
32101
32160
|
* - the command says the new content is empty and has no border/format/style
|
|
@@ -32136,12 +32195,11 @@ class CellPlugin extends CorePlugin {
|
|
|
32136
32195
|
}
|
|
32137
32196
|
createLiteralCell(id, content, format, style) {
|
|
32138
32197
|
const locale = this.getters.getLocale();
|
|
32139
|
-
content = parseLiteral(content, locale).toString();
|
|
32140
32198
|
return {
|
|
32141
32199
|
id,
|
|
32142
|
-
content,
|
|
32200
|
+
content: parseLiteral(content, locale).toString(),
|
|
32143
32201
|
style,
|
|
32144
|
-
format,
|
|
32202
|
+
format: format || detectDateFormat(content, locale) || detectNumberFormat(content),
|
|
32145
32203
|
isFormula: false,
|
|
32146
32204
|
};
|
|
32147
32205
|
}
|
|
@@ -32202,6 +32260,18 @@ class CellPlugin extends CorePlugin {
|
|
|
32202
32260
|
}
|
|
32203
32261
|
return 0 /* CommandResult.Success */;
|
|
32204
32262
|
}
|
|
32263
|
+
checkUselessUpdateCell(cmd) {
|
|
32264
|
+
const cell = this.getters.getCell(cmd);
|
|
32265
|
+
const hasContent = "content" in cmd || "formula" in cmd;
|
|
32266
|
+
const hasStyle = "style" in cmd;
|
|
32267
|
+
const hasFormat = "format" in cmd;
|
|
32268
|
+
if ((!hasContent || cell?.content === cmd.content) &&
|
|
32269
|
+
(!hasStyle || deepEquals(cell?.style, cmd.style)) &&
|
|
32270
|
+
(!hasFormat || cell?.format === cmd.format)) {
|
|
32271
|
+
return 98 /* CommandResult.NoChanges */;
|
|
32272
|
+
}
|
|
32273
|
+
return 0 /* CommandResult.Success */;
|
|
32274
|
+
}
|
|
32205
32275
|
}
|
|
32206
32276
|
class FormulaCellWithDependencies {
|
|
32207
32277
|
id;
|
|
@@ -36342,7 +36412,15 @@ class SpreadsheetRTree {
|
|
|
36342
36412
|
if (!this.rTrees[sheetId]) {
|
|
36343
36413
|
return;
|
|
36344
36414
|
}
|
|
36345
|
-
this.rTrees[sheetId].remove(item,
|
|
36415
|
+
this.rTrees[sheetId].remove(item, this.rtreeItemComparer);
|
|
36416
|
+
}
|
|
36417
|
+
rtreeItemComparer(left, right) {
|
|
36418
|
+
return (left.data == right.data &&
|
|
36419
|
+
left.boundingBox.sheetId === right.boundingBox.sheetId &&
|
|
36420
|
+
left.boundingBox?.zone.left === right.boundingBox.zone.left &&
|
|
36421
|
+
left.boundingBox?.zone.top === right.boundingBox.zone.top &&
|
|
36422
|
+
left.boundingBox?.zone.right === right.boundingBox.zone.right &&
|
|
36423
|
+
left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom);
|
|
36346
36424
|
}
|
|
36347
36425
|
}
|
|
36348
36426
|
/**
|
|
@@ -36420,7 +36498,7 @@ class FormulaDependencyGraph {
|
|
|
36420
36498
|
const queue = Array.from(ranges).reverse();
|
|
36421
36499
|
while (queue.length > 0) {
|
|
36422
36500
|
const range = queue.pop();
|
|
36423
|
-
visited.
|
|
36501
|
+
visited.addMany(this.encoder.encodeBoundingBox(range));
|
|
36424
36502
|
const impactedPositionIds = this.rTree.search(range).map((dep) => dep.data);
|
|
36425
36503
|
for (const positionId of impactedPositionIds) {
|
|
36426
36504
|
if (!visited.has(positionId)) {
|
|
@@ -36428,7 +36506,7 @@ class FormulaDependencyGraph {
|
|
|
36428
36506
|
}
|
|
36429
36507
|
}
|
|
36430
36508
|
}
|
|
36431
|
-
visited.
|
|
36509
|
+
visited.deleteMany(ranges.flatMap((r) => this.encoder.encodeBoundingBox(r)));
|
|
36432
36510
|
return visited;
|
|
36433
36511
|
}
|
|
36434
36512
|
}
|
|
@@ -36559,9 +36637,9 @@ class Evaluator {
|
|
|
36559
36637
|
const cells = positions.map((p) => this.encoder.encode(p));
|
|
36560
36638
|
const cellsToCompute = new JetSet(cells);
|
|
36561
36639
|
const arrayFormulasPositionIds = this.getArrayFormulasImpactedByChangesOf(cells);
|
|
36562
|
-
cellsToCompute.
|
|
36563
|
-
cellsToCompute.
|
|
36564
|
-
cellsToCompute.
|
|
36640
|
+
cellsToCompute.addMany(this.getCellsDependingOn(cells));
|
|
36641
|
+
cellsToCompute.addMany(arrayFormulasPositionIds);
|
|
36642
|
+
cellsToCompute.addMany(this.getCellsDependingOn(arrayFormulasPositionIds));
|
|
36565
36643
|
this.evaluate(cellsToCompute);
|
|
36566
36644
|
}
|
|
36567
36645
|
getArrayFormulasImpactedByChangesOf(positionIds) {
|
|
@@ -36575,7 +36653,7 @@ class Evaluator {
|
|
|
36575
36653
|
}
|
|
36576
36654
|
if (!content) {
|
|
36577
36655
|
// The previous content could have blocked some array formulas
|
|
36578
|
-
impactedPositionIds.
|
|
36656
|
+
impactedPositionIds.addMany(this.getArrayFormulasBlockedByOrSpreadingOn(positionId));
|
|
36579
36657
|
}
|
|
36580
36658
|
}
|
|
36581
36659
|
return impactedPositionIds;
|
|
@@ -36623,7 +36701,7 @@ class Evaluator {
|
|
|
36623
36701
|
}
|
|
36624
36702
|
const arrayFormulas = this.spreadingRelations.getFormulaPositionsSpreadingOn(positionId);
|
|
36625
36703
|
const cells = new JetSet(arrayFormulas);
|
|
36626
|
-
cells.
|
|
36704
|
+
cells.addMany(this.getCellsDependingOn(arrayFormulas));
|
|
36627
36705
|
return cells;
|
|
36628
36706
|
}
|
|
36629
36707
|
nextPositionsToUpdate = new JetSet();
|
|
@@ -36774,7 +36852,7 @@ class Evaluator {
|
|
|
36774
36852
|
this.setEvaluatedCell(positionId, evaluatedCell);
|
|
36775
36853
|
// check if formula dependencies present in the spread zone
|
|
36776
36854
|
// if so, they need to be recomputed
|
|
36777
|
-
this.nextPositionsToUpdate.
|
|
36855
|
+
this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([positionId]));
|
|
36778
36856
|
};
|
|
36779
36857
|
}
|
|
36780
36858
|
invalidateSpreading(positionId) {
|
|
@@ -36789,8 +36867,8 @@ class Evaluator {
|
|
|
36789
36867
|
continue;
|
|
36790
36868
|
}
|
|
36791
36869
|
this.evaluatedCells.delete(child);
|
|
36792
|
-
this.nextPositionsToUpdate.
|
|
36793
|
-
this.nextPositionsToUpdate.
|
|
36870
|
+
this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([child]));
|
|
36871
|
+
this.nextPositionsToUpdate.addMany(this.getArrayFormulasBlockedByOrSpreadingOn(child));
|
|
36794
36872
|
}
|
|
36795
36873
|
this.spreadingRelations.removeNode(positionId);
|
|
36796
36874
|
}
|
|
@@ -37150,7 +37228,13 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
37150
37228
|
const format = newFormat
|
|
37151
37229
|
? getItemId(newFormat, data.formats)
|
|
37152
37230
|
: exportedCellData.format;
|
|
37153
|
-
|
|
37231
|
+
let content;
|
|
37232
|
+
if (formulaCell instanceof FormulaCellWithDependencies) {
|
|
37233
|
+
content = this.getters.buildFormulaContent(exportedSheetData.id, formulaCell, formulaCell.dependencies, true);
|
|
37234
|
+
}
|
|
37235
|
+
else {
|
|
37236
|
+
content = !isExported ? newContent : exportedCellData.content;
|
|
37237
|
+
}
|
|
37154
37238
|
exportedSheetData.cells[xc] = { ...exportedCellData, value, isFormula, content, format };
|
|
37155
37239
|
}
|
|
37156
37240
|
}
|
|
@@ -40973,14 +41057,12 @@ class SelectionInputsManagerPlugin extends UIPlugin {
|
|
|
40973
41057
|
break;
|
|
40974
41058
|
case "FOCUS_RANGE":
|
|
40975
41059
|
case "CHANGE_RANGE":
|
|
40976
|
-
|
|
40977
|
-
|
|
40978
|
-
|
|
40979
|
-
|
|
40980
|
-
|
|
40981
|
-
|
|
40982
|
-
this.selection.capture(input, { cell: { col: zone.left, row: zone.top }, zone }, { handleEvent: input.handleEvent.bind(input) });
|
|
40983
|
-
}
|
|
41060
|
+
const input = this.inputs[cmd.id];
|
|
41061
|
+
const range = input.ranges.find((range) => range.id === cmd.rangeId);
|
|
41062
|
+
if (range) {
|
|
41063
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
41064
|
+
const zone = this.getters.getRangeFromSheetXC(sheetId, range?.xc || "A1").zone;
|
|
41065
|
+
this.selection.capture(input, { cell: { col: zone.left, row: zone.top }, zone }, { handleEvent: input.handleEvent.bind(input) });
|
|
40984
41066
|
this.focusedInputId = cmd.id;
|
|
40985
41067
|
}
|
|
40986
41068
|
break;
|
|
@@ -43669,7 +43751,7 @@ class EditionPlugin extends UIPlugin {
|
|
|
43669
43751
|
this.replaceText(ref, this.selectionInitialStart, this.selectionEnd);
|
|
43670
43752
|
}
|
|
43671
43753
|
getZoneReference(zone) {
|
|
43672
|
-
const inputSheetId = this.getters.getCurrentEditedCell().
|
|
43754
|
+
const inputSheetId = this.getters.getCurrentEditedCell()?.sheetId || this.getters.getActiveSheetId();
|
|
43673
43755
|
const sheetId = this.getters.getActiveSheetId();
|
|
43674
43756
|
const range = this.getters.getRangeFromZone(sheetId, zone);
|
|
43675
43757
|
return this.getters.getSelectionRangeString(range, inputSheetId);
|
|
@@ -43683,7 +43765,7 @@ class EditionPlugin extends UIPlugin {
|
|
|
43683
43765
|
_fixedParts.pop();
|
|
43684
43766
|
}
|
|
43685
43767
|
const newRange = range.clone({ parts: _fixedParts });
|
|
43686
|
-
return this.getters.getSelectionRangeString(newRange, this.getters.getCurrentEditedCell().
|
|
43768
|
+
return this.getters.getSelectionRangeString(newRange, this.getters.getCurrentEditedCell()?.sheetId || this.getters.getActiveSheetId());
|
|
43687
43769
|
}
|
|
43688
43770
|
/**
|
|
43689
43771
|
* Replace the current selection by a new text.
|
|
@@ -43716,7 +43798,7 @@ class EditionPlugin extends UIPlugin {
|
|
|
43716
43798
|
if (!this.currentContent.startsWith("=") || this.mode === "inactive") {
|
|
43717
43799
|
return;
|
|
43718
43800
|
}
|
|
43719
|
-
const editionSheetId = this.getters.getCurrentEditedCell().
|
|
43801
|
+
const editionSheetId = this.getters.getCurrentEditedCell()?.sheetId || this.getters.getActiveSheetId();
|
|
43720
43802
|
const XCs = this.getReferencedRanges().map((range) => this.getters.getRangeString(range, editionSheetId));
|
|
43721
43803
|
const colorsToKeep = {};
|
|
43722
43804
|
for (const xc of XCs) {
|
|
@@ -43745,7 +43827,7 @@ class EditionPlugin extends UIPlugin {
|
|
|
43745
43827
|
if (!this.currentContent.startsWith("=") || this.mode === "inactive") {
|
|
43746
43828
|
return [];
|
|
43747
43829
|
}
|
|
43748
|
-
const editionSheetId = this.getters.getCurrentEditedCell().
|
|
43830
|
+
const editionSheetId = this.getters.getCurrentEditedCell()?.sheetId || this.getters.getActiveSheetId();
|
|
43749
43831
|
const rangeColor = (rangeString) => {
|
|
43750
43832
|
const colorIndex = this.colorIndexByRange[rangeString];
|
|
43751
43833
|
return colors$1[colorIndex % colors$1.length];
|
|
@@ -43763,7 +43845,7 @@ class EditionPlugin extends UIPlugin {
|
|
|
43763
43845
|
* Return ranges currently referenced in the composer
|
|
43764
43846
|
*/
|
|
43765
43847
|
getReferencedRanges() {
|
|
43766
|
-
const editionSheetId = this.getters.getCurrentEditedCell().
|
|
43848
|
+
const editionSheetId = this.getters.getCurrentEditedCell()?.sheetId || this.getters.getActiveSheetId();
|
|
43767
43849
|
const referenceRanges = this.currentTokens
|
|
43768
43850
|
.filter((token) => token.type === "REFERENCE")
|
|
43769
43851
|
.map((token) => this.getters.getRangeFromSheetXC(editionSheetId, token.value));
|
|
@@ -45727,6 +45809,16 @@ class ImageProvider {
|
|
|
45727
45809
|
}
|
|
45728
45810
|
}
|
|
45729
45811
|
|
|
45812
|
+
class FocusableElement {
|
|
45813
|
+
focusableElement = undefined;
|
|
45814
|
+
setFocusableElement(element) {
|
|
45815
|
+
this.focusableElement = element;
|
|
45816
|
+
}
|
|
45817
|
+
focus() {
|
|
45818
|
+
this.focusableElement?.focus();
|
|
45819
|
+
}
|
|
45820
|
+
}
|
|
45821
|
+
|
|
45730
45822
|
const RIPPLE_KEY_FRAMES = [
|
|
45731
45823
|
{ transform: "scale(0)" },
|
|
45732
45824
|
{ transform: "scale(0.8)", offset: 0.33 },
|
|
@@ -47769,6 +47861,7 @@ class Spreadsheet extends Component {
|
|
|
47769
47861
|
_t: Spreadsheet._t,
|
|
47770
47862
|
clipboard: this.env.clipboard || instantiateClipboard(),
|
|
47771
47863
|
startCellEdition: (content) => this.onGridComposerCellFocused(content),
|
|
47864
|
+
focusableElement: new FocusableElement(),
|
|
47772
47865
|
});
|
|
47773
47866
|
useExternalListener(window, "resize", () => this.render(true));
|
|
47774
47867
|
useExternalListener(window, "beforeunload", this.unbindModelEvents.bind(this));
|
|
@@ -47875,17 +47968,18 @@ class Spreadsheet extends Component {
|
|
|
47875
47968
|
this.model.dispatch("UNFOCUS_SELECTION_INPUT");
|
|
47876
47969
|
this.composer.topBarFocus = "contentFocus";
|
|
47877
47970
|
this.composer.gridFocusMode = "inactive";
|
|
47878
|
-
this.setComposerContent({ selection }
|
|
47971
|
+
this.setComposerContent({ selection });
|
|
47879
47972
|
}
|
|
47880
|
-
onGridComposerContentFocused() {
|
|
47973
|
+
onGridComposerContentFocused(selection) {
|
|
47881
47974
|
if (this.model.getters.isReadonly()) {
|
|
47882
47975
|
return;
|
|
47883
47976
|
}
|
|
47884
47977
|
this.model.dispatch("UNFOCUS_SELECTION_INPUT");
|
|
47885
47978
|
this.composer.topBarFocus = "inactive";
|
|
47886
47979
|
this.composer.gridFocusMode = "contentFocus";
|
|
47887
|
-
this.setComposerContent({});
|
|
47980
|
+
this.setComposerContent({ selection });
|
|
47888
47981
|
}
|
|
47982
|
+
// TODO: either both are defined or none of them. change those args to an object
|
|
47889
47983
|
onGridComposerCellFocused(content, selection) {
|
|
47890
47984
|
if (this.model.getters.isReadonly()) {
|
|
47891
47985
|
return;
|
|
@@ -49297,11 +49391,10 @@ class SelectionStreamProcessorImpl {
|
|
|
49297
49391
|
* next cluster if the given cell is outside a cluster or at the border of a cluster in the given direction.
|
|
49298
49392
|
*/
|
|
49299
49393
|
getEndOfCluster(startPosition, dim, dir) {
|
|
49300
|
-
const sheet = this.getters.getActiveSheet();
|
|
49301
49394
|
let currentPosition = startPosition;
|
|
49302
49395
|
// If both the current cell and the next cell are not empty, we want to go to the end of the cluster
|
|
49303
49396
|
const nextCellPosition = this.getNextCellPosition(startPosition, dim, dir);
|
|
49304
|
-
let mode = !this.
|
|
49397
|
+
let mode = !this.isEvaluatedCellEmpty(currentPosition) && !this.isEvaluatedCellEmpty(nextCellPosition)
|
|
49305
49398
|
? "endOfCluster"
|
|
49306
49399
|
: "nextCluster";
|
|
49307
49400
|
while (true) {
|
|
@@ -49311,7 +49404,7 @@ class SelectionStreamProcessorImpl {
|
|
|
49311
49404
|
currentPosition.row === nextCellPosition.row) {
|
|
49312
49405
|
break;
|
|
49313
49406
|
}
|
|
49314
|
-
const isNextCellEmpty = this.
|
|
49407
|
+
const isNextCellEmpty = this.isEvaluatedCellEmpty(nextCellPosition);
|
|
49315
49408
|
if (mode === "endOfCluster" && isNextCellEmpty) {
|
|
49316
49409
|
break;
|
|
49317
49410
|
}
|
|
@@ -49325,10 +49418,20 @@ class SelectionStreamProcessorImpl {
|
|
|
49325
49418
|
return dim === "cols" ? currentPosition.col : currentPosition.row;
|
|
49326
49419
|
}
|
|
49327
49420
|
/**
|
|
49328
|
-
*
|
|
49329
|
-
* check
|
|
49421
|
+
* Checks if a cell is empty (i.e. does not have a content). If the cell is part of a merge,
|
|
49422
|
+
* the check applies to the main cell of the merge.
|
|
49423
|
+
*/
|
|
49424
|
+
isCellEmpty({ col, row }) {
|
|
49425
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
49426
|
+
const position = this.getters.getMainCellPosition({ sheetId, col, row });
|
|
49427
|
+
return !(this.getters.getCorrespondingFormulaCell(position) || this.getters.getCell(position)?.content);
|
|
49428
|
+
}
|
|
49429
|
+
/**
|
|
49430
|
+
* Checks if a cell evaluated value is empty. If the cell is part of a merge,
|
|
49431
|
+
* the check applies to the main cell of the merge.
|
|
49330
49432
|
*/
|
|
49331
|
-
|
|
49433
|
+
isEvaluatedCellEmpty({ col, row }) {
|
|
49434
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
49332
49435
|
const position = this.getters.getMainCellPosition({ sheetId, col, row });
|
|
49333
49436
|
const cell = this.getters.getEvaluatedCell(position);
|
|
49334
49437
|
return cell.type === CellValueType.empty;
|
|
@@ -51577,6 +51680,6 @@ const constants = {
|
|
|
51577
51680
|
export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
|
|
51578
51681
|
|
|
51579
51682
|
|
|
51580
|
-
__info__.version = '16.4.
|
|
51581
|
-
__info__.date = '2024-02-
|
|
51582
|
-
__info__.hash = '
|
|
51683
|
+
__info__.version = '16.4.24';
|
|
51684
|
+
__info__.date = '2024-02-28T12:27:32.683Z';
|
|
51685
|
+
__info__.hash = '90c74d1';
|