@odoo/o-spreadsheet 16.3.0-alpha.7 → 16.3.0-alpha.8
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 +655 -245
- package/dist/o-spreadsheet.d.ts +185 -110
- package/dist/o-spreadsheet.esm.js +655 -245
- package/dist/o-spreadsheet.iife.js +655 -245
- package/dist/o-spreadsheet.iife.min.js +373 -289
- package/package.json +1 -1
|
@@ -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",
|
|
@@ -4385,6 +4398,7 @@ var CommandResult;
|
|
|
4385
4398
|
CommandResult[CommandResult["NoSplitSeparatorInSelection"] = 91] = "NoSplitSeparatorInSelection";
|
|
4386
4399
|
})(CommandResult || (CommandResult = {}));
|
|
4387
4400
|
|
|
4401
|
+
const borderStyles = ["thin", "medium", "thick", "dashed", "dotted"];
|
|
4388
4402
|
var DIRECTION;
|
|
4389
4403
|
(function (DIRECTION) {
|
|
4390
4404
|
DIRECTION["UP"] = "up";
|
|
@@ -5478,12 +5492,6 @@ css /* scss */ `
|
|
|
5478
5492
|
cursor: pointer;
|
|
5479
5493
|
user-select: none;
|
|
5480
5494
|
|
|
5481
|
-
.o-menu-item-name {
|
|
5482
|
-
overflow: hidden;
|
|
5483
|
-
white-space: nowrap;
|
|
5484
|
-
text-overflow: ellipsis;
|
|
5485
|
-
}
|
|
5486
|
-
|
|
5487
5495
|
&.o-menu-root {
|
|
5488
5496
|
display: flex;
|
|
5489
5497
|
justify-content: space-between;
|
|
@@ -5494,10 +5502,6 @@ css /* scss */ `
|
|
|
5494
5502
|
margin: 0px 8px 0px 0px;
|
|
5495
5503
|
width: ${MENU_ITEM_HEIGHT - 2 * MENU_ITEM_PADDING_VERTICAL}px;
|
|
5496
5504
|
line-height: ${MENU_ITEM_HEIGHT - 2 * MENU_ITEM_PADDING_VERTICAL}px;
|
|
5497
|
-
|
|
5498
|
-
.o-icon {
|
|
5499
|
-
color: ${ICONS_COLOR};
|
|
5500
|
-
}
|
|
5501
5505
|
}
|
|
5502
5506
|
.o-menu-item-root {
|
|
5503
5507
|
width: 10px;
|
|
@@ -5511,6 +5515,11 @@ css /* scss */ `
|
|
|
5511
5515
|
.o-menu-item-description {
|
|
5512
5516
|
color: grey;
|
|
5513
5517
|
}
|
|
5518
|
+
.o-menu-item-icon {
|
|
5519
|
+
.o-icon {
|
|
5520
|
+
color: ${ICONS_COLOR};
|
|
5521
|
+
}
|
|
5522
|
+
}
|
|
5514
5523
|
}
|
|
5515
5524
|
&.disabled {
|
|
5516
5525
|
color: ${MENU_ITEM_DISABLED_COLOR};
|
|
@@ -6327,8 +6336,14 @@ function createDataSets(getters, dataSetsString, sheetId, dataSetsHaveTitle) {
|
|
|
6327
6336
|
: undefined));
|
|
6328
6337
|
}
|
|
6329
6338
|
}
|
|
6339
|
+
else if (zone.left === zone.right && zone.top === zone.bottom) {
|
|
6340
|
+
// A single cell. If it's only the title, the dataset is not added.
|
|
6341
|
+
if (!dataSetsHaveTitle) {
|
|
6342
|
+
dataSets.push(createDataSet(getters, dataSetSheetId, zone, undefined));
|
|
6343
|
+
}
|
|
6344
|
+
}
|
|
6330
6345
|
else {
|
|
6331
|
-
/* 1
|
|
6346
|
+
/* 1 row or 1 column */
|
|
6332
6347
|
dataSets.push(createDataSet(getters, dataSetSheetId, zone, dataSetsHaveTitle
|
|
6333
6348
|
? {
|
|
6334
6349
|
top: zone.top,
|
|
@@ -8939,7 +8954,7 @@ const DELETE_CELL_SHIFT_LEFT = (env) => {
|
|
|
8939
8954
|
handlePasteResult(env, result);
|
|
8940
8955
|
};
|
|
8941
8956
|
const MENU_INSERT_ROWS_NAME = (env) => {
|
|
8942
|
-
const number =
|
|
8957
|
+
const number = getRowsNumber(env);
|
|
8943
8958
|
return number === 1 ? _lt("Insert row") : _lt("Insert %s rows", number.toString());
|
|
8944
8959
|
};
|
|
8945
8960
|
const MENU_INSERT_ROWS_BEFORE_NAME = (env) => {
|
|
@@ -15304,7 +15319,11 @@ const LOOKUP = {
|
|
|
15304
15319
|
: getNormalizedValueFromRowRange;
|
|
15305
15320
|
const rangeLength = verticalSearch ? nbRow : nbCol;
|
|
15306
15321
|
const index = dichotomicSearch(searchArray, _searchKey, "nextSmaller", "asc", rangeLength, getElement);
|
|
15307
|
-
|
|
15322
|
+
if (index === -1)
|
|
15323
|
+
assertAvailable(undefined, searchKey);
|
|
15324
|
+
verticalSearch
|
|
15325
|
+
? assertAvailable(searchArray[0][index], searchKey)
|
|
15326
|
+
: assertAvailable(searchArray[index][nbRow - 1], searchKey);
|
|
15308
15327
|
if (resultRange === undefined) {
|
|
15309
15328
|
return (verticalSearch ? searchArray[nbCol - 1][index] : searchArray[index][nbRow - 1]);
|
|
15310
15329
|
}
|
|
@@ -16211,75 +16230,97 @@ for (let category of categories) {
|
|
|
16211
16230
|
|
|
16212
16231
|
const insertRow = {
|
|
16213
16232
|
name: MENU_INSERT_ROWS_NAME,
|
|
16214
|
-
isVisible:
|
|
16233
|
+
isVisible: (env) => isConsecutive(env.model.getters.getActiveRows()) &&
|
|
16234
|
+
IS_ONLY_ONE_RANGE(env) &&
|
|
16235
|
+
env.model.getters.getActiveCols().size === 0,
|
|
16215
16236
|
icon: "o-spreadsheet-Icon.INSERT_ROW",
|
|
16216
16237
|
};
|
|
16217
16238
|
const rowInsertRowBefore = {
|
|
16218
16239
|
name: ROW_INSERT_ROWS_BEFORE_NAME,
|
|
16219
16240
|
execute: INSERT_ROWS_BEFORE_ACTION,
|
|
16241
|
+
isVisible: (env) => isConsecutive(env.model.getters.getActiveRows()) &&
|
|
16242
|
+
IS_ONLY_ONE_RANGE(env) &&
|
|
16243
|
+
env.model.getters.getActiveCols().size === 0,
|
|
16244
|
+
icon: "o-spreadsheet-Icon.INSERT_ROW_BEFORE",
|
|
16220
16245
|
};
|
|
16221
16246
|
const topBarInsertRowsBefore = {
|
|
16222
16247
|
...rowInsertRowBefore,
|
|
16223
16248
|
name: MENU_INSERT_ROWS_BEFORE_NAME,
|
|
16224
|
-
isVisible: (env) => env.model.getters.getActiveCols().size === 0,
|
|
16225
16249
|
};
|
|
16226
16250
|
const cellInsertRowsBefore = {
|
|
16227
16251
|
...rowInsertRowBefore,
|
|
16228
16252
|
name: CELL_INSERT_ROWS_BEFORE_NAME,
|
|
16229
16253
|
isVisible: IS_ONLY_ONE_RANGE,
|
|
16230
|
-
icon: "o-spreadsheet-Icon.
|
|
16254
|
+
icon: "o-spreadsheet-Icon.INSERT_ROW_BEFORE",
|
|
16231
16255
|
};
|
|
16232
16256
|
const rowInsertRowsAfter = {
|
|
16233
16257
|
execute: INSERT_ROWS_AFTER_ACTION,
|
|
16234
16258
|
name: ROW_INSERT_ROWS_AFTER_NAME,
|
|
16259
|
+
isVisible: (env) => isConsecutive(env.model.getters.getActiveRows()) &&
|
|
16260
|
+
IS_ONLY_ONE_RANGE(env) &&
|
|
16261
|
+
env.model.getters.getActiveCols().size === 0,
|
|
16262
|
+
icon: "o-spreadsheet-Icon.INSERT_ROW_AFTER",
|
|
16235
16263
|
};
|
|
16236
16264
|
const topBarInsertRowsAfter = {
|
|
16237
16265
|
...rowInsertRowsAfter,
|
|
16238
16266
|
name: MENU_INSERT_ROWS_AFTER_NAME,
|
|
16239
|
-
isVisible: (env) => env.model.getters.getActiveCols().size === 0,
|
|
16240
16267
|
};
|
|
16241
16268
|
const insertCol = {
|
|
16242
16269
|
name: MENU_INSERT_COLUMNS_NAME,
|
|
16243
|
-
isVisible:
|
|
16270
|
+
isVisible: (env) => isConsecutive(env.model.getters.getActiveCols()) &&
|
|
16271
|
+
IS_ONLY_ONE_RANGE(env) &&
|
|
16272
|
+
env.model.getters.getActiveRows().size === 0,
|
|
16244
16273
|
icon: "o-spreadsheet-Icon.INSERT_COL",
|
|
16245
16274
|
};
|
|
16246
16275
|
const colInsertColsBefore = {
|
|
16247
16276
|
name: COLUMN_INSERT_COLUMNS_BEFORE_NAME,
|
|
16248
16277
|
execute: INSERT_COLUMNS_BEFORE_ACTION,
|
|
16278
|
+
isVisible: (env) => isConsecutive(env.model.getters.getActiveCols()) &&
|
|
16279
|
+
IS_ONLY_ONE_RANGE(env) &&
|
|
16280
|
+
env.model.getters.getActiveRows().size === 0,
|
|
16281
|
+
icon: "o-spreadsheet-Icon.INSERT_COL_BEFORE",
|
|
16249
16282
|
};
|
|
16250
16283
|
const topBarInsertColsBefore = {
|
|
16251
16284
|
...colInsertColsBefore,
|
|
16252
16285
|
name: MENU_INSERT_COLUMNS_BEFORE_NAME,
|
|
16253
|
-
isVisible: (env) => env.model.getters.getActiveRows().size === 0,
|
|
16254
16286
|
};
|
|
16255
16287
|
const cellInsertColsBefore = {
|
|
16256
16288
|
...colInsertColsBefore,
|
|
16257
16289
|
name: CELL_INSERT_COLUMNS_BEFORE_NAME,
|
|
16258
16290
|
isVisible: IS_ONLY_ONE_RANGE,
|
|
16259
|
-
icon: "o-spreadsheet-Icon.
|
|
16291
|
+
icon: "o-spreadsheet-Icon.INSERT_COL_BEFORE",
|
|
16260
16292
|
};
|
|
16261
16293
|
const colInsertColsAfter = {
|
|
16262
16294
|
name: COLUMN_INSERT_COLUMNS_AFTER_NAME,
|
|
16263
16295
|
execute: INSERT_COLUMNS_AFTER_ACTION,
|
|
16296
|
+
isVisible: (env) => isConsecutive(env.model.getters.getActiveCols()) &&
|
|
16297
|
+
IS_ONLY_ONE_RANGE(env) &&
|
|
16298
|
+
env.model.getters.getActiveRows().size === 0,
|
|
16299
|
+
icon: "o-spreadsheet-Icon.INSERT_COL_AFTER",
|
|
16264
16300
|
};
|
|
16265
16301
|
const topBarInsertColsAfter = {
|
|
16266
16302
|
...colInsertColsAfter,
|
|
16267
16303
|
name: MENU_INSERT_COLUMNS_AFTER_NAME,
|
|
16268
16304
|
execute: INSERT_COLUMNS_AFTER_ACTION,
|
|
16269
|
-
isVisible: (env) => env.model.getters.getActiveRows().size === 0,
|
|
16270
16305
|
};
|
|
16271
16306
|
const insertCell = {
|
|
16272
16307
|
name: _lt("Insert cells"),
|
|
16273
|
-
isVisible: IS_ONLY_ONE_RANGE
|
|
16308
|
+
isVisible: (env) => IS_ONLY_ONE_RANGE(env) &&
|
|
16309
|
+
env.model.getters.getActiveCols().size === 0 &&
|
|
16310
|
+
env.model.getters.getActiveRows().size === 0,
|
|
16274
16311
|
icon: "o-spreadsheet-Icon.INSERT_CELL",
|
|
16275
16312
|
};
|
|
16276
16313
|
const insertCellShiftDown = {
|
|
16277
16314
|
name: _lt("Insert cells and shift down"),
|
|
16278
16315
|
execute: INSERT_CELL_SHIFT_DOWN,
|
|
16316
|
+
isVisible: (env) => env.model.getters.getActiveRows().size === 0 && env.model.getters.getActiveCols().size === 0,
|
|
16317
|
+
icon: "o-spreadsheet-Icon.INSERT_CELL_SHIFT_DOWN",
|
|
16279
16318
|
};
|
|
16280
16319
|
const insertCellShiftRight = {
|
|
16281
16320
|
name: _lt("Insert cells and shift right"),
|
|
16282
16321
|
execute: INSERT_CELL_SHIFT_RIGHT,
|
|
16322
|
+
isVisible: (env) => env.model.getters.getActiveRows().size === 0 && env.model.getters.getActiveCols().size === 0,
|
|
16323
|
+
icon: "o-spreadsheet-Icon.INSERT_CELL_SHIFT_RIGHT",
|
|
16283
16324
|
};
|
|
16284
16325
|
const insertChart = {
|
|
16285
16326
|
name: _lt("Chart"),
|
|
@@ -16477,6 +16518,7 @@ const splitToColumns = {
|
|
|
16477
16518
|
sequence: 1,
|
|
16478
16519
|
execute: (env) => env.openSidePanel("SplitToColumns", {}),
|
|
16479
16520
|
isEnabled: (env) => env.model.getters.isSingleColSelected(),
|
|
16521
|
+
icon: "o-spreadsheet-Icon.SPLIT_TEXT",
|
|
16480
16522
|
};
|
|
16481
16523
|
|
|
16482
16524
|
const formatNumberAutomatic = {
|
|
@@ -16692,60 +16734,6 @@ const clearFormat = {
|
|
|
16692
16734
|
execute: FORMAT_CLEARFORMAT_ACTION,
|
|
16693
16735
|
icon: "o-spreadsheet-Icon.CLEAR_FORMAT",
|
|
16694
16736
|
};
|
|
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
16737
|
function fontSizeMenuBuilder() {
|
|
16750
16738
|
return FONT_SIZES.map((fs) => {
|
|
16751
16739
|
return {
|
|
@@ -16758,24 +16746,17 @@ function fontSizeMenuBuilder() {
|
|
|
16758
16746
|
});
|
|
16759
16747
|
}
|
|
16760
16748
|
function isAutomaticFormatSelected(env) {
|
|
16761
|
-
const activeCell = env.model.getters.
|
|
16749
|
+
const activeCell = env.model.getters.getCell(env.model.getters.getActivePosition());
|
|
16762
16750
|
return !activeCell || !activeCell.format;
|
|
16763
16751
|
}
|
|
16764
16752
|
function isFormatSelected(env, format) {
|
|
16765
|
-
const activeCell = env.model.getters.
|
|
16766
|
-
return activeCell
|
|
16753
|
+
const activeCell = env.model.getters.getCell(env.model.getters.getActivePosition());
|
|
16754
|
+
return activeCell?.format === format;
|
|
16767
16755
|
}
|
|
16768
16756
|
function isFontSizeSelected(env, fontSize) {
|
|
16769
16757
|
const currentFontSize = env.model.getters.getCurrentStyle().fontSize || DEFAULT_FONT_SIZE;
|
|
16770
16758
|
return currentFontSize === fontSize;
|
|
16771
16759
|
}
|
|
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
16760
|
function getHorizontalAlign(env) {
|
|
16780
16761
|
const style = env.model.getters.getCurrentStyle();
|
|
16781
16762
|
if (style.align) {
|
|
@@ -16822,18 +16803,7 @@ var ACTION_FORMAT = /*#__PURE__*/Object.freeze({
|
|
|
16822
16803
|
fillColor: fillColor,
|
|
16823
16804
|
formatCF: formatCF,
|
|
16824
16805
|
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
|
|
16806
|
+
clearFormat: clearFormat
|
|
16837
16807
|
});
|
|
16838
16808
|
|
|
16839
16809
|
function interactiveFreezeColumnsRows(env, dimension, base) {
|
|
@@ -16849,6 +16819,7 @@ const hideCols = {
|
|
|
16849
16819
|
name: HIDE_COLUMNS_NAME,
|
|
16850
16820
|
execute: HIDE_COLUMNS_ACTION,
|
|
16851
16821
|
isVisible: NOT_ALL_VISIBLE_COLS_SELECTED,
|
|
16822
|
+
icon: "o-spreadsheet-Icon.HIDE_COL",
|
|
16852
16823
|
};
|
|
16853
16824
|
const unhideCols = {
|
|
16854
16825
|
name: _lt("Unhide columns"),
|
|
@@ -16870,6 +16841,7 @@ const hideRows = {
|
|
|
16870
16841
|
name: HIDE_ROWS_NAME,
|
|
16871
16842
|
execute: HIDE_ROWS_ACTION,
|
|
16872
16843
|
isVisible: NOT_ALL_VISIBLE_ROWS_SELECTED,
|
|
16844
|
+
icon: "o-spreadsheet-Icon.HIDE_ROW",
|
|
16873
16845
|
};
|
|
16874
16846
|
const unhideRows = {
|
|
16875
16847
|
name: _lt("Unhide rows"),
|
|
@@ -17073,19 +17045,21 @@ colMenuRegistry
|
|
|
17073
17045
|
.add("delete_column", {
|
|
17074
17046
|
...deleteCols,
|
|
17075
17047
|
sequence: 90,
|
|
17048
|
+
icon: "o-spreadsheet-Icon.DELETE",
|
|
17076
17049
|
})
|
|
17077
17050
|
.add("clear_column", {
|
|
17078
17051
|
...clearCols,
|
|
17079
17052
|
sequence: 100,
|
|
17053
|
+
icon: "o-spreadsheet-Icon.CLEAR",
|
|
17080
17054
|
})
|
|
17081
17055
|
.add("hide_columns", {
|
|
17082
17056
|
...hideCols,
|
|
17083
|
-
sequence:
|
|
17057
|
+
sequence: 105,
|
|
17084
17058
|
separator: true,
|
|
17085
17059
|
})
|
|
17086
17060
|
.add("unhide_columns", {
|
|
17087
17061
|
...unhideCols,
|
|
17088
|
-
sequence:
|
|
17062
|
+
sequence: 106,
|
|
17089
17063
|
separator: true,
|
|
17090
17064
|
})
|
|
17091
17065
|
.add("conditional_formatting", {
|
|
@@ -17183,10 +17157,12 @@ rowMenuRegistry
|
|
|
17183
17157
|
.add("delete_row", {
|
|
17184
17158
|
...deleteRows,
|
|
17185
17159
|
sequence: 70,
|
|
17160
|
+
icon: "o-spreadsheet-Icon.DELETE",
|
|
17186
17161
|
})
|
|
17187
17162
|
.add("clear_row", {
|
|
17188
17163
|
...clearRows,
|
|
17189
17164
|
sequence: 80,
|
|
17165
|
+
icon: "o-spreadsheet-Icon.CLEAR",
|
|
17190
17166
|
})
|
|
17191
17167
|
.add("hide_rows", {
|
|
17192
17168
|
...hideRows,
|
|
@@ -17679,6 +17655,12 @@ css /* scss */ `
|
|
|
17679
17655
|
height: 25px;
|
|
17680
17656
|
}
|
|
17681
17657
|
}
|
|
17658
|
+
/** Make the character a bit bigger
|
|
17659
|
+
compared to its neighbor INPUT box */
|
|
17660
|
+
.o-remove-selection {
|
|
17661
|
+
font-weight: bold;
|
|
17662
|
+
font-size: calc(100% + 4px);
|
|
17663
|
+
}
|
|
17682
17664
|
}
|
|
17683
17665
|
`;
|
|
17684
17666
|
/**
|
|
@@ -17774,6 +17756,9 @@ class SelectionInput extends Component {
|
|
|
17774
17756
|
this.confirm();
|
|
17775
17757
|
}
|
|
17776
17758
|
}
|
|
17759
|
+
extractRanges(value) {
|
|
17760
|
+
return this.props.hasSingleRange ? value.split(",")[0] : value;
|
|
17761
|
+
}
|
|
17777
17762
|
focus(rangeId) {
|
|
17778
17763
|
this.state.isMissing = false;
|
|
17779
17764
|
this.state.mode = "select-range";
|
|
@@ -17792,10 +17777,11 @@ class SelectionInput extends Component {
|
|
|
17792
17777
|
}
|
|
17793
17778
|
onInputChanged(rangeId, ev) {
|
|
17794
17779
|
const target = ev.target;
|
|
17780
|
+
const value = this.extractRanges(target.value);
|
|
17795
17781
|
this.env.model.dispatch("CHANGE_RANGE", {
|
|
17796
17782
|
id: this.id,
|
|
17797
17783
|
rangeId,
|
|
17798
|
-
value
|
|
17784
|
+
value,
|
|
17799
17785
|
});
|
|
17800
17786
|
this.triggerChange();
|
|
17801
17787
|
}
|
|
@@ -20564,14 +20550,31 @@ class ContentEditableHelper {
|
|
|
20564
20550
|
* */
|
|
20565
20551
|
getCurrentSelection() {
|
|
20566
20552
|
let { startElement, endElement, startSelectionOffset, endSelectionOffset } = this.getStartAndEndSelection();
|
|
20567
|
-
let startSizeBefore = this.
|
|
20568
|
-
let endSizeBefore = this.
|
|
20553
|
+
let startSizeBefore = this.findSelectionIndex(startElement, startSelectionOffset);
|
|
20554
|
+
let endSizeBefore = this.findSelectionIndex(endElement, endSelectionOffset);
|
|
20569
20555
|
return {
|
|
20570
|
-
start: startSizeBefore
|
|
20571
|
-
end: endSizeBefore
|
|
20556
|
+
start: startSizeBefore,
|
|
20557
|
+
end: endSizeBefore,
|
|
20572
20558
|
};
|
|
20573
20559
|
}
|
|
20574
|
-
|
|
20560
|
+
/**
|
|
20561
|
+
* Computes the text 'index' inside this.el based on the currently selected node and its offset.
|
|
20562
|
+
* The selected node is either a Text node or an Element node.
|
|
20563
|
+
*
|
|
20564
|
+
* case 1 -Text node:
|
|
20565
|
+
* the offset is the number of characters from the start of the node. We have to add this offset to the
|
|
20566
|
+
* content length of all previous nodes.
|
|
20567
|
+
*
|
|
20568
|
+
* case 2 - Element node:
|
|
20569
|
+
* the offset is the number of child nodes before the selected node. We have to add the content length of
|
|
20570
|
+
* all the bnodes prior to the selected node as well as the content of the child node before the offset.
|
|
20571
|
+
*
|
|
20572
|
+
* See the MDN documentation for more details.
|
|
20573
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
|
|
20574
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Range/endOffset
|
|
20575
|
+
*
|
|
20576
|
+
*/
|
|
20577
|
+
findSelectionIndex(nodeToFind, nodeOffset) {
|
|
20575
20578
|
let usedCharacters = 0;
|
|
20576
20579
|
let it = iterateChildren(this.el);
|
|
20577
20580
|
let current = it.next();
|
|
@@ -20598,6 +20601,28 @@ class ContentEditableHelper {
|
|
|
20598
20601
|
if (current.value !== nodeToFind) {
|
|
20599
20602
|
throw new Error("Cannot find the node in the children of the element");
|
|
20600
20603
|
}
|
|
20604
|
+
else {
|
|
20605
|
+
if (!current.value.hasChildNodes()) {
|
|
20606
|
+
usedCharacters += nodeOffset;
|
|
20607
|
+
}
|
|
20608
|
+
else {
|
|
20609
|
+
const children = [...current.value.childNodes].slice(0, nodeOffset);
|
|
20610
|
+
usedCharacters += children.reduce((acc, child, index) => {
|
|
20611
|
+
if (child.textContent !== null) {
|
|
20612
|
+
// need to account for paragraph nodes that implicitely add a new line
|
|
20613
|
+
// except for the last paragraph
|
|
20614
|
+
let chars = child.textContent.length;
|
|
20615
|
+
if (child.nodeName === "P" && index !== children.length - 1) {
|
|
20616
|
+
chars++;
|
|
20617
|
+
}
|
|
20618
|
+
return acc + chars;
|
|
20619
|
+
}
|
|
20620
|
+
else {
|
|
20621
|
+
return acc;
|
|
20622
|
+
}
|
|
20623
|
+
}, 0);
|
|
20624
|
+
}
|
|
20625
|
+
}
|
|
20601
20626
|
if (nodeToFind.nodeName === "P" && !isFirstParagraph && nodeToFind.textContent == "") {
|
|
20602
20627
|
usedCharacters++;
|
|
20603
20628
|
}
|
|
@@ -21398,13 +21423,13 @@ GridComposer.props = {
|
|
|
21398
21423
|
|
|
21399
21424
|
const CSS$1 = css /* scss */ `
|
|
21400
21425
|
.o-filter-icon {
|
|
21426
|
+
color: ${FILTERS_COLOR};
|
|
21401
21427
|
position: absolute;
|
|
21402
21428
|
display: flex;
|
|
21403
21429
|
align-items: center;
|
|
21404
21430
|
justify-content: center;
|
|
21405
21431
|
width: ${FILTER_ICON_EDGE_LENGTH}px;
|
|
21406
21432
|
height: ${FILTER_ICON_EDGE_LENGTH}px;
|
|
21407
|
-
color: #4a4f59;
|
|
21408
21433
|
}
|
|
21409
21434
|
.o-filter-icon:hover {
|
|
21410
21435
|
background: ${FILTERS_COLOR};
|
|
@@ -24135,17 +24160,17 @@ const CELL_TYPE_CONVERSION_MAP = {
|
|
|
24135
24160
|
const BORDER_STYLE_CONVERSION_MAP = {
|
|
24136
24161
|
dashDot: "thin",
|
|
24137
24162
|
dashDotDot: "thin",
|
|
24138
|
-
dashed: "
|
|
24139
|
-
dotted: "
|
|
24163
|
+
dashed: "dashed",
|
|
24164
|
+
dotted: "dotted",
|
|
24140
24165
|
double: "thin",
|
|
24141
24166
|
hair: "thin",
|
|
24142
|
-
medium: "
|
|
24167
|
+
medium: "medium",
|
|
24143
24168
|
mediumDashDot: "thin",
|
|
24144
24169
|
mediumDashDotDot: "thin",
|
|
24145
24170
|
mediumDashed: "thin",
|
|
24146
24171
|
none: undefined,
|
|
24147
24172
|
slantDashDot: "thin",
|
|
24148
|
-
thick: "
|
|
24173
|
+
thick: "thick",
|
|
24149
24174
|
thin: "thin",
|
|
24150
24175
|
};
|
|
24151
24176
|
/** Conversion map Horizontal Alignment in XLSX <=> Horizontal Alignment in o_spreadsheet*/
|
|
@@ -24644,7 +24669,7 @@ function convertBorderDescr$1(borderDescr, warningManager) {
|
|
|
24644
24669
|
return undefined;
|
|
24645
24670
|
addBorderDescrWarnings(borderDescr, warningManager);
|
|
24646
24671
|
const style = BORDER_STYLE_CONVERSION_MAP[borderDescr.style];
|
|
24647
|
-
return style ?
|
|
24672
|
+
return style ? { style, color: convertColor(borderDescr.color) } : undefined;
|
|
24648
24673
|
}
|
|
24649
24674
|
function convertStyles(data, warningManager) {
|
|
24650
24675
|
const stylesArray = data.styles.map((style) => {
|
|
@@ -26042,8 +26067,8 @@ function convertBorderDescr(descr) {
|
|
|
26042
26067
|
return undefined;
|
|
26043
26068
|
}
|
|
26044
26069
|
return {
|
|
26045
|
-
style: descr
|
|
26046
|
-
color: { rgb: descr
|
|
26070
|
+
style: descr.style,
|
|
26071
|
+
color: { rgb: descr.color },
|
|
26047
26072
|
};
|
|
26048
26073
|
}
|
|
26049
26074
|
function extractStyle(cell, data) {
|
|
@@ -26621,7 +26646,7 @@ const TABLE_HEADER_STYLE = {
|
|
|
26621
26646
|
const TABLE_HIGHLIGHTED_CELL_STYLE = {
|
|
26622
26647
|
bold: true,
|
|
26623
26648
|
};
|
|
26624
|
-
const TABLE_BORDER_STYLE =
|
|
26649
|
+
const TABLE_BORDER_STYLE = { style: "thin", color: "#000000FF" };
|
|
26625
26650
|
/**
|
|
26626
26651
|
* Convert the imported XLSX tables.
|
|
26627
26652
|
*
|
|
@@ -28190,7 +28215,7 @@ function normalizeV9(formula) {
|
|
|
28190
28215
|
* a breaking change is made in the way the state is handled, and an upgrade
|
|
28191
28216
|
* function should be defined
|
|
28192
28217
|
*/
|
|
28193
|
-
const CURRENT_VERSION =
|
|
28218
|
+
const CURRENT_VERSION = 13;
|
|
28194
28219
|
const INITIAL_SHEET_ID = "Sheet1";
|
|
28195
28220
|
/**
|
|
28196
28221
|
* This function tries to load anything that could look like a valid
|
|
@@ -28454,6 +28479,25 @@ const MIGRATIONS = [
|
|
|
28454
28479
|
return data;
|
|
28455
28480
|
},
|
|
28456
28481
|
},
|
|
28482
|
+
{
|
|
28483
|
+
description: "Change Border description structure",
|
|
28484
|
+
from: 12,
|
|
28485
|
+
to: 13,
|
|
28486
|
+
applyMigration(data) {
|
|
28487
|
+
for (const borderId in data.borders) {
|
|
28488
|
+
const border = data.borders[borderId];
|
|
28489
|
+
for (const position in border) {
|
|
28490
|
+
if (Array.isArray(border[position])) {
|
|
28491
|
+
border[position] = {
|
|
28492
|
+
style: border[position][0],
|
|
28493
|
+
color: border[position][1],
|
|
28494
|
+
};
|
|
28495
|
+
}
|
|
28496
|
+
}
|
|
28497
|
+
}
|
|
28498
|
+
return data;
|
|
28499
|
+
},
|
|
28500
|
+
},
|
|
28457
28501
|
];
|
|
28458
28502
|
/**
|
|
28459
28503
|
* This function is used to repair faulty data independently of the migration.
|
|
@@ -28789,7 +28833,7 @@ class CorePlugin extends BasePlugin {
|
|
|
28789
28833
|
* - borders
|
|
28790
28834
|
*/
|
|
28791
28835
|
class BordersPlugin extends CorePlugin {
|
|
28792
|
-
static getters = ["getCellBorder"];
|
|
28836
|
+
static getters = ["getCellBorder", "getBordersColors"];
|
|
28793
28837
|
borders = {};
|
|
28794
28838
|
// ---------------------------------------------------------------------------
|
|
28795
28839
|
// Command Handling
|
|
@@ -28820,10 +28864,15 @@ class BordersPlugin extends CorePlugin {
|
|
|
28820
28864
|
case "SET_BORDER":
|
|
28821
28865
|
this.setBorder(cmd.sheetId, cmd.col, cmd.row, cmd.border);
|
|
28822
28866
|
break;
|
|
28823
|
-
case "
|
|
28867
|
+
case "SET_ZONE_BORDERS":
|
|
28824
28868
|
if (cmd.border) {
|
|
28825
28869
|
const target = cmd.target.map((zone) => this.getters.expandZone(cmd.sheetId, zone));
|
|
28826
|
-
this.setBorders(cmd.sheetId, target, cmd.border
|
|
28870
|
+
this.setBorders(cmd.sheetId, target, cmd.border.position, cmd.border.color === ""
|
|
28871
|
+
? undefined
|
|
28872
|
+
: {
|
|
28873
|
+
style: cmd.border.style || DEFAULT_BORDER_DESC.style,
|
|
28874
|
+
color: cmd.border.color || DEFAULT_BORDER_DESC.color,
|
|
28875
|
+
});
|
|
28827
28876
|
}
|
|
28828
28877
|
break;
|
|
28829
28878
|
case "CLEAR_FORMATTING":
|
|
@@ -28912,6 +28961,23 @@ class BordersPlugin extends CorePlugin {
|
|
|
28912
28961
|
}
|
|
28913
28962
|
return border;
|
|
28914
28963
|
}
|
|
28964
|
+
getBordersColors(sheetId) {
|
|
28965
|
+
const colors = [];
|
|
28966
|
+
const sheetBorders = this.borders[sheetId];
|
|
28967
|
+
if (sheetBorders) {
|
|
28968
|
+
for (const borders of sheetBorders.filter(isDefined$1)) {
|
|
28969
|
+
for (const cellBorder of borders) {
|
|
28970
|
+
if (cellBorder?.horizontal) {
|
|
28971
|
+
colors.push(cellBorder.horizontal.color);
|
|
28972
|
+
}
|
|
28973
|
+
if (cellBorder?.vertical) {
|
|
28974
|
+
colors.push(cellBorder.vertical.color);
|
|
28975
|
+
}
|
|
28976
|
+
}
|
|
28977
|
+
}
|
|
28978
|
+
}
|
|
28979
|
+
return colors;
|
|
28980
|
+
}
|
|
28915
28981
|
// ---------------------------------------------------------------------------
|
|
28916
28982
|
// Private
|
|
28917
28983
|
// ---------------------------------------------------------------------------
|
|
@@ -29123,43 +29189,43 @@ class BordersPlugin extends CorePlugin {
|
|
|
29123
29189
|
* Set the borders of a zone by computing the borders to add from the given
|
|
29124
29190
|
* command
|
|
29125
29191
|
*/
|
|
29126
|
-
setBorders(sheetId, zones,
|
|
29127
|
-
if (
|
|
29192
|
+
setBorders(sheetId, zones, position, border) {
|
|
29193
|
+
if (position === "clear") {
|
|
29128
29194
|
return this.clearBorders(sheetId, zones);
|
|
29129
29195
|
}
|
|
29130
29196
|
for (let zone of zones) {
|
|
29131
|
-
if (
|
|
29197
|
+
if (position === "h" || position === "hv" || position === "all") {
|
|
29132
29198
|
for (let row = zone.top + 1; row <= zone.bottom; row++) {
|
|
29133
29199
|
for (let col = zone.left; col <= zone.right; col++) {
|
|
29134
|
-
this.addBorder(sheetId, col, row, { top:
|
|
29200
|
+
this.addBorder(sheetId, col, row, { top: border });
|
|
29135
29201
|
}
|
|
29136
29202
|
}
|
|
29137
29203
|
}
|
|
29138
|
-
if (
|
|
29204
|
+
if (position === "v" || position === "hv" || position === "all") {
|
|
29139
29205
|
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
29140
29206
|
for (let col = zone.left + 1; col <= zone.right; col++) {
|
|
29141
|
-
this.addBorder(sheetId, col, row, { left:
|
|
29207
|
+
this.addBorder(sheetId, col, row, { left: border });
|
|
29142
29208
|
}
|
|
29143
29209
|
}
|
|
29144
29210
|
}
|
|
29145
|
-
if (
|
|
29211
|
+
if (position === "left" || position === "all" || position === "external") {
|
|
29146
29212
|
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
29147
|
-
this.addBorder(sheetId, zone.left, row, { left:
|
|
29213
|
+
this.addBorder(sheetId, zone.left, row, { left: border });
|
|
29148
29214
|
}
|
|
29149
29215
|
}
|
|
29150
|
-
if (
|
|
29216
|
+
if (position === "right" || position === "all" || position === "external") {
|
|
29151
29217
|
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
29152
|
-
this.addBorder(sheetId, zone.right + 1, row, { left:
|
|
29218
|
+
this.addBorder(sheetId, zone.right + 1, row, { left: border });
|
|
29153
29219
|
}
|
|
29154
29220
|
}
|
|
29155
|
-
if (
|
|
29221
|
+
if (position === "top" || position === "all" || position === "external") {
|
|
29156
29222
|
for (let col = zone.left; col <= zone.right; col++) {
|
|
29157
|
-
this.addBorder(sheetId, col, zone.top, { top:
|
|
29223
|
+
this.addBorder(sheetId, col, zone.top, { top: border });
|
|
29158
29224
|
}
|
|
29159
29225
|
}
|
|
29160
|
-
if (
|
|
29226
|
+
if (position === "bottom" || position === "all" || position === "external") {
|
|
29161
29227
|
for (let col = zone.left; col <= zone.right; col++) {
|
|
29162
|
-
this.addBorder(sheetId, col, zone.bottom + 1, { top:
|
|
29228
|
+
this.addBorder(sheetId, col, zone.bottom + 1, { top: border });
|
|
29163
29229
|
}
|
|
29164
29230
|
}
|
|
29165
29231
|
}
|
|
@@ -29173,16 +29239,22 @@ class BordersPlugin extends CorePlugin {
|
|
|
29173
29239
|
const bordersBottomRight = this.getCellBorder({ sheetId, col: right, row: bottom });
|
|
29174
29240
|
this.clearBorders(sheetId, [zone]);
|
|
29175
29241
|
if (bordersTopLeft?.top) {
|
|
29176
|
-
this.setBorders(sheetId, [{ ...zone, bottom: top }], "top");
|
|
29242
|
+
this.setBorders(sheetId, [{ ...zone, bottom: top }], "top", bordersTopLeft.top);
|
|
29177
29243
|
}
|
|
29178
29244
|
if (bordersTopLeft?.left) {
|
|
29179
|
-
this.setBorders(sheetId, [{ ...zone, right: left }], "left");
|
|
29245
|
+
this.setBorders(sheetId, [{ ...zone, right: left }], "left", bordersTopLeft.left);
|
|
29246
|
+
}
|
|
29247
|
+
if (bordersBottomRight?.bottom) {
|
|
29248
|
+
this.setBorders(sheetId, [{ ...zone, top: bottom }], "bottom", bordersBottomRight.bottom);
|
|
29249
|
+
}
|
|
29250
|
+
else if (bordersTopLeft?.bottom) {
|
|
29251
|
+
this.setBorders(sheetId, [{ ...zone, top: bottom }], "bottom", bordersTopLeft.bottom);
|
|
29180
29252
|
}
|
|
29181
|
-
if (bordersBottomRight?.
|
|
29182
|
-
this.setBorders(sheetId, [{ ...zone,
|
|
29253
|
+
if (bordersBottomRight?.right) {
|
|
29254
|
+
this.setBorders(sheetId, [{ ...zone, left: right }], "right", bordersBottomRight.right);
|
|
29183
29255
|
}
|
|
29184
|
-
if (
|
|
29185
|
-
this.setBorders(sheetId, [{ ...zone, left: right }], "right");
|
|
29256
|
+
else if (bordersTopLeft?.right) {
|
|
29257
|
+
this.setBorders(sheetId, [{ ...zone, left: right }], "right", bordersTopLeft.right);
|
|
29186
29258
|
}
|
|
29187
29259
|
}
|
|
29188
29260
|
// ---------------------------------------------------------------------------
|
|
@@ -33035,6 +33107,9 @@ class CustomColorsPlugin extends UIPlugin {
|
|
|
33035
33107
|
case "UPDATE_CHART":
|
|
33036
33108
|
case "CREATE_CHART":
|
|
33037
33109
|
case "ADD_CONDITIONAL_FORMAT":
|
|
33110
|
+
case "SET_BORDER":
|
|
33111
|
+
case "SET_ZONE_BORDERS":
|
|
33112
|
+
case "SET_FORMATTING":
|
|
33038
33113
|
this.shouldUpdateColors = true;
|
|
33039
33114
|
}
|
|
33040
33115
|
}
|
|
@@ -33049,8 +33124,7 @@ class CustomColorsPlugin extends UIPlugin {
|
|
|
33049
33124
|
getCustomColors() {
|
|
33050
33125
|
let usedColors = [];
|
|
33051
33126
|
for (const sheetId of this.getters.getSheetIds()) {
|
|
33052
|
-
|
|
33053
|
-
usedColors = usedColors.concat(this.getColorsFromCells(cells), this.getFormattingColors(sheetId), this.getChartColors(sheetId));
|
|
33127
|
+
usedColors = usedColors.concat(this.getColorsFromCells(sheetId), this.getFormattingColors(sheetId), this.getChartColors(sheetId));
|
|
33054
33128
|
}
|
|
33055
33129
|
return sortWithClusters([
|
|
33056
33130
|
...new Set(
|
|
@@ -33060,7 +33134,8 @@ class CustomColorsPlugin extends UIPlugin {
|
|
|
33060
33134
|
[...new Set([...usedColors, ...this.customColors])].filter(isColorValid).map(toHex)),
|
|
33061
33135
|
]).filter((color) => !COLOR_PICKER_DEFAULTS.includes(color));
|
|
33062
33136
|
}
|
|
33063
|
-
getColorsFromCells(
|
|
33137
|
+
getColorsFromCells(sheetId) {
|
|
33138
|
+
const cells = Object.values(this.getters.getCells(sheetId));
|
|
33064
33139
|
const colors = new Set();
|
|
33065
33140
|
for (const cell of cells) {
|
|
33066
33141
|
if (cell.style?.textColor) {
|
|
@@ -33070,6 +33145,9 @@ class CustomColorsPlugin extends UIPlugin {
|
|
|
33070
33145
|
colors.add(cell.style.fillColor);
|
|
33071
33146
|
}
|
|
33072
33147
|
}
|
|
33148
|
+
for (const color of this.getters.getBordersColors(sheetId)) {
|
|
33149
|
+
colors.add(color);
|
|
33150
|
+
}
|
|
33073
33151
|
return [...colors];
|
|
33074
33152
|
}
|
|
33075
33153
|
getFormattingColors(sheetId) {
|
|
@@ -33343,7 +33421,7 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
33343
33421
|
// magic "empty" value
|
|
33344
33422
|
// Returning {value: null} instead of undefined will ensure that we don't
|
|
33345
33423
|
// fall back on the default value of the argument provided to the formula's compute function
|
|
33346
|
-
return { value: null };
|
|
33424
|
+
return { value: null, format: cell?.format };
|
|
33347
33425
|
}
|
|
33348
33426
|
return getEvaluatedCell(cell);
|
|
33349
33427
|
}
|
|
@@ -36172,6 +36250,7 @@ function transformPositionWithMerge(cmd, executed) {
|
|
|
36172
36250
|
|
|
36173
36251
|
class Revision {
|
|
36174
36252
|
rootCommand;
|
|
36253
|
+
timestamp;
|
|
36175
36254
|
id;
|
|
36176
36255
|
clientId;
|
|
36177
36256
|
_commands = [];
|
|
@@ -36185,8 +36264,9 @@ class Revision {
|
|
|
36185
36264
|
* - clientId: Client who initiated the action
|
|
36186
36265
|
* - changes: List of changes applied on the state.
|
|
36187
36266
|
*/
|
|
36188
|
-
constructor(id, clientId, commands, rootCommand, changes) {
|
|
36267
|
+
constructor(id, clientId, commands, rootCommand, changes, timestamp) {
|
|
36189
36268
|
this.rootCommand = rootCommand;
|
|
36269
|
+
this.timestamp = timestamp;
|
|
36190
36270
|
this.id = id;
|
|
36191
36271
|
this.clientId = clientId;
|
|
36192
36272
|
this._commands = [...commands];
|
|
@@ -36258,7 +36338,7 @@ class Session extends EventBus {
|
|
|
36258
36338
|
save(rootCommand, commands, changes) {
|
|
36259
36339
|
if (!commands.length || !changes.length || !this.canApplyOptimisticUpdate())
|
|
36260
36340
|
return;
|
|
36261
|
-
const revision = new Revision(this.uuidGenerator.uuidv4(), this.clientId, commands, rootCommand, changes);
|
|
36341
|
+
const revision = new Revision(this.uuidGenerator.uuidv4(), this.clientId, commands, rootCommand, changes, Date.now());
|
|
36262
36342
|
this.revisions.append(revision.id, revision);
|
|
36263
36343
|
this.trigger("new-local-state-update", { id: revision.id });
|
|
36264
36344
|
this.sendUpdateMessage({
|
|
@@ -36309,13 +36389,9 @@ class Session extends EventBus {
|
|
|
36309
36389
|
}
|
|
36310
36390
|
loadInitialMessages(messages) {
|
|
36311
36391
|
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
36392
|
for (const message of messages) {
|
|
36316
36393
|
this.onMessageReceived(message);
|
|
36317
36394
|
}
|
|
36318
|
-
this.off("unexpected-revision-id", this);
|
|
36319
36395
|
this.isReplayingInitialRevisions = false;
|
|
36320
36396
|
}
|
|
36321
36397
|
/**
|
|
@@ -36401,6 +36477,10 @@ class Session extends EventBus {
|
|
|
36401
36477
|
onMessageReceived(message) {
|
|
36402
36478
|
if (this.isAlreadyProcessed(message))
|
|
36403
36479
|
return;
|
|
36480
|
+
if (this.isWrongServerRevisionId(message)) {
|
|
36481
|
+
this.trigger("unexpected-revision-id");
|
|
36482
|
+
return;
|
|
36483
|
+
}
|
|
36404
36484
|
switch (message.type) {
|
|
36405
36485
|
case "CLIENT_MOVED":
|
|
36406
36486
|
this.onClientMoved(message);
|
|
@@ -36427,12 +36507,8 @@ class Session extends EventBus {
|
|
|
36427
36507
|
});
|
|
36428
36508
|
break;
|
|
36429
36509
|
case "REMOTE_REVISION":
|
|
36430
|
-
|
|
36431
|
-
|
|
36432
|
-
return;
|
|
36433
|
-
}
|
|
36434
|
-
const { clientId, commands } = message;
|
|
36435
|
-
const revision = new Revision(message.nextRevisionId, clientId, commands, "REMOTE");
|
|
36510
|
+
const { clientId, commands, timestamp } = message;
|
|
36511
|
+
const revision = new Revision(message.nextRevisionId, clientId, commands, "REMOTE", undefined, timestamp);
|
|
36436
36512
|
if (revision.clientId !== this.clientId) {
|
|
36437
36513
|
this.revisions.insert(revision.id, revision, message.serverRevisionId);
|
|
36438
36514
|
const pendingCommands = this.pendingMessages
|
|
@@ -36445,7 +36521,7 @@ class Session extends EventBus {
|
|
|
36445
36521
|
}
|
|
36446
36522
|
break;
|
|
36447
36523
|
case "SNAPSHOT_CREATED": {
|
|
36448
|
-
const revision = new Revision(message.nextRevisionId, "server", [], "SNAPSHOT");
|
|
36524
|
+
const revision = new Revision(message.nextRevisionId, "server", [], "SNAPSHOT", undefined, Date.now());
|
|
36449
36525
|
this.revisions.insert(revision.id, revision, message.serverRevisionId);
|
|
36450
36526
|
this.dropPendingHistoryMessages();
|
|
36451
36527
|
this.trigger("snapshot");
|
|
@@ -36562,6 +36638,17 @@ class Session extends EventBus {
|
|
|
36562
36638
|
return false;
|
|
36563
36639
|
}
|
|
36564
36640
|
}
|
|
36641
|
+
isWrongServerRevisionId(message) {
|
|
36642
|
+
switch (message.type) {
|
|
36643
|
+
case "REMOTE_REVISION":
|
|
36644
|
+
case "REVISION_REDONE":
|
|
36645
|
+
case "REVISION_UNDONE":
|
|
36646
|
+
case "SNAPSHOT_CREATED":
|
|
36647
|
+
return message.serverRevisionId !== this.serverRevisionId;
|
|
36648
|
+
default:
|
|
36649
|
+
return false;
|
|
36650
|
+
}
|
|
36651
|
+
}
|
|
36565
36652
|
dropPendingHistoryMessages() {
|
|
36566
36653
|
this.waitingUndoRedoAck = false;
|
|
36567
36654
|
this.pendingMessages = this.pendingMessages.filter(({ type }) => type !== "REVISION_REDONE" && type !== "REVISION_UNDONE");
|
|
@@ -37277,7 +37364,7 @@ class RendererPlugin extends UIPlugin {
|
|
|
37277
37364
|
}
|
|
37278
37365
|
}
|
|
37279
37366
|
drawBorders(renderingContext) {
|
|
37280
|
-
const { ctx
|
|
37367
|
+
const { ctx } = renderingContext;
|
|
37281
37368
|
for (let box of this.boxes) {
|
|
37282
37369
|
const border = box.border;
|
|
37283
37370
|
if (border) {
|
|
@@ -37296,13 +37383,66 @@ class RendererPlugin extends UIPlugin {
|
|
|
37296
37383
|
}
|
|
37297
37384
|
}
|
|
37298
37385
|
}
|
|
37299
|
-
|
|
37386
|
+
/**
|
|
37387
|
+
* Following https://usefulangle.com/post/17/html5-canvas-drawing-1px-crisp-straight-lines,
|
|
37388
|
+
* we need to make sure that a "single" pixel line is drawn on a "half" pixel coordinate,
|
|
37389
|
+
* while a "double" pixel line is drawn on a "full" pixel coordinate. As, in the rendering
|
|
37390
|
+
* process, we always had 0.5 before rendering line (to make sure it is drawn on a "half"
|
|
37391
|
+
* pixel), we need to correct this behavior for the "medium" and the "dotted" styles, as
|
|
37392
|
+
* they are drawing a two pixels width line.
|
|
37393
|
+
* We also adapt here the coordinates of the line to make sure corner are correctly drawn,
|
|
37394
|
+
* avoiding a "round corners" effect. This is done by subtracting 1 pixel to the origin of
|
|
37395
|
+
* each line and adding 1 pixel to the end of each line (depending on the direction of the
|
|
37396
|
+
* line).
|
|
37397
|
+
*/
|
|
37398
|
+
function drawBorder({ style, color }, x1, y1, x2, y2) {
|
|
37300
37399
|
ctx.strokeStyle = color;
|
|
37301
|
-
|
|
37400
|
+
switch (style) {
|
|
37401
|
+
case "medium":
|
|
37402
|
+
ctx.lineWidth = 2;
|
|
37403
|
+
x1 += y1 === y2 ? -0.5 : 0.5;
|
|
37404
|
+
x2 += y1 === y2 ? 1.5 : 0.5;
|
|
37405
|
+
y1 += x1 === x2 ? -0.5 : 0.5;
|
|
37406
|
+
y2 += x1 === x2 ? 1.5 : 0.5;
|
|
37407
|
+
break;
|
|
37408
|
+
case "thick":
|
|
37409
|
+
ctx.lineWidth = 3;
|
|
37410
|
+
if (y1 === y2) {
|
|
37411
|
+
x1--;
|
|
37412
|
+
x2++;
|
|
37413
|
+
}
|
|
37414
|
+
if (x1 === x2) {
|
|
37415
|
+
y1--;
|
|
37416
|
+
y2++;
|
|
37417
|
+
}
|
|
37418
|
+
break;
|
|
37419
|
+
case "dashed":
|
|
37420
|
+
ctx.lineWidth = 1;
|
|
37421
|
+
ctx.setLineDash([1, 3]);
|
|
37422
|
+
break;
|
|
37423
|
+
case "dotted":
|
|
37424
|
+
ctx.lineWidth = 1;
|
|
37425
|
+
if (y1 === y2) {
|
|
37426
|
+
x1 += 0.5;
|
|
37427
|
+
x2 += 0.5;
|
|
37428
|
+
}
|
|
37429
|
+
if (x1 === x2) {
|
|
37430
|
+
y1 += 0.5;
|
|
37431
|
+
y2 += 0.5;
|
|
37432
|
+
}
|
|
37433
|
+
ctx.setLineDash([1, 1]);
|
|
37434
|
+
break;
|
|
37435
|
+
case "thin":
|
|
37436
|
+
default:
|
|
37437
|
+
ctx.lineWidth = 1;
|
|
37438
|
+
break;
|
|
37439
|
+
}
|
|
37302
37440
|
ctx.beginPath();
|
|
37303
37441
|
ctx.moveTo(x1, y1);
|
|
37304
37442
|
ctx.lineTo(x2, y2);
|
|
37305
37443
|
ctx.stroke();
|
|
37444
|
+
ctx.lineWidth = 1;
|
|
37445
|
+
ctx.setLineDash([]);
|
|
37306
37446
|
}
|
|
37307
37447
|
}
|
|
37308
37448
|
drawTexts(renderingContext) {
|
|
@@ -37780,6 +37920,9 @@ class SelectionInputPlugin extends UIPlugin {
|
|
|
37780
37920
|
activeSheet;
|
|
37781
37921
|
willAddNewRange = false;
|
|
37782
37922
|
constructor(config, initialRanges, inputHasSingleRange) {
|
|
37923
|
+
if (inputHasSingleRange && initialRanges.length > 1) {
|
|
37924
|
+
throw new Error("Input with a single range cannot be instantiated with several range references.");
|
|
37925
|
+
}
|
|
37783
37926
|
super(config);
|
|
37784
37927
|
this.inputHasSingleRange = inputHasSingleRange;
|
|
37785
37928
|
this.insertNewRange(0, initialRanges);
|
|
@@ -37799,6 +37942,11 @@ class SelectionInputPlugin extends UIPlugin {
|
|
|
37799
37942
|
return 30 /* CommandResult.MaximumRangesReached */;
|
|
37800
37943
|
}
|
|
37801
37944
|
break;
|
|
37945
|
+
case "CHANGE_RANGE":
|
|
37946
|
+
if (this.inputHasSingleRange && cmd.value.split(",").length > 1) {
|
|
37947
|
+
return 30 /* CommandResult.MaximumRangesReached */;
|
|
37948
|
+
}
|
|
37949
|
+
break;
|
|
37802
37950
|
}
|
|
37803
37951
|
return 0 /* CommandResult.Success */;
|
|
37804
37952
|
}
|
|
@@ -41285,7 +41433,8 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
41285
41433
|
},
|
|
41286
41434
|
zone: selectedZone,
|
|
41287
41435
|
};
|
|
41288
|
-
this.
|
|
41436
|
+
const selections = this.gridSelection.zones.map((zone) => updateSelectionOnDeletion(zone, "left", [...cmd.elements]));
|
|
41437
|
+
this.setSelectionMixin(anchor, selections);
|
|
41289
41438
|
}
|
|
41290
41439
|
onRowsRemoved(cmd) {
|
|
41291
41440
|
const { cell, zone } = this.gridSelection.anchor;
|
|
@@ -41299,13 +41448,18 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
41299
41448
|
},
|
|
41300
41449
|
zone: selectedZone,
|
|
41301
41450
|
};
|
|
41302
|
-
this.
|
|
41451
|
+
const selections = this.gridSelection.zones.map((zone) => updateSelectionOnDeletion(zone, "top", [...cmd.elements]));
|
|
41452
|
+
this.setSelectionMixin(anchor, selections);
|
|
41303
41453
|
}
|
|
41304
41454
|
onAddElements(cmd) {
|
|
41305
|
-
const
|
|
41306
|
-
const
|
|
41307
|
-
const
|
|
41308
|
-
|
|
41455
|
+
const start = cmd.dimension === "COL" ? "left" : "top";
|
|
41456
|
+
const anchorZone = updateSelectionOnInsertion(this.gridSelection.anchor.zone, start, cmd.base, cmd.position, cmd.quantity);
|
|
41457
|
+
const selection = this.gridSelection.zones.map((zone) => updateSelectionOnInsertion(zone, start, cmd.base, cmd.position, cmd.quantity));
|
|
41458
|
+
const anchor = {
|
|
41459
|
+
cell: { col: anchorZone.left, row: anchorZone.top },
|
|
41460
|
+
zone: anchorZone,
|
|
41461
|
+
};
|
|
41462
|
+
this.setSelectionMixin(anchor, selection);
|
|
41309
41463
|
}
|
|
41310
41464
|
onMoveElements(cmd) {
|
|
41311
41465
|
const thickness = cmd.elements.length;
|
|
@@ -42551,7 +42705,6 @@ css /* scss */ `
|
|
|
42551
42705
|
color: dimgrey;
|
|
42552
42706
|
}
|
|
42553
42707
|
.o-sidePanelClose {
|
|
42554
|
-
font-size: 1.5rem;
|
|
42555
42708
|
padding: 5px 10px;
|
|
42556
42709
|
cursor: pointer;
|
|
42557
42710
|
&:hover {
|
|
@@ -42736,7 +42889,6 @@ css /* scss */ `
|
|
|
42736
42889
|
justify-content: center;
|
|
42737
42890
|
align-items: center;
|
|
42738
42891
|
margin: 2px;
|
|
42739
|
-
padding: 0px 3px;
|
|
42740
42892
|
border-radius: 2px;
|
|
42741
42893
|
min-width: 20px;
|
|
42742
42894
|
}
|
|
@@ -42793,7 +42945,228 @@ ActionButton.props = {
|
|
|
42793
42945
|
onClick: { type: Function, optional: true },
|
|
42794
42946
|
};
|
|
42795
42947
|
|
|
42948
|
+
/**
|
|
42949
|
+
* List the available borders positions and the corresponding icons.
|
|
42950
|
+
* The structure of this array is defined to match the order/lines we want
|
|
42951
|
+
* to display in the topbar's border tool.
|
|
42952
|
+
*/
|
|
42953
|
+
const BORDER_POSITIONS = [
|
|
42954
|
+
[
|
|
42955
|
+
["all", "o-spreadsheet-Icon.BORDERS"],
|
|
42956
|
+
["hv", "o-spreadsheet-Icon.BORDER_HV"],
|
|
42957
|
+
["h", "o-spreadsheet-Icon.BORDER_H"],
|
|
42958
|
+
["v", "o-spreadsheet-Icon.BORDER_V"],
|
|
42959
|
+
["external", "o-spreadsheet-Icon.BORDER_EXTERNAL"],
|
|
42960
|
+
],
|
|
42961
|
+
[
|
|
42962
|
+
["left", "o-spreadsheet-Icon.BORDER_LEFT"],
|
|
42963
|
+
["top", "o-spreadsheet-Icon.BORDER_TOP"],
|
|
42964
|
+
["right", "o-spreadsheet-Icon.BORDER_RIGHT"],
|
|
42965
|
+
["bottom", "o-spreadsheet-Icon.BORDER_BOTTOM"],
|
|
42966
|
+
["clear", "o-spreadsheet-Icon.BORDER_CLEAR"],
|
|
42967
|
+
],
|
|
42968
|
+
];
|
|
42969
|
+
// -----------------------------------------------------------------------------
|
|
42970
|
+
// Border Editor
|
|
42971
|
+
// -----------------------------------------------------------------------------
|
|
42972
|
+
css /* scss */ `
|
|
42973
|
+
.o-border-selector {
|
|
42974
|
+
padding: 4px;
|
|
42975
|
+
}
|
|
42976
|
+
.o-divider {
|
|
42977
|
+
border-right: 1px solid #e0e2e4;
|
|
42978
|
+
margin: 0 6px;
|
|
42979
|
+
}
|
|
42980
|
+
.o-border-selector-section {
|
|
42981
|
+
.o-dropdown-line {
|
|
42982
|
+
height: 30px;
|
|
42983
|
+
margin: 1px;
|
|
42984
|
+
.o-line-item {
|
|
42985
|
+
padding: 4px;
|
|
42986
|
+
width: 18px;
|
|
42987
|
+
height: 18px;
|
|
42988
|
+
}
|
|
42989
|
+
}
|
|
42990
|
+
.o-border-style-tool {
|
|
42991
|
+
padding: 0px 3px;
|
|
42992
|
+
margin: 2px;
|
|
42993
|
+
height: 25px;
|
|
42994
|
+
}
|
|
42995
|
+
}
|
|
42996
|
+
.o-style-preview {
|
|
42997
|
+
margin: 7px 5px 7px 5px;
|
|
42998
|
+
width: 60px;
|
|
42999
|
+
height: 5px;
|
|
43000
|
+
}
|
|
43001
|
+
.o-style-thin {
|
|
43002
|
+
border-bottom: 1px solid #000000;
|
|
43003
|
+
}
|
|
43004
|
+
.o-style-medium {
|
|
43005
|
+
border-bottom: 2px solid #000000;
|
|
43006
|
+
}
|
|
43007
|
+
.o-style-thick {
|
|
43008
|
+
border-bottom: 3px solid #000000;
|
|
43009
|
+
}
|
|
43010
|
+
.o-style-dashed {
|
|
43011
|
+
border-bottom: 1px dashed #000000;
|
|
43012
|
+
}
|
|
43013
|
+
.o-style-dotted {
|
|
43014
|
+
border-bottom: 1px dotted #000000;
|
|
43015
|
+
}
|
|
43016
|
+
.o-dropdown-border-type {
|
|
43017
|
+
&:not(.o-disabled):not(.active):hover {
|
|
43018
|
+
background-color: ${BG_HOVER_COLOR};
|
|
43019
|
+
}
|
|
43020
|
+
}
|
|
43021
|
+
.o-dropdown-border-check {
|
|
43022
|
+
width: 20px;
|
|
43023
|
+
font-size: 12px;
|
|
43024
|
+
}
|
|
43025
|
+
.o-border-style-dropdown {
|
|
43026
|
+
background: #ffffff;
|
|
43027
|
+
padding: 4px;
|
|
43028
|
+
.o-dropdown-line {
|
|
43029
|
+
.o-line-item.active {
|
|
43030
|
+
background-color: rgba(0, 0, 0, 0.2);
|
|
43031
|
+
}
|
|
43032
|
+
}
|
|
43033
|
+
}
|
|
43034
|
+
.o-border-picker-button {
|
|
43035
|
+
padding: 0px !important;
|
|
43036
|
+
margin: 5px 0px 0px 0px !important;
|
|
43037
|
+
height: 25px !important;
|
|
43038
|
+
}
|
|
43039
|
+
`;
|
|
43040
|
+
class BorderEditor extends Component {
|
|
43041
|
+
static template = "o-spreadsheet-BorderEditor";
|
|
43042
|
+
static components = { ColorPickerWidget, Popover };
|
|
43043
|
+
BORDER_POSITIONS = BORDER_POSITIONS;
|
|
43044
|
+
lineStyleButtonRef = useRef("lineStyleButton");
|
|
43045
|
+
borderStyles = borderStyles;
|
|
43046
|
+
state = useState({
|
|
43047
|
+
activeTool: undefined,
|
|
43048
|
+
});
|
|
43049
|
+
toggleDropdownTool(tool) {
|
|
43050
|
+
const isOpen = this.state.activeTool === tool;
|
|
43051
|
+
this.state.activeTool = isOpen ? undefined : tool;
|
|
43052
|
+
}
|
|
43053
|
+
closeDropdown() {
|
|
43054
|
+
this.state.activeTool = undefined;
|
|
43055
|
+
}
|
|
43056
|
+
setBorderPosition(position) {
|
|
43057
|
+
this.props.onBorderPositionPicked(position);
|
|
43058
|
+
this.closeDropdown();
|
|
43059
|
+
}
|
|
43060
|
+
setBorderColor(color) {
|
|
43061
|
+
this.props.onBorderColorPicked(color);
|
|
43062
|
+
this.closeDropdown();
|
|
43063
|
+
}
|
|
43064
|
+
setBorderStyle(style) {
|
|
43065
|
+
this.props.onBorderStylePicked(style);
|
|
43066
|
+
this.closeDropdown();
|
|
43067
|
+
}
|
|
43068
|
+
get lineStylePickerPopoverProps() {
|
|
43069
|
+
return {
|
|
43070
|
+
anchorRect: this.lineStylePickerAnchorRect,
|
|
43071
|
+
positioning: "BottomLeft",
|
|
43072
|
+
verticalOffset: 0,
|
|
43073
|
+
};
|
|
43074
|
+
}
|
|
43075
|
+
get popoverProps() {
|
|
43076
|
+
return {
|
|
43077
|
+
anchorRect: this.props.anchorRect,
|
|
43078
|
+
maxHeight: this.props.maxHeight,
|
|
43079
|
+
positioning: "BottomLeft",
|
|
43080
|
+
verticalOffset: 0,
|
|
43081
|
+
};
|
|
43082
|
+
}
|
|
43083
|
+
get lineStylePickerAnchorRect() {
|
|
43084
|
+
const button = this.lineStyleButtonRef.el;
|
|
43085
|
+
if (button === null) {
|
|
43086
|
+
return { x: 0, y: 0, width: 0, height: 0 };
|
|
43087
|
+
}
|
|
43088
|
+
const buttonRect = button.getBoundingClientRect();
|
|
43089
|
+
return {
|
|
43090
|
+
x: buttonRect.x,
|
|
43091
|
+
y: buttonRect.y,
|
|
43092
|
+
width: buttonRect.width,
|
|
43093
|
+
height: buttonRect.height,
|
|
43094
|
+
};
|
|
43095
|
+
}
|
|
43096
|
+
}
|
|
43097
|
+
BorderEditor.props = {
|
|
43098
|
+
class: { type: String, optional: true },
|
|
43099
|
+
currentBorderColor: { type: String, optional: false },
|
|
43100
|
+
currentBorderStyle: { type: String, optional: false },
|
|
43101
|
+
currentBorderPosition: { type: String, optional: true },
|
|
43102
|
+
onBorderColorPicked: Function,
|
|
43103
|
+
onBorderStylePicked: Function,
|
|
43104
|
+
onBorderPositionPicked: Function,
|
|
43105
|
+
maxHeight: { type: Number, optional: true },
|
|
43106
|
+
anchorRect: Object,
|
|
43107
|
+
};
|
|
43108
|
+
|
|
43109
|
+
class BorderEditorWidget extends Component {
|
|
43110
|
+
static template = "o-spreadsheet-BorderEditorWidget";
|
|
43111
|
+
static components = { BorderEditor };
|
|
43112
|
+
borderEditorButtonRef = useRef("borderEditorButton");
|
|
43113
|
+
state = useState({
|
|
43114
|
+
currentColor: DEFAULT_BORDER_DESC.color,
|
|
43115
|
+
currentStyle: DEFAULT_BORDER_DESC.style,
|
|
43116
|
+
currentPosition: undefined,
|
|
43117
|
+
});
|
|
43118
|
+
get borderEditorAnchorRect() {
|
|
43119
|
+
const button = this.borderEditorButtonRef.el;
|
|
43120
|
+
const buttonRect = button.getBoundingClientRect();
|
|
43121
|
+
return {
|
|
43122
|
+
x: buttonRect.x,
|
|
43123
|
+
y: buttonRect.y,
|
|
43124
|
+
width: buttonRect.width,
|
|
43125
|
+
height: buttonRect.height,
|
|
43126
|
+
};
|
|
43127
|
+
}
|
|
43128
|
+
onBorderPositionPicked(position) {
|
|
43129
|
+
this.state.currentPosition = position;
|
|
43130
|
+
this.updateBorder();
|
|
43131
|
+
}
|
|
43132
|
+
onBorderColorPicked(color) {
|
|
43133
|
+
this.state.currentColor = color;
|
|
43134
|
+
this.updateBorder();
|
|
43135
|
+
}
|
|
43136
|
+
onBorderStylePicked(style) {
|
|
43137
|
+
this.state.currentStyle = style;
|
|
43138
|
+
this.updateBorder();
|
|
43139
|
+
}
|
|
43140
|
+
updateBorder() {
|
|
43141
|
+
if (this.state.currentPosition === undefined) {
|
|
43142
|
+
return;
|
|
43143
|
+
}
|
|
43144
|
+
this.env.model.dispatch("SET_ZONE_BORDERS", {
|
|
43145
|
+
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
43146
|
+
target: this.env.model.getters.getSelectedZones(),
|
|
43147
|
+
border: {
|
|
43148
|
+
position: this.state.currentPosition,
|
|
43149
|
+
color: this.state.currentColor,
|
|
43150
|
+
style: this.state.currentStyle,
|
|
43151
|
+
},
|
|
43152
|
+
});
|
|
43153
|
+
}
|
|
43154
|
+
}
|
|
43155
|
+
BorderEditorWidget.props = {
|
|
43156
|
+
toggleBorderEditor: Function,
|
|
43157
|
+
showBorderEditor: Boolean,
|
|
43158
|
+
disabled: { type: Boolean, optional: true },
|
|
43159
|
+
dropdownMaxHeight: { type: Number, optional: true },
|
|
43160
|
+
class: { type: String, optional: true },
|
|
43161
|
+
};
|
|
43162
|
+
|
|
42796
43163
|
const COMPOSER_MAX_HEIGHT = 100;
|
|
43164
|
+
/* svg free of use from https://uxwing.com/formula-fx-icon/ */
|
|
43165
|
+
const FX_SVG = /*xml*/ `
|
|
43166
|
+
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 121.8 122.9' width='16' height='16' focusable='false'>
|
|
43167
|
+
<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'/>
|
|
43168
|
+
</svg>
|
|
43169
|
+
`;
|
|
42797
43170
|
css /* scss */ `
|
|
42798
43171
|
.o-topbar-composer {
|
|
42799
43172
|
height: fit-content;
|
|
@@ -42801,9 +43174,10 @@ css /* scss */ `
|
|
|
42801
43174
|
border: 1px solid;
|
|
42802
43175
|
z-index: ${ComponentsImportance.TopBarComposer};
|
|
42803
43176
|
|
|
42804
|
-
.o-composer:empty:not(:focus)::before {
|
|
42805
|
-
|
|
42806
|
-
|
|
43177
|
+
.o-composer:empty:not(:focus):not(.active)::before {
|
|
43178
|
+
content: url("data:image/svg+xml,${encodeURIComponent(FX_SVG)}");
|
|
43179
|
+
position: relative;
|
|
43180
|
+
top: 20%;
|
|
42807
43181
|
}
|
|
42808
43182
|
}
|
|
42809
43183
|
`;
|
|
@@ -42926,11 +43300,6 @@ FontSizeEditor.props = {
|
|
|
42926
43300
|
dropdownStyle: String,
|
|
42927
43301
|
};
|
|
42928
43302
|
|
|
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
43303
|
// -----------------------------------------------------------------------------
|
|
42935
43304
|
// TopBar
|
|
42936
43305
|
// -----------------------------------------------------------------------------
|
|
@@ -42940,27 +43309,6 @@ css /* scss */ `
|
|
|
42940
43309
|
font-size: 13px;
|
|
42941
43310
|
font-weight: 500;
|
|
42942
43311
|
|
|
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
43312
|
.o-topbar-top {
|
|
42965
43313
|
border-bottom: 1px solid ${SEPARATOR_COLOR};
|
|
42966
43314
|
padding: 2px 10px;
|
|
@@ -42970,6 +43318,11 @@ css /* scss */ `
|
|
|
42970
43318
|
.o-topbar-menu {
|
|
42971
43319
|
padding: 4px 6px;
|
|
42972
43320
|
margin: 0 2px;
|
|
43321
|
+
|
|
43322
|
+
&.active {
|
|
43323
|
+
background-color: ${BG_HOVER_COLOR};
|
|
43324
|
+
color: #000;
|
|
43325
|
+
}
|
|
42973
43326
|
}
|
|
42974
43327
|
}
|
|
42975
43328
|
}
|
|
@@ -43047,6 +43400,7 @@ class TopBar extends Component {
|
|
|
43047
43400
|
TopBarComposer,
|
|
43048
43401
|
FontSizeEditor,
|
|
43049
43402
|
ActionButton,
|
|
43403
|
+
BorderEditorWidget,
|
|
43050
43404
|
};
|
|
43051
43405
|
state = useState({
|
|
43052
43406
|
menuState: { isOpen: false, position: null, menuItems: [] },
|
|
@@ -43122,7 +43476,9 @@ class TopBar extends Component {
|
|
|
43122
43476
|
this.state.activeTool = "";
|
|
43123
43477
|
this.state.menuState.isOpen = true;
|
|
43124
43478
|
this.state.menuState.position = { x: left, y: top + height };
|
|
43125
|
-
this.state.menuState.menuItems = menu
|
|
43479
|
+
this.state.menuState.menuItems = menu
|
|
43480
|
+
.children(this.env)
|
|
43481
|
+
.sort((a, b) => a.sequence - b.sequence);
|
|
43126
43482
|
this.state.menuState.parentMenu = menu;
|
|
43127
43483
|
this.isSelectingMenu = true;
|
|
43128
43484
|
this.openedEl = ev.target;
|
|
@@ -43208,6 +43564,11 @@ class WebClipboardWrapper {
|
|
|
43208
43564
|
}
|
|
43209
43565
|
}
|
|
43210
43566
|
|
|
43567
|
+
// If we ever change these colors, make sure the filter tool stays green to match the icon in the grid
|
|
43568
|
+
const ACTIVE_BG_COLOR = BACKGROUND_HEADER_FILTER_COLOR;
|
|
43569
|
+
const ACTIVE_FONT_COLOR = FILTERS_COLOR;
|
|
43570
|
+
const HOVERED_BG_COLOR = BG_HOVER_COLOR;
|
|
43571
|
+
const HOVERED_FONT_COLOR = "#000";
|
|
43211
43572
|
css /* scss */ `
|
|
43212
43573
|
.o-spreadsheet {
|
|
43213
43574
|
position: relative;
|
|
@@ -43240,6 +43601,27 @@ css /* scss */ `
|
|
|
43240
43601
|
margin-top: ${MENU_SEPARATOR_PADDING}px;
|
|
43241
43602
|
margin-bottom: ${MENU_SEPARATOR_PADDING}px;
|
|
43242
43603
|
}
|
|
43604
|
+
.o-hoverable-button {
|
|
43605
|
+
border-radius: 2px;
|
|
43606
|
+
cursor: pointer;
|
|
43607
|
+
.o-icon {
|
|
43608
|
+
color: ${ICONS_COLOR};
|
|
43609
|
+
}
|
|
43610
|
+
&:not(.o-disabled):not(.active):hover {
|
|
43611
|
+
background-color: ${HOVERED_BG_COLOR};
|
|
43612
|
+
color: ${HOVERED_FONT_COLOR};
|
|
43613
|
+
.o-icon {
|
|
43614
|
+
color: ${HOVERED_FONT_COLOR};
|
|
43615
|
+
}
|
|
43616
|
+
}
|
|
43617
|
+
&.active {
|
|
43618
|
+
background-color: ${ACTIVE_BG_COLOR};
|
|
43619
|
+
color: ${ACTIVE_FONT_COLOR};
|
|
43620
|
+
.o-icon {
|
|
43621
|
+
color: ${ACTIVE_FONT_COLOR};
|
|
43622
|
+
}
|
|
43623
|
+
}
|
|
43624
|
+
}
|
|
43243
43625
|
}
|
|
43244
43626
|
|
|
43245
43627
|
.o-two-columns {
|
|
@@ -43389,6 +43771,9 @@ class Spreadsheet extends Component {
|
|
|
43389
43771
|
}
|
|
43390
43772
|
}
|
|
43391
43773
|
openSidePanel(panel, panelProps) {
|
|
43774
|
+
if (this.sidePanel.isOpen && panel !== this.sidePanel.component) {
|
|
43775
|
+
this.sidePanel.panelProps?.onCloseSidePanel?.();
|
|
43776
|
+
}
|
|
43392
43777
|
this.sidePanel.component = panel;
|
|
43393
43778
|
this.sidePanel.panelProps = panelProps;
|
|
43394
43779
|
this.sidePanel.isOpen = true;
|
|
@@ -44098,13 +44483,13 @@ class Tree {
|
|
|
44098
44483
|
}
|
|
44099
44484
|
|
|
44100
44485
|
class SelectiveHistory {
|
|
44486
|
+
HEAD_BRANCH;
|
|
44487
|
+
HEAD_OPERATION;
|
|
44488
|
+
tree;
|
|
44101
44489
|
applyOperation;
|
|
44102
44490
|
revertOperation;
|
|
44103
44491
|
buildEmpty;
|
|
44104
44492
|
buildTransformation;
|
|
44105
|
-
HEAD_BRANCH;
|
|
44106
|
-
HEAD_OPERATION;
|
|
44107
|
-
tree;
|
|
44108
44493
|
/**
|
|
44109
44494
|
* The selective history is a data structure used to register changes/updates of a state.
|
|
44110
44495
|
* Each change/update is called an "operation".
|
|
@@ -44125,14 +44510,15 @@ class SelectiveHistory {
|
|
|
44125
44510
|
* (used for internal implementation)
|
|
44126
44511
|
* @param buildTransformation Factory used to build transformations
|
|
44127
44512
|
*/
|
|
44128
|
-
constructor(
|
|
44129
|
-
this.applyOperation = applyOperation;
|
|
44130
|
-
this.revertOperation = revertOperation;
|
|
44131
|
-
this.buildEmpty = buildEmpty;
|
|
44132
|
-
this.buildTransformation = buildTransformation;
|
|
44513
|
+
constructor(args) {
|
|
44514
|
+
this.applyOperation = args.applyOperation;
|
|
44515
|
+
this.revertOperation = args.revertOperation;
|
|
44516
|
+
this.buildEmpty = args.buildEmpty;
|
|
44517
|
+
this.buildTransformation = args.buildTransformation;
|
|
44133
44518
|
this.HEAD_BRANCH = new Branch(this.buildTransformation);
|
|
44134
|
-
this.tree = new Tree(buildTransformation, this.HEAD_BRANCH);
|
|
44135
|
-
const
|
|
44519
|
+
this.tree = new Tree(this.buildTransformation, this.HEAD_BRANCH);
|
|
44520
|
+
const initialOperationId = args.initialOperationId;
|
|
44521
|
+
const initial = new Operation(initialOperationId, this.buildEmpty(initialOperationId));
|
|
44136
44522
|
this.tree.insertOperationLast(this.HEAD_BRANCH, initial);
|
|
44137
44523
|
this.HEAD_OPERATION = initial;
|
|
44138
44524
|
}
|
|
@@ -44246,21 +44632,27 @@ class SelectiveHistory {
|
|
|
44246
44632
|
}
|
|
44247
44633
|
}
|
|
44248
44634
|
|
|
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);
|
|
44635
|
+
function buildRevisionLog(args) {
|
|
44636
|
+
return new SelectiveHistory({
|
|
44637
|
+
initialOperationId: args.initialRevisionId,
|
|
44638
|
+
applyOperation: (revision) => {
|
|
44639
|
+
const commands = revision.commands.slice();
|
|
44640
|
+
const { changes } = args.recordChanges(() => {
|
|
44641
|
+
for (const command of commands) {
|
|
44642
|
+
args.dispatch(command);
|
|
44643
|
+
}
|
|
44644
|
+
});
|
|
44645
|
+
revision.setChanges(changes);
|
|
44261
44646
|
},
|
|
44262
|
-
|
|
44263
|
-
|
|
44647
|
+
revertOperation: (revision) => revertChanges([revision]),
|
|
44648
|
+
buildEmpty: (id) => new Revision(id, "empty", []),
|
|
44649
|
+
buildTransformation: {
|
|
44650
|
+
with: (revision) => (toTransform) => {
|
|
44651
|
+
return new Revision(toTransform.id, toTransform.clientId, transformAll(toTransform.commands, revision.commands), toTransform.rootCommand, undefined, toTransform.timestamp);
|
|
44652
|
+
},
|
|
44653
|
+
without: (revision) => (toTransform) => {
|
|
44654
|
+
return new Revision(toTransform.id, toTransform.clientId, transformAll(toTransform.commands, revision.commands.map(inverseCommand).flat()), toTransform.rootCommand, undefined, toTransform.timestamp);
|
|
44655
|
+
},
|
|
44264
44656
|
},
|
|
44265
44657
|
});
|
|
44266
44658
|
}
|
|
@@ -45933,11 +46325,21 @@ function addBorders(borders) {
|
|
|
45933
46325
|
for (let border of Object.values(borders)) {
|
|
45934
46326
|
borderNodes.push(escapeXml /*xml*/ `
|
|
45935
46327
|
<border>
|
|
45936
|
-
<left ${formatBorderAttribute(border["left"])}
|
|
45937
|
-
|
|
45938
|
-
|
|
45939
|
-
<
|
|
45940
|
-
|
|
46328
|
+
<left ${formatBorderAttribute(border["left"])}>
|
|
46329
|
+
${addBorderColor(border["left"])}
|
|
46330
|
+
</left>
|
|
46331
|
+
<right ${formatBorderAttribute(border["right"])}>
|
|
46332
|
+
${addBorderColor(border["right"])}
|
|
46333
|
+
</right>
|
|
46334
|
+
<top ${formatBorderAttribute(border["top"])}>
|
|
46335
|
+
${addBorderColor(border["top"])}
|
|
46336
|
+
</top>
|
|
46337
|
+
<bottom ${formatBorderAttribute(border["bottom"])}>
|
|
46338
|
+
${addBorderColor(border["bottom"])}
|
|
46339
|
+
</bottom>
|
|
46340
|
+
<diagonal ${formatBorderAttribute(border["diagonal"])}>
|
|
46341
|
+
${addBorderColor(border["diagonal"])}
|
|
46342
|
+
</diagonal>
|
|
45941
46343
|
</border>
|
|
45942
46344
|
`);
|
|
45943
46345
|
}
|
|
@@ -45951,10 +46353,15 @@ function formatBorderAttribute(description) {
|
|
|
45951
46353
|
if (!description) {
|
|
45952
46354
|
return escapeXml ``;
|
|
45953
46355
|
}
|
|
45954
|
-
return formatAttributes([
|
|
45955
|
-
|
|
45956
|
-
|
|
45957
|
-
|
|
46356
|
+
return formatAttributes([["style", description.style]]);
|
|
46357
|
+
}
|
|
46358
|
+
function addBorderColor(description) {
|
|
46359
|
+
if (!description) {
|
|
46360
|
+
return escapeXml ``;
|
|
46361
|
+
}
|
|
46362
|
+
return escapeXml /*xml*/ `
|
|
46363
|
+
<color ${formatAttributes([["rgb", toXlsxHexColor(description.color.rgb)]])}/>
|
|
46364
|
+
`;
|
|
45958
46365
|
}
|
|
45959
46366
|
function addStyles(styles) {
|
|
45960
46367
|
const styleNodes = [];
|
|
@@ -46598,6 +47005,7 @@ class Model extends EventBus {
|
|
|
46598
47005
|
this.setupCorePlugin(Plugin, workbookData);
|
|
46599
47006
|
}
|
|
46600
47007
|
Object.assign(this.getters, this.coreGetters);
|
|
47008
|
+
this.session.loadInitialMessages(stateUpdateMessages);
|
|
46601
47009
|
for (let Plugin of statefulUIPluginRegistry.getAll()) {
|
|
46602
47010
|
const plugin = this.setupUiPlugin(Plugin);
|
|
46603
47011
|
this.statefulUIPlugins.push(plugin);
|
|
@@ -46625,8 +47033,6 @@ class Model extends EventBus {
|
|
|
46625
47033
|
// This should be done after construction of LocalHistory due to order of
|
|
46626
47034
|
// events
|
|
46627
47035
|
this.setupSessionEvents();
|
|
46628
|
-
// Load the initial revisions
|
|
46629
|
-
this.session.loadInitialMessages(stateUpdateMessages);
|
|
46630
47036
|
this.joinSession();
|
|
46631
47037
|
if (config.snapshotRequested) {
|
|
46632
47038
|
this.session.snapshot(this.exportData());
|
|
@@ -46690,14 +47096,18 @@ class Model extends EventBus {
|
|
|
46690
47096
|
this.finalize();
|
|
46691
47097
|
}
|
|
46692
47098
|
setupSession(revisionId) {
|
|
46693
|
-
const session = new Session(buildRevisionLog(
|
|
46694
|
-
|
|
46695
|
-
|
|
46696
|
-
|
|
46697
|
-
|
|
46698
|
-
|
|
46699
|
-
|
|
46700
|
-
|
|
47099
|
+
const session = new Session(buildRevisionLog({
|
|
47100
|
+
initialRevisionId: revisionId,
|
|
47101
|
+
recordChanges: this.state.recordChanges.bind(this.state),
|
|
47102
|
+
dispatch: (command) => {
|
|
47103
|
+
const result = this.checkDispatchAllowed(command);
|
|
47104
|
+
if (!result.isSuccessful) {
|
|
47105
|
+
return;
|
|
47106
|
+
}
|
|
47107
|
+
this.isReplayingCommand = true;
|
|
47108
|
+
this.dispatchToHandlers(this.coreHandlers, command);
|
|
47109
|
+
this.isReplayingCommand = false;
|
|
47110
|
+
},
|
|
46701
47111
|
}), this.config.transportService, revisionId);
|
|
46702
47112
|
return session;
|
|
46703
47113
|
}
|
|
@@ -47068,6 +47478,6 @@ function addFunction(functionName, functionDescription) {
|
|
|
47068
47478
|
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
47479
|
|
|
47070
47480
|
|
|
47071
|
-
__info__.version = '16.3.0-alpha.
|
|
47072
|
-
__info__.date = '2023-05-
|
|
47073
|
-
__info__.hash = '
|
|
47481
|
+
__info__.version = '16.3.0-alpha.8';
|
|
47482
|
+
__info__.date = '2023-05-12T10:59:42.550Z';
|
|
47483
|
+
__info__.hash = 'afee7d5';
|