@odoo/o-spreadsheet 16.3.0-alpha.7 → 16.3.0
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 +751 -293
- package/dist/o-spreadsheet.d.ts +212 -118
- package/dist/o-spreadsheet.esm.js +751 -293
- package/dist/o-spreadsheet.iife.js +751 -293
- package/dist/o-spreadsheet.iife.min.js +384 -289
- package/package.json +2 -2
|
@@ -236,8 +236,8 @@ const HEADER_FONT_SIZE = 11;
|
|
|
236
236
|
const DEFAULT_FONT = "'Roboto', arial";
|
|
237
237
|
const DEFAULT_VERTICAL_ALIGN = "bottom";
|
|
238
238
|
// Borders
|
|
239
|
-
const DEFAULT_BORDER_DESC =
|
|
240
|
-
const DEFAULT_FILTER_BORDER_DESC =
|
|
239
|
+
const DEFAULT_BORDER_DESC = { style: "thin", color: "#000000" };
|
|
240
|
+
const DEFAULT_FILTER_BORDER_DESC = { style: "thin", color: FILTERS_COLOR };
|
|
241
241
|
// Ranges
|
|
242
242
|
const INCORRECT_RANGE_STRING = CellErrorType.InvalidReference;
|
|
243
243
|
// Max Number of history steps kept in memory
|
|
@@ -1101,6 +1101,18 @@ function replaceSpecialSpaces(text) {
|
|
|
1101
1101
|
text = text.replace(whiteSpaceRegexp, " ");
|
|
1102
1102
|
text = text.replace(newLineRegex, NEWLINE);
|
|
1103
1103
|
return text;
|
|
1104
|
+
}
|
|
1105
|
+
/**
|
|
1106
|
+
* Determine if the numbers are consecutive.
|
|
1107
|
+
*/
|
|
1108
|
+
function isConsecutive(iterable) {
|
|
1109
|
+
const array = Array.from(iterable).sort((a, b) => a - b); // sort numerically rather than lexicographically
|
|
1110
|
+
for (let i = 1; i < array.length; i++) {
|
|
1111
|
+
if (array[i] - array[i - 1] !== 1) {
|
|
1112
|
+
return false;
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
return true;
|
|
1104
1116
|
}
|
|
1105
1117
|
|
|
1106
1118
|
const RBA_REGEX = /rgba?\(|\s+|\)/gi;
|
|
@@ -4243,6 +4255,7 @@ const coreTypes = new Set([
|
|
|
4243
4255
|
"SET_FORMATTING",
|
|
4244
4256
|
"CLEAR_FORMATTING",
|
|
4245
4257
|
"SET_BORDER",
|
|
4258
|
+
"SET_ZONE_BORDERS",
|
|
4246
4259
|
/** CHART */
|
|
4247
4260
|
"CREATE_CHART",
|
|
4248
4261
|
"UPDATE_CHART",
|
|
@@ -4383,8 +4396,10 @@ var CommandResult;
|
|
|
4383
4396
|
CommandResult[CommandResult["EmptySplitSeparator"] = 89] = "EmptySplitSeparator";
|
|
4384
4397
|
CommandResult[CommandResult["SplitWillOverwriteContent"] = 90] = "SplitWillOverwriteContent";
|
|
4385
4398
|
CommandResult[CommandResult["NoSplitSeparatorInSelection"] = 91] = "NoSplitSeparatorInSelection";
|
|
4399
|
+
CommandResult[CommandResult["NoActiveSheet"] = 92] = "NoActiveSheet";
|
|
4386
4400
|
})(CommandResult || (CommandResult = {}));
|
|
4387
4401
|
|
|
4402
|
+
const borderStyles = ["thin", "medium", "thick", "dashed", "dotted"];
|
|
4388
4403
|
var DIRECTION;
|
|
4389
4404
|
(function (DIRECTION) {
|
|
4390
4405
|
DIRECTION["UP"] = "up";
|
|
@@ -5478,12 +5493,6 @@ css /* scss */ `
|
|
|
5478
5493
|
cursor: pointer;
|
|
5479
5494
|
user-select: none;
|
|
5480
5495
|
|
|
5481
|
-
.o-menu-item-name {
|
|
5482
|
-
overflow: hidden;
|
|
5483
|
-
white-space: nowrap;
|
|
5484
|
-
text-overflow: ellipsis;
|
|
5485
|
-
}
|
|
5486
|
-
|
|
5487
5496
|
&.o-menu-root {
|
|
5488
5497
|
display: flex;
|
|
5489
5498
|
justify-content: space-between;
|
|
@@ -5494,10 +5503,6 @@ css /* scss */ `
|
|
|
5494
5503
|
margin: 0px 8px 0px 0px;
|
|
5495
5504
|
width: ${MENU_ITEM_HEIGHT - 2 * MENU_ITEM_PADDING_VERTICAL}px;
|
|
5496
5505
|
line-height: ${MENU_ITEM_HEIGHT - 2 * MENU_ITEM_PADDING_VERTICAL}px;
|
|
5497
|
-
|
|
5498
|
-
.o-icon {
|
|
5499
|
-
color: ${ICONS_COLOR};
|
|
5500
|
-
}
|
|
5501
5506
|
}
|
|
5502
5507
|
.o-menu-item-root {
|
|
5503
5508
|
width: 10px;
|
|
@@ -5511,6 +5516,11 @@ css /* scss */ `
|
|
|
5511
5516
|
.o-menu-item-description {
|
|
5512
5517
|
color: grey;
|
|
5513
5518
|
}
|
|
5519
|
+
.o-menu-item-icon {
|
|
5520
|
+
.o-icon {
|
|
5521
|
+
color: ${ICONS_COLOR};
|
|
5522
|
+
}
|
|
5523
|
+
}
|
|
5514
5524
|
}
|
|
5515
5525
|
&.disabled {
|
|
5516
5526
|
color: ${MENU_ITEM_DISABLED_COLOR};
|
|
@@ -6327,8 +6337,14 @@ function createDataSets(getters, dataSetsString, sheetId, dataSetsHaveTitle) {
|
|
|
6327
6337
|
: undefined));
|
|
6328
6338
|
}
|
|
6329
6339
|
}
|
|
6340
|
+
else if (zone.left === zone.right && zone.top === zone.bottom) {
|
|
6341
|
+
// A single cell. If it's only the title, the dataset is not added.
|
|
6342
|
+
if (!dataSetsHaveTitle) {
|
|
6343
|
+
dataSets.push(createDataSet(getters, dataSetSheetId, zone, undefined));
|
|
6344
|
+
}
|
|
6345
|
+
}
|
|
6330
6346
|
else {
|
|
6331
|
-
/* 1
|
|
6347
|
+
/* 1 row or 1 column */
|
|
6332
6348
|
dataSets.push(createDataSet(getters, dataSetSheetId, zone, dataSetsHaveTitle
|
|
6333
6349
|
? {
|
|
6334
6350
|
top: zone.top,
|
|
@@ -8939,7 +8955,7 @@ const DELETE_CELL_SHIFT_LEFT = (env) => {
|
|
|
8939
8955
|
handlePasteResult(env, result);
|
|
8940
8956
|
};
|
|
8941
8957
|
const MENU_INSERT_ROWS_NAME = (env) => {
|
|
8942
|
-
const number =
|
|
8958
|
+
const number = getRowsNumber(env);
|
|
8943
8959
|
return number === 1 ? _lt("Insert row") : _lt("Insert %s rows", number.toString());
|
|
8944
8960
|
};
|
|
8945
8961
|
const MENU_INSERT_ROWS_BEFORE_NAME = (env) => {
|
|
@@ -15304,7 +15320,11 @@ const LOOKUP = {
|
|
|
15304
15320
|
: getNormalizedValueFromRowRange;
|
|
15305
15321
|
const rangeLength = verticalSearch ? nbRow : nbCol;
|
|
15306
15322
|
const index = dichotomicSearch(searchArray, _searchKey, "nextSmaller", "asc", rangeLength, getElement);
|
|
15307
|
-
|
|
15323
|
+
if (index === -1)
|
|
15324
|
+
assertAvailable(undefined, searchKey);
|
|
15325
|
+
verticalSearch
|
|
15326
|
+
? assertAvailable(searchArray[0][index], searchKey)
|
|
15327
|
+
: assertAvailable(searchArray[index][nbRow - 1], searchKey);
|
|
15308
15328
|
if (resultRange === undefined) {
|
|
15309
15329
|
return (verticalSearch ? searchArray[nbCol - 1][index] : searchArray[index][nbRow - 1]);
|
|
15310
15330
|
}
|
|
@@ -16211,75 +16231,97 @@ for (let category of categories) {
|
|
|
16211
16231
|
|
|
16212
16232
|
const insertRow = {
|
|
16213
16233
|
name: MENU_INSERT_ROWS_NAME,
|
|
16214
|
-
isVisible:
|
|
16234
|
+
isVisible: (env) => isConsecutive(env.model.getters.getActiveRows()) &&
|
|
16235
|
+
IS_ONLY_ONE_RANGE(env) &&
|
|
16236
|
+
env.model.getters.getActiveCols().size === 0,
|
|
16215
16237
|
icon: "o-spreadsheet-Icon.INSERT_ROW",
|
|
16216
16238
|
};
|
|
16217
16239
|
const rowInsertRowBefore = {
|
|
16218
16240
|
name: ROW_INSERT_ROWS_BEFORE_NAME,
|
|
16219
16241
|
execute: INSERT_ROWS_BEFORE_ACTION,
|
|
16242
|
+
isVisible: (env) => isConsecutive(env.model.getters.getActiveRows()) &&
|
|
16243
|
+
IS_ONLY_ONE_RANGE(env) &&
|
|
16244
|
+
env.model.getters.getActiveCols().size === 0,
|
|
16245
|
+
icon: "o-spreadsheet-Icon.INSERT_ROW_BEFORE",
|
|
16220
16246
|
};
|
|
16221
16247
|
const topBarInsertRowsBefore = {
|
|
16222
16248
|
...rowInsertRowBefore,
|
|
16223
16249
|
name: MENU_INSERT_ROWS_BEFORE_NAME,
|
|
16224
|
-
isVisible: (env) => env.model.getters.getActiveCols().size === 0,
|
|
16225
16250
|
};
|
|
16226
16251
|
const cellInsertRowsBefore = {
|
|
16227
16252
|
...rowInsertRowBefore,
|
|
16228
16253
|
name: CELL_INSERT_ROWS_BEFORE_NAME,
|
|
16229
16254
|
isVisible: IS_ONLY_ONE_RANGE,
|
|
16230
|
-
icon: "o-spreadsheet-Icon.
|
|
16255
|
+
icon: "o-spreadsheet-Icon.INSERT_ROW_BEFORE",
|
|
16231
16256
|
};
|
|
16232
16257
|
const rowInsertRowsAfter = {
|
|
16233
16258
|
execute: INSERT_ROWS_AFTER_ACTION,
|
|
16234
16259
|
name: ROW_INSERT_ROWS_AFTER_NAME,
|
|
16260
|
+
isVisible: (env) => isConsecutive(env.model.getters.getActiveRows()) &&
|
|
16261
|
+
IS_ONLY_ONE_RANGE(env) &&
|
|
16262
|
+
env.model.getters.getActiveCols().size === 0,
|
|
16263
|
+
icon: "o-spreadsheet-Icon.INSERT_ROW_AFTER",
|
|
16235
16264
|
};
|
|
16236
16265
|
const topBarInsertRowsAfter = {
|
|
16237
16266
|
...rowInsertRowsAfter,
|
|
16238
16267
|
name: MENU_INSERT_ROWS_AFTER_NAME,
|
|
16239
|
-
isVisible: (env) => env.model.getters.getActiveCols().size === 0,
|
|
16240
16268
|
};
|
|
16241
16269
|
const insertCol = {
|
|
16242
16270
|
name: MENU_INSERT_COLUMNS_NAME,
|
|
16243
|
-
isVisible:
|
|
16271
|
+
isVisible: (env) => isConsecutive(env.model.getters.getActiveCols()) &&
|
|
16272
|
+
IS_ONLY_ONE_RANGE(env) &&
|
|
16273
|
+
env.model.getters.getActiveRows().size === 0,
|
|
16244
16274
|
icon: "o-spreadsheet-Icon.INSERT_COL",
|
|
16245
16275
|
};
|
|
16246
16276
|
const colInsertColsBefore = {
|
|
16247
16277
|
name: COLUMN_INSERT_COLUMNS_BEFORE_NAME,
|
|
16248
16278
|
execute: INSERT_COLUMNS_BEFORE_ACTION,
|
|
16279
|
+
isVisible: (env) => isConsecutive(env.model.getters.getActiveCols()) &&
|
|
16280
|
+
IS_ONLY_ONE_RANGE(env) &&
|
|
16281
|
+
env.model.getters.getActiveRows().size === 0,
|
|
16282
|
+
icon: "o-spreadsheet-Icon.INSERT_COL_BEFORE",
|
|
16249
16283
|
};
|
|
16250
16284
|
const topBarInsertColsBefore = {
|
|
16251
16285
|
...colInsertColsBefore,
|
|
16252
16286
|
name: MENU_INSERT_COLUMNS_BEFORE_NAME,
|
|
16253
|
-
isVisible: (env) => env.model.getters.getActiveRows().size === 0,
|
|
16254
16287
|
};
|
|
16255
16288
|
const cellInsertColsBefore = {
|
|
16256
16289
|
...colInsertColsBefore,
|
|
16257
16290
|
name: CELL_INSERT_COLUMNS_BEFORE_NAME,
|
|
16258
16291
|
isVisible: IS_ONLY_ONE_RANGE,
|
|
16259
|
-
icon: "o-spreadsheet-Icon.
|
|
16292
|
+
icon: "o-spreadsheet-Icon.INSERT_COL_BEFORE",
|
|
16260
16293
|
};
|
|
16261
16294
|
const colInsertColsAfter = {
|
|
16262
16295
|
name: COLUMN_INSERT_COLUMNS_AFTER_NAME,
|
|
16263
16296
|
execute: INSERT_COLUMNS_AFTER_ACTION,
|
|
16297
|
+
isVisible: (env) => isConsecutive(env.model.getters.getActiveCols()) &&
|
|
16298
|
+
IS_ONLY_ONE_RANGE(env) &&
|
|
16299
|
+
env.model.getters.getActiveRows().size === 0,
|
|
16300
|
+
icon: "o-spreadsheet-Icon.INSERT_COL_AFTER",
|
|
16264
16301
|
};
|
|
16265
16302
|
const topBarInsertColsAfter = {
|
|
16266
16303
|
...colInsertColsAfter,
|
|
16267
16304
|
name: MENU_INSERT_COLUMNS_AFTER_NAME,
|
|
16268
16305
|
execute: INSERT_COLUMNS_AFTER_ACTION,
|
|
16269
|
-
isVisible: (env) => env.model.getters.getActiveRows().size === 0,
|
|
16270
16306
|
};
|
|
16271
16307
|
const insertCell = {
|
|
16272
16308
|
name: _lt("Insert cells"),
|
|
16273
|
-
isVisible: IS_ONLY_ONE_RANGE
|
|
16309
|
+
isVisible: (env) => IS_ONLY_ONE_RANGE(env) &&
|
|
16310
|
+
env.model.getters.getActiveCols().size === 0 &&
|
|
16311
|
+
env.model.getters.getActiveRows().size === 0,
|
|
16274
16312
|
icon: "o-spreadsheet-Icon.INSERT_CELL",
|
|
16275
16313
|
};
|
|
16276
16314
|
const insertCellShiftDown = {
|
|
16277
16315
|
name: _lt("Insert cells and shift down"),
|
|
16278
16316
|
execute: INSERT_CELL_SHIFT_DOWN,
|
|
16317
|
+
isVisible: (env) => env.model.getters.getActiveRows().size === 0 && env.model.getters.getActiveCols().size === 0,
|
|
16318
|
+
icon: "o-spreadsheet-Icon.INSERT_CELL_SHIFT_DOWN",
|
|
16279
16319
|
};
|
|
16280
16320
|
const insertCellShiftRight = {
|
|
16281
16321
|
name: _lt("Insert cells and shift right"),
|
|
16282
16322
|
execute: INSERT_CELL_SHIFT_RIGHT,
|
|
16323
|
+
isVisible: (env) => env.model.getters.getActiveRows().size === 0 && env.model.getters.getActiveCols().size === 0,
|
|
16324
|
+
icon: "o-spreadsheet-Icon.INSERT_CELL_SHIFT_RIGHT",
|
|
16283
16325
|
};
|
|
16284
16326
|
const insertChart = {
|
|
16285
16327
|
name: _lt("Chart"),
|
|
@@ -16477,6 +16519,7 @@ const splitToColumns = {
|
|
|
16477
16519
|
sequence: 1,
|
|
16478
16520
|
execute: (env) => env.openSidePanel("SplitToColumns", {}),
|
|
16479
16521
|
isEnabled: (env) => env.model.getters.isSingleColSelected(),
|
|
16522
|
+
icon: "o-spreadsheet-Icon.SPLIT_TEXT",
|
|
16480
16523
|
};
|
|
16481
16524
|
|
|
16482
16525
|
const formatNumberAutomatic = {
|
|
@@ -16692,60 +16735,6 @@ const clearFormat = {
|
|
|
16692
16735
|
execute: FORMAT_CLEARFORMAT_ACTION,
|
|
16693
16736
|
icon: "o-spreadsheet-Icon.CLEAR_FORMAT",
|
|
16694
16737
|
};
|
|
16695
|
-
const borders = {
|
|
16696
|
-
name: _lt("Borders"),
|
|
16697
|
-
icon: "o-spreadsheet-Icon.BORDERS",
|
|
16698
|
-
};
|
|
16699
|
-
const bordersAll = {
|
|
16700
|
-
name: _lt("All borders"),
|
|
16701
|
-
execute: (env) => setBorder(env, "all"),
|
|
16702
|
-
icon: "o-spreadsheet-Icon.BORDERS",
|
|
16703
|
-
};
|
|
16704
|
-
const bordersInner = {
|
|
16705
|
-
name: _lt("Inner borders"),
|
|
16706
|
-
execute: (env) => setBorder(env, "hv"),
|
|
16707
|
-
icon: "o-spreadsheet-Icon.BORDER_HV",
|
|
16708
|
-
};
|
|
16709
|
-
const bordersHorizontal = {
|
|
16710
|
-
name: _lt("Horizontal borders"),
|
|
16711
|
-
execute: (env) => setBorder(env, "h"),
|
|
16712
|
-
icon: "o-spreadsheet-Icon.BORDER_H",
|
|
16713
|
-
};
|
|
16714
|
-
const bordersVertical = {
|
|
16715
|
-
name: _lt("Vertical borders"),
|
|
16716
|
-
execute: (env) => setBorder(env, "v"),
|
|
16717
|
-
icon: "o-spreadsheet-Icon.BORDER_V",
|
|
16718
|
-
};
|
|
16719
|
-
const bordersExternal = {
|
|
16720
|
-
name: _lt("External borders"),
|
|
16721
|
-
execute: (env) => setBorder(env, "external"),
|
|
16722
|
-
icon: "o-spreadsheet-Icon.BORDER_EXTERNAL",
|
|
16723
|
-
};
|
|
16724
|
-
const bordersLeft = {
|
|
16725
|
-
name: _lt("Left borders"),
|
|
16726
|
-
execute: (env) => setBorder(env, "left"),
|
|
16727
|
-
icon: "o-spreadsheet-Icon.BORDER_LEFT",
|
|
16728
|
-
};
|
|
16729
|
-
const bordersTop = {
|
|
16730
|
-
name: _lt("Top borders"),
|
|
16731
|
-
execute: (env) => setBorder(env, "top"),
|
|
16732
|
-
icon: "o-spreadsheet-Icon.BORDER_TOP",
|
|
16733
|
-
};
|
|
16734
|
-
const bordersRight = {
|
|
16735
|
-
name: _lt("Right borders"),
|
|
16736
|
-
execute: (env) => setBorder(env, "right"),
|
|
16737
|
-
icon: "o-spreadsheet-Icon.BORDER_RIGHT",
|
|
16738
|
-
};
|
|
16739
|
-
const bordersBottom = {
|
|
16740
|
-
name: _lt("Bottom borders"),
|
|
16741
|
-
execute: (env) => setBorder(env, "bottom"),
|
|
16742
|
-
icon: "o-spreadsheet-Icon.BORDER_BOTTOM",
|
|
16743
|
-
};
|
|
16744
|
-
const bordersClear = {
|
|
16745
|
-
name: _lt("Clear borders"),
|
|
16746
|
-
execute: (env) => setBorder(env, "clear"),
|
|
16747
|
-
icon: "o-spreadsheet-Icon.BORDER_CLEAR",
|
|
16748
|
-
};
|
|
16749
16738
|
function fontSizeMenuBuilder() {
|
|
16750
16739
|
return FONT_SIZES.map((fs) => {
|
|
16751
16740
|
return {
|
|
@@ -16758,24 +16747,17 @@ function fontSizeMenuBuilder() {
|
|
|
16758
16747
|
});
|
|
16759
16748
|
}
|
|
16760
16749
|
function isAutomaticFormatSelected(env) {
|
|
16761
|
-
const activeCell = env.model.getters.
|
|
16750
|
+
const activeCell = env.model.getters.getCell(env.model.getters.getActivePosition());
|
|
16762
16751
|
return !activeCell || !activeCell.format;
|
|
16763
16752
|
}
|
|
16764
16753
|
function isFormatSelected(env, format) {
|
|
16765
|
-
const activeCell = env.model.getters.
|
|
16766
|
-
return activeCell
|
|
16754
|
+
const activeCell = env.model.getters.getCell(env.model.getters.getActivePosition());
|
|
16755
|
+
return activeCell?.format === format;
|
|
16767
16756
|
}
|
|
16768
16757
|
function isFontSizeSelected(env, fontSize) {
|
|
16769
16758
|
const currentFontSize = env.model.getters.getCurrentStyle().fontSize || DEFAULT_FONT_SIZE;
|
|
16770
16759
|
return currentFontSize === fontSize;
|
|
16771
16760
|
}
|
|
16772
|
-
function setBorder(env, command) {
|
|
16773
|
-
env.model.dispatch("SET_FORMATTING", {
|
|
16774
|
-
sheetId: env.model.getters.getActiveSheetId(),
|
|
16775
|
-
target: env.model.getters.getSelectedZones(),
|
|
16776
|
-
border: command,
|
|
16777
|
-
});
|
|
16778
|
-
}
|
|
16779
16761
|
function getHorizontalAlign(env) {
|
|
16780
16762
|
const style = env.model.getters.getCurrentStyle();
|
|
16781
16763
|
if (style.align) {
|
|
@@ -16822,18 +16804,7 @@ var ACTION_FORMAT = /*#__PURE__*/Object.freeze({
|
|
|
16822
16804
|
fillColor: fillColor,
|
|
16823
16805
|
formatCF: formatCF,
|
|
16824
16806
|
paintFormat: paintFormat,
|
|
16825
|
-
clearFormat: clearFormat
|
|
16826
|
-
borders: borders,
|
|
16827
|
-
bordersAll: bordersAll,
|
|
16828
|
-
bordersInner: bordersInner,
|
|
16829
|
-
bordersHorizontal: bordersHorizontal,
|
|
16830
|
-
bordersVertical: bordersVertical,
|
|
16831
|
-
bordersExternal: bordersExternal,
|
|
16832
|
-
bordersLeft: bordersLeft,
|
|
16833
|
-
bordersTop: bordersTop,
|
|
16834
|
-
bordersRight: bordersRight,
|
|
16835
|
-
bordersBottom: bordersBottom,
|
|
16836
|
-
bordersClear: bordersClear
|
|
16807
|
+
clearFormat: clearFormat
|
|
16837
16808
|
});
|
|
16838
16809
|
|
|
16839
16810
|
function interactiveFreezeColumnsRows(env, dimension, base) {
|
|
@@ -16849,6 +16820,7 @@ const hideCols = {
|
|
|
16849
16820
|
name: HIDE_COLUMNS_NAME,
|
|
16850
16821
|
execute: HIDE_COLUMNS_ACTION,
|
|
16851
16822
|
isVisible: NOT_ALL_VISIBLE_COLS_SELECTED,
|
|
16823
|
+
icon: "o-spreadsheet-Icon.HIDE_COL",
|
|
16852
16824
|
};
|
|
16853
16825
|
const unhideCols = {
|
|
16854
16826
|
name: _lt("Unhide columns"),
|
|
@@ -16870,6 +16842,7 @@ const hideRows = {
|
|
|
16870
16842
|
name: HIDE_ROWS_NAME,
|
|
16871
16843
|
execute: HIDE_ROWS_ACTION,
|
|
16872
16844
|
isVisible: NOT_ALL_VISIBLE_ROWS_SELECTED,
|
|
16845
|
+
icon: "o-spreadsheet-Icon.HIDE_ROW",
|
|
16873
16846
|
};
|
|
16874
16847
|
const unhideRows = {
|
|
16875
16848
|
name: _lt("Unhide rows"),
|
|
@@ -17073,19 +17046,21 @@ colMenuRegistry
|
|
|
17073
17046
|
.add("delete_column", {
|
|
17074
17047
|
...deleteCols,
|
|
17075
17048
|
sequence: 90,
|
|
17049
|
+
icon: "o-spreadsheet-Icon.DELETE",
|
|
17076
17050
|
})
|
|
17077
17051
|
.add("clear_column", {
|
|
17078
17052
|
...clearCols,
|
|
17079
17053
|
sequence: 100,
|
|
17054
|
+
icon: "o-spreadsheet-Icon.CLEAR",
|
|
17080
17055
|
})
|
|
17081
17056
|
.add("hide_columns", {
|
|
17082
17057
|
...hideCols,
|
|
17083
|
-
sequence:
|
|
17058
|
+
sequence: 105,
|
|
17084
17059
|
separator: true,
|
|
17085
17060
|
})
|
|
17086
17061
|
.add("unhide_columns", {
|
|
17087
17062
|
...unhideCols,
|
|
17088
|
-
sequence:
|
|
17063
|
+
sequence: 106,
|
|
17089
17064
|
separator: true,
|
|
17090
17065
|
})
|
|
17091
17066
|
.add("conditional_formatting", {
|
|
@@ -17183,10 +17158,12 @@ rowMenuRegistry
|
|
|
17183
17158
|
.add("delete_row", {
|
|
17184
17159
|
...deleteRows,
|
|
17185
17160
|
sequence: 70,
|
|
17161
|
+
icon: "o-spreadsheet-Icon.DELETE",
|
|
17186
17162
|
})
|
|
17187
17163
|
.add("clear_row", {
|
|
17188
17164
|
...clearRows,
|
|
17189
17165
|
sequence: 80,
|
|
17166
|
+
icon: "o-spreadsheet-Icon.CLEAR",
|
|
17190
17167
|
})
|
|
17191
17168
|
.add("hide_rows", {
|
|
17192
17169
|
...hideRows,
|
|
@@ -17569,7 +17546,7 @@ topbarMenuRegistry
|
|
|
17569
17546
|
})
|
|
17570
17547
|
.addChild("sort_range", ["data"], {
|
|
17571
17548
|
...sortRange,
|
|
17572
|
-
sequence:
|
|
17549
|
+
sequence: 10,
|
|
17573
17550
|
separator: true,
|
|
17574
17551
|
})
|
|
17575
17552
|
.addChild("sort_ascending", ["data", "sort_range"], {
|
|
@@ -17582,16 +17559,16 @@ topbarMenuRegistry
|
|
|
17582
17559
|
})
|
|
17583
17560
|
.addChild("split_to_columns", ["data"], {
|
|
17584
17561
|
...splitToColumns,
|
|
17585
|
-
sequence:
|
|
17562
|
+
sequence: 20,
|
|
17586
17563
|
separator: true,
|
|
17587
17564
|
})
|
|
17588
17565
|
.addChild("add_data_filter", ["data"], {
|
|
17589
17566
|
...addDataFilter,
|
|
17590
|
-
sequence:
|
|
17567
|
+
sequence: 30,
|
|
17591
17568
|
})
|
|
17592
17569
|
.addChild("remove_data_filter", ["data"], {
|
|
17593
17570
|
...removeDataFilter,
|
|
17594
|
-
sequence:
|
|
17571
|
+
sequence: 30,
|
|
17595
17572
|
});
|
|
17596
17573
|
|
|
17597
17574
|
class OTRegistry extends Registry {
|
|
@@ -17679,6 +17656,12 @@ css /* scss */ `
|
|
|
17679
17656
|
height: 25px;
|
|
17680
17657
|
}
|
|
17681
17658
|
}
|
|
17659
|
+
/** Make the character a bit bigger
|
|
17660
|
+
compared to its neighbor INPUT box */
|
|
17661
|
+
.o-remove-selection {
|
|
17662
|
+
font-weight: bold;
|
|
17663
|
+
font-size: calc(100% + 4px);
|
|
17664
|
+
}
|
|
17682
17665
|
}
|
|
17683
17666
|
`;
|
|
17684
17667
|
/**
|
|
@@ -17774,6 +17757,9 @@ class SelectionInput extends Component {
|
|
|
17774
17757
|
this.confirm();
|
|
17775
17758
|
}
|
|
17776
17759
|
}
|
|
17760
|
+
extractRanges(value) {
|
|
17761
|
+
return this.props.hasSingleRange ? value.split(",")[0] : value;
|
|
17762
|
+
}
|
|
17777
17763
|
focus(rangeId) {
|
|
17778
17764
|
this.state.isMissing = false;
|
|
17779
17765
|
this.state.mode = "select-range";
|
|
@@ -17792,10 +17778,11 @@ class SelectionInput extends Component {
|
|
|
17792
17778
|
}
|
|
17793
17779
|
onInputChanged(rangeId, ev) {
|
|
17794
17780
|
const target = ev.target;
|
|
17781
|
+
const value = this.extractRanges(target.value);
|
|
17795
17782
|
this.env.model.dispatch("CHANGE_RANGE", {
|
|
17796
17783
|
id: this.id,
|
|
17797
17784
|
rangeId,
|
|
17798
|
-
value
|
|
17785
|
+
value,
|
|
17799
17786
|
});
|
|
17800
17787
|
this.triggerChange();
|
|
17801
17788
|
}
|
|
@@ -18688,6 +18675,18 @@ ChartPanel.props = {
|
|
|
18688
18675
|
onCloseSidePanel: Function,
|
|
18689
18676
|
};
|
|
18690
18677
|
|
|
18678
|
+
css /* scss */ `
|
|
18679
|
+
.o-spreadsheet {
|
|
18680
|
+
.o-icon {
|
|
18681
|
+
.small-text {
|
|
18682
|
+
font: bold 9px sans-serif;
|
|
18683
|
+
}
|
|
18684
|
+
.heavy-text {
|
|
18685
|
+
font: bold 16px sans-serif;
|
|
18686
|
+
}
|
|
18687
|
+
}
|
|
18688
|
+
}
|
|
18689
|
+
`;
|
|
18691
18690
|
// -----------------------------------------------------------------------------
|
|
18692
18691
|
// We need here the svg of the icons that we need to convert to images for the renderer
|
|
18693
18692
|
// -----------------------------------------------------------------------------
|
|
@@ -20564,14 +20563,31 @@ class ContentEditableHelper {
|
|
|
20564
20563
|
* */
|
|
20565
20564
|
getCurrentSelection() {
|
|
20566
20565
|
let { startElement, endElement, startSelectionOffset, endSelectionOffset } = this.getStartAndEndSelection();
|
|
20567
|
-
let startSizeBefore = this.
|
|
20568
|
-
let endSizeBefore = this.
|
|
20566
|
+
let startSizeBefore = this.findSelectionIndex(startElement, startSelectionOffset);
|
|
20567
|
+
let endSizeBefore = this.findSelectionIndex(endElement, endSelectionOffset);
|
|
20569
20568
|
return {
|
|
20570
|
-
start: startSizeBefore
|
|
20571
|
-
end: endSizeBefore
|
|
20569
|
+
start: startSizeBefore,
|
|
20570
|
+
end: endSizeBefore,
|
|
20572
20571
|
};
|
|
20573
20572
|
}
|
|
20574
|
-
|
|
20573
|
+
/**
|
|
20574
|
+
* Computes the text 'index' inside this.el based on the currently selected node and its offset.
|
|
20575
|
+
* The selected node is either a Text node or an Element node.
|
|
20576
|
+
*
|
|
20577
|
+
* case 1 -Text node:
|
|
20578
|
+
* the offset is the number of characters from the start of the node. We have to add this offset to the
|
|
20579
|
+
* content length of all previous nodes.
|
|
20580
|
+
*
|
|
20581
|
+
* case 2 - Element node:
|
|
20582
|
+
* the offset is the number of child nodes before the selected node. We have to add the content length of
|
|
20583
|
+
* all the bnodes prior to the selected node as well as the content of the child node before the offset.
|
|
20584
|
+
*
|
|
20585
|
+
* See the MDN documentation for more details.
|
|
20586
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
|
|
20587
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Range/endOffset
|
|
20588
|
+
*
|
|
20589
|
+
*/
|
|
20590
|
+
findSelectionIndex(nodeToFind, nodeOffset) {
|
|
20575
20591
|
let usedCharacters = 0;
|
|
20576
20592
|
let it = iterateChildren(this.el);
|
|
20577
20593
|
let current = it.next();
|
|
@@ -20598,6 +20614,28 @@ class ContentEditableHelper {
|
|
|
20598
20614
|
if (current.value !== nodeToFind) {
|
|
20599
20615
|
throw new Error("Cannot find the node in the children of the element");
|
|
20600
20616
|
}
|
|
20617
|
+
else {
|
|
20618
|
+
if (!current.value.hasChildNodes()) {
|
|
20619
|
+
usedCharacters += nodeOffset;
|
|
20620
|
+
}
|
|
20621
|
+
else {
|
|
20622
|
+
const children = [...current.value.childNodes].slice(0, nodeOffset);
|
|
20623
|
+
usedCharacters += children.reduce((acc, child, index) => {
|
|
20624
|
+
if (child.textContent !== null) {
|
|
20625
|
+
// need to account for paragraph nodes that implicitely add a new line
|
|
20626
|
+
// except for the last paragraph
|
|
20627
|
+
let chars = child.textContent.length;
|
|
20628
|
+
if (child.nodeName === "P" && index !== children.length - 1) {
|
|
20629
|
+
chars++;
|
|
20630
|
+
}
|
|
20631
|
+
return acc + chars;
|
|
20632
|
+
}
|
|
20633
|
+
else {
|
|
20634
|
+
return acc;
|
|
20635
|
+
}
|
|
20636
|
+
}, 0);
|
|
20637
|
+
}
|
|
20638
|
+
}
|
|
20601
20639
|
if (nodeToFind.nodeName === "P" && !isFirstParagraph && nodeToFind.textContent == "") {
|
|
20602
20640
|
usedCharacters++;
|
|
20603
20641
|
}
|
|
@@ -21398,13 +21436,13 @@ GridComposer.props = {
|
|
|
21398
21436
|
|
|
21399
21437
|
const CSS$1 = css /* scss */ `
|
|
21400
21438
|
.o-filter-icon {
|
|
21439
|
+
color: ${FILTERS_COLOR};
|
|
21401
21440
|
position: absolute;
|
|
21402
21441
|
display: flex;
|
|
21403
21442
|
align-items: center;
|
|
21404
21443
|
justify-content: center;
|
|
21405
21444
|
width: ${FILTER_ICON_EDGE_LENGTH}px;
|
|
21406
21445
|
height: ${FILTER_ICON_EDGE_LENGTH}px;
|
|
21407
|
-
color: #4a4f59;
|
|
21408
21446
|
}
|
|
21409
21447
|
.o-filter-icon:hover {
|
|
21410
21448
|
background: ${FILTERS_COLOR};
|
|
@@ -24135,17 +24173,17 @@ const CELL_TYPE_CONVERSION_MAP = {
|
|
|
24135
24173
|
const BORDER_STYLE_CONVERSION_MAP = {
|
|
24136
24174
|
dashDot: "thin",
|
|
24137
24175
|
dashDotDot: "thin",
|
|
24138
|
-
dashed: "
|
|
24139
|
-
dotted: "
|
|
24176
|
+
dashed: "dashed",
|
|
24177
|
+
dotted: "dotted",
|
|
24140
24178
|
double: "thin",
|
|
24141
24179
|
hair: "thin",
|
|
24142
|
-
medium: "
|
|
24180
|
+
medium: "medium",
|
|
24143
24181
|
mediumDashDot: "thin",
|
|
24144
24182
|
mediumDashDotDot: "thin",
|
|
24145
24183
|
mediumDashed: "thin",
|
|
24146
24184
|
none: undefined,
|
|
24147
24185
|
slantDashDot: "thin",
|
|
24148
|
-
thick: "
|
|
24186
|
+
thick: "thick",
|
|
24149
24187
|
thin: "thin",
|
|
24150
24188
|
};
|
|
24151
24189
|
/** Conversion map Horizontal Alignment in XLSX <=> Horizontal Alignment in o_spreadsheet*/
|
|
@@ -24644,7 +24682,7 @@ function convertBorderDescr$1(borderDescr, warningManager) {
|
|
|
24644
24682
|
return undefined;
|
|
24645
24683
|
addBorderDescrWarnings(borderDescr, warningManager);
|
|
24646
24684
|
const style = BORDER_STYLE_CONVERSION_MAP[borderDescr.style];
|
|
24647
|
-
return style ?
|
|
24685
|
+
return style ? { style, color: convertColor(borderDescr.color) } : undefined;
|
|
24648
24686
|
}
|
|
24649
24687
|
function convertStyles(data, warningManager) {
|
|
24650
24688
|
const stylesArray = data.styles.map((style) => {
|
|
@@ -26042,8 +26080,8 @@ function convertBorderDescr(descr) {
|
|
|
26042
26080
|
return undefined;
|
|
26043
26081
|
}
|
|
26044
26082
|
return {
|
|
26045
|
-
style: descr
|
|
26046
|
-
color: { rgb: descr
|
|
26083
|
+
style: descr.style,
|
|
26084
|
+
color: { rgb: descr.color },
|
|
26047
26085
|
};
|
|
26048
26086
|
}
|
|
26049
26087
|
function extractStyle(cell, data) {
|
|
@@ -26621,7 +26659,7 @@ const TABLE_HEADER_STYLE = {
|
|
|
26621
26659
|
const TABLE_HIGHLIGHTED_CELL_STYLE = {
|
|
26622
26660
|
bold: true,
|
|
26623
26661
|
};
|
|
26624
|
-
const TABLE_BORDER_STYLE =
|
|
26662
|
+
const TABLE_BORDER_STYLE = { style: "thin", color: "#000000FF" };
|
|
26625
26663
|
/**
|
|
26626
26664
|
* Convert the imported XLSX tables.
|
|
26627
26665
|
*
|
|
@@ -28190,7 +28228,7 @@ function normalizeV9(formula) {
|
|
|
28190
28228
|
* a breaking change is made in the way the state is handled, and an upgrade
|
|
28191
28229
|
* function should be defined
|
|
28192
28230
|
*/
|
|
28193
|
-
const CURRENT_VERSION =
|
|
28231
|
+
const CURRENT_VERSION = 13;
|
|
28194
28232
|
const INITIAL_SHEET_ID = "Sheet1";
|
|
28195
28233
|
/**
|
|
28196
28234
|
* This function tries to load anything that could look like a valid
|
|
@@ -28454,6 +28492,25 @@ const MIGRATIONS = [
|
|
|
28454
28492
|
return data;
|
|
28455
28493
|
},
|
|
28456
28494
|
},
|
|
28495
|
+
{
|
|
28496
|
+
description: "Change Border description structure",
|
|
28497
|
+
from: 12,
|
|
28498
|
+
to: 13,
|
|
28499
|
+
applyMigration(data) {
|
|
28500
|
+
for (const borderId in data.borders) {
|
|
28501
|
+
const border = data.borders[borderId];
|
|
28502
|
+
for (const position in border) {
|
|
28503
|
+
if (Array.isArray(border[position])) {
|
|
28504
|
+
border[position] = {
|
|
28505
|
+
style: border[position][0],
|
|
28506
|
+
color: border[position][1],
|
|
28507
|
+
};
|
|
28508
|
+
}
|
|
28509
|
+
}
|
|
28510
|
+
}
|
|
28511
|
+
return data;
|
|
28512
|
+
},
|
|
28513
|
+
},
|
|
28457
28514
|
];
|
|
28458
28515
|
/**
|
|
28459
28516
|
* This function is used to repair faulty data independently of the migration.
|
|
@@ -28789,7 +28846,7 @@ class CorePlugin extends BasePlugin {
|
|
|
28789
28846
|
* - borders
|
|
28790
28847
|
*/
|
|
28791
28848
|
class BordersPlugin extends CorePlugin {
|
|
28792
|
-
static getters = ["getCellBorder"];
|
|
28849
|
+
static getters = ["getCellBorder", "getBordersColors"];
|
|
28793
28850
|
borders = {};
|
|
28794
28851
|
// ---------------------------------------------------------------------------
|
|
28795
28852
|
// Command Handling
|
|
@@ -28820,10 +28877,15 @@ class BordersPlugin extends CorePlugin {
|
|
|
28820
28877
|
case "SET_BORDER":
|
|
28821
28878
|
this.setBorder(cmd.sheetId, cmd.col, cmd.row, cmd.border);
|
|
28822
28879
|
break;
|
|
28823
|
-
case "
|
|
28880
|
+
case "SET_ZONE_BORDERS":
|
|
28824
28881
|
if (cmd.border) {
|
|
28825
28882
|
const target = cmd.target.map((zone) => this.getters.expandZone(cmd.sheetId, zone));
|
|
28826
|
-
this.setBorders(cmd.sheetId, target, cmd.border
|
|
28883
|
+
this.setBorders(cmd.sheetId, target, cmd.border.position, cmd.border.color === ""
|
|
28884
|
+
? undefined
|
|
28885
|
+
: {
|
|
28886
|
+
style: cmd.border.style || DEFAULT_BORDER_DESC.style,
|
|
28887
|
+
color: cmd.border.color || DEFAULT_BORDER_DESC.color,
|
|
28888
|
+
});
|
|
28827
28889
|
}
|
|
28828
28890
|
break;
|
|
28829
28891
|
case "CLEAR_FORMATTING":
|
|
@@ -28912,6 +28974,23 @@ class BordersPlugin extends CorePlugin {
|
|
|
28912
28974
|
}
|
|
28913
28975
|
return border;
|
|
28914
28976
|
}
|
|
28977
|
+
getBordersColors(sheetId) {
|
|
28978
|
+
const colors = [];
|
|
28979
|
+
const sheetBorders = this.borders[sheetId];
|
|
28980
|
+
if (sheetBorders) {
|
|
28981
|
+
for (const borders of sheetBorders.filter(isDefined$1)) {
|
|
28982
|
+
for (const cellBorder of borders) {
|
|
28983
|
+
if (cellBorder?.horizontal) {
|
|
28984
|
+
colors.push(cellBorder.horizontal.color);
|
|
28985
|
+
}
|
|
28986
|
+
if (cellBorder?.vertical) {
|
|
28987
|
+
colors.push(cellBorder.vertical.color);
|
|
28988
|
+
}
|
|
28989
|
+
}
|
|
28990
|
+
}
|
|
28991
|
+
}
|
|
28992
|
+
return colors;
|
|
28993
|
+
}
|
|
28915
28994
|
// ---------------------------------------------------------------------------
|
|
28916
28995
|
// Private
|
|
28917
28996
|
// ---------------------------------------------------------------------------
|
|
@@ -29123,43 +29202,43 @@ class BordersPlugin extends CorePlugin {
|
|
|
29123
29202
|
* Set the borders of a zone by computing the borders to add from the given
|
|
29124
29203
|
* command
|
|
29125
29204
|
*/
|
|
29126
|
-
setBorders(sheetId, zones,
|
|
29127
|
-
if (
|
|
29205
|
+
setBorders(sheetId, zones, position, border) {
|
|
29206
|
+
if (position === "clear") {
|
|
29128
29207
|
return this.clearBorders(sheetId, zones);
|
|
29129
29208
|
}
|
|
29130
29209
|
for (let zone of zones) {
|
|
29131
|
-
if (
|
|
29210
|
+
if (position === "h" || position === "hv" || position === "all") {
|
|
29132
29211
|
for (let row = zone.top + 1; row <= zone.bottom; row++) {
|
|
29133
29212
|
for (let col = zone.left; col <= zone.right; col++) {
|
|
29134
|
-
this.addBorder(sheetId, col, row, { top:
|
|
29213
|
+
this.addBorder(sheetId, col, row, { top: border });
|
|
29135
29214
|
}
|
|
29136
29215
|
}
|
|
29137
29216
|
}
|
|
29138
|
-
if (
|
|
29217
|
+
if (position === "v" || position === "hv" || position === "all") {
|
|
29139
29218
|
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
29140
29219
|
for (let col = zone.left + 1; col <= zone.right; col++) {
|
|
29141
|
-
this.addBorder(sheetId, col, row, { left:
|
|
29220
|
+
this.addBorder(sheetId, col, row, { left: border });
|
|
29142
29221
|
}
|
|
29143
29222
|
}
|
|
29144
29223
|
}
|
|
29145
|
-
if (
|
|
29224
|
+
if (position === "left" || position === "all" || position === "external") {
|
|
29146
29225
|
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
29147
|
-
this.addBorder(sheetId, zone.left, row, { left:
|
|
29226
|
+
this.addBorder(sheetId, zone.left, row, { left: border });
|
|
29148
29227
|
}
|
|
29149
29228
|
}
|
|
29150
|
-
if (
|
|
29229
|
+
if (position === "right" || position === "all" || position === "external") {
|
|
29151
29230
|
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
29152
|
-
this.addBorder(sheetId, zone.right + 1, row, { left:
|
|
29231
|
+
this.addBorder(sheetId, zone.right + 1, row, { left: border });
|
|
29153
29232
|
}
|
|
29154
29233
|
}
|
|
29155
|
-
if (
|
|
29234
|
+
if (position === "top" || position === "all" || position === "external") {
|
|
29156
29235
|
for (let col = zone.left; col <= zone.right; col++) {
|
|
29157
|
-
this.addBorder(sheetId, col, zone.top, { top:
|
|
29236
|
+
this.addBorder(sheetId, col, zone.top, { top: border });
|
|
29158
29237
|
}
|
|
29159
29238
|
}
|
|
29160
|
-
if (
|
|
29239
|
+
if (position === "bottom" || position === "all" || position === "external") {
|
|
29161
29240
|
for (let col = zone.left; col <= zone.right; col++) {
|
|
29162
|
-
this.addBorder(sheetId, col, zone.bottom + 1, { top:
|
|
29241
|
+
this.addBorder(sheetId, col, zone.bottom + 1, { top: border });
|
|
29163
29242
|
}
|
|
29164
29243
|
}
|
|
29165
29244
|
}
|
|
@@ -29173,16 +29252,22 @@ class BordersPlugin extends CorePlugin {
|
|
|
29173
29252
|
const bordersBottomRight = this.getCellBorder({ sheetId, col: right, row: bottom });
|
|
29174
29253
|
this.clearBorders(sheetId, [zone]);
|
|
29175
29254
|
if (bordersTopLeft?.top) {
|
|
29176
|
-
this.setBorders(sheetId, [{ ...zone, bottom: top }], "top");
|
|
29255
|
+
this.setBorders(sheetId, [{ ...zone, bottom: top }], "top", bordersTopLeft.top);
|
|
29177
29256
|
}
|
|
29178
29257
|
if (bordersTopLeft?.left) {
|
|
29179
|
-
this.setBorders(sheetId, [{ ...zone, right: left }], "left");
|
|
29258
|
+
this.setBorders(sheetId, [{ ...zone, right: left }], "left", bordersTopLeft.left);
|
|
29259
|
+
}
|
|
29260
|
+
if (bordersBottomRight?.bottom) {
|
|
29261
|
+
this.setBorders(sheetId, [{ ...zone, top: bottom }], "bottom", bordersBottomRight.bottom);
|
|
29180
29262
|
}
|
|
29181
|
-
if (
|
|
29182
|
-
this.setBorders(sheetId, [{ ...zone, top: bottom }], "bottom");
|
|
29263
|
+
else if (bordersTopLeft?.bottom) {
|
|
29264
|
+
this.setBorders(sheetId, [{ ...zone, top: bottom }], "bottom", bordersTopLeft.bottom);
|
|
29183
29265
|
}
|
|
29184
|
-
if (bordersBottomRight?.right
|
|
29185
|
-
this.setBorders(sheetId, [{ ...zone, left: right }], "right");
|
|
29266
|
+
if (bordersBottomRight?.right) {
|
|
29267
|
+
this.setBorders(sheetId, [{ ...zone, left: right }], "right", bordersBottomRight.right);
|
|
29268
|
+
}
|
|
29269
|
+
else if (bordersTopLeft?.right) {
|
|
29270
|
+
this.setBorders(sheetId, [{ ...zone, left: right }], "right", bordersTopLeft.right);
|
|
29186
29271
|
}
|
|
29187
29272
|
}
|
|
29188
29273
|
// ---------------------------------------------------------------------------
|
|
@@ -32118,6 +32203,8 @@ class SheetPlugin extends CorePlugin {
|
|
|
32118
32203
|
"getSheetSize",
|
|
32119
32204
|
"getSheetZone",
|
|
32120
32205
|
"getPaneDivisions",
|
|
32206
|
+
"checkZonesExistInSheet",
|
|
32207
|
+
"getCommandZones",
|
|
32121
32208
|
];
|
|
32122
32209
|
sheetIdsMapName = {};
|
|
32123
32210
|
orderedSheetIds = [];
|
|
@@ -32127,7 +32214,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
32127
32214
|
// Command Handling
|
|
32128
32215
|
// ---------------------------------------------------------------------------
|
|
32129
32216
|
allowDispatch(cmd) {
|
|
32130
|
-
const genericChecks = this.chainValidations(this.checkSheetExists, this.
|
|
32217
|
+
const genericChecks = this.chainValidations(this.checkSheetExists, this.checkZonesAreInSheet)(cmd);
|
|
32131
32218
|
if (genericChecks !== 0 /* CommandResult.Success */) {
|
|
32132
32219
|
return genericChecks;
|
|
32133
32220
|
}
|
|
@@ -32467,6 +32554,37 @@ class SheetPlugin extends CorePlugin {
|
|
|
32467
32554
|
.map(({ col, row }) => this.getCell({ sheetId, col, row }))
|
|
32468
32555
|
.every((cell) => !cell || cell.content === "");
|
|
32469
32556
|
}
|
|
32557
|
+
getCommandZones(cmd) {
|
|
32558
|
+
const zones = [];
|
|
32559
|
+
if ("zone" in cmd) {
|
|
32560
|
+
zones.push(cmd.zone);
|
|
32561
|
+
}
|
|
32562
|
+
if ("target" in cmd) {
|
|
32563
|
+
zones.push(...cmd.target);
|
|
32564
|
+
}
|
|
32565
|
+
if ("ranges" in cmd) {
|
|
32566
|
+
zones.push(...cmd.ranges.map((rangeData) => this.getters.getRangeFromRangeData(rangeData).zone));
|
|
32567
|
+
}
|
|
32568
|
+
if ("col" in cmd && "row" in cmd) {
|
|
32569
|
+
zones.push({ top: cmd.row, left: cmd.col, bottom: cmd.row, right: cmd.col });
|
|
32570
|
+
}
|
|
32571
|
+
return zones;
|
|
32572
|
+
}
|
|
32573
|
+
/**
|
|
32574
|
+
* Check if zones in the command are well formed and
|
|
32575
|
+
* not outside the sheet.
|
|
32576
|
+
*/
|
|
32577
|
+
checkZonesExistInSheet(sheetId, zones) {
|
|
32578
|
+
if (!zones.every(isZoneValid))
|
|
32579
|
+
return 25 /* CommandResult.InvalidRange */;
|
|
32580
|
+
if (zones.length) {
|
|
32581
|
+
const sheetZone = this.getSheetZone(sheetId);
|
|
32582
|
+
return zones.every((zone) => isZoneInside(zone, sheetZone))
|
|
32583
|
+
? 0 /* CommandResult.Success */
|
|
32584
|
+
: 18 /* CommandResult.TargetOutOfSheet */;
|
|
32585
|
+
}
|
|
32586
|
+
return 0 /* CommandResult.Success */;
|
|
32587
|
+
}
|
|
32470
32588
|
updateCellPosition(cmd) {
|
|
32471
32589
|
const { sheetId, cellId, col, row } = cmd;
|
|
32472
32590
|
if (cellId) {
|
|
@@ -32915,9 +33033,6 @@ class SheetPlugin extends CorePlugin {
|
|
|
32915
33033
|
}
|
|
32916
33034
|
return { rowNumber, colNumber };
|
|
32917
33035
|
}
|
|
32918
|
-
// ----------------------------------------------------
|
|
32919
|
-
// HIDE / SHOW
|
|
32920
|
-
// ----------------------------------------------------
|
|
32921
33036
|
/**
|
|
32922
33037
|
* Check that any "sheetId" in the command matches an existing
|
|
32923
33038
|
* sheet.
|
|
@@ -32935,27 +33050,10 @@ class SheetPlugin extends CorePlugin {
|
|
|
32935
33050
|
* Check if zones in the command are well formed and
|
|
32936
33051
|
* not outside the sheet.
|
|
32937
33052
|
*/
|
|
32938
|
-
|
|
32939
|
-
|
|
32940
|
-
|
|
32941
|
-
|
|
32942
|
-
}
|
|
32943
|
-
if ("target" in cmd && Array.isArray(cmd.target)) {
|
|
32944
|
-
zones.push(...cmd.target);
|
|
32945
|
-
}
|
|
32946
|
-
if ("ranges" in cmd && Array.isArray(cmd.ranges)) {
|
|
32947
|
-
zones.push(...cmd.ranges.map((rangeData) => this.getters.getRangeFromRangeData(rangeData).zone));
|
|
32948
|
-
}
|
|
32949
|
-
if (!zones.every(isZoneValid)) {
|
|
32950
|
-
return 25 /* CommandResult.InvalidRange */;
|
|
32951
|
-
}
|
|
32952
|
-
else if (zones.length && "sheetId" in cmd) {
|
|
32953
|
-
const sheetZone = this.getSheetZone(cmd.sheetId);
|
|
32954
|
-
return zones.every((zone) => isZoneInside(zone, sheetZone))
|
|
32955
|
-
? 0 /* CommandResult.Success */
|
|
32956
|
-
: 18 /* CommandResult.TargetOutOfSheet */;
|
|
32957
|
-
}
|
|
32958
|
-
return 0 /* CommandResult.Success */;
|
|
33053
|
+
checkZonesAreInSheet(cmd) {
|
|
33054
|
+
if (!("sheetId" in cmd))
|
|
33055
|
+
return 0 /* CommandResult.Success */;
|
|
33056
|
+
return this.checkZonesExistInSheet(cmd.sheetId, this.getCommandZones(cmd));
|
|
32959
33057
|
}
|
|
32960
33058
|
}
|
|
32961
33059
|
|
|
@@ -33035,6 +33133,9 @@ class CustomColorsPlugin extends UIPlugin {
|
|
|
33035
33133
|
case "UPDATE_CHART":
|
|
33036
33134
|
case "CREATE_CHART":
|
|
33037
33135
|
case "ADD_CONDITIONAL_FORMAT":
|
|
33136
|
+
case "SET_BORDER":
|
|
33137
|
+
case "SET_ZONE_BORDERS":
|
|
33138
|
+
case "SET_FORMATTING":
|
|
33038
33139
|
this.shouldUpdateColors = true;
|
|
33039
33140
|
}
|
|
33040
33141
|
}
|
|
@@ -33049,8 +33150,7 @@ class CustomColorsPlugin extends UIPlugin {
|
|
|
33049
33150
|
getCustomColors() {
|
|
33050
33151
|
let usedColors = [];
|
|
33051
33152
|
for (const sheetId of this.getters.getSheetIds()) {
|
|
33052
|
-
|
|
33053
|
-
usedColors = usedColors.concat(this.getColorsFromCells(cells), this.getFormattingColors(sheetId), this.getChartColors(sheetId));
|
|
33153
|
+
usedColors = usedColors.concat(this.getColorsFromCells(sheetId), this.getFormattingColors(sheetId), this.getChartColors(sheetId));
|
|
33054
33154
|
}
|
|
33055
33155
|
return sortWithClusters([
|
|
33056
33156
|
...new Set(
|
|
@@ -33060,7 +33160,8 @@ class CustomColorsPlugin extends UIPlugin {
|
|
|
33060
33160
|
[...new Set([...usedColors, ...this.customColors])].filter(isColorValid).map(toHex)),
|
|
33061
33161
|
]).filter((color) => !COLOR_PICKER_DEFAULTS.includes(color));
|
|
33062
33162
|
}
|
|
33063
|
-
getColorsFromCells(
|
|
33163
|
+
getColorsFromCells(sheetId) {
|
|
33164
|
+
const cells = Object.values(this.getters.getCells(sheetId));
|
|
33064
33165
|
const colors = new Set();
|
|
33065
33166
|
for (const cell of cells) {
|
|
33066
33167
|
if (cell.style?.textColor) {
|
|
@@ -33070,6 +33171,9 @@ class CustomColorsPlugin extends UIPlugin {
|
|
|
33070
33171
|
colors.add(cell.style.fillColor);
|
|
33071
33172
|
}
|
|
33072
33173
|
}
|
|
33174
|
+
for (const color of this.getters.getBordersColors(sheetId)) {
|
|
33175
|
+
colors.add(color);
|
|
33176
|
+
}
|
|
33073
33177
|
return [...colors];
|
|
33074
33178
|
}
|
|
33075
33179
|
getFormattingColors(sheetId) {
|
|
@@ -33343,7 +33447,7 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
33343
33447
|
// magic "empty" value
|
|
33344
33448
|
// Returning {value: null} instead of undefined will ensure that we don't
|
|
33345
33449
|
// fall back on the default value of the argument provided to the formula's compute function
|
|
33346
|
-
return { value: null };
|
|
33450
|
+
return { value: null, format: cell?.format };
|
|
33347
33451
|
}
|
|
33348
33452
|
return getEvaluatedCell(cell);
|
|
33349
33453
|
}
|
|
@@ -33540,7 +33644,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
33540
33644
|
}
|
|
33541
33645
|
break;
|
|
33542
33646
|
case "PASTE_CONDITIONAL_FORMAT":
|
|
33543
|
-
this.pasteCf(cmd.
|
|
33647
|
+
this.pasteCf(cmd.originPosition, cmd.targetPosition, cmd.operation);
|
|
33544
33648
|
break;
|
|
33545
33649
|
}
|
|
33546
33650
|
}
|
|
@@ -36172,6 +36276,7 @@ function transformPositionWithMerge(cmd, executed) {
|
|
|
36172
36276
|
|
|
36173
36277
|
class Revision {
|
|
36174
36278
|
rootCommand;
|
|
36279
|
+
timestamp;
|
|
36175
36280
|
id;
|
|
36176
36281
|
clientId;
|
|
36177
36282
|
_commands = [];
|
|
@@ -36185,8 +36290,9 @@ class Revision {
|
|
|
36185
36290
|
* - clientId: Client who initiated the action
|
|
36186
36291
|
* - changes: List of changes applied on the state.
|
|
36187
36292
|
*/
|
|
36188
|
-
constructor(id, clientId, commands, rootCommand, changes) {
|
|
36293
|
+
constructor(id, clientId, commands, rootCommand, changes, timestamp) {
|
|
36189
36294
|
this.rootCommand = rootCommand;
|
|
36295
|
+
this.timestamp = timestamp;
|
|
36190
36296
|
this.id = id;
|
|
36191
36297
|
this.clientId = clientId;
|
|
36192
36298
|
this._commands = [...commands];
|
|
@@ -36258,7 +36364,7 @@ class Session extends EventBus {
|
|
|
36258
36364
|
save(rootCommand, commands, changes) {
|
|
36259
36365
|
if (!commands.length || !changes.length || !this.canApplyOptimisticUpdate())
|
|
36260
36366
|
return;
|
|
36261
|
-
const revision = new Revision(this.uuidGenerator.uuidv4(), this.clientId, commands, rootCommand, changes);
|
|
36367
|
+
const revision = new Revision(this.uuidGenerator.uuidv4(), this.clientId, commands, rootCommand, changes, Date.now());
|
|
36262
36368
|
this.revisions.append(revision.id, revision);
|
|
36263
36369
|
this.trigger("new-local-state-update", { id: revision.id });
|
|
36264
36370
|
this.sendUpdateMessage({
|
|
@@ -36309,13 +36415,9 @@ class Session extends EventBus {
|
|
|
36309
36415
|
}
|
|
36310
36416
|
loadInitialMessages(messages) {
|
|
36311
36417
|
this.isReplayingInitialRevisions = true;
|
|
36312
|
-
this.on("unexpected-revision-id", this, ({ revisionId }) => {
|
|
36313
|
-
throw new Error(`The spreadsheet could not be loaded. Revision ${revisionId} is corrupted.`);
|
|
36314
|
-
});
|
|
36315
36418
|
for (const message of messages) {
|
|
36316
36419
|
this.onMessageReceived(message);
|
|
36317
36420
|
}
|
|
36318
|
-
this.off("unexpected-revision-id", this);
|
|
36319
36421
|
this.isReplayingInitialRevisions = false;
|
|
36320
36422
|
}
|
|
36321
36423
|
/**
|
|
@@ -36401,6 +36503,10 @@ class Session extends EventBus {
|
|
|
36401
36503
|
onMessageReceived(message) {
|
|
36402
36504
|
if (this.isAlreadyProcessed(message))
|
|
36403
36505
|
return;
|
|
36506
|
+
if (this.isWrongServerRevisionId(message)) {
|
|
36507
|
+
this.trigger("unexpected-revision-id");
|
|
36508
|
+
return;
|
|
36509
|
+
}
|
|
36404
36510
|
switch (message.type) {
|
|
36405
36511
|
case "CLIENT_MOVED":
|
|
36406
36512
|
this.onClientMoved(message);
|
|
@@ -36427,12 +36533,8 @@ class Session extends EventBus {
|
|
|
36427
36533
|
});
|
|
36428
36534
|
break;
|
|
36429
36535
|
case "REMOTE_REVISION":
|
|
36430
|
-
|
|
36431
|
-
|
|
36432
|
-
return;
|
|
36433
|
-
}
|
|
36434
|
-
const { clientId, commands } = message;
|
|
36435
|
-
const revision = new Revision(message.nextRevisionId, clientId, commands, "REMOTE");
|
|
36536
|
+
const { clientId, commands, timestamp } = message;
|
|
36537
|
+
const revision = new Revision(message.nextRevisionId, clientId, commands, "REMOTE", undefined, timestamp);
|
|
36436
36538
|
if (revision.clientId !== this.clientId) {
|
|
36437
36539
|
this.revisions.insert(revision.id, revision, message.serverRevisionId);
|
|
36438
36540
|
const pendingCommands = this.pendingMessages
|
|
@@ -36445,7 +36547,7 @@ class Session extends EventBus {
|
|
|
36445
36547
|
}
|
|
36446
36548
|
break;
|
|
36447
36549
|
case "SNAPSHOT_CREATED": {
|
|
36448
|
-
const revision = new Revision(message.nextRevisionId, "server", [], "SNAPSHOT");
|
|
36550
|
+
const revision = new Revision(message.nextRevisionId, "server", [], "SNAPSHOT", undefined, Date.now());
|
|
36449
36551
|
this.revisions.insert(revision.id, revision, message.serverRevisionId);
|
|
36450
36552
|
this.dropPendingHistoryMessages();
|
|
36451
36553
|
this.trigger("snapshot");
|
|
@@ -36562,6 +36664,17 @@ class Session extends EventBus {
|
|
|
36562
36664
|
return false;
|
|
36563
36665
|
}
|
|
36564
36666
|
}
|
|
36667
|
+
isWrongServerRevisionId(message) {
|
|
36668
|
+
switch (message.type) {
|
|
36669
|
+
case "REMOTE_REVISION":
|
|
36670
|
+
case "REVISION_REDONE":
|
|
36671
|
+
case "REVISION_UNDONE":
|
|
36672
|
+
case "SNAPSHOT_CREATED":
|
|
36673
|
+
return message.serverRevisionId !== this.serverRevisionId;
|
|
36674
|
+
default:
|
|
36675
|
+
return false;
|
|
36676
|
+
}
|
|
36677
|
+
}
|
|
36565
36678
|
dropPendingHistoryMessages() {
|
|
36566
36679
|
this.waitingUndoRedoAck = false;
|
|
36567
36680
|
this.pendingMessages = this.pendingMessages.filter(({ type }) => type !== "REVISION_REDONE" && type !== "REVISION_UNDONE");
|
|
@@ -37277,7 +37390,7 @@ class RendererPlugin extends UIPlugin {
|
|
|
37277
37390
|
}
|
|
37278
37391
|
}
|
|
37279
37392
|
drawBorders(renderingContext) {
|
|
37280
|
-
const { ctx
|
|
37393
|
+
const { ctx } = renderingContext;
|
|
37281
37394
|
for (let box of this.boxes) {
|
|
37282
37395
|
const border = box.border;
|
|
37283
37396
|
if (border) {
|
|
@@ -37296,13 +37409,66 @@ class RendererPlugin extends UIPlugin {
|
|
|
37296
37409
|
}
|
|
37297
37410
|
}
|
|
37298
37411
|
}
|
|
37299
|
-
|
|
37412
|
+
/**
|
|
37413
|
+
* Following https://usefulangle.com/post/17/html5-canvas-drawing-1px-crisp-straight-lines,
|
|
37414
|
+
* we need to make sure that a "single" pixel line is drawn on a "half" pixel coordinate,
|
|
37415
|
+
* while a "double" pixel line is drawn on a "full" pixel coordinate. As, in the rendering
|
|
37416
|
+
* process, we always had 0.5 before rendering line (to make sure it is drawn on a "half"
|
|
37417
|
+
* pixel), we need to correct this behavior for the "medium" and the "dotted" styles, as
|
|
37418
|
+
* they are drawing a two pixels width line.
|
|
37419
|
+
* We also adapt here the coordinates of the line to make sure corner are correctly drawn,
|
|
37420
|
+
* avoiding a "round corners" effect. This is done by subtracting 1 pixel to the origin of
|
|
37421
|
+
* each line and adding 1 pixel to the end of each line (depending on the direction of the
|
|
37422
|
+
* line).
|
|
37423
|
+
*/
|
|
37424
|
+
function drawBorder({ style, color }, x1, y1, x2, y2) {
|
|
37300
37425
|
ctx.strokeStyle = color;
|
|
37301
|
-
|
|
37426
|
+
switch (style) {
|
|
37427
|
+
case "medium":
|
|
37428
|
+
ctx.lineWidth = 2;
|
|
37429
|
+
x1 += y1 === y2 ? -0.5 : 0.5;
|
|
37430
|
+
x2 += y1 === y2 ? 1.5 : 0.5;
|
|
37431
|
+
y1 += x1 === x2 ? -0.5 : 0.5;
|
|
37432
|
+
y2 += x1 === x2 ? 1.5 : 0.5;
|
|
37433
|
+
break;
|
|
37434
|
+
case "thick":
|
|
37435
|
+
ctx.lineWidth = 3;
|
|
37436
|
+
if (y1 === y2) {
|
|
37437
|
+
x1--;
|
|
37438
|
+
x2++;
|
|
37439
|
+
}
|
|
37440
|
+
if (x1 === x2) {
|
|
37441
|
+
y1--;
|
|
37442
|
+
y2++;
|
|
37443
|
+
}
|
|
37444
|
+
break;
|
|
37445
|
+
case "dashed":
|
|
37446
|
+
ctx.lineWidth = 1;
|
|
37447
|
+
ctx.setLineDash([1, 3]);
|
|
37448
|
+
break;
|
|
37449
|
+
case "dotted":
|
|
37450
|
+
ctx.lineWidth = 1;
|
|
37451
|
+
if (y1 === y2) {
|
|
37452
|
+
x1 += 0.5;
|
|
37453
|
+
x2 += 0.5;
|
|
37454
|
+
}
|
|
37455
|
+
if (x1 === x2) {
|
|
37456
|
+
y1 += 0.5;
|
|
37457
|
+
y2 += 0.5;
|
|
37458
|
+
}
|
|
37459
|
+
ctx.setLineDash([1, 1]);
|
|
37460
|
+
break;
|
|
37461
|
+
case "thin":
|
|
37462
|
+
default:
|
|
37463
|
+
ctx.lineWidth = 1;
|
|
37464
|
+
break;
|
|
37465
|
+
}
|
|
37302
37466
|
ctx.beginPath();
|
|
37303
37467
|
ctx.moveTo(x1, y1);
|
|
37304
37468
|
ctx.lineTo(x2, y2);
|
|
37305
37469
|
ctx.stroke();
|
|
37470
|
+
ctx.lineWidth = 1;
|
|
37471
|
+
ctx.setLineDash([]);
|
|
37306
37472
|
}
|
|
37307
37473
|
}
|
|
37308
37474
|
drawTexts(renderingContext) {
|
|
@@ -37780,6 +37946,9 @@ class SelectionInputPlugin extends UIPlugin {
|
|
|
37780
37946
|
activeSheet;
|
|
37781
37947
|
willAddNewRange = false;
|
|
37782
37948
|
constructor(config, initialRanges, inputHasSingleRange) {
|
|
37949
|
+
if (inputHasSingleRange && initialRanges.length > 1) {
|
|
37950
|
+
throw new Error("Input with a single range cannot be instantiated with several range references.");
|
|
37951
|
+
}
|
|
37783
37952
|
super(config);
|
|
37784
37953
|
this.inputHasSingleRange = inputHasSingleRange;
|
|
37785
37954
|
this.insertNewRange(0, initialRanges);
|
|
@@ -37799,6 +37968,11 @@ class SelectionInputPlugin extends UIPlugin {
|
|
|
37799
37968
|
return 30 /* CommandResult.MaximumRangesReached */;
|
|
37800
37969
|
}
|
|
37801
37970
|
break;
|
|
37971
|
+
case "CHANGE_RANGE":
|
|
37972
|
+
if (this.inputHasSingleRange && cmd.value.split(",").length > 1) {
|
|
37973
|
+
return 30 /* CommandResult.MaximumRangesReached */;
|
|
37974
|
+
}
|
|
37975
|
+
break;
|
|
37802
37976
|
}
|
|
37803
37977
|
return 0 /* CommandResult.Success */;
|
|
37804
37978
|
}
|
|
@@ -38455,18 +38629,7 @@ class SheetUIPlugin extends UIPlugin {
|
|
|
38455
38629
|
// Command Handling
|
|
38456
38630
|
// ---------------------------------------------------------------------------
|
|
38457
38631
|
allowDispatch(cmd) {
|
|
38458
|
-
|
|
38459
|
-
case "AUTORESIZE_ROWS":
|
|
38460
|
-
case "AUTORESIZE_COLUMNS":
|
|
38461
|
-
try {
|
|
38462
|
-
this.getters.getSheet(cmd.sheetId);
|
|
38463
|
-
break;
|
|
38464
|
-
}
|
|
38465
|
-
catch (error) {
|
|
38466
|
-
return 27 /* CommandResult.InvalidSheetId */;
|
|
38467
|
-
}
|
|
38468
|
-
}
|
|
38469
|
-
return 0 /* CommandResult.Success */;
|
|
38632
|
+
return this.chainValidations(this.checkSheetExists, this.checkZonesAreInSheet)(cmd);
|
|
38470
38633
|
}
|
|
38471
38634
|
handle(cmd) {
|
|
38472
38635
|
switch (cmd.type) {
|
|
@@ -38666,6 +38829,31 @@ class SheetUIPlugin extends UIPlugin {
|
|
|
38666
38829
|
splitWord.push(wordPart);
|
|
38667
38830
|
return splitWord;
|
|
38668
38831
|
}
|
|
38832
|
+
/**
|
|
38833
|
+
* Check that any "sheetId" in the command matches an existing
|
|
38834
|
+
* sheet.
|
|
38835
|
+
*/
|
|
38836
|
+
checkSheetExists(cmd) {
|
|
38837
|
+
if ("sheetId" in cmd && this.getters.tryGetSheet(cmd.sheetId) === undefined) {
|
|
38838
|
+
return 27 /* CommandResult.InvalidSheetId */;
|
|
38839
|
+
}
|
|
38840
|
+
return 0 /* CommandResult.Success */;
|
|
38841
|
+
}
|
|
38842
|
+
/**
|
|
38843
|
+
* Check if zones in the command are well formed and
|
|
38844
|
+
* not outside the sheet.
|
|
38845
|
+
*/
|
|
38846
|
+
checkZonesAreInSheet(cmd) {
|
|
38847
|
+
const sheetId = "sheetId" in cmd ? cmd.sheetId : this.getters.tryGetActiveSheetId();
|
|
38848
|
+
const zones = this.getters.getCommandZones(cmd);
|
|
38849
|
+
if (!sheetId && zones.length > 0) {
|
|
38850
|
+
return 92 /* CommandResult.NoActiveSheet */;
|
|
38851
|
+
}
|
|
38852
|
+
if (sheetId && zones.length > 0) {
|
|
38853
|
+
return this.getters.checkZonesExistInSheet(sheetId, zones);
|
|
38854
|
+
}
|
|
38855
|
+
return 0 /* CommandResult.Success */;
|
|
38856
|
+
}
|
|
38669
38857
|
}
|
|
38670
38858
|
|
|
38671
38859
|
const genericRepeatsTransforms = [
|
|
@@ -39490,8 +39678,8 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
39490
39678
|
this.pasteCell(origin, position, this.operation, clipboardOptions);
|
|
39491
39679
|
if (shouldPasteCF) {
|
|
39492
39680
|
this.dispatch("PASTE_CONDITIONAL_FORMAT", {
|
|
39493
|
-
|
|
39494
|
-
|
|
39681
|
+
originPosition: origin.position,
|
|
39682
|
+
targetPosition: position,
|
|
39495
39683
|
operation: this.operation,
|
|
39496
39684
|
});
|
|
39497
39685
|
}
|
|
@@ -39882,7 +40070,7 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
39882
40070
|
allowDispatch(cmd) {
|
|
39883
40071
|
switch (cmd.type) {
|
|
39884
40072
|
case "CUT":
|
|
39885
|
-
const zones = cmd.
|
|
40073
|
+
const zones = cmd.cutTarget || this.getters.getSelectedZones();
|
|
39886
40074
|
const state = this.getClipboardState(zones, cmd.type);
|
|
39887
40075
|
return state.isCutAllowed(zones);
|
|
39888
40076
|
case "PASTE":
|
|
@@ -39912,7 +40100,7 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
39912
40100
|
switch (cmd.type) {
|
|
39913
40101
|
case "COPY":
|
|
39914
40102
|
case "CUT":
|
|
39915
|
-
const zones = ("
|
|
40103
|
+
const zones = ("cutTarget" in cmd && cmd.cutTarget) || this.getters.getSelectedZones();
|
|
39916
40104
|
this.state = this.getClipboardState(zones, cmd.type);
|
|
39917
40105
|
this.status = "visible";
|
|
39918
40106
|
break;
|
|
@@ -40868,6 +41056,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
40868
41056
|
"isSelected",
|
|
40869
41057
|
"isSingleColSelected",
|
|
40870
41058
|
"getElementsFromSelection",
|
|
41059
|
+
"tryGetActiveSheetId",
|
|
40871
41060
|
];
|
|
40872
41061
|
gridSelection = {
|
|
40873
41062
|
anchor: {
|
|
@@ -41083,6 +41272,9 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
41083
41272
|
getActiveSheetId() {
|
|
41084
41273
|
return this.activeSheet.id;
|
|
41085
41274
|
}
|
|
41275
|
+
tryGetActiveSheetId() {
|
|
41276
|
+
return this.activeSheet?.id;
|
|
41277
|
+
}
|
|
41086
41278
|
getActiveCell() {
|
|
41087
41279
|
return this.getters.getEvaluatedCell(this.getActivePosition());
|
|
41088
41280
|
}
|
|
@@ -41285,7 +41477,8 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
41285
41477
|
},
|
|
41286
41478
|
zone: selectedZone,
|
|
41287
41479
|
};
|
|
41288
|
-
this.
|
|
41480
|
+
const selections = this.gridSelection.zones.map((zone) => updateSelectionOnDeletion(zone, "left", [...cmd.elements]));
|
|
41481
|
+
this.setSelectionMixin(anchor, selections);
|
|
41289
41482
|
}
|
|
41290
41483
|
onRowsRemoved(cmd) {
|
|
41291
41484
|
const { cell, zone } = this.gridSelection.anchor;
|
|
@@ -41299,13 +41492,18 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
41299
41492
|
},
|
|
41300
41493
|
zone: selectedZone,
|
|
41301
41494
|
};
|
|
41302
|
-
this.
|
|
41495
|
+
const selections = this.gridSelection.zones.map((zone) => updateSelectionOnDeletion(zone, "top", [...cmd.elements]));
|
|
41496
|
+
this.setSelectionMixin(anchor, selections);
|
|
41303
41497
|
}
|
|
41304
41498
|
onAddElements(cmd) {
|
|
41305
|
-
const
|
|
41306
|
-
const
|
|
41307
|
-
const
|
|
41308
|
-
|
|
41499
|
+
const start = cmd.dimension === "COL" ? "left" : "top";
|
|
41500
|
+
const anchorZone = updateSelectionOnInsertion(this.gridSelection.anchor.zone, start, cmd.base, cmd.position, cmd.quantity);
|
|
41501
|
+
const selection = this.gridSelection.zones.map((zone) => updateSelectionOnInsertion(zone, start, cmd.base, cmd.position, cmd.quantity));
|
|
41502
|
+
const anchor = {
|
|
41503
|
+
cell: { col: anchorZone.left, row: anchorZone.top },
|
|
41504
|
+
zone: anchorZone,
|
|
41505
|
+
};
|
|
41506
|
+
this.setSelectionMixin(anchor, selection);
|
|
41309
41507
|
}
|
|
41310
41508
|
onMoveElements(cmd) {
|
|
41311
41509
|
const thickness = cmd.elements.length;
|
|
@@ -41323,7 +41521,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
41323
41521
|
const deltaCol = isBasedBefore && isCol ? thickness : 0;
|
|
41324
41522
|
const deltaRow = isBasedBefore && !isCol ? thickness : 0;
|
|
41325
41523
|
this.dispatch("CUT", {
|
|
41326
|
-
|
|
41524
|
+
cutTarget: [
|
|
41327
41525
|
{
|
|
41328
41526
|
left: isCol ? start + deltaCol : 0,
|
|
41329
41527
|
right: isCol ? end + deltaCol : this.getters.getNumberCols(cmd.sheetId) - 1,
|
|
@@ -42551,7 +42749,6 @@ css /* scss */ `
|
|
|
42551
42749
|
color: dimgrey;
|
|
42552
42750
|
}
|
|
42553
42751
|
.o-sidePanelClose {
|
|
42554
|
-
font-size: 1.5rem;
|
|
42555
42752
|
padding: 5px 10px;
|
|
42556
42753
|
cursor: pointer;
|
|
42557
42754
|
&:hover {
|
|
@@ -42736,7 +42933,6 @@ css /* scss */ `
|
|
|
42736
42933
|
justify-content: center;
|
|
42737
42934
|
align-items: center;
|
|
42738
42935
|
margin: 2px;
|
|
42739
|
-
padding: 0px 3px;
|
|
42740
42936
|
border-radius: 2px;
|
|
42741
42937
|
min-width: 20px;
|
|
42742
42938
|
}
|
|
@@ -42793,7 +42989,228 @@ ActionButton.props = {
|
|
|
42793
42989
|
onClick: { type: Function, optional: true },
|
|
42794
42990
|
};
|
|
42795
42991
|
|
|
42992
|
+
/**
|
|
42993
|
+
* List the available borders positions and the corresponding icons.
|
|
42994
|
+
* The structure of this array is defined to match the order/lines we want
|
|
42995
|
+
* to display in the topbar's border tool.
|
|
42996
|
+
*/
|
|
42997
|
+
const BORDER_POSITIONS = [
|
|
42998
|
+
[
|
|
42999
|
+
["all", "o-spreadsheet-Icon.BORDERS"],
|
|
43000
|
+
["hv", "o-spreadsheet-Icon.BORDER_HV"],
|
|
43001
|
+
["h", "o-spreadsheet-Icon.BORDER_H"],
|
|
43002
|
+
["v", "o-spreadsheet-Icon.BORDER_V"],
|
|
43003
|
+
["external", "o-spreadsheet-Icon.BORDER_EXTERNAL"],
|
|
43004
|
+
],
|
|
43005
|
+
[
|
|
43006
|
+
["left", "o-spreadsheet-Icon.BORDER_LEFT"],
|
|
43007
|
+
["top", "o-spreadsheet-Icon.BORDER_TOP"],
|
|
43008
|
+
["right", "o-spreadsheet-Icon.BORDER_RIGHT"],
|
|
43009
|
+
["bottom", "o-spreadsheet-Icon.BORDER_BOTTOM"],
|
|
43010
|
+
["clear", "o-spreadsheet-Icon.BORDER_CLEAR"],
|
|
43011
|
+
],
|
|
43012
|
+
];
|
|
43013
|
+
// -----------------------------------------------------------------------------
|
|
43014
|
+
// Border Editor
|
|
43015
|
+
// -----------------------------------------------------------------------------
|
|
43016
|
+
css /* scss */ `
|
|
43017
|
+
.o-border-selector {
|
|
43018
|
+
padding: 4px;
|
|
43019
|
+
}
|
|
43020
|
+
.o-divider {
|
|
43021
|
+
border-right: 1px solid #e0e2e4;
|
|
43022
|
+
margin: 0 6px;
|
|
43023
|
+
}
|
|
43024
|
+
.o-border-selector-section {
|
|
43025
|
+
.o-dropdown-line {
|
|
43026
|
+
height: 30px;
|
|
43027
|
+
margin: 1px;
|
|
43028
|
+
.o-line-item {
|
|
43029
|
+
padding: 4px;
|
|
43030
|
+
width: 18px;
|
|
43031
|
+
height: 18px;
|
|
43032
|
+
}
|
|
43033
|
+
}
|
|
43034
|
+
.o-border-style-tool {
|
|
43035
|
+
padding: 0px 3px;
|
|
43036
|
+
margin: 2px;
|
|
43037
|
+
height: 25px;
|
|
43038
|
+
}
|
|
43039
|
+
}
|
|
43040
|
+
.o-style-preview {
|
|
43041
|
+
margin: 7px 5px 7px 5px;
|
|
43042
|
+
width: 60px;
|
|
43043
|
+
height: 5px;
|
|
43044
|
+
}
|
|
43045
|
+
.o-style-thin {
|
|
43046
|
+
border-bottom: 1px solid #000000;
|
|
43047
|
+
}
|
|
43048
|
+
.o-style-medium {
|
|
43049
|
+
border-bottom: 2px solid #000000;
|
|
43050
|
+
}
|
|
43051
|
+
.o-style-thick {
|
|
43052
|
+
border-bottom: 3px solid #000000;
|
|
43053
|
+
}
|
|
43054
|
+
.o-style-dashed {
|
|
43055
|
+
border-bottom: 1px dashed #000000;
|
|
43056
|
+
}
|
|
43057
|
+
.o-style-dotted {
|
|
43058
|
+
border-bottom: 1px dotted #000000;
|
|
43059
|
+
}
|
|
43060
|
+
.o-dropdown-border-type {
|
|
43061
|
+
&:not(.o-disabled):not(.active):hover {
|
|
43062
|
+
background-color: ${BG_HOVER_COLOR};
|
|
43063
|
+
}
|
|
43064
|
+
}
|
|
43065
|
+
.o-dropdown-border-check {
|
|
43066
|
+
width: 20px;
|
|
43067
|
+
font-size: 12px;
|
|
43068
|
+
}
|
|
43069
|
+
.o-border-style-dropdown {
|
|
43070
|
+
background: #ffffff;
|
|
43071
|
+
padding: 4px;
|
|
43072
|
+
.o-dropdown-line {
|
|
43073
|
+
.o-line-item.active {
|
|
43074
|
+
background-color: rgba(0, 0, 0, 0.2);
|
|
43075
|
+
}
|
|
43076
|
+
}
|
|
43077
|
+
}
|
|
43078
|
+
.o-border-picker-button {
|
|
43079
|
+
padding: 0px !important;
|
|
43080
|
+
margin: 5px 0px 0px 0px !important;
|
|
43081
|
+
height: 25px !important;
|
|
43082
|
+
}
|
|
43083
|
+
`;
|
|
43084
|
+
class BorderEditor extends Component {
|
|
43085
|
+
static template = "o-spreadsheet-BorderEditor";
|
|
43086
|
+
static components = { ColorPickerWidget, Popover };
|
|
43087
|
+
BORDER_POSITIONS = BORDER_POSITIONS;
|
|
43088
|
+
lineStyleButtonRef = useRef("lineStyleButton");
|
|
43089
|
+
borderStyles = borderStyles;
|
|
43090
|
+
state = useState({
|
|
43091
|
+
activeTool: undefined,
|
|
43092
|
+
});
|
|
43093
|
+
toggleDropdownTool(tool) {
|
|
43094
|
+
const isOpen = this.state.activeTool === tool;
|
|
43095
|
+
this.state.activeTool = isOpen ? undefined : tool;
|
|
43096
|
+
}
|
|
43097
|
+
closeDropdown() {
|
|
43098
|
+
this.state.activeTool = undefined;
|
|
43099
|
+
}
|
|
43100
|
+
setBorderPosition(position) {
|
|
43101
|
+
this.props.onBorderPositionPicked(position);
|
|
43102
|
+
this.closeDropdown();
|
|
43103
|
+
}
|
|
43104
|
+
setBorderColor(color) {
|
|
43105
|
+
this.props.onBorderColorPicked(color);
|
|
43106
|
+
this.closeDropdown();
|
|
43107
|
+
}
|
|
43108
|
+
setBorderStyle(style) {
|
|
43109
|
+
this.props.onBorderStylePicked(style);
|
|
43110
|
+
this.closeDropdown();
|
|
43111
|
+
}
|
|
43112
|
+
get lineStylePickerPopoverProps() {
|
|
43113
|
+
return {
|
|
43114
|
+
anchorRect: this.lineStylePickerAnchorRect,
|
|
43115
|
+
positioning: "BottomLeft",
|
|
43116
|
+
verticalOffset: 0,
|
|
43117
|
+
};
|
|
43118
|
+
}
|
|
43119
|
+
get popoverProps() {
|
|
43120
|
+
return {
|
|
43121
|
+
anchorRect: this.props.anchorRect,
|
|
43122
|
+
maxHeight: this.props.maxHeight,
|
|
43123
|
+
positioning: "BottomLeft",
|
|
43124
|
+
verticalOffset: 0,
|
|
43125
|
+
};
|
|
43126
|
+
}
|
|
43127
|
+
get lineStylePickerAnchorRect() {
|
|
43128
|
+
const button = this.lineStyleButtonRef.el;
|
|
43129
|
+
if (button === null) {
|
|
43130
|
+
return { x: 0, y: 0, width: 0, height: 0 };
|
|
43131
|
+
}
|
|
43132
|
+
const buttonRect = button.getBoundingClientRect();
|
|
43133
|
+
return {
|
|
43134
|
+
x: buttonRect.x,
|
|
43135
|
+
y: buttonRect.y,
|
|
43136
|
+
width: buttonRect.width,
|
|
43137
|
+
height: buttonRect.height,
|
|
43138
|
+
};
|
|
43139
|
+
}
|
|
43140
|
+
}
|
|
43141
|
+
BorderEditor.props = {
|
|
43142
|
+
class: { type: String, optional: true },
|
|
43143
|
+
currentBorderColor: { type: String, optional: false },
|
|
43144
|
+
currentBorderStyle: { type: String, optional: false },
|
|
43145
|
+
currentBorderPosition: { type: String, optional: true },
|
|
43146
|
+
onBorderColorPicked: Function,
|
|
43147
|
+
onBorderStylePicked: Function,
|
|
43148
|
+
onBorderPositionPicked: Function,
|
|
43149
|
+
maxHeight: { type: Number, optional: true },
|
|
43150
|
+
anchorRect: Object,
|
|
43151
|
+
};
|
|
43152
|
+
|
|
43153
|
+
class BorderEditorWidget extends Component {
|
|
43154
|
+
static template = "o-spreadsheet-BorderEditorWidget";
|
|
43155
|
+
static components = { BorderEditor };
|
|
43156
|
+
borderEditorButtonRef = useRef("borderEditorButton");
|
|
43157
|
+
state = useState({
|
|
43158
|
+
currentColor: DEFAULT_BORDER_DESC.color,
|
|
43159
|
+
currentStyle: DEFAULT_BORDER_DESC.style,
|
|
43160
|
+
currentPosition: undefined,
|
|
43161
|
+
});
|
|
43162
|
+
get borderEditorAnchorRect() {
|
|
43163
|
+
const button = this.borderEditorButtonRef.el;
|
|
43164
|
+
const buttonRect = button.getBoundingClientRect();
|
|
43165
|
+
return {
|
|
43166
|
+
x: buttonRect.x,
|
|
43167
|
+
y: buttonRect.y,
|
|
43168
|
+
width: buttonRect.width,
|
|
43169
|
+
height: buttonRect.height,
|
|
43170
|
+
};
|
|
43171
|
+
}
|
|
43172
|
+
onBorderPositionPicked(position) {
|
|
43173
|
+
this.state.currentPosition = position;
|
|
43174
|
+
this.updateBorder();
|
|
43175
|
+
}
|
|
43176
|
+
onBorderColorPicked(color) {
|
|
43177
|
+
this.state.currentColor = color;
|
|
43178
|
+
this.updateBorder();
|
|
43179
|
+
}
|
|
43180
|
+
onBorderStylePicked(style) {
|
|
43181
|
+
this.state.currentStyle = style;
|
|
43182
|
+
this.updateBorder();
|
|
43183
|
+
}
|
|
43184
|
+
updateBorder() {
|
|
43185
|
+
if (this.state.currentPosition === undefined) {
|
|
43186
|
+
return;
|
|
43187
|
+
}
|
|
43188
|
+
this.env.model.dispatch("SET_ZONE_BORDERS", {
|
|
43189
|
+
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
43190
|
+
target: this.env.model.getters.getSelectedZones(),
|
|
43191
|
+
border: {
|
|
43192
|
+
position: this.state.currentPosition,
|
|
43193
|
+
color: this.state.currentColor,
|
|
43194
|
+
style: this.state.currentStyle,
|
|
43195
|
+
},
|
|
43196
|
+
});
|
|
43197
|
+
}
|
|
43198
|
+
}
|
|
43199
|
+
BorderEditorWidget.props = {
|
|
43200
|
+
toggleBorderEditor: Function,
|
|
43201
|
+
showBorderEditor: Boolean,
|
|
43202
|
+
disabled: { type: Boolean, optional: true },
|
|
43203
|
+
dropdownMaxHeight: { type: Number, optional: true },
|
|
43204
|
+
class: { type: String, optional: true },
|
|
43205
|
+
};
|
|
43206
|
+
|
|
42796
43207
|
const COMPOSER_MAX_HEIGHT = 100;
|
|
43208
|
+
/* svg free of use from https://uxwing.com/formula-fx-icon/ */
|
|
43209
|
+
const FX_SVG = /*xml*/ `
|
|
43210
|
+
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 121.8 122.9' width='16' height='16' focusable='false'>
|
|
43211
|
+
<path d='m28 34-4 5v2h10l-6 40c-4 22-6 28-7 30-2 2-3 3-5 3-3 0-7-2-9-4H4c-2 2-4 4-4 7s4 6 8 6 9-2 15-8c8-7 13-17 18-39l7-35 13-1 3-6H49c4-23 7-27 11-27 2 0 5 2 8 6h4c1-1 4-4 4-7 0-2-3-6-9-6-5 0-13 4-20 10-6 7-9 14-11 24h-8zm41 16c4-5 7-7 8-7s2 1 5 9l3 12c-7 11-12 17-16 17l-3-1-2-1c-3 0-6 3-6 7s3 7 7 7c6 0 12-6 22-23l3 10c3 9 6 13 10 13 5 0 11-4 18-15l-3-4c-4 6-7 8-8 8-2 0-4-3-6-10l-5-15 8-10 6-4 3 1 3 2c2 0 6-3 6-7s-2-7-6-7c-6 0-11 5-21 20l-2-6c-3-9-5-14-9-14-5 0-12 6-18 15l3 3z' fill='#BDBDBD'/>
|
|
43212
|
+
</svg>
|
|
43213
|
+
`;
|
|
42797
43214
|
css /* scss */ `
|
|
42798
43215
|
.o-topbar-composer {
|
|
42799
43216
|
height: fit-content;
|
|
@@ -42801,9 +43218,10 @@ css /* scss */ `
|
|
|
42801
43218
|
border: 1px solid;
|
|
42802
43219
|
z-index: ${ComponentsImportance.TopBarComposer};
|
|
42803
43220
|
|
|
42804
|
-
.o-composer:empty:not(:focus)::before {
|
|
42805
|
-
|
|
42806
|
-
|
|
43221
|
+
.o-composer:empty:not(:focus):not(.active)::before {
|
|
43222
|
+
content: url("data:image/svg+xml,${encodeURIComponent(FX_SVG)}");
|
|
43223
|
+
position: relative;
|
|
43224
|
+
top: 20%;
|
|
42807
43225
|
}
|
|
42808
43226
|
}
|
|
42809
43227
|
`;
|
|
@@ -42926,11 +43344,6 @@ FontSizeEditor.props = {
|
|
|
42926
43344
|
dropdownStyle: String,
|
|
42927
43345
|
};
|
|
42928
43346
|
|
|
42929
|
-
// If we ever change these colors, make sure the filter tool stays green to match the icon in the grid
|
|
42930
|
-
const ACTIVE_BG_COLOR = BACKGROUND_HEADER_FILTER_COLOR;
|
|
42931
|
-
const ACTIVE_FONT_COLOR = FILTERS_COLOR;
|
|
42932
|
-
const HOVERED_BG_COLOR = BG_HOVER_COLOR;
|
|
42933
|
-
const HOVERED_FONT_COLOR = "#000";
|
|
42934
43347
|
// -----------------------------------------------------------------------------
|
|
42935
43348
|
// TopBar
|
|
42936
43349
|
// -----------------------------------------------------------------------------
|
|
@@ -42940,27 +43353,6 @@ css /* scss */ `
|
|
|
42940
43353
|
font-size: 13px;
|
|
42941
43354
|
font-weight: 500;
|
|
42942
43355
|
|
|
42943
|
-
.o-topbar-hoverable {
|
|
42944
|
-
cursor: pointer;
|
|
42945
|
-
.o-icon {
|
|
42946
|
-
color: ${ICONS_COLOR};
|
|
42947
|
-
}
|
|
42948
|
-
&:not(.o-disabled):not(.active):hover {
|
|
42949
|
-
background-color: ${HOVERED_BG_COLOR};
|
|
42950
|
-
color: ${HOVERED_FONT_COLOR};
|
|
42951
|
-
.o-icon {
|
|
42952
|
-
color: ${HOVERED_FONT_COLOR};
|
|
42953
|
-
}
|
|
42954
|
-
}
|
|
42955
|
-
&.active {
|
|
42956
|
-
background-color: ${ACTIVE_BG_COLOR};
|
|
42957
|
-
color: ${ACTIVE_FONT_COLOR};
|
|
42958
|
-
.o-icon {
|
|
42959
|
-
color: ${ACTIVE_FONT_COLOR};
|
|
42960
|
-
}
|
|
42961
|
-
}
|
|
42962
|
-
}
|
|
42963
|
-
|
|
42964
43356
|
.o-topbar-top {
|
|
42965
43357
|
border-bottom: 1px solid ${SEPARATOR_COLOR};
|
|
42966
43358
|
padding: 2px 10px;
|
|
@@ -42970,6 +43362,11 @@ css /* scss */ `
|
|
|
42970
43362
|
.o-topbar-menu {
|
|
42971
43363
|
padding: 4px 6px;
|
|
42972
43364
|
margin: 0 2px;
|
|
43365
|
+
|
|
43366
|
+
&.active {
|
|
43367
|
+
background-color: ${BG_HOVER_COLOR};
|
|
43368
|
+
color: #000;
|
|
43369
|
+
}
|
|
42973
43370
|
}
|
|
42974
43371
|
}
|
|
42975
43372
|
}
|
|
@@ -43047,6 +43444,7 @@ class TopBar extends Component {
|
|
|
43047
43444
|
TopBarComposer,
|
|
43048
43445
|
FontSizeEditor,
|
|
43049
43446
|
ActionButton,
|
|
43447
|
+
BorderEditorWidget,
|
|
43050
43448
|
};
|
|
43051
43449
|
state = useState({
|
|
43052
43450
|
menuState: { isOpen: false, position: null, menuItems: [] },
|
|
@@ -43122,7 +43520,9 @@ class TopBar extends Component {
|
|
|
43122
43520
|
this.state.activeTool = "";
|
|
43123
43521
|
this.state.menuState.isOpen = true;
|
|
43124
43522
|
this.state.menuState.position = { x: left, y: top + height };
|
|
43125
|
-
this.state.menuState.menuItems = menu
|
|
43523
|
+
this.state.menuState.menuItems = menu
|
|
43524
|
+
.children(this.env)
|
|
43525
|
+
.sort((a, b) => a.sequence - b.sequence);
|
|
43126
43526
|
this.state.menuState.parentMenu = menu;
|
|
43127
43527
|
this.isSelectingMenu = true;
|
|
43128
43528
|
this.openedEl = ev.target;
|
|
@@ -43208,6 +43608,11 @@ class WebClipboardWrapper {
|
|
|
43208
43608
|
}
|
|
43209
43609
|
}
|
|
43210
43610
|
|
|
43611
|
+
// If we ever change these colors, make sure the filter tool stays green to match the icon in the grid
|
|
43612
|
+
const ACTIVE_BG_COLOR = BACKGROUND_HEADER_FILTER_COLOR;
|
|
43613
|
+
const ACTIVE_FONT_COLOR = FILTERS_COLOR;
|
|
43614
|
+
const HOVERED_BG_COLOR = BG_HOVER_COLOR;
|
|
43615
|
+
const HOVERED_FONT_COLOR = "#000";
|
|
43211
43616
|
css /* scss */ `
|
|
43212
43617
|
.o-spreadsheet {
|
|
43213
43618
|
position: relative;
|
|
@@ -43240,6 +43645,27 @@ css /* scss */ `
|
|
|
43240
43645
|
margin-top: ${MENU_SEPARATOR_PADDING}px;
|
|
43241
43646
|
margin-bottom: ${MENU_SEPARATOR_PADDING}px;
|
|
43242
43647
|
}
|
|
43648
|
+
.o-hoverable-button {
|
|
43649
|
+
border-radius: 2px;
|
|
43650
|
+
cursor: pointer;
|
|
43651
|
+
.o-icon {
|
|
43652
|
+
color: ${ICONS_COLOR};
|
|
43653
|
+
}
|
|
43654
|
+
&:not(.o-disabled):not(.active):hover {
|
|
43655
|
+
background-color: ${HOVERED_BG_COLOR};
|
|
43656
|
+
color: ${HOVERED_FONT_COLOR};
|
|
43657
|
+
.o-icon {
|
|
43658
|
+
color: ${HOVERED_FONT_COLOR};
|
|
43659
|
+
}
|
|
43660
|
+
}
|
|
43661
|
+
&.active {
|
|
43662
|
+
background-color: ${ACTIVE_BG_COLOR};
|
|
43663
|
+
color: ${ACTIVE_FONT_COLOR};
|
|
43664
|
+
.o-icon {
|
|
43665
|
+
color: ${ACTIVE_FONT_COLOR};
|
|
43666
|
+
}
|
|
43667
|
+
}
|
|
43668
|
+
}
|
|
43243
43669
|
}
|
|
43244
43670
|
|
|
43245
43671
|
.o-two-columns {
|
|
@@ -43389,6 +43815,9 @@ class Spreadsheet extends Component {
|
|
|
43389
43815
|
}
|
|
43390
43816
|
}
|
|
43391
43817
|
openSidePanel(panel, panelProps) {
|
|
43818
|
+
if (this.sidePanel.isOpen && panel !== this.sidePanel.component) {
|
|
43819
|
+
this.sidePanel.panelProps?.onCloseSidePanel?.();
|
|
43820
|
+
}
|
|
43392
43821
|
this.sidePanel.component = panel;
|
|
43393
43822
|
this.sidePanel.panelProps = panelProps;
|
|
43394
43823
|
this.sidePanel.isOpen = true;
|
|
@@ -44098,13 +44527,13 @@ class Tree {
|
|
|
44098
44527
|
}
|
|
44099
44528
|
|
|
44100
44529
|
class SelectiveHistory {
|
|
44530
|
+
HEAD_BRANCH;
|
|
44531
|
+
HEAD_OPERATION;
|
|
44532
|
+
tree;
|
|
44101
44533
|
applyOperation;
|
|
44102
44534
|
revertOperation;
|
|
44103
44535
|
buildEmpty;
|
|
44104
44536
|
buildTransformation;
|
|
44105
|
-
HEAD_BRANCH;
|
|
44106
|
-
HEAD_OPERATION;
|
|
44107
|
-
tree;
|
|
44108
44537
|
/**
|
|
44109
44538
|
* The selective history is a data structure used to register changes/updates of a state.
|
|
44110
44539
|
* Each change/update is called an "operation".
|
|
@@ -44125,14 +44554,15 @@ class SelectiveHistory {
|
|
|
44125
44554
|
* (used for internal implementation)
|
|
44126
44555
|
* @param buildTransformation Factory used to build transformations
|
|
44127
44556
|
*/
|
|
44128
|
-
constructor(
|
|
44129
|
-
this.applyOperation = applyOperation;
|
|
44130
|
-
this.revertOperation = revertOperation;
|
|
44131
|
-
this.buildEmpty = buildEmpty;
|
|
44132
|
-
this.buildTransformation = buildTransformation;
|
|
44557
|
+
constructor(args) {
|
|
44558
|
+
this.applyOperation = args.applyOperation;
|
|
44559
|
+
this.revertOperation = args.revertOperation;
|
|
44560
|
+
this.buildEmpty = args.buildEmpty;
|
|
44561
|
+
this.buildTransformation = args.buildTransformation;
|
|
44133
44562
|
this.HEAD_BRANCH = new Branch(this.buildTransformation);
|
|
44134
|
-
this.tree = new Tree(buildTransformation, this.HEAD_BRANCH);
|
|
44135
|
-
const
|
|
44563
|
+
this.tree = new Tree(this.buildTransformation, this.HEAD_BRANCH);
|
|
44564
|
+
const initialOperationId = args.initialOperationId;
|
|
44565
|
+
const initial = new Operation(initialOperationId, this.buildEmpty(initialOperationId));
|
|
44136
44566
|
this.tree.insertOperationLast(this.HEAD_BRANCH, initial);
|
|
44137
44567
|
this.HEAD_OPERATION = initial;
|
|
44138
44568
|
}
|
|
@@ -44246,21 +44676,27 @@ class SelectiveHistory {
|
|
|
44246
44676
|
}
|
|
44247
44677
|
}
|
|
44248
44678
|
|
|
44249
|
-
function buildRevisionLog(
|
|
44250
|
-
return new SelectiveHistory(
|
|
44251
|
-
|
|
44252
|
-
|
|
44253
|
-
|
|
44254
|
-
|
|
44255
|
-
|
|
44256
|
-
|
|
44257
|
-
|
|
44258
|
-
|
|
44259
|
-
|
|
44260
|
-
return new Revision(toTransform.id, toTransform.clientId, transformAll(toTransform.commands, revision.commands), toTransform.rootCommand);
|
|
44679
|
+
function buildRevisionLog(args) {
|
|
44680
|
+
return new SelectiveHistory({
|
|
44681
|
+
initialOperationId: args.initialRevisionId,
|
|
44682
|
+
applyOperation: (revision) => {
|
|
44683
|
+
const commands = revision.commands.slice();
|
|
44684
|
+
const { changes } = args.recordChanges(() => {
|
|
44685
|
+
for (const command of commands) {
|
|
44686
|
+
args.dispatch(command);
|
|
44687
|
+
}
|
|
44688
|
+
});
|
|
44689
|
+
revision.setChanges(changes);
|
|
44261
44690
|
},
|
|
44262
|
-
|
|
44263
|
-
|
|
44691
|
+
revertOperation: (revision) => revertChanges([revision]),
|
|
44692
|
+
buildEmpty: (id) => new Revision(id, "empty", []),
|
|
44693
|
+
buildTransformation: {
|
|
44694
|
+
with: (revision) => (toTransform) => {
|
|
44695
|
+
return new Revision(toTransform.id, toTransform.clientId, transformAll(toTransform.commands, revision.commands), toTransform.rootCommand, undefined, toTransform.timestamp);
|
|
44696
|
+
},
|
|
44697
|
+
without: (revision) => (toTransform) => {
|
|
44698
|
+
return new Revision(toTransform.id, toTransform.clientId, transformAll(toTransform.commands, revision.commands.map(inverseCommand).flat()), toTransform.rootCommand, undefined, toTransform.timestamp);
|
|
44699
|
+
},
|
|
44264
44700
|
},
|
|
44265
44701
|
});
|
|
44266
44702
|
}
|
|
@@ -45933,11 +46369,21 @@ function addBorders(borders) {
|
|
|
45933
46369
|
for (let border of Object.values(borders)) {
|
|
45934
46370
|
borderNodes.push(escapeXml /*xml*/ `
|
|
45935
46371
|
<border>
|
|
45936
|
-
<left ${formatBorderAttribute(border["left"])}
|
|
45937
|
-
|
|
45938
|
-
|
|
45939
|
-
<
|
|
45940
|
-
|
|
46372
|
+
<left ${formatBorderAttribute(border["left"])}>
|
|
46373
|
+
${addBorderColor(border["left"])}
|
|
46374
|
+
</left>
|
|
46375
|
+
<right ${formatBorderAttribute(border["right"])}>
|
|
46376
|
+
${addBorderColor(border["right"])}
|
|
46377
|
+
</right>
|
|
46378
|
+
<top ${formatBorderAttribute(border["top"])}>
|
|
46379
|
+
${addBorderColor(border["top"])}
|
|
46380
|
+
</top>
|
|
46381
|
+
<bottom ${formatBorderAttribute(border["bottom"])}>
|
|
46382
|
+
${addBorderColor(border["bottom"])}
|
|
46383
|
+
</bottom>
|
|
46384
|
+
<diagonal ${formatBorderAttribute(border["diagonal"])}>
|
|
46385
|
+
${addBorderColor(border["diagonal"])}
|
|
46386
|
+
</diagonal>
|
|
45941
46387
|
</border>
|
|
45942
46388
|
`);
|
|
45943
46389
|
}
|
|
@@ -45951,10 +46397,15 @@ function formatBorderAttribute(description) {
|
|
|
45951
46397
|
if (!description) {
|
|
45952
46398
|
return escapeXml ``;
|
|
45953
46399
|
}
|
|
45954
|
-
return formatAttributes([
|
|
45955
|
-
|
|
45956
|
-
|
|
45957
|
-
|
|
46400
|
+
return formatAttributes([["style", description.style]]);
|
|
46401
|
+
}
|
|
46402
|
+
function addBorderColor(description) {
|
|
46403
|
+
if (!description) {
|
|
46404
|
+
return escapeXml ``;
|
|
46405
|
+
}
|
|
46406
|
+
return escapeXml /*xml*/ `
|
|
46407
|
+
<color ${formatAttributes([["rgb", toXlsxHexColor(description.color.rgb)]])}/>
|
|
46408
|
+
`;
|
|
45958
46409
|
}
|
|
45959
46410
|
function addStyles(styles) {
|
|
45960
46411
|
const styleNodes = [];
|
|
@@ -46564,6 +47015,7 @@ class Model extends EventBus {
|
|
|
46564
47015
|
coreGetters;
|
|
46565
47016
|
uuidGenerator;
|
|
46566
47017
|
handlers = [];
|
|
47018
|
+
uiHandlers = [];
|
|
46567
47019
|
coreHandlers = [];
|
|
46568
47020
|
constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = true) {
|
|
46569
47021
|
super();
|
|
@@ -46598,21 +47050,25 @@ class Model extends EventBus {
|
|
|
46598
47050
|
this.setupCorePlugin(Plugin, workbookData);
|
|
46599
47051
|
}
|
|
46600
47052
|
Object.assign(this.getters, this.coreGetters);
|
|
47053
|
+
this.session.loadInitialMessages(stateUpdateMessages);
|
|
46601
47054
|
for (let Plugin of statefulUIPluginRegistry.getAll()) {
|
|
46602
47055
|
const plugin = this.setupUiPlugin(Plugin);
|
|
46603
47056
|
this.statefulUIPlugins.push(plugin);
|
|
46604
47057
|
this.handlers.push(plugin);
|
|
47058
|
+
this.uiHandlers.push(plugin);
|
|
46605
47059
|
}
|
|
46606
47060
|
for (let Plugin of coreViewsPluginRegistry.getAll()) {
|
|
46607
47061
|
const plugin = this.setupUiPlugin(Plugin);
|
|
46608
47062
|
this.coreViewsPlugins.push(plugin);
|
|
46609
47063
|
this.handlers.push(plugin);
|
|
47064
|
+
this.uiHandlers.push(plugin);
|
|
46610
47065
|
this.coreHandlers.push(plugin);
|
|
46611
47066
|
}
|
|
46612
47067
|
for (let Plugin of featurePluginRegistry.getAll()) {
|
|
46613
47068
|
const plugin = this.setupUiPlugin(Plugin);
|
|
46614
47069
|
this.featurePlugins.push(plugin);
|
|
46615
47070
|
this.handlers.push(plugin);
|
|
47071
|
+
this.uiHandlers.push(plugin);
|
|
46616
47072
|
}
|
|
46617
47073
|
this.uuidGenerator.setIsFastStrategy(false);
|
|
46618
47074
|
// starting plugins
|
|
@@ -46625,8 +47081,6 @@ class Model extends EventBus {
|
|
|
46625
47081
|
// This should be done after construction of LocalHistory due to order of
|
|
46626
47082
|
// events
|
|
46627
47083
|
this.setupSessionEvents();
|
|
46628
|
-
// Load the initial revisions
|
|
46629
|
-
this.session.loadInitialMessages(stateUpdateMessages);
|
|
46630
47084
|
this.joinSession();
|
|
46631
47085
|
if (config.snapshotRequested) {
|
|
46632
47086
|
this.session.snapshot(this.exportData());
|
|
@@ -46690,14 +47144,18 @@ class Model extends EventBus {
|
|
|
46690
47144
|
this.finalize();
|
|
46691
47145
|
}
|
|
46692
47146
|
setupSession(revisionId) {
|
|
46693
|
-
const session = new Session(buildRevisionLog(
|
|
46694
|
-
|
|
46695
|
-
|
|
46696
|
-
|
|
46697
|
-
|
|
46698
|
-
|
|
46699
|
-
|
|
46700
|
-
|
|
47147
|
+
const session = new Session(buildRevisionLog({
|
|
47148
|
+
initialRevisionId: revisionId,
|
|
47149
|
+
recordChanges: this.state.recordChanges.bind(this.state),
|
|
47150
|
+
dispatch: (command) => {
|
|
47151
|
+
const result = this.checkDispatchAllowed(command);
|
|
47152
|
+
if (!result.isSuccessful) {
|
|
47153
|
+
return;
|
|
47154
|
+
}
|
|
47155
|
+
this.isReplayingCommand = true;
|
|
47156
|
+
this.dispatchToHandlers(this.coreHandlers, command);
|
|
47157
|
+
this.isReplayingCommand = false;
|
|
47158
|
+
},
|
|
46701
47159
|
}), this.config.transportService, revisionId);
|
|
46702
47160
|
return session;
|
|
46703
47161
|
}
|
|
@@ -46779,7 +47237,7 @@ class Model extends EventBus {
|
|
|
46779
47237
|
return new DispatchResult(results.flat());
|
|
46780
47238
|
}
|
|
46781
47239
|
checkDispatchAllowedLocalCommand(command) {
|
|
46782
|
-
const results = this.
|
|
47240
|
+
const results = this.uiHandlers.map((handler) => handler.allowDispatch(command));
|
|
46783
47241
|
return new DispatchResult(results.flat());
|
|
46784
47242
|
}
|
|
46785
47243
|
finalize() {
|
|
@@ -47068,6 +47526,6 @@ function addFunction(functionName, functionDescription) {
|
|
|
47068
47526
|
export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, links, load, parse, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
|
|
47069
47527
|
|
|
47070
47528
|
|
|
47071
|
-
__info__.version = '16.3.0
|
|
47072
|
-
__info__.date = '2023-05-
|
|
47073
|
-
__info__.hash = '
|
|
47529
|
+
__info__.version = '16.3.0';
|
|
47530
|
+
__info__.date = '2023-05-17T14:44:57.860Z';
|
|
47531
|
+
__info__.hash = '33b37e4';
|