@odoo/o-spreadsheet 17.0.10 → 17.0.12
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 +304 -187
- package/dist/o-spreadsheet.d.ts +31 -15
- package/dist/o-spreadsheet.esm.js +304 -187
- package/dist/o-spreadsheet.iife.js +304 -187
- package/dist/o-spreadsheet.iife.min.js +261 -260
- package/dist/o_spreadsheet.xml +19 -36
- 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 17.0.
|
|
6
|
-
* @date 2024-02-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.0.12
|
|
6
|
+
* @date 2024-02-16T14:24:02.984Z
|
|
7
|
+
* @hash 8fa2bab
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports, owl) {
|
|
@@ -551,8 +551,8 @@
|
|
|
551
551
|
* If the given item does not exist in the dictionary, it creates one with a new id.
|
|
552
552
|
*/
|
|
553
553
|
function getItemId(item, itemsDic) {
|
|
554
|
-
for (
|
|
555
|
-
if (deepEquals(
|
|
554
|
+
for (const key in itemsDic) {
|
|
555
|
+
if (deepEquals(itemsDic[key], item)) {
|
|
556
556
|
return parseInt(key, 10);
|
|
557
557
|
}
|
|
558
558
|
}
|
|
@@ -651,11 +651,13 @@
|
|
|
651
651
|
if (typeof o1 !== "object")
|
|
652
652
|
return o1 === o2;
|
|
653
653
|
// Objects can have different keys if the values are undefined
|
|
654
|
-
const
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
654
|
+
for (const key in o2) {
|
|
655
|
+
if (!(key in o1) && o2[key] !== undefined) {
|
|
656
|
+
return false;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
for (const key in o1) {
|
|
660
|
+
if (typeof o1[key] !== typeof o2[key])
|
|
659
661
|
return false;
|
|
660
662
|
if (typeof o1[key] === "object") {
|
|
661
663
|
if (!deepEquals(o1[key], o2[key]))
|
|
@@ -725,18 +727,18 @@
|
|
|
725
727
|
return true;
|
|
726
728
|
}
|
|
727
729
|
class JetSet extends Set {
|
|
728
|
-
|
|
730
|
+
addMany(iterable) {
|
|
729
731
|
for (const element of iterable) {
|
|
730
732
|
super.add(element);
|
|
731
733
|
}
|
|
732
734
|
return this;
|
|
733
735
|
}
|
|
734
|
-
|
|
735
|
-
let
|
|
736
|
+
deleteMany(iterable) {
|
|
737
|
+
let wasDeleted = false;
|
|
736
738
|
for (const element of iterable) {
|
|
737
|
-
|
|
739
|
+
wasDeleted ||= super.delete(element);
|
|
738
740
|
}
|
|
739
|
-
return
|
|
741
|
+
return wasDeleted;
|
|
740
742
|
}
|
|
741
743
|
}
|
|
742
744
|
/**
|
|
@@ -1995,7 +1997,7 @@
|
|
|
1995
1997
|
* Static helper which returns a successful DispatchResult
|
|
1996
1998
|
*/
|
|
1997
1999
|
static get Success() {
|
|
1998
|
-
return
|
|
2000
|
+
return SUCCESS;
|
|
1999
2001
|
}
|
|
2000
2002
|
get isSuccessful() {
|
|
2001
2003
|
return this.reasons.length === 0;
|
|
@@ -2008,6 +2010,7 @@
|
|
|
2008
2010
|
return this.reasons.includes(reason);
|
|
2009
2011
|
}
|
|
2010
2012
|
}
|
|
2013
|
+
const SUCCESS = new DispatchResult();
|
|
2011
2014
|
exports.CommandResult = void 0;
|
|
2012
2015
|
(function (CommandResult) {
|
|
2013
2016
|
CommandResult["Success"] = "Success";
|
|
@@ -2889,6 +2892,9 @@
|
|
|
2889
2892
|
function formatValue(value, { format, locale }) {
|
|
2890
2893
|
switch (typeof value) {
|
|
2891
2894
|
case "string":
|
|
2895
|
+
if (value.includes('\\"')) {
|
|
2896
|
+
return value.replace(/\\"/g, '"');
|
|
2897
|
+
}
|
|
2892
2898
|
return value;
|
|
2893
2899
|
case "boolean":
|
|
2894
2900
|
return value ? "TRUE" : "FALSE";
|
|
@@ -7380,7 +7386,7 @@
|
|
|
7380
7386
|
while (!chars.isOver()) {
|
|
7381
7387
|
let token = tokenizeSpace(chars) ||
|
|
7382
7388
|
tokenizeArgsSeparator(chars, locale) ||
|
|
7383
|
-
|
|
7389
|
+
tokenizeParenthesis(chars) ||
|
|
7384
7390
|
tokenizeOperator(chars) ||
|
|
7385
7391
|
tokenizeString(chars) ||
|
|
7386
7392
|
tokenizeDebugger(chars) ||
|
|
@@ -7401,15 +7407,14 @@
|
|
|
7401
7407
|
}
|
|
7402
7408
|
return null;
|
|
7403
7409
|
}
|
|
7404
|
-
const
|
|
7405
|
-
"(": "LEFT_PAREN",
|
|
7406
|
-
")": "RIGHT_PAREN",
|
|
7410
|
+
const parenthesis = {
|
|
7411
|
+
"(": { type: "LEFT_PAREN", value: "(" },
|
|
7412
|
+
")": { type: "RIGHT_PAREN", value: ")" },
|
|
7407
7413
|
};
|
|
7408
|
-
function
|
|
7409
|
-
if (chars.current
|
|
7414
|
+
function tokenizeParenthesis(chars) {
|
|
7415
|
+
if (chars.current === "(" || chars.current === ")") {
|
|
7410
7416
|
const value = chars.shift();
|
|
7411
|
-
|
|
7412
|
-
return { type, value };
|
|
7417
|
+
return parenthesis[value];
|
|
7413
7418
|
}
|
|
7414
7419
|
return null;
|
|
7415
7420
|
}
|
|
@@ -7430,7 +7435,12 @@
|
|
|
7430
7435
|
}
|
|
7431
7436
|
return null;
|
|
7432
7437
|
}
|
|
7438
|
+
const FIRST_POSSIBLE_NUMBER_CHARS = new Set("0123456789");
|
|
7433
7439
|
function tokenizeNumber(chars, locale) {
|
|
7440
|
+
if (!FIRST_POSSIBLE_NUMBER_CHARS.has(chars.current) &&
|
|
7441
|
+
chars.current !== locale.decimalSeparator) {
|
|
7442
|
+
return null;
|
|
7443
|
+
}
|
|
7434
7444
|
const match = chars.remaining().match(getFormulaNumberRegex(locale.decimalSeparator));
|
|
7435
7445
|
if (match) {
|
|
7436
7446
|
chars.advanceBy(match[0].length);
|
|
@@ -7455,7 +7465,7 @@
|
|
|
7455
7465
|
}
|
|
7456
7466
|
return null;
|
|
7457
7467
|
}
|
|
7458
|
-
const separatorRegexp =
|
|
7468
|
+
const separatorRegexp = /^[\w\.!\$]+/;
|
|
7459
7469
|
/**
|
|
7460
7470
|
* A "Symbol" is just basically any word-like element that can appear in a
|
|
7461
7471
|
* formula, which is not a string. So:
|
|
@@ -7495,8 +7505,11 @@
|
|
|
7495
7505
|
};
|
|
7496
7506
|
}
|
|
7497
7507
|
}
|
|
7498
|
-
|
|
7499
|
-
|
|
7508
|
+
const match = chars.remaining().match(separatorRegexp);
|
|
7509
|
+
if (match) {
|
|
7510
|
+
const value = match[0];
|
|
7511
|
+
result += value;
|
|
7512
|
+
chars.advanceBy(value.length);
|
|
7500
7513
|
}
|
|
7501
7514
|
if (result.length) {
|
|
7502
7515
|
const value = result;
|
|
@@ -7558,7 +7571,10 @@
|
|
|
7558
7571
|
return this.text.substring(this.currentIndex);
|
|
7559
7572
|
}
|
|
7560
7573
|
currentStartsWith(str) {
|
|
7561
|
-
|
|
7574
|
+
if (this.current !== str[0]) {
|
|
7575
|
+
return false;
|
|
7576
|
+
}
|
|
7577
|
+
for (let j = 1; j < str.length; j++) {
|
|
7562
7578
|
if (this.text[this.currentIndex + j] !== str[j]) {
|
|
7563
7579
|
return false;
|
|
7564
7580
|
}
|
|
@@ -7585,6 +7601,9 @@
|
|
|
7585
7601
|
if (locale.formulaArgSeparator === locale.decimalSeparator) {
|
|
7586
7602
|
return false;
|
|
7587
7603
|
}
|
|
7604
|
+
if (locale.thousandsSeparator === locale.decimalSeparator) {
|
|
7605
|
+
return false;
|
|
7606
|
+
}
|
|
7588
7607
|
try {
|
|
7589
7608
|
formatValue(1, { locale, format: "#,##0.00" });
|
|
7590
7609
|
formatValue(1, { locale, format: locale.dateFormat });
|
|
@@ -7675,7 +7694,7 @@
|
|
|
7675
7694
|
if (locale.decimalSeparator === "." || !isNumber(content, locale)) {
|
|
7676
7695
|
return content;
|
|
7677
7696
|
}
|
|
7678
|
-
return content.replace(locale.decimalSeparator, ".");
|
|
7697
|
+
return content.replace(locale.thousandsSeparator, "").replace(locale.decimalSeparator, ".");
|
|
7679
7698
|
}
|
|
7680
7699
|
/**
|
|
7681
7700
|
* Change a content string from the given locale to its canonical form (en_US locale). Also convert date string.
|
|
@@ -10747,6 +10766,12 @@
|
|
|
10747
10766
|
let { col, row } = env.model.getters.getActivePosition();
|
|
10748
10767
|
env.model.dispatch("OPEN_CELL_POPOVER", { col, row, popoverType: "LinkEditor" });
|
|
10749
10768
|
};
|
|
10769
|
+
const INSERT_LINK_NAME = (env) => {
|
|
10770
|
+
const sheetId = env.model.getters.getActiveSheetId();
|
|
10771
|
+
const { col, row } = env.model.getters.getActivePosition();
|
|
10772
|
+
const cell = env.model.getters.getEvaluatedCell({ sheetId, col, row });
|
|
10773
|
+
return cell && cell.link ? _t("Edit link") : _t("Insert link");
|
|
10774
|
+
};
|
|
10750
10775
|
//------------------------------------------------------------------------------
|
|
10751
10776
|
// Filters action
|
|
10752
10777
|
//------------------------------------------------------------------------------
|
|
@@ -19778,7 +19803,7 @@
|
|
|
19778
19803
|
})
|
|
19779
19804
|
.add("insert_link", {
|
|
19780
19805
|
...insertLink,
|
|
19781
|
-
name:
|
|
19806
|
+
name: INSERT_LINK_NAME,
|
|
19782
19807
|
sequence: 150,
|
|
19783
19808
|
separator: true,
|
|
19784
19809
|
});
|
|
@@ -26031,6 +26056,17 @@
|
|
|
26031
26056
|
`;
|
|
26032
26057
|
class TextValueProvider extends owl.Component {
|
|
26033
26058
|
static template = "o-spreadsheet-TextValueProvider";
|
|
26059
|
+
autoCompleteListRef = owl.useRef("autoCompleteList");
|
|
26060
|
+
setup() {
|
|
26061
|
+
owl.useEffect(() => {
|
|
26062
|
+
const selectedIndex = this.props.selectedIndex;
|
|
26063
|
+
if (selectedIndex === undefined) {
|
|
26064
|
+
return;
|
|
26065
|
+
}
|
|
26066
|
+
const selectedElement = this.autoCompleteListRef.el?.children[selectedIndex];
|
|
26067
|
+
selectedElement?.scrollIntoView?.({ block: "nearest" });
|
|
26068
|
+
}, () => [this.props.selectedIndex, this.autoCompleteListRef.el]);
|
|
26069
|
+
}
|
|
26034
26070
|
}
|
|
26035
26071
|
TextValueProvider.props = {
|
|
26036
26072
|
values: Array,
|
|
@@ -26482,6 +26518,7 @@
|
|
|
26482
26518
|
position: absolute;
|
|
26483
26519
|
margin: 1px 4px;
|
|
26484
26520
|
pointer-events: none;
|
|
26521
|
+
overflow: auto;
|
|
26485
26522
|
|
|
26486
26523
|
.o-semi-bold {
|
|
26487
26524
|
/** FIXME: to remove in favor of Bootstrap
|
|
@@ -26497,6 +26534,7 @@
|
|
|
26497
26534
|
static components = { TextValueProvider, FunctionDescriptionProvider };
|
|
26498
26535
|
static defaultProps = {
|
|
26499
26536
|
inputStyle: "",
|
|
26537
|
+
isDefaultFocus: false,
|
|
26500
26538
|
};
|
|
26501
26539
|
composerRef = owl.useRef("o_composer");
|
|
26502
26540
|
contentHelper = new ContentEditableHelper(this.composerRef.el);
|
|
@@ -26527,7 +26565,10 @@
|
|
|
26527
26565
|
if (this.props.delimitation && this.props.rect) {
|
|
26528
26566
|
const { x: cellX, y: cellY, height: cellHeight } = this.props.rect;
|
|
26529
26567
|
const remainingHeight = this.props.delimitation.height - (cellY + cellHeight);
|
|
26568
|
+
assistantStyle["max-height"] = `${remainingHeight}px`;
|
|
26530
26569
|
if (cellY > remainingHeight) {
|
|
26570
|
+
const availableSpaceAbove = cellY;
|
|
26571
|
+
assistantStyle["max-height"] = `${availableSpaceAbove}px`;
|
|
26531
26572
|
// render top
|
|
26532
26573
|
// We compensate 2 px of margin on the assistant style + 1px for design reasons
|
|
26533
26574
|
assistantStyle.top = `-3px`;
|
|
@@ -26553,7 +26594,6 @@
|
|
|
26553
26594
|
F2: () => console.warn("Not implemented"),
|
|
26554
26595
|
F4: this.processF4Key,
|
|
26555
26596
|
Tab: (ev) => this.processTabKey(ev),
|
|
26556
|
-
" ": (ev) => this.processSpaceKey(ev),
|
|
26557
26597
|
};
|
|
26558
26598
|
keyCodeMapping = {
|
|
26559
26599
|
NumpadDecimal: this.processNumpadDecimal,
|
|
@@ -26561,12 +26601,12 @@
|
|
|
26561
26601
|
setup() {
|
|
26562
26602
|
owl.onMounted(() => {
|
|
26563
26603
|
const el = this.composerRef.el;
|
|
26604
|
+
if (this.props.isDefaultFocus) {
|
|
26605
|
+
this.env.focusableElement.setFocusableElement(el);
|
|
26606
|
+
}
|
|
26564
26607
|
this.contentHelper.updateEl(el);
|
|
26565
26608
|
this.processTokenAtCursor();
|
|
26566
26609
|
});
|
|
26567
|
-
owl.onWillUnmount(() => {
|
|
26568
|
-
this.props.onComposerUnmounted?.();
|
|
26569
|
-
});
|
|
26570
26610
|
owl.useEffect(() => {
|
|
26571
26611
|
this.processContent();
|
|
26572
26612
|
});
|
|
@@ -26575,7 +26615,8 @@
|
|
|
26575
26615
|
// Handlers
|
|
26576
26616
|
// ---------------------------------------------------------------------------
|
|
26577
26617
|
processArrowKeys(ev) {
|
|
26578
|
-
if (this.env.model.getters.isSelectingForComposer()
|
|
26618
|
+
if (this.env.model.getters.isSelectingForComposer() ||
|
|
26619
|
+
this.env.model.getters.getEditionMode() === "inactive") {
|
|
26579
26620
|
this.functionDescriptionState.showDescription = false;
|
|
26580
26621
|
// Prevent the default content editable behavior which moves the cursor
|
|
26581
26622
|
ev.preventDefault();
|
|
@@ -26618,26 +26659,20 @@
|
|
|
26618
26659
|
processTabKey(ev) {
|
|
26619
26660
|
ev.preventDefault();
|
|
26620
26661
|
ev.stopPropagation();
|
|
26621
|
-
|
|
26622
|
-
|
|
26623
|
-
|
|
26624
|
-
|
|
26625
|
-
|
|
26626
|
-
|
|
26662
|
+
if (this.env.model.getters.getEditionMode() !== "inactive") {
|
|
26663
|
+
const state = this.autoCompleteState;
|
|
26664
|
+
if (state.showProvider && state.selectedIndex !== undefined) {
|
|
26665
|
+
const autoCompleteValue = this.autoCompleteState.values[state.selectedIndex]?.text;
|
|
26666
|
+
if (autoCompleteValue) {
|
|
26667
|
+
this.autoComplete(autoCompleteValue);
|
|
26668
|
+
return;
|
|
26669
|
+
}
|
|
26627
26670
|
}
|
|
26671
|
+
interactiveStopEdition(this.env);
|
|
26628
26672
|
}
|
|
26629
26673
|
const direction = ev.shiftKey ? "left" : "right";
|
|
26630
|
-
interactiveStopEdition(this.env);
|
|
26631
26674
|
this.env.model.selection.moveAnchorCell(direction, 1);
|
|
26632
26675
|
}
|
|
26633
|
-
processSpaceKey(ev) {
|
|
26634
|
-
if (ev.ctrlKey) {
|
|
26635
|
-
ev.preventDefault();
|
|
26636
|
-
ev.stopPropagation();
|
|
26637
|
-
this.showFunctionAutocomplete("");
|
|
26638
|
-
this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
|
|
26639
|
-
}
|
|
26640
|
-
}
|
|
26641
26676
|
processEnterKey(ev) {
|
|
26642
26677
|
ev.preventDefault();
|
|
26643
26678
|
ev.stopPropagation();
|
|
@@ -26690,6 +26725,9 @@
|
|
|
26690
26725
|
this.compositionActive = false;
|
|
26691
26726
|
}
|
|
26692
26727
|
onKeydown(ev) {
|
|
26728
|
+
if (this.env.model.getters.getEditionMode() === "inactive") {
|
|
26729
|
+
return;
|
|
26730
|
+
}
|
|
26693
26731
|
let handler = this.keyMapping[ev.key] || this.keyCodeMapping[ev.code];
|
|
26694
26732
|
if (handler) {
|
|
26695
26733
|
handler.call(this, ev);
|
|
@@ -26698,14 +26736,33 @@
|
|
|
26698
26736
|
ev.stopPropagation();
|
|
26699
26737
|
}
|
|
26700
26738
|
}
|
|
26739
|
+
onPaste(ev) {
|
|
26740
|
+
if (this.env.model.getters.getEditionMode() !== "inactive") {
|
|
26741
|
+
ev.stopPropagation();
|
|
26742
|
+
}
|
|
26743
|
+
}
|
|
26701
26744
|
/*
|
|
26702
26745
|
* Triggered automatically by the content-editable between the keydown and key up
|
|
26703
26746
|
* */
|
|
26704
26747
|
onInput(ev) {
|
|
26705
|
-
if (
|
|
26748
|
+
if (!this.shouldProcessInputEvents) {
|
|
26706
26749
|
return;
|
|
26707
26750
|
}
|
|
26708
|
-
|
|
26751
|
+
if (ev.inputType === "insertFromPaste" &&
|
|
26752
|
+
this.env.model.getters.getEditionMode() === "inactive") {
|
|
26753
|
+
return;
|
|
26754
|
+
}
|
|
26755
|
+
ev.stopPropagation();
|
|
26756
|
+
let content;
|
|
26757
|
+
if (this.env.model.getters.getEditionMode() === "inactive") {
|
|
26758
|
+
content = ev.data || "";
|
|
26759
|
+
}
|
|
26760
|
+
else {
|
|
26761
|
+
content = this.contentHelper.getText();
|
|
26762
|
+
}
|
|
26763
|
+
if (this.props.focus === "inactive") {
|
|
26764
|
+
return this.props.onComposerCellFocused?.(content);
|
|
26765
|
+
}
|
|
26709
26766
|
let selection = this.contentHelper.getCurrentSelection();
|
|
26710
26767
|
if (ev.inputType === "insertParagraph") {
|
|
26711
26768
|
const start = Math.min(selection.start, selection.end);
|
|
@@ -26787,9 +26844,8 @@
|
|
|
26787
26844
|
}
|
|
26788
26845
|
const newSelection = this.contentHelper.getCurrentSelection();
|
|
26789
26846
|
this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
|
|
26790
|
-
|
|
26791
|
-
|
|
26792
|
-
}
|
|
26847
|
+
this.props.onComposerContentFocused();
|
|
26848
|
+
if (this.props.focus === "inactive") ;
|
|
26793
26849
|
this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", newSelection);
|
|
26794
26850
|
this.processTokenAtCursor();
|
|
26795
26851
|
}
|
|
@@ -26956,7 +27012,7 @@
|
|
|
26956
27012
|
const highlights = this.env.model.getters.getHighlights();
|
|
26957
27013
|
const refSheet = sheetName
|
|
26958
27014
|
? this.env.model.getters.getSheetIdByName(sheetName)
|
|
26959
|
-
: this.env.model.getters.getCurrentEditedCell()
|
|
27015
|
+
: this.env.model.getters.getCurrentEditedCell()?.sheetId;
|
|
26960
27016
|
const highlight = highlights.find((highlight) => {
|
|
26961
27017
|
if (highlight.sheetId !== refSheet)
|
|
26962
27018
|
return false;
|
|
@@ -27049,12 +27105,13 @@
|
|
|
27049
27105
|
}
|
|
27050
27106
|
}
|
|
27051
27107
|
Composer.props = {
|
|
27052
|
-
focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
|
|
27053
|
-
onComposerContentFocused: Function,
|
|
27054
27108
|
inputStyle: { type: String, optional: true },
|
|
27055
27109
|
rect: { type: Object, optional: true },
|
|
27056
27110
|
delimitation: { type: Object, optional: true },
|
|
27057
|
-
|
|
27111
|
+
focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
|
|
27112
|
+
onComposerCellFocused: { type: Function, optional: true },
|
|
27113
|
+
onComposerContentFocused: Function,
|
|
27114
|
+
isDefaultFocus: { type: Boolean, optional: true },
|
|
27058
27115
|
};
|
|
27059
27116
|
|
|
27060
27117
|
const COMPOSER_BORDER_WIDTH = 3 * 0.4 * window.devicePixelRatio || 1;
|
|
@@ -27088,51 +27145,25 @@
|
|
|
27088
27145
|
class GridComposer extends owl.Component {
|
|
27089
27146
|
static template = "o-spreadsheet-GridComposer";
|
|
27090
27147
|
static components = { Composer };
|
|
27091
|
-
|
|
27092
|
-
|
|
27093
|
-
rect;
|
|
27148
|
+
rect = this.defaultRect;
|
|
27149
|
+
isEditing = false;
|
|
27094
27150
|
isCellReferenceVisible;
|
|
27095
|
-
|
|
27151
|
+
get defaultRect() {
|
|
27152
|
+
return { x: 0, y: 0, width: 0, height: 0 };
|
|
27153
|
+
}
|
|
27096
27154
|
setup() {
|
|
27097
|
-
this.gridComposerRef = owl.useRef("gridComposer");
|
|
27098
|
-
this.composerState = owl.useState({
|
|
27099
|
-
rect: undefined,
|
|
27100
|
-
delimitation: undefined,
|
|
27101
|
-
});
|
|
27102
|
-
const { sheetId, col, row } = this.env.model.getters.getActivePosition();
|
|
27103
|
-
this.zone = this.env.model.getters.expandZone(sheetId, positionToZone({ col, row }));
|
|
27104
|
-
this.rect = this.env.model.getters.getVisibleRect(this.zone);
|
|
27105
|
-
this.isCellReferenceVisible = false;
|
|
27106
|
-
owl.onMounted(() => {
|
|
27107
|
-
const el = this.gridComposerRef.el;
|
|
27108
|
-
this.composerState.rect = {
|
|
27109
|
-
x: this.rect.x,
|
|
27110
|
-
y: this.rect.y,
|
|
27111
|
-
width: el.clientWidth,
|
|
27112
|
-
height: el.clientHeight,
|
|
27113
|
-
};
|
|
27114
|
-
this.composerState.delimitation = {
|
|
27115
|
-
width: this.props.gridDims.width,
|
|
27116
|
-
height: this.props.gridDims.height,
|
|
27117
|
-
};
|
|
27118
|
-
});
|
|
27119
27155
|
owl.onWillUpdateProps(() => {
|
|
27120
|
-
|
|
27121
|
-
|
|
27122
|
-
}
|
|
27123
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
27124
|
-
const zone = this.env.model.getters.getSelectedZone();
|
|
27125
|
-
const rect = this.env.model.getters.getVisibleRect(zone);
|
|
27126
|
-
if (!deepEquals(rect, this.rect) ||
|
|
27127
|
-
sheetId !== this.env.model.getters.getCurrentEditedCell().sheetId) {
|
|
27128
|
-
this.isCellReferenceVisible = true;
|
|
27129
|
-
}
|
|
27156
|
+
this.updateComponentPosition();
|
|
27157
|
+
this.updateCellReferenceVisibility();
|
|
27130
27158
|
});
|
|
27131
27159
|
}
|
|
27132
27160
|
get shouldDisplayCellReference() {
|
|
27133
27161
|
return this.isCellReferenceVisible;
|
|
27134
27162
|
}
|
|
27135
27163
|
get cellReference() {
|
|
27164
|
+
if (!this.env.model.getters.getCurrentEditedCell()) {
|
|
27165
|
+
return "";
|
|
27166
|
+
}
|
|
27136
27167
|
const { col, row, sheetId } = this.env.model.getters.getCurrentEditedCell();
|
|
27137
27168
|
const prefixSheet = sheetId !== this.env.model.getters.getActiveSheetId();
|
|
27138
27169
|
return `${prefixSheet ? getCanonicalSheetName(this.env.model.getters.getSheetName(sheetId)) + "!" : ""}${toXC(col, row)}`;
|
|
@@ -27144,7 +27175,27 @@
|
|
|
27144
27175
|
top: `${top - GRID_CELL_REFERENCE_TOP_OFFSET}px`,
|
|
27145
27176
|
});
|
|
27146
27177
|
}
|
|
27178
|
+
get composerProps() {
|
|
27179
|
+
const { width, height } = this.env.model.getters.getSheetViewDimensionWithHeaders();
|
|
27180
|
+
return {
|
|
27181
|
+
rect: { ...this.rect },
|
|
27182
|
+
delimitation: {
|
|
27183
|
+
width,
|
|
27184
|
+
height,
|
|
27185
|
+
},
|
|
27186
|
+
focus: this.props.focus,
|
|
27187
|
+
isDefaultFocus: true,
|
|
27188
|
+
onComposerContentFocused: this.props.onComposerContentFocused,
|
|
27189
|
+
onComposerCellFocused: this.props.onComposerCellFocused,
|
|
27190
|
+
};
|
|
27191
|
+
}
|
|
27147
27192
|
get containerStyle() {
|
|
27193
|
+
if (this.env.model.getters.getEditionMode() === "inactive" || !this.rect) {
|
|
27194
|
+
return `
|
|
27195
|
+
position: absolute;
|
|
27196
|
+
z-index: -1000;
|
|
27197
|
+
`;
|
|
27198
|
+
}
|
|
27148
27199
|
const isFormula = this.env.model.getters.getCurrentContent().startsWith("=");
|
|
27149
27200
|
const cell = this.env.model.getters.getActiveCell();
|
|
27150
27201
|
const position = this.env.model.getters.getActivePosition();
|
|
@@ -27164,6 +27215,8 @@
|
|
|
27164
27215
|
if (!isFormula) {
|
|
27165
27216
|
textAlign = style.align || cell.defaultAlign;
|
|
27166
27217
|
}
|
|
27218
|
+
const maxHeight = this.props.gridDims.height - this.rect.y;
|
|
27219
|
+
const maxWidth = this.props.gridDims.width - this.rect.x;
|
|
27167
27220
|
/**
|
|
27168
27221
|
* min-size is on the container, not the composer element, because we want to have the same size as the cell by default,
|
|
27169
27222
|
* including all the paddings/margins of the composer
|
|
@@ -27175,6 +27228,8 @@
|
|
|
27175
27228
|
top: `${top}px`,
|
|
27176
27229
|
"min-width": `${width + 1}px`,
|
|
27177
27230
|
"min-height": `${height + 1}px`,
|
|
27231
|
+
"max-width": `${maxWidth}px`,
|
|
27232
|
+
"max-height": `${maxHeight}px`,
|
|
27178
27233
|
background,
|
|
27179
27234
|
color,
|
|
27180
27235
|
"font-size": `${fontSizeInPixels(fontSize)}px`,
|
|
@@ -27184,20 +27239,38 @@
|
|
|
27184
27239
|
"text-align": textAlign,
|
|
27185
27240
|
});
|
|
27186
27241
|
}
|
|
27187
|
-
|
|
27188
|
-
const
|
|
27189
|
-
|
|
27190
|
-
|
|
27191
|
-
|
|
27192
|
-
|
|
27193
|
-
|
|
27242
|
+
updateComponentPosition() {
|
|
27243
|
+
const isEditing = this.env.model.getters.getEditionMode() !== "inactive";
|
|
27244
|
+
if (this.isEditing !== isEditing) {
|
|
27245
|
+
this.isEditing = isEditing;
|
|
27246
|
+
if (!isEditing) {
|
|
27247
|
+
this.rect = this.defaultRect;
|
|
27248
|
+
this.env.focusableElement.focus();
|
|
27249
|
+
return;
|
|
27250
|
+
}
|
|
27251
|
+
const position = this.env.model.getters.getActivePosition();
|
|
27252
|
+
const zone = this.env.model.getters.expandZone(position.sheetId, positionToZone(position));
|
|
27253
|
+
this.rect = this.env.model.getters.getVisibleRect(zone);
|
|
27254
|
+
}
|
|
27255
|
+
}
|
|
27256
|
+
updateCellReferenceVisibility() {
|
|
27257
|
+
if (this.isCellReferenceVisible || this.env.model.getters.getEditionMode() === "inactive") {
|
|
27258
|
+
return;
|
|
27259
|
+
}
|
|
27260
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
27261
|
+
const zone = this.env.model.getters.getSelectedZone();
|
|
27262
|
+
const rect = this.env.model.getters.getVisibleRect(zone);
|
|
27263
|
+
if (!deepEquals(rect, this.rect) ||
|
|
27264
|
+
sheetId !== this.env.model.getters.getCurrentEditedCell().sheetId) {
|
|
27265
|
+
this.isCellReferenceVisible = true;
|
|
27266
|
+
}
|
|
27194
27267
|
}
|
|
27195
27268
|
}
|
|
27196
27269
|
GridComposer.props = {
|
|
27197
27270
|
focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
|
|
27198
|
-
onComposerUnmounted: Function,
|
|
27199
27271
|
onComposerContentFocused: Function,
|
|
27200
27272
|
gridDims: Object,
|
|
27273
|
+
onComposerCellFocused: Function,
|
|
27201
27274
|
};
|
|
27202
27275
|
|
|
27203
27276
|
const CSS$1 = css /* scss */ `
|
|
@@ -28288,7 +28361,6 @@
|
|
|
28288
28361
|
this.props.onCellDoubleClicked(col, row);
|
|
28289
28362
|
}
|
|
28290
28363
|
onContextMenu(ev) {
|
|
28291
|
-
ev.preventDefault();
|
|
28292
28364
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
28293
28365
|
this.props.onCellRightClicked(col, row, { x: ev.clientX, y: ev.clientY });
|
|
28294
28366
|
}
|
|
@@ -29373,7 +29445,6 @@
|
|
|
29373
29445
|
HEADER_WIDTH = HEADER_WIDTH;
|
|
29374
29446
|
menuState;
|
|
29375
29447
|
gridRef;
|
|
29376
|
-
hiddenInput;
|
|
29377
29448
|
onMouseWheel;
|
|
29378
29449
|
canvasPosition;
|
|
29379
29450
|
hoveredCell;
|
|
@@ -29384,17 +29455,16 @@
|
|
|
29384
29455
|
menuItems: [],
|
|
29385
29456
|
});
|
|
29386
29457
|
this.gridRef = owl.useRef("grid");
|
|
29387
|
-
this.hiddenInput = owl.useRef("hiddenInput");
|
|
29388
29458
|
this.canvasPosition = useAbsoluteBoundingRect(this.gridRef);
|
|
29389
29459
|
this.hoveredCell = owl.useState({ col: undefined, row: undefined });
|
|
29390
29460
|
owl.useChildSubEnv({ getPopoverContainerRect: () => this.getGridRect() });
|
|
29391
29461
|
owl.useExternalListener(document.body, "cut", this.copy.bind(this, true));
|
|
29392
29462
|
owl.useExternalListener(document.body, "copy", this.copy.bind(this, false));
|
|
29393
29463
|
owl.useExternalListener(document.body, "paste", this.paste);
|
|
29394
|
-
owl.onMounted(() => this.
|
|
29395
|
-
this.props.exposeFocus(() => this.
|
|
29464
|
+
owl.onMounted(() => this.focusDefaultElement());
|
|
29465
|
+
this.props.exposeFocus(() => this.focusDefaultElement());
|
|
29396
29466
|
useGridDrawing("canvas", this.env.model, () => this.env.model.getters.getSheetViewDimensionWithHeaders());
|
|
29397
|
-
owl.useEffect(() => this.
|
|
29467
|
+
owl.useEffect(() => this.focusDefaultElement(), () => [this.env.model.getters.getActiveSheetId()]);
|
|
29398
29468
|
this.onMouseWheel = useWheelHandler((deltaX, deltaY) => {
|
|
29399
29469
|
this.moveCanvas(deltaX, deltaY);
|
|
29400
29470
|
this.hoveredCell.col = undefined;
|
|
@@ -29417,7 +29487,7 @@
|
|
|
29417
29487
|
if (this.env.model.getters.hasOpenedPopover()) {
|
|
29418
29488
|
this.closeOpenedPopover();
|
|
29419
29489
|
}
|
|
29420
|
-
this.
|
|
29490
|
+
this.focusDefaultElement();
|
|
29421
29491
|
}
|
|
29422
29492
|
// this map will handle most of the actions that should happen on key down. The arrow keys are managed in the key
|
|
29423
29493
|
// down itself
|
|
@@ -29596,10 +29666,10 @@
|
|
|
29596
29666
|
"ALT+SHIFT+ARROWUP": () => this.processHeaderGroupingKey("up"),
|
|
29597
29667
|
"ALT+SHIFT+ARROWDOWN": () => this.processHeaderGroupingKey("down"),
|
|
29598
29668
|
};
|
|
29599
|
-
|
|
29669
|
+
focusDefaultElement() {
|
|
29600
29670
|
if (!this.env.model.getters.getSelectedFigureId() &&
|
|
29601
29671
|
this.env.model.getters.getEditionMode() === "inactive") {
|
|
29602
|
-
this.
|
|
29672
|
+
this.env.focusableElement.focus();
|
|
29603
29673
|
}
|
|
29604
29674
|
}
|
|
29605
29675
|
get gridEl() {
|
|
@@ -29744,19 +29814,6 @@
|
|
|
29744
29814
|
return;
|
|
29745
29815
|
}
|
|
29746
29816
|
}
|
|
29747
|
-
onInput(ev) {
|
|
29748
|
-
// the user meant to paste in the sheet, not open the composer with the pasted content
|
|
29749
|
-
if (!ev.isComposing && ev.inputType === "insertFromPaste") {
|
|
29750
|
-
return;
|
|
29751
|
-
}
|
|
29752
|
-
if (ev.data) {
|
|
29753
|
-
// if the user types a character on the grid, it means he wants to start composing the selected cell with that
|
|
29754
|
-
// character
|
|
29755
|
-
ev.preventDefault();
|
|
29756
|
-
ev.stopPropagation();
|
|
29757
|
-
this.props.onGridComposerCellFocused(ev.data);
|
|
29758
|
-
}
|
|
29759
|
-
}
|
|
29760
29817
|
// ---------------------------------------------------------------------------
|
|
29761
29818
|
// Context Menu
|
|
29762
29819
|
// ---------------------------------------------------------------------------
|
|
@@ -29871,7 +29928,7 @@
|
|
|
29871
29928
|
}
|
|
29872
29929
|
closeMenu() {
|
|
29873
29930
|
this.menuState.isOpen = false;
|
|
29874
|
-
this.
|
|
29931
|
+
this.focusDefaultElement();
|
|
29875
29932
|
}
|
|
29876
29933
|
processHeaderGroupingKey(direction) {
|
|
29877
29934
|
if (this.env.model.getters.getSelectedZones().length !== 1) {
|
|
@@ -33766,6 +33823,31 @@
|
|
|
33766
33823
|
return data;
|
|
33767
33824
|
},
|
|
33768
33825
|
},
|
|
33826
|
+
{
|
|
33827
|
+
description: "Fix datafilter duplication",
|
|
33828
|
+
from: 12,
|
|
33829
|
+
to: 12.5,
|
|
33830
|
+
applyMigration(data) {
|
|
33831
|
+
for (let sheet of data.sheets || []) {
|
|
33832
|
+
let knownDataFilterZones = [];
|
|
33833
|
+
for (let filterTable of sheet.filterTables || []) {
|
|
33834
|
+
const zone = toZone(filterTable.range);
|
|
33835
|
+
// See commit message for the details
|
|
33836
|
+
const intersectZoneIndex = knownDataFilterZones.findIndex((knownZone) => overlap(knownZone, zone));
|
|
33837
|
+
if (intersectZoneIndex !== -1) {
|
|
33838
|
+
knownDataFilterZones[intersectZoneIndex] = zone;
|
|
33839
|
+
}
|
|
33840
|
+
else {
|
|
33841
|
+
knownDataFilterZones.push(zone);
|
|
33842
|
+
}
|
|
33843
|
+
}
|
|
33844
|
+
sheet.filterTables = knownDataFilterZones.map((zone) => ({
|
|
33845
|
+
range: zoneToXc(zone),
|
|
33846
|
+
}));
|
|
33847
|
+
}
|
|
33848
|
+
return data;
|
|
33849
|
+
},
|
|
33850
|
+
},
|
|
33769
33851
|
{
|
|
33770
33852
|
description: "Change Border description structure",
|
|
33771
33853
|
from: 12,
|
|
@@ -34605,22 +34687,7 @@
|
|
|
34605
34687
|
}
|
|
34606
34688
|
}
|
|
34607
34689
|
export(data) {
|
|
34608
|
-
// Borders
|
|
34609
|
-
let borderId = 0;
|
|
34610
34690
|
const borders = {};
|
|
34611
|
-
/**
|
|
34612
|
-
* Get the id of the given border. If the border does not exist, it creates
|
|
34613
|
-
* one.
|
|
34614
|
-
*/
|
|
34615
|
-
function getBorderId(border) {
|
|
34616
|
-
for (let [key, value] of Object.entries(borders)) {
|
|
34617
|
-
if (deepEquals(value, border)) {
|
|
34618
|
-
return parseInt(key, 10);
|
|
34619
|
-
}
|
|
34620
|
-
}
|
|
34621
|
-
borders[++borderId] = border;
|
|
34622
|
-
return borderId;
|
|
34623
|
-
}
|
|
34624
34691
|
for (let sheet of data.sheets) {
|
|
34625
34692
|
for (let col = 0; col < sheet.colNumber; col++) {
|
|
34626
34693
|
for (let row = 0; row < sheet.rowNumber; row++) {
|
|
@@ -34628,7 +34695,7 @@
|
|
|
34628
34695
|
if (border) {
|
|
34629
34696
|
const xc = toXC(col, row);
|
|
34630
34697
|
const cell = sheet.cells[xc];
|
|
34631
|
-
const borderId =
|
|
34698
|
+
const borderId = getItemId(border, borders);
|
|
34632
34699
|
if (cell) {
|
|
34633
34700
|
cell.border = borderId;
|
|
34634
34701
|
}
|
|
@@ -35433,9 +35500,9 @@
|
|
|
35433
35500
|
allowDispatch(cmd) {
|
|
35434
35501
|
switch (cmd.type) {
|
|
35435
35502
|
case "UPDATE_CELL":
|
|
35436
|
-
return this.
|
|
35503
|
+
return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessUpdateCell);
|
|
35437
35504
|
case "CLEAR_CELL":
|
|
35438
|
-
return this.checkValidations(cmd, this.
|
|
35505
|
+
return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessClearCell);
|
|
35439
35506
|
default:
|
|
35440
35507
|
return "Success" /* CommandResult.Success */;
|
|
35441
35508
|
}
|
|
@@ -35568,9 +35635,6 @@
|
|
|
35568
35635
|
format: cell.format ? getItemId(cell.format, formats) : undefined,
|
|
35569
35636
|
content: cell.content || undefined,
|
|
35570
35637
|
};
|
|
35571
|
-
if (cell instanceof FormulaCellWithDependencies) {
|
|
35572
|
-
cells[xc].content = cell.contentWithFixedReferences || undefined;
|
|
35573
|
-
}
|
|
35574
35638
|
}
|
|
35575
35639
|
_sheet.cells = cells;
|
|
35576
35640
|
}
|
|
@@ -35588,8 +35652,8 @@
|
|
|
35588
35652
|
}
|
|
35589
35653
|
removeDefaultStyleValues(style) {
|
|
35590
35654
|
const cleanedStyle = { ...style };
|
|
35591
|
-
for (const
|
|
35592
|
-
if (cleanedStyle[property] ===
|
|
35655
|
+
for (const property in DEFAULT_STYLE) {
|
|
35656
|
+
if (cleanedStyle[property] === DEFAULT_STYLE[property]) {
|
|
35593
35657
|
delete cleanedStyle[property];
|
|
35594
35658
|
}
|
|
35595
35659
|
}
|
|
@@ -35746,10 +35810,7 @@
|
|
|
35746
35810
|
else {
|
|
35747
35811
|
style = before ? before.style : undefined;
|
|
35748
35812
|
}
|
|
35749
|
-
const
|
|
35750
|
-
let format = ("format" in after ? after.format : before && before.format) ||
|
|
35751
|
-
detectDateFormat(afterContent, locale) ||
|
|
35752
|
-
detectNumberFormat(afterContent);
|
|
35813
|
+
const format = "format" in after ? after.format : before && before.format;
|
|
35753
35814
|
/* Read the following IF as:
|
|
35754
35815
|
* we need to remove the cell if it is completely empty, but we can know if it completely empty if:
|
|
35755
35816
|
* - the command says the new content is empty and has no border/format/style
|
|
@@ -35790,12 +35851,11 @@
|
|
|
35790
35851
|
}
|
|
35791
35852
|
createLiteralCell(id, content, format, style) {
|
|
35792
35853
|
const locale = this.getters.getLocale();
|
|
35793
|
-
content = parseLiteral(content, locale).toString();
|
|
35794
35854
|
return {
|
|
35795
35855
|
id,
|
|
35796
|
-
content,
|
|
35856
|
+
content: parseLiteral(content, locale).toString(),
|
|
35797
35857
|
style,
|
|
35798
|
-
format,
|
|
35858
|
+
format: format || detectDateFormat(content, locale) || detectNumberFormat(content),
|
|
35799
35859
|
isFormula: false,
|
|
35800
35860
|
};
|
|
35801
35861
|
}
|
|
@@ -35821,8 +35881,11 @@
|
|
|
35821
35881
|
* being a computed property to rebuild the dependencies XC.
|
|
35822
35882
|
*/
|
|
35823
35883
|
createFormulaCellWithDependencies(id, compiledFormula, format, style, sheetId) {
|
|
35824
|
-
const dependencies =
|
|
35825
|
-
|
|
35884
|
+
const dependencies = [];
|
|
35885
|
+
for (const xc of compiledFormula.dependencies) {
|
|
35886
|
+
dependencies.push(this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
35887
|
+
}
|
|
35888
|
+
return new FormulaCellWithDependencies(id, compiledFormula, format, style, dependencies, sheetId, this.getters.getRangeString);
|
|
35826
35889
|
}
|
|
35827
35890
|
createErrorFormula(id, content, format, style, error) {
|
|
35828
35891
|
return {
|
|
@@ -35857,6 +35920,18 @@
|
|
|
35857
35920
|
}
|
|
35858
35921
|
return "Success" /* CommandResult.Success */;
|
|
35859
35922
|
}
|
|
35923
|
+
checkUselessUpdateCell(cmd) {
|
|
35924
|
+
const cell = this.getters.getCell(cmd);
|
|
35925
|
+
const hasContent = "content" in cmd || "formula" in cmd;
|
|
35926
|
+
const hasStyle = "style" in cmd;
|
|
35927
|
+
const hasFormat = "format" in cmd;
|
|
35928
|
+
if ((!hasContent || cell?.content === cmd.content) &&
|
|
35929
|
+
(!hasStyle || deepEquals(cell?.style, cmd.style)) &&
|
|
35930
|
+
(!hasFormat || cell?.format === cmd.format)) {
|
|
35931
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
35932
|
+
}
|
|
35933
|
+
return "Success" /* CommandResult.Success */;
|
|
35934
|
+
}
|
|
35860
35935
|
}
|
|
35861
35936
|
class FormulaCellWithDependencies {
|
|
35862
35937
|
id;
|
|
@@ -35876,7 +35951,7 @@
|
|
|
35876
35951
|
const tokens = compiledFormula.tokens.map((token) => {
|
|
35877
35952
|
if (token.type === "REFERENCE") {
|
|
35878
35953
|
const index = rangeIndex++;
|
|
35879
|
-
return new RangeReferenceToken(
|
|
35954
|
+
return new RangeReferenceToken(dependencies, index, this.sheetId, this.getRangeString);
|
|
35880
35955
|
}
|
|
35881
35956
|
return token;
|
|
35882
35957
|
});
|
|
@@ -35903,13 +35978,20 @@
|
|
|
35903
35978
|
}
|
|
35904
35979
|
}
|
|
35905
35980
|
class RangeReferenceToken {
|
|
35906
|
-
|
|
35981
|
+
ranges;
|
|
35982
|
+
rangeIndex;
|
|
35983
|
+
sheetId;
|
|
35984
|
+
getRangeString;
|
|
35907
35985
|
type = "REFERENCE";
|
|
35908
|
-
constructor(
|
|
35909
|
-
this.
|
|
35986
|
+
constructor(ranges, rangeIndex, sheetId, getRangeString) {
|
|
35987
|
+
this.ranges = ranges;
|
|
35988
|
+
this.rangeIndex = rangeIndex;
|
|
35989
|
+
this.sheetId = sheetId;
|
|
35990
|
+
this.getRangeString = getRangeString;
|
|
35910
35991
|
}
|
|
35911
35992
|
get value() {
|
|
35912
|
-
|
|
35993
|
+
const range = this.ranges[this.rangeIndex];
|
|
35994
|
+
return this.getRangeString(range, this.sheetId);
|
|
35913
35995
|
}
|
|
35914
35996
|
}
|
|
35915
35997
|
|
|
@@ -40645,7 +40727,15 @@
|
|
|
40645
40727
|
if (!this.rTrees[sheetId]) {
|
|
40646
40728
|
return;
|
|
40647
40729
|
}
|
|
40648
|
-
this.rTrees[sheetId].remove(item,
|
|
40730
|
+
this.rTrees[sheetId].remove(item, this.rtreeItemComparer);
|
|
40731
|
+
}
|
|
40732
|
+
rtreeItemComparer(left, right) {
|
|
40733
|
+
return (left.data == right.data &&
|
|
40734
|
+
left.boundingBox.sheetId === right.boundingBox.sheetId &&
|
|
40735
|
+
left.boundingBox?.zone.left === right.boundingBox.zone.left &&
|
|
40736
|
+
left.boundingBox?.zone.top === right.boundingBox.zone.top &&
|
|
40737
|
+
left.boundingBox?.zone.right === right.boundingBox.zone.right &&
|
|
40738
|
+
left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom);
|
|
40649
40739
|
}
|
|
40650
40740
|
}
|
|
40651
40741
|
/**
|
|
@@ -40723,7 +40813,7 @@
|
|
|
40723
40813
|
const queue = Array.from(ranges).reverse();
|
|
40724
40814
|
while (queue.length > 0) {
|
|
40725
40815
|
const range = queue.pop();
|
|
40726
|
-
visited.
|
|
40816
|
+
visited.addMany(this.encoder.encodeBoundingBox(range));
|
|
40727
40817
|
const impactedPositionIds = this.rTree.search(range).map((dep) => dep.data);
|
|
40728
40818
|
for (const positionId of impactedPositionIds) {
|
|
40729
40819
|
if (!visited.has(positionId)) {
|
|
@@ -40731,7 +40821,7 @@
|
|
|
40731
40821
|
}
|
|
40732
40822
|
}
|
|
40733
40823
|
}
|
|
40734
|
-
visited.
|
|
40824
|
+
visited.deleteMany(ranges.flatMap((r) => this.encoder.encodeBoundingBox(r)));
|
|
40735
40825
|
return visited;
|
|
40736
40826
|
}
|
|
40737
40827
|
}
|
|
@@ -40869,9 +40959,9 @@
|
|
|
40869
40959
|
const cells = positions.map((p) => this.encoder.encode(p));
|
|
40870
40960
|
const cellsToCompute = new JetSet(cells);
|
|
40871
40961
|
const arrayFormulasPositionIds = this.getArrayFormulasImpactedByChangesOf(cells);
|
|
40872
|
-
cellsToCompute.
|
|
40873
|
-
cellsToCompute.
|
|
40874
|
-
cellsToCompute.
|
|
40962
|
+
cellsToCompute.addMany(this.getCellsDependingOn(cells));
|
|
40963
|
+
cellsToCompute.addMany(arrayFormulasPositionIds);
|
|
40964
|
+
cellsToCompute.addMany(this.getCellsDependingOn(arrayFormulasPositionIds));
|
|
40875
40965
|
this.evaluate(cellsToCompute);
|
|
40876
40966
|
}
|
|
40877
40967
|
getArrayFormulasImpactedByChangesOf(positionIds) {
|
|
@@ -40885,7 +40975,7 @@
|
|
|
40885
40975
|
}
|
|
40886
40976
|
if (!content) {
|
|
40887
40977
|
// The previous content could have blocked some array formulas
|
|
40888
|
-
impactedPositionIds.
|
|
40978
|
+
impactedPositionIds.addMany(this.getArrayFormulasBlockedByOrSpreadingOn(positionId));
|
|
40889
40979
|
}
|
|
40890
40980
|
}
|
|
40891
40981
|
return impactedPositionIds;
|
|
@@ -40934,7 +41024,7 @@
|
|
|
40934
41024
|
}
|
|
40935
41025
|
const arrayFormulas = this.spreadingRelations.getFormulaPositionsSpreadingOn(positionId);
|
|
40936
41026
|
const cells = new JetSet(arrayFormulas);
|
|
40937
|
-
cells.
|
|
41027
|
+
cells.addMany(this.getCellsDependingOn(arrayFormulas));
|
|
40938
41028
|
return cells;
|
|
40939
41029
|
}
|
|
40940
41030
|
nextPositionsToUpdate = new JetSet();
|
|
@@ -41083,7 +41173,7 @@
|
|
|
41083
41173
|
this.setEvaluatedCell(positionId, evaluatedCell);
|
|
41084
41174
|
// check if formula dependencies present in the spread zone
|
|
41085
41175
|
// if so, they need to be recomputed
|
|
41086
|
-
this.nextPositionsToUpdate.
|
|
41176
|
+
this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([positionId]));
|
|
41087
41177
|
};
|
|
41088
41178
|
}
|
|
41089
41179
|
invalidateSpreading(positionId) {
|
|
@@ -41098,8 +41188,8 @@
|
|
|
41098
41188
|
continue;
|
|
41099
41189
|
}
|
|
41100
41190
|
this.evaluatedCells.delete(child);
|
|
41101
|
-
this.nextPositionsToUpdate.
|
|
41102
|
-
this.nextPositionsToUpdate.
|
|
41191
|
+
this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([child]));
|
|
41192
|
+
this.nextPositionsToUpdate.addMany(this.getArrayFormulasBlockedByOrSpreadingOn(child));
|
|
41103
41193
|
}
|
|
41104
41194
|
this.spreadingRelations.removeNode(positionId);
|
|
41105
41195
|
}
|
|
@@ -41448,7 +41538,13 @@
|
|
|
41448
41538
|
const format = newFormat
|
|
41449
41539
|
? getItemId(newFormat, data.formats)
|
|
41450
41540
|
: exportedCellData.format;
|
|
41451
|
-
|
|
41541
|
+
let content;
|
|
41542
|
+
if (formulaCell instanceof FormulaCellWithDependencies) {
|
|
41543
|
+
content = this.getters.getFormulaCellContent(exportedSheetData.id, formulaCell.compiledFormula, formulaCell.compiledFormula.dependencies, true);
|
|
41544
|
+
}
|
|
41545
|
+
else {
|
|
41546
|
+
content = !isExported ? newContent : exportedCellData.content;
|
|
41547
|
+
}
|
|
41452
41548
|
exportedSheetData.cells[xc] = { ...exportedCellData, value, isFormula, content, format };
|
|
41453
41549
|
}
|
|
41454
41550
|
}
|
|
@@ -50764,6 +50860,16 @@
|
|
|
50764
50860
|
}
|
|
50765
50861
|
}
|
|
50766
50862
|
|
|
50863
|
+
class FocusableElement {
|
|
50864
|
+
focusableElement = undefined;
|
|
50865
|
+
setFocusableElement(element) {
|
|
50866
|
+
this.focusableElement = element;
|
|
50867
|
+
}
|
|
50868
|
+
focus() {
|
|
50869
|
+
this.focusableElement?.focus();
|
|
50870
|
+
}
|
|
50871
|
+
}
|
|
50872
|
+
|
|
50767
50873
|
const RIPPLE_KEY_FRAMES = [
|
|
50768
50874
|
{ transform: "scale(0)" },
|
|
50769
50875
|
{ transform: "scale(0.8)", offset: 0.33 },
|
|
@@ -52920,6 +53026,7 @@
|
|
|
52920
53026
|
toggleSidePanel: this.toggleSidePanel.bind(this),
|
|
52921
53027
|
clipboard: this.env.clipboard || instantiateClipboard(),
|
|
52922
53028
|
startCellEdition: (content) => this.onGridComposerCellFocused(content),
|
|
53029
|
+
focusableElement: new FocusableElement(),
|
|
52923
53030
|
});
|
|
52924
53031
|
owl.useExternalListener(window, "resize", () => this.render(true));
|
|
52925
53032
|
owl.useExternalListener(window, "beforeunload", this.unbindModelEvents.bind(this));
|
|
@@ -53026,16 +53133,17 @@
|
|
|
53026
53133
|
}
|
|
53027
53134
|
this.composer.topBarFocus = "contentFocus";
|
|
53028
53135
|
this.composer.gridFocusMode = "inactive";
|
|
53029
|
-
this.setComposerContent({ selection }
|
|
53136
|
+
this.setComposerContent({ selection });
|
|
53030
53137
|
}
|
|
53031
|
-
onGridComposerContentFocused() {
|
|
53138
|
+
onGridComposerContentFocused(selection) {
|
|
53032
53139
|
if (this.model.getters.isReadonly()) {
|
|
53033
53140
|
return;
|
|
53034
53141
|
}
|
|
53035
53142
|
this.composer.topBarFocus = "inactive";
|
|
53036
53143
|
this.composer.gridFocusMode = "contentFocus";
|
|
53037
|
-
this.setComposerContent({});
|
|
53144
|
+
this.setComposerContent({ selection });
|
|
53038
53145
|
}
|
|
53146
|
+
// TODO: either both are defined or none of them. change those args to an object
|
|
53039
53147
|
onGridComposerCellFocused(content, selection) {
|
|
53040
53148
|
if (this.model.getters.isReadonly()) {
|
|
53041
53149
|
return;
|
|
@@ -54461,11 +54569,10 @@
|
|
|
54461
54569
|
* next cluster if the given cell is outside a cluster or at the border of a cluster in the given direction.
|
|
54462
54570
|
*/
|
|
54463
54571
|
getEndOfCluster(startPosition, dim, dir) {
|
|
54464
|
-
const sheet = this.getters.getActiveSheet();
|
|
54465
54572
|
let currentPosition = startPosition;
|
|
54466
54573
|
// If both the current cell and the next cell are not empty, we want to go to the end of the cluster
|
|
54467
54574
|
const nextCellPosition = this.getNextCellPosition(startPosition, dim, dir);
|
|
54468
|
-
let mode = !this.
|
|
54575
|
+
let mode = !this.isEvaluatedCellEmpty(currentPosition) && !this.isEvaluatedCellEmpty(nextCellPosition)
|
|
54469
54576
|
? "endOfCluster"
|
|
54470
54577
|
: "nextCluster";
|
|
54471
54578
|
while (true) {
|
|
@@ -54475,7 +54582,7 @@
|
|
|
54475
54582
|
currentPosition.row === nextCellPosition.row) {
|
|
54476
54583
|
break;
|
|
54477
54584
|
}
|
|
54478
|
-
const isNextCellEmpty = this.
|
|
54585
|
+
const isNextCellEmpty = this.isEvaluatedCellEmpty(nextCellPosition);
|
|
54479
54586
|
if (mode === "endOfCluster" && isNextCellEmpty) {
|
|
54480
54587
|
break;
|
|
54481
54588
|
}
|
|
@@ -54489,10 +54596,20 @@
|
|
|
54489
54596
|
return dim === "cols" ? currentPosition.col : currentPosition.row;
|
|
54490
54597
|
}
|
|
54491
54598
|
/**
|
|
54492
|
-
*
|
|
54493
|
-
* check
|
|
54599
|
+
* Checks if a cell is empty (i.e. does not have a content). If the cell is part of a merge,
|
|
54600
|
+
* the check applies to the main cell of the merge.
|
|
54601
|
+
*/
|
|
54602
|
+
isCellEmpty({ col, row }) {
|
|
54603
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
54604
|
+
const position = this.getters.getMainCellPosition({ sheetId, col, row });
|
|
54605
|
+
return !(this.getters.getCorrespondingFormulaCell(position) || this.getters.getCell(position)?.content);
|
|
54606
|
+
}
|
|
54607
|
+
/**
|
|
54608
|
+
* Checks if a cell evaluated value is empty. If the cell is part of a merge,
|
|
54609
|
+
* the check applies to the main cell of the merge.
|
|
54494
54610
|
*/
|
|
54495
|
-
|
|
54611
|
+
isEvaluatedCellEmpty({ col, row }) {
|
|
54612
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
54496
54613
|
const position = this.getters.getMainCellPosition({ sheetId, col, row });
|
|
54497
54614
|
const cell = this.getters.getEvaluatedCell(position);
|
|
54498
54615
|
return cell.type === CellValueType.empty;
|
|
@@ -56798,9 +56915,9 @@
|
|
|
56798
56915
|
exports.tokenize = tokenize;
|
|
56799
56916
|
|
|
56800
56917
|
|
|
56801
|
-
__info__.version = "17.0.
|
|
56802
|
-
__info__.date = "2024-02-
|
|
56803
|
-
__info__.hash = "
|
|
56918
|
+
__info__.version = "17.0.12";
|
|
56919
|
+
__info__.date = "2024-02-16T14:24:02.984Z";
|
|
56920
|
+
__info__.hash = "8fa2bab";
|
|
56804
56921
|
|
|
56805
56922
|
|
|
56806
56923
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|