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