@odoo/o-spreadsheet 16.4.0-alpha.4 → 16.4.0-alpha.5

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.
@@ -750,12 +750,20 @@ function getDefaultCellHeight(cell) {
750
750
  return computeTextLinesHeight(fontSize, numberOfLines) + 2 * PADDING_AUTORESIZE_VERTICAL;
751
751
  }
752
752
  function computeTextWidth(context, text, style) {
753
- context.save();
754
- context.font = computeTextFont(style);
755
- const textWidth = context.measureText(text).width;
756
- context.restore();
757
- return textWidth;
753
+ const font = computeTextFont(style);
754
+ if (!textWidthCache[font]) {
755
+ textWidthCache[font] = {};
756
+ }
757
+ if (textWidthCache[font][text] === undefined) {
758
+ context.save();
759
+ context.font = font;
760
+ const textWidth = context.measureText(text).width;
761
+ context.restore();
762
+ textWidthCache[font][text] = textWidth;
763
+ }
764
+ return textWidthCache[font][text];
758
765
  }
766
+ const textWidthCache = {};
759
767
  function fontSizeInPixels(fontSize) {
760
768
  return Math.round((fontSize * 96) / 72);
761
769
  }
@@ -1063,10 +1071,17 @@ function removeFalsyAttributes(obj) {
1063
1071
  function toLowerCase(str) {
1064
1072
  return str ? str.toLowerCase() : "";
1065
1073
  }
1066
- function transpose2dArray(matrix) {
1074
+ function transpose2dArray(matrix, callback = (val) => val) {
1067
1075
  if (!matrix.length)
1068
- return matrix;
1069
- return matrix[0].map((_, i) => matrix.map((row) => row[i]));
1076
+ return [];
1077
+ const transposed = Array(matrix[0].length);
1078
+ for (let i = 0; i < matrix[0].length; i++) {
1079
+ transposed[i] = Array(matrix.length);
1080
+ for (let j = 0; j < matrix.length; j++) {
1081
+ transposed[i][j] = callback(matrix[j][i]);
1082
+ }
1083
+ }
1084
+ return transposed;
1070
1085
  }
1071
1086
  /**
1072
1087
  * Equivalent to "\s" in regexp, minus the new lines characters
@@ -3704,6 +3719,290 @@ function detectLink(value) {
3704
3719
  return undefined;
3705
3720
  }
3706
3721
 
3722
+ var CellValueType;
3723
+ (function (CellValueType) {
3724
+ CellValueType["boolean"] = "boolean";
3725
+ CellValueType["number"] = "number";
3726
+ CellValueType["text"] = "text";
3727
+ CellValueType["empty"] = "empty";
3728
+ CellValueType["error"] = "error";
3729
+ })(CellValueType || (CellValueType = {}));
3730
+
3731
+ var ClipboardMIMEType;
3732
+ (function (ClipboardMIMEType) {
3733
+ ClipboardMIMEType["PlainText"] = "text/plain";
3734
+ ClipboardMIMEType["Html"] = "text/html";
3735
+ })(ClipboardMIMEType || (ClipboardMIMEType = {}));
3736
+
3737
+ function isSheetDependent(cmd) {
3738
+ return "sheetId" in cmd;
3739
+ }
3740
+ function isGridDependent(cmd) {
3741
+ return "dimension" in cmd && "sheetId" in cmd;
3742
+ }
3743
+ function isTargetDependent(cmd) {
3744
+ return "target" in cmd && "sheetId" in cmd;
3745
+ }
3746
+ function isRangeDependant(cmd) {
3747
+ return "ranges" in cmd;
3748
+ }
3749
+ function isPositionDependent(cmd) {
3750
+ return "col" in cmd && "row" in cmd && "sheetId" in cmd;
3751
+ }
3752
+ const invalidateEvaluationCommands = new Set([
3753
+ "RENAME_SHEET",
3754
+ "DELETE_SHEET",
3755
+ "CREATE_SHEET",
3756
+ "ADD_COLUMNS_ROWS",
3757
+ "REMOVE_COLUMNS_ROWS",
3758
+ "UNDO",
3759
+ "REDO",
3760
+ "ADD_MERGE",
3761
+ ]);
3762
+ const invalidateDependenciesCommands = new Set([
3763
+ ...invalidateEvaluationCommands,
3764
+ "MOVE_RANGES",
3765
+ ]);
3766
+ const invalidateCFEvaluationCommands = new Set([
3767
+ ...invalidateEvaluationCommands,
3768
+ "DUPLICATE_SHEET",
3769
+ "EVALUATE_CELLS",
3770
+ "ADD_CONDITIONAL_FORMAT",
3771
+ "REMOVE_CONDITIONAL_FORMAT",
3772
+ "MOVE_CONDITIONAL_FORMAT",
3773
+ ]);
3774
+ const readonlyAllowedCommands = new Set([
3775
+ "START",
3776
+ "ACTIVATE_SHEET",
3777
+ "COPY",
3778
+ "PREPARE_SELECTION_INPUT_EXPANSION",
3779
+ "STOP_SELECTION_INPUT",
3780
+ "RESIZE_SHEETVIEW",
3781
+ "SET_VIEWPORT_OFFSET",
3782
+ "SELECT_SEARCH_NEXT_MATCH",
3783
+ "SELECT_SEARCH_PREVIOUS_MATCH",
3784
+ "REFRESH_SEARCH",
3785
+ "UPDATE_SEARCH",
3786
+ "CLEAR_SEARCH",
3787
+ "EVALUATE_CELLS",
3788
+ "SET_CURRENT_CONTENT",
3789
+ "SET_FORMULA_VISIBILITY",
3790
+ "OPEN_CELL_POPOVER",
3791
+ "CLOSE_CELL_POPOVER",
3792
+ "UPDATE_FILTER",
3793
+ ]);
3794
+ const coreTypes = new Set([
3795
+ /** CELLS */
3796
+ "UPDATE_CELL",
3797
+ "UPDATE_CELL_POSITION",
3798
+ "CLEAR_CELL",
3799
+ "DELETE_CONTENT",
3800
+ /** GRID SHAPE */
3801
+ "ADD_COLUMNS_ROWS",
3802
+ "REMOVE_COLUMNS_ROWS",
3803
+ "RESIZE_COLUMNS_ROWS",
3804
+ "HIDE_COLUMNS_ROWS",
3805
+ "UNHIDE_COLUMNS_ROWS",
3806
+ "SET_GRID_LINES_VISIBILITY",
3807
+ "UNFREEZE_COLUMNS",
3808
+ "UNFREEZE_ROWS",
3809
+ "FREEZE_COLUMNS",
3810
+ "FREEZE_ROWS",
3811
+ "UNFREEZE_COLUMNS_ROWS",
3812
+ /** MERGE */
3813
+ "ADD_MERGE",
3814
+ "REMOVE_MERGE",
3815
+ /** SHEETS MANIPULATION */
3816
+ "CREATE_SHEET",
3817
+ "DELETE_SHEET",
3818
+ "DUPLICATE_SHEET",
3819
+ "MOVE_SHEET",
3820
+ "RENAME_SHEET",
3821
+ "HIDE_SHEET",
3822
+ "SHOW_SHEET",
3823
+ /** RANGES MANIPULATION */
3824
+ "MOVE_RANGES",
3825
+ /** CONDITIONAL FORMAT */
3826
+ "ADD_CONDITIONAL_FORMAT",
3827
+ "REMOVE_CONDITIONAL_FORMAT",
3828
+ "MOVE_CONDITIONAL_FORMAT",
3829
+ /** FIGURES */
3830
+ "CREATE_FIGURE",
3831
+ "DELETE_FIGURE",
3832
+ "UPDATE_FIGURE",
3833
+ /** FORMATTING */
3834
+ "SET_FORMATTING",
3835
+ "CLEAR_FORMATTING",
3836
+ "SET_BORDER",
3837
+ "SET_ZONE_BORDERS",
3838
+ /** CHART */
3839
+ "CREATE_CHART",
3840
+ "UPDATE_CHART",
3841
+ /** FILTERS */
3842
+ "CREATE_FILTER_TABLE",
3843
+ "REMOVE_FILTER_TABLE",
3844
+ /** IMAGE */
3845
+ "CREATE_IMAGE",
3846
+ ]);
3847
+ function isCoreCommand(cmd) {
3848
+ return coreTypes.has(cmd.type);
3849
+ }
3850
+ function canExecuteInReadonly(cmd) {
3851
+ return readonlyAllowedCommands.has(cmd.type);
3852
+ }
3853
+ /**
3854
+ * Holds the result of a command dispatch.
3855
+ * The command may have been successfully dispatched or cancelled
3856
+ * for one or more reasons.
3857
+ */
3858
+ class DispatchResult {
3859
+ reasons;
3860
+ constructor(results = []) {
3861
+ if (!Array.isArray(results)) {
3862
+ results = [results];
3863
+ }
3864
+ results = [...new Set(results)];
3865
+ this.reasons = results.filter((result) => result !== 0 /* CommandResult.Success */);
3866
+ }
3867
+ /**
3868
+ * Static helper which returns a successful DispatchResult
3869
+ */
3870
+ static get Success() {
3871
+ return new DispatchResult();
3872
+ }
3873
+ get isSuccessful() {
3874
+ return this.reasons.length === 0;
3875
+ }
3876
+ /**
3877
+ * Check if the dispatch has been cancelled because of
3878
+ * the given reason.
3879
+ */
3880
+ isCancelledBecause(reason) {
3881
+ return this.reasons.includes(reason);
3882
+ }
3883
+ }
3884
+ var CommandResult;
3885
+ (function (CommandResult) {
3886
+ CommandResult[CommandResult["Success"] = 0] = "Success";
3887
+ CommandResult[CommandResult["CancelledForUnknownReason"] = 1] = "CancelledForUnknownReason";
3888
+ CommandResult[CommandResult["WillRemoveExistingMerge"] = 2] = "WillRemoveExistingMerge";
3889
+ CommandResult[CommandResult["MergeIsDestructive"] = 3] = "MergeIsDestructive";
3890
+ CommandResult[CommandResult["CellIsMerged"] = 4] = "CellIsMerged";
3891
+ CommandResult[CommandResult["InvalidTarget"] = 5] = "InvalidTarget";
3892
+ CommandResult[CommandResult["EmptyUndoStack"] = 6] = "EmptyUndoStack";
3893
+ CommandResult[CommandResult["EmptyRedoStack"] = 7] = "EmptyRedoStack";
3894
+ CommandResult[CommandResult["NotEnoughElements"] = 8] = "NotEnoughElements";
3895
+ CommandResult[CommandResult["NotEnoughSheets"] = 9] = "NotEnoughSheets";
3896
+ CommandResult[CommandResult["MissingSheetName"] = 10] = "MissingSheetName";
3897
+ CommandResult[CommandResult["UnchangedSheetName"] = 11] = "UnchangedSheetName";
3898
+ CommandResult[CommandResult["DuplicatedSheetName"] = 12] = "DuplicatedSheetName";
3899
+ CommandResult[CommandResult["DuplicatedSheetId"] = 13] = "DuplicatedSheetId";
3900
+ CommandResult[CommandResult["ForbiddenCharactersInSheetName"] = 14] = "ForbiddenCharactersInSheetName";
3901
+ CommandResult[CommandResult["WrongSheetMove"] = 15] = "WrongSheetMove";
3902
+ CommandResult[CommandResult["WrongSheetPosition"] = 16] = "WrongSheetPosition";
3903
+ CommandResult[CommandResult["InvalidAnchorZone"] = 17] = "InvalidAnchorZone";
3904
+ CommandResult[CommandResult["SelectionOutOfBound"] = 18] = "SelectionOutOfBound";
3905
+ CommandResult[CommandResult["TargetOutOfSheet"] = 19] = "TargetOutOfSheet";
3906
+ CommandResult[CommandResult["WrongCutSelection"] = 20] = "WrongCutSelection";
3907
+ CommandResult[CommandResult["WrongPasteSelection"] = 21] = "WrongPasteSelection";
3908
+ CommandResult[CommandResult["WrongPasteOption"] = 22] = "WrongPasteOption";
3909
+ CommandResult[CommandResult["WrongFigurePasteOption"] = 23] = "WrongFigurePasteOption";
3910
+ CommandResult[CommandResult["EmptyClipboard"] = 24] = "EmptyClipboard";
3911
+ CommandResult[CommandResult["EmptyRange"] = 25] = "EmptyRange";
3912
+ CommandResult[CommandResult["InvalidRange"] = 26] = "InvalidRange";
3913
+ CommandResult[CommandResult["InvalidZones"] = 27] = "InvalidZones";
3914
+ CommandResult[CommandResult["InvalidSheetId"] = 28] = "InvalidSheetId";
3915
+ CommandResult[CommandResult["InvalidFigureId"] = 29] = "InvalidFigureId";
3916
+ CommandResult[CommandResult["InputAlreadyFocused"] = 30] = "InputAlreadyFocused";
3917
+ CommandResult[CommandResult["MaximumRangesReached"] = 31] = "MaximumRangesReached";
3918
+ CommandResult[CommandResult["InvalidChartDefinition"] = 32] = "InvalidChartDefinition";
3919
+ CommandResult[CommandResult["InvalidDataSet"] = 33] = "InvalidDataSet";
3920
+ CommandResult[CommandResult["InvalidLabelRange"] = 34] = "InvalidLabelRange";
3921
+ CommandResult[CommandResult["InvalidScorecardKeyValue"] = 35] = "InvalidScorecardKeyValue";
3922
+ CommandResult[CommandResult["InvalidScorecardBaseline"] = 36] = "InvalidScorecardBaseline";
3923
+ CommandResult[CommandResult["InvalidGaugeDataRange"] = 37] = "InvalidGaugeDataRange";
3924
+ CommandResult[CommandResult["EmptyGaugeRangeMin"] = 38] = "EmptyGaugeRangeMin";
3925
+ CommandResult[CommandResult["GaugeRangeMinNaN"] = 39] = "GaugeRangeMinNaN";
3926
+ CommandResult[CommandResult["EmptyGaugeRangeMax"] = 40] = "EmptyGaugeRangeMax";
3927
+ CommandResult[CommandResult["GaugeRangeMaxNaN"] = 41] = "GaugeRangeMaxNaN";
3928
+ CommandResult[CommandResult["GaugeRangeMinBiggerThanRangeMax"] = 42] = "GaugeRangeMinBiggerThanRangeMax";
3929
+ CommandResult[CommandResult["GaugeLowerInflectionPointNaN"] = 43] = "GaugeLowerInflectionPointNaN";
3930
+ CommandResult[CommandResult["GaugeUpperInflectionPointNaN"] = 44] = "GaugeUpperInflectionPointNaN";
3931
+ CommandResult[CommandResult["GaugeLowerBiggerThanUpper"] = 45] = "GaugeLowerBiggerThanUpper";
3932
+ CommandResult[CommandResult["InvalidAutofillSelection"] = 46] = "InvalidAutofillSelection";
3933
+ CommandResult[CommandResult["WrongComposerSelection"] = 47] = "WrongComposerSelection";
3934
+ CommandResult[CommandResult["MinBiggerThanMax"] = 48] = "MinBiggerThanMax";
3935
+ CommandResult[CommandResult["LowerBiggerThanUpper"] = 49] = "LowerBiggerThanUpper";
3936
+ CommandResult[CommandResult["MidBiggerThanMax"] = 50] = "MidBiggerThanMax";
3937
+ CommandResult[CommandResult["MinBiggerThanMid"] = 51] = "MinBiggerThanMid";
3938
+ CommandResult[CommandResult["FirstArgMissing"] = 52] = "FirstArgMissing";
3939
+ CommandResult[CommandResult["SecondArgMissing"] = 53] = "SecondArgMissing";
3940
+ CommandResult[CommandResult["MinNaN"] = 54] = "MinNaN";
3941
+ CommandResult[CommandResult["MidNaN"] = 55] = "MidNaN";
3942
+ CommandResult[CommandResult["MaxNaN"] = 56] = "MaxNaN";
3943
+ CommandResult[CommandResult["ValueUpperInflectionNaN"] = 57] = "ValueUpperInflectionNaN";
3944
+ CommandResult[CommandResult["ValueLowerInflectionNaN"] = 58] = "ValueLowerInflectionNaN";
3945
+ CommandResult[CommandResult["MinInvalidFormula"] = 59] = "MinInvalidFormula";
3946
+ CommandResult[CommandResult["MidInvalidFormula"] = 60] = "MidInvalidFormula";
3947
+ CommandResult[CommandResult["MaxInvalidFormula"] = 61] = "MaxInvalidFormula";
3948
+ CommandResult[CommandResult["ValueUpperInvalidFormula"] = 62] = "ValueUpperInvalidFormula";
3949
+ CommandResult[CommandResult["ValueLowerInvalidFormula"] = 63] = "ValueLowerInvalidFormula";
3950
+ CommandResult[CommandResult["InvalidSortZone"] = 64] = "InvalidSortZone";
3951
+ CommandResult[CommandResult["WaitingSessionConfirmation"] = 65] = "WaitingSessionConfirmation";
3952
+ CommandResult[CommandResult["MergeOverlap"] = 66] = "MergeOverlap";
3953
+ CommandResult[CommandResult["TooManyHiddenElements"] = 67] = "TooManyHiddenElements";
3954
+ CommandResult[CommandResult["Readonly"] = 68] = "Readonly";
3955
+ CommandResult[CommandResult["InvalidViewportSize"] = 69] = "InvalidViewportSize";
3956
+ CommandResult[CommandResult["InvalidScrollingDirection"] = 70] = "InvalidScrollingDirection";
3957
+ CommandResult[CommandResult["FigureDoesNotExist"] = 71] = "FigureDoesNotExist";
3958
+ CommandResult[CommandResult["InvalidConditionalFormatId"] = 72] = "InvalidConditionalFormatId";
3959
+ CommandResult[CommandResult["InvalidCellPopover"] = 73] = "InvalidCellPopover";
3960
+ CommandResult[CommandResult["EmptyTarget"] = 74] = "EmptyTarget";
3961
+ CommandResult[CommandResult["InvalidFreezeQuantity"] = 75] = "InvalidFreezeQuantity";
3962
+ CommandResult[CommandResult["FrozenPaneOverlap"] = 76] = "FrozenPaneOverlap";
3963
+ CommandResult[CommandResult["ValuesNotChanged"] = 77] = "ValuesNotChanged";
3964
+ CommandResult[CommandResult["InvalidFilterZone"] = 78] = "InvalidFilterZone";
3965
+ CommandResult[CommandResult["FilterOverlap"] = 79] = "FilterOverlap";
3966
+ CommandResult[CommandResult["FilterNotFound"] = 80] = "FilterNotFound";
3967
+ CommandResult[CommandResult["MergeInFilter"] = 81] = "MergeInFilter";
3968
+ CommandResult[CommandResult["NonContinuousTargets"] = 82] = "NonContinuousTargets";
3969
+ CommandResult[CommandResult["DuplicatedFigureId"] = 83] = "DuplicatedFigureId";
3970
+ CommandResult[CommandResult["InvalidSelectionStep"] = 84] = "InvalidSelectionStep";
3971
+ CommandResult[CommandResult["DuplicatedChartId"] = 85] = "DuplicatedChartId";
3972
+ CommandResult[CommandResult["ChartDoesNotExist"] = 86] = "ChartDoesNotExist";
3973
+ CommandResult[CommandResult["InvalidHeaderIndex"] = 87] = "InvalidHeaderIndex";
3974
+ CommandResult[CommandResult["InvalidQuantity"] = 88] = "InvalidQuantity";
3975
+ CommandResult[CommandResult["MoreThanOneColumnSelected"] = 89] = "MoreThanOneColumnSelected";
3976
+ CommandResult[CommandResult["EmptySplitSeparator"] = 90] = "EmptySplitSeparator";
3977
+ CommandResult[CommandResult["SplitWillOverwriteContent"] = 91] = "SplitWillOverwriteContent";
3978
+ CommandResult[CommandResult["NoSplitSeparatorInSelection"] = 92] = "NoSplitSeparatorInSelection";
3979
+ CommandResult[CommandResult["NoActiveSheet"] = 93] = "NoActiveSheet";
3980
+ })(CommandResult || (CommandResult = {}));
3981
+
3982
+ const borderStyles = ["thin", "medium", "thick", "dashed", "dotted"];
3983
+ function isMatrix(x) {
3984
+ return Array.isArray(x) && Array.isArray(x[0]);
3985
+ }
3986
+ var DIRECTION;
3987
+ (function (DIRECTION) {
3988
+ DIRECTION["UP"] = "up";
3989
+ DIRECTION["DOWN"] = "down";
3990
+ DIRECTION["LEFT"] = "left";
3991
+ DIRECTION["RIGHT"] = "right";
3992
+ })(DIRECTION || (DIRECTION = {}));
3993
+
3994
+ var LAYERS;
3995
+ (function (LAYERS) {
3996
+ LAYERS[LAYERS["Background"] = 0] = "Background";
3997
+ LAYERS[LAYERS["Highlights"] = 1] = "Highlights";
3998
+ LAYERS[LAYERS["Clipboard"] = 2] = "Clipboard";
3999
+ LAYERS[LAYERS["Search"] = 3] = "Search";
4000
+ LAYERS[LAYERS["Chart"] = 4] = "Chart";
4001
+ LAYERS[LAYERS["Autofill"] = 5] = "Autofill";
4002
+ LAYERS[LAYERS["Selection"] = 6] = "Selection";
4003
+ LAYERS[LAYERS["Headers"] = 7] = "Headers";
4004
+ })(LAYERS || (LAYERS = {}));
4005
+
3707
4006
  // HELPERS
3708
4007
  const SORT_TYPES_ORDER = ["number", "string", "boolean", "undefined"];
3709
4008
  function assert(condition, message) {
@@ -3745,6 +4044,9 @@ function strictToNumber(value) {
3745
4044
  }
3746
4045
  return toNumber(value);
3747
4046
  }
4047
+ function toInteger(value) {
4048
+ return Math.trunc(toNumber(value));
4049
+ }
3748
4050
  function strictToInteger(value) {
3749
4051
  return Math.trunc(strictToNumber(value));
3750
4052
  }
@@ -3847,16 +4149,25 @@ function visitNumbers(args, cb) {
3847
4149
  // -----------------------------------------------------------------------------
3848
4150
  // REDUCE FUNCTIONS
3849
4151
  // -----------------------------------------------------------------------------
3850
- function reduceArgs(args, cellCb, dataCb, initialValue) {
4152
+ function reduceArgs(args, cellCb, dataCb, initialValue, dir = "rowFirst") {
3851
4153
  let val = initialValue;
3852
4154
  for (let arg of args) {
3853
4155
  if (Array.isArray(arg)) {
3854
4156
  // arg is ref to a Cell/Range
3855
- const lenRow = arg.length;
3856
- const lenCol = arg[0].length;
3857
- for (let y = 0; y < lenCol; y++) {
3858
- for (let x = 0; x < lenRow; x++) {
3859
- val = cellCb(val, arg[x][y]);
4157
+ const numberOfCols = arg.length;
4158
+ const numberOfRows = arg[0].length;
4159
+ if (dir === "rowFirst") {
4160
+ for (let row = 0; row < numberOfRows; row++) {
4161
+ for (let col = 0; col < numberOfCols; col++) {
4162
+ val = cellCb(val, arg[col][row]);
4163
+ }
4164
+ }
4165
+ }
4166
+ else {
4167
+ for (let col = 0; col < numberOfCols; col++) {
4168
+ for (let row = 0; row < numberOfRows; row++) {
4169
+ val = cellCb(val, arg[col][row]);
4170
+ }
3860
4171
  }
3861
4172
  }
3862
4173
  }
@@ -3867,8 +4178,8 @@ function reduceArgs(args, cellCb, dataCb, initialValue) {
3867
4178
  }
3868
4179
  return val;
3869
4180
  }
3870
- function reduceAny(args, cb, initialValue) {
3871
- return reduceArgs(args, cb, cb, initialValue);
4181
+ function reduceAny(args, cb, initialValue, dir = "rowFirst") {
4182
+ return reduceArgs(args, cb, cb, initialValue, dir);
3872
4183
  }
3873
4184
  function reduceNumbers(args, cb, initialValue) {
3874
4185
  return reduceArgs(args, (acc, ArgValue) => {
@@ -4245,290 +4556,57 @@ function compareCellValues(left, right) {
4245
4556
  }
4246
4557
  }
4247
4558
  return typeOrder;
4248
- }
4249
-
4250
- var CellValueType;
4251
- (function (CellValueType) {
4252
- CellValueType["boolean"] = "boolean";
4253
- CellValueType["number"] = "number";
4254
- CellValueType["text"] = "text";
4255
- CellValueType["empty"] = "empty";
4256
- CellValueType["error"] = "error";
4257
- })(CellValueType || (CellValueType = {}));
4258
-
4259
- var ClipboardMIMEType;
4260
- (function (ClipboardMIMEType) {
4261
- ClipboardMIMEType["PlainText"] = "text/plain";
4262
- ClipboardMIMEType["Html"] = "text/html";
4263
- })(ClipboardMIMEType || (ClipboardMIMEType = {}));
4264
-
4265
- function isSheetDependent(cmd) {
4266
- return "sheetId" in cmd;
4267
- }
4268
- function isGridDependent(cmd) {
4269
- return "dimension" in cmd && "sheetId" in cmd;
4270
4559
  }
4271
- function isTargetDependent(cmd) {
4272
- return "target" in cmd && "sheetId" in cmd;
4273
- }
4274
- function isRangeDependant(cmd) {
4275
- return "ranges" in cmd;
4560
+ function matrixMap(matrix, fn) {
4561
+ let result = new Array(matrix.length);
4562
+ for (let i = 0; i < matrix.length; i++) {
4563
+ result[i] = new Array(matrix[i].length);
4564
+ for (let j = 0; j < matrix[i].length; j++) {
4565
+ result[i][j] = fn(matrix[i][j]);
4566
+ }
4567
+ }
4568
+ return result;
4276
4569
  }
4277
- function isPositionDependent(cmd) {
4278
- return "col" in cmd && "row" in cmd && "sheetId" in cmd;
4570
+ function toCellValueMatrix(values) {
4571
+ return matrixMap(values, toCellValue);
4279
4572
  }
4280
- const invalidateEvaluationCommands = new Set([
4281
- "RENAME_SHEET",
4282
- "DELETE_SHEET",
4283
- "CREATE_SHEET",
4284
- "ADD_COLUMNS_ROWS",
4285
- "REMOVE_COLUMNS_ROWS",
4286
- "UNDO",
4287
- "REDO",
4288
- "ADD_MERGE",
4289
- ]);
4290
- const invalidateDependenciesCommands = new Set([
4291
- ...invalidateEvaluationCommands,
4292
- "MOVE_RANGES",
4293
- ]);
4294
- const invalidateCFEvaluationCommands = new Set([
4295
- ...invalidateEvaluationCommands,
4296
- "DUPLICATE_SHEET",
4297
- "EVALUATE_CELLS",
4298
- "ADD_CONDITIONAL_FORMAT",
4299
- "REMOVE_CONDITIONAL_FORMAT",
4300
- "MOVE_CONDITIONAL_FORMAT",
4301
- ]);
4302
- const readonlyAllowedCommands = new Set([
4303
- "START",
4304
- "ACTIVATE_SHEET",
4305
- "COPY",
4306
- "PREPARE_SELECTION_INPUT_EXPANSION",
4307
- "STOP_SELECTION_INPUT",
4308
- "RESIZE_SHEETVIEW",
4309
- "SET_VIEWPORT_OFFSET",
4310
- "SELECT_SEARCH_NEXT_MATCH",
4311
- "SELECT_SEARCH_PREVIOUS_MATCH",
4312
- "REFRESH_SEARCH",
4313
- "UPDATE_SEARCH",
4314
- "CLEAR_SEARCH",
4315
- "EVALUATE_CELLS",
4316
- "SET_CURRENT_CONTENT",
4317
- "SET_FORMULA_VISIBILITY",
4318
- "OPEN_CELL_POPOVER",
4319
- "CLOSE_CELL_POPOVER",
4320
- "UPDATE_FILTER",
4321
- ]);
4322
- const coreTypes = new Set([
4323
- /** CELLS */
4324
- "UPDATE_CELL",
4325
- "UPDATE_CELL_POSITION",
4326
- "CLEAR_CELL",
4327
- "DELETE_CONTENT",
4328
- /** GRID SHAPE */
4329
- "ADD_COLUMNS_ROWS",
4330
- "REMOVE_COLUMNS_ROWS",
4331
- "RESIZE_COLUMNS_ROWS",
4332
- "HIDE_COLUMNS_ROWS",
4333
- "UNHIDE_COLUMNS_ROWS",
4334
- "SET_GRID_LINES_VISIBILITY",
4335
- "UNFREEZE_COLUMNS",
4336
- "UNFREEZE_ROWS",
4337
- "FREEZE_COLUMNS",
4338
- "FREEZE_ROWS",
4339
- "UNFREEZE_COLUMNS_ROWS",
4340
- /** MERGE */
4341
- "ADD_MERGE",
4342
- "REMOVE_MERGE",
4343
- /** SHEETS MANIPULATION */
4344
- "CREATE_SHEET",
4345
- "DELETE_SHEET",
4346
- "DUPLICATE_SHEET",
4347
- "MOVE_SHEET",
4348
- "RENAME_SHEET",
4349
- "HIDE_SHEET",
4350
- "SHOW_SHEET",
4351
- /** RANGES MANIPULATION */
4352
- "MOVE_RANGES",
4353
- /** CONDITIONAL FORMAT */
4354
- "ADD_CONDITIONAL_FORMAT",
4355
- "REMOVE_CONDITIONAL_FORMAT",
4356
- "MOVE_CONDITIONAL_FORMAT",
4357
- /** FIGURES */
4358
- "CREATE_FIGURE",
4359
- "DELETE_FIGURE",
4360
- "UPDATE_FIGURE",
4361
- /** FORMATTING */
4362
- "SET_FORMATTING",
4363
- "CLEAR_FORMATTING",
4364
- "SET_BORDER",
4365
- "SET_ZONE_BORDERS",
4366
- /** CHART */
4367
- "CREATE_CHART",
4368
- "UPDATE_CHART",
4369
- /** FILTERS */
4370
- "CREATE_FILTER_TABLE",
4371
- "REMOVE_FILTER_TABLE",
4372
- /** IMAGE */
4373
- "CREATE_IMAGE",
4374
- ]);
4375
- function isCoreCommand(cmd) {
4376
- return coreTypes.has(cmd.type);
4573
+ function toCellValue(value) {
4574
+ if (value === null || value === undefined)
4575
+ return 0;
4576
+ if (typeof value === "number")
4577
+ return value;
4578
+ if (typeof value === "string")
4579
+ return value;
4580
+ if (typeof value === "boolean")
4581
+ return value;
4582
+ return String(value);
4377
4583
  }
4378
- function canExecuteInReadonly(cmd) {
4379
- return readonlyAllowedCommands.has(cmd.type);
4584
+ function toMatrixArgValue(values) {
4585
+ if (isMatrix(values))
4586
+ return values;
4587
+ return [[values === null ? 0 : values]];
4380
4588
  }
4381
4589
  /**
4382
- * Holds the result of a command dispatch.
4383
- * The command may have been successfully dispatched or cancelled
4384
- * for one or more reasons.
4590
+ * Flatten an array of items, where each item can be a single value or a 2D array, and apply the
4591
+ * callback to each element.
4592
+ *
4593
+ * The 2D array are flattened row first.
4385
4594
  */
4386
- class DispatchResult {
4387
- reasons;
4388
- constructor(results = []) {
4389
- if (!Array.isArray(results)) {
4390
- results = [results];
4595
+ function flattenRowFirst(items, callback) {
4596
+ const flattened = [];
4597
+ for (const item of items) {
4598
+ if (!Array.isArray(item)) {
4599
+ flattened.push(callback(item));
4600
+ continue;
4601
+ }
4602
+ for (let row = 0; row < item[0].length; row++) {
4603
+ for (let col = 0; col < item.length; col++) {
4604
+ flattened.push(callback(item[col][row]));
4605
+ }
4391
4606
  }
4392
- results = [...new Set(results)];
4393
- this.reasons = results.filter((result) => result !== 0 /* CommandResult.Success */);
4394
- }
4395
- /**
4396
- * Static helper which returns a successful DispatchResult
4397
- */
4398
- static get Success() {
4399
- return new DispatchResult();
4400
- }
4401
- get isSuccessful() {
4402
- return this.reasons.length === 0;
4403
- }
4404
- /**
4405
- * Check if the dispatch has been cancelled because of
4406
- * the given reason.
4407
- */
4408
- isCancelledBecause(reason) {
4409
- return this.reasons.includes(reason);
4410
4607
  }
4411
- }
4412
- var CommandResult;
4413
- (function (CommandResult) {
4414
- CommandResult[CommandResult["Success"] = 0] = "Success";
4415
- CommandResult[CommandResult["CancelledForUnknownReason"] = 1] = "CancelledForUnknownReason";
4416
- CommandResult[CommandResult["WillRemoveExistingMerge"] = 2] = "WillRemoveExistingMerge";
4417
- CommandResult[CommandResult["MergeIsDestructive"] = 3] = "MergeIsDestructive";
4418
- CommandResult[CommandResult["CellIsMerged"] = 4] = "CellIsMerged";
4419
- CommandResult[CommandResult["InvalidTarget"] = 5] = "InvalidTarget";
4420
- CommandResult[CommandResult["EmptyUndoStack"] = 6] = "EmptyUndoStack";
4421
- CommandResult[CommandResult["EmptyRedoStack"] = 7] = "EmptyRedoStack";
4422
- CommandResult[CommandResult["NotEnoughElements"] = 8] = "NotEnoughElements";
4423
- CommandResult[CommandResult["NotEnoughSheets"] = 9] = "NotEnoughSheets";
4424
- CommandResult[CommandResult["MissingSheetName"] = 10] = "MissingSheetName";
4425
- CommandResult[CommandResult["DuplicatedSheetName"] = 11] = "DuplicatedSheetName";
4426
- CommandResult[CommandResult["DuplicatedSheetId"] = 12] = "DuplicatedSheetId";
4427
- CommandResult[CommandResult["ForbiddenCharactersInSheetName"] = 13] = "ForbiddenCharactersInSheetName";
4428
- CommandResult[CommandResult["WrongSheetMove"] = 14] = "WrongSheetMove";
4429
- CommandResult[CommandResult["WrongSheetPosition"] = 15] = "WrongSheetPosition";
4430
- CommandResult[CommandResult["InvalidAnchorZone"] = 16] = "InvalidAnchorZone";
4431
- CommandResult[CommandResult["SelectionOutOfBound"] = 17] = "SelectionOutOfBound";
4432
- CommandResult[CommandResult["TargetOutOfSheet"] = 18] = "TargetOutOfSheet";
4433
- CommandResult[CommandResult["WrongCutSelection"] = 19] = "WrongCutSelection";
4434
- CommandResult[CommandResult["WrongPasteSelection"] = 20] = "WrongPasteSelection";
4435
- CommandResult[CommandResult["WrongPasteOption"] = 21] = "WrongPasteOption";
4436
- CommandResult[CommandResult["WrongFigurePasteOption"] = 22] = "WrongFigurePasteOption";
4437
- CommandResult[CommandResult["EmptyClipboard"] = 23] = "EmptyClipboard";
4438
- CommandResult[CommandResult["EmptyRange"] = 24] = "EmptyRange";
4439
- CommandResult[CommandResult["InvalidRange"] = 25] = "InvalidRange";
4440
- CommandResult[CommandResult["InvalidZones"] = 26] = "InvalidZones";
4441
- CommandResult[CommandResult["InvalidSheetId"] = 27] = "InvalidSheetId";
4442
- CommandResult[CommandResult["InvalidFigureId"] = 28] = "InvalidFigureId";
4443
- CommandResult[CommandResult["InputAlreadyFocused"] = 29] = "InputAlreadyFocused";
4444
- CommandResult[CommandResult["MaximumRangesReached"] = 30] = "MaximumRangesReached";
4445
- CommandResult[CommandResult["InvalidChartDefinition"] = 31] = "InvalidChartDefinition";
4446
- CommandResult[CommandResult["InvalidDataSet"] = 32] = "InvalidDataSet";
4447
- CommandResult[CommandResult["InvalidLabelRange"] = 33] = "InvalidLabelRange";
4448
- CommandResult[CommandResult["InvalidScorecardKeyValue"] = 34] = "InvalidScorecardKeyValue";
4449
- CommandResult[CommandResult["InvalidScorecardBaseline"] = 35] = "InvalidScorecardBaseline";
4450
- CommandResult[CommandResult["InvalidGaugeDataRange"] = 36] = "InvalidGaugeDataRange";
4451
- CommandResult[CommandResult["EmptyGaugeRangeMin"] = 37] = "EmptyGaugeRangeMin";
4452
- CommandResult[CommandResult["GaugeRangeMinNaN"] = 38] = "GaugeRangeMinNaN";
4453
- CommandResult[CommandResult["EmptyGaugeRangeMax"] = 39] = "EmptyGaugeRangeMax";
4454
- CommandResult[CommandResult["GaugeRangeMaxNaN"] = 40] = "GaugeRangeMaxNaN";
4455
- CommandResult[CommandResult["GaugeRangeMinBiggerThanRangeMax"] = 41] = "GaugeRangeMinBiggerThanRangeMax";
4456
- CommandResult[CommandResult["GaugeLowerInflectionPointNaN"] = 42] = "GaugeLowerInflectionPointNaN";
4457
- CommandResult[CommandResult["GaugeUpperInflectionPointNaN"] = 43] = "GaugeUpperInflectionPointNaN";
4458
- CommandResult[CommandResult["GaugeLowerBiggerThanUpper"] = 44] = "GaugeLowerBiggerThanUpper";
4459
- CommandResult[CommandResult["InvalidAutofillSelection"] = 45] = "InvalidAutofillSelection";
4460
- CommandResult[CommandResult["WrongComposerSelection"] = 46] = "WrongComposerSelection";
4461
- CommandResult[CommandResult["MinBiggerThanMax"] = 47] = "MinBiggerThanMax";
4462
- CommandResult[CommandResult["LowerBiggerThanUpper"] = 48] = "LowerBiggerThanUpper";
4463
- CommandResult[CommandResult["MidBiggerThanMax"] = 49] = "MidBiggerThanMax";
4464
- CommandResult[CommandResult["MinBiggerThanMid"] = 50] = "MinBiggerThanMid";
4465
- CommandResult[CommandResult["FirstArgMissing"] = 51] = "FirstArgMissing";
4466
- CommandResult[CommandResult["SecondArgMissing"] = 52] = "SecondArgMissing";
4467
- CommandResult[CommandResult["MinNaN"] = 53] = "MinNaN";
4468
- CommandResult[CommandResult["MidNaN"] = 54] = "MidNaN";
4469
- CommandResult[CommandResult["MaxNaN"] = 55] = "MaxNaN";
4470
- CommandResult[CommandResult["ValueUpperInflectionNaN"] = 56] = "ValueUpperInflectionNaN";
4471
- CommandResult[CommandResult["ValueLowerInflectionNaN"] = 57] = "ValueLowerInflectionNaN";
4472
- CommandResult[CommandResult["MinInvalidFormula"] = 58] = "MinInvalidFormula";
4473
- CommandResult[CommandResult["MidInvalidFormula"] = 59] = "MidInvalidFormula";
4474
- CommandResult[CommandResult["MaxInvalidFormula"] = 60] = "MaxInvalidFormula";
4475
- CommandResult[CommandResult["ValueUpperInvalidFormula"] = 61] = "ValueUpperInvalidFormula";
4476
- CommandResult[CommandResult["ValueLowerInvalidFormula"] = 62] = "ValueLowerInvalidFormula";
4477
- CommandResult[CommandResult["InvalidSortZone"] = 63] = "InvalidSortZone";
4478
- CommandResult[CommandResult["WaitingSessionConfirmation"] = 64] = "WaitingSessionConfirmation";
4479
- CommandResult[CommandResult["MergeOverlap"] = 65] = "MergeOverlap";
4480
- CommandResult[CommandResult["TooManyHiddenElements"] = 66] = "TooManyHiddenElements";
4481
- CommandResult[CommandResult["Readonly"] = 67] = "Readonly";
4482
- CommandResult[CommandResult["InvalidViewportSize"] = 68] = "InvalidViewportSize";
4483
- CommandResult[CommandResult["InvalidScrollingDirection"] = 69] = "InvalidScrollingDirection";
4484
- CommandResult[CommandResult["FigureDoesNotExist"] = 70] = "FigureDoesNotExist";
4485
- CommandResult[CommandResult["InvalidConditionalFormatId"] = 71] = "InvalidConditionalFormatId";
4486
- CommandResult[CommandResult["InvalidCellPopover"] = 72] = "InvalidCellPopover";
4487
- CommandResult[CommandResult["EmptyTarget"] = 73] = "EmptyTarget";
4488
- CommandResult[CommandResult["InvalidFreezeQuantity"] = 74] = "InvalidFreezeQuantity";
4489
- CommandResult[CommandResult["FrozenPaneOverlap"] = 75] = "FrozenPaneOverlap";
4490
- CommandResult[CommandResult["ValuesNotChanged"] = 76] = "ValuesNotChanged";
4491
- CommandResult[CommandResult["InvalidFilterZone"] = 77] = "InvalidFilterZone";
4492
- CommandResult[CommandResult["FilterOverlap"] = 78] = "FilterOverlap";
4493
- CommandResult[CommandResult["FilterNotFound"] = 79] = "FilterNotFound";
4494
- CommandResult[CommandResult["MergeInFilter"] = 80] = "MergeInFilter";
4495
- CommandResult[CommandResult["NonContinuousTargets"] = 81] = "NonContinuousTargets";
4496
- CommandResult[CommandResult["DuplicatedFigureId"] = 82] = "DuplicatedFigureId";
4497
- CommandResult[CommandResult["InvalidSelectionStep"] = 83] = "InvalidSelectionStep";
4498
- CommandResult[CommandResult["DuplicatedChartId"] = 84] = "DuplicatedChartId";
4499
- CommandResult[CommandResult["ChartDoesNotExist"] = 85] = "ChartDoesNotExist";
4500
- CommandResult[CommandResult["InvalidHeaderIndex"] = 86] = "InvalidHeaderIndex";
4501
- CommandResult[CommandResult["InvalidQuantity"] = 87] = "InvalidQuantity";
4502
- CommandResult[CommandResult["MoreThanOneColumnSelected"] = 88] = "MoreThanOneColumnSelected";
4503
- CommandResult[CommandResult["EmptySplitSeparator"] = 89] = "EmptySplitSeparator";
4504
- CommandResult[CommandResult["SplitWillOverwriteContent"] = 90] = "SplitWillOverwriteContent";
4505
- CommandResult[CommandResult["NoSplitSeparatorInSelection"] = 91] = "NoSplitSeparatorInSelection";
4506
- CommandResult[CommandResult["NoActiveSheet"] = 92] = "NoActiveSheet";
4507
- })(CommandResult || (CommandResult = {}));
4508
-
4509
- const borderStyles = ["thin", "medium", "thick", "dashed", "dotted"];
4510
- function isMatrix(x) {
4511
- return Array.isArray(x) && Array.isArray(x[0]);
4512
- }
4513
- var DIRECTION;
4514
- (function (DIRECTION) {
4515
- DIRECTION["UP"] = "up";
4516
- DIRECTION["DOWN"] = "down";
4517
- DIRECTION["LEFT"] = "left";
4518
- DIRECTION["RIGHT"] = "right";
4519
- })(DIRECTION || (DIRECTION = {}));
4520
-
4521
- var LAYERS;
4522
- (function (LAYERS) {
4523
- LAYERS[LAYERS["Background"] = 0] = "Background";
4524
- LAYERS[LAYERS["Highlights"] = 1] = "Highlights";
4525
- LAYERS[LAYERS["Clipboard"] = 2] = "Clipboard";
4526
- LAYERS[LAYERS["Search"] = 3] = "Search";
4527
- LAYERS[LAYERS["Chart"] = 4] = "Chart";
4528
- LAYERS[LAYERS["Autofill"] = 5] = "Autofill";
4529
- LAYERS[LAYERS["Selection"] = 6] = "Selection";
4530
- LAYERS[LAYERS["Headers"] = 7] = "Headers";
4531
- })(LAYERS || (LAYERS = {}));
4608
+ return flattened;
4609
+ }
4532
4610
 
4533
4611
  function evaluateLiteral(content, format) {
4534
4612
  return createEvaluatedCell(parseLiteral(content || ""), format);
@@ -5109,10 +5187,10 @@ class FilterMenu extends Component {
5109
5187
  this.state.selectedValue = value.string;
5110
5188
  }
5111
5189
  selectAll() {
5112
- this.state.values.forEach((value) => (value.checked = true));
5190
+ this.displayedValues.forEach((value) => (value.checked = true));
5113
5191
  }
5114
5192
  clearAll() {
5115
- this.state.values.forEach((value) => (value.checked = false));
5193
+ this.displayedValues.forEach((value) => (value.checked = false));
5116
5194
  }
5117
5195
  get filterTable() {
5118
5196
  const sheetId = this.env.model.getters.getActiveSheetId();
@@ -6575,11 +6653,11 @@ function checkDataset(definition) {
6575
6653
  if (definition.dataSets) {
6576
6654
  const invalidRanges = definition.dataSets.find((range) => !rangeReference.test(range)) !== undefined;
6577
6655
  if (invalidRanges) {
6578
- return 32 /* CommandResult.InvalidDataSet */;
6656
+ return 33 /* CommandResult.InvalidDataSet */;
6579
6657
  }
6580
6658
  const zones = definition.dataSets.map(toUnboundedZone);
6581
6659
  if (zones.some((zone) => zone.top !== zone.bottom && isFullRow(zone))) {
6582
- return 32 /* CommandResult.InvalidDataSet */;
6660
+ return 33 /* CommandResult.InvalidDataSet */;
6583
6661
  }
6584
6662
  }
6585
6663
  return 0 /* CommandResult.Success */;
@@ -6588,7 +6666,7 @@ function checkLabelRange(definition) {
6588
6666
  if (definition.labelRange) {
6589
6667
  const invalidLabels = !rangeReference.test(definition.labelRange || "");
6590
6668
  if (invalidLabels) {
6591
- return 33 /* CommandResult.InvalidLabelRange */;
6669
+ return 34 /* CommandResult.InvalidLabelRange */;
6592
6670
  }
6593
6671
  }
6594
6672
  return 0 /* CommandResult.Success */;
@@ -6674,24 +6752,24 @@ function getChartPositionAtCenterOfViewport(getters, chartSize) {
6674
6752
 
6675
6753
  const CfTerms = {
6676
6754
  Errors: {
6677
- [25 /* CommandResult.InvalidRange */]: _lt("The range is invalid"),
6678
- [51 /* CommandResult.FirstArgMissing */]: _lt("The argument is missing. Please provide a value"),
6679
- [52 /* CommandResult.SecondArgMissing */]: _lt("The second argument is missing. Please provide a value"),
6680
- [53 /* CommandResult.MinNaN */]: _lt("The minpoint must be a number"),
6681
- [54 /* CommandResult.MidNaN */]: _lt("The midpoint must be a number"),
6682
- [55 /* CommandResult.MaxNaN */]: _lt("The maxpoint must be a number"),
6683
- [56 /* CommandResult.ValueUpperInflectionNaN */]: _lt("The first value must be a number"),
6684
- [57 /* CommandResult.ValueLowerInflectionNaN */]: _lt("The second value must be a number"),
6685
- [47 /* CommandResult.MinBiggerThanMax */]: _lt("Minimum must be smaller then Maximum"),
6686
- [50 /* CommandResult.MinBiggerThanMid */]: _lt("Minimum must be smaller then Midpoint"),
6687
- [49 /* CommandResult.MidBiggerThanMax */]: _lt("Midpoint must be smaller then Maximum"),
6688
- [48 /* CommandResult.LowerBiggerThanUpper */]: _lt("Lower inflection point must be smaller than upper inflection point"),
6689
- [58 /* CommandResult.MinInvalidFormula */]: _lt("Invalid Minpoint formula"),
6690
- [60 /* CommandResult.MaxInvalidFormula */]: _lt("Invalid Maxpoint formula"),
6691
- [59 /* CommandResult.MidInvalidFormula */]: _lt("Invalid Midpoint formula"),
6692
- [61 /* CommandResult.ValueUpperInvalidFormula */]: _lt("Invalid upper inflection point formula"),
6693
- [62 /* CommandResult.ValueLowerInvalidFormula */]: _lt("Invalid lower inflection point formula"),
6694
- [24 /* CommandResult.EmptyRange */]: _lt("A range needs to be defined"),
6755
+ [26 /* CommandResult.InvalidRange */]: _lt("The range is invalid"),
6756
+ [52 /* CommandResult.FirstArgMissing */]: _lt("The argument is missing. Please provide a value"),
6757
+ [53 /* CommandResult.SecondArgMissing */]: _lt("The second argument is missing. Please provide a value"),
6758
+ [54 /* CommandResult.MinNaN */]: _lt("The minpoint must be a number"),
6759
+ [55 /* CommandResult.MidNaN */]: _lt("The midpoint must be a number"),
6760
+ [56 /* CommandResult.MaxNaN */]: _lt("The maxpoint must be a number"),
6761
+ [57 /* CommandResult.ValueUpperInflectionNaN */]: _lt("The first value must be a number"),
6762
+ [58 /* CommandResult.ValueLowerInflectionNaN */]: _lt("The second value must be a number"),
6763
+ [48 /* CommandResult.MinBiggerThanMax */]: _lt("Minimum must be smaller then Maximum"),
6764
+ [51 /* CommandResult.MinBiggerThanMid */]: _lt("Minimum must be smaller then Midpoint"),
6765
+ [50 /* CommandResult.MidBiggerThanMax */]: _lt("Midpoint must be smaller then Maximum"),
6766
+ [49 /* CommandResult.LowerBiggerThanUpper */]: _lt("Lower inflection point must be smaller than upper inflection point"),
6767
+ [59 /* CommandResult.MinInvalidFormula */]: _lt("Invalid Minpoint formula"),
6768
+ [61 /* CommandResult.MaxInvalidFormula */]: _lt("Invalid Maxpoint formula"),
6769
+ [60 /* CommandResult.MidInvalidFormula */]: _lt("Invalid Midpoint formula"),
6770
+ [62 /* CommandResult.ValueUpperInvalidFormula */]: _lt("Invalid upper inflection point formula"),
6771
+ [63 /* CommandResult.ValueLowerInvalidFormula */]: _lt("Invalid lower inflection point formula"),
6772
+ [25 /* CommandResult.EmptyRange */]: _lt("A range needs to be defined"),
6695
6773
  Unexpected: _lt("The rule is invalid for an unknown reason"),
6696
6774
  },
6697
6775
  ColorScale: _lt("Color scale"),
@@ -6718,20 +6796,20 @@ const ChartTerms = {
6718
6796
  Errors: {
6719
6797
  Unexpected: _lt("The chart definition is invalid for an unknown reason"),
6720
6798
  // BASIC CHART ERRORS (LINE | BAR | PIE)
6721
- [32 /* CommandResult.InvalidDataSet */]: _lt("The dataset is invalid"),
6722
- [33 /* CommandResult.InvalidLabelRange */]: _lt("Labels are invalid"),
6799
+ [33 /* CommandResult.InvalidDataSet */]: _lt("The dataset is invalid"),
6800
+ [34 /* CommandResult.InvalidLabelRange */]: _lt("Labels are invalid"),
6723
6801
  // SCORECARD CHART ERRORS
6724
- [34 /* CommandResult.InvalidScorecardKeyValue */]: _lt("The key value is invalid"),
6725
- [35 /* CommandResult.InvalidScorecardBaseline */]: _lt("The baseline value is invalid"),
6802
+ [35 /* CommandResult.InvalidScorecardKeyValue */]: _lt("The key value is invalid"),
6803
+ [36 /* CommandResult.InvalidScorecardBaseline */]: _lt("The baseline value is invalid"),
6726
6804
  // GAUGE CHART ERRORS
6727
- [36 /* CommandResult.InvalidGaugeDataRange */]: _lt("The data range is invalid"),
6728
- [37 /* CommandResult.EmptyGaugeRangeMin */]: _lt("A minimum range limit value is needed"),
6729
- [38 /* CommandResult.GaugeRangeMinNaN */]: _lt("The minimum range limit value must be a number"),
6730
- [39 /* CommandResult.EmptyGaugeRangeMax */]: _lt("A maximum range limit value is needed"),
6731
- [40 /* CommandResult.GaugeRangeMaxNaN */]: _lt("The maximum range limit value must be a number"),
6732
- [41 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */]: _lt("Minimum range limit must be smaller than maximum range limit"),
6733
- [42 /* CommandResult.GaugeLowerInflectionPointNaN */]: _lt("The lower inflection point value must be a number"),
6734
- [43 /* CommandResult.GaugeUpperInflectionPointNaN */]: _lt("The upper inflection point value must be a number"),
6805
+ [37 /* CommandResult.InvalidGaugeDataRange */]: _lt("The data range is invalid"),
6806
+ [38 /* CommandResult.EmptyGaugeRangeMin */]: _lt("A minimum range limit value is needed"),
6807
+ [39 /* CommandResult.GaugeRangeMinNaN */]: _lt("The minimum range limit value must be a number"),
6808
+ [40 /* CommandResult.EmptyGaugeRangeMax */]: _lt("A maximum range limit value is needed"),
6809
+ [41 /* CommandResult.GaugeRangeMaxNaN */]: _lt("The maximum range limit value must be a number"),
6810
+ [42 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */]: _lt("Minimum range limit must be smaller than maximum range limit"),
6811
+ [43 /* CommandResult.GaugeLowerInflectionPointNaN */]: _lt("The lower inflection point value must be a number"),
6812
+ [44 /* CommandResult.GaugeUpperInflectionPointNaN */]: _lt("The upper inflection point value must be a number"),
6735
6813
  },
6736
6814
  };
6737
6815
  const CustomCurrencyTerms = {
@@ -6741,9 +6819,9 @@ const MergeErrorMessage = _lt("Merged cells are preventing this operation. Unmer
6741
6819
  const SplitToColumnsTerms = {
6742
6820
  Errors: {
6743
6821
  Unexpected: _lt("Cannot split the selection for an unknown reason"),
6744
- [91 /* CommandResult.NoSplitSeparatorInSelection */]: _lt("There is no match for the selected separator in the selection"),
6745
- [88 /* CommandResult.MoreThanOneColumnSelected */]: _lt("Only a selection from a single column can be split"),
6746
- [90 /* CommandResult.SplitWillOverwriteContent */]: _lt("Splitting will overwrite existing content"),
6822
+ [92 /* CommandResult.NoSplitSeparatorInSelection */]: _lt("There is no match for the selected separator in the selection"),
6823
+ [89 /* CommandResult.MoreThanOneColumnSelected */]: _lt("Only a selection from a single column can be split"),
6824
+ [91 /* CommandResult.SplitWillOverwriteContent */]: _lt("Splitting will overwrite existing content"),
6747
6825
  },
6748
6826
  };
6749
6827
 
@@ -7147,7 +7225,7 @@ function createBarChartRuntime(chart, getters) {
7147
7225
 
7148
7226
  function isDataRangeValid(definition) {
7149
7227
  return definition.dataRange && !rangeReference.test(definition.dataRange)
7150
- ? 36 /* CommandResult.InvalidGaugeDataRange */
7228
+ ? 37 /* CommandResult.InvalidGaugeDataRange */
7151
7229
  : 0 /* CommandResult.Success */;
7152
7230
  }
7153
7231
  function checkRangeLimits(check, batchValidations) {
@@ -7179,7 +7257,7 @@ function checkInflectionPointsValue(check, batchValidations) {
7179
7257
  function checkRangeMinBiggerThanRangeMax(definition) {
7180
7258
  if (definition.sectionRule) {
7181
7259
  if (Number(definition.sectionRule.rangeMin) >= Number(definition.sectionRule.rangeMax)) {
7182
- return 41 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */;
7260
+ return 42 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */;
7183
7261
  }
7184
7262
  }
7185
7263
  return 0 /* CommandResult.Success */;
@@ -7188,9 +7266,9 @@ function checkEmpty(value, valueName) {
7188
7266
  if (value === "") {
7189
7267
  switch (valueName) {
7190
7268
  case "rangeMin":
7191
- return 37 /* CommandResult.EmptyGaugeRangeMin */;
7269
+ return 38 /* CommandResult.EmptyGaugeRangeMin */;
7192
7270
  case "rangeMax":
7193
- return 39 /* CommandResult.EmptyGaugeRangeMax */;
7271
+ return 40 /* CommandResult.EmptyGaugeRangeMax */;
7194
7272
  }
7195
7273
  }
7196
7274
  return 0 /* CommandResult.Success */;
@@ -7199,13 +7277,13 @@ function checkNaN(value, valueName) {
7199
7277
  if (isNaN(value)) {
7200
7278
  switch (valueName) {
7201
7279
  case "rangeMin":
7202
- return 38 /* CommandResult.GaugeRangeMinNaN */;
7280
+ return 39 /* CommandResult.GaugeRangeMinNaN */;
7203
7281
  case "rangeMax":
7204
- return 40 /* CommandResult.GaugeRangeMaxNaN */;
7282
+ return 41 /* CommandResult.GaugeRangeMaxNaN */;
7205
7283
  case "lowerInflectionPointValue":
7206
- return 42 /* CommandResult.GaugeLowerInflectionPointNaN */;
7284
+ return 43 /* CommandResult.GaugeLowerInflectionPointNaN */;
7207
7285
  case "upperInflectionPointValue":
7208
- return 43 /* CommandResult.GaugeUpperInflectionPointNaN */;
7286
+ return 44 /* CommandResult.GaugeUpperInflectionPointNaN */;
7209
7287
  }
7210
7288
  }
7211
7289
  return 0 /* CommandResult.Success */;
@@ -7981,12 +8059,12 @@ function createPieChartRuntime(chart, getters) {
7981
8059
 
7982
8060
  function checkKeyValue(definition) {
7983
8061
  return definition.keyValue && !rangeReference.test(definition.keyValue)
7984
- ? 34 /* CommandResult.InvalidScorecardKeyValue */
8062
+ ? 35 /* CommandResult.InvalidScorecardKeyValue */
7985
8063
  : 0 /* CommandResult.Success */;
7986
8064
  }
7987
8065
  function checkBaseline(definition) {
7988
8066
  return definition.baseline && !rangeReference.test(definition.baseline)
7989
- ? 35 /* CommandResult.InvalidScorecardBaseline */
8067
+ ? 36 /* CommandResult.InvalidScorecardBaseline */
7990
8068
  : 0 /* CommandResult.Success */;
7991
8069
  }
7992
8070
  class ScorecardChart extends AbstractChart {
@@ -8486,13 +8564,22 @@ function inverseUnhideColumnsRows(cmd) {
8486
8564
  ];
8487
8565
  }
8488
8566
 
8567
+ function interactiveCut(env) {
8568
+ const result = env.model.dispatch("CUT");
8569
+ if (!result.isSuccessful) {
8570
+ if (result.isCancelledBecause(20 /* CommandResult.WrongCutSelection */)) {
8571
+ env.raiseError(_lt("This operation is not allowed with multiple selections."));
8572
+ }
8573
+ }
8574
+ }
8575
+
8489
8576
  const AddMergeInteractiveContent = {
8490
8577
  MergeIsDestructive: _lt("Merging these cells will only preserve the top-leftmost value. Merge anyway?"),
8491
8578
  MergeInFilter: _lt("You can't merge cells inside of an existing filter."),
8492
8579
  };
8493
8580
  function interactiveAddMerge(env, sheetId, target) {
8494
8581
  const result = env.model.dispatch("ADD_MERGE", { sheetId, target });
8495
- if (result.isCancelledBecause(80 /* CommandResult.MergeInFilter */)) {
8582
+ if (result.isCancelledBecause(81 /* CommandResult.MergeInFilter */)) {
8496
8583
  env.raiseError(AddMergeInteractiveContent.MergeInFilter);
8497
8584
  }
8498
8585
  else if (result.isCancelledBecause(3 /* CommandResult.MergeIsDestructive */)) {
@@ -8502,279 +8589,6 @@ function interactiveAddMerge(env, sheetId, target) {
8502
8589
  }
8503
8590
  }
8504
8591
 
8505
- /**
8506
- * Create a function used to create a Chart based on the definition
8507
- */
8508
- function chartFactory(getters) {
8509
- const builders = chartRegistry.getAll().sort((a, b) => a.sequence - b.sequence);
8510
- function createChart(id, definition, sheetId) {
8511
- const builder = builders.find((builder) => builder.match(definition.type));
8512
- if (!builder) {
8513
- throw new Error(`No builder for this chart: ${definition.type}`);
8514
- }
8515
- return builder.createChart(definition, sheetId, getters);
8516
- }
8517
- return createChart;
8518
- }
8519
- /**
8520
- * Create a function used to create a Chart Runtime based on the chart class
8521
- * instance
8522
- */
8523
- function chartRuntimeFactory(getters) {
8524
- const builders = chartRegistry.getAll().sort((a, b) => a.sequence - b.sequence);
8525
- function createRuntimeChart(chart) {
8526
- const builder = builders.find((builder) => builder.match(chart.type));
8527
- if (!builder) {
8528
- throw new Error("No runtime builder for this chart.");
8529
- }
8530
- return builder.getChartRuntime(chart, getters);
8531
- }
8532
- return createRuntimeChart;
8533
- }
8534
- /**
8535
- * Validate the chart definition given in arguments
8536
- */
8537
- function validateChartDefinition(validator, definition) {
8538
- const validators = chartRegistry.getAll().find((validator) => validator.match(definition.type));
8539
- if (!validators) {
8540
- throw new Error("Unknown chart type.");
8541
- }
8542
- return validators.validateChartDefinition(validator, definition);
8543
- }
8544
- /**
8545
- * Get a new chart definition transformed with the executed command. This
8546
- * functions will be called during operational transform process
8547
- */
8548
- function transformDefinition(definition, executed) {
8549
- const transformation = chartRegistry.getAll().find((factory) => factory.match(definition.type));
8550
- if (!transformation) {
8551
- throw new Error("Unknown chart type.");
8552
- }
8553
- return transformation.transformDefinition(definition, executed);
8554
- }
8555
- /**
8556
- * Get an empty definition based on the given context and the given type
8557
- */
8558
- function getChartDefinitionFromContextCreation(context, type) {
8559
- const chartClass = chartRegistry.get(type);
8560
- return chartClass.getChartDefinitionFromContextCreation(context);
8561
- }
8562
- function getChartTypes() {
8563
- const result = {};
8564
- for (const key of chartRegistry.getKeys()) {
8565
- result[key] = chartRegistry.get(key).name;
8566
- }
8567
- return result;
8568
- }
8569
- /**
8570
- * Return a "smart" chart definition in the given zone. The definition is "smart" because it will
8571
- * use the best type of chart to display the data of the zone.
8572
- *
8573
- * It will also try to find labels and datasets in the range, and try to find title for the datasets.
8574
- *
8575
- * The type of chart will be :
8576
- * - If the zone is a single non-empty cell, returns a scorecard
8577
- * - If the all the labels are numbers/date, returns a line chart
8578
- * - Else returns a bar chart
8579
- */
8580
- function getSmartChartDefinition(zone, getters) {
8581
- let dataSetZone = zone;
8582
- if (zone.left !== zone.right) {
8583
- dataSetZone = { ...zone, left: zone.left + 1 };
8584
- }
8585
- const dataSets = [zoneToXc(dataSetZone)];
8586
- const sheetId = getters.getActiveSheetId();
8587
- const topLeftCell = getters.getCell({ sheetId, col: zone.left, row: zone.top });
8588
- if (getZoneArea(zone) === 1 && topLeftCell?.content) {
8589
- return {
8590
- type: "scorecard",
8591
- title: "",
8592
- background: topLeftCell.style?.fillColor || undefined,
8593
- keyValue: zoneToXc(zone),
8594
- baselineMode: DEFAULT_SCORECARD_BASELINE_MODE,
8595
- baselineColorUp: DEFAULT_SCORECARD_BASELINE_COLOR_UP,
8596
- baselineColorDown: DEFAULT_SCORECARD_BASELINE_COLOR_DOWN,
8597
- };
8598
- }
8599
- let title = "";
8600
- const cellsInFirstRow = getters.getEvaluatedCellsInZone(sheetId, {
8601
- ...dataSetZone,
8602
- bottom: dataSetZone.top,
8603
- });
8604
- const dataSetsHaveTitle = !!cellsInFirstRow.find((cell) => cell.type !== CellValueType.empty && cell.type !== CellValueType.number);
8605
- if (dataSetsHaveTitle) {
8606
- const texts = cellsInFirstRow
8607
- .filter((cell) => cell.type !== CellValueType.error && cell.type !== CellValueType.empty)
8608
- .map((cell) => cell.formattedValue);
8609
- const lastElement = texts.splice(-1)[0];
8610
- title = texts.join(", ");
8611
- if (lastElement) {
8612
- title += (title ? " " + _t("and") + " " : "") + lastElement;
8613
- }
8614
- }
8615
- let labelRangeXc;
8616
- if (zone.left !== zone.right) {
8617
- labelRangeXc = zoneToXc({
8618
- ...zone,
8619
- right: zone.left,
8620
- });
8621
- }
8622
- // Only display legend for several datasets.
8623
- const newLegendPos = dataSetZone.right === dataSetZone.left ? "none" : "top";
8624
- const labelRange = labelRangeXc ? getters.getRangeFromSheetXC(sheetId, labelRangeXc) : undefined;
8625
- if (canChartParseLabels(labelRange, getters)) {
8626
- return {
8627
- title,
8628
- dataSets,
8629
- labelsAsText: false,
8630
- stacked: false,
8631
- aggregated: false,
8632
- labelRange: labelRangeXc,
8633
- type: "line",
8634
- dataSetsHaveTitle,
8635
- verticalAxisPosition: "left",
8636
- legendPosition: newLegendPos,
8637
- };
8638
- }
8639
- return {
8640
- title,
8641
- dataSets,
8642
- labelRange: labelRangeXc,
8643
- type: "bar",
8644
- stacked: false,
8645
- aggregated: false,
8646
- dataSetsHaveTitle,
8647
- verticalAxisPosition: "left",
8648
- legendPosition: newLegendPos,
8649
- };
8650
- }
8651
-
8652
- const SORT_TYPES = [
8653
- CellValueType.number,
8654
- CellValueType.error,
8655
- CellValueType.text,
8656
- CellValueType.boolean,
8657
- ];
8658
- function sortCells(cells, sortDirection, emptyCellAsZero) {
8659
- const cellsWithIndex = cells.map((cell, index) => ({
8660
- index,
8661
- type: cell.type,
8662
- value: cell.value,
8663
- }));
8664
- let emptyCells = cellsWithIndex.filter((x) => x.type === CellValueType.empty);
8665
- let nonEmptyCells = cellsWithIndex.filter((x) => x.type !== CellValueType.empty);
8666
- if (emptyCellAsZero) {
8667
- nonEmptyCells.push(...emptyCells.map((emptyCell) => ({ ...emptyCell, type: CellValueType.number, value: 0 })));
8668
- emptyCells = [];
8669
- }
8670
- const inverse = sortDirection === "descending" ? -1 : 1;
8671
- return nonEmptyCells
8672
- .sort((left, right) => {
8673
- let typeOrder = SORT_TYPES.indexOf(left.type) - SORT_TYPES.indexOf(right.type);
8674
- if (typeOrder === 0) {
8675
- if (left.type === CellValueType.text || left.type === CellValueType.error) {
8676
- typeOrder = left.value.localeCompare(right.value);
8677
- }
8678
- else
8679
- typeOrder = left.value - right.value;
8680
- }
8681
- return inverse * typeOrder;
8682
- })
8683
- .concat(emptyCells);
8684
- }
8685
- function interactiveSortSelection(env, sheetId, anchor, zone, sortDirection) {
8686
- let result = DispatchResult.Success;
8687
- //several columns => bypass the contiguity check
8688
- let multiColumns = zone.right > zone.left;
8689
- if (env.model.getters.doesIntersectMerge(sheetId, zone)) {
8690
- multiColumns = false;
8691
- let table;
8692
- for (let row = zone.top; row <= zone.bottom; row++) {
8693
- table = [];
8694
- for (let col = zone.left; col <= zone.right; col++) {
8695
- let merge = env.model.getters.getMerge({ sheetId, col, row });
8696
- if (merge && !table.includes(merge.id.toString())) {
8697
- table.push(merge.id.toString());
8698
- }
8699
- }
8700
- if (table.length >= 2) {
8701
- multiColumns = true;
8702
- break;
8703
- }
8704
- }
8705
- }
8706
- const { col, row } = anchor;
8707
- if (multiColumns) {
8708
- result = env.model.dispatch("SORT_CELLS", { sheetId, col, row, zone, sortDirection });
8709
- }
8710
- else {
8711
- // check contiguity
8712
- const contiguousZone = env.model.getters.getContiguousZone(sheetId, zone);
8713
- if (isEqual(contiguousZone, zone)) {
8714
- // merge as it is
8715
- result = env.model.dispatch("SORT_CELLS", {
8716
- sheetId,
8717
- col,
8718
- row,
8719
- zone,
8720
- sortDirection,
8721
- });
8722
- }
8723
- else {
8724
- env.askConfirmation(_lt("We found data next to your selection. Since this data was not selected, it will not be sorted. Do you want to extend your selection?"), () => {
8725
- zone = contiguousZone;
8726
- result = env.model.dispatch("SORT_CELLS", {
8727
- sheetId,
8728
- col,
8729
- row,
8730
- zone,
8731
- sortDirection,
8732
- });
8733
- }, () => {
8734
- result = env.model.dispatch("SORT_CELLS", {
8735
- sheetId,
8736
- col,
8737
- row,
8738
- zone,
8739
- sortDirection,
8740
- });
8741
- });
8742
- }
8743
- }
8744
- if (result.isCancelledBecause(63 /* CommandResult.InvalidSortZone */)) {
8745
- const { col, row } = anchor;
8746
- env.model.selection.selectZone({ cell: { col, row }, zone });
8747
- env.raiseError(_lt("Cannot sort. To sort, select only cells or only merges that have the same size."));
8748
- }
8749
- }
8750
-
8751
- function interactiveCut(env) {
8752
- const result = env.model.dispatch("CUT");
8753
- if (!result.isSuccessful) {
8754
- if (result.isCancelledBecause(19 /* CommandResult.WrongCutSelection */)) {
8755
- env.raiseError(_lt("This operation is not allowed with multiple selections."));
8756
- }
8757
- }
8758
- }
8759
-
8760
- const AddFilterInteractiveContent = {
8761
- filterOverlap: _lt("You cannot create overlapping filters."),
8762
- nonContinuousTargets: _lt("A filter can only be created on a continuous selection."),
8763
- mergeInFilter: _lt("You can't create a filter over a range that contains a merge."),
8764
- };
8765
- function interactiveAddFilter(env, sheetId, target) {
8766
- const result = env.model.dispatch("CREATE_FILTER_TABLE", { target, sheetId });
8767
- if (result.isCancelledBecause(78 /* CommandResult.FilterOverlap */)) {
8768
- env.raiseError(AddFilterInteractiveContent.filterOverlap);
8769
- }
8770
- else if (result.isCancelledBecause(80 /* CommandResult.MergeInFilter */)) {
8771
- env.raiseError(AddFilterInteractiveContent.mergeInFilter);
8772
- }
8773
- else if (result.isCancelledBecause(81 /* CommandResult.NonContinuousTargets */)) {
8774
- env.raiseError(AddFilterInteractiveContent.nonContinuousTargets);
8775
- }
8776
- }
8777
-
8778
8592
  const PasteInteractiveContent = {
8779
8593
  wrongPasteSelection: _lt("This operation is not allowed with multiple selections."),
8780
8594
  willRemoveExistingMerge: _lt("This operation is not possible due to a merge. Please remove the merges first than try again."),
@@ -8783,16 +8597,16 @@ const PasteInteractiveContent = {
8783
8597
  };
8784
8598
  function handlePasteResult(env, result) {
8785
8599
  if (!result.isSuccessful) {
8786
- if (result.reasons.includes(20 /* CommandResult.WrongPasteSelection */)) {
8600
+ if (result.reasons.includes(21 /* CommandResult.WrongPasteSelection */)) {
8787
8601
  env.raiseError(PasteInteractiveContent.wrongPasteSelection);
8788
8602
  }
8789
8603
  else if (result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
8790
8604
  env.raiseError(PasteInteractiveContent.willRemoveExistingMerge);
8791
8605
  }
8792
- else if (result.reasons.includes(22 /* CommandResult.WrongFigurePasteOption */)) {
8606
+ else if (result.reasons.includes(23 /* CommandResult.WrongFigurePasteOption */)) {
8793
8607
  env.raiseError(PasteInteractiveContent.wrongFigurePasteOption);
8794
8608
  }
8795
- else if (result.reasons.includes(75 /* CommandResult.FrozenPaneOverlap */)) {
8609
+ else if (result.reasons.includes(76 /* CommandResult.FrozenPaneOverlap */)) {
8796
8610
  env.raiseError(PasteInteractiveContent.frozenPaneOverlap);
8797
8611
  }
8798
8612
  }
@@ -8801,34 +8615,161 @@ function interactivePaste(env, target, pasteOption) {
8801
8615
  const result = env.model.dispatch("PASTE", { target, pasteOption });
8802
8616
  handlePasteResult(env, result);
8803
8617
  }
8804
- function interactivePasteFromOS(env, target, text) {
8805
- const result = env.model.dispatch("PASTE_FROM_OS_CLIPBOARD", { target, text });
8618
+ function interactivePasteFromOS(env, target, text, pasteOption) {
8619
+ const result = env.model.dispatch("PASTE_FROM_OS_CLIPBOARD", { target, text, pasteOption });
8806
8620
  handlePasteResult(env, result);
8807
8621
  }
8808
8622
 
8809
- //------------------------------------------------------------------------------
8810
- // Helpers
8811
- //------------------------------------------------------------------------------
8812
- function getColumnsNumber(env) {
8813
- const activeCols = env.model.getters.getActiveCols();
8814
- if (activeCols.size) {
8815
- return activeCols.size;
8623
+ /**
8624
+ * Create a function used to create a Chart based on the definition
8625
+ */
8626
+ function chartFactory(getters) {
8627
+ const builders = chartRegistry.getAll().sort((a, b) => a.sequence - b.sequence);
8628
+ function createChart(id, definition, sheetId) {
8629
+ const builder = builders.find((builder) => builder.match(definition.type));
8630
+ if (!builder) {
8631
+ throw new Error(`No builder for this chart: ${definition.type}`);
8632
+ }
8633
+ return builder.createChart(definition, sheetId, getters);
8816
8634
  }
8817
- else {
8818
- const zone = env.model.getters.getSelectedZones()[0];
8819
- return zone.right - zone.left + 1;
8635
+ return createChart;
8636
+ }
8637
+ /**
8638
+ * Create a function used to create a Chart Runtime based on the chart class
8639
+ * instance
8640
+ */
8641
+ function chartRuntimeFactory(getters) {
8642
+ const builders = chartRegistry.getAll().sort((a, b) => a.sequence - b.sequence);
8643
+ function createRuntimeChart(chart) {
8644
+ const builder = builders.find((builder) => builder.match(chart.type));
8645
+ if (!builder) {
8646
+ throw new Error("No runtime builder for this chart.");
8647
+ }
8648
+ return builder.getChartRuntime(chart, getters);
8820
8649
  }
8650
+ return createRuntimeChart;
8821
8651
  }
8822
- function getRowsNumber(env) {
8823
- const activeRows = env.model.getters.getActiveRows();
8824
- if (activeRows.size) {
8825
- return activeRows.size;
8652
+ /**
8653
+ * Validate the chart definition given in arguments
8654
+ */
8655
+ function validateChartDefinition(validator, definition) {
8656
+ const validators = chartRegistry.getAll().find((validator) => validator.match(definition.type));
8657
+ if (!validators) {
8658
+ throw new Error("Unknown chart type.");
8826
8659
  }
8827
- else {
8828
- const zone = env.model.getters.getSelectedZones()[0];
8829
- return zone.bottom - zone.top + 1;
8660
+ return validators.validateChartDefinition(validator, definition);
8661
+ }
8662
+ /**
8663
+ * Get a new chart definition transformed with the executed command. This
8664
+ * functions will be called during operational transform process
8665
+ */
8666
+ function transformDefinition(definition, executed) {
8667
+ const transformation = chartRegistry.getAll().find((factory) => factory.match(definition.type));
8668
+ if (!transformation) {
8669
+ throw new Error("Unknown chart type.");
8670
+ }
8671
+ return transformation.transformDefinition(definition, executed);
8672
+ }
8673
+ /**
8674
+ * Get an empty definition based on the given context and the given type
8675
+ */
8676
+ function getChartDefinitionFromContextCreation(context, type) {
8677
+ const chartClass = chartRegistry.get(type);
8678
+ return chartClass.getChartDefinitionFromContextCreation(context);
8679
+ }
8680
+ function getChartTypes() {
8681
+ const result = {};
8682
+ for (const key of chartRegistry.getKeys()) {
8683
+ result[key] = chartRegistry.get(key).name;
8830
8684
  }
8685
+ return result;
8831
8686
  }
8687
+ /**
8688
+ * Return a "smart" chart definition in the given zone. The definition is "smart" because it will
8689
+ * use the best type of chart to display the data of the zone.
8690
+ *
8691
+ * It will also try to find labels and datasets in the range, and try to find title for the datasets.
8692
+ *
8693
+ * The type of chart will be :
8694
+ * - If the zone is a single non-empty cell, returns a scorecard
8695
+ * - If the all the labels are numbers/date, returns a line chart
8696
+ * - Else returns a bar chart
8697
+ */
8698
+ function getSmartChartDefinition(zone, getters) {
8699
+ let dataSetZone = zone;
8700
+ if (zone.left !== zone.right) {
8701
+ dataSetZone = { ...zone, left: zone.left + 1 };
8702
+ }
8703
+ const dataSets = [zoneToXc(dataSetZone)];
8704
+ const sheetId = getters.getActiveSheetId();
8705
+ const topLeftCell = getters.getCell({ sheetId, col: zone.left, row: zone.top });
8706
+ if (getZoneArea(zone) === 1 && topLeftCell?.content) {
8707
+ return {
8708
+ type: "scorecard",
8709
+ title: "",
8710
+ background: topLeftCell.style?.fillColor || undefined,
8711
+ keyValue: zoneToXc(zone),
8712
+ baselineMode: DEFAULT_SCORECARD_BASELINE_MODE,
8713
+ baselineColorUp: DEFAULT_SCORECARD_BASELINE_COLOR_UP,
8714
+ baselineColorDown: DEFAULT_SCORECARD_BASELINE_COLOR_DOWN,
8715
+ };
8716
+ }
8717
+ let title = "";
8718
+ const cellsInFirstRow = getters.getEvaluatedCellsInZone(sheetId, {
8719
+ ...dataSetZone,
8720
+ bottom: dataSetZone.top,
8721
+ });
8722
+ const dataSetsHaveTitle = !!cellsInFirstRow.find((cell) => cell.type !== CellValueType.empty && cell.type !== CellValueType.number);
8723
+ if (dataSetsHaveTitle) {
8724
+ const texts = cellsInFirstRow
8725
+ .filter((cell) => cell.type !== CellValueType.error && cell.type !== CellValueType.empty)
8726
+ .map((cell) => cell.formattedValue);
8727
+ const lastElement = texts.splice(-1)[0];
8728
+ title = texts.join(", ");
8729
+ if (lastElement) {
8730
+ title += (title ? " " + _t("and") + " " : "") + lastElement;
8731
+ }
8732
+ }
8733
+ let labelRangeXc;
8734
+ if (zone.left !== zone.right) {
8735
+ labelRangeXc = zoneToXc({
8736
+ ...zone,
8737
+ right: zone.left,
8738
+ });
8739
+ }
8740
+ // Only display legend for several datasets.
8741
+ const newLegendPos = dataSetZone.right === dataSetZone.left ? "none" : "top";
8742
+ const labelRange = labelRangeXc ? getters.getRangeFromSheetXC(sheetId, labelRangeXc) : undefined;
8743
+ if (canChartParseLabels(labelRange, getters)) {
8744
+ return {
8745
+ title,
8746
+ dataSets,
8747
+ labelsAsText: false,
8748
+ stacked: false,
8749
+ aggregated: false,
8750
+ labelRange: labelRangeXc,
8751
+ type: "line",
8752
+ dataSetsHaveTitle,
8753
+ verticalAxisPosition: "left",
8754
+ legendPosition: newLegendPos,
8755
+ };
8756
+ }
8757
+ return {
8758
+ title,
8759
+ dataSets,
8760
+ labelRange: labelRangeXc,
8761
+ type: "bar",
8762
+ stacked: false,
8763
+ aggregated: false,
8764
+ dataSetsHaveTitle,
8765
+ verticalAxisPosition: "left",
8766
+ legendPosition: newLegendPos,
8767
+ };
8768
+ }
8769
+
8770
+ //------------------------------------------------------------------------------
8771
+ // Helpers
8772
+ //------------------------------------------------------------------------------
8832
8773
  function setFormatter(env, format) {
8833
8774
  env.model.dispatch("SET_FORMATTING", {
8834
8775
  sheetId: env.model.getters.getActiveSheetId(),
@@ -8846,16 +8787,6 @@ function setStyle(env, style) {
8846
8787
  //------------------------------------------------------------------------------
8847
8788
  // Simple actions
8848
8789
  //------------------------------------------------------------------------------
8849
- const UNDO_ACTION = (env) => env.model.dispatch("REQUEST_UNDO");
8850
- const REDO_ACTION = (env) => env.model.dispatch("REQUEST_REDO");
8851
- const COPY_ACTION = async (env) => {
8852
- env.model.dispatch("COPY");
8853
- await env.clipboard.write(env.model.getters.getClipboardContent());
8854
- };
8855
- const CUT_ACTION = async (env) => {
8856
- interactiveCut(env);
8857
- await env.clipboard.write(env.model.getters.getClipboardContent());
8858
- };
8859
8790
  const PASTE_ACTION = async (env) => paste$1(env);
8860
8791
  const PASTE_VALUE_ACTION = async (env) => paste$1(env, "onlyValue");
8861
8792
  async function paste$1(env, pasteOption) {
@@ -8865,11 +8796,14 @@ async function paste$1(env, pasteOption) {
8865
8796
  case "ok":
8866
8797
  const target = env.model.getters.getSelectedZones();
8867
8798
  if (osClipboard && osClipboard.content !== spreadsheetClipboard) {
8868
- interactivePasteFromOS(env, target, osClipboard.content);
8799
+ interactivePasteFromOS(env, target, osClipboard.content, pasteOption);
8869
8800
  }
8870
8801
  else {
8871
8802
  interactivePaste(env, target, pasteOption);
8872
8803
  }
8804
+ if (env.model.getters.isCutOperation() && pasteOption !== "onlyValue") {
8805
+ await env.clipboard.write({ [ClipboardMIMEType.PlainText]: "" });
8806
+ }
8873
8807
  break;
8874
8808
  case "notImplemented":
8875
8809
  env.raiseError(_lt("Pasting from the context menu is not supported in this browser. Use keyboard shortcuts ctrl+c / ctrl+v instead."));
@@ -8879,22 +8813,7 @@ async function paste$1(env, pasteOption) {
8879
8813
  break;
8880
8814
  }
8881
8815
  }
8882
- const PASTE_FORMAT_ACTION = (env) => interactivePaste(env, env.model.getters.getSelectedZones(), "onlyFormat");
8883
- const DELETE_CONTENT_ACTION = (env) => env.model.dispatch("DELETE_CONTENT", {
8884
- sheetId: env.model.getters.getActiveSheetId(),
8885
- target: env.model.getters.getSelectedZones(),
8886
- });
8887
- const SET_FORMULA_VISIBILITY_ACTION = (env) => env.model.dispatch("SET_FORMULA_VISIBILITY", { show: !env.model.getters.shouldShowFormulas() });
8888
- const SET_GRID_LINES_VISIBILITY_ACTION = (env) => {
8889
- const sheetId = env.model.getters.getActiveSheetId();
8890
- env.model.dispatch("SET_GRID_LINES_VISIBILITY", {
8891
- sheetId,
8892
- areGridLinesVisible: !env.model.getters.getGridLinesVisibility(sheetId),
8893
- });
8894
- };
8895
- const IS_NOT_CUT_OPERATION = (env) => {
8896
- return !env.model.getters.isCutOperation();
8897
- };
8816
+ const PASTE_FORMAT_ACTION = (env) => paste$1(env, "onlyFormat");
8898
8817
  //------------------------------------------------------------------------------
8899
8818
  // Grid manipulations
8900
8819
  //------------------------------------------------------------------------------
@@ -9036,48 +8955,6 @@ const NOT_ALL_VISIBLE_COLS_SELECTED = (env) => {
9036
8955
  const selectedCols = env.model.getters.getElementsFromSelection("COL");
9037
8956
  return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
9038
8957
  };
9039
- const INSERT_CELL_SHIFT_DOWN = (env) => {
9040
- const zone = env.model.getters.getSelectedZone();
9041
- const result = env.model.dispatch("INSERT_CELL", { zone, shiftDimension: "ROW" });
9042
- handlePasteResult(env, result);
9043
- };
9044
- const INSERT_CELL_SHIFT_RIGHT = (env) => {
9045
- const zone = env.model.getters.getSelectedZone();
9046
- const result = env.model.dispatch("INSERT_CELL", { zone, shiftDimension: "COL" });
9047
- handlePasteResult(env, result);
9048
- };
9049
- const DELETE_CELL_SHIFT_UP = (env) => {
9050
- const zone = env.model.getters.getSelectedZone();
9051
- const result = env.model.dispatch("DELETE_CELL", { zone, shiftDimension: "ROW" });
9052
- handlePasteResult(env, result);
9053
- };
9054
- const DELETE_CELL_SHIFT_LEFT = (env) => {
9055
- const zone = env.model.getters.getSelectedZone();
9056
- const result = env.model.dispatch("DELETE_CELL", { zone, shiftDimension: "COL" });
9057
- handlePasteResult(env, result);
9058
- };
9059
- const MENU_INSERT_ROWS_NAME = (env) => {
9060
- const number = getRowsNumber(env);
9061
- return number === 1 ? _lt("Insert row") : _lt("Insert %s rows", number.toString());
9062
- };
9063
- const MENU_INSERT_ROWS_BEFORE_NAME = (env) => {
9064
- const number = getRowsNumber(env);
9065
- if (number === 1) {
9066
- return _lt("Row above");
9067
- }
9068
- return _lt("%s Rows above", number.toString());
9069
- };
9070
- const ROW_INSERT_ROWS_BEFORE_NAME = (env) => {
9071
- const number = getRowsNumber(env);
9072
- return number === 1 ? _lt("Insert row above") : _lt("Insert %s rows above", number.toString());
9073
- };
9074
- const CELL_INSERT_ROWS_BEFORE_NAME = (env) => {
9075
- const number = getRowsNumber(env);
9076
- if (number === 1) {
9077
- return _lt("Insert row");
9078
- }
9079
- return _lt("Insert %s rows", number.toString());
9080
- };
9081
8958
  const INSERT_ROWS_BEFORE_ACTION = (env) => {
9082
8959
  const activeRows = env.model.getters.getActiveRows();
9083
8960
  let row;
@@ -9099,17 +8976,6 @@ const INSERT_ROWS_BEFORE_ACTION = (env) => {
9099
8976
  dimension: "ROW",
9100
8977
  });
9101
8978
  };
9102
- const MENU_INSERT_ROWS_AFTER_NAME = (env) => {
9103
- const number = getRowsNumber(env);
9104
- if (number === 1) {
9105
- return _lt("Row below");
9106
- }
9107
- return _lt("%s Rows below", number.toString());
9108
- };
9109
- const ROW_INSERT_ROWS_AFTER_NAME = (env) => {
9110
- const number = getRowsNumber(env);
9111
- return number === 1 ? _lt("Insert row below") : _lt("Insert %s rows below", number.toString());
9112
- };
9113
8979
  const INSERT_ROWS_AFTER_ACTION = (env) => {
9114
8980
  const activeRows = env.model.getters.getActiveRows();
9115
8981
  let row;
@@ -9131,30 +8997,6 @@ const INSERT_ROWS_AFTER_ACTION = (env) => {
9131
8997
  dimension: "ROW",
9132
8998
  });
9133
8999
  };
9134
- const MENU_INSERT_COLUMNS_BEFORE_NAME = (env) => {
9135
- const number = getColumnsNumber(env);
9136
- if (number === 1) {
9137
- return _lt("Column left");
9138
- }
9139
- return _lt("%s Columns left", number.toString());
9140
- };
9141
- const MENU_INSERT_COLUMNS_NAME = (env) => {
9142
- const number = getColumnsNumber(env);
9143
- return number === 1 ? _lt("Insert column") : _lt("Insert %s columns", number.toString());
9144
- };
9145
- const COLUMN_INSERT_COLUMNS_BEFORE_NAME = (env) => {
9146
- const number = getColumnsNumber(env);
9147
- return number === 1
9148
- ? _lt("Insert column left")
9149
- : _lt("Insert %s columns left", number.toString());
9150
- };
9151
- const CELL_INSERT_COLUMNS_BEFORE_NAME = (env) => {
9152
- const number = getColumnsNumber(env);
9153
- if (number === 1) {
9154
- return _lt("Insert column");
9155
- }
9156
- return _lt("Insert %s columns", number.toString());
9157
- };
9158
9000
  const INSERT_COLUMNS_BEFORE_ACTION = (env) => {
9159
9001
  const activeCols = env.model.getters.getActiveCols();
9160
9002
  let column;
@@ -9176,19 +9018,6 @@ const INSERT_COLUMNS_BEFORE_ACTION = (env) => {
9176
9018
  quantity,
9177
9019
  });
9178
9020
  };
9179
- const MENU_INSERT_COLUMNS_AFTER_NAME = (env) => {
9180
- const number = getColumnsNumber(env);
9181
- if (number === 1) {
9182
- return _lt("Column right");
9183
- }
9184
- return _lt("%s Columns right", number.toString());
9185
- };
9186
- const COLUMN_INSERT_COLUMNS_AFTER_NAME = (env) => {
9187
- const number = getColumnsNumber(env);
9188
- return number === 1
9189
- ? _lt("Insert column right")
9190
- : _lt("Insert %s columns right", number.toString());
9191
- };
9192
9021
  const INSERT_COLUMNS_AFTER_ACTION = (env) => {
9193
9022
  const activeCols = env.model.getters.getActiveCols();
9194
9023
  let column;
@@ -9224,30 +9053,6 @@ const HIDE_COLUMNS_NAME = (env) => {
9224
9053
  return _lt("Hide columns");
9225
9054
  }
9226
9055
  };
9227
- const HIDE_COLUMNS_ACTION = (env) => {
9228
- const columns = env.model.getters.getElementsFromSelection("COL");
9229
- env.model.dispatch("HIDE_COLUMNS_ROWS", {
9230
- sheetId: env.model.getters.getActiveSheetId(),
9231
- dimension: "COL",
9232
- elements: columns,
9233
- });
9234
- };
9235
- const UNHIDE_ALL_COLUMNS_ACTION = (env) => {
9236
- const sheetId = env.model.getters.getActiveSheetId();
9237
- env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
9238
- sheetId,
9239
- dimension: "COL",
9240
- elements: Array.from(Array(env.model.getters.getNumberCols(sheetId)).keys()),
9241
- });
9242
- };
9243
- const UNHIDE_COLUMNS_ACTION = (env) => {
9244
- const columns = env.model.getters.getElementsFromSelection("COL");
9245
- env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
9246
- sheetId: env.model.getters.getActiveSheetId(),
9247
- dimension: "COL",
9248
- elements: columns,
9249
- });
9250
- };
9251
9056
  const HIDE_ROWS_NAME = (env) => {
9252
9057
  const rows = env.model.getters.getElementsFromSelection("ROW");
9253
9058
  let first = rows[0];
@@ -9262,40 +9067,6 @@ const HIDE_ROWS_NAME = (env) => {
9262
9067
  return _lt("Hide rows");
9263
9068
  }
9264
9069
  };
9265
- const HIDE_ROWS_ACTION = (env) => {
9266
- const rows = env.model.getters.getElementsFromSelection("ROW");
9267
- env.model.dispatch("HIDE_COLUMNS_ROWS", {
9268
- sheetId: env.model.getters.getActiveSheetId(),
9269
- dimension: "ROW",
9270
- elements: rows,
9271
- });
9272
- };
9273
- const UNHIDE_ALL_ROWS_ACTION = (env) => {
9274
- const sheetId = env.model.getters.getActiveSheetId();
9275
- env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
9276
- sheetId,
9277
- dimension: "ROW",
9278
- elements: Array.from(Array(env.model.getters.getNumberRows(sheetId)).keys()),
9279
- });
9280
- };
9281
- const UNHIDE_ROWS_ACTION = (env) => {
9282
- const columns = env.model.getters.getElementsFromSelection("ROW");
9283
- env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
9284
- sheetId: env.model.getters.getActiveSheetId(),
9285
- dimension: "ROW",
9286
- elements: columns,
9287
- });
9288
- };
9289
- //------------------------------------------------------------------------------
9290
- // Sheets
9291
- //------------------------------------------------------------------------------
9292
- const CREATE_SHEET_ACTION = (env) => {
9293
- const activeSheetId = env.model.getters.getActiveSheetId();
9294
- const position = env.model.getters.getSheetIds().indexOf(activeSheetId) + 1;
9295
- const sheetId = env.model.uuidGenerator.uuidv4();
9296
- env.model.dispatch("CREATE_SHEET", { sheetId, position });
9297
- env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
9298
- };
9299
9070
  //------------------------------------------------------------------------------
9300
9071
  // Charts
9301
9072
  //------------------------------------------------------------------------------
@@ -9354,37 +9125,13 @@ const CREATE_IMAGE = async (env) => {
9354
9125
  //------------------------------------------------------------------------------
9355
9126
  // Style/Format
9356
9127
  //------------------------------------------------------------------------------
9357
- const FORMAT_AUTOMATIC_ACTION = (env) => setFormatter(env, "");
9358
- const FORMAT_NUMBER_ACTION = (env) => setFormatter(env, "#,##0.00");
9359
9128
  const FORMAT_PERCENT_ACTION = (env) => setFormatter(env, "0.00%");
9360
- const FORMAT_CURRENCY_ACTION = (env) => setFormatter(env, "[$$]#,##0.00");
9361
- const FORMAT_CURRENCY_ROUNDED_ACTION = (env) => setFormatter(env, "[$$]#,##0");
9362
- const FORMAT_DATE_ACTION = (env) => setFormatter(env, "m/d/yyyy");
9363
- const FORMAT_TIME_ACTION = (env) => setFormatter(env, "hh:mm:ss a");
9364
- const FORMAT_DATE_TIME_ACTION = (env) => setFormatter(env, "m/d/yyyy hh:mm:ss");
9365
- const FORMAT_DURATION_ACTION = (env) => setFormatter(env, "hhhh:mm:ss");
9366
- const FORMAT_BOLD_ACTION = (env) => setStyle(env, { bold: !env.model.getters.getCurrentStyle().bold });
9367
- const FORMAT_ITALIC_ACTION = (env) => setStyle(env, { italic: !env.model.getters.getCurrentStyle().italic });
9368
- const FORMAT_STRIKETHROUGH_ACTION = (env) => setStyle(env, { strikethrough: !env.model.getters.getCurrentStyle().strikethrough });
9369
- const FORMAT_UNDERLINE_ACTION = (env) => setStyle(env, { underline: !env.model.getters.getCurrentStyle().underline });
9370
- const FORMAT_CLEARFORMAT_ACTION = (env) => {
9371
- env.model.dispatch("CLEAR_FORMATTING", {
9372
- sheetId: env.model.getters.getActiveSheetId(),
9373
- target: env.model.getters.getSelectedZones(),
9374
- });
9375
- };
9376
9129
  //------------------------------------------------------------------------------
9377
9130
  // Side panel
9378
9131
  //------------------------------------------------------------------------------
9379
9132
  const OPEN_CF_SIDEPANEL_ACTION = (env) => {
9380
9133
  env.openSidePanel("ConditionalFormatting", { selection: env.model.getters.getSelectedZones() });
9381
9134
  };
9382
- const OPEN_FAR_SIDEPANEL_ACTION = (env) => {
9383
- env.openSidePanel("FindAndReplace", {});
9384
- };
9385
- const OPEN_CUSTOM_CURRENCY_SIDEPANEL_ACTION = (env) => {
9386
- env.openSidePanel("CustomCurrency", {});
9387
- };
9388
9135
  const INSERT_LINK = (env) => {
9389
9136
  let { col, row } = env.model.getters.getActivePosition();
9390
9137
  env.model.dispatch("OPEN_CELL_POPOVER", { col, row, popoverType: "LinkEditor" });
@@ -9392,40 +9139,14 @@ const INSERT_LINK = (env) => {
9392
9139
  //------------------------------------------------------------------------------
9393
9140
  // Filters action
9394
9141
  //------------------------------------------------------------------------------
9395
- const FILTERS_CREATE_FILTER_TABLE = (env) => {
9396
- const sheetId = env.model.getters.getActiveSheetId();
9397
- const selection = env.model.getters.getSelection().zones;
9398
- interactiveAddFilter(env, sheetId, selection);
9399
- };
9400
- const FILTERS_REMOVE_FILTER_TABLE = (env) => {
9401
- const sheetId = env.model.getters.getActiveSheetId();
9402
- env.model.dispatch("REMOVE_FILTER_TABLE", {
9403
- sheetId,
9404
- target: env.model.getters.getSelectedZones(),
9405
- });
9406
- };
9407
9142
  const SELECTION_CONTAINS_FILTER = (env) => {
9408
9143
  const sheetId = env.model.getters.getActiveSheetId();
9409
9144
  const selectedZones = env.model.getters.getSelectedZones();
9410
9145
  return env.model.getters.doesZonesContainFilter(sheetId, selectedZones);
9411
9146
  };
9412
- const SELECTION_IS_CONTINUOUS = (env) => {
9413
- const selectedZones = env.model.getters.getSelectedZones();
9414
- return areZonesContinuous(...selectedZones);
9415
- };
9416
9147
  //------------------------------------------------------------------------------
9417
9148
  // Sorting action
9418
9149
  //------------------------------------------------------------------------------
9419
- const SORT_CELLS_ASCENDING = (env) => {
9420
- const { anchor, zones } = env.model.getters.getSelection();
9421
- const sheetId = env.model.getters.getActiveSheetId();
9422
- interactiveSortSelection(env, sheetId, anchor.cell, zones[0], "ascending");
9423
- };
9424
- const SORT_CELLS_DESCENDING = (env) => {
9425
- const { anchor, zones } = env.model.getters.getSelection();
9426
- const sheetId = env.model.getters.getActiveSheetId();
9427
- interactiveSortSelection(env, sheetId, anchor.cell, zones[0], "descending");
9428
- };
9429
9150
  const IS_ONLY_ONE_RANGE = (env) => {
9430
9151
  return env.model.getters.getSelectedZones().length === 1;
9431
9152
  };
@@ -9433,14 +9154,14 @@ const IS_ONLY_ONE_RANGE = (env) => {
9433
9154
  const undo = {
9434
9155
  name: _lt("Undo"),
9435
9156
  description: "Ctrl+Z",
9436
- execute: UNDO_ACTION,
9157
+ execute: (env) => env.model.dispatch("REQUEST_UNDO"),
9437
9158
  isEnabled: (env) => env.model.getters.canUndo(),
9438
9159
  icon: "o-spreadsheet-Icon.UNDO",
9439
9160
  };
9440
9161
  const redo = {
9441
9162
  name: _lt("Redo"),
9442
9163
  description: "Ctrl+Y",
9443
- execute: REDO_ACTION,
9164
+ execute: (env) => env.model.dispatch("REQUEST_REDO"),
9444
9165
  isEnabled: (env) => env.model.getters.canRedo(),
9445
9166
  icon: "o-spreadsheet-Icon.REDO",
9446
9167
  };
@@ -9448,13 +9169,19 @@ const copy = {
9448
9169
  name: _lt("Copy"),
9449
9170
  description: "Ctrl+C",
9450
9171
  isReadonlyAllowed: true,
9451
- execute: COPY_ACTION,
9172
+ execute: async (env) => {
9173
+ env.model.dispatch("COPY");
9174
+ await env.clipboard.write(env.model.getters.getClipboardContent());
9175
+ },
9452
9176
  icon: "o-spreadsheet-Icon.COPY",
9453
9177
  };
9454
9178
  const cut = {
9455
9179
  name: _lt("Cut"),
9456
9180
  description: "Ctrl+X",
9457
- execute: CUT_ACTION,
9181
+ execute: async (env) => {
9182
+ interactiveCut(env);
9183
+ await env.clipboard.write(env.model.getters.getClipboardContent());
9184
+ },
9458
9185
  icon: "o-spreadsheet-Icon.CUT",
9459
9186
  };
9460
9187
  const paste = {
@@ -9465,7 +9192,9 @@ const paste = {
9465
9192
  };
9466
9193
  const pasteSpecial = {
9467
9194
  name: _lt("Paste special"),
9468
- isVisible: IS_NOT_CUT_OPERATION,
9195
+ isVisible: (env) => {
9196
+ return !env.model.getters.isCutOperation();
9197
+ },
9469
9198
  icon: "o-spreadsheet-Icon.PASTE",
9470
9199
  };
9471
9200
  const pasteSpecialValue = {
@@ -9481,12 +9210,17 @@ const findAndReplace = {
9481
9210
  name: _lt("Find and replace"),
9482
9211
  description: "Ctrl+H",
9483
9212
  isReadonlyAllowed: true,
9484
- execute: OPEN_FAR_SIDEPANEL_ACTION,
9213
+ execute: (env) => {
9214
+ env.openSidePanel("FindAndReplace", {});
9215
+ },
9485
9216
  icon: "o-spreadsheet-Icon.FIND_AND_REPLACE",
9486
9217
  };
9487
9218
  const deleteValues = {
9488
9219
  name: _lt("Delete values"),
9489
- execute: DELETE_CONTENT_ACTION,
9220
+ execute: (env) => env.model.dispatch("DELETE_CONTENT", {
9221
+ sheetId: env.model.getters.getActiveSheetId(),
9222
+ target: env.model.getters.getSelectedZones(),
9223
+ }),
9490
9224
  };
9491
9225
  const deleteRows = {
9492
9226
  name: REMOVE_ROWS_NAME,
@@ -9520,11 +9254,19 @@ const deleteCells = {
9520
9254
  };
9521
9255
  const deleteCellShiftUp = {
9522
9256
  name: _lt("Delete cell and shift up"),
9523
- execute: DELETE_CELL_SHIFT_UP,
9257
+ execute: (env) => {
9258
+ const zone = env.model.getters.getSelectedZone();
9259
+ const result = env.model.dispatch("DELETE_CELL", { zone, shiftDimension: "ROW" });
9260
+ handlePasteResult(env, result);
9261
+ },
9524
9262
  };
9525
9263
  const deleteCellShiftLeft = {
9526
9264
  name: _lt("Delete cell and shift left"),
9527
- execute: DELETE_CELL_SHIFT_LEFT,
9265
+ execute: (env) => {
9266
+ const zone = env.model.getters.getSelectedZone();
9267
+ const result = env.model.dispatch("DELETE_CELL", { zone, shiftDimension: "COL" });
9268
+ handlePasteResult(env, result);
9269
+ },
9528
9270
  };
9529
9271
  const mergeCells = {
9530
9272
  name: _lt("Merge cells"),
@@ -9609,9 +9351,9 @@ const ARG_TYPES = [
9609
9351
  "META",
9610
9352
  ];
9611
9353
  function arg(definition, description = "") {
9612
- return makeArg(`${definition} ${description}`);
9354
+ return makeArg(definition, description);
9613
9355
  }
9614
- function makeArg(str) {
9356
+ function makeArg(str, description) {
9615
9357
  let parts = str.match(ARG_REGEXP);
9616
9358
  let name = parts[1].trim();
9617
9359
  let types = [];
@@ -9641,7 +9383,6 @@ function makeArg(str) {
9641
9383
  defaultValue = param.trim().slice(8);
9642
9384
  }
9643
9385
  }
9644
- let description = parts[3].trim();
9645
9386
  const result = {
9646
9387
  name,
9647
9388
  description,
@@ -9755,6 +9496,740 @@ function validateArguments(args) {
9755
9496
  }
9756
9497
  }
9757
9498
 
9499
+ function assertSingleColOrRow(errorStr, arg) {
9500
+ assert(() => arg.length === 1 || arg[0].length === 1, errorStr);
9501
+ }
9502
+ function assertSameDimensions(errorStr, ...args) {
9503
+ if (args.every(isMatrix)) {
9504
+ const cols = args[0].length;
9505
+ const rows = args[0][0].length;
9506
+ for (const arg of args) {
9507
+ assert(() => arg.length === cols && arg[0].length === rows, errorStr);
9508
+ }
9509
+ return;
9510
+ }
9511
+ if (args.some((arg) => Array.isArray(arg) && (arg.length !== 1 || arg[0].length !== 1))) {
9512
+ throw new Error(errorStr);
9513
+ }
9514
+ }
9515
+ function assertPositive(errorStr, arg) {
9516
+ assert(() => arg > 0, errorStr);
9517
+ }
9518
+ function assertSquareMatrix(errorStr, arg) {
9519
+ assert(() => arg.length === arg[0].length, errorStr);
9520
+ }
9521
+ function isNumberMatrix(arg) {
9522
+ return arg.every((row) => row.every((val) => typeof val === "number"));
9523
+ }
9524
+
9525
+ function getUnitMatrix(n) {
9526
+ const matrix = Array(n);
9527
+ for (let i = 0; i < n; i++) {
9528
+ matrix[i] = Array(n).fill(0);
9529
+ matrix[i][i] = 1;
9530
+ }
9531
+ return matrix;
9532
+ }
9533
+ /**
9534
+ * Invert a matrix and compute its determinant using Gaussian Elimination.
9535
+ *
9536
+ * The Matrix should be a square matrix, and should be indexed [col][row] instead of the
9537
+ * standard mathematical indexing [row][col].
9538
+ */
9539
+ function invertMatrix(M) {
9540
+ // Use Gaussian Elimination to calculate the inverse:
9541
+ // (1) 'augment' the matrix (left) by the identity (on the right)
9542
+ // (2) Turn the matrix on the left into the identity using elementary row operations
9543
+ // (3) The matrix on the right becomes the inverse (was the identity matrix)
9544
+ //
9545
+ // There are 3 elementary row operations:
9546
+ // (a) Swap 2 rows. This multiply the determinant by -1.
9547
+ // (b) Multiply a row by a scalar. This multiply the determinant by that scalar.
9548
+ // (c) Add to a row a multiple of another row. This does not change the determinant.
9549
+ if (M.length !== M[0].length) {
9550
+ throw new Error(`Function [[FUNCTION_NAME]] invert matrix error, only square matrices are invertible`);
9551
+ }
9552
+ let determinant = 1;
9553
+ const dim = M.length;
9554
+ const I = getUnitMatrix(dim);
9555
+ const C = M.map((row) => row.slice());
9556
+ // Perform elementary row operations
9557
+ for (let pivot = 0; pivot < dim; pivot++) {
9558
+ let diagonalElement = C[pivot][pivot];
9559
+ // if we have a 0 on the diagonal we'll need to swap with a lower row
9560
+ if (diagonalElement == 0) {
9561
+ //look through every row below the i'th row
9562
+ for (let row = pivot + 1; row < dim; row++) {
9563
+ //if the ii'th row has a non-0 in the i'th col, swap it with that row
9564
+ if (C[pivot][row] != 0) {
9565
+ swapMatrixRows(C, pivot, row);
9566
+ swapMatrixRows(I, pivot, row);
9567
+ determinant *= -1;
9568
+ break;
9569
+ }
9570
+ }
9571
+ diagonalElement = C[pivot][pivot];
9572
+ //if it's still 0, matrix isn't invertible
9573
+ if (diagonalElement === 0) {
9574
+ return { determinant: 0 };
9575
+ }
9576
+ }
9577
+ // Scale this row down by e (so we have a 1 on the diagonal)
9578
+ for (let col = 0; col < dim; col++) {
9579
+ C[col][pivot] = C[col][pivot] / diagonalElement;
9580
+ I[col][pivot] = I[col][pivot] / diagonalElement;
9581
+ }
9582
+ determinant *= diagonalElement;
9583
+ // Subtract a multiple of the current row from ALL of
9584
+ // the other rows so that there will be 0's in this column in the
9585
+ // rows above and below this one
9586
+ for (let row = 0; row < dim; row++) {
9587
+ if (row == pivot) {
9588
+ continue;
9589
+ }
9590
+ // We want to change this element to 0
9591
+ const e = C[pivot][row];
9592
+ // Subtract (the row above(or below) scaled by e) from (the
9593
+ // current row) but start at the i'th column and assume all the
9594
+ // stuff left of diagonal is 0 (which it should be if we made this
9595
+ // algorithm correctly)
9596
+ for (let col = 0; col < dim; col++) {
9597
+ C[col][row] -= e * C[col][pivot];
9598
+ I[col][row] -= e * I[col][pivot];
9599
+ }
9600
+ }
9601
+ }
9602
+ // We've done all operations, C should be the identity matrix I should be the inverse
9603
+ return { inverted: I, determinant };
9604
+ }
9605
+ function swapMatrixRows(matrix, row1, row2) {
9606
+ for (let i = 0; i < matrix.length; i++) {
9607
+ const tmp = matrix[i][row1];
9608
+ matrix[i][row1] = matrix[i][row2];
9609
+ matrix[i][row2] = tmp;
9610
+ }
9611
+ }
9612
+ /**
9613
+ * Matrix multiplication of 2 matrices.
9614
+ * ex: matrix1 : n x l, matrix2 : m x n => result : m x l
9615
+ *
9616
+ * Note: we use indexing [col][row] instead of the standard mathematical notation [row][col]
9617
+ */
9618
+ function multiplyMatrices(matrix1, matrix2) {
9619
+ if (matrix1.length !== matrix2[0].length) {
9620
+ throw new Error(_lt("Cannot multiply matrices : incompatible matrices size."));
9621
+ }
9622
+ const rowsM1 = matrix1[0].length;
9623
+ const colsM2 = matrix2.length;
9624
+ const n = matrix1.length;
9625
+ const result = Array(colsM2);
9626
+ for (let col = 0; col < colsM2; col++) {
9627
+ result[col] = Array(rowsM1);
9628
+ for (let row = 0; row < rowsM1; row++) {
9629
+ let sum = 0;
9630
+ for (let k = 0; k < n; k++) {
9631
+ sum += matrix1[k][row] * matrix2[col][k];
9632
+ }
9633
+ result[col][row] = sum;
9634
+ }
9635
+ }
9636
+ return result;
9637
+ }
9638
+
9639
+ // -----------------------------------------------------------------------------
9640
+ // ARRAY_CONSTRAIN
9641
+ // -----------------------------------------------------------------------------
9642
+ const ARRAY_CONSTRAIN = {
9643
+ description: _lt("Returns a result array constrained to a specific width and height."),
9644
+ args: [
9645
+ arg("input_range (any, range<any>)", _lt("The range to constrain.")),
9646
+ arg("rows (number)", _lt("The number of rows in the constrained array.")),
9647
+ arg("columns (number)", _lt("The number of columns in the constrained array.")),
9648
+ ],
9649
+ returns: ["RANGE<ANY>"],
9650
+ //TODO computeFormat
9651
+ compute: function (array, rows, columns) {
9652
+ const _array = toMatrixArgValue(array);
9653
+ const _rowsArg = toInteger(rows);
9654
+ const _columnsArg = toInteger(columns);
9655
+ assertPositive(_lt("The rows argument (%s) must be strictly positive.", _rowsArg.toString()), _rowsArg);
9656
+ assertPositive(_lt("The columns argument (%s) must be strictly positive.", _rowsArg.toString()), _columnsArg);
9657
+ const _rows = Math.min(_rowsArg, _array[0].length);
9658
+ const _columns = Math.min(_columnsArg, _array.length);
9659
+ const result = Array(_columns);
9660
+ for (let col = 0; col < _columns; col++) {
9661
+ result[col] = Array(_rows);
9662
+ for (let row = 0; row < _rows; row++) {
9663
+ result[col][row] = toCellValue(_array[col][row]);
9664
+ }
9665
+ }
9666
+ return result;
9667
+ },
9668
+ isExported: false,
9669
+ };
9670
+ // -----------------------------------------------------------------------------
9671
+ // CHOOSECOLS
9672
+ // -----------------------------------------------------------------------------
9673
+ const CHOOSECOLS = {
9674
+ description: _lt("Creates a new array from the selected columns in the existing range."),
9675
+ args: [
9676
+ arg("array (any, range<any>)", _lt("The array that contains the columns to be returned.")),
9677
+ arg("col_num (number, range<number>)", _lt("The first column index of the columns to be returned.")),
9678
+ arg("col_num2 (number, range<number>, repeating)", _lt("The columns indexes of the columns to be returned.")),
9679
+ ],
9680
+ returns: ["RANGE<ANY>"],
9681
+ //TODO computeFormat
9682
+ compute: function (array, ...columns) {
9683
+ const _array = toMatrixArgValue(array);
9684
+ const _columns = flattenRowFirst(columns, toInteger);
9685
+ assert(() => _columns.every((col) => col > 0 && col <= _array.length), _lt("The columns arguments must be between 1 and %s (got %s).", _array.length.toString(), (_columns.find((col) => col <= 0 || col > _array.length) || 0).toString()));
9686
+ const result = Array(_columns.length);
9687
+ for (let i = 0; i < _columns.length; i++) {
9688
+ const colIndex = _columns[i] - 1; // -1 because columns arguments are 1-indexed
9689
+ result[i] = _array[colIndex];
9690
+ }
9691
+ return toCellValueMatrix(result);
9692
+ },
9693
+ isExported: true,
9694
+ };
9695
+ // -----------------------------------------------------------------------------
9696
+ // CHOOSEROWS
9697
+ // -----------------------------------------------------------------------------
9698
+ const CHOOSEROWS = {
9699
+ description: _lt("Creates a new array from the selected rows in the existing range."),
9700
+ args: [
9701
+ arg("array (any, range<any>)", _lt("The array that contains the rows to be returned.")),
9702
+ arg("row_num (number, range<number>)", _lt("The first row index of the rows to be returned.")),
9703
+ arg("row_num2 (number, range<number>, repeating)", _lt("The rows indexes of the rows to be returned.")),
9704
+ ],
9705
+ returns: ["RANGE<ANY>"],
9706
+ //TODO computeFormat
9707
+ compute: function (array, ...rows) {
9708
+ const _array = toMatrixArgValue(array);
9709
+ const _rows = flattenRowFirst(rows, toInteger);
9710
+ assert(() => _rows.every((row) => row > 0 && row <= _array[0].length), _lt("The rows arguments must be between 1 and %s (got %s).", _array[0].length.toString(), (_rows.find((row) => row <= 0 || row > _array[0].length) || 0).toString()));
9711
+ const result = Array(_array.length);
9712
+ for (let col = 0; col < _array.length; col++) {
9713
+ result[col] = Array(_rows.length);
9714
+ for (let row = 0; row < _rows.length; row++) {
9715
+ const rowIndex = _rows[row] - 1; // -1 because rows arguments are 1-indexed
9716
+ result[col][row] = toCellValue(_array[col][rowIndex]);
9717
+ }
9718
+ }
9719
+ return result;
9720
+ },
9721
+ isExported: true,
9722
+ };
9723
+ // -----------------------------------------------------------------------------
9724
+ // EXPAND
9725
+ // -----------------------------------------------------------------------------
9726
+ const EXPAND = {
9727
+ description: _lt("Expands or pads an array to specified row and column dimensions."),
9728
+ args: [
9729
+ arg("array (any, range<any>)", _lt("The array to expand.")),
9730
+ arg("rows (number)", _lt("The number of rows in the expanded array. If missing, rows will not be expanded.")),
9731
+ arg("columns (number, optional)", _lt("The number of columns in the expanded array. If missing, columns will not be expanded.")),
9732
+ arg("pad_with (any, default=0)", _lt("The value with which to pad.")), // @compatibility: on Excel, pad with #N/A
9733
+ ],
9734
+ returns: ["RANGE<ANY>"],
9735
+ //TODO computeFormat
9736
+ compute: function (array, rows, columns, padWith = 0) {
9737
+ const _array = toMatrixArgValue(array);
9738
+ const _rows = toInteger(rows);
9739
+ const _columns = columns !== undefined ? toInteger(columns) : _array.length;
9740
+ const _padWith = padWith !== undefined && padWith !== null ? padWith : 0; // TODO : Replace with #N/A errors once it's supported
9741
+ assert(() => _rows >= _array[0].length, _lt("The rows arguments (%s) must be greater or equal than the number of rows of the array.", _rows.toString()));
9742
+ assert(() => _columns >= _array.length, _lt("The columns arguments (%s) must be greater or equal than the number of columns of the array.", _columns.toString()));
9743
+ const result = [];
9744
+ for (let col = 0; col < _columns; col++) {
9745
+ result[col] = [];
9746
+ for (let row = 0; row < _rows; row++) {
9747
+ if (col >= _array.length || row >= _array[col].length) {
9748
+ result[col][row] = _padWith;
9749
+ }
9750
+ else {
9751
+ result[col][row] = _array[col][row] ?? 0;
9752
+ }
9753
+ }
9754
+ }
9755
+ return result;
9756
+ },
9757
+ isExported: true,
9758
+ };
9759
+ // -----------------------------------------------------------------------------
9760
+ // FLATTEN
9761
+ // -----------------------------------------------------------------------------
9762
+ const FLATTEN = {
9763
+ description: _lt("Flattens all the values from one or more ranges into a single column."),
9764
+ args: [
9765
+ arg("range (any, range<any>)", _lt("The first range to flatten.")),
9766
+ arg("range2 (any, range<any>, repeating)", _lt("Additional ranges to flatten.")),
9767
+ ],
9768
+ returns: ["RANGE<ANY>"],
9769
+ compute: function (...ranges) {
9770
+ return [flattenRowFirst(ranges, toCellValue)];
9771
+ },
9772
+ isExported: false,
9773
+ };
9774
+ // -----------------------------------------------------------------------------
9775
+ // FREQUENCY
9776
+ // -----------------------------------------------------------------------------
9777
+ const FREQUENCY = {
9778
+ description: _lt("Calculates the frequency distribution of a range."),
9779
+ args: [
9780
+ arg("data (range<number>)", _lt("The array of ranges containing the values to be counted.")),
9781
+ arg("classes (number, range<number>)", _lt("The range containing the set of classes.")),
9782
+ ],
9783
+ returns: ["RANGE<NUMBER>"],
9784
+ compute: function (data, classes) {
9785
+ const _data = flattenRowFirst([data], (val) => val).filter((val) => typeof val === "number");
9786
+ const _classes = flattenRowFirst([classes], (val) => val).filter((val) => typeof val === "number");
9787
+ /**
9788
+ * Returns the frequency distribution of the data in the classes, ie. the number of elements in the range
9789
+ * between each classes.
9790
+ *
9791
+ * For example:
9792
+ * - data = [1, 3, 2, 5, 4]
9793
+ * - classes = [3, 5, 1]
9794
+ *
9795
+ * The result will be:
9796
+ * - 2 ==> number of elements 1 > el >= 3
9797
+ * - 2 ==> number of elements 3 > el >= 5
9798
+ * - 1 ==> number of elements <= 1
9799
+ * - 0 ==> number of elements > 5
9800
+ *
9801
+ * @compatibility: GSheet sort the input classes. We do the implemntation of Excel, where we kee the classes unsorted.
9802
+ */
9803
+ const sortedClasses = _classes
9804
+ .map((value, index) => ({ initialIndex: index, value, count: 0 }))
9805
+ .sort((a, b) => a.value - b.value);
9806
+ sortedClasses.push({ initialIndex: sortedClasses.length, value: Infinity, count: 0 });
9807
+ const sortedData = _data.sort((a, b) => a - b);
9808
+ let index = 0;
9809
+ for (const val of sortedData) {
9810
+ while (val > sortedClasses[index].value && index < sortedClasses.length - 1) {
9811
+ index++;
9812
+ }
9813
+ sortedClasses[index].count++;
9814
+ }
9815
+ const result = sortedClasses
9816
+ .sort((a, b) => a.initialIndex - b.initialIndex)
9817
+ .map((val) => val.count);
9818
+ return [result];
9819
+ },
9820
+ isExported: true,
9821
+ };
9822
+ // -----------------------------------------------------------------------------
9823
+ // HSTACK
9824
+ // -----------------------------------------------------------------------------
9825
+ const HSTACK = {
9826
+ description: _lt("Appends ranges horizontally and in sequence to return a larger array."),
9827
+ args: [
9828
+ arg("range1 (any, range<any>)", _lt("The first range to be appended.")),
9829
+ arg("range2 (any, range<any>, repeating)", _lt("Additional ranges to add to range1.")),
9830
+ ],
9831
+ returns: ["RANGE<ANY>"],
9832
+ //TODO computeFormat
9833
+ compute: function (...ranges) {
9834
+ const _ranges = ranges.map((range) => toMatrixArgValue(range));
9835
+ const nRows = Math.max(..._ranges.map((range) => range[0].length));
9836
+ const colArray = [];
9837
+ for (const range of _ranges) {
9838
+ for (const col of range) {
9839
+ //TODO: fill with #N/A for unavailable values instead of zeroes
9840
+ const paddedCol = Array(nRows).fill(0);
9841
+ for (let i = 0; i < col.length; i++) {
9842
+ paddedCol[i] = toCellValue(col[i]);
9843
+ }
9844
+ colArray.push(paddedCol);
9845
+ }
9846
+ }
9847
+ return colArray;
9848
+ },
9849
+ isExported: true,
9850
+ };
9851
+ // -----------------------------------------------------------------------------
9852
+ // MDETERM
9853
+ // -----------------------------------------------------------------------------
9854
+ const MDETERM = {
9855
+ description: _lt("Returns the matrix determinant of a square matrix."),
9856
+ args: [
9857
+ arg("square_matrix (number, range<number>)", _lt("An range with an equal number of rows and columns representing a matrix whose determinant will be calculated.")),
9858
+ ],
9859
+ returns: ["NUMBER"],
9860
+ compute: function (matrix) {
9861
+ const _matrix = toMatrixArgValue(matrix);
9862
+ assertSquareMatrix(_lt("The argument square_matrix must have the same number of columns and rows."), _matrix);
9863
+ if (!isNumberMatrix(_matrix)) {
9864
+ throw new Error(_lt("The argument square_matrix must be a matrix of numbers."));
9865
+ }
9866
+ const { determinant } = invertMatrix(_matrix);
9867
+ return determinant;
9868
+ },
9869
+ isExported: true,
9870
+ };
9871
+ // -----------------------------------------------------------------------------
9872
+ // MINVERSE
9873
+ // -----------------------------------------------------------------------------
9874
+ const MINVERSE = {
9875
+ description: _lt("Returns the multiplicative inverse of a square matrix."),
9876
+ args: [
9877
+ arg("square_matrix (number, range<number>)", _lt("An range with an equal number of rows and columns representing a matrix whose multiplicative inverse will be calculated.")),
9878
+ ],
9879
+ returns: ["RANGE<NUMBER>"],
9880
+ compute: function (matrix) {
9881
+ const _matrix = toMatrixArgValue(matrix);
9882
+ assertSquareMatrix(_lt("The argument square_matrix must have the same number of columns and rows."), _matrix);
9883
+ if (!isNumberMatrix(_matrix)) {
9884
+ throw new Error(_lt("The argument square_matrix must be a matrix of numbers."));
9885
+ }
9886
+ const { inverted } = invertMatrix(_matrix);
9887
+ if (!inverted) {
9888
+ throw new Error(_lt("The matrix is not invertible."));
9889
+ }
9890
+ return inverted;
9891
+ },
9892
+ isExported: true,
9893
+ };
9894
+ // -----------------------------------------------------------------------------
9895
+ // MMULT
9896
+ // -----------------------------------------------------------------------------
9897
+ const MMULT = {
9898
+ description: _lt("Calculates the matrix product of two matrices."),
9899
+ args: [
9900
+ arg("matrix1 (number, range<number>)", _lt("The first matrix in the matrix multiplication operation.")),
9901
+ arg("matrix2 (number, range<number>)", _lt("The second matrix in the matrix multiplication operation.")),
9902
+ ],
9903
+ returns: ["RANGE<NUMBER>"],
9904
+ compute: function (matrix1, matrix2) {
9905
+ const _matrix1 = toMatrixArgValue(matrix1);
9906
+ const _matrix2 = toMatrixArgValue(matrix2);
9907
+ assert(() => _matrix1.length === _matrix2[0].length, _lt("In [[FUNCTION_NAME]], the number of columns of the first matrix (%s) must be equal to the \
9908
+ number of rows of the second matrix (%s).", _matrix1.length.toString(), _matrix2[0].length.toString()));
9909
+ if (!isNumberMatrix(_matrix1) || !isNumberMatrix(_matrix2)) {
9910
+ throw new Error(_lt("The arguments matrix1 and matrix2 must be matrices of numbers."));
9911
+ }
9912
+ return multiplyMatrices(_matrix1, _matrix2);
9913
+ },
9914
+ isExported: true,
9915
+ };
9916
+ // -----------------------------------------------------------------------------
9917
+ // SUMPRODUCT
9918
+ // -----------------------------------------------------------------------------
9919
+ const SUMPRODUCT = {
9920
+ description: _lt("Calculates the sum of the products of corresponding entries in equal-sized ranges."),
9921
+ args: [
9922
+ arg("range1 (number, range<number>)", _lt("The first range whose entries will be multiplied with corresponding entries in the other ranges.")),
9923
+ arg("range2 (number, range<number>, repeating)", _lt("The other range whose entries will be multiplied with corresponding entries in the other ranges.")),
9924
+ ],
9925
+ returns: ["NUMBER"],
9926
+ compute: function (...args) {
9927
+ assertSameDimensions(_lt("All the ranges must have the same dimensions."), ...args);
9928
+ const _args = args.map(toMatrixArgValue);
9929
+ let result = 0;
9930
+ for (let i = 0; i < _args[0].length; i++) {
9931
+ for (let j = 0; j < _args[0][i].length; j++) {
9932
+ if (!_args.every((range) => typeof range[i][j] === "number")) {
9933
+ continue;
9934
+ }
9935
+ let product = 1;
9936
+ for (const range of _args) {
9937
+ product *= toNumber(range[i][j]);
9938
+ }
9939
+ result += product;
9940
+ }
9941
+ }
9942
+ return result;
9943
+ },
9944
+ isExported: true,
9945
+ };
9946
+ // -----------------------------------------------------------------------------
9947
+ // SUMX2MY2
9948
+ // -----------------------------------------------------------------------------
9949
+ /**
9950
+ * Return the sum of the callback applied to each pair of values in the two arrays.
9951
+ *
9952
+ * Ignore the pairs X,Y where one of the value isn't a number. Throw an error if no pair of numbers is found.
9953
+ */
9954
+ function getSumXAndY(arrayX, arrayY, cb) {
9955
+ assertSameDimensions("The arguments array_x and array_y must have the same dimensions.", arrayX, arrayY);
9956
+ const _arrayX = toMatrixArgValue(arrayX);
9957
+ const _arrayY = toMatrixArgValue(arrayY);
9958
+ let validPairFound = false;
9959
+ let result = 0;
9960
+ for (const i in _arrayX) {
9961
+ for (const j in _arrayX[i]) {
9962
+ const arrayXValue = _arrayX[i][j];
9963
+ const arrayYValue = _arrayY[i][j];
9964
+ if (typeof arrayXValue !== "number" || typeof arrayYValue !== "number") {
9965
+ continue;
9966
+ }
9967
+ validPairFound = true;
9968
+ result += cb(arrayXValue, arrayYValue);
9969
+ }
9970
+ }
9971
+ if (!validPairFound) {
9972
+ throw new Error("The arguments array_x and array_y must contain at least one pair of numbers.");
9973
+ }
9974
+ return result;
9975
+ }
9976
+ const SUMX2MY2 = {
9977
+ description: _lt("Calculates the sum of the difference of the squares of the values in two array."),
9978
+ args: [
9979
+ arg("array_x (number, range<number>)", _lt("The array or range of values whose squares will be reduced by the squares of corresponding entries in array_y and added together.")),
9980
+ arg("array_y (number, range<number>)", _lt("The array or range of values whose squares will be subtracted from the squares of corresponding entries in array_x and added together.")),
9981
+ ],
9982
+ returns: ["NUMBER"],
9983
+ compute: function (arrayX, arrayY) {
9984
+ return getSumXAndY(arrayX, arrayY, (x, y) => x ** 2 - y ** 2);
9985
+ },
9986
+ isExported: true,
9987
+ };
9988
+ // -----------------------------------------------------------------------------
9989
+ // SUMX2PY2
9990
+ // -----------------------------------------------------------------------------
9991
+ const SUMX2PY2 = {
9992
+ description: _lt("Calculates the sum of the sum of the squares of the values in two array."),
9993
+ args: [
9994
+ arg("array_x (number, range<number>)", _lt("The array or range of values whose squares will be added to the squares of corresponding entries in array_y and added together.")),
9995
+ arg("array_y (number, range<number>)", _lt("The array or range of values whose squares will be added to the squares of corresponding entries in array_x and added together.")),
9996
+ ],
9997
+ returns: ["NUMBER"],
9998
+ compute: function (arrayX, arrayY) {
9999
+ return getSumXAndY(arrayX, arrayY, (x, y) => x ** 2 + y ** 2);
10000
+ },
10001
+ isExported: true,
10002
+ };
10003
+ // -----------------------------------------------------------------------------
10004
+ // SUMXMY2
10005
+ // -----------------------------------------------------------------------------
10006
+ const SUMXMY2 = {
10007
+ description: _lt("Calculates the sum of squares of the differences of values in two array."),
10008
+ args: [
10009
+ arg("array_x (number, range<number>)", _lt("The array or range of values that will be reduced by corresponding entries in array_y, squared, and added together.")),
10010
+ arg("array_y (number, range<number>)", _lt("The array or range of values that will be subtracted from corresponding entries in array_x, the result squared, and all such results added together.")),
10011
+ ],
10012
+ returns: ["NUMBER"],
10013
+ compute: function (arrayX, arrayY) {
10014
+ return getSumXAndY(arrayX, arrayY, (x, y) => (x - y) ** 2);
10015
+ },
10016
+ isExported: true,
10017
+ };
10018
+ // -----------------------------------------------------------------------------
10019
+ // TOCOL
10020
+ // -----------------------------------------------------------------------------
10021
+ const TO_COL_ROW_DEFAULT_IGNORE = 0;
10022
+ const TO_COL_ROW_DEFAULT_SCAN = false;
10023
+ const TO_COL_ROW_ARGS = [
10024
+ arg("array (any, range<any>)", _lt("The array which will be transformed.")),
10025
+ arg(`ignore (number, default=${TO_COL_ROW_DEFAULT_IGNORE})`, _lt("The control to ignore blanks and errors. 0 (default) is to keep all values, 1 is to ignore blanks, 2 is to ignore errors, and 3 is to ignore blanks and errors.")),
10026
+ arg(`scan_by_column (number, default=${TO_COL_ROW_DEFAULT_SCAN})`, _lt("Whether the array should be scanned by column. True scans the array by column and false (default) \
10027
+ scans the array by row.")),
10028
+ ];
10029
+ const TOCOL = {
10030
+ description: _lt("Transforms a range of cells into a single column."),
10031
+ args: TO_COL_ROW_ARGS,
10032
+ returns: ["RANGE<ANY>"],
10033
+ //TODO compute format
10034
+ compute: function (array, ignore = TO_COL_ROW_DEFAULT_IGNORE, scanByColumn = TO_COL_ROW_DEFAULT_SCAN) {
10035
+ const _array = toMatrixArgValue(array);
10036
+ const _ignore = toInteger(ignore);
10037
+ const _scanByColumn = toBoolean(scanByColumn);
10038
+ assert(() => _ignore >= 0 && _ignore <= 3, _lt("Argument ignore must be between 0 and 3"));
10039
+ const mappedFn = (acc, item) => {
10040
+ // TODO : implement ignore value 2 (ignore error) & 3 (ignore blanks and errors) once we can have errors in
10041
+ // the array w/o crashing
10042
+ if ((_ignore === 1 || _ignore === 3) && (item === undefined || item === null)) {
10043
+ return acc;
10044
+ }
10045
+ acc.push(toCellValue(item));
10046
+ return acc;
10047
+ };
10048
+ const result = reduceAny([_array], mappedFn, [], _scanByColumn ? "colFirst" : "rowFirst");
10049
+ if (result.length === 0) {
10050
+ throw new NotAvailableError(_lt("No results for the given arguments of TOCOL."));
10051
+ }
10052
+ return [result];
10053
+ },
10054
+ isExported: true,
10055
+ };
10056
+ // -----------------------------------------------------------------------------
10057
+ // TOROW
10058
+ // -----------------------------------------------------------------------------
10059
+ const TOROW = {
10060
+ description: _lt("Transforms a range of cells into a single row."),
10061
+ args: TO_COL_ROW_ARGS,
10062
+ returns: ["RANGE<ANY>"],
10063
+ //TODO compute format
10064
+ compute: function (array, ignore = TO_COL_ROW_DEFAULT_IGNORE, scanByColumn = TO_COL_ROW_DEFAULT_SCAN) {
10065
+ const _array = toMatrixArgValue(array);
10066
+ const _ignore = toInteger(ignore);
10067
+ const _scanByColumn = toBoolean(scanByColumn);
10068
+ assert(() => _ignore >= 0 && _ignore <= 3, _lt("Argument ignore must be between 0 and 3"));
10069
+ const mappedFn = (acc, item) => {
10070
+ // TODO : implement ignore value 2 (ignore error) & 3 (ignore blanks and errors) once we can have errors in
10071
+ // the array w/o crashing
10072
+ if ((_ignore === 1 || _ignore === 3) && (item === undefined || item === null)) {
10073
+ return acc;
10074
+ }
10075
+ acc.push([toCellValue(item)]);
10076
+ return acc;
10077
+ };
10078
+ const result = reduceAny([_array], mappedFn, [], _scanByColumn ? "colFirst" : "rowFirst");
10079
+ if (result.length === 0 || result[0].length === 0) {
10080
+ throw new NotAvailableError(_lt("No results for the given arguments of TOROW."));
10081
+ }
10082
+ return result;
10083
+ },
10084
+ isExported: true,
10085
+ };
10086
+ // -----------------------------------------------------------------------------
10087
+ // TRANSPOSE
10088
+ // -----------------------------------------------------------------------------
10089
+ const TRANSPOSE = {
10090
+ description: _lt("Transposes the rows and columns of a range."),
10091
+ args: [arg("range (any, range<any>)", _lt("The range to be transposed."))],
10092
+ returns: ["RANGE<ANY>"],
10093
+ computeFormat: (values) => {
10094
+ if (!values.format) {
10095
+ return undefined;
10096
+ }
10097
+ if (!isMatrix(values.format)) {
10098
+ return values.format;
10099
+ }
10100
+ return transpose2dArray(values.format);
10101
+ },
10102
+ compute: function (values) {
10103
+ const _values = toMatrixArgValue(values);
10104
+ return transpose2dArray(_values, toCellValue);
10105
+ },
10106
+ isExported: true,
10107
+ };
10108
+ // -----------------------------------------------------------------------------
10109
+ // VSTACK
10110
+ // -----------------------------------------------------------------------------
10111
+ const VSTACK = {
10112
+ description: _lt("Appends ranges vertically and in sequence to return a larger array."),
10113
+ args: [
10114
+ arg("range1 (any, range<any>)", _lt("The first range to be appended.")),
10115
+ arg("range2 (any, range<any>, repeating)", _lt("Additional ranges to add to range1.")),
10116
+ ],
10117
+ returns: ["RANGE<ANY>"],
10118
+ //TODO computeFormat
10119
+ compute: function (...ranges) {
10120
+ const _ranges = ranges.map((range) => toMatrixArgValue(range));
10121
+ const nCols = Math.max(..._ranges.map((range) => range.length));
10122
+ const nRows = _ranges.reduce((acc, range) => acc + range[0].length, 0);
10123
+ const result = Array(nCols)
10124
+ .fill([])
10125
+ .map(() => Array(nRows).fill(0)); // TODO fill with #N/A
10126
+ let currentRow = 0;
10127
+ for (const range of _ranges) {
10128
+ for (let col = 0; col < range.length; col++) {
10129
+ for (let row = 0; row < range[col].length; row++) {
10130
+ result[col][currentRow + row] = toCellValue(range[col][row]);
10131
+ }
10132
+ }
10133
+ currentRow += range[0].length;
10134
+ }
10135
+ return result;
10136
+ },
10137
+ isExported: true,
10138
+ };
10139
+ // -----------------------------------------------------------------------------
10140
+ // WRAPCOLS
10141
+ // -----------------------------------------------------------------------------
10142
+ const WRAPCOLS = {
10143
+ description: _lt("Wraps the provided row or column of cells by columns after a specified number of elements to form a new array."),
10144
+ args: [
10145
+ arg("range (any, range<any>)", _lt("The range to wrap.")),
10146
+ arg("wrap_count (number)", _lt("The maximum number of cells for each column, rounded down to the nearest whole number.")),
10147
+ arg("pad_with (any, default=0)", // TODO : replace with #N/A
10148
+ _lt("The value with which to fill the extra cells in the range.")),
10149
+ ],
10150
+ returns: ["RANGE<ANY>"],
10151
+ //TODO computeFormat
10152
+ compute: function (range, wrapCount, padWith = 0) {
10153
+ const _range = toMatrixArgValue(range);
10154
+ const nOfRows = toInteger(wrapCount);
10155
+ const _padWith = padWith === null ? 0 : padWith;
10156
+ assertSingleColOrRow(_lt("Argument range must be a single row or column."), _range);
10157
+ const values = _range.flat();
10158
+ const nOfCols = Math.ceil(values.length / nOfRows);
10159
+ const result = Array(nOfCols);
10160
+ for (let col = 0; col < nOfCols; col++) {
10161
+ result[col] = Array(nOfRows).fill(_padWith);
10162
+ for (let row = 0; row < nOfRows; row++) {
10163
+ const index = col * nOfRows + row;
10164
+ if (index < values.length) {
10165
+ result[col][row] = toCellValue(values[index]);
10166
+ }
10167
+ }
10168
+ }
10169
+ return result;
10170
+ },
10171
+ isExported: true,
10172
+ };
10173
+ // -----------------------------------------------------------------------------
10174
+ // WRAPROWS
10175
+ // -----------------------------------------------------------------------------
10176
+ const WRAPROWS = {
10177
+ description: _lt("Wraps the provided row or column of cells by rows after a specified number of elements to form a new array."),
10178
+ args: [
10179
+ arg("range (any, range<any>)", _lt("The range to wrap.")),
10180
+ arg("wrap_count (number)", _lt("The maximum number of cells for each row, rounded down to the nearest whole number.")),
10181
+ arg("pad_with (any, default=0)", // TODO : replace with #N/A
10182
+ _lt("The value with which to fill the extra cells in the range.")),
10183
+ ],
10184
+ returns: ["RANGE<ANY>"],
10185
+ //TODO computeFormat
10186
+ compute: function (range, wrapCount, padWith = 0) {
10187
+ const _range = toMatrixArgValue(range);
10188
+ const nOfCols = toInteger(wrapCount);
10189
+ const _padWith = padWith === null ? 0 : padWith;
10190
+ assertSingleColOrRow(_lt("Argument range must be a single row or column."), _range);
10191
+ const values = _range.flat();
10192
+ const nOfRows = Math.ceil(values.length / nOfCols);
10193
+ const result = Array(nOfCols)
10194
+ .fill([])
10195
+ .map(() => Array(nOfRows).fill(_padWith));
10196
+ for (let row = 0; row < nOfRows; row++) {
10197
+ for (let col = 0; col < nOfCols; col++) {
10198
+ const index = row * nOfCols + col;
10199
+ if (index < values.length) {
10200
+ result[col][row] = toCellValue(values[index]);
10201
+ }
10202
+ }
10203
+ }
10204
+ return result;
10205
+ },
10206
+ isExported: true,
10207
+ };
10208
+
10209
+ var array = /*#__PURE__*/Object.freeze({
10210
+ __proto__: null,
10211
+ ARRAY_CONSTRAIN: ARRAY_CONSTRAIN,
10212
+ CHOOSECOLS: CHOOSECOLS,
10213
+ CHOOSEROWS: CHOOSEROWS,
10214
+ EXPAND: EXPAND,
10215
+ FLATTEN: FLATTEN,
10216
+ FREQUENCY: FREQUENCY,
10217
+ HSTACK: HSTACK,
10218
+ MDETERM: MDETERM,
10219
+ MINVERSE: MINVERSE,
10220
+ MMULT: MMULT,
10221
+ SUMPRODUCT: SUMPRODUCT,
10222
+ SUMX2MY2: SUMX2MY2,
10223
+ SUMX2PY2: SUMX2PY2,
10224
+ SUMXMY2: SUMXMY2,
10225
+ TOCOL: TOCOL,
10226
+ TOROW: TOROW,
10227
+ TRANSPOSE: TRANSPOSE,
10228
+ VSTACK: VSTACK,
10229
+ WRAPCOLS: WRAPCOLS,
10230
+ WRAPROWS: WRAPROWS
10231
+ });
10232
+
9758
10233
  // -----------------------------------------------------------------------------
9759
10234
  // FORMAT.LARGE.NUMBER
9760
10235
  // -----------------------------------------------------------------------------
@@ -10410,6 +10885,22 @@ const MOD = {
10410
10885
  isExported: true,
10411
10886
  };
10412
10887
  // -----------------------------------------------------------------------------
10888
+ // MUNIT
10889
+ // -----------------------------------------------------------------------------
10890
+ const MUNIT = {
10891
+ description: _lt("Returns a n x n unit matrix, where n is the input dimension."),
10892
+ args: [
10893
+ arg("dimension (number)", _lt("An integer specifying the dimension size of the unit matrix. It must be positive.")),
10894
+ ],
10895
+ returns: ["RANGE<NUMBER>"],
10896
+ compute: function (n) {
10897
+ const _n = toInteger(n);
10898
+ assertPositive(_lt("The argument dimension must be positive"), _n);
10899
+ return getUnitMatrix(_n);
10900
+ },
10901
+ isExported: true,
10902
+ };
10903
+ // -----------------------------------------------------------------------------
10413
10904
  // ODD
10414
10905
  // -----------------------------------------------------------------------------
10415
10906
  const ODD = {
@@ -10508,6 +10999,47 @@ const RAND = {
10508
10999
  isExported: true,
10509
11000
  };
10510
11001
  // -----------------------------------------------------------------------------
11002
+ // RANDARRAY
11003
+ // -----------------------------------------------------------------------------
11004
+ const RANDARRAY = {
11005
+ description: _lt("Returns a grid of random numbers between 0 inclusive and 1 exclusive."),
11006
+ args: [
11007
+ arg("rows (number, default=1)", _lt("The number of rows to be returned.")),
11008
+ arg("columns (number, default=1)", _lt("The number of columns to be returned.")),
11009
+ arg("min (number, default=0)", _lt("The minimum number you would like returned.")),
11010
+ arg("max (number, default=1)", _lt("The maximum number you would like returned.")),
11011
+ arg("whole_number (number, default=FALSE)", _lt("Return a whole number or a decimal value.")),
11012
+ ],
11013
+ returns: ["RANGE<NUMBER>"],
11014
+ compute: function (rows = 1, columns = 1, min = 0, max = 1, whole_number = false) {
11015
+ const _cols = toInteger(columns);
11016
+ const _rows = toInteger(rows);
11017
+ const _min = toNumber(min);
11018
+ const _max = toNumber(max);
11019
+ const _whole_number = toBoolean(whole_number);
11020
+ assertPositive(_lt("The number columns (%s) must be positive.", _cols.toString()), _cols);
11021
+ assertPositive(_lt("The number rows (%s) must be positive.", _rows.toString()), _rows);
11022
+ assert(() => _min <= _max, _lt("The maximum (%s) must be greater than or equal to the minimum (%s).", _max.toString(), _min.toString()));
11023
+ if (_whole_number) {
11024
+ assert(() => Number.isInteger(_min) && Number.isInteger(_max), _lt("The maximum (%s) and minimum (%s) must be integers when whole_number is TRUE.", _max.toString(), _min.toString()));
11025
+ }
11026
+ const result = Array(_cols);
11027
+ for (let col = 0; col < _cols; col++) {
11028
+ result[col] = Array(_rows);
11029
+ for (let row = 0; row < _rows; row++) {
11030
+ if (!_whole_number) {
11031
+ result[col][row] = _min + Math.random() * (_max - _min);
11032
+ }
11033
+ else {
11034
+ result[col][row] = Math.floor(Math.random() * (_max - _min + 1) + _min);
11035
+ }
11036
+ }
11037
+ }
11038
+ return result;
11039
+ },
11040
+ isExported: true,
11041
+ };
11042
+ // -----------------------------------------------------------------------------
10511
11043
  // RANDBETWEEN
10512
11044
  // -----------------------------------------------------------------------------
10513
11045
  const RANDBETWEEN = {
@@ -10837,11 +11369,13 @@ var math = /*#__PURE__*/Object.freeze({
10837
11369
  ISODD: ISODD,
10838
11370
  LN: LN,
10839
11371
  MOD: MOD,
11372
+ MUNIT: MUNIT,
10840
11373
  ODD: ODD,
10841
11374
  PI: PI,
10842
11375
  POWER: POWER,
10843
11376
  PRODUCT: PRODUCT,
10844
11377
  RAND: RAND,
11378
+ RANDARRAY: RANDARRAY,
10845
11379
  RANDBETWEEN: RANDBETWEEN,
10846
11380
  ROUND: ROUND,
10847
11381
  ROUNDDOWN: ROUNDDOWN,
@@ -12868,6 +13402,89 @@ var engineering = /*#__PURE__*/Object.freeze({
12868
13402
  DELTA: DELTA
12869
13403
  });
12870
13404
 
13405
+ // -----------------------------------------------------------------------------
13406
+ // FILTER
13407
+ // -----------------------------------------------------------------------------
13408
+ const FILTER = {
13409
+ description: _lt("Returns a filtered version of the source range, returning only rows or columns that meet the specified conditions."),
13410
+ // TODO modify args description when vectorization on formulas is available
13411
+ args: [
13412
+ arg("range (any, range<any>)", _lt("The data to be filtered.")),
13413
+ arg("condition1 (boolean, range<boolean>)", _lt("A column or row containing true or false values corresponding to the first column or row of range.")),
13414
+ arg("condition2 (boolean, range<boolean>, repeating)", _lt("Additional column or row containing true or false values.")),
13415
+ ],
13416
+ returns: ["RANGE<ANY>"],
13417
+ //TODO computeFormat
13418
+ compute: function (range, ...conditions) {
13419
+ let _range = toMatrixArgValue(range);
13420
+ const _conditionsMatrices = conditions.map((cond) => toMatrixArgValue(cond));
13421
+ _conditionsMatrices.map((c) => assertSingleColOrRow(_lt("The arguments condition must be a single column or row."), c));
13422
+ assertSameDimensions(_lt("The arguments conditions must have the same dimensions."), ..._conditionsMatrices);
13423
+ const _conditions = _conditionsMatrices.map((c) => c.flat());
13424
+ const mode = _conditionsMatrices[0].length === 1 ? "row" : "col";
13425
+ _range = mode === "row" ? transpose2dArray(_range) : _range;
13426
+ assert(() => _conditions.every((cond) => cond.length === _range.length), _lt(`FILTER has mismatched sizes on the range and conditions.`));
13427
+ const results = [];
13428
+ for (let i = 0; i < _range.length; i++) {
13429
+ const row = _range[i];
13430
+ if (_conditions.every((c) => c[i])) {
13431
+ results.push(row);
13432
+ }
13433
+ }
13434
+ if (!results.length) {
13435
+ throw new NotAvailableError(_lt("No match found in FILTER evaluation"));
13436
+ }
13437
+ return toCellValueMatrix(mode === "row" ? transpose2dArray(results) : results);
13438
+ },
13439
+ isExported: true,
13440
+ };
13441
+ // -----------------------------------------------------------------------------
13442
+ // UNIQUE
13443
+ // -----------------------------------------------------------------------------
13444
+ const UNIQUE = {
13445
+ description: _lt("Unique rows in the provided source range."),
13446
+ args: [
13447
+ arg("range (any, range<any>)", _lt("The data to filter by unique entries.")),
13448
+ arg("by_column (boolean, default=FALSE)", _lt("Whether to filter the data by columns or by rows.")),
13449
+ arg("exactly_once (boolean, default=FALSE)", _lt("Whether to return only entries with no duplicates.")),
13450
+ ],
13451
+ returns: ["RANGE<NUMBER>"],
13452
+ // TODO computeFormat
13453
+ compute: function (range, byColumn, exactlyOnce) {
13454
+ if (!isMatrix(range)) {
13455
+ return toCellValue(range);
13456
+ }
13457
+ const _byColumn = toBoolean(byColumn) || false;
13458
+ const _exactlyOnce = toBoolean(exactlyOnce) || false;
13459
+ if (!_byColumn)
13460
+ range = transpose2dArray(range);
13461
+ const map = new Map();
13462
+ for (const row of range) {
13463
+ const key = JSON.stringify(row);
13464
+ const occurrence = map.get(key);
13465
+ if (!occurrence) {
13466
+ map.set(key, { val: row, count: 1 });
13467
+ }
13468
+ else {
13469
+ occurrence.count++;
13470
+ }
13471
+ }
13472
+ const results = _exactlyOnce
13473
+ ? [...map.values()].filter((v) => v.count === 1).map((v) => v.val)
13474
+ : [...map.values()].map((v) => v.val);
13475
+ if (!results.length)
13476
+ throw new Error(_lt("No unique values found"));
13477
+ return toCellValueMatrix(_byColumn ? results : transpose2dArray(results));
13478
+ },
13479
+ isExported: true,
13480
+ };
13481
+
13482
+ var filter = /*#__PURE__*/Object.freeze({
13483
+ __proto__: null,
13484
+ FILTER: FILTER,
13485
+ UNIQUE: UNIQUE
13486
+ });
13487
+
12871
13488
  /** Assert maturity date > settlement date */
12872
13489
  function assertMaturityAndSettlementDatesAreValid(settlement, maturity) {
12873
13490
  assert(() => settlement < maturity, _lt("The maturity (%s) must be strictly greater than the settlement (%s).", maturity.toString(), settlement.toString()));
@@ -15563,13 +16180,16 @@ const XLOOKUP = {
15563
16180
  const _searchMode = Math.trunc(toNumber(searchMode));
15564
16181
  const _searchKey = normalizeValue(searchKey);
15565
16182
  assert(() => lookupRange.length === 1 || lookupRange[0].length === 1, _lt("lookup_range should be either a single row or single column."));
15566
- assert(() => returnRange.length === 1 || returnRange[0].length === 1, _lt("return_range should be either a single row or single column."));
15567
- assert(() => returnRange.length === lookupRange.length &&
15568
- returnRange[0].length === lookupRange[0].length, _lt("return_range should have the same dimensions as lookup_range."));
15569
16183
  assert(() => [-1, 1, -2, 2].includes(_searchMode), _lt("searchMode should be a value in [-1, 1, -2, 2]."));
15570
16184
  assert(() => [-1, 0, 1].includes(_matchMode), _lt("matchMode should be a value in [-1, 0, 1]."));
15571
- const getElement = lookupRange.length === 1 ? getNormalizedValueFromColumnRange : getNormalizedValueFromRowRange;
15572
- const rangeLen = lookupRange.length === 1 ? lookupRange[0].length : lookupRange.length;
16185
+ const lookupDirection = lookupRange.length === 1 ? "col" : "row";
16186
+ assert(() => lookupDirection === "col"
16187
+ ? returnRange[0].length === lookupRange[0].length
16188
+ : returnRange.length === lookupRange.length, _lt("return_range should have the same dimensions as lookup_range."));
16189
+ const getElement = lookupDirection === "col"
16190
+ ? getNormalizedValueFromColumnRange
16191
+ : getNormalizedValueFromRowRange;
16192
+ const rangeLen = lookupDirection === "col" ? lookupRange[0].length : lookupRange.length;
15573
16193
  const mode = _matchMode === 0 ? "strict" : _matchMode === 1 ? "nextGreater" : "nextSmaller";
15574
16194
  const reverseSearch = _searchMode === -1;
15575
16195
  let index;
@@ -15581,7 +16201,7 @@ const XLOOKUP = {
15581
16201
  index = linearSearch(lookupRange, _searchKey, mode, rangeLen, getElement, reverseSearch);
15582
16202
  }
15583
16203
  if (index !== -1) {
15584
- return (lookupRange.length === 1 ? returnRange[0][index] : returnRange[index][0]);
16204
+ return toCellValueMatrix(lookupDirection === "col" ? returnRange.map((col) => [col[index]]) : [returnRange[index]]);
15585
16205
  }
15586
16206
  const _defaultValue = defaultValue?.();
15587
16207
  assertAvailable(_defaultValue, searchKey);
@@ -16122,6 +16742,36 @@ const SEARCH = {
16122
16742
  isExported: true,
16123
16743
  };
16124
16744
  // -----------------------------------------------------------------------------
16745
+ // SPLIT
16746
+ // -----------------------------------------------------------------------------
16747
+ const SPLIT_DEFAULT_SPLIT_BY_EACH = true;
16748
+ const SPLIT_DEFAULT_REMOVE_EMPTY_TEXT = true;
16749
+ const SPLIT = {
16750
+ description: _lt("Split text by specific character delimiter(s)."),
16751
+ args: [
16752
+ arg("text (string)", _lt("The text to divide.")),
16753
+ arg("delimiter (string)", _lt("The character or characters to use to split text.")),
16754
+ arg(`split_by_each (boolean, default=${SPLIT_DEFAULT_SPLIT_BY_EACH}})`, _lt("Whether or not to divide text around each character contained in delimiter.")),
16755
+ arg(`remove_empty_text (boolean, default=${SPLIT_DEFAULT_REMOVE_EMPTY_TEXT})`, _lt("Whether or not to remove empty text messages from the split results. The default behavior is to treat \
16756
+ consecutive delimiters as one (if TRUE). If FALSE, empty cells values are added between consecutive delimiters.")),
16757
+ ],
16758
+ returns: ["RANGE<STRING>"],
16759
+ compute: function (text, delimiter, splitByEach = SPLIT_DEFAULT_SPLIT_BY_EACH, removeEmptyText = SPLIT_DEFAULT_REMOVE_EMPTY_TEXT) {
16760
+ const _text = toString(text);
16761
+ const _delimiter = escapeRegExp(toString(delimiter));
16762
+ const _splitByEach = toBoolean(splitByEach);
16763
+ const _removeEmptyText = toBoolean(removeEmptyText);
16764
+ assert(() => _delimiter.length > 0, _lt("The _delimiter (%s) must be not be empty.", _delimiter));
16765
+ const regex = _splitByEach ? new RegExp(`[${_delimiter}]`, "g") : new RegExp(_delimiter, "g");
16766
+ let result = _text.split(regex);
16767
+ if (_removeEmptyText) {
16768
+ result = result.filter((text) => text !== "");
16769
+ }
16770
+ return transpose2dArray([result]);
16771
+ },
16772
+ isExported: true,
16773
+ };
16774
+ // -----------------------------------------------------------------------------
16125
16775
  // SUBSTITUTE
16126
16776
  // -----------------------------------------------------------------------------
16127
16777
  const SUBSTITUTE = {
@@ -16230,6 +16880,7 @@ var text = /*#__PURE__*/Object.freeze({
16230
16880
  REPLACE: REPLACE,
16231
16881
  RIGHT: RIGHT,
16232
16882
  SEARCH: SEARCH,
16883
+ SPLIT: SPLIT,
16233
16884
  SUBSTITUTE: SUBSTITUTE,
16234
16885
  TEXTJOIN: TEXTJOIN,
16235
16886
  TRIM: TRIM,
@@ -16263,8 +16914,10 @@ var web = /*#__PURE__*/Object.freeze({
16263
16914
  });
16264
16915
 
16265
16916
  const categories = [
16917
+ { name: _lt("Array"), functions: array },
16266
16918
  { name: _lt("Database"), functions: database },
16267
16919
  { name: _lt("Date"), functions: date },
16920
+ { name: _lt("Filter"), functions: filter },
16268
16921
  { name: _lt("Financial"), functions: financial },
16269
16922
  { name: _lt("Info"), functions: info },
16270
16923
  { name: _lt("Lookup"), functions: lookup },
@@ -16337,14 +16990,20 @@ for (let category of categories) {
16337
16990
  }
16338
16991
 
16339
16992
  const insertRow = {
16340
- name: MENU_INSERT_ROWS_NAME,
16993
+ name: (env) => {
16994
+ const number = getRowsNumber(env);
16995
+ return number === 1 ? _lt("Insert row") : _lt("Insert %s rows", number.toString());
16996
+ },
16341
16997
  isVisible: (env) => isConsecutive(env.model.getters.getActiveRows()) &&
16342
16998
  IS_ONLY_ONE_RANGE(env) &&
16343
16999
  env.model.getters.getActiveCols().size === 0,
16344
17000
  icon: "o-spreadsheet-Icon.INSERT_ROW",
16345
17001
  };
16346
17002
  const rowInsertRowBefore = {
16347
- name: ROW_INSERT_ROWS_BEFORE_NAME,
17003
+ name: (env) => {
17004
+ const number = getRowsNumber(env);
17005
+ return number === 1 ? _lt("Insert row above") : _lt("Insert %s rows above", number.toString());
17006
+ },
16348
17007
  execute: INSERT_ROWS_BEFORE_ACTION,
16349
17008
  isVisible: (env) => isConsecutive(env.model.getters.getActiveRows()) &&
16350
17009
  IS_ONLY_ONE_RANGE(env) &&
@@ -16353,17 +17012,32 @@ const rowInsertRowBefore = {
16353
17012
  };
16354
17013
  const topBarInsertRowsBefore = {
16355
17014
  ...rowInsertRowBefore,
16356
- name: MENU_INSERT_ROWS_BEFORE_NAME,
17015
+ name: (env) => {
17016
+ const number = getRowsNumber(env);
17017
+ if (number === 1) {
17018
+ return _lt("Row above");
17019
+ }
17020
+ return _lt("%s Rows above", number.toString());
17021
+ },
16357
17022
  };
16358
17023
  const cellInsertRowsBefore = {
16359
17024
  ...rowInsertRowBefore,
16360
- name: CELL_INSERT_ROWS_BEFORE_NAME,
17025
+ name: (env) => {
17026
+ const number = getRowsNumber(env);
17027
+ if (number === 1) {
17028
+ return _lt("Insert row");
17029
+ }
17030
+ return _lt("Insert %s rows", number.toString());
17031
+ },
16361
17032
  isVisible: IS_ONLY_ONE_RANGE,
16362
17033
  icon: "o-spreadsheet-Icon.INSERT_ROW_BEFORE",
16363
17034
  };
16364
17035
  const rowInsertRowsAfter = {
16365
17036
  execute: INSERT_ROWS_AFTER_ACTION,
16366
- name: ROW_INSERT_ROWS_AFTER_NAME,
17037
+ name: (env) => {
17038
+ const number = getRowsNumber(env);
17039
+ return number === 1 ? _lt("Insert row below") : _lt("Insert %s rows below", number.toString());
17040
+ },
16367
17041
  isVisible: (env) => isConsecutive(env.model.getters.getActiveRows()) &&
16368
17042
  IS_ONLY_ONE_RANGE(env) &&
16369
17043
  env.model.getters.getActiveCols().size === 0,
@@ -16371,17 +17045,31 @@ const rowInsertRowsAfter = {
16371
17045
  };
16372
17046
  const topBarInsertRowsAfter = {
16373
17047
  ...rowInsertRowsAfter,
16374
- name: MENU_INSERT_ROWS_AFTER_NAME,
17048
+ name: (env) => {
17049
+ const number = getRowsNumber(env);
17050
+ if (number === 1) {
17051
+ return _lt("Row below");
17052
+ }
17053
+ return _lt("%s Rows below", number.toString());
17054
+ },
16375
17055
  };
16376
17056
  const insertCol = {
16377
- name: MENU_INSERT_COLUMNS_NAME,
17057
+ name: (env) => {
17058
+ const number = getColumnsNumber(env);
17059
+ return number === 1 ? _lt("Insert column") : _lt("Insert %s columns", number.toString());
17060
+ },
16378
17061
  isVisible: (env) => isConsecutive(env.model.getters.getActiveCols()) &&
16379
17062
  IS_ONLY_ONE_RANGE(env) &&
16380
17063
  env.model.getters.getActiveRows().size === 0,
16381
17064
  icon: "o-spreadsheet-Icon.INSERT_COL",
16382
17065
  };
16383
17066
  const colInsertColsBefore = {
16384
- name: COLUMN_INSERT_COLUMNS_BEFORE_NAME,
17067
+ name: (env) => {
17068
+ const number = getColumnsNumber(env);
17069
+ return number === 1
17070
+ ? _lt("Insert column left")
17071
+ : _lt("Insert %s columns left", number.toString());
17072
+ },
16385
17073
  execute: INSERT_COLUMNS_BEFORE_ACTION,
16386
17074
  isVisible: (env) => isConsecutive(env.model.getters.getActiveCols()) &&
16387
17075
  IS_ONLY_ONE_RANGE(env) &&
@@ -16390,16 +17078,33 @@ const colInsertColsBefore = {
16390
17078
  };
16391
17079
  const topBarInsertColsBefore = {
16392
17080
  ...colInsertColsBefore,
16393
- name: MENU_INSERT_COLUMNS_BEFORE_NAME,
17081
+ name: (env) => {
17082
+ const number = getColumnsNumber(env);
17083
+ if (number === 1) {
17084
+ return _lt("Column left");
17085
+ }
17086
+ return _lt("%s Columns left", number.toString());
17087
+ },
16394
17088
  };
16395
17089
  const cellInsertColsBefore = {
16396
17090
  ...colInsertColsBefore,
16397
- name: CELL_INSERT_COLUMNS_BEFORE_NAME,
17091
+ name: (env) => {
17092
+ const number = getColumnsNumber(env);
17093
+ if (number === 1) {
17094
+ return _lt("Insert column");
17095
+ }
17096
+ return _lt("Insert %s columns", number.toString());
17097
+ },
16398
17098
  isVisible: IS_ONLY_ONE_RANGE,
16399
17099
  icon: "o-spreadsheet-Icon.INSERT_COL_BEFORE",
16400
17100
  };
16401
17101
  const colInsertColsAfter = {
16402
- name: COLUMN_INSERT_COLUMNS_AFTER_NAME,
17102
+ name: (env) => {
17103
+ const number = getColumnsNumber(env);
17104
+ return number === 1
17105
+ ? _lt("Insert column right")
17106
+ : _lt("Insert %s columns right", number.toString());
17107
+ },
16403
17108
  execute: INSERT_COLUMNS_AFTER_ACTION,
16404
17109
  isVisible: (env) => isConsecutive(env.model.getters.getActiveCols()) &&
16405
17110
  IS_ONLY_ONE_RANGE(env) &&
@@ -16408,7 +17113,13 @@ const colInsertColsAfter = {
16408
17113
  };
16409
17114
  const topBarInsertColsAfter = {
16410
17115
  ...colInsertColsAfter,
16411
- name: MENU_INSERT_COLUMNS_AFTER_NAME,
17116
+ name: (env) => {
17117
+ const number = getColumnsNumber(env);
17118
+ if (number === 1) {
17119
+ return _lt("Column right");
17120
+ }
17121
+ return _lt("%s Columns right", number.toString());
17122
+ },
16412
17123
  execute: INSERT_COLUMNS_AFTER_ACTION,
16413
17124
  };
16414
17125
  const insertCell = {
@@ -16420,13 +17131,21 @@ const insertCell = {
16420
17131
  };
16421
17132
  const insertCellShiftDown = {
16422
17133
  name: _lt("Insert cells and shift down"),
16423
- execute: INSERT_CELL_SHIFT_DOWN,
17134
+ execute: (env) => {
17135
+ const zone = env.model.getters.getSelectedZone();
17136
+ const result = env.model.dispatch("INSERT_CELL", { zone, shiftDimension: "ROW" });
17137
+ handlePasteResult(env, result);
17138
+ },
16424
17139
  isVisible: (env) => env.model.getters.getActiveRows().size === 0 && env.model.getters.getActiveCols().size === 0,
16425
17140
  icon: "o-spreadsheet-Icon.INSERT_CELL_SHIFT_DOWN",
16426
17141
  };
16427
17142
  const insertCellShiftRight = {
16428
17143
  name: _lt("Insert cells and shift right"),
16429
- execute: INSERT_CELL_SHIFT_RIGHT,
17144
+ execute: (env) => {
17145
+ const zone = env.model.getters.getSelectedZone();
17146
+ const result = env.model.dispatch("INSERT_CELL", { zone, shiftDimension: "COL" });
17147
+ handlePasteResult(env, result);
17148
+ },
16430
17149
  isVisible: (env) => env.model.getters.getActiveRows().size === 0 && env.model.getters.getActiveCols().size === 0,
16431
17150
  icon: "o-spreadsheet-Icon.INSERT_CELL_SHIFT_RIGHT",
16432
17151
  };
@@ -16492,7 +17211,13 @@ const insertLink = {
16492
17211
  };
16493
17212
  const insertSheet = {
16494
17213
  name: _lt("Insert sheet"),
16495
- execute: CREATE_SHEET_ACTION,
17214
+ execute: (env) => {
17215
+ const activeSheetId = env.model.getters.getActiveSheetId();
17216
+ const position = env.model.getters.getSheetIds().indexOf(activeSheetId) + 1;
17217
+ const sheetId = env.model.uuidGenerator.uuidv4();
17218
+ env.model.dispatch("CREATE_SHEET", { sheetId, position });
17219
+ env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
17220
+ },
16496
17221
  icon: "o-spreadsheet-Icon.INSERT_SHEET",
16497
17222
  };
16498
17223
  function createFormulaFunctions(fnNames) {
@@ -16503,6 +17228,26 @@ function createFormulaFunctions(fnNames) {
16503
17228
  execute: (env) => env.startCellEdition(`=${fnName}(`),
16504
17229
  };
16505
17230
  });
17231
+ }
17232
+ function getRowsNumber(env) {
17233
+ const activeRows = env.model.getters.getActiveRows();
17234
+ if (activeRows.size) {
17235
+ return activeRows.size;
17236
+ }
17237
+ else {
17238
+ const zone = env.model.getters.getSelectedZones()[0];
17239
+ return zone.bottom - zone.top + 1;
17240
+ }
17241
+ }
17242
+ function getColumnsNumber(env) {
17243
+ const activeCols = env.model.getters.getActiveCols();
17244
+ if (activeCols.size) {
17245
+ return activeCols.size;
17246
+ }
17247
+ else {
17248
+ const zone = env.model.getters.getSelectedZones()[0];
17249
+ return zone.right - zone.left + 1;
17250
+ }
16506
17251
  }
16507
17252
 
16508
17253
  //------------------------------------------------------------------------------
@@ -16593,6 +17338,123 @@ cellMenuRegistry
16593
17338
  separator: true,
16594
17339
  });
16595
17340
 
17341
+ const SORT_TYPES = [
17342
+ CellValueType.number,
17343
+ CellValueType.error,
17344
+ CellValueType.text,
17345
+ CellValueType.boolean,
17346
+ ];
17347
+ function sortCells(cells, sortDirection, emptyCellAsZero) {
17348
+ const cellsWithIndex = cells.map((cell, index) => ({
17349
+ index,
17350
+ type: cell.type,
17351
+ value: cell.value,
17352
+ }));
17353
+ let emptyCells = cellsWithIndex.filter((x) => x.type === CellValueType.empty);
17354
+ let nonEmptyCells = cellsWithIndex.filter((x) => x.type !== CellValueType.empty);
17355
+ if (emptyCellAsZero) {
17356
+ nonEmptyCells.push(...emptyCells.map((emptyCell) => ({ ...emptyCell, type: CellValueType.number, value: 0 })));
17357
+ emptyCells = [];
17358
+ }
17359
+ const inverse = sortDirection === "descending" ? -1 : 1;
17360
+ return nonEmptyCells
17361
+ .sort((left, right) => {
17362
+ let typeOrder = SORT_TYPES.indexOf(left.type) - SORT_TYPES.indexOf(right.type);
17363
+ if (typeOrder === 0) {
17364
+ if (left.type === CellValueType.text || left.type === CellValueType.error) {
17365
+ typeOrder = left.value.localeCompare(right.value);
17366
+ }
17367
+ else
17368
+ typeOrder = left.value - right.value;
17369
+ }
17370
+ return inverse * typeOrder;
17371
+ })
17372
+ .concat(emptyCells);
17373
+ }
17374
+ function interactiveSortSelection(env, sheetId, anchor, zone, sortDirection) {
17375
+ let result = DispatchResult.Success;
17376
+ //several columns => bypass the contiguity check
17377
+ let multiColumns = zone.right > zone.left;
17378
+ if (env.model.getters.doesIntersectMerge(sheetId, zone)) {
17379
+ multiColumns = false;
17380
+ let table;
17381
+ for (let row = zone.top; row <= zone.bottom; row++) {
17382
+ table = [];
17383
+ for (let col = zone.left; col <= zone.right; col++) {
17384
+ let merge = env.model.getters.getMerge({ sheetId, col, row });
17385
+ if (merge && !table.includes(merge.id.toString())) {
17386
+ table.push(merge.id.toString());
17387
+ }
17388
+ }
17389
+ if (table.length >= 2) {
17390
+ multiColumns = true;
17391
+ break;
17392
+ }
17393
+ }
17394
+ }
17395
+ const { col, row } = anchor;
17396
+ if (multiColumns) {
17397
+ result = env.model.dispatch("SORT_CELLS", { sheetId, col, row, zone, sortDirection });
17398
+ }
17399
+ else {
17400
+ // check contiguity
17401
+ const contiguousZone = env.model.getters.getContiguousZone(sheetId, zone);
17402
+ if (isEqual(contiguousZone, zone)) {
17403
+ // merge as it is
17404
+ result = env.model.dispatch("SORT_CELLS", {
17405
+ sheetId,
17406
+ col,
17407
+ row,
17408
+ zone,
17409
+ sortDirection,
17410
+ });
17411
+ }
17412
+ else {
17413
+ env.askConfirmation(_lt("We found data next to your selection. Since this data was not selected, it will not be sorted. Do you want to extend your selection?"), () => {
17414
+ zone = contiguousZone;
17415
+ result = env.model.dispatch("SORT_CELLS", {
17416
+ sheetId,
17417
+ col,
17418
+ row,
17419
+ zone,
17420
+ sortDirection,
17421
+ });
17422
+ }, () => {
17423
+ result = env.model.dispatch("SORT_CELLS", {
17424
+ sheetId,
17425
+ col,
17426
+ row,
17427
+ zone,
17428
+ sortDirection,
17429
+ });
17430
+ });
17431
+ }
17432
+ }
17433
+ if (result.isCancelledBecause(64 /* CommandResult.InvalidSortZone */)) {
17434
+ const { col, row } = anchor;
17435
+ env.model.selection.selectZone({ cell: { col, row }, zone });
17436
+ env.raiseError(_lt("Cannot sort. To sort, select only cells or only merges that have the same size."));
17437
+ }
17438
+ }
17439
+
17440
+ const AddFilterInteractiveContent = {
17441
+ filterOverlap: _lt("You cannot create overlapping filters."),
17442
+ nonContinuousTargets: _lt("A filter can only be created on a continuous selection."),
17443
+ mergeInFilter: _lt("You can't create a filter over a range that contains a merge."),
17444
+ };
17445
+ function interactiveAddFilter(env, sheetId, target) {
17446
+ const result = env.model.dispatch("CREATE_FILTER_TABLE", { target, sheetId });
17447
+ if (result.isCancelledBecause(79 /* CommandResult.FilterOverlap */)) {
17448
+ env.raiseError(AddFilterInteractiveContent.filterOverlap);
17449
+ }
17450
+ else if (result.isCancelledBecause(81 /* CommandResult.MergeInFilter */)) {
17451
+ env.raiseError(AddFilterInteractiveContent.mergeInFilter);
17452
+ }
17453
+ else if (result.isCancelledBecause(82 /* CommandResult.NonContinuousTargets */)) {
17454
+ env.raiseError(AddFilterInteractiveContent.nonContinuousTargets);
17455
+ }
17456
+ }
17457
+
16596
17458
  const sortRange = {
16597
17459
  name: _lt("Sort range"),
16598
17460
  isVisible: IS_ONLY_ONE_RANGE,
@@ -16600,24 +17462,45 @@ const sortRange = {
16600
17462
  };
16601
17463
  const sortAscending = {
16602
17464
  name: _lt("Ascending (A ⟶ Z)"),
16603
- execute: SORT_CELLS_ASCENDING,
17465
+ execute: (env) => {
17466
+ const { anchor, zones } = env.model.getters.getSelection();
17467
+ const sheetId = env.model.getters.getActiveSheetId();
17468
+ interactiveSortSelection(env, sheetId, anchor.cell, zones[0], "ascending");
17469
+ },
16604
17470
  icon: "o-spreadsheet-Icon.SORT_ASCENDING",
16605
17471
  };
16606
17472
  const sortDescending = {
16607
17473
  name: _lt("Descending (Z ⟶ A)"),
16608
- execute: SORT_CELLS_DESCENDING,
17474
+ execute: (env) => {
17475
+ const { anchor, zones } = env.model.getters.getSelection();
17476
+ const sheetId = env.model.getters.getActiveSheetId();
17477
+ interactiveSortSelection(env, sheetId, anchor.cell, zones[0], "descending");
17478
+ },
16609
17479
  icon: "o-spreadsheet-Icon.SORT_DESCENDING",
16610
17480
  };
16611
17481
  const addDataFilter = {
16612
17482
  name: _lt("Create filter"),
16613
- execute: FILTERS_CREATE_FILTER_TABLE,
17483
+ execute: (env) => {
17484
+ const sheetId = env.model.getters.getActiveSheetId();
17485
+ const selection = env.model.getters.getSelection().zones;
17486
+ interactiveAddFilter(env, sheetId, selection);
17487
+ },
16614
17488
  isVisible: (env) => !SELECTION_CONTAINS_FILTER(env),
16615
- isEnabled: (env) => SELECTION_IS_CONTINUOUS(env),
17489
+ isEnabled: (env) => {
17490
+ const selectedZones = env.model.getters.getSelectedZones();
17491
+ return areZonesContinuous(...selectedZones);
17492
+ },
16616
17493
  icon: "o-spreadsheet-Icon.MENU_FILTER_ICON",
16617
17494
  };
16618
17495
  const removeDataFilter = {
16619
17496
  name: _lt("Remove filter"),
16620
- execute: FILTERS_REMOVE_FILTER_TABLE,
17497
+ execute: (env) => {
17498
+ const sheetId = env.model.getters.getActiveSheetId();
17499
+ env.model.dispatch("REMOVE_FILTER_TABLE", {
17500
+ sheetId,
17501
+ target: env.model.getters.getSelectedZones(),
17502
+ });
17503
+ },
16621
17504
  isVisible: SELECTION_CONTAINS_FILTER,
16622
17505
  icon: "o-spreadsheet-Icon.MENU_FILTER_ICON",
16623
17506
  };
@@ -16631,13 +17514,13 @@ const splitToColumns = {
16631
17514
 
16632
17515
  const formatNumberAutomatic = {
16633
17516
  name: _lt("Automatic"),
16634
- execute: FORMAT_AUTOMATIC_ACTION,
17517
+ execute: (env) => setFormatter(env, ""),
16635
17518
  isActive: (env) => isAutomaticFormatSelected(env),
16636
17519
  };
16637
17520
  const formatNumberNumber = {
16638
17521
  name: _lt("Number"),
16639
17522
  description: "1,000.12",
16640
- execute: FORMAT_NUMBER_ACTION,
17523
+ execute: (env) => setFormatter(env, "#,##0.00"),
16641
17524
  isActive: (env) => isFormatSelected(env, "#,##0.00"),
16642
17525
  };
16643
17526
  const formatPercent = {
@@ -16654,42 +17537,42 @@ const formatNumberPercent = {
16654
17537
  const formatNumberCurrency = {
16655
17538
  name: _lt("Currency"),
16656
17539
  description: "$1,000.12",
16657
- execute: FORMAT_CURRENCY_ACTION,
17540
+ execute: (env) => setFormatter(env, "[$$]#,##0.00"),
16658
17541
  isActive: (env) => isFormatSelected(env, "[$$]#,##0.00"),
16659
17542
  };
16660
17543
  const formatNumberCurrencyRounded = {
16661
17544
  name: _lt("Currency rounded"),
16662
17545
  description: "$1,000",
16663
- execute: FORMAT_CURRENCY_ROUNDED_ACTION,
17546
+ execute: (env) => setFormatter(env, "[$$]#,##0"),
16664
17547
  isActive: (env) => isFormatSelected(env, "[$$]#,##0"),
16665
17548
  };
16666
17549
  const formatCustomCurrency = {
16667
17550
  name: _lt("Custom currency"),
16668
17551
  isVisible: (env) => env.loadCurrencies !== undefined,
16669
- execute: OPEN_CUSTOM_CURRENCY_SIDEPANEL_ACTION,
17552
+ execute: (env) => env.openSidePanel("CustomCurrency", {}),
16670
17553
  };
16671
17554
  const formatNumberDate = {
16672
17555
  name: _lt("Date"),
16673
17556
  description: "9/26/2008",
16674
- execute: FORMAT_DATE_ACTION,
17557
+ execute: (env) => setFormatter(env, "m/d/yyyy"),
16675
17558
  isActive: (env) => isFormatSelected(env, "m/d/yyyy"),
16676
17559
  };
16677
17560
  const formatNumberTime = {
16678
17561
  name: _lt("Time"),
16679
17562
  description: "10:43:00 PM",
16680
- execute: FORMAT_TIME_ACTION,
17563
+ execute: (env) => setFormatter(env, "hh:mm:ss a"),
16681
17564
  isActive: (env) => isFormatSelected(env, "hh:mm:ss a"),
16682
17565
  };
16683
17566
  const formatNumberDateTime = {
16684
17567
  name: _lt("Date time"),
16685
17568
  description: "9/26/2008 22:43:00",
16686
- execute: FORMAT_DATE_TIME_ACTION,
17569
+ execute: (env) => setFormatter(env, "m/d/yyyy hh:mm:ss"),
16687
17570
  isActive: (env) => isFormatSelected(env, "m/d/yyyy hh:mm:ss"),
16688
17571
  };
16689
17572
  const formatNumberDuration = {
16690
17573
  name: _lt("Duration"),
16691
17574
  description: "27:51:38",
16692
- execute: FORMAT_DURATION_ACTION,
17575
+ execute: (env) => setFormatter(env, "hhhh:mm:ss"),
16693
17576
  isActive: (env) => isFormatSelected(env, "hhhh:mm:ss"),
16694
17577
  };
16695
17578
  const incraseDecimalPlaces = {
@@ -16713,27 +17596,27 @@ const decraseDecimalPlaces = {
16713
17596
  const formatBold = {
16714
17597
  name: _lt("Bold"),
16715
17598
  description: "Ctrl+B",
16716
- execute: FORMAT_BOLD_ACTION,
17599
+ execute: (env) => setStyle(env, { bold: !env.model.getters.getCurrentStyle().bold }),
16717
17600
  icon: "o-spreadsheet-Icon.BOLD",
16718
17601
  isActive: (env) => !!env.model.getters.getCurrentStyle().bold,
16719
17602
  };
16720
17603
  const formatItalic = {
16721
17604
  name: _lt("Italic"),
16722
17605
  description: "Ctrl+I",
16723
- execute: FORMAT_ITALIC_ACTION,
17606
+ execute: (env) => setStyle(env, { italic: !env.model.getters.getCurrentStyle().italic }),
16724
17607
  icon: "o-spreadsheet-Icon.ITALIC",
16725
17608
  isActive: (env) => !!env.model.getters.getCurrentStyle().italic,
16726
17609
  };
16727
17610
  const formatUnderline = {
16728
17611
  name: _lt("Underline"),
16729
17612
  description: "Ctrl+U",
16730
- execute: FORMAT_UNDERLINE_ACTION,
17613
+ execute: (env) => setStyle(env, { underline: !env.model.getters.getCurrentStyle().underline }),
16731
17614
  icon: "o-spreadsheet-Icon.UNDERLINE",
16732
17615
  isActive: (env) => !!env.model.getters.getCurrentStyle().underline,
16733
17616
  };
16734
17617
  const formatStrikethrough = {
16735
17618
  name: _lt("Strikethrough"),
16736
- execute: FORMAT_STRIKETHROUGH_ACTION,
17619
+ execute: (env) => setStyle(env, { strikethrough: !env.model.getters.getCurrentStyle().strikethrough }),
16737
17620
  icon: "o-spreadsheet-Icon.STRIKE",
16738
17621
  isActive: (env) => !!env.model.getters.getCurrentStyle().strikethrough,
16739
17622
  };
@@ -16839,7 +17722,10 @@ const paintFormat = {
16839
17722
  const clearFormat = {
16840
17723
  name: _lt("Clear formatting"),
16841
17724
  description: "Ctrl+<",
16842
- execute: FORMAT_CLEARFORMAT_ACTION,
17725
+ execute: (env) => env.model.dispatch("CLEAR_FORMATTING", {
17726
+ sheetId: env.model.getters.getActiveSheetId(),
17727
+ target: env.model.getters.getSelectedZones(),
17728
+ }),
16843
17729
  icon: "o-spreadsheet-Icon.CLEAR_FORMAT",
16844
17730
  };
16845
17731
  function fontSizeMenuBuilder() {
@@ -16918,20 +17804,34 @@ function interactiveFreezeColumnsRows(env, dimension, base) {
16918
17804
  const sheetId = env.model.getters.getActiveSheetId();
16919
17805
  const cmd = dimension === "COL" ? "FREEZE_COLUMNS" : "FREEZE_ROWS";
16920
17806
  const result = env.model.dispatch(cmd, { sheetId, quantity: base });
16921
- if (result.isCancelledBecause(65 /* CommandResult.MergeOverlap */)) {
17807
+ if (result.isCancelledBecause(66 /* CommandResult.MergeOverlap */)) {
16922
17808
  env.raiseError(MergeErrorMessage);
16923
17809
  }
16924
17810
  }
16925
17811
 
16926
17812
  const hideCols = {
16927
17813
  name: HIDE_COLUMNS_NAME,
16928
- execute: HIDE_COLUMNS_ACTION,
17814
+ execute: (env) => {
17815
+ const columns = env.model.getters.getElementsFromSelection("COL");
17816
+ env.model.dispatch("HIDE_COLUMNS_ROWS", {
17817
+ sheetId: env.model.getters.getActiveSheetId(),
17818
+ dimension: "COL",
17819
+ elements: columns,
17820
+ });
17821
+ },
16929
17822
  isVisible: NOT_ALL_VISIBLE_COLS_SELECTED,
16930
17823
  icon: "o-spreadsheet-Icon.HIDE_COL",
16931
17824
  };
16932
17825
  const unhideCols = {
16933
17826
  name: _lt("Unhide columns"),
16934
- execute: UNHIDE_COLUMNS_ACTION,
17827
+ execute: (env) => {
17828
+ const columns = env.model.getters.getElementsFromSelection("COL");
17829
+ env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
17830
+ sheetId: env.model.getters.getActiveSheetId(),
17831
+ dimension: "COL",
17832
+ elements: columns,
17833
+ });
17834
+ },
16935
17835
  isVisible: (env) => {
16936
17836
  const hiddenCols = env.model.getters
16937
17837
  .getHiddenColsGroups(env.model.getters.getActiveSheetId())
@@ -16942,18 +17842,39 @@ const unhideCols = {
16942
17842
  };
16943
17843
  const unhideAllCols = {
16944
17844
  name: _lt("Unhide all columns"),
16945
- execute: UNHIDE_ALL_COLUMNS_ACTION,
17845
+ execute: (env) => {
17846
+ const sheetId = env.model.getters.getActiveSheetId();
17847
+ env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
17848
+ sheetId,
17849
+ dimension: "COL",
17850
+ elements: Array.from(Array(env.model.getters.getNumberCols(sheetId)).keys()),
17851
+ });
17852
+ },
16946
17853
  isVisible: (env) => env.model.getters.getHiddenColsGroups(env.model.getters.getActiveSheetId()).length > 0,
16947
17854
  };
16948
17855
  const hideRows = {
16949
17856
  name: HIDE_ROWS_NAME,
16950
- execute: HIDE_ROWS_ACTION,
17857
+ execute: (env) => {
17858
+ const rows = env.model.getters.getElementsFromSelection("ROW");
17859
+ env.model.dispatch("HIDE_COLUMNS_ROWS", {
17860
+ sheetId: env.model.getters.getActiveSheetId(),
17861
+ dimension: "ROW",
17862
+ elements: rows,
17863
+ });
17864
+ },
16951
17865
  isVisible: NOT_ALL_VISIBLE_ROWS_SELECTED,
16952
17866
  icon: "o-spreadsheet-Icon.HIDE_ROW",
16953
17867
  };
16954
17868
  const unhideRows = {
16955
17869
  name: _lt("Unhide rows"),
16956
- execute: UNHIDE_ROWS_ACTION,
17870
+ execute: (env) => {
17871
+ const columns = env.model.getters.getElementsFromSelection("ROW");
17872
+ env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
17873
+ sheetId: env.model.getters.getActiveSheetId(),
17874
+ dimension: "ROW",
17875
+ elements: columns,
17876
+ });
17877
+ },
16957
17878
  isVisible: (env) => {
16958
17879
  const hiddenRows = env.model.getters
16959
17880
  .getHiddenRowsGroups(env.model.getters.getActiveSheetId())
@@ -16964,7 +17885,14 @@ const unhideRows = {
16964
17885
  };
16965
17886
  const unhideAllRows = {
16966
17887
  name: _lt("Unhide all rows"),
16967
- execute: UNHIDE_ALL_ROWS_ACTION,
17888
+ execute: (env) => {
17889
+ const sheetId = env.model.getters.getActiveSheetId();
17890
+ env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
17891
+ sheetId,
17892
+ dimension: "ROW",
17893
+ elements: Array.from(Array(env.model.getters.getNumberRows(sheetId)).keys()),
17894
+ });
17895
+ },
16968
17896
  isVisible: (env) => env.model.getters.getHiddenRowsGroups(env.model.getters.getActiveSheetId()).length > 0,
16969
17897
  };
16970
17898
  const unFreezePane = {
@@ -17038,12 +17966,18 @@ const viewGridlines = {
17038
17966
  name: (env) => env.model.getters.getGridLinesVisibility(env.model.getters.getActiveSheetId())
17039
17967
  ? _lt("Hide gridlines")
17040
17968
  : _lt("Show gridlines"),
17041
- execute: SET_GRID_LINES_VISIBILITY_ACTION,
17969
+ execute: (env) => {
17970
+ const sheetId = env.model.getters.getActiveSheetId();
17971
+ env.model.dispatch("SET_GRID_LINES_VISIBILITY", {
17972
+ sheetId,
17973
+ areGridLinesVisible: !env.model.getters.getGridLinesVisibility(sheetId),
17974
+ });
17975
+ },
17042
17976
  icon: "o-spreadsheet-Icon.SHOW_HIDE_GRID",
17043
17977
  };
17044
17978
  const viewFormulas = {
17045
17979
  name: (env) => env.model.getters.shouldShowFormulas() ? _lt("Hide formulas") : _lt("Show formulas"),
17046
- execute: SET_FORMULA_VISIBILITY_ACTION,
17980
+ execute: (env) => env.model.dispatch("SET_FORMULA_VISIBILITY", { show: !env.model.getters.shouldShowFormulas() }),
17047
17981
  isReadonlyAllowed: true,
17048
17982
  icon: "o-spreadsheet-Icon.SHOW_HIDE_FORMULA",
17049
17983
  };
@@ -18007,10 +18941,10 @@ class LineBarPieConfigPanel extends Component {
18007
18941
  return cancelledReasons.map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
18008
18942
  }
18009
18943
  get isDatasetInvalid() {
18010
- return !!this.state.datasetDispatchResult?.isCancelledBecause(32 /* CommandResult.InvalidDataSet */);
18944
+ return !!this.state.datasetDispatchResult?.isCancelledBecause(33 /* CommandResult.InvalidDataSet */);
18011
18945
  }
18012
18946
  get isLabelInvalid() {
18013
- return !!this.state.labelsDispatchResult?.isCancelledBecause(33 /* CommandResult.InvalidLabelRange */);
18947
+ return !!this.state.labelsDispatchResult?.isCancelledBecause(34 /* CommandResult.InvalidLabelRange */);
18014
18948
  }
18015
18949
  onUpdateDataSetsHaveTitle(ev) {
18016
18950
  this.props.updateChart(this.props.figureId, {
@@ -18641,12 +19575,14 @@ class LineBarPieDesignPanel extends Component {
18641
19575
  static template = "o-spreadsheet-LineBarPieDesignPanel";
18642
19576
  static components = { ColorPickerWidget };
18643
19577
  state = useState({
19578
+ title: "",
18644
19579
  fillColorTool: false,
18645
19580
  });
18646
19581
  onClick(ev) {
18647
19582
  this.state.fillColorTool = false;
18648
19583
  }
18649
19584
  setup() {
19585
+ this.state.title = _t(this.props.definition.title);
18650
19586
  useExternalListener(window, "click", this.onClick);
18651
19587
  }
18652
19588
  toggleColorPicker() {
@@ -18657,9 +19593,9 @@ class LineBarPieDesignPanel extends Component {
18657
19593
  background: color,
18658
19594
  });
18659
19595
  }
18660
- updateTitle(ev) {
19596
+ updateTitle() {
18661
19597
  this.props.updateChart(this.props.figureId, {
18662
- title: ev.target.value,
19598
+ title: this.state.title,
18663
19599
  });
18664
19600
  }
18665
19601
  updateSelect(attr, ev) {
@@ -18691,7 +19627,7 @@ class GaugeChartConfigPanel extends Component {
18691
19627
  return cancelledReasons.map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
18692
19628
  }
18693
19629
  get isDataRangeInvalid() {
18694
- return !!this.state.dataRangeDispatchResult?.isCancelledBecause(36 /* CommandResult.InvalidGaugeDataRange */);
19630
+ return !!this.state.dataRangeDispatchResult?.isCancelledBecause(37 /* CommandResult.InvalidGaugeDataRange */);
18695
19631
  }
18696
19632
  onDataRangeChanged(ranges) {
18697
19633
  this.dataRange = ranges[0];
@@ -18750,11 +19686,13 @@ class GaugeChartDesignPanel extends Component {
18750
19686
  static template = "o-spreadsheet-GaugeChartDesignPanel";
18751
19687
  static components = { ColorPickerWidget, SidePanelErrors };
18752
19688
  state = useState({
19689
+ title: "",
18753
19690
  openedMenu: undefined,
18754
19691
  sectionRuleDispatchResult: undefined,
18755
19692
  sectionRule: deepCopy(this.props.definition.sectionRule),
18756
19693
  });
18757
19694
  setup() {
19695
+ this.state.title = _t(this.props.definition.title);
18758
19696
  useExternalListener(window, "click", this.closeMenus);
18759
19697
  }
18760
19698
  get designErrorMessages() {
@@ -18767,31 +19705,31 @@ class GaugeChartDesignPanel extends Component {
18767
19705
  background: color,
18768
19706
  });
18769
19707
  }
18770
- updateTitle(ev) {
19708
+ updateTitle() {
18771
19709
  this.props.updateChart(this.props.figureId, {
18772
- title: ev.target.value,
19710
+ title: this.state.title,
18773
19711
  });
18774
19712
  }
18775
19713
  isRangeMinInvalid() {
18776
- return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(37 /* CommandResult.EmptyGaugeRangeMin */) ||
18777
- this.state.sectionRuleDispatchResult?.isCancelledBecause(38 /* CommandResult.GaugeRangeMinNaN */) ||
18778
- this.state.sectionRuleDispatchResult?.isCancelledBecause(41 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */));
19714
+ return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(38 /* CommandResult.EmptyGaugeRangeMin */) ||
19715
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(39 /* CommandResult.GaugeRangeMinNaN */) ||
19716
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(42 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */));
18779
19717
  }
18780
19718
  isRangeMaxInvalid() {
18781
- return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(39 /* CommandResult.EmptyGaugeRangeMax */) ||
18782
- this.state.sectionRuleDispatchResult?.isCancelledBecause(40 /* CommandResult.GaugeRangeMaxNaN */) ||
18783
- this.state.sectionRuleDispatchResult?.isCancelledBecause(41 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */));
19719
+ return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(40 /* CommandResult.EmptyGaugeRangeMax */) ||
19720
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(41 /* CommandResult.GaugeRangeMaxNaN */) ||
19721
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(42 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */));
18784
19722
  }
18785
19723
  // ---------------------------------------------------------------------------
18786
19724
  // COLOR_SECTION_TEMPLATE
18787
19725
  // ---------------------------------------------------------------------------
18788
19726
  get isLowerInflectionPointInvalid() {
18789
- return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(42 /* CommandResult.GaugeLowerInflectionPointNaN */) ||
18790
- this.state.sectionRuleDispatchResult?.isCancelledBecause(44 /* CommandResult.GaugeLowerBiggerThanUpper */));
19727
+ return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(43 /* CommandResult.GaugeLowerInflectionPointNaN */) ||
19728
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(45 /* CommandResult.GaugeLowerBiggerThanUpper */));
18791
19729
  }
18792
19730
  get isUpperInflectionPointInvalid() {
18793
- return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(43 /* CommandResult.GaugeUpperInflectionPointNaN */) ||
18794
- this.state.sectionRuleDispatchResult?.isCancelledBecause(44 /* CommandResult.GaugeLowerBiggerThanUpper */));
19731
+ return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(44 /* CommandResult.GaugeUpperInflectionPointNaN */) ||
19732
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(45 /* CommandResult.GaugeLowerBiggerThanUpper */));
18795
19733
  }
18796
19734
  updateSectionColor(target, color) {
18797
19735
  const sectionRule = deepCopy(this.state.sectionRule);
@@ -18874,10 +19812,10 @@ class ScorecardChartConfigPanel extends Component {
18874
19812
  return cancelledReasons.map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
18875
19813
  }
18876
19814
  get isKeyValueInvalid() {
18877
- return !!this.state.keyValueDispatchResult?.isCancelledBecause(34 /* CommandResult.InvalidScorecardKeyValue */);
19815
+ return !!this.state.keyValueDispatchResult?.isCancelledBecause(35 /* CommandResult.InvalidScorecardKeyValue */);
18878
19816
  }
18879
19817
  get isBaselineInvalid() {
18880
- return !!this.state.keyValueDispatchResult?.isCancelledBecause(35 /* CommandResult.InvalidScorecardBaseline */);
19818
+ return !!this.state.keyValueDispatchResult?.isCancelledBecause(36 /* CommandResult.InvalidScorecardBaseline */);
18881
19819
  }
18882
19820
  onKeyValueRangeChanged(ranges) {
18883
19821
  this.keyValue = ranges[0];
@@ -18922,14 +19860,16 @@ class ScorecardChartDesignPanel extends Component {
18922
19860
  static template = "o-spreadsheet-ScorecardChartDesignPanel";
18923
19861
  static components = { ColorPickerWidget };
18924
19862
  state = useState({
19863
+ title: "",
18925
19864
  openedColorPicker: undefined,
18926
19865
  });
18927
19866
  setup() {
19867
+ this.state.title = _t(this.props.definition.title);
18928
19868
  useExternalListener(window, "click", this.closeMenus);
18929
19869
  }
18930
- updateTitle(ev) {
19870
+ updateTitle() {
18931
19871
  this.props.updateChart(this.props.figureId, {
18932
- title: ev.target.value,
19872
+ title: this.state.title,
18933
19873
  });
18934
19874
  }
18935
19875
  updateBaselineDescr(ev) {
@@ -19551,7 +20491,7 @@ class ConditionalFormattingPanel extends Component {
19551
20491
  return this.env.model.getters.getConditionalFormats(this.env.model.getters.getActiveSheetId());
19552
20492
  }
19553
20493
  get isRangeValid() {
19554
- return this.state.errors.includes(24 /* CommandResult.EmptyRange */);
20494
+ return this.state.errors.includes(25 /* CommandResult.EmptyRange */);
19555
20495
  }
19556
20496
  errorMessage(error) {
19557
20497
  return CfTerms.Errors[error] || CfTerms.Errors.Unexpected;
@@ -19610,7 +20550,7 @@ class ConditionalFormattingPanel extends Component {
19610
20550
  if (this.state.currentCF) {
19611
20551
  const invalidRanges = this.state.currentCF.ranges.some((xc) => !xc.match(rangeReference));
19612
20552
  if (invalidRanges) {
19613
- this.state.errors = [25 /* CommandResult.InvalidRange */];
20553
+ this.state.errors = [26 /* CommandResult.InvalidRange */];
19614
20554
  return;
19615
20555
  }
19616
20556
  const sheetId = this.env.model.getters.getActiveSheetId();
@@ -19765,10 +20705,10 @@ class ConditionalFormattingPanel extends Component {
19765
20705
  * Cell Is Rule
19766
20706
  ****************************************************************************/
19767
20707
  get isValue1Invalid() {
19768
- return !!this.state.errors?.includes(51 /* CommandResult.FirstArgMissing */);
20708
+ return !!this.state.errors?.includes(52 /* CommandResult.FirstArgMissing */);
19769
20709
  }
19770
20710
  get isValue2Invalid() {
19771
- return !!this.state.errors?.includes(52 /* CommandResult.SecondArgMissing */);
20711
+ return !!this.state.errors?.includes(53 /* CommandResult.SecondArgMissing */);
19772
20712
  }
19773
20713
  toggleStyle(tool) {
19774
20714
  const style = this.state.rules.cellIs.style;
@@ -19785,17 +20725,17 @@ class ConditionalFormattingPanel extends Component {
19785
20725
  isValueInvalid(threshold) {
19786
20726
  switch (threshold) {
19787
20727
  case "minimum":
19788
- return (this.state.errors.includes(58 /* CommandResult.MinInvalidFormula */) ||
19789
- this.state.errors.includes(50 /* CommandResult.MinBiggerThanMid */) ||
19790
- this.state.errors.includes(47 /* CommandResult.MinBiggerThanMax */) ||
19791
- this.state.errors.includes(53 /* CommandResult.MinNaN */));
20728
+ return (this.state.errors.includes(59 /* CommandResult.MinInvalidFormula */) ||
20729
+ this.state.errors.includes(51 /* CommandResult.MinBiggerThanMid */) ||
20730
+ this.state.errors.includes(48 /* CommandResult.MinBiggerThanMax */) ||
20731
+ this.state.errors.includes(54 /* CommandResult.MinNaN */));
19792
20732
  case "midpoint":
19793
- return (this.state.errors.includes(59 /* CommandResult.MidInvalidFormula */) ||
19794
- this.state.errors.includes(54 /* CommandResult.MidNaN */) ||
19795
- this.state.errors.includes(49 /* CommandResult.MidBiggerThanMax */));
20733
+ return (this.state.errors.includes(60 /* CommandResult.MidInvalidFormula */) ||
20734
+ this.state.errors.includes(55 /* CommandResult.MidNaN */) ||
20735
+ this.state.errors.includes(50 /* CommandResult.MidBiggerThanMax */));
19796
20736
  case "maximum":
19797
- return (this.state.errors.includes(60 /* CommandResult.MaxInvalidFormula */) ||
19798
- this.state.errors.includes(55 /* CommandResult.MaxNaN */));
20737
+ return (this.state.errors.includes(61 /* CommandResult.MaxInvalidFormula */) ||
20738
+ this.state.errors.includes(56 /* CommandResult.MaxNaN */));
19799
20739
  default:
19800
20740
  return false;
19801
20741
  }
@@ -19843,13 +20783,13 @@ class ConditionalFormattingPanel extends Component {
19843
20783
  isInflectionPointInvalid(inflectionPoint) {
19844
20784
  switch (inflectionPoint) {
19845
20785
  case "lowerInflectionPoint":
19846
- return (this.state.errors.includes(57 /* CommandResult.ValueLowerInflectionNaN */) ||
19847
- this.state.errors.includes(62 /* CommandResult.ValueLowerInvalidFormula */) ||
19848
- this.state.errors.includes(48 /* CommandResult.LowerBiggerThanUpper */));
20786
+ return (this.state.errors.includes(58 /* CommandResult.ValueLowerInflectionNaN */) ||
20787
+ this.state.errors.includes(63 /* CommandResult.ValueLowerInvalidFormula */) ||
20788
+ this.state.errors.includes(49 /* CommandResult.LowerBiggerThanUpper */));
19849
20789
  case "upperInflectionPoint":
19850
- return (this.state.errors.includes(56 /* CommandResult.ValueUpperInflectionNaN */) ||
19851
- this.state.errors.includes(61 /* CommandResult.ValueUpperInvalidFormula */) ||
19852
- this.state.errors.includes(48 /* CommandResult.LowerBiggerThanUpper */));
20790
+ return (this.state.errors.includes(57 /* CommandResult.ValueUpperInflectionNaN */) ||
20791
+ this.state.errors.includes(62 /* CommandResult.ValueUpperInvalidFormula */) ||
20792
+ this.state.errors.includes(49 /* CommandResult.LowerBiggerThanUpper */));
19853
20793
  default:
19854
20794
  return true;
19855
20795
  }
@@ -20159,7 +21099,7 @@ const SplitToColumnsInteractiveContent = {
20159
21099
  };
20160
21100
  function interactiveSplitToColumns(env, separator, addNewColumns) {
20161
21101
  let result = env.model.dispatch("SPLIT_TEXT_INTO_COLUMNS", { separator, addNewColumns });
20162
- if (result.isCancelledBecause(90 /* CommandResult.SplitWillOverwriteContent */)) {
21102
+ if (result.isCancelledBecause(91 /* CommandResult.SplitWillOverwriteContent */)) {
20163
21103
  env.askConfirmation(SplitToColumnsInteractiveContent.SplitIsDestructive, () => {
20164
21104
  result = env.model.dispatch("SPLIT_TEXT_INTO_COLUMNS", {
20165
21105
  separator,
@@ -20223,8 +21163,8 @@ class SplitIntoColumnsPanel extends Component {
20223
21163
  const errors = new Set();
20224
21164
  for (const reason of cancelledReasons) {
20225
21165
  switch (reason) {
20226
- case 90 /* CommandResult.SplitWillOverwriteContent */:
20227
- case 89 /* CommandResult.EmptySplitSeparator */:
21166
+ case 91 /* CommandResult.SplitWillOverwriteContent */:
21167
+ case 90 /* CommandResult.EmptySplitSeparator */:
20228
21168
  break;
20229
21169
  default:
20230
21170
  errors.add(SplitToColumnsTerms.Errors[reason] || SplitToColumnsTerms.Errors.Unexpected);
@@ -20239,8 +21179,8 @@ class SplitIntoColumnsPanel extends Component {
20239
21179
  addNewColumns: this.state.addNewColumns,
20240
21180
  force: false,
20241
21181
  }).reasons;
20242
- if (cancelledReasons.includes(90 /* CommandResult.SplitWillOverwriteContent */)) {
20243
- warnings.push(SplitToColumnsTerms.Errors[90 /* CommandResult.SplitWillOverwriteContent */]);
21182
+ if (cancelledReasons.includes(91 /* CommandResult.SplitWillOverwriteContent */)) {
21183
+ warnings.push(SplitToColumnsTerms.Errors[91 /* CommandResult.SplitWillOverwriteContent */]);
20244
21184
  }
20245
21185
  return warnings;
20246
21186
  }
@@ -20893,6 +21833,13 @@ class ContentEditableHelper {
20893
21833
  const element = focusedNode instanceof HTMLElement ? focusedNode : focusedNode.parentElement;
20894
21834
  element?.scrollIntoView({ block: "nearest" });
20895
21835
  }
21836
+ /**
21837
+ * remove the current selection of the user
21838
+ * */
21839
+ removeSelection() {
21840
+ let selection = window.getSelection();
21841
+ selection.removeAllRanges();
21842
+ }
20896
21843
  removeAll() {
20897
21844
  if (this.el) {
20898
21845
  while (this.el.firstChild) {
@@ -21379,6 +22326,21 @@ class Composer extends Component {
21379
22326
  this.autoCompleteState.values = values.slice(0, 10);
21380
22327
  this.autoCompleteState.selectedIndex = 0;
21381
22328
  }
22329
+ /**
22330
+ * This is required to ensure the content helper selection is
22331
+ * properly updated on "onclick" events. Depending on the browser,
22332
+ * the callback onClick from the composer will be executed before
22333
+ * the selection was updated in the dom, which means we capture an
22334
+ * wrong selection which is then forced upon the content helper on
22335
+ * patchContent.
22336
+ */
22337
+ onMousedown(ev) {
22338
+ if (ev.button > 0) {
22339
+ // not main button, probably a context menu
22340
+ return;
22341
+ }
22342
+ this.contentHelper.removeSelection();
22343
+ }
21382
22344
  onClick() {
21383
22345
  if (this.env.model.getters.isReadonly()) {
21384
22346
  return;
@@ -21391,6 +22353,29 @@ class Composer extends Component {
21391
22353
  this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", newSelection);
21392
22354
  this.processTokenAtCursor();
21393
22355
  }
22356
+ onDblClick() {
22357
+ if (this.env.model.getters.isReadonly()) {
22358
+ return;
22359
+ }
22360
+ const composerContent = this.env.model.getters.getCurrentContent();
22361
+ const isValidFormula = composerContent.startsWith("=");
22362
+ if (isValidFormula) {
22363
+ const tokens = this.env.model.getters.getCurrentTokens();
22364
+ const currentSelection = this.contentHelper.getCurrentSelection();
22365
+ if (currentSelection.start === currentSelection.end)
22366
+ return;
22367
+ const currentSelectedText = composerContent.substring(currentSelection.start, currentSelection.end);
22368
+ const token = tokens.filter((token) => token.value.includes(currentSelectedText) &&
22369
+ token.start <= currentSelection.start &&
22370
+ token.end >= currentSelection.end)[0];
22371
+ if (token.type === "REFERENCE") {
22372
+ this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", {
22373
+ start: token.start,
22374
+ end: token.end,
22375
+ });
22376
+ }
22377
+ }
22378
+ }
21394
22379
  // ---------------------------------------------------------------------------
21395
22380
  // Private
21396
22381
  // ---------------------------------------------------------------------------
@@ -21419,7 +22404,7 @@ class Composer extends Component {
21419
22404
  */
21420
22405
  getContentLines() {
21421
22406
  let value = this.env.model.getters.getCurrentContent();
21422
- const isValidFormula = value.startsWith("=") && this.env.model.getters.getCurrentTokens().length > 0;
22407
+ const isValidFormula = value.startsWith("=");
21423
22408
  if (value === "") {
21424
22409
  return [];
21425
22410
  }
@@ -24128,7 +25113,7 @@ class Grid extends Component {
24128
25113
  }
24129
25114
  ev.preventDefault();
24130
25115
  }
24131
- paste(ev) {
25116
+ async paste(ev) {
24132
25117
  if (!this.gridEl.contains(document.activeElement)) {
24133
25118
  return;
24134
25119
  }
@@ -24148,6 +25133,9 @@ class Grid extends Component {
24148
25133
  else {
24149
25134
  interactivePasteFromOS(this.env, target, content);
24150
25135
  }
25136
+ if (this.env.model.getters.isCutOperation()) {
25137
+ await this.env.clipboard.write({ [ClipboardMIMEType.PlainText]: "" });
25138
+ }
24151
25139
  }
24152
25140
  }
24153
25141
  displayWarningCopyPasteNotSupported() {
@@ -30087,9 +31075,9 @@ class CellPlugin extends CorePlugin {
30087
31075
  checkCellOutOfSheet(sheetId, col, row) {
30088
31076
  const sheet = this.getters.tryGetSheet(sheetId);
30089
31077
  if (!sheet)
30090
- return 27 /* CommandResult.InvalidSheetId */;
31078
+ return 28 /* CommandResult.InvalidSheetId */;
30091
31079
  const sheetZone = this.getters.getSheetZone(sheetId);
30092
- return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
31080
+ return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 19 /* CommandResult.TargetOutOfSheet */;
30093
31081
  }
30094
31082
  }
30095
31083
  class FormulaCellWithDependencies {
@@ -30312,13 +31300,13 @@ class ChartPlugin extends CorePlugin {
30312
31300
  }
30313
31301
  checkChartDuplicate(cmd) {
30314
31302
  return this.getters.getFigureSheetId(cmd.id)
30315
- ? 84 /* CommandResult.DuplicatedChartId */
31303
+ ? 85 /* CommandResult.DuplicatedChartId */
30316
31304
  : 0 /* CommandResult.Success */;
30317
31305
  }
30318
31306
  checkChartExists(cmd) {
30319
31307
  return this.getters.getFigureSheetId(cmd.id)
30320
31308
  ? 0 /* CommandResult.Success */
30321
- : 85 /* CommandResult.ChartDoesNotExist */;
31309
+ : 86 /* CommandResult.ChartDoesNotExist */;
30322
31310
  }
30323
31311
  }
30324
31312
 
@@ -30527,18 +31515,18 @@ class ConditionalFormatPlugin extends CorePlugin {
30527
31515
  }
30528
31516
  checkValidReordering(cfId, direction, sheetId) {
30529
31517
  if (!this.cfRules[sheetId])
30530
- return 27 /* CommandResult.InvalidSheetId */;
31518
+ return 28 /* CommandResult.InvalidSheetId */;
30531
31519
  const ruleIndex = this.cfRules[sheetId].findIndex((cf) => cf.id === cfId);
30532
31520
  if (ruleIndex === -1)
30533
- return 71 /* CommandResult.InvalidConditionalFormatId */;
31521
+ return 72 /* CommandResult.InvalidConditionalFormatId */;
30534
31522
  const cfIndex2 = direction === "up" ? ruleIndex - 1 : ruleIndex + 1;
30535
31523
  if (cfIndex2 < 0 || cfIndex2 >= this.cfRules[sheetId].length) {
30536
- return 71 /* CommandResult.InvalidConditionalFormatId */;
31524
+ return 72 /* CommandResult.InvalidConditionalFormatId */;
30537
31525
  }
30538
31526
  return 0 /* CommandResult.Success */;
30539
31527
  }
30540
31528
  checkEmptyRange(cmd) {
30541
- return cmd.ranges.length ? 0 /* CommandResult.Success */ : 24 /* CommandResult.EmptyRange */;
31529
+ return cmd.ranges.length ? 0 /* CommandResult.Success */ : 25 /* CommandResult.EmptyRange */;
30542
31530
  }
30543
31531
  checkCFRule(cmd) {
30544
31532
  const rule = cmd.cf.rule;
@@ -30574,10 +31562,10 @@ class ConditionalFormatPlugin extends CorePlugin {
30574
31562
  const errors = [];
30575
31563
  const isEmpty = (value) => value === undefined || value === "";
30576
31564
  if (expectedNumber >= 1 && isEmpty(rule.values[0])) {
30577
- errors.push(51 /* CommandResult.FirstArgMissing */);
31565
+ errors.push(52 /* CommandResult.FirstArgMissing */);
30578
31566
  }
30579
31567
  if (expectedNumber >= 2 && isEmpty(rule.values[1])) {
30580
- errors.push(52 /* CommandResult.SecondArgMissing */);
31568
+ errors.push(53 /* CommandResult.SecondArgMissing */);
30581
31569
  }
30582
31570
  return errors.length ? errors : 0 /* CommandResult.Success */;
30583
31571
  }
@@ -30589,15 +31577,15 @@ class ConditionalFormatPlugin extends CorePlugin {
30589
31577
  (threshold.value === "" || isNaN(threshold.value))) {
30590
31578
  switch (thresholdName) {
30591
31579
  case "min":
30592
- return 53 /* CommandResult.MinNaN */;
31580
+ return 54 /* CommandResult.MinNaN */;
30593
31581
  case "max":
30594
- return 55 /* CommandResult.MaxNaN */;
31582
+ return 56 /* CommandResult.MaxNaN */;
30595
31583
  case "mid":
30596
- return 54 /* CommandResult.MidNaN */;
31584
+ return 55 /* CommandResult.MidNaN */;
30597
31585
  case "upperInflectionPoint":
30598
- return 56 /* CommandResult.ValueUpperInflectionNaN */;
31586
+ return 57 /* CommandResult.ValueUpperInflectionNaN */;
30599
31587
  case "lowerInflectionPoint":
30600
- return 57 /* CommandResult.ValueLowerInflectionNaN */;
31588
+ return 58 /* CommandResult.ValueLowerInflectionNaN */;
30601
31589
  }
30602
31590
  }
30603
31591
  return 0 /* CommandResult.Success */;
@@ -30611,15 +31599,15 @@ class ConditionalFormatPlugin extends CorePlugin {
30611
31599
  catch (error) {
30612
31600
  switch (thresholdName) {
30613
31601
  case "min":
30614
- return 58 /* CommandResult.MinInvalidFormula */;
31602
+ return 59 /* CommandResult.MinInvalidFormula */;
30615
31603
  case "max":
30616
- return 60 /* CommandResult.MaxInvalidFormula */;
31604
+ return 61 /* CommandResult.MaxInvalidFormula */;
30617
31605
  case "mid":
30618
- return 59 /* CommandResult.MidInvalidFormula */;
31606
+ return 60 /* CommandResult.MidInvalidFormula */;
30619
31607
  case "upperInflectionPoint":
30620
- return 61 /* CommandResult.ValueUpperInvalidFormula */;
31608
+ return 62 /* CommandResult.ValueUpperInvalidFormula */;
30621
31609
  case "lowerInflectionPoint":
30622
- return 62 /* CommandResult.ValueLowerInvalidFormula */;
31610
+ return 63 /* CommandResult.ValueLowerInvalidFormula */;
30623
31611
  }
30624
31612
  }
30625
31613
  return 0 /* CommandResult.Success */;
@@ -30636,7 +31624,7 @@ class ConditionalFormatPlugin extends CorePlugin {
30636
31624
  if (["number", "percentage", "percentile"].includes(rule.lowerInflectionPoint.type) &&
30637
31625
  rule.lowerInflectionPoint.type === rule.upperInflectionPoint.type &&
30638
31626
  Number(minValue) > Number(maxValue)) {
30639
- return 48 /* CommandResult.LowerBiggerThanUpper */;
31627
+ return 49 /* CommandResult.LowerBiggerThanUpper */;
30640
31628
  }
30641
31629
  return 0 /* CommandResult.Success */;
30642
31630
  }
@@ -30646,7 +31634,7 @@ class ConditionalFormatPlugin extends CorePlugin {
30646
31634
  if (["number", "percentage", "percentile"].includes(rule.minimum.type) &&
30647
31635
  rule.minimum.type === rule.maximum.type &&
30648
31636
  stringToNumber(minValue) >= stringToNumber(maxValue)) {
30649
- return 47 /* CommandResult.MinBiggerThanMax */;
31637
+ return 48 /* CommandResult.MinBiggerThanMax */;
30650
31638
  }
30651
31639
  return 0 /* CommandResult.Success */;
30652
31640
  }
@@ -30657,7 +31645,7 @@ class ConditionalFormatPlugin extends CorePlugin {
30657
31645
  ["number", "percentage", "percentile"].includes(rule.midpoint.type) &&
30658
31646
  rule.midpoint.type === rule.maximum.type &&
30659
31647
  stringToNumber(midValue) >= stringToNumber(maxValue)) {
30660
- return 49 /* CommandResult.MidBiggerThanMax */;
31648
+ return 50 /* CommandResult.MidBiggerThanMax */;
30661
31649
  }
30662
31650
  return 0 /* CommandResult.Success */;
30663
31651
  }
@@ -30668,7 +31656,7 @@ class ConditionalFormatPlugin extends CorePlugin {
30668
31656
  ["number", "percentage", "percentile"].includes(rule.midpoint.type) &&
30669
31657
  rule.minimum.type === rule.midpoint.type &&
30670
31658
  stringToNumber(minValue) >= stringToNumber(midValue)) {
30671
- return 50 /* CommandResult.MinBiggerThanMid */;
31659
+ return 51 /* CommandResult.MinBiggerThanMid */;
30672
31660
  }
30673
31661
  return 0 /* CommandResult.Success */;
30674
31662
  }
@@ -30798,13 +31786,13 @@ class FigurePlugin extends CorePlugin {
30798
31786
  }
30799
31787
  checkFigureExists(sheetId, figureId) {
30800
31788
  if (this.figures[sheetId]?.[figureId] === undefined) {
30801
- return 70 /* CommandResult.FigureDoesNotExist */;
31789
+ return 71 /* CommandResult.FigureDoesNotExist */;
30802
31790
  }
30803
31791
  return 0 /* CommandResult.Success */;
30804
31792
  }
30805
31793
  checkFigureDuplicate(figureId) {
30806
31794
  if (Object.values(this.figures).find((sheet) => sheet?.[figureId])) {
30807
- return 82 /* CommandResult.DuplicatedFigureId */;
31795
+ return 83 /* CommandResult.DuplicatedFigureId */;
30808
31796
  }
30809
31797
  return 0 /* CommandResult.Success */;
30810
31798
  }
@@ -30916,12 +31904,12 @@ class FiltersPlugin extends CorePlugin {
30916
31904
  switch (cmd.type) {
30917
31905
  case "CREATE_FILTER_TABLE":
30918
31906
  if (!areZonesContinuous(...cmd.target)) {
30919
- return 81 /* CommandResult.NonContinuousTargets */;
31907
+ return 82 /* CommandResult.NonContinuousTargets */;
30920
31908
  }
30921
31909
  const zone = union(...cmd.target);
30922
31910
  const checkFilterOverlap = () => {
30923
31911
  if (this.getFilterTables(cmd.sheetId).some((filter) => overlap(filter.zone, zone))) {
30924
- return 78 /* CommandResult.FilterOverlap */;
31912
+ return 79 /* CommandResult.FilterOverlap */;
30925
31913
  }
30926
31914
  return 0 /* CommandResult.Success */;
30927
31915
  };
@@ -30929,7 +31917,7 @@ class FiltersPlugin extends CorePlugin {
30929
31917
  const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, zone);
30930
31918
  for (let merge of mergesInTarget) {
30931
31919
  if (overlap(zone, merge)) {
30932
- return 80 /* CommandResult.MergeInFilter */;
31920
+ return 81 /* CommandResult.MergeInFilter */;
30933
31921
  }
30934
31922
  }
30935
31923
  return 0 /* CommandResult.Success */;
@@ -30939,7 +31927,7 @@ class FiltersPlugin extends CorePlugin {
30939
31927
  for (let merge of cmd.target) {
30940
31928
  for (let filterTable of this.getFilterTables(cmd.sheetId)) {
30941
31929
  if (overlap(filterTable.zone, merge)) {
30942
- return 80 /* CommandResult.MergeInFilter */;
31930
+ return 81 /* CommandResult.MergeInFilter */;
30943
31931
  }
30944
31932
  }
30945
31933
  }
@@ -30958,7 +31946,14 @@ class FiltersPlugin extends CorePlugin {
30958
31946
  this.history.update("tables", filterTables);
30959
31947
  break;
30960
31948
  case "DUPLICATE_SHEET":
30961
- this.history.update("tables", cmd.sheetIdTo, deepCopy(this.tables[cmd.sheetId]));
31949
+ const tables = {};
31950
+ for (const filterTable of Object.values(this.tables[cmd.sheetId] || {})) {
31951
+ if (filterTable) {
31952
+ const newFilterTable = deepCopy(filterTable);
31953
+ tables[newFilterTable.id] = newFilterTable;
31954
+ }
31955
+ }
31956
+ this.history.update("tables", cmd.sheetIdTo, tables);
30962
31957
  break;
30963
31958
  case "ADD_COLUMNS_ROWS":
30964
31959
  this.onAddColumnsRows(cmd);
@@ -31410,7 +32405,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
31410
32405
  switch (cmd.type) {
31411
32406
  case "HIDE_COLUMNS_ROWS": {
31412
32407
  if (!this.getters.tryGetSheet(cmd.sheetId)) {
31413
- return 27 /* CommandResult.InvalidSheetId */;
32408
+ return 28 /* CommandResult.InvalidSheetId */;
31414
32409
  }
31415
32410
  const hiddenGroup = cmd.dimension === "COL"
31416
32411
  ? this.getHiddenColsGroups(cmd.sheetId)
@@ -31420,10 +32415,10 @@ class HeaderVisibilityPlugin extends CorePlugin {
31420
32415
  : this.getters.getNumberRows(cmd.sheetId);
31421
32416
  const hiddenElements = new Set((hiddenGroup || []).flat().concat(cmd.elements));
31422
32417
  if (hiddenElements.size >= elements) {
31423
- return 66 /* CommandResult.TooManyHiddenElements */;
32418
+ return 67 /* CommandResult.TooManyHiddenElements */;
31424
32419
  }
31425
32420
  else if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
31426
- return 86 /* CommandResult.InvalidHeaderIndex */;
32421
+ return 87 /* CommandResult.InvalidHeaderIndex */;
31427
32422
  }
31428
32423
  else {
31429
32424
  return 0 /* CommandResult.Success */;
@@ -31431,7 +32426,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
31431
32426
  }
31432
32427
  case "REMOVE_COLUMNS_ROWS":
31433
32428
  if (!this.getters.tryGetSheet(cmd.sheetId)) {
31434
- return 27 /* CommandResult.InvalidSheetId */;
32429
+ return 28 /* CommandResult.InvalidSheetId */;
31435
32430
  }
31436
32431
  if (!this.canRemoveHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
31437
32432
  return 8 /* CommandResult.NotEnoughElements */;
@@ -31599,7 +32594,7 @@ class ImagePlugin extends CorePlugin {
31599
32594
  switch (cmd.type) {
31600
32595
  case "CREATE_IMAGE":
31601
32596
  if (this.getters.getFigure(cmd.sheetId, cmd.figureId)) {
31602
- return 28 /* CommandResult.InvalidFigureId */;
32597
+ return 29 /* CommandResult.InvalidFigureId */;
31603
32598
  }
31604
32599
  return 0 /* CommandResult.Success */;
31605
32600
  default:
@@ -31987,7 +32982,7 @@ class MergePlugin extends CorePlugin {
31987
32982
  for (const zone of target) {
31988
32983
  for (const zone2 of target) {
31989
32984
  if (zone !== zone2 && overlap(zone, zone2)) {
31990
- return 65 /* CommandResult.MergeOverlap */;
32985
+ return 66 /* CommandResult.MergeOverlap */;
31991
32986
  }
31992
32987
  }
31993
32988
  }
@@ -32001,7 +32996,7 @@ class MergePlugin extends CorePlugin {
32001
32996
  for (const zone of target) {
32002
32997
  if ((zone.left < xSplit && zone.right >= xSplit) ||
32003
32998
  (zone.top < ySplit && zone.bottom >= ySplit)) {
32004
- return 75 /* CommandResult.FrozenPaneOverlap */;
32999
+ return 76 /* CommandResult.FrozenPaneOverlap */;
32005
33000
  }
32006
33001
  }
32007
33002
  return 0 /* CommandResult.Success */;
@@ -32195,7 +33190,7 @@ class RangeAdapter {
32195
33190
  // ---------------------------------------------------------------------------
32196
33191
  allowDispatch(cmd) {
32197
33192
  if (cmd.type === "MOVE_RANGES") {
32198
- return cmd.target.length === 1 ? 0 /* CommandResult.Success */ : 26 /* CommandResult.InvalidZones */;
33193
+ return cmd.target.length === 1 ? 0 /* CommandResult.Success */ : 27 /* CommandResult.InvalidZones */;
32199
33194
  }
32200
33195
  return 0 /* CommandResult.Success */;
32201
33196
  }
@@ -32620,7 +33615,7 @@ class SheetPlugin extends CorePlugin {
32620
33615
  return 0 /* CommandResult.Success */;
32621
33616
  }
32622
33617
  catch (e) {
32623
- return 14 /* CommandResult.WrongSheetMove */;
33618
+ return 15 /* CommandResult.WrongSheetMove */;
32624
33619
  }
32625
33620
  case "RENAME_SHEET":
32626
33621
  return this.isRenameAllowed(cmd);
@@ -32633,10 +33628,10 @@ class SheetPlugin extends CorePlugin {
32633
33628
  ? this.getNumberCols(cmd.sheetId)
32634
33629
  : this.getNumberRows(cmd.sheetId);
32635
33630
  if (cmd.base < 0 || cmd.base > elements) {
32636
- return 86 /* CommandResult.InvalidHeaderIndex */;
33631
+ return 87 /* CommandResult.InvalidHeaderIndex */;
32637
33632
  }
32638
33633
  else if (cmd.quantity <= 0) {
32639
- return 87 /* CommandResult.InvalidQuantity */;
33634
+ return 88 /* CommandResult.InvalidQuantity */;
32640
33635
  }
32641
33636
  return 0 /* CommandResult.Success */;
32642
33637
  case "REMOVE_COLUMNS_ROWS": {
@@ -32644,7 +33639,7 @@ class SheetPlugin extends CorePlugin {
32644
33639
  ? this.getNumberCols(cmd.sheetId)
32645
33640
  : this.getNumberRows(cmd.sheetId);
32646
33641
  if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
32647
- return 86 /* CommandResult.InvalidHeaderIndex */;
33642
+ return 87 /* CommandResult.InvalidHeaderIndex */;
32648
33643
  }
32649
33644
  else {
32650
33645
  return 0 /* CommandResult.Success */;
@@ -32971,12 +33966,12 @@ class SheetPlugin extends CorePlugin {
32971
33966
  */
32972
33967
  checkZonesExistInSheet(sheetId, zones) {
32973
33968
  if (!zones.every(isZoneValid))
32974
- return 25 /* CommandResult.InvalidRange */;
33969
+ return 26 /* CommandResult.InvalidRange */;
32975
33970
  if (zones.length) {
32976
33971
  const sheetZone = this.getSheetZone(sheetId);
32977
33972
  return zones.every((zone) => isZoneInside(zone, sheetZone))
32978
33973
  ? 0 /* CommandResult.Success */
32979
- : 18 /* CommandResult.TargetOutOfSheet */;
33974
+ : 19 /* CommandResult.TargetOutOfSheet */;
32980
33975
  }
32981
33976
  return 0 /* CommandResult.Success */;
32982
33977
  }
@@ -33083,38 +34078,42 @@ class SheetPlugin extends CorePlugin {
33083
34078
  throw new Error(_lt("There is not enough visible sheets"));
33084
34079
  }
33085
34080
  checkSheetName(cmd) {
34081
+ const originalSheetName = this.getters.tryGetSheetName(cmd.sheetId);
34082
+ if (originalSheetName !== undefined && cmd.name === originalSheetName) {
34083
+ return 11 /* CommandResult.UnchangedSheetName */;
34084
+ }
33086
34085
  const { orderedSheetIds, sheets } = this;
33087
34086
  const name = cmd.name && cmd.name.trim().toLowerCase();
33088
- if (orderedSheetIds.find((id) => sheets[id]?.name.toLowerCase() === name)) {
33089
- return 11 /* CommandResult.DuplicatedSheetName */;
34087
+ if (orderedSheetIds.find((id) => sheets[id]?.name.toLowerCase() === name && id !== cmd.sheetId)) {
34088
+ return 12 /* CommandResult.DuplicatedSheetName */;
33090
34089
  }
33091
34090
  if (FORBIDDEN_IN_EXCEL_REGEX.test(name)) {
33092
- return 13 /* CommandResult.ForbiddenCharactersInSheetName */;
34091
+ return 14 /* CommandResult.ForbiddenCharactersInSheetName */;
33093
34092
  }
33094
34093
  return 0 /* CommandResult.Success */;
33095
34094
  }
33096
34095
  checkSheetPosition(cmd) {
33097
34096
  const { orderedSheetIds } = this;
33098
34097
  if (cmd.position > orderedSheetIds.length || cmd.position < 0) {
33099
- return 15 /* CommandResult.WrongSheetPosition */;
34098
+ return 16 /* CommandResult.WrongSheetPosition */;
33100
34099
  }
33101
34100
  return 0 /* CommandResult.Success */;
33102
34101
  }
33103
34102
  checkRowFreezeQuantity(cmd) {
33104
34103
  return cmd.quantity >= 1 && cmd.quantity < this.getNumberRows(cmd.sheetId)
33105
34104
  ? 0 /* CommandResult.Success */
33106
- : 74 /* CommandResult.InvalidFreezeQuantity */;
34105
+ : 75 /* CommandResult.InvalidFreezeQuantity */;
33107
34106
  }
33108
34107
  checkColFreezeQuantity(cmd) {
33109
34108
  return cmd.quantity >= 1 && cmd.quantity < this.getNumberCols(cmd.sheetId)
33110
34109
  ? 0 /* CommandResult.Success */
33111
- : 74 /* CommandResult.InvalidFreezeQuantity */;
34110
+ : 75 /* CommandResult.InvalidFreezeQuantity */;
33112
34111
  }
33113
34112
  checkRowFreezeOverlapMerge(cmd) {
33114
34113
  const merges = this.getters.getMerges(cmd.sheetId);
33115
34114
  for (let merge of merges) {
33116
34115
  if (merge.top < cmd.quantity && cmd.quantity <= merge.bottom) {
33117
- return 65 /* CommandResult.MergeOverlap */;
34116
+ return 66 /* CommandResult.MergeOverlap */;
33118
34117
  }
33119
34118
  }
33120
34119
  return 0 /* CommandResult.Success */;
@@ -33123,7 +34122,7 @@ class SheetPlugin extends CorePlugin {
33123
34122
  const merges = this.getters.getMerges(cmd.sheetId);
33124
34123
  for (let merge of merges) {
33125
34124
  if (merge.left < cmd.quantity && cmd.quantity <= merge.right) {
33126
- return 65 /* CommandResult.MergeOverlap */;
34125
+ return 66 /* CommandResult.MergeOverlap */;
33127
34126
  }
33128
34127
  }
33129
34128
  return 0 /* CommandResult.Success */;
@@ -33139,8 +34138,8 @@ class SheetPlugin extends CorePlugin {
33139
34138
  const oldName = sheet.name;
33140
34139
  this.history.update("sheets", sheet.id, "name", name.trim());
33141
34140
  const sheetIdsMapName = Object.assign({}, this.sheetIdsMapName);
33142
- sheetIdsMapName[name] = sheet.id;
33143
34141
  delete sheetIdsMapName[oldName];
34142
+ sheetIdsMapName[name] = sheet.id;
33144
34143
  this.history.update("sheetIdsMapName", sheetIdsMapName);
33145
34144
  }
33146
34145
  hideSheet(sheetId) {
@@ -33434,10 +34433,10 @@ class SheetPlugin extends CorePlugin {
33434
34433
  */
33435
34434
  checkSheetExists(cmd) {
33436
34435
  if (cmd.type !== "CREATE_SHEET" && "sheetId" in cmd && this.sheets[cmd.sheetId] === undefined) {
33437
- return 27 /* CommandResult.InvalidSheetId */;
34436
+ return 28 /* CommandResult.InvalidSheetId */;
33438
34437
  }
33439
34438
  else if (cmd.type === "CREATE_SHEET" && this.sheets[cmd.sheetId] !== undefined) {
33440
- return 12 /* CommandResult.DuplicatedSheetId */;
34439
+ return 13 /* CommandResult.DuplicatedSheetId */;
33441
34440
  }
33442
34441
  return 0 /* CommandResult.Success */;
33443
34442
  }
@@ -34998,7 +35997,7 @@ class AutofillPlugin extends UIPlugin {
34998
35997
  if (this.lastCellSelected.col !== undefined && this.lastCellSelected.row !== undefined) {
34999
35998
  return 0 /* CommandResult.Success */;
35000
35999
  }
35001
- return 45 /* CommandResult.InvalidAutofillSelection */;
36000
+ return 46 /* CommandResult.InvalidAutofillSelection */;
35002
36001
  case "AUTOFILL_AUTO":
35003
36002
  const zone = this.getters.getSelectedZone();
35004
36003
  return zone.top === zone.bottom
@@ -35615,7 +36614,7 @@ class CellPopoverPlugin extends UIPlugin {
35615
36614
  cellPopoverRegistry.get(cmd.popoverType);
35616
36615
  }
35617
36616
  catch (error) {
35618
- return 72 /* CommandResult.InvalidCellPopover */;
36617
+ return 73 /* CommandResult.InvalidCellPopover */;
35619
36618
  }
35620
36619
  return 0 /* CommandResult.Success */;
35621
36620
  default:
@@ -37745,12 +38744,12 @@ class SelectionInputPlugin extends UIPlugin {
37745
38744
  case "ADD_RANGE":
37746
38745
  case "ADD_EMPTY_RANGE":
37747
38746
  if (this.inputHasSingleRange && this.ranges.length === 1) {
37748
- return 30 /* CommandResult.MaximumRangesReached */;
38747
+ return 31 /* CommandResult.MaximumRangesReached */;
37749
38748
  }
37750
38749
  break;
37751
38750
  case "CHANGE_RANGE":
37752
38751
  if (this.inputHasSingleRange && cmd.value.split(",").length > 1) {
37753
- return 30 /* CommandResult.MaximumRangesReached */;
38752
+ return 31 /* CommandResult.MaximumRangesReached */;
37754
38753
  }
37755
38754
  break;
37756
38755
  }
@@ -37979,7 +38978,7 @@ class SelectionInputsManagerPlugin extends UIPlugin {
37979
38978
  case "FOCUS_RANGE":
37980
38979
  const index = this.currentInput?.getIndex(cmd.rangeId);
37981
38980
  if (this.focusedInputId === cmd.id && this.currentInput?.focusedRangeIndex === index) {
37982
- return 29 /* CommandResult.InputAlreadyFocused */;
38981
+ return 30 /* CommandResult.InputAlreadyFocused */;
37983
38982
  }
37984
38983
  break;
37985
38984
  }
@@ -38111,7 +39110,7 @@ class SortPlugin extends UIPlugin {
38111
39110
  /*Test the presence of single cells*/
38112
39111
  const singleCells = positions(zone).some(({ col, row }) => !this.getters.isInMerge({ sheetId, col, row }));
38113
39112
  if (singleCells) {
38114
- return 63 /* CommandResult.InvalidSortZone */;
39113
+ return 64 /* CommandResult.InvalidSortZone */;
38115
39114
  }
38116
39115
  return 0 /* CommandResult.Success */;
38117
39116
  }
@@ -38130,7 +39129,7 @@ class SortPlugin extends UIPlugin {
38130
39129
  ];
38131
39130
  return widthCurrent === widthFirst && heightCurrent === heightFirst;
38132
39131
  })) {
38133
- return 63 /* CommandResult.InvalidSortZone */;
39132
+ return 64 /* CommandResult.InvalidSortZone */;
38134
39133
  }
38135
39134
  return 0 /* CommandResult.Success */;
38136
39135
  }
@@ -38623,7 +39622,7 @@ class SheetUIPlugin extends UIPlugin {
38623
39622
  */
38624
39623
  checkSheetExists(cmd) {
38625
39624
  if ("sheetId" in cmd && this.getters.tryGetSheet(cmd.sheetId) === undefined) {
38626
- return 27 /* CommandResult.InvalidSheetId */;
39625
+ return 28 /* CommandResult.InvalidSheetId */;
38627
39626
  }
38628
39627
  return 0 /* CommandResult.Success */;
38629
39628
  }
@@ -38635,7 +39634,7 @@ class SheetUIPlugin extends UIPlugin {
38635
39634
  const sheetId = "sheetId" in cmd ? cmd.sheetId : this.getters.tryGetActiveSheetId();
38636
39635
  const zones = this.getters.getCommandZones(cmd);
38637
39636
  if (!sheetId && zones.length > 0) {
38638
- return 92 /* CommandResult.NoActiveSheet */;
39637
+ return 93 /* CommandResult.NoActiveSheet */;
38639
39638
  }
38640
39639
  if (sheetId && zones.length > 0) {
38641
39640
  return this.getters.checkZonesExistInSheet(sheetId, zones);
@@ -39117,13 +40116,13 @@ class SplitToColumnsPlugin extends UIPlugin {
39117
40116
  }
39118
40117
  checkSingleColSelected() {
39119
40118
  if (!this.getters.isSingleColSelected()) {
39120
- return 88 /* CommandResult.MoreThanOneColumnSelected */;
40119
+ return 89 /* CommandResult.MoreThanOneColumnSelected */;
39121
40120
  }
39122
40121
  return 0 /* CommandResult.Success */;
39123
40122
  }
39124
40123
  checkNonEmptySelector(cmd) {
39125
40124
  if (cmd.separator === "") {
39126
- return 89 /* CommandResult.EmptySplitSeparator */;
40125
+ return 90 /* CommandResult.EmptySplitSeparator */;
39127
40126
  }
39128
40127
  return 0 /* CommandResult.Success */;
39129
40128
  }
@@ -39134,7 +40133,7 @@ class SplitToColumnsPlugin extends UIPlugin {
39134
40133
  const selection = this.getters.getSelectedZones()[0];
39135
40134
  const splitted = this.getSplittedCols(selection, cmd.separator);
39136
40135
  if (this.willSplittedColsOverwriteContent(selection, splitted)) {
39137
- return 90 /* CommandResult.SplitWillOverwriteContent */;
40136
+ return 91 /* CommandResult.SplitWillOverwriteContent */;
39138
40137
  }
39139
40138
  return 0 /* CommandResult.Success */;
39140
40139
  }
@@ -39145,7 +40144,7 @@ class SplitToColumnsPlugin extends UIPlugin {
39145
40144
  return 0 /* CommandResult.Success */;
39146
40145
  }
39147
40146
  }
39148
- return 91 /* CommandResult.NoSplitSeparatorInSelection */;
40147
+ return 92 /* CommandResult.NoSplitSeparatorInSelection */;
39149
40148
  }
39150
40149
  }
39151
40150
 
@@ -39260,7 +40259,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
39260
40259
  }
39261
40260
  isCutAllowed(target) {
39262
40261
  if (target.length !== 1) {
39263
- return 19 /* CommandResult.WrongCutSelection */;
40262
+ return 20 /* CommandResult.WrongCutSelection */;
39264
40263
  }
39265
40264
  return 0 /* CommandResult.Success */;
39266
40265
  }
@@ -39268,13 +40267,13 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
39268
40267
  const sheetId = this.getters.getActiveSheetId();
39269
40268
  if (this.operation === "CUT" && clipboardOption?.pasteOption !== undefined) {
39270
40269
  // cannot paste only format or only value if the previous operation is a CUT
39271
- return 21 /* CommandResult.WrongPasteOption */;
40270
+ return 22 /* CommandResult.WrongPasteOption */;
39272
40271
  }
39273
40272
  if (target.length > 1) {
39274
40273
  // cannot paste if we have a clipped zone larger than a cell and multiple
39275
40274
  // zones selected
39276
40275
  if (this.cells.length > 1 || this.cells[0].length > 1) {
39277
- return 20 /* CommandResult.WrongPasteSelection */;
40276
+ return 21 /* CommandResult.WrongPasteSelection */;
39278
40277
  }
39279
40278
  }
39280
40279
  const clipboardHeight = this.cells.length;
@@ -39292,7 +40291,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
39292
40291
  for (const zone of this.getPasteZones(target)) {
39293
40292
  if ((zone.left < xSplit && zone.right >= xSplit) ||
39294
40293
  (zone.top < ySplit && zone.bottom >= ySplit)) {
39295
- return 75 /* CommandResult.FrozenPaneOverlap */;
40294
+ return 76 /* CommandResult.FrozenPaneOverlap */;
39296
40295
  }
39297
40296
  }
39298
40297
  return 0 /* CommandResult.Success */;
@@ -39360,6 +40359,13 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
39360
40359
  });
39361
40360
  }
39362
40361
  this.pasteCopiedTables(target);
40362
+ this.cells.forEach((row) => {
40363
+ row.forEach((c) => {
40364
+ if (c.cell) {
40365
+ c.cell = undefined;
40366
+ }
40367
+ });
40368
+ });
39363
40369
  }
39364
40370
  /**
39365
40371
  * The clipped zone is copied as many times as it fits in the target.
@@ -39592,7 +40598,9 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
39592
40598
  return (this.cells
39593
40599
  .map((cells) => {
39594
40600
  return cells
39595
- .map((c) => c.cell ? this.getters.getCellText(c.position, this.getters.shouldShowFormulas()) : "")
40601
+ .map((c) => this.getters.shouldShowFormulas() && c.cell?.isFormula
40602
+ ? c.cell?.content || ""
40603
+ : c.evaluatedCell?.formattedValue || "")
39596
40604
  .join("\t");
39597
40605
  })
39598
40606
  .join("\n") || "\t");
@@ -39723,10 +40731,10 @@ class ClipboardFigureState {
39723
40731
  }
39724
40732
  isPasteAllowed(target, option) {
39725
40733
  if (target.length === 0) {
39726
- return 73 /* CommandResult.EmptyTarget */;
40734
+ return 74 /* CommandResult.EmptyTarget */;
39727
40735
  }
39728
40736
  if (option?.pasteOption !== undefined) {
39729
- return 22 /* CommandResult.WrongFigurePasteOption */;
40737
+ return 23 /* CommandResult.WrongFigurePasteOption */;
39730
40738
  }
39731
40739
  return 0 /* CommandResult.Success */;
39732
40740
  }
@@ -39828,7 +40836,10 @@ class ClipboardOsState extends ClipboardCellsAbstractState {
39828
40836
  }
39829
40837
  return 0 /* CommandResult.Success */;
39830
40838
  }
39831
- paste(target) {
40839
+ paste(target, clipboardOption) {
40840
+ if (clipboardOption?.pasteOption === "onlyFormat") {
40841
+ return;
40842
+ }
39832
40843
  const values = this.values;
39833
40844
  const pasteZone = this.getPasteZone(target);
39834
40845
  const { left: activeCol, top: activeRow } = pasteZone;
@@ -39889,6 +40900,7 @@ class ClipboardPlugin extends UIPlugin {
39889
40900
  state;
39890
40901
  lastPasteState;
39891
40902
  _isPaintingFormat = false;
40903
+ originSheetId;
39892
40904
  // ---------------------------------------------------------------------------
39893
40905
  // Command Handling
39894
40906
  // ---------------------------------------------------------------------------
@@ -39900,13 +40912,13 @@ class ClipboardPlugin extends UIPlugin {
39900
40912
  return state.isCutAllowed(zones);
39901
40913
  case "PASTE":
39902
40914
  if (!this.state) {
39903
- return 23 /* CommandResult.EmptyClipboard */;
40915
+ return 24 /* CommandResult.EmptyClipboard */;
39904
40916
  }
39905
40917
  const pasteOption = cmd.pasteOption || (this._isPaintingFormat ? "onlyFormat" : undefined);
39906
40918
  return this.state.isPasteAllowed(cmd.target, { pasteOption });
39907
40919
  case "PASTE_FROM_OS_CLIPBOARD": {
39908
40920
  const state = new ClipboardOsState(cmd.text, this.getters, this.dispatch, this.selection);
39909
- return state.isPasteAllowed(cmd.target);
40921
+ return state.isPasteAllowed(cmd.target, { pasteOption: cmd.pasteOption });
39910
40922
  }
39911
40923
  case "INSERT_CELL": {
39912
40924
  const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
@@ -39928,6 +40940,7 @@ class ClipboardPlugin extends UIPlugin {
39928
40940
  const zones = ("cutTarget" in cmd && cmd.cutTarget) || this.getters.getSelectedZones();
39929
40941
  this.state = this.getClipboardState(zones, cmd.type);
39930
40942
  this.status = "visible";
40943
+ this.originSheetId = this.getters.getActiveSheetId();
39931
40944
  break;
39932
40945
  case "PASTE":
39933
40946
  if (!this.state) {
@@ -39936,9 +40949,6 @@ class ClipboardPlugin extends UIPlugin {
39936
40949
  const pasteOption = cmd.pasteOption || (this._isPaintingFormat ? "onlyFormat" : undefined);
39937
40950
  this._isPaintingFormat = false;
39938
40951
  this.state.paste(cmd.target, { pasteOption, shouldPasteCF: true, selectTarget: true });
39939
- if (this.state.operation === "CUT") {
39940
- this.state = undefined;
39941
- }
39942
40952
  this.lastPasteState = this.state;
39943
40953
  this.status = "invisible";
39944
40954
  break;
@@ -39993,7 +41003,7 @@ class ClipboardPlugin extends UIPlugin {
39993
41003
  }
39994
41004
  case "PASTE_FROM_OS_CLIPBOARD":
39995
41005
  this.state = new ClipboardOsState(cmd.text, this.getters, this.dispatch, this.selection);
39996
- this.state.paste(cmd.target);
41006
+ this.state.paste(cmd.target, { pasteOption: cmd.pasteOption });
39997
41007
  this.lastPasteState = this.state;
39998
41008
  this.status = "invisible";
39999
41009
  break;
@@ -40012,6 +41022,15 @@ class ClipboardPlugin extends UIPlugin {
40012
41022
  this.status = "visible";
40013
41023
  break;
40014
41024
  }
41025
+ case "DELETE_SHEET":
41026
+ if (this.state?.operation !== "CUT") {
41027
+ return;
41028
+ }
41029
+ if (this.originSheetId === cmd.sheetId) {
41030
+ this.state = undefined;
41031
+ this.status = "invisible";
41032
+ }
41033
+ break;
40015
41034
  default:
40016
41035
  if (isCoreCommand(cmd)) {
40017
41036
  this.status = "invisible";
@@ -40470,7 +41489,7 @@ class EditionPlugin extends UIPlugin {
40470
41489
  validateSelection(length, start, end) {
40471
41490
  return start >= 0 && start <= length && end >= 0 && end <= length
40472
41491
  ? 0 /* CommandResult.Success */
40473
- : 46 /* CommandResult.WrongComposerSelection */;
41492
+ : 47 /* CommandResult.WrongComposerSelection */;
40474
41493
  }
40475
41494
  onColumnsRemoved(cmd) {
40476
41495
  if (cmd.elements.includes(this.col) && this.mode !== "inactive") {
@@ -40846,7 +41865,7 @@ class FilterEvaluationPlugin extends UIPlugin {
40846
41865
  switch (cmd.type) {
40847
41866
  case "UPDATE_FILTER":
40848
41867
  if (!this.getters.getFilterId(cmd)) {
40849
- return 79 /* CommandResult.FilterNotFound */;
41868
+ return 80 /* CommandResult.FilterNotFound */;
40850
41869
  }
40851
41870
  break;
40852
41871
  }
@@ -40987,6 +42006,7 @@ class FilterEvaluationPlugin extends UIPlugin {
40987
42006
  }
40988
42007
  exportForExcel(data) {
40989
42008
  for (const sheetData of data.sheets) {
42009
+ const sheetId = sheetData.id;
40990
42010
  for (const tableData of sheetData.filterTables) {
40991
42011
  const tableZone = toZone(tableData.range);
40992
42012
  const filters = [];
@@ -41002,20 +42022,20 @@ class FilterEvaluationPlugin extends UIPlugin {
41002
42022
  if (!filter)
41003
42023
  continue;
41004
42024
  const valuesInFilterZone = filter.filteredZone
41005
- ? positions(filter.filteredZone)
41006
- .map(({ col, row }) => this.getters.getEvaluatedCell({ sheetId: sheetData.id, col, row }))
41007
- .filter((cell) => cell.type !== CellValueType.empty)
41008
- .map((cell) => cell.formattedValue)
42025
+ ? positions(filter.filteredZone).map((position) => this.getters.getEvaluatedCell({ sheetId, ...position }).formattedValue)
41009
42026
  : [];
41010
- // In xlsx, filtered values = values that are displayed, not values that are hidden
41011
- const xlsxFilteredValues = valuesInFilterZone.filter((val) => !filteredValues.includes(val));
41012
- filters.push({ colId: i, filteredValues: [...new Set(xlsxFilteredValues)] });
41013
- // In xlsx, filter header should ALWAYS be a string and should be unique
41014
- const headerPosition = {
41015
- col: filter.col,
41016
- row: filter.zoneWithHeaders.top,
41017
- sheetId: sheetData.id,
41018
- };
42027
+ if (filteredValues.length) {
42028
+ const xlsxDisplayedValues = valuesInFilterZone
42029
+ .filter((val) => val)
42030
+ .filter((val) => !filteredValues.includes(val));
42031
+ filters.push({
42032
+ colId: i,
42033
+ displayedValues: [...new Set(xlsxDisplayedValues)],
42034
+ displayBlanks: !filteredValues.includes("") && valuesInFilterZone.some((val) => !val),
42035
+ });
42036
+ }
42037
+ // In xlsx, filter header should ALWAYS be a string and should be unique in the table
42038
+ const headerPosition = { col: filter.col, row: filter.zoneWithHeaders.top, sheetId };
41019
42039
  const headerString = this.getters.getEvaluatedCell(headerPosition).formattedValue;
41020
42040
  const headerName = this.getUniqueColNameForExcel(i, headerString, headerNames);
41021
42041
  headerNames.push(headerName);
@@ -41134,7 +42154,7 @@ class GridSelectionPlugin extends UIPlugin {
41134
42154
  break;
41135
42155
  }
41136
42156
  catch (error) {
41137
- return 27 /* CommandResult.InvalidSheetId */;
42157
+ return 28 /* CommandResult.InvalidSheetId */;
41138
42158
  }
41139
42159
  case "MOVE_COLUMNS_ROWS":
41140
42160
  return this.isMoveElementAllowed(cmd);
@@ -42437,7 +43457,7 @@ class SheetViewPlugin extends UIPlugin {
42437
43457
  }
42438
43458
  checkPositiveDimension(cmd) {
42439
43459
  if (cmd.width < 0 || cmd.height < 0) {
42440
- return 68 /* CommandResult.InvalidViewportSize */;
43460
+ return 69 /* CommandResult.InvalidViewportSize */;
42441
43461
  }
42442
43462
  return 0 /* CommandResult.Success */;
42443
43463
  }
@@ -42447,7 +43467,7 @@ class SheetViewPlugin extends UIPlugin {
42447
43467
  cmd.gridOffsetY === this.gridOffsetY &&
42448
43468
  cmd.width === width &&
42449
43469
  cmd.height === height) {
42450
- return 76 /* CommandResult.ValuesNotChanged */;
43470
+ return 77 /* CommandResult.ValuesNotChanged */;
42451
43471
  }
42452
43472
  return 0 /* CommandResult.Success */;
42453
43473
  }
@@ -42455,7 +43475,7 @@ class SheetViewPlugin extends UIPlugin {
42455
43475
  const pane = this.getMainInternalViewport(this.getters.getActiveSheetId());
42456
43476
  if ((!pane.canScrollHorizontally && offsetX > 0) ||
42457
43477
  (!pane.canScrollVertically && offsetY > 0)) {
42458
- return 69 /* CommandResult.InvalidScrollingDirection */;
43478
+ return 70 /* CommandResult.InvalidScrollingDirection */;
42459
43479
  }
42460
43480
  return 0 /* CommandResult.Success */;
42461
43481
  }
@@ -42882,17 +43902,14 @@ Ripple.props = {
42882
43902
  };
42883
43903
 
42884
43904
  function interactiveRenameSheet(env, sheetId, name, errorCallback) {
42885
- const originalSheetName = env.model.getters.getSheetName(sheetId);
42886
- if (name === null || name === originalSheetName)
42887
- return;
42888
43905
  const result = env.model.dispatch("RENAME_SHEET", { sheetId, name });
42889
43906
  if (result.reasons.includes(10 /* CommandResult.MissingSheetName */)) {
42890
43907
  env.raiseError(_lt("The sheet name cannot be empty."), errorCallback);
42891
43908
  }
42892
- else if (result.reasons.includes(11 /* CommandResult.DuplicatedSheetName */)) {
43909
+ else if (result.reasons.includes(12 /* CommandResult.DuplicatedSheetName */)) {
42893
43910
  env.raiseError(_lt("A sheet with the name %s already exists. Please select another name.", name), errorCallback);
42894
43911
  }
42895
- else if (result.reasons.includes(13 /* CommandResult.ForbiddenCharactersInSheetName */)) {
43912
+ else if (result.reasons.includes(14 /* CommandResult.ForbiddenCharactersInSheetName */)) {
42896
43913
  env.raiseError(_lt("Some used characters are not allowed in a sheet name (Forbidden characters are %s).", FORBIDDEN_SHEET_CHARS.join(" ")), errorCallback);
42897
43914
  }
42898
43915
  }
@@ -44221,11 +45238,9 @@ TopBarComposer.props = {
44221
45238
  onComposerContentFocused: Function,
44222
45239
  };
44223
45240
 
44224
- // -----------------------------------------------------------------------------
44225
- // TopBar
44226
- // -----------------------------------------------------------------------------
44227
45241
  css /* scss */ `
44228
45242
  .o-font-size-editor {
45243
+ height: calc(100% - 4px);
44229
45244
  input.o-font-size {
44230
45245
  outline-color: ${SELECTION_BORDER_COLOR};
44231
45246
  height: 20px;
@@ -44238,13 +45253,13 @@ css /* scss */ `
44238
45253
  input::-webkit-inner-spin-button {
44239
45254
  -webkit-appearance: none;
44240
45255
  }
44241
-
44242
- .o-text-options > div {
44243
- line-height: 26px;
44244
- padding: 3px 12px;
44245
- &:hover {
44246
- background-color: rgba(0, 0, 0, 0.08);
44247
- }
45256
+ }
45257
+ .o-text-options > div {
45258
+ cursor: pointer;
45259
+ line-height: 26px;
45260
+ padding: 3px 12px;
45261
+ &:hover {
45262
+ background-color: rgba(0, 0, 0, 0.08);
44248
45263
  }
44249
45264
  }
44250
45265
  `;
@@ -44309,6 +45324,7 @@ class FontSizeEditor extends Component {
44309
45324
  FontSizeEditor.props = {
44310
45325
  onToggle: Function,
44311
45326
  dropdownStyle: String,
45327
+ class: String,
44312
45328
  };
44313
45329
 
44314
45330
  // -----------------------------------------------------------------------------
@@ -45881,7 +46897,7 @@ class SelectionStreamProcessorImpl {
45881
46897
  */
45882
46898
  moveAnchorCell(direction, step = 1) {
45883
46899
  if (step !== "end" && step <= 0) {
45884
- return new DispatchResult(83 /* CommandResult.InvalidSelectionStep */);
46900
+ return new DispatchResult(84 /* CommandResult.InvalidSelectionStep */);
45885
46901
  }
45886
46902
  const { col, row } = this.getNextAvailablePosition(direction, step);
45887
46903
  return this.selectCell(col, row);
@@ -45927,7 +46943,7 @@ class SelectionStreamProcessorImpl {
45927
46943
  */
45928
46944
  resizeAnchorZone(direction, step = 1) {
45929
46945
  if (step !== "end" && step <= 0) {
45930
- return new DispatchResult(83 /* CommandResult.InvalidSelectionStep */);
46946
+ return new DispatchResult(84 /* CommandResult.InvalidSelectionStep */);
45931
46947
  }
45932
46948
  const sheetId = this.getters.getActiveSheetId();
45933
46949
  const anchor = this.anchor;
@@ -46121,20 +47137,20 @@ class SelectionStreamProcessorImpl {
46121
47137
  checkAnchorZone(anchor) {
46122
47138
  const { cell, zone } = anchor;
46123
47139
  if (!isInside(cell.col, cell.row, zone)) {
46124
- return 16 /* CommandResult.InvalidAnchorZone */;
47140
+ return 17 /* CommandResult.InvalidAnchorZone */;
46125
47141
  }
46126
47142
  const { left, right, top, bottom } = zone;
46127
47143
  const sheetId = this.getters.getActiveSheetId();
46128
47144
  const refCol = this.getters.findVisibleHeader(sheetId, "COL", left, right);
46129
47145
  const refRow = this.getters.findVisibleHeader(sheetId, "ROW", top, bottom);
46130
47146
  if (refRow === undefined || refCol === undefined) {
46131
- return 17 /* CommandResult.SelectionOutOfBound */;
47147
+ return 18 /* CommandResult.SelectionOutOfBound */;
46132
47148
  }
46133
47149
  return 0 /* CommandResult.Success */;
46134
47150
  }
46135
47151
  checkAnchorZoneOrThrow(anchor) {
46136
47152
  const result = this.checkAnchorZone(anchor);
46137
- if (result === 16 /* CommandResult.InvalidAnchorZone */) {
47153
+ if (result === 17 /* CommandResult.InvalidAnchorZone */) {
46138
47154
  throw new Error(_t("The provided anchor is invalid. The cell must be part of the zone."));
46139
47155
  }
46140
47156
  }
@@ -47477,15 +48493,10 @@ function addAutoFilter(table) {
47477
48493
  `;
47478
48494
  }
47479
48495
  function addFilterColumns(table) {
47480
- const tableZone = toZone(table.range);
47481
48496
  const columns = [];
47482
- for (const i of range(0, zoneToDimension(tableZone).numberOfCols)) {
47483
- const filter = table.filters[i];
47484
- if (!filter || !filter.filteredValues.length) {
47485
- continue;
47486
- }
48497
+ for (const filter of table.filters) {
47487
48498
  const colXml = escapeXml /*xml*/ `
47488
- <filterColumn ${formatAttributes([["colId", i]])}>
48499
+ <filterColumn ${formatAttributes([["colId", filter.colId]])}>
47489
48500
  ${addFilter(filter)}
47490
48501
  </filterColumn>
47491
48502
  `;
@@ -47494,9 +48505,10 @@ function addFilterColumns(table) {
47494
48505
  return columns;
47495
48506
  }
47496
48507
  function addFilter(filter) {
47497
- const filterValues = filter.filteredValues.map((val) => escapeXml /*xml*/ `<filter ${formatAttributes([["val", val]])}/>`);
48508
+ const filterValues = filter.displayedValues.map((val) => escapeXml /*xml*/ `<filter ${formatAttributes([["val", val]])}/>`);
48509
+ const filterAttributes = filter.displayBlanks ? [["blank", 1]] : [];
47498
48510
  return escapeXml /*xml*/ `
47499
- <filters>
48511
+ <filters ${formatAttributes(filterAttributes)}>
47500
48512
  ${joinXmlNodes(filterValues)}
47501
48513
  </filters>
47502
48514
  `;
@@ -47615,8 +48627,13 @@ function addHyperlinks(construct, data, sheetIndex) {
47615
48627
  const sheetId = parseSheetUrl(url);
47616
48628
  const sheet = data.sheets.find((sheet) => sheet.id === sheetId);
47617
48629
  const location = sheet ? `${sheet.name}!A1` : INCORRECT_RANGE_STRING;
48630
+ const hyperlinkAttributes = [
48631
+ ["display", label],
48632
+ ["location", location],
48633
+ ["ref", xc],
48634
+ ];
47618
48635
  linkNodes.push(escapeXml /*xml*/ `
47619
- <hyperlink display="${label}" location="${location}" ref="${xc}"/>
48636
+ <hyperlink ${formatAttributes(hyperlinkAttributes)}/>
47620
48637
  `);
47621
48638
  }
47622
48639
  else {
@@ -47625,8 +48642,12 @@ function addHyperlinks(construct, data, sheetIndex) {
47625
48642
  type: XLSX_RELATION_TYPE.hyperlink,
47626
48643
  targetMode: "External",
47627
48644
  });
48645
+ const hyperlinkAttributes = [
48646
+ ["r:id", linkRelId],
48647
+ ["ref", xc],
48648
+ ];
47628
48649
  linkNodes.push(escapeXml /*xml*/ `
47629
- <hyperlink r:id="${linkRelId}" ref="${xc}"/>
48650
+ <hyperlink ${formatAttributes(hyperlinkAttributes)}/>
47630
48651
  `);
47631
48652
  }
47632
48653
  }
@@ -48250,10 +49271,10 @@ class Model extends EventBus {
48250
49271
  const command = createCommand(type, payload);
48251
49272
  let status = this.status;
48252
49273
  if (this.getters.isReadonly() && !canExecuteInReadonly(command)) {
48253
- return new DispatchResult(67 /* CommandResult.Readonly */);
49274
+ return new DispatchResult(68 /* CommandResult.Readonly */);
48254
49275
  }
48255
49276
  if (!this.session.canApplyOptimisticUpdate()) {
48256
- return new DispatchResult(64 /* CommandResult.WaitingSessionConfirmation */);
49277
+ return new DispatchResult(65 /* CommandResult.WaitingSessionConfirmation */);
48257
49278
  }
48258
49279
  switch (status) {
48259
49280
  case 0 /* Status.Ready */:
@@ -48504,6 +49525,6 @@ function addFunction(functionName, functionDescription) {
48504
49525
  export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, links, load, parse, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
48505
49526
 
48506
49527
 
48507
- __info__.version = '16.4.0-alpha.4';
48508
- __info__.date = '2023-06-12T13:55:29.711Z';
48509
- __info__.hash = '251a52e';
49528
+ __info__.version = '16.4.0-alpha.5';
49529
+ __info__.date = '2023-06-26T14:35:24.001Z';
49530
+ __info__.hash = '3b0b6f1';