@odoo/o-spreadsheet 17.0.9 → 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 +363 -232
- package/dist/o-spreadsheet.d.ts +39 -18
- package/dist/o-spreadsheet.esm.js +363 -232
- package/dist/o-spreadsheet.iife.js +363 -232
- package/dist/o-spreadsheet.iife.min.js +262 -268
- 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-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.0.12
|
|
6
|
+
* @date 2024-02-16T14:24:02.984Z
|
|
7
|
+
* @hash 8fa2bab
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { Component, useRef, onMounted, useEffect, onWillPatch, useState, onWillUpdateProps, onPatched, useComponent, useExternalListener, onWillUnmount, onWillStart, xml, useChildSubEnv, useSubEnv, markRaw } from '@odoo/owl';
|
|
@@ -550,8 +550,8 @@ function isObjectEmptyRecursive(argument) {
|
|
|
550
550
|
* If the given item does not exist in the dictionary, it creates one with a new id.
|
|
551
551
|
*/
|
|
552
552
|
function getItemId(item, itemsDic) {
|
|
553
|
-
for (
|
|
554
|
-
if (deepEquals(
|
|
553
|
+
for (const key in itemsDic) {
|
|
554
|
+
if (deepEquals(itemsDic[key], item)) {
|
|
555
555
|
return parseInt(key, 10);
|
|
556
556
|
}
|
|
557
557
|
}
|
|
@@ -650,11 +650,13 @@ function deepEquals(o1, o2) {
|
|
|
650
650
|
if (typeof o1 !== "object")
|
|
651
651
|
return o1 === o2;
|
|
652
652
|
// Objects can have different keys if the values are undefined
|
|
653
|
-
const
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
653
|
+
for (const key in o2) {
|
|
654
|
+
if (!(key in o1) && o2[key] !== undefined) {
|
|
655
|
+
return false;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
for (const key in o1) {
|
|
659
|
+
if (typeof o1[key] !== typeof o2[key])
|
|
658
660
|
return false;
|
|
659
661
|
if (typeof o1[key] === "object") {
|
|
660
662
|
if (!deepEquals(o1[key], o2[key]))
|
|
@@ -724,18 +726,18 @@ function isConsecutive(iterable) {
|
|
|
724
726
|
return true;
|
|
725
727
|
}
|
|
726
728
|
class JetSet extends Set {
|
|
727
|
-
|
|
729
|
+
addMany(iterable) {
|
|
728
730
|
for (const element of iterable) {
|
|
729
731
|
super.add(element);
|
|
730
732
|
}
|
|
731
733
|
return this;
|
|
732
734
|
}
|
|
733
|
-
|
|
734
|
-
let
|
|
735
|
+
deleteMany(iterable) {
|
|
736
|
+
let wasDeleted = false;
|
|
735
737
|
for (const element of iterable) {
|
|
736
|
-
|
|
738
|
+
wasDeleted ||= super.delete(element);
|
|
737
739
|
}
|
|
738
|
-
return
|
|
740
|
+
return wasDeleted;
|
|
739
741
|
}
|
|
740
742
|
}
|
|
741
743
|
/**
|
|
@@ -1994,7 +1996,7 @@ class DispatchResult {
|
|
|
1994
1996
|
* Static helper which returns a successful DispatchResult
|
|
1995
1997
|
*/
|
|
1996
1998
|
static get Success() {
|
|
1997
|
-
return
|
|
1999
|
+
return SUCCESS;
|
|
1998
2000
|
}
|
|
1999
2001
|
get isSuccessful() {
|
|
2000
2002
|
return this.reasons.length === 0;
|
|
@@ -2007,6 +2009,7 @@ class DispatchResult {
|
|
|
2007
2009
|
return this.reasons.includes(reason);
|
|
2008
2010
|
}
|
|
2009
2011
|
}
|
|
2012
|
+
const SUCCESS = new DispatchResult();
|
|
2010
2013
|
var CommandResult;
|
|
2011
2014
|
(function (CommandResult) {
|
|
2012
2015
|
CommandResult["Success"] = "Success";
|
|
@@ -2888,6 +2891,9 @@ function parseFormat(formatString) {
|
|
|
2888
2891
|
function formatValue(value, { format, locale }) {
|
|
2889
2892
|
switch (typeof value) {
|
|
2890
2893
|
case "string":
|
|
2894
|
+
if (value.includes('\\"')) {
|
|
2895
|
+
return value.replace(/\\"/g, '"');
|
|
2896
|
+
}
|
|
2891
2897
|
return value;
|
|
2892
2898
|
case "boolean":
|
|
2893
2899
|
return value ? "TRUE" : "FALSE";
|
|
@@ -4932,14 +4938,8 @@ function createDataSets(getters, dataSetsString, sheetId, dataSetsHaveTitle) {
|
|
|
4932
4938
|
: undefined));
|
|
4933
4939
|
}
|
|
4934
4940
|
}
|
|
4935
|
-
else if (zone.left === zone.right && zone.top === zone.bottom) {
|
|
4936
|
-
// A single cell. If it's only the title, the dataset is not added.
|
|
4937
|
-
if (!dataSetsHaveTitle) {
|
|
4938
|
-
dataSets.push(createDataSet(getters, dataSetSheetId, zone, undefined));
|
|
4939
|
-
}
|
|
4940
|
-
}
|
|
4941
4941
|
else {
|
|
4942
|
-
/* 1 row or 1 column */
|
|
4942
|
+
/* 1 cell, 1 row or 1 column */
|
|
4943
4943
|
dataSets.push(createDataSet(getters, dataSetSheetId, zone, dataSetsHaveTitle
|
|
4944
4944
|
? {
|
|
4945
4945
|
top: zone.top,
|
|
@@ -4988,8 +4988,10 @@ function toExcelDataset(getters, ds) {
|
|
|
4988
4988
|
}
|
|
4989
4989
|
const dataRange = ds.dataRange.clone({ zone: dataZone });
|
|
4990
4990
|
return {
|
|
4991
|
-
label: ds.labelCell
|
|
4992
|
-
|
|
4991
|
+
label: ds.labelCell
|
|
4992
|
+
? getters.getRangeString(ds.labelCell, "forceSheetReference", { useFixedReference: true })
|
|
4993
|
+
: undefined,
|
|
4994
|
+
range: getters.getRangeString(dataRange, "forceSheetReference", { useFixedReference: true }),
|
|
4993
4995
|
};
|
|
4994
4996
|
}
|
|
4995
4997
|
function toExcelLabelRange(getters, labelRange, shouldRemoveFirstLabel) {
|
|
@@ -5002,7 +5004,7 @@ function toExcelLabelRange(getters, labelRange, shouldRemoveFirstLabel) {
|
|
|
5002
5004
|
zone.top = zone.top + 1;
|
|
5003
5005
|
}
|
|
5004
5006
|
const range = labelRange.clone({ zone });
|
|
5005
|
-
return getters.getRangeString(range, "forceSheetReference");
|
|
5007
|
+
return getters.getRangeString(range, "forceSheetReference", { useFixedReference: true });
|
|
5006
5008
|
}
|
|
5007
5009
|
/**
|
|
5008
5010
|
* Transform a chart definition which supports dataSets (dataSets and LabelRange)
|
|
@@ -7383,7 +7385,7 @@ function tokenize(str, locale = DEFAULT_LOCALE) {
|
|
|
7383
7385
|
while (!chars.isOver()) {
|
|
7384
7386
|
let token = tokenizeSpace(chars) ||
|
|
7385
7387
|
tokenizeArgsSeparator(chars, locale) ||
|
|
7386
|
-
|
|
7388
|
+
tokenizeParenthesis(chars) ||
|
|
7387
7389
|
tokenizeOperator(chars) ||
|
|
7388
7390
|
tokenizeString(chars) ||
|
|
7389
7391
|
tokenizeDebugger(chars) ||
|
|
@@ -7404,15 +7406,14 @@ function tokenizeDebugger(chars) {
|
|
|
7404
7406
|
}
|
|
7405
7407
|
return null;
|
|
7406
7408
|
}
|
|
7407
|
-
const
|
|
7408
|
-
"(": "LEFT_PAREN",
|
|
7409
|
-
")": "RIGHT_PAREN",
|
|
7409
|
+
const parenthesis = {
|
|
7410
|
+
"(": { type: "LEFT_PAREN", value: "(" },
|
|
7411
|
+
")": { type: "RIGHT_PAREN", value: ")" },
|
|
7410
7412
|
};
|
|
7411
|
-
function
|
|
7412
|
-
if (chars.current
|
|
7413
|
+
function tokenizeParenthesis(chars) {
|
|
7414
|
+
if (chars.current === "(" || chars.current === ")") {
|
|
7413
7415
|
const value = chars.shift();
|
|
7414
|
-
|
|
7415
|
-
return { type, value };
|
|
7416
|
+
return parenthesis[value];
|
|
7416
7417
|
}
|
|
7417
7418
|
return null;
|
|
7418
7419
|
}
|
|
@@ -7433,7 +7434,12 @@ function tokenizeOperator(chars) {
|
|
|
7433
7434
|
}
|
|
7434
7435
|
return null;
|
|
7435
7436
|
}
|
|
7437
|
+
const FIRST_POSSIBLE_NUMBER_CHARS = new Set("0123456789");
|
|
7436
7438
|
function tokenizeNumber(chars, locale) {
|
|
7439
|
+
if (!FIRST_POSSIBLE_NUMBER_CHARS.has(chars.current) &&
|
|
7440
|
+
chars.current !== locale.decimalSeparator) {
|
|
7441
|
+
return null;
|
|
7442
|
+
}
|
|
7437
7443
|
const match = chars.remaining().match(getFormulaNumberRegex(locale.decimalSeparator));
|
|
7438
7444
|
if (match) {
|
|
7439
7445
|
chars.advanceBy(match[0].length);
|
|
@@ -7458,7 +7464,7 @@ function tokenizeString(chars) {
|
|
|
7458
7464
|
}
|
|
7459
7465
|
return null;
|
|
7460
7466
|
}
|
|
7461
|
-
const separatorRegexp =
|
|
7467
|
+
const separatorRegexp = /^[\w\.!\$]+/;
|
|
7462
7468
|
/**
|
|
7463
7469
|
* A "Symbol" is just basically any word-like element that can appear in a
|
|
7464
7470
|
* formula, which is not a string. So:
|
|
@@ -7498,8 +7504,11 @@ function tokenizeSymbol(chars) {
|
|
|
7498
7504
|
};
|
|
7499
7505
|
}
|
|
7500
7506
|
}
|
|
7501
|
-
|
|
7502
|
-
|
|
7507
|
+
const match = chars.remaining().match(separatorRegexp);
|
|
7508
|
+
if (match) {
|
|
7509
|
+
const value = match[0];
|
|
7510
|
+
result += value;
|
|
7511
|
+
chars.advanceBy(value.length);
|
|
7503
7512
|
}
|
|
7504
7513
|
if (result.length) {
|
|
7505
7514
|
const value = result;
|
|
@@ -7561,7 +7570,10 @@ class TokenizingChars {
|
|
|
7561
7570
|
return this.text.substring(this.currentIndex);
|
|
7562
7571
|
}
|
|
7563
7572
|
currentStartsWith(str) {
|
|
7564
|
-
|
|
7573
|
+
if (this.current !== str[0]) {
|
|
7574
|
+
return false;
|
|
7575
|
+
}
|
|
7576
|
+
for (let j = 1; j < str.length; j++) {
|
|
7565
7577
|
if (this.text[this.currentIndex + j] !== str[j]) {
|
|
7566
7578
|
return false;
|
|
7567
7579
|
}
|
|
@@ -7588,6 +7600,9 @@ function isValidLocale(locale) {
|
|
|
7588
7600
|
if (locale.formulaArgSeparator === locale.decimalSeparator) {
|
|
7589
7601
|
return false;
|
|
7590
7602
|
}
|
|
7603
|
+
if (locale.thousandsSeparator === locale.decimalSeparator) {
|
|
7604
|
+
return false;
|
|
7605
|
+
}
|
|
7591
7606
|
try {
|
|
7592
7607
|
formatValue(1, { locale, format: "#,##0.00" });
|
|
7593
7608
|
formatValue(1, { locale, format: locale.dateFormat });
|
|
@@ -7678,7 +7693,7 @@ function canonicalizeNumberLiteral(content, locale) {
|
|
|
7678
7693
|
if (locale.decimalSeparator === "." || !isNumber(content, locale)) {
|
|
7679
7694
|
return content;
|
|
7680
7695
|
}
|
|
7681
|
-
return content.replace(locale.decimalSeparator, ".");
|
|
7696
|
+
return content.replace(locale.thousandsSeparator, "").replace(locale.decimalSeparator, ".");
|
|
7682
7697
|
}
|
|
7683
7698
|
/**
|
|
7684
7699
|
* Change a content string from the given locale to its canonical form (en_US locale). Also convert date string.
|
|
@@ -8592,7 +8607,7 @@ class BarChart extends AbstractChart {
|
|
|
8592
8607
|
return undefined;
|
|
8593
8608
|
const dataSets = this.dataSets
|
|
8594
8609
|
.map((ds) => toExcelDataset(this.getters, ds))
|
|
8595
|
-
.filter((ds) => ds.range !== ""
|
|
8610
|
+
.filter((ds) => ds.range !== "" && ds.range !== INCORRECT_RANGE_STRING);
|
|
8596
8611
|
const labelRange = toExcelLabelRange(this.getters, this.labelRange, shouldRemoveFirstLabel(this.labelRange, this.dataSets[0], this.dataSetsHaveTitle));
|
|
8597
8612
|
return {
|
|
8598
8613
|
...this.getDefinition(),
|
|
@@ -9170,7 +9185,7 @@ class LineChart extends AbstractChart {
|
|
|
9170
9185
|
return undefined;
|
|
9171
9186
|
const dataSets = this.dataSets
|
|
9172
9187
|
.map((ds) => toExcelDataset(this.getters, ds))
|
|
9173
|
-
.filter((ds) => ds.range !== ""
|
|
9188
|
+
.filter((ds) => ds.range !== "" && ds.range !== INCORRECT_RANGE_STRING);
|
|
9174
9189
|
const labelRange = toExcelLabelRange(this.getters, this.labelRange, shouldRemoveFirstLabel(this.labelRange, this.dataSets[0], this.dataSetsHaveTitle));
|
|
9175
9190
|
return {
|
|
9176
9191
|
...this.getDefinition(),
|
|
@@ -9476,7 +9491,7 @@ class PieChart extends AbstractChart {
|
|
|
9476
9491
|
return undefined;
|
|
9477
9492
|
const dataSets = this.dataSets
|
|
9478
9493
|
.map((ds) => toExcelDataset(this.getters, ds))
|
|
9479
|
-
.filter((ds) => ds.range !== ""
|
|
9494
|
+
.filter((ds) => ds.range !== "" && ds.range !== INCORRECT_RANGE_STRING);
|
|
9480
9495
|
const labelRange = toExcelLabelRange(this.getters, this.labelRange, shouldRemoveFirstLabel(this.labelRange, this.dataSets[0], this.dataSetsHaveTitle));
|
|
9481
9496
|
return {
|
|
9482
9497
|
...this.getDefinition(),
|
|
@@ -10750,6 +10765,12 @@ const INSERT_LINK = (env) => {
|
|
|
10750
10765
|
let { col, row } = env.model.getters.getActivePosition();
|
|
10751
10766
|
env.model.dispatch("OPEN_CELL_POPOVER", { col, row, popoverType: "LinkEditor" });
|
|
10752
10767
|
};
|
|
10768
|
+
const INSERT_LINK_NAME = (env) => {
|
|
10769
|
+
const sheetId = env.model.getters.getActiveSheetId();
|
|
10770
|
+
const { col, row } = env.model.getters.getActivePosition();
|
|
10771
|
+
const cell = env.model.getters.getEvaluatedCell({ sheetId, col, row });
|
|
10772
|
+
return cell && cell.link ? _t("Edit link") : _t("Insert link");
|
|
10773
|
+
};
|
|
10753
10774
|
//------------------------------------------------------------------------------
|
|
10754
10775
|
// Filters action
|
|
10755
10776
|
//------------------------------------------------------------------------------
|
|
@@ -19781,7 +19802,7 @@ cellMenuRegistry
|
|
|
19781
19802
|
})
|
|
19782
19803
|
.add("insert_link", {
|
|
19783
19804
|
...insertLink,
|
|
19784
|
-
name:
|
|
19805
|
+
name: INSERT_LINK_NAME,
|
|
19785
19806
|
sequence: 150,
|
|
19786
19807
|
separator: true,
|
|
19787
19808
|
});
|
|
@@ -19919,19 +19940,20 @@ const formatNumberPercent = createFormatActionSpec({
|
|
|
19919
19940
|
const formatNumberCurrency = createFormatActionSpec({
|
|
19920
19941
|
name: _t("Currency"),
|
|
19921
19942
|
descriptionValue: 1000.12,
|
|
19922
|
-
format: (env) => env.model.config.defaultCurrencyFormat,
|
|
19943
|
+
format: (env) => env.model.config.defaultCurrencyFormat ?? DEFAULT_CURRENCY_FORMAT,
|
|
19923
19944
|
});
|
|
19924
19945
|
const formatNumberCurrencyRounded = {
|
|
19925
19946
|
...createFormatActionSpec({
|
|
19926
19947
|
name: _t("Currency rounded"),
|
|
19927
19948
|
descriptionValue: 1000,
|
|
19928
|
-
format: (env) => roundFormat(env.model.config.defaultCurrencyFormat),
|
|
19949
|
+
format: (env) => roundFormat(env.model.config.defaultCurrencyFormat ?? DEFAULT_CURRENCY_FORMAT),
|
|
19929
19950
|
}),
|
|
19930
19951
|
isVisible: (env) => {
|
|
19931
19952
|
const currencyFormat = env.model.config.defaultCurrencyFormat;
|
|
19932
|
-
return currencyFormat !== roundFormat(currencyFormat);
|
|
19953
|
+
return currencyFormat !== roundFormat(currencyFormat ?? DEFAULT_CURRENCY_FORMAT);
|
|
19933
19954
|
},
|
|
19934
19955
|
};
|
|
19956
|
+
const DEFAULT_CURRENCY_FORMAT = "[$$]#,##0.00";
|
|
19935
19957
|
const EXAMPLE_DATE = parseLiteral("2023/09/26 10:43:00 PM", DEFAULT_LOCALE);
|
|
19936
19958
|
const formatCustomCurrency = {
|
|
19937
19959
|
name: _t("Custom currency"),
|
|
@@ -26033,6 +26055,17 @@ css /* scss */ `
|
|
|
26033
26055
|
`;
|
|
26034
26056
|
class TextValueProvider extends Component {
|
|
26035
26057
|
static template = "o-spreadsheet-TextValueProvider";
|
|
26058
|
+
autoCompleteListRef = useRef("autoCompleteList");
|
|
26059
|
+
setup() {
|
|
26060
|
+
useEffect(() => {
|
|
26061
|
+
const selectedIndex = this.props.selectedIndex;
|
|
26062
|
+
if (selectedIndex === undefined) {
|
|
26063
|
+
return;
|
|
26064
|
+
}
|
|
26065
|
+
const selectedElement = this.autoCompleteListRef.el?.children[selectedIndex];
|
|
26066
|
+
selectedElement?.scrollIntoView?.({ block: "nearest" });
|
|
26067
|
+
}, () => [this.props.selectedIndex, this.autoCompleteListRef.el]);
|
|
26068
|
+
}
|
|
26036
26069
|
}
|
|
26037
26070
|
TextValueProvider.props = {
|
|
26038
26071
|
values: Array,
|
|
@@ -26484,6 +26517,7 @@ css /* scss */ `
|
|
|
26484
26517
|
position: absolute;
|
|
26485
26518
|
margin: 1px 4px;
|
|
26486
26519
|
pointer-events: none;
|
|
26520
|
+
overflow: auto;
|
|
26487
26521
|
|
|
26488
26522
|
.o-semi-bold {
|
|
26489
26523
|
/** FIXME: to remove in favor of Bootstrap
|
|
@@ -26499,6 +26533,7 @@ class Composer extends Component {
|
|
|
26499
26533
|
static components = { TextValueProvider, FunctionDescriptionProvider };
|
|
26500
26534
|
static defaultProps = {
|
|
26501
26535
|
inputStyle: "",
|
|
26536
|
+
isDefaultFocus: false,
|
|
26502
26537
|
};
|
|
26503
26538
|
composerRef = useRef("o_composer");
|
|
26504
26539
|
contentHelper = new ContentEditableHelper(this.composerRef.el);
|
|
@@ -26529,7 +26564,10 @@ class Composer extends Component {
|
|
|
26529
26564
|
if (this.props.delimitation && this.props.rect) {
|
|
26530
26565
|
const { x: cellX, y: cellY, height: cellHeight } = this.props.rect;
|
|
26531
26566
|
const remainingHeight = this.props.delimitation.height - (cellY + cellHeight);
|
|
26567
|
+
assistantStyle["max-height"] = `${remainingHeight}px`;
|
|
26532
26568
|
if (cellY > remainingHeight) {
|
|
26569
|
+
const availableSpaceAbove = cellY;
|
|
26570
|
+
assistantStyle["max-height"] = `${availableSpaceAbove}px`;
|
|
26533
26571
|
// render top
|
|
26534
26572
|
// We compensate 2 px of margin on the assistant style + 1px for design reasons
|
|
26535
26573
|
assistantStyle.top = `-3px`;
|
|
@@ -26555,7 +26593,6 @@ class Composer extends Component {
|
|
|
26555
26593
|
F2: () => console.warn("Not implemented"),
|
|
26556
26594
|
F4: this.processF4Key,
|
|
26557
26595
|
Tab: (ev) => this.processTabKey(ev),
|
|
26558
|
-
" ": (ev) => this.processSpaceKey(ev),
|
|
26559
26596
|
};
|
|
26560
26597
|
keyCodeMapping = {
|
|
26561
26598
|
NumpadDecimal: this.processNumpadDecimal,
|
|
@@ -26563,12 +26600,12 @@ class Composer extends Component {
|
|
|
26563
26600
|
setup() {
|
|
26564
26601
|
onMounted(() => {
|
|
26565
26602
|
const el = this.composerRef.el;
|
|
26603
|
+
if (this.props.isDefaultFocus) {
|
|
26604
|
+
this.env.focusableElement.setFocusableElement(el);
|
|
26605
|
+
}
|
|
26566
26606
|
this.contentHelper.updateEl(el);
|
|
26567
26607
|
this.processTokenAtCursor();
|
|
26568
26608
|
});
|
|
26569
|
-
onWillUnmount(() => {
|
|
26570
|
-
this.props.onComposerUnmounted?.();
|
|
26571
|
-
});
|
|
26572
26609
|
useEffect(() => {
|
|
26573
26610
|
this.processContent();
|
|
26574
26611
|
});
|
|
@@ -26577,7 +26614,8 @@ class Composer extends Component {
|
|
|
26577
26614
|
// Handlers
|
|
26578
26615
|
// ---------------------------------------------------------------------------
|
|
26579
26616
|
processArrowKeys(ev) {
|
|
26580
|
-
if (this.env.model.getters.isSelectingForComposer()
|
|
26617
|
+
if (this.env.model.getters.isSelectingForComposer() ||
|
|
26618
|
+
this.env.model.getters.getEditionMode() === "inactive") {
|
|
26581
26619
|
this.functionDescriptionState.showDescription = false;
|
|
26582
26620
|
// Prevent the default content editable behavior which moves the cursor
|
|
26583
26621
|
ev.preventDefault();
|
|
@@ -26620,26 +26658,20 @@ class Composer extends Component {
|
|
|
26620
26658
|
processTabKey(ev) {
|
|
26621
26659
|
ev.preventDefault();
|
|
26622
26660
|
ev.stopPropagation();
|
|
26623
|
-
|
|
26624
|
-
|
|
26625
|
-
|
|
26626
|
-
|
|
26627
|
-
|
|
26628
|
-
|
|
26661
|
+
if (this.env.model.getters.getEditionMode() !== "inactive") {
|
|
26662
|
+
const state = this.autoCompleteState;
|
|
26663
|
+
if (state.showProvider && state.selectedIndex !== undefined) {
|
|
26664
|
+
const autoCompleteValue = this.autoCompleteState.values[state.selectedIndex]?.text;
|
|
26665
|
+
if (autoCompleteValue) {
|
|
26666
|
+
this.autoComplete(autoCompleteValue);
|
|
26667
|
+
return;
|
|
26668
|
+
}
|
|
26629
26669
|
}
|
|
26670
|
+
interactiveStopEdition(this.env);
|
|
26630
26671
|
}
|
|
26631
26672
|
const direction = ev.shiftKey ? "left" : "right";
|
|
26632
|
-
interactiveStopEdition(this.env);
|
|
26633
26673
|
this.env.model.selection.moveAnchorCell(direction, 1);
|
|
26634
26674
|
}
|
|
26635
|
-
processSpaceKey(ev) {
|
|
26636
|
-
if (ev.ctrlKey) {
|
|
26637
|
-
ev.preventDefault();
|
|
26638
|
-
ev.stopPropagation();
|
|
26639
|
-
this.showFunctionAutocomplete("");
|
|
26640
|
-
this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
|
|
26641
|
-
}
|
|
26642
|
-
}
|
|
26643
26675
|
processEnterKey(ev) {
|
|
26644
26676
|
ev.preventDefault();
|
|
26645
26677
|
ev.stopPropagation();
|
|
@@ -26692,6 +26724,9 @@ class Composer extends Component {
|
|
|
26692
26724
|
this.compositionActive = false;
|
|
26693
26725
|
}
|
|
26694
26726
|
onKeydown(ev) {
|
|
26727
|
+
if (this.env.model.getters.getEditionMode() === "inactive") {
|
|
26728
|
+
return;
|
|
26729
|
+
}
|
|
26695
26730
|
let handler = this.keyMapping[ev.key] || this.keyCodeMapping[ev.code];
|
|
26696
26731
|
if (handler) {
|
|
26697
26732
|
handler.call(this, ev);
|
|
@@ -26700,14 +26735,33 @@ class Composer extends Component {
|
|
|
26700
26735
|
ev.stopPropagation();
|
|
26701
26736
|
}
|
|
26702
26737
|
}
|
|
26738
|
+
onPaste(ev) {
|
|
26739
|
+
if (this.env.model.getters.getEditionMode() !== "inactive") {
|
|
26740
|
+
ev.stopPropagation();
|
|
26741
|
+
}
|
|
26742
|
+
}
|
|
26703
26743
|
/*
|
|
26704
26744
|
* Triggered automatically by the content-editable between the keydown and key up
|
|
26705
26745
|
* */
|
|
26706
26746
|
onInput(ev) {
|
|
26707
|
-
if (
|
|
26747
|
+
if (!this.shouldProcessInputEvents) {
|
|
26748
|
+
return;
|
|
26749
|
+
}
|
|
26750
|
+
if (ev.inputType === "insertFromPaste" &&
|
|
26751
|
+
this.env.model.getters.getEditionMode() === "inactive") {
|
|
26708
26752
|
return;
|
|
26709
26753
|
}
|
|
26710
|
-
|
|
26754
|
+
ev.stopPropagation();
|
|
26755
|
+
let content;
|
|
26756
|
+
if (this.env.model.getters.getEditionMode() === "inactive") {
|
|
26757
|
+
content = ev.data || "";
|
|
26758
|
+
}
|
|
26759
|
+
else {
|
|
26760
|
+
content = this.contentHelper.getText();
|
|
26761
|
+
}
|
|
26762
|
+
if (this.props.focus === "inactive") {
|
|
26763
|
+
return this.props.onComposerCellFocused?.(content);
|
|
26764
|
+
}
|
|
26711
26765
|
let selection = this.contentHelper.getCurrentSelection();
|
|
26712
26766
|
if (ev.inputType === "insertParagraph") {
|
|
26713
26767
|
const start = Math.min(selection.start, selection.end);
|
|
@@ -26789,9 +26843,8 @@ class Composer extends Component {
|
|
|
26789
26843
|
}
|
|
26790
26844
|
const newSelection = this.contentHelper.getCurrentSelection();
|
|
26791
26845
|
this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
|
|
26792
|
-
|
|
26793
|
-
|
|
26794
|
-
}
|
|
26846
|
+
this.props.onComposerContentFocused();
|
|
26847
|
+
if (this.props.focus === "inactive") ;
|
|
26795
26848
|
this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", newSelection);
|
|
26796
26849
|
this.processTokenAtCursor();
|
|
26797
26850
|
}
|
|
@@ -26958,7 +27011,7 @@ class Composer extends Component {
|
|
|
26958
27011
|
const highlights = this.env.model.getters.getHighlights();
|
|
26959
27012
|
const refSheet = sheetName
|
|
26960
27013
|
? this.env.model.getters.getSheetIdByName(sheetName)
|
|
26961
|
-
: this.env.model.getters.getCurrentEditedCell()
|
|
27014
|
+
: this.env.model.getters.getCurrentEditedCell()?.sheetId;
|
|
26962
27015
|
const highlight = highlights.find((highlight) => {
|
|
26963
27016
|
if (highlight.sheetId !== refSheet)
|
|
26964
27017
|
return false;
|
|
@@ -27051,12 +27104,13 @@ class Composer extends Component {
|
|
|
27051
27104
|
}
|
|
27052
27105
|
}
|
|
27053
27106
|
Composer.props = {
|
|
27054
|
-
focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
|
|
27055
|
-
onComposerContentFocused: Function,
|
|
27056
27107
|
inputStyle: { type: String, optional: true },
|
|
27057
27108
|
rect: { type: Object, optional: true },
|
|
27058
27109
|
delimitation: { type: Object, optional: true },
|
|
27059
|
-
|
|
27110
|
+
focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
|
|
27111
|
+
onComposerCellFocused: { type: Function, optional: true },
|
|
27112
|
+
onComposerContentFocused: Function,
|
|
27113
|
+
isDefaultFocus: { type: Boolean, optional: true },
|
|
27060
27114
|
};
|
|
27061
27115
|
|
|
27062
27116
|
const COMPOSER_BORDER_WIDTH = 3 * 0.4 * window.devicePixelRatio || 1;
|
|
@@ -27090,51 +27144,25 @@ css /* scss */ `
|
|
|
27090
27144
|
class GridComposer extends Component {
|
|
27091
27145
|
static template = "o-spreadsheet-GridComposer";
|
|
27092
27146
|
static components = { Composer };
|
|
27093
|
-
|
|
27094
|
-
|
|
27095
|
-
rect;
|
|
27147
|
+
rect = this.defaultRect;
|
|
27148
|
+
isEditing = false;
|
|
27096
27149
|
isCellReferenceVisible;
|
|
27097
|
-
|
|
27150
|
+
get defaultRect() {
|
|
27151
|
+
return { x: 0, y: 0, width: 0, height: 0 };
|
|
27152
|
+
}
|
|
27098
27153
|
setup() {
|
|
27099
|
-
this.gridComposerRef = useRef("gridComposer");
|
|
27100
|
-
this.composerState = useState({
|
|
27101
|
-
rect: undefined,
|
|
27102
|
-
delimitation: undefined,
|
|
27103
|
-
});
|
|
27104
|
-
const { sheetId, col, row } = this.env.model.getters.getActivePosition();
|
|
27105
|
-
this.zone = this.env.model.getters.expandZone(sheetId, positionToZone({ col, row }));
|
|
27106
|
-
this.rect = this.env.model.getters.getVisibleRect(this.zone);
|
|
27107
|
-
this.isCellReferenceVisible = false;
|
|
27108
|
-
onMounted(() => {
|
|
27109
|
-
const el = this.gridComposerRef.el;
|
|
27110
|
-
this.composerState.rect = {
|
|
27111
|
-
x: this.rect.x,
|
|
27112
|
-
y: this.rect.y,
|
|
27113
|
-
width: el.clientWidth,
|
|
27114
|
-
height: el.clientHeight,
|
|
27115
|
-
};
|
|
27116
|
-
this.composerState.delimitation = {
|
|
27117
|
-
width: this.props.gridDims.width,
|
|
27118
|
-
height: this.props.gridDims.height,
|
|
27119
|
-
};
|
|
27120
|
-
});
|
|
27121
27154
|
onWillUpdateProps(() => {
|
|
27122
|
-
|
|
27123
|
-
|
|
27124
|
-
}
|
|
27125
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
27126
|
-
const zone = this.env.model.getters.getSelectedZone();
|
|
27127
|
-
const rect = this.env.model.getters.getVisibleRect(zone);
|
|
27128
|
-
if (!deepEquals(rect, this.rect) ||
|
|
27129
|
-
sheetId !== this.env.model.getters.getCurrentEditedCell().sheetId) {
|
|
27130
|
-
this.isCellReferenceVisible = true;
|
|
27131
|
-
}
|
|
27155
|
+
this.updateComponentPosition();
|
|
27156
|
+
this.updateCellReferenceVisibility();
|
|
27132
27157
|
});
|
|
27133
27158
|
}
|
|
27134
27159
|
get shouldDisplayCellReference() {
|
|
27135
27160
|
return this.isCellReferenceVisible;
|
|
27136
27161
|
}
|
|
27137
27162
|
get cellReference() {
|
|
27163
|
+
if (!this.env.model.getters.getCurrentEditedCell()) {
|
|
27164
|
+
return "";
|
|
27165
|
+
}
|
|
27138
27166
|
const { col, row, sheetId } = this.env.model.getters.getCurrentEditedCell();
|
|
27139
27167
|
const prefixSheet = sheetId !== this.env.model.getters.getActiveSheetId();
|
|
27140
27168
|
return `${prefixSheet ? getCanonicalSheetName(this.env.model.getters.getSheetName(sheetId)) + "!" : ""}${toXC(col, row)}`;
|
|
@@ -27146,7 +27174,27 @@ class GridComposer extends Component {
|
|
|
27146
27174
|
top: `${top - GRID_CELL_REFERENCE_TOP_OFFSET}px`,
|
|
27147
27175
|
});
|
|
27148
27176
|
}
|
|
27177
|
+
get composerProps() {
|
|
27178
|
+
const { width, height } = this.env.model.getters.getSheetViewDimensionWithHeaders();
|
|
27179
|
+
return {
|
|
27180
|
+
rect: { ...this.rect },
|
|
27181
|
+
delimitation: {
|
|
27182
|
+
width,
|
|
27183
|
+
height,
|
|
27184
|
+
},
|
|
27185
|
+
focus: this.props.focus,
|
|
27186
|
+
isDefaultFocus: true,
|
|
27187
|
+
onComposerContentFocused: this.props.onComposerContentFocused,
|
|
27188
|
+
onComposerCellFocused: this.props.onComposerCellFocused,
|
|
27189
|
+
};
|
|
27190
|
+
}
|
|
27149
27191
|
get containerStyle() {
|
|
27192
|
+
if (this.env.model.getters.getEditionMode() === "inactive" || !this.rect) {
|
|
27193
|
+
return `
|
|
27194
|
+
position: absolute;
|
|
27195
|
+
z-index: -1000;
|
|
27196
|
+
`;
|
|
27197
|
+
}
|
|
27150
27198
|
const isFormula = this.env.model.getters.getCurrentContent().startsWith("=");
|
|
27151
27199
|
const cell = this.env.model.getters.getActiveCell();
|
|
27152
27200
|
const position = this.env.model.getters.getActivePosition();
|
|
@@ -27166,6 +27214,8 @@ class GridComposer extends Component {
|
|
|
27166
27214
|
if (!isFormula) {
|
|
27167
27215
|
textAlign = style.align || cell.defaultAlign;
|
|
27168
27216
|
}
|
|
27217
|
+
const maxHeight = this.props.gridDims.height - this.rect.y;
|
|
27218
|
+
const maxWidth = this.props.gridDims.width - this.rect.x;
|
|
27169
27219
|
/**
|
|
27170
27220
|
* min-size is on the container, not the composer element, because we want to have the same size as the cell by default,
|
|
27171
27221
|
* including all the paddings/margins of the composer
|
|
@@ -27177,6 +27227,8 @@ class GridComposer extends Component {
|
|
|
27177
27227
|
top: `${top}px`,
|
|
27178
27228
|
"min-width": `${width + 1}px`,
|
|
27179
27229
|
"min-height": `${height + 1}px`,
|
|
27230
|
+
"max-width": `${maxWidth}px`,
|
|
27231
|
+
"max-height": `${maxHeight}px`,
|
|
27180
27232
|
background,
|
|
27181
27233
|
color,
|
|
27182
27234
|
"font-size": `${fontSizeInPixels(fontSize)}px`,
|
|
@@ -27186,20 +27238,38 @@ class GridComposer extends Component {
|
|
|
27186
27238
|
"text-align": textAlign,
|
|
27187
27239
|
});
|
|
27188
27240
|
}
|
|
27189
|
-
|
|
27190
|
-
const
|
|
27191
|
-
|
|
27192
|
-
|
|
27193
|
-
|
|
27194
|
-
|
|
27195
|
-
|
|
27241
|
+
updateComponentPosition() {
|
|
27242
|
+
const isEditing = this.env.model.getters.getEditionMode() !== "inactive";
|
|
27243
|
+
if (this.isEditing !== isEditing) {
|
|
27244
|
+
this.isEditing = isEditing;
|
|
27245
|
+
if (!isEditing) {
|
|
27246
|
+
this.rect = this.defaultRect;
|
|
27247
|
+
this.env.focusableElement.focus();
|
|
27248
|
+
return;
|
|
27249
|
+
}
|
|
27250
|
+
const position = this.env.model.getters.getActivePosition();
|
|
27251
|
+
const zone = this.env.model.getters.expandZone(position.sheetId, positionToZone(position));
|
|
27252
|
+
this.rect = this.env.model.getters.getVisibleRect(zone);
|
|
27253
|
+
}
|
|
27254
|
+
}
|
|
27255
|
+
updateCellReferenceVisibility() {
|
|
27256
|
+
if (this.isCellReferenceVisible || this.env.model.getters.getEditionMode() === "inactive") {
|
|
27257
|
+
return;
|
|
27258
|
+
}
|
|
27259
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
27260
|
+
const zone = this.env.model.getters.getSelectedZone();
|
|
27261
|
+
const rect = this.env.model.getters.getVisibleRect(zone);
|
|
27262
|
+
if (!deepEquals(rect, this.rect) ||
|
|
27263
|
+
sheetId !== this.env.model.getters.getCurrentEditedCell().sheetId) {
|
|
27264
|
+
this.isCellReferenceVisible = true;
|
|
27265
|
+
}
|
|
27196
27266
|
}
|
|
27197
27267
|
}
|
|
27198
27268
|
GridComposer.props = {
|
|
27199
27269
|
focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
|
|
27200
|
-
onComposerUnmounted: Function,
|
|
27201
27270
|
onComposerContentFocused: Function,
|
|
27202
27271
|
gridDims: Object,
|
|
27272
|
+
onComposerCellFocused: Function,
|
|
27203
27273
|
};
|
|
27204
27274
|
|
|
27205
27275
|
const CSS$1 = css /* scss */ `
|
|
@@ -28290,7 +28360,6 @@ class GridOverlay extends Component {
|
|
|
28290
28360
|
this.props.onCellDoubleClicked(col, row);
|
|
28291
28361
|
}
|
|
28292
28362
|
onContextMenu(ev) {
|
|
28293
|
-
ev.preventDefault();
|
|
28294
28363
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
28295
28364
|
this.props.onCellRightClicked(col, row, { x: ev.clientX, y: ev.clientY });
|
|
28296
28365
|
}
|
|
@@ -29351,6 +29420,7 @@ const registries$1 = {
|
|
|
29351
29420
|
GROUP_HEADERS: groupHeadersMenuRegistry,
|
|
29352
29421
|
UNGROUP_HEADERS: unGroupHeadersMenuRegistry,
|
|
29353
29422
|
};
|
|
29423
|
+
const MODIFIER_KEYS = ["Shift", "Control", "Alt", "Meta"];
|
|
29354
29424
|
// -----------------------------------------------------------------------------
|
|
29355
29425
|
// JS
|
|
29356
29426
|
// -----------------------------------------------------------------------------
|
|
@@ -29374,7 +29444,6 @@ class Grid extends Component {
|
|
|
29374
29444
|
HEADER_WIDTH = HEADER_WIDTH;
|
|
29375
29445
|
menuState;
|
|
29376
29446
|
gridRef;
|
|
29377
|
-
hiddenInput;
|
|
29378
29447
|
onMouseWheel;
|
|
29379
29448
|
canvasPosition;
|
|
29380
29449
|
hoveredCell;
|
|
@@ -29385,17 +29454,16 @@ class Grid extends Component {
|
|
|
29385
29454
|
menuItems: [],
|
|
29386
29455
|
});
|
|
29387
29456
|
this.gridRef = useRef("grid");
|
|
29388
|
-
this.hiddenInput = useRef("hiddenInput");
|
|
29389
29457
|
this.canvasPosition = useAbsoluteBoundingRect(this.gridRef);
|
|
29390
29458
|
this.hoveredCell = useState({ col: undefined, row: undefined });
|
|
29391
29459
|
useChildSubEnv({ getPopoverContainerRect: () => this.getGridRect() });
|
|
29392
29460
|
useExternalListener(document.body, "cut", this.copy.bind(this, true));
|
|
29393
29461
|
useExternalListener(document.body, "copy", this.copy.bind(this, false));
|
|
29394
29462
|
useExternalListener(document.body, "paste", this.paste);
|
|
29395
|
-
onMounted(() => this.
|
|
29396
|
-
this.props.exposeFocus(() => this.
|
|
29463
|
+
onMounted(() => this.focusDefaultElement());
|
|
29464
|
+
this.props.exposeFocus(() => this.focusDefaultElement());
|
|
29397
29465
|
useGridDrawing("canvas", this.env.model, () => this.env.model.getters.getSheetViewDimensionWithHeaders());
|
|
29398
|
-
useEffect(() => this.
|
|
29466
|
+
useEffect(() => this.focusDefaultElement(), () => [this.env.model.getters.getActiveSheetId()]);
|
|
29399
29467
|
this.onMouseWheel = useWheelHandler((deltaX, deltaY) => {
|
|
29400
29468
|
this.moveCanvas(deltaX, deltaY);
|
|
29401
29469
|
this.hoveredCell.col = undefined;
|
|
@@ -29418,7 +29486,7 @@ class Grid extends Component {
|
|
|
29418
29486
|
if (this.env.model.getters.hasOpenedPopover()) {
|
|
29419
29487
|
this.closeOpenedPopover();
|
|
29420
29488
|
}
|
|
29421
|
-
this.
|
|
29489
|
+
this.focusDefaultElement();
|
|
29422
29490
|
}
|
|
29423
29491
|
// this map will handle most of the actions that should happen on key down. The arrow keys are managed in the key
|
|
29424
29492
|
// down itself
|
|
@@ -29597,10 +29665,10 @@ class Grid extends Component {
|
|
|
29597
29665
|
"ALT+SHIFT+ARROWUP": () => this.processHeaderGroupingKey("up"),
|
|
29598
29666
|
"ALT+SHIFT+ARROWDOWN": () => this.processHeaderGroupingKey("down"),
|
|
29599
29667
|
};
|
|
29600
|
-
|
|
29668
|
+
focusDefaultElement() {
|
|
29601
29669
|
if (!this.env.model.getters.getSelectedFigureId() &&
|
|
29602
29670
|
this.env.model.getters.getEditionMode() === "inactive") {
|
|
29603
|
-
this.
|
|
29671
|
+
this.env.focusableElement.focus();
|
|
29604
29672
|
}
|
|
29605
29673
|
}
|
|
29606
29674
|
get gridEl() {
|
|
@@ -29723,16 +29791,15 @@ class Grid extends Component {
|
|
|
29723
29791
|
}
|
|
29724
29792
|
}
|
|
29725
29793
|
onKeydown(ev) {
|
|
29726
|
-
const eventKey = ev.key.toUpperCase();
|
|
29727
29794
|
let keyDownString = "";
|
|
29728
|
-
if (
|
|
29729
|
-
|
|
29730
|
-
|
|
29731
|
-
|
|
29732
|
-
|
|
29733
|
-
|
|
29734
|
-
|
|
29735
|
-
|
|
29795
|
+
if (!MODIFIER_KEYS.includes(ev.key)) {
|
|
29796
|
+
if (isCtrlKey(ev))
|
|
29797
|
+
keyDownString += "CTRL+";
|
|
29798
|
+
if (ev.altKey)
|
|
29799
|
+
keyDownString += "ALT+";
|
|
29800
|
+
if (ev.shiftKey)
|
|
29801
|
+
keyDownString += "SHIFT+";
|
|
29802
|
+
}
|
|
29736
29803
|
keyDownString += ev.key.toUpperCase();
|
|
29737
29804
|
let handler = this.keyDownMapping[keyDownString];
|
|
29738
29805
|
if (handler) {
|
|
@@ -29746,19 +29813,6 @@ class Grid extends Component {
|
|
|
29746
29813
|
return;
|
|
29747
29814
|
}
|
|
29748
29815
|
}
|
|
29749
|
-
onInput(ev) {
|
|
29750
|
-
// the user meant to paste in the sheet, not open the composer with the pasted content
|
|
29751
|
-
if (!ev.isComposing && ev.inputType === "insertFromPaste") {
|
|
29752
|
-
return;
|
|
29753
|
-
}
|
|
29754
|
-
if (ev.data) {
|
|
29755
|
-
// if the user types a character on the grid, it means he wants to start composing the selected cell with that
|
|
29756
|
-
// character
|
|
29757
|
-
ev.preventDefault();
|
|
29758
|
-
ev.stopPropagation();
|
|
29759
|
-
this.props.onGridComposerCellFocused(ev.data);
|
|
29760
|
-
}
|
|
29761
|
-
}
|
|
29762
29816
|
// ---------------------------------------------------------------------------
|
|
29763
29817
|
// Context Menu
|
|
29764
29818
|
// ---------------------------------------------------------------------------
|
|
@@ -29873,7 +29927,7 @@ class Grid extends Component {
|
|
|
29873
29927
|
}
|
|
29874
29928
|
closeMenu() {
|
|
29875
29929
|
this.menuState.isOpen = false;
|
|
29876
|
-
this.
|
|
29930
|
+
this.focusDefaultElement();
|
|
29877
29931
|
}
|
|
29878
29932
|
processHeaderGroupingKey(direction) {
|
|
29879
29933
|
if (this.env.model.getters.getSelectedZones().length !== 1) {
|
|
@@ -33768,6 +33822,31 @@ const MIGRATIONS = [
|
|
|
33768
33822
|
return data;
|
|
33769
33823
|
},
|
|
33770
33824
|
},
|
|
33825
|
+
{
|
|
33826
|
+
description: "Fix datafilter duplication",
|
|
33827
|
+
from: 12,
|
|
33828
|
+
to: 12.5,
|
|
33829
|
+
applyMigration(data) {
|
|
33830
|
+
for (let sheet of data.sheets || []) {
|
|
33831
|
+
let knownDataFilterZones = [];
|
|
33832
|
+
for (let filterTable of sheet.filterTables || []) {
|
|
33833
|
+
const zone = toZone(filterTable.range);
|
|
33834
|
+
// See commit message for the details
|
|
33835
|
+
const intersectZoneIndex = knownDataFilterZones.findIndex((knownZone) => overlap(knownZone, zone));
|
|
33836
|
+
if (intersectZoneIndex !== -1) {
|
|
33837
|
+
knownDataFilterZones[intersectZoneIndex] = zone;
|
|
33838
|
+
}
|
|
33839
|
+
else {
|
|
33840
|
+
knownDataFilterZones.push(zone);
|
|
33841
|
+
}
|
|
33842
|
+
}
|
|
33843
|
+
sheet.filterTables = knownDataFilterZones.map((zone) => ({
|
|
33844
|
+
range: zoneToXc(zone),
|
|
33845
|
+
}));
|
|
33846
|
+
}
|
|
33847
|
+
return data;
|
|
33848
|
+
},
|
|
33849
|
+
},
|
|
33771
33850
|
{
|
|
33772
33851
|
description: "Change Border description structure",
|
|
33773
33852
|
from: 12,
|
|
@@ -34607,22 +34686,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
34607
34686
|
}
|
|
34608
34687
|
}
|
|
34609
34688
|
export(data) {
|
|
34610
|
-
// Borders
|
|
34611
|
-
let borderId = 0;
|
|
34612
34689
|
const borders = {};
|
|
34613
|
-
/**
|
|
34614
|
-
* Get the id of the given border. If the border does not exist, it creates
|
|
34615
|
-
* one.
|
|
34616
|
-
*/
|
|
34617
|
-
function getBorderId(border) {
|
|
34618
|
-
for (let [key, value] of Object.entries(borders)) {
|
|
34619
|
-
if (deepEquals(value, border)) {
|
|
34620
|
-
return parseInt(key, 10);
|
|
34621
|
-
}
|
|
34622
|
-
}
|
|
34623
|
-
borders[++borderId] = border;
|
|
34624
|
-
return borderId;
|
|
34625
|
-
}
|
|
34626
34690
|
for (let sheet of data.sheets) {
|
|
34627
34691
|
for (let col = 0; col < sheet.colNumber; col++) {
|
|
34628
34692
|
for (let row = 0; row < sheet.rowNumber; row++) {
|
|
@@ -34630,7 +34694,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
34630
34694
|
if (border) {
|
|
34631
34695
|
const xc = toXC(col, row);
|
|
34632
34696
|
const cell = sheet.cells[xc];
|
|
34633
|
-
const borderId =
|
|
34697
|
+
const borderId = getItemId(border, borders);
|
|
34634
34698
|
if (cell) {
|
|
34635
34699
|
cell.border = borderId;
|
|
34636
34700
|
}
|
|
@@ -35435,9 +35499,9 @@ class CellPlugin extends CorePlugin {
|
|
|
35435
35499
|
allowDispatch(cmd) {
|
|
35436
35500
|
switch (cmd.type) {
|
|
35437
35501
|
case "UPDATE_CELL":
|
|
35438
|
-
return this.
|
|
35502
|
+
return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessUpdateCell);
|
|
35439
35503
|
case "CLEAR_CELL":
|
|
35440
|
-
return this.checkValidations(cmd, this.
|
|
35504
|
+
return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessClearCell);
|
|
35441
35505
|
default:
|
|
35442
35506
|
return "Success" /* CommandResult.Success */;
|
|
35443
35507
|
}
|
|
@@ -35587,8 +35651,8 @@ class CellPlugin extends CorePlugin {
|
|
|
35587
35651
|
}
|
|
35588
35652
|
removeDefaultStyleValues(style) {
|
|
35589
35653
|
const cleanedStyle = { ...style };
|
|
35590
|
-
for (const
|
|
35591
|
-
if (cleanedStyle[property] ===
|
|
35654
|
+
for (const property in DEFAULT_STYLE) {
|
|
35655
|
+
if (cleanedStyle[property] === DEFAULT_STYLE[property]) {
|
|
35592
35656
|
delete cleanedStyle[property];
|
|
35593
35657
|
}
|
|
35594
35658
|
}
|
|
@@ -35613,13 +35677,13 @@ class CellPlugin extends CorePlugin {
|
|
|
35613
35677
|
/*
|
|
35614
35678
|
* Reconstructs the original formula string based on a normalized form and its dependencies
|
|
35615
35679
|
*/
|
|
35616
|
-
getFormulaCellContent(sheetId, compiledFormula, dependencies) {
|
|
35680
|
+
getFormulaCellContent(sheetId, compiledFormula, dependencies, useFixedReference = false) {
|
|
35617
35681
|
const ranges = dependencies || compiledFormula.dependencies;
|
|
35618
35682
|
let rangeIndex = 0;
|
|
35619
35683
|
return concat(compiledFormula.tokens.map((token) => {
|
|
35620
35684
|
if (token.type === "REFERENCE") {
|
|
35621
35685
|
const range = ranges[rangeIndex++];
|
|
35622
|
-
return this.getters.getRangeString(range, sheetId);
|
|
35686
|
+
return this.getters.getRangeString(range, sheetId, { useFixedReference });
|
|
35623
35687
|
}
|
|
35624
35688
|
return token.value;
|
|
35625
35689
|
}));
|
|
@@ -35745,10 +35809,7 @@ class CellPlugin extends CorePlugin {
|
|
|
35745
35809
|
else {
|
|
35746
35810
|
style = before ? before.style : undefined;
|
|
35747
35811
|
}
|
|
35748
|
-
const
|
|
35749
|
-
let format = ("format" in after ? after.format : before && before.format) ||
|
|
35750
|
-
detectDateFormat(afterContent, locale) ||
|
|
35751
|
-
detectNumberFormat(afterContent);
|
|
35812
|
+
const format = "format" in after ? after.format : before && before.format;
|
|
35752
35813
|
/* Read the following IF as:
|
|
35753
35814
|
* we need to remove the cell if it is completely empty, but we can know if it completely empty if:
|
|
35754
35815
|
* - the command says the new content is empty and has no border/format/style
|
|
@@ -35789,12 +35850,11 @@ class CellPlugin extends CorePlugin {
|
|
|
35789
35850
|
}
|
|
35790
35851
|
createLiteralCell(id, content, format, style) {
|
|
35791
35852
|
const locale = this.getters.getLocale();
|
|
35792
|
-
content = parseLiteral(content, locale).toString();
|
|
35793
35853
|
return {
|
|
35794
35854
|
id,
|
|
35795
|
-
content,
|
|
35855
|
+
content: parseLiteral(content, locale).toString(),
|
|
35796
35856
|
style,
|
|
35797
|
-
format,
|
|
35857
|
+
format: format || detectDateFormat(content, locale) || detectNumberFormat(content),
|
|
35798
35858
|
isFormula: false,
|
|
35799
35859
|
};
|
|
35800
35860
|
}
|
|
@@ -35820,8 +35880,11 @@ class CellPlugin extends CorePlugin {
|
|
|
35820
35880
|
* being a computed property to rebuild the dependencies XC.
|
|
35821
35881
|
*/
|
|
35822
35882
|
createFormulaCellWithDependencies(id, compiledFormula, format, style, sheetId) {
|
|
35823
|
-
const dependencies =
|
|
35824
|
-
|
|
35883
|
+
const dependencies = [];
|
|
35884
|
+
for (const xc of compiledFormula.dependencies) {
|
|
35885
|
+
dependencies.push(this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
35886
|
+
}
|
|
35887
|
+
return new FormulaCellWithDependencies(id, compiledFormula, format, style, dependencies, sheetId, this.getters.getRangeString);
|
|
35825
35888
|
}
|
|
35826
35889
|
createErrorFormula(id, content, format, style, error) {
|
|
35827
35890
|
return {
|
|
@@ -35856,6 +35919,18 @@ class CellPlugin extends CorePlugin {
|
|
|
35856
35919
|
}
|
|
35857
35920
|
return "Success" /* CommandResult.Success */;
|
|
35858
35921
|
}
|
|
35922
|
+
checkUselessUpdateCell(cmd) {
|
|
35923
|
+
const cell = this.getters.getCell(cmd);
|
|
35924
|
+
const hasContent = "content" in cmd || "formula" in cmd;
|
|
35925
|
+
const hasStyle = "style" in cmd;
|
|
35926
|
+
const hasFormat = "format" in cmd;
|
|
35927
|
+
if ((!hasContent || cell?.content === cmd.content) &&
|
|
35928
|
+
(!hasStyle || deepEquals(cell?.style, cmd.style)) &&
|
|
35929
|
+
(!hasFormat || cell?.format === cmd.format)) {
|
|
35930
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
35931
|
+
}
|
|
35932
|
+
return "Success" /* CommandResult.Success */;
|
|
35933
|
+
}
|
|
35859
35934
|
}
|
|
35860
35935
|
class FormulaCellWithDependencies {
|
|
35861
35936
|
id;
|
|
@@ -35875,7 +35950,7 @@ class FormulaCellWithDependencies {
|
|
|
35875
35950
|
const tokens = compiledFormula.tokens.map((token) => {
|
|
35876
35951
|
if (token.type === "REFERENCE") {
|
|
35877
35952
|
const index = rangeIndex++;
|
|
35878
|
-
return new RangeReferenceToken(
|
|
35953
|
+
return new RangeReferenceToken(dependencies, index, this.sheetId, this.getRangeString);
|
|
35879
35954
|
}
|
|
35880
35955
|
return token;
|
|
35881
35956
|
});
|
|
@@ -35888,15 +35963,34 @@ class FormulaCellWithDependencies {
|
|
|
35888
35963
|
get content() {
|
|
35889
35964
|
return concat(this.compiledFormula.tokens.map((token) => token.value));
|
|
35890
35965
|
}
|
|
35966
|
+
get contentWithFixedReferences() {
|
|
35967
|
+
let rangeIndex = 0;
|
|
35968
|
+
return concat(this.compiledFormula.tokens.map((token) => {
|
|
35969
|
+
if (token.type === "REFERENCE") {
|
|
35970
|
+
const index = rangeIndex++;
|
|
35971
|
+
return this.getRangeString(this.compiledFormula.dependencies[index], this.sheetId, {
|
|
35972
|
+
useFixedReference: true,
|
|
35973
|
+
});
|
|
35974
|
+
}
|
|
35975
|
+
return token.value;
|
|
35976
|
+
}));
|
|
35977
|
+
}
|
|
35891
35978
|
}
|
|
35892
35979
|
class RangeReferenceToken {
|
|
35893
|
-
|
|
35980
|
+
ranges;
|
|
35981
|
+
rangeIndex;
|
|
35982
|
+
sheetId;
|
|
35983
|
+
getRangeString;
|
|
35894
35984
|
type = "REFERENCE";
|
|
35895
|
-
constructor(
|
|
35896
|
-
this.
|
|
35985
|
+
constructor(ranges, rangeIndex, sheetId, getRangeString) {
|
|
35986
|
+
this.ranges = ranges;
|
|
35987
|
+
this.rangeIndex = rangeIndex;
|
|
35988
|
+
this.sheetId = sheetId;
|
|
35989
|
+
this.getRangeString = getRangeString;
|
|
35897
35990
|
}
|
|
35898
35991
|
get value() {
|
|
35899
|
-
|
|
35992
|
+
const range = this.ranges[this.rangeIndex];
|
|
35993
|
+
return this.getRangeString(range, this.sheetId);
|
|
35900
35994
|
}
|
|
35901
35995
|
}
|
|
35902
35996
|
|
|
@@ -36192,7 +36286,13 @@ class ConditionalFormatPlugin extends CorePlugin {
|
|
|
36192
36286
|
}
|
|
36193
36287
|
}
|
|
36194
36288
|
exportForExcel(data) {
|
|
36195
|
-
|
|
36289
|
+
if (data.sheets) {
|
|
36290
|
+
for (let sheet of data.sheets) {
|
|
36291
|
+
if (this.cfRules[sheet.id]) {
|
|
36292
|
+
sheet.conditionalFormats = this.cfRules[sheet.id].map((rule) => this.mapToConditionalFormat(sheet.id, rule, { useFixedReference: true }));
|
|
36293
|
+
}
|
|
36294
|
+
}
|
|
36295
|
+
}
|
|
36196
36296
|
}
|
|
36197
36297
|
// ---------------------------------------------------------------------------
|
|
36198
36298
|
// Getters
|
|
@@ -36257,11 +36357,11 @@ class ConditionalFormatPlugin extends CorePlugin {
|
|
|
36257
36357
|
// ---------------------------------------------------------------------------
|
|
36258
36358
|
// Private
|
|
36259
36359
|
// ---------------------------------------------------------------------------
|
|
36260
|
-
mapToConditionalFormat(sheetId, cf) {
|
|
36360
|
+
mapToConditionalFormat(sheetId, cf, { useFixedReference } = { useFixedReference: false }) {
|
|
36261
36361
|
return {
|
|
36262
36362
|
...cf,
|
|
36263
36363
|
ranges: cf.ranges.map((range) => {
|
|
36264
|
-
return this.getters.getRangeString(range, sheetId);
|
|
36364
|
+
return this.getters.getRangeString(range, sheetId, { useFixedReference });
|
|
36265
36365
|
}),
|
|
36266
36366
|
};
|
|
36267
36367
|
}
|
|
@@ -38329,8 +38429,10 @@ class RangeAdapter {
|
|
|
38329
38429
|
*
|
|
38330
38430
|
* @param range the range (received from getRangeFromXC or getRangeFromZone)
|
|
38331
38431
|
* @param forSheetId the id of the sheet where the range string is supposed to be used.
|
|
38432
|
+
* @param options
|
|
38433
|
+
* @param options.useFixedReference if true, the range will be returned with fixed row and column
|
|
38332
38434
|
*/
|
|
38333
|
-
getRangeString(range, forSheetId) {
|
|
38435
|
+
getRangeString(range, forSheetId, options = { useFixedReference: false }) {
|
|
38334
38436
|
if (!range) {
|
|
38335
38437
|
return INCORRECT_RANGE_STRING;
|
|
38336
38438
|
}
|
|
@@ -38357,7 +38459,7 @@ class RangeAdapter {
|
|
|
38357
38459
|
if (prefixSheet && !sheetName) {
|
|
38358
38460
|
return INCORRECT_RANGE_STRING;
|
|
38359
38461
|
}
|
|
38360
|
-
let rangeString = this.getRangePartString(rangeImpl, 0);
|
|
38462
|
+
let rangeString = this.getRangePartString(rangeImpl, 0, options);
|
|
38361
38463
|
if (rangeImpl.parts && rangeImpl.parts.length === 2) {
|
|
38362
38464
|
// this if converts A2:A2 into A2 except if any part of the original range had fixed row or column (with $)
|
|
38363
38465
|
if (rangeImpl.zone.top !== rangeImpl.zone.bottom ||
|
|
@@ -38367,7 +38469,7 @@ class RangeAdapter {
|
|
|
38367
38469
|
rangeImpl.parts[1].rowFixed ||
|
|
38368
38470
|
rangeImpl.parts[1].colFixed) {
|
|
38369
38471
|
rangeString += ":";
|
|
38370
|
-
rangeString += this.getRangePartString(rangeImpl, 1);
|
|
38472
|
+
rangeString += this.getRangePartString(rangeImpl, 1, options);
|
|
38371
38473
|
}
|
|
38372
38474
|
}
|
|
38373
38475
|
return `${prefixSheet ? sheetName + "!" : ""}${rangeString}`;
|
|
@@ -38408,13 +38510,13 @@ class RangeAdapter {
|
|
|
38408
38510
|
/**
|
|
38409
38511
|
* Get a Xc string that represent a part of a range
|
|
38410
38512
|
*/
|
|
38411
|
-
getRangePartString(range, part) {
|
|
38513
|
+
getRangePartString(range, part, options = { useFixedReference: false }) {
|
|
38412
38514
|
const colFixed = range.parts && range.parts[part]?.colFixed ? "$" : "";
|
|
38413
38515
|
const col = part === 0 ? numberToLetters(range.zone.left) : numberToLetters(range.zone.right);
|
|
38414
38516
|
const rowFixed = range.parts && range.parts[part]?.rowFixed ? "$" : "";
|
|
38415
38517
|
const row = part === 0 ? String(range.zone.top + 1) : String(range.zone.bottom + 1);
|
|
38416
38518
|
let str = "";
|
|
38417
|
-
if (range.isFullCol) {
|
|
38519
|
+
if (range.isFullCol && !options.useFixedReference) {
|
|
38418
38520
|
if (part === 0 && range.unboundedZone.hasHeader) {
|
|
38419
38521
|
str = colFixed + col + rowFixed + row;
|
|
38420
38522
|
}
|
|
@@ -38422,7 +38524,7 @@ class RangeAdapter {
|
|
|
38422
38524
|
str = colFixed + col;
|
|
38423
38525
|
}
|
|
38424
38526
|
}
|
|
38425
|
-
else if (range.isFullRow) {
|
|
38527
|
+
else if (range.isFullRow && !options.useFixedReference) {
|
|
38426
38528
|
if (part === 0 && range.unboundedZone.hasHeader) {
|
|
38427
38529
|
str = colFixed + col + rowFixed + row;
|
|
38428
38530
|
}
|
|
@@ -40624,7 +40726,15 @@ class SpreadsheetRTree {
|
|
|
40624
40726
|
if (!this.rTrees[sheetId]) {
|
|
40625
40727
|
return;
|
|
40626
40728
|
}
|
|
40627
|
-
this.rTrees[sheetId].remove(item,
|
|
40729
|
+
this.rTrees[sheetId].remove(item, this.rtreeItemComparer);
|
|
40730
|
+
}
|
|
40731
|
+
rtreeItemComparer(left, right) {
|
|
40732
|
+
return (left.data == right.data &&
|
|
40733
|
+
left.boundingBox.sheetId === right.boundingBox.sheetId &&
|
|
40734
|
+
left.boundingBox?.zone.left === right.boundingBox.zone.left &&
|
|
40735
|
+
left.boundingBox?.zone.top === right.boundingBox.zone.top &&
|
|
40736
|
+
left.boundingBox?.zone.right === right.boundingBox.zone.right &&
|
|
40737
|
+
left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom);
|
|
40628
40738
|
}
|
|
40629
40739
|
}
|
|
40630
40740
|
/**
|
|
@@ -40702,7 +40812,7 @@ class FormulaDependencyGraph {
|
|
|
40702
40812
|
const queue = Array.from(ranges).reverse();
|
|
40703
40813
|
while (queue.length > 0) {
|
|
40704
40814
|
const range = queue.pop();
|
|
40705
|
-
visited.
|
|
40815
|
+
visited.addMany(this.encoder.encodeBoundingBox(range));
|
|
40706
40816
|
const impactedPositionIds = this.rTree.search(range).map((dep) => dep.data);
|
|
40707
40817
|
for (const positionId of impactedPositionIds) {
|
|
40708
40818
|
if (!visited.has(positionId)) {
|
|
@@ -40710,7 +40820,7 @@ class FormulaDependencyGraph {
|
|
|
40710
40820
|
}
|
|
40711
40821
|
}
|
|
40712
40822
|
}
|
|
40713
|
-
visited.
|
|
40823
|
+
visited.deleteMany(ranges.flatMap((r) => this.encoder.encodeBoundingBox(r)));
|
|
40714
40824
|
return visited;
|
|
40715
40825
|
}
|
|
40716
40826
|
}
|
|
@@ -40848,9 +40958,9 @@ class Evaluator {
|
|
|
40848
40958
|
const cells = positions.map((p) => this.encoder.encode(p));
|
|
40849
40959
|
const cellsToCompute = new JetSet(cells);
|
|
40850
40960
|
const arrayFormulasPositionIds = this.getArrayFormulasImpactedByChangesOf(cells);
|
|
40851
|
-
cellsToCompute.
|
|
40852
|
-
cellsToCompute.
|
|
40853
|
-
cellsToCompute.
|
|
40961
|
+
cellsToCompute.addMany(this.getCellsDependingOn(cells));
|
|
40962
|
+
cellsToCompute.addMany(arrayFormulasPositionIds);
|
|
40963
|
+
cellsToCompute.addMany(this.getCellsDependingOn(arrayFormulasPositionIds));
|
|
40854
40964
|
this.evaluate(cellsToCompute);
|
|
40855
40965
|
}
|
|
40856
40966
|
getArrayFormulasImpactedByChangesOf(positionIds) {
|
|
@@ -40864,7 +40974,7 @@ class Evaluator {
|
|
|
40864
40974
|
}
|
|
40865
40975
|
if (!content) {
|
|
40866
40976
|
// The previous content could have blocked some array formulas
|
|
40867
|
-
impactedPositionIds.
|
|
40977
|
+
impactedPositionIds.addMany(this.getArrayFormulasBlockedByOrSpreadingOn(positionId));
|
|
40868
40978
|
}
|
|
40869
40979
|
}
|
|
40870
40980
|
return impactedPositionIds;
|
|
@@ -40913,7 +41023,7 @@ class Evaluator {
|
|
|
40913
41023
|
}
|
|
40914
41024
|
const arrayFormulas = this.spreadingRelations.getFormulaPositionsSpreadingOn(positionId);
|
|
40915
41025
|
const cells = new JetSet(arrayFormulas);
|
|
40916
|
-
cells.
|
|
41026
|
+
cells.addMany(this.getCellsDependingOn(arrayFormulas));
|
|
40917
41027
|
return cells;
|
|
40918
41028
|
}
|
|
40919
41029
|
nextPositionsToUpdate = new JetSet();
|
|
@@ -41062,7 +41172,7 @@ class Evaluator {
|
|
|
41062
41172
|
this.setEvaluatedCell(positionId, evaluatedCell);
|
|
41063
41173
|
// check if formula dependencies present in the spread zone
|
|
41064
41174
|
// if so, they need to be recomputed
|
|
41065
|
-
this.nextPositionsToUpdate.
|
|
41175
|
+
this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([positionId]));
|
|
41066
41176
|
};
|
|
41067
41177
|
}
|
|
41068
41178
|
invalidateSpreading(positionId) {
|
|
@@ -41077,8 +41187,8 @@ class Evaluator {
|
|
|
41077
41187
|
continue;
|
|
41078
41188
|
}
|
|
41079
41189
|
this.evaluatedCells.delete(child);
|
|
41080
|
-
this.nextPositionsToUpdate.
|
|
41081
|
-
this.nextPositionsToUpdate.
|
|
41190
|
+
this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([child]));
|
|
41191
|
+
this.nextPositionsToUpdate.addMany(this.getArrayFormulasBlockedByOrSpreadingOn(child));
|
|
41082
41192
|
}
|
|
41083
41193
|
this.spreadingRelations.removeNode(positionId);
|
|
41084
41194
|
}
|
|
@@ -41427,7 +41537,13 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
41427
41537
|
const format = newFormat
|
|
41428
41538
|
? getItemId(newFormat, data.formats)
|
|
41429
41539
|
: exportedCellData.format;
|
|
41430
|
-
|
|
41540
|
+
let content;
|
|
41541
|
+
if (formulaCell instanceof FormulaCellWithDependencies) {
|
|
41542
|
+
content = this.getters.getFormulaCellContent(exportedSheetData.id, formulaCell.compiledFormula, formulaCell.compiledFormula.dependencies, true);
|
|
41543
|
+
}
|
|
41544
|
+
else {
|
|
41545
|
+
content = !isExported ? newContent : exportedCellData.content;
|
|
41546
|
+
}
|
|
41431
41547
|
exportedSheetData.cells[xc] = { ...exportedCellData, value, isFormula, content, format };
|
|
41432
41548
|
}
|
|
41433
41549
|
}
|
|
@@ -50743,6 +50859,16 @@ class ImageProvider {
|
|
|
50743
50859
|
}
|
|
50744
50860
|
}
|
|
50745
50861
|
|
|
50862
|
+
class FocusableElement {
|
|
50863
|
+
focusableElement = undefined;
|
|
50864
|
+
setFocusableElement(element) {
|
|
50865
|
+
this.focusableElement = element;
|
|
50866
|
+
}
|
|
50867
|
+
focus() {
|
|
50868
|
+
this.focusableElement?.focus();
|
|
50869
|
+
}
|
|
50870
|
+
}
|
|
50871
|
+
|
|
50746
50872
|
const RIPPLE_KEY_FRAMES = [
|
|
50747
50873
|
{ transform: "scale(0)" },
|
|
50748
50874
|
{ transform: "scale(0.8)", offset: 0.33 },
|
|
@@ -52899,6 +53025,7 @@ class Spreadsheet extends Component {
|
|
|
52899
53025
|
toggleSidePanel: this.toggleSidePanel.bind(this),
|
|
52900
53026
|
clipboard: this.env.clipboard || instantiateClipboard(),
|
|
52901
53027
|
startCellEdition: (content) => this.onGridComposerCellFocused(content),
|
|
53028
|
+
focusableElement: new FocusableElement(),
|
|
52902
53029
|
});
|
|
52903
53030
|
useExternalListener(window, "resize", () => this.render(true));
|
|
52904
53031
|
useExternalListener(window, "beforeunload", this.unbindModelEvents.bind(this));
|
|
@@ -53005,16 +53132,17 @@ class Spreadsheet extends Component {
|
|
|
53005
53132
|
}
|
|
53006
53133
|
this.composer.topBarFocus = "contentFocus";
|
|
53007
53134
|
this.composer.gridFocusMode = "inactive";
|
|
53008
|
-
this.setComposerContent({ selection }
|
|
53135
|
+
this.setComposerContent({ selection });
|
|
53009
53136
|
}
|
|
53010
|
-
onGridComposerContentFocused() {
|
|
53137
|
+
onGridComposerContentFocused(selection) {
|
|
53011
53138
|
if (this.model.getters.isReadonly()) {
|
|
53012
53139
|
return;
|
|
53013
53140
|
}
|
|
53014
53141
|
this.composer.topBarFocus = "inactive";
|
|
53015
53142
|
this.composer.gridFocusMode = "contentFocus";
|
|
53016
|
-
this.setComposerContent({});
|
|
53143
|
+
this.setComposerContent({ selection });
|
|
53017
53144
|
}
|
|
53145
|
+
// TODO: either both are defined or none of them. change those args to an object
|
|
53018
53146
|
onGridComposerCellFocused(content, selection) {
|
|
53019
53147
|
if (this.model.getters.isReadonly()) {
|
|
53020
53148
|
return;
|
|
@@ -54440,11 +54568,10 @@ class SelectionStreamProcessorImpl {
|
|
|
54440
54568
|
* next cluster if the given cell is outside a cluster or at the border of a cluster in the given direction.
|
|
54441
54569
|
*/
|
|
54442
54570
|
getEndOfCluster(startPosition, dim, dir) {
|
|
54443
|
-
const sheet = this.getters.getActiveSheet();
|
|
54444
54571
|
let currentPosition = startPosition;
|
|
54445
54572
|
// If both the current cell and the next cell are not empty, we want to go to the end of the cluster
|
|
54446
54573
|
const nextCellPosition = this.getNextCellPosition(startPosition, dim, dir);
|
|
54447
|
-
let mode = !this.
|
|
54574
|
+
let mode = !this.isEvaluatedCellEmpty(currentPosition) && !this.isEvaluatedCellEmpty(nextCellPosition)
|
|
54448
54575
|
? "endOfCluster"
|
|
54449
54576
|
: "nextCluster";
|
|
54450
54577
|
while (true) {
|
|
@@ -54454,7 +54581,7 @@ class SelectionStreamProcessorImpl {
|
|
|
54454
54581
|
currentPosition.row === nextCellPosition.row) {
|
|
54455
54582
|
break;
|
|
54456
54583
|
}
|
|
54457
|
-
const isNextCellEmpty = this.
|
|
54584
|
+
const isNextCellEmpty = this.isEvaluatedCellEmpty(nextCellPosition);
|
|
54458
54585
|
if (mode === "endOfCluster" && isNextCellEmpty) {
|
|
54459
54586
|
break;
|
|
54460
54587
|
}
|
|
@@ -54468,10 +54595,20 @@ class SelectionStreamProcessorImpl {
|
|
|
54468
54595
|
return dim === "cols" ? currentPosition.col : currentPosition.row;
|
|
54469
54596
|
}
|
|
54470
54597
|
/**
|
|
54471
|
-
*
|
|
54472
|
-
* check
|
|
54598
|
+
* Checks if a cell is empty (i.e. does not have a content). If the cell is part of a merge,
|
|
54599
|
+
* the check applies to the main cell of the merge.
|
|
54473
54600
|
*/
|
|
54474
|
-
isCellEmpty({ col, row }
|
|
54601
|
+
isCellEmpty({ col, row }) {
|
|
54602
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
54603
|
+
const position = this.getters.getMainCellPosition({ sheetId, col, row });
|
|
54604
|
+
return !(this.getters.getCorrespondingFormulaCell(position) || this.getters.getCell(position)?.content);
|
|
54605
|
+
}
|
|
54606
|
+
/**
|
|
54607
|
+
* Checks if a cell evaluated value is empty. If the cell is part of a merge,
|
|
54608
|
+
* the check applies to the main cell of the merge.
|
|
54609
|
+
*/
|
|
54610
|
+
isEvaluatedCellEmpty({ col, row }) {
|
|
54611
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
54475
54612
|
const position = this.getters.getMainCellPosition({ sheetId, col, row });
|
|
54476
54613
|
const cell = this.getters.getEvaluatedCell(position);
|
|
54477
54614
|
return cell.type === CellValueType.empty;
|
|
@@ -54949,12 +55086,7 @@ function addFormula(cell) {
|
|
|
54949
55086
|
attrs.push(["t", "str"]);
|
|
54950
55087
|
cycle = escapeXml /*xml*/ `<v>${cell.value}</v>`;
|
|
54951
55088
|
}
|
|
54952
|
-
node = escapeXml /*xml*/
|
|
54953
|
-
<f>
|
|
54954
|
-
${XlsxFormula}
|
|
54955
|
-
</f>
|
|
54956
|
-
${cycle}
|
|
54957
|
-
`;
|
|
55089
|
+
node = escapeXml /*xml*/ `<f>${XlsxFormula}</f>${cycle}`;
|
|
54958
55090
|
return { attrs, node };
|
|
54959
55091
|
}
|
|
54960
55092
|
function addContent(content, sharedStrings, forceString = false) {
|
|
@@ -55773,11 +55905,10 @@ function addRows(construct, data, sheet) {
|
|
|
55773
55905
|
({ attrs: additionalAttrs, node: cellNode } = addContent(cell.content, construct.sharedStrings, isTableHeader));
|
|
55774
55906
|
}
|
|
55775
55907
|
attributes.push(...additionalAttrs);
|
|
55776
|
-
|
|
55777
|
-
|
|
55778
|
-
|
|
55779
|
-
|
|
55780
|
-
`);
|
|
55908
|
+
// prettier-ignore
|
|
55909
|
+
cellNodes.push(escapeXml /*xml*/ `<c ${formatAttributes(attributes)}>
|
|
55910
|
+
${cellNode}
|
|
55911
|
+
</c>`);
|
|
55781
55912
|
}
|
|
55782
55913
|
}
|
|
55783
55914
|
if (cellNodes.length || row.size !== DEFAULT_CELL_HEIGHT || row.isHidden) {
|
|
@@ -56373,7 +56504,6 @@ class Model extends EventBus {
|
|
|
56373
56504
|
...config,
|
|
56374
56505
|
mode: config.mode || "normal",
|
|
56375
56506
|
custom: config.custom || {},
|
|
56376
|
-
defaultCurrencyFormat: config.defaultCurrencyFormat || "[$$]#,##0.00",
|
|
56377
56507
|
external: this.setupExternalConfig(config.external || {}),
|
|
56378
56508
|
transportService,
|
|
56379
56509
|
client,
|
|
@@ -56411,6 +56541,7 @@ class Model extends EventBus {
|
|
|
56411
56541
|
custom: this.config.custom,
|
|
56412
56542
|
uiActions: this.config,
|
|
56413
56543
|
session: this.session,
|
|
56544
|
+
defaultCurrencyFormat: this.config.defaultCurrencyFormat,
|
|
56414
56545
|
};
|
|
56415
56546
|
}
|
|
56416
56547
|
// ---------------------------------------------------------------------------
|
|
@@ -56748,6 +56879,6 @@ const constants = {
|
|
|
56748
56879
|
export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
|
|
56749
56880
|
|
|
56750
56881
|
|
|
56751
|
-
__info__.version = "17.0.
|
|
56752
|
-
__info__.date = "2024-
|
|
56753
|
-
__info__.hash = "
|
|
56882
|
+
__info__.version = "17.0.12";
|
|
56883
|
+
__info__.date = "2024-02-16T14:24:02.984Z";
|
|
56884
|
+
__info__.hash = "8fa2bab";
|