@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.
@@ -754,12 +754,20 @@ function getDefaultCellHeight(cell) {
754
754
  return computeTextLinesHeight(fontSize, numberOfLines) + 2 * PADDING_AUTORESIZE_VERTICAL;
755
755
  }
756
756
  function computeTextWidth(context, text, style) {
757
- context.save();
758
- context.font = computeTextFont(style);
759
- const textWidth = context.measureText(text).width;
760
- context.restore();
761
- return textWidth;
757
+ const font = computeTextFont(style);
758
+ if (!textWidthCache[font]) {
759
+ textWidthCache[font] = {};
760
+ }
761
+ if (textWidthCache[font][text] === undefined) {
762
+ context.save();
763
+ context.font = font;
764
+ const textWidth = context.measureText(text).width;
765
+ context.restore();
766
+ textWidthCache[font][text] = textWidth;
767
+ }
768
+ return textWidthCache[font][text];
762
769
  }
770
+ const textWidthCache = {};
763
771
  function fontSizeInPixels(fontSize) {
764
772
  return Math.round((fontSize * 96) / 72);
765
773
  }
@@ -1067,10 +1075,17 @@ function removeFalsyAttributes(obj) {
1067
1075
  function toLowerCase(str) {
1068
1076
  return str ? str.toLowerCase() : "";
1069
1077
  }
1070
- function transpose2dArray(matrix) {
1078
+ function transpose2dArray(matrix, callback = (val) => val) {
1071
1079
  if (!matrix.length)
1072
- return matrix;
1073
- return matrix[0].map((_, i) => matrix.map((row) => row[i]));
1080
+ return [];
1081
+ const transposed = Array(matrix[0].length);
1082
+ for (let i = 0; i < matrix[0].length; i++) {
1083
+ transposed[i] = Array(matrix.length);
1084
+ for (let j = 0; j < matrix.length; j++) {
1085
+ transposed[i][j] = callback(matrix[j][i]);
1086
+ }
1087
+ }
1088
+ return transposed;
1074
1089
  }
1075
1090
  /**
1076
1091
  * Equivalent to "\s" in regexp, minus the new lines characters
@@ -3708,6 +3723,290 @@ function detectLink(value) {
3708
3723
  return undefined;
3709
3724
  }
3710
3725
 
3726
+ var CellValueType;
3727
+ (function (CellValueType) {
3728
+ CellValueType["boolean"] = "boolean";
3729
+ CellValueType["number"] = "number";
3730
+ CellValueType["text"] = "text";
3731
+ CellValueType["empty"] = "empty";
3732
+ CellValueType["error"] = "error";
3733
+ })(CellValueType || (CellValueType = {}));
3734
+
3735
+ var ClipboardMIMEType;
3736
+ (function (ClipboardMIMEType) {
3737
+ ClipboardMIMEType["PlainText"] = "text/plain";
3738
+ ClipboardMIMEType["Html"] = "text/html";
3739
+ })(ClipboardMIMEType || (ClipboardMIMEType = {}));
3740
+
3741
+ function isSheetDependent(cmd) {
3742
+ return "sheetId" in cmd;
3743
+ }
3744
+ function isGridDependent(cmd) {
3745
+ return "dimension" in cmd && "sheetId" in cmd;
3746
+ }
3747
+ function isTargetDependent(cmd) {
3748
+ return "target" in cmd && "sheetId" in cmd;
3749
+ }
3750
+ function isRangeDependant(cmd) {
3751
+ return "ranges" in cmd;
3752
+ }
3753
+ function isPositionDependent(cmd) {
3754
+ return "col" in cmd && "row" in cmd && "sheetId" in cmd;
3755
+ }
3756
+ const invalidateEvaluationCommands = new Set([
3757
+ "RENAME_SHEET",
3758
+ "DELETE_SHEET",
3759
+ "CREATE_SHEET",
3760
+ "ADD_COLUMNS_ROWS",
3761
+ "REMOVE_COLUMNS_ROWS",
3762
+ "UNDO",
3763
+ "REDO",
3764
+ "ADD_MERGE",
3765
+ ]);
3766
+ const invalidateDependenciesCommands = new Set([
3767
+ ...invalidateEvaluationCommands,
3768
+ "MOVE_RANGES",
3769
+ ]);
3770
+ const invalidateCFEvaluationCommands = new Set([
3771
+ ...invalidateEvaluationCommands,
3772
+ "DUPLICATE_SHEET",
3773
+ "EVALUATE_CELLS",
3774
+ "ADD_CONDITIONAL_FORMAT",
3775
+ "REMOVE_CONDITIONAL_FORMAT",
3776
+ "MOVE_CONDITIONAL_FORMAT",
3777
+ ]);
3778
+ const readonlyAllowedCommands = new Set([
3779
+ "START",
3780
+ "ACTIVATE_SHEET",
3781
+ "COPY",
3782
+ "PREPARE_SELECTION_INPUT_EXPANSION",
3783
+ "STOP_SELECTION_INPUT",
3784
+ "RESIZE_SHEETVIEW",
3785
+ "SET_VIEWPORT_OFFSET",
3786
+ "SELECT_SEARCH_NEXT_MATCH",
3787
+ "SELECT_SEARCH_PREVIOUS_MATCH",
3788
+ "REFRESH_SEARCH",
3789
+ "UPDATE_SEARCH",
3790
+ "CLEAR_SEARCH",
3791
+ "EVALUATE_CELLS",
3792
+ "SET_CURRENT_CONTENT",
3793
+ "SET_FORMULA_VISIBILITY",
3794
+ "OPEN_CELL_POPOVER",
3795
+ "CLOSE_CELL_POPOVER",
3796
+ "UPDATE_FILTER",
3797
+ ]);
3798
+ const coreTypes = new Set([
3799
+ /** CELLS */
3800
+ "UPDATE_CELL",
3801
+ "UPDATE_CELL_POSITION",
3802
+ "CLEAR_CELL",
3803
+ "DELETE_CONTENT",
3804
+ /** GRID SHAPE */
3805
+ "ADD_COLUMNS_ROWS",
3806
+ "REMOVE_COLUMNS_ROWS",
3807
+ "RESIZE_COLUMNS_ROWS",
3808
+ "HIDE_COLUMNS_ROWS",
3809
+ "UNHIDE_COLUMNS_ROWS",
3810
+ "SET_GRID_LINES_VISIBILITY",
3811
+ "UNFREEZE_COLUMNS",
3812
+ "UNFREEZE_ROWS",
3813
+ "FREEZE_COLUMNS",
3814
+ "FREEZE_ROWS",
3815
+ "UNFREEZE_COLUMNS_ROWS",
3816
+ /** MERGE */
3817
+ "ADD_MERGE",
3818
+ "REMOVE_MERGE",
3819
+ /** SHEETS MANIPULATION */
3820
+ "CREATE_SHEET",
3821
+ "DELETE_SHEET",
3822
+ "DUPLICATE_SHEET",
3823
+ "MOVE_SHEET",
3824
+ "RENAME_SHEET",
3825
+ "HIDE_SHEET",
3826
+ "SHOW_SHEET",
3827
+ /** RANGES MANIPULATION */
3828
+ "MOVE_RANGES",
3829
+ /** CONDITIONAL FORMAT */
3830
+ "ADD_CONDITIONAL_FORMAT",
3831
+ "REMOVE_CONDITIONAL_FORMAT",
3832
+ "MOVE_CONDITIONAL_FORMAT",
3833
+ /** FIGURES */
3834
+ "CREATE_FIGURE",
3835
+ "DELETE_FIGURE",
3836
+ "UPDATE_FIGURE",
3837
+ /** FORMATTING */
3838
+ "SET_FORMATTING",
3839
+ "CLEAR_FORMATTING",
3840
+ "SET_BORDER",
3841
+ "SET_ZONE_BORDERS",
3842
+ /** CHART */
3843
+ "CREATE_CHART",
3844
+ "UPDATE_CHART",
3845
+ /** FILTERS */
3846
+ "CREATE_FILTER_TABLE",
3847
+ "REMOVE_FILTER_TABLE",
3848
+ /** IMAGE */
3849
+ "CREATE_IMAGE",
3850
+ ]);
3851
+ function isCoreCommand(cmd) {
3852
+ return coreTypes.has(cmd.type);
3853
+ }
3854
+ function canExecuteInReadonly(cmd) {
3855
+ return readonlyAllowedCommands.has(cmd.type);
3856
+ }
3857
+ /**
3858
+ * Holds the result of a command dispatch.
3859
+ * The command may have been successfully dispatched or cancelled
3860
+ * for one or more reasons.
3861
+ */
3862
+ class DispatchResult {
3863
+ reasons;
3864
+ constructor(results = []) {
3865
+ if (!Array.isArray(results)) {
3866
+ results = [results];
3867
+ }
3868
+ results = [...new Set(results)];
3869
+ this.reasons = results.filter((result) => result !== 0 /* CommandResult.Success */);
3870
+ }
3871
+ /**
3872
+ * Static helper which returns a successful DispatchResult
3873
+ */
3874
+ static get Success() {
3875
+ return new DispatchResult();
3876
+ }
3877
+ get isSuccessful() {
3878
+ return this.reasons.length === 0;
3879
+ }
3880
+ /**
3881
+ * Check if the dispatch has been cancelled because of
3882
+ * the given reason.
3883
+ */
3884
+ isCancelledBecause(reason) {
3885
+ return this.reasons.includes(reason);
3886
+ }
3887
+ }
3888
+ exports.CommandResult = void 0;
3889
+ (function (CommandResult) {
3890
+ CommandResult[CommandResult["Success"] = 0] = "Success";
3891
+ CommandResult[CommandResult["CancelledForUnknownReason"] = 1] = "CancelledForUnknownReason";
3892
+ CommandResult[CommandResult["WillRemoveExistingMerge"] = 2] = "WillRemoveExistingMerge";
3893
+ CommandResult[CommandResult["MergeIsDestructive"] = 3] = "MergeIsDestructive";
3894
+ CommandResult[CommandResult["CellIsMerged"] = 4] = "CellIsMerged";
3895
+ CommandResult[CommandResult["InvalidTarget"] = 5] = "InvalidTarget";
3896
+ CommandResult[CommandResult["EmptyUndoStack"] = 6] = "EmptyUndoStack";
3897
+ CommandResult[CommandResult["EmptyRedoStack"] = 7] = "EmptyRedoStack";
3898
+ CommandResult[CommandResult["NotEnoughElements"] = 8] = "NotEnoughElements";
3899
+ CommandResult[CommandResult["NotEnoughSheets"] = 9] = "NotEnoughSheets";
3900
+ CommandResult[CommandResult["MissingSheetName"] = 10] = "MissingSheetName";
3901
+ CommandResult[CommandResult["UnchangedSheetName"] = 11] = "UnchangedSheetName";
3902
+ CommandResult[CommandResult["DuplicatedSheetName"] = 12] = "DuplicatedSheetName";
3903
+ CommandResult[CommandResult["DuplicatedSheetId"] = 13] = "DuplicatedSheetId";
3904
+ CommandResult[CommandResult["ForbiddenCharactersInSheetName"] = 14] = "ForbiddenCharactersInSheetName";
3905
+ CommandResult[CommandResult["WrongSheetMove"] = 15] = "WrongSheetMove";
3906
+ CommandResult[CommandResult["WrongSheetPosition"] = 16] = "WrongSheetPosition";
3907
+ CommandResult[CommandResult["InvalidAnchorZone"] = 17] = "InvalidAnchorZone";
3908
+ CommandResult[CommandResult["SelectionOutOfBound"] = 18] = "SelectionOutOfBound";
3909
+ CommandResult[CommandResult["TargetOutOfSheet"] = 19] = "TargetOutOfSheet";
3910
+ CommandResult[CommandResult["WrongCutSelection"] = 20] = "WrongCutSelection";
3911
+ CommandResult[CommandResult["WrongPasteSelection"] = 21] = "WrongPasteSelection";
3912
+ CommandResult[CommandResult["WrongPasteOption"] = 22] = "WrongPasteOption";
3913
+ CommandResult[CommandResult["WrongFigurePasteOption"] = 23] = "WrongFigurePasteOption";
3914
+ CommandResult[CommandResult["EmptyClipboard"] = 24] = "EmptyClipboard";
3915
+ CommandResult[CommandResult["EmptyRange"] = 25] = "EmptyRange";
3916
+ CommandResult[CommandResult["InvalidRange"] = 26] = "InvalidRange";
3917
+ CommandResult[CommandResult["InvalidZones"] = 27] = "InvalidZones";
3918
+ CommandResult[CommandResult["InvalidSheetId"] = 28] = "InvalidSheetId";
3919
+ CommandResult[CommandResult["InvalidFigureId"] = 29] = "InvalidFigureId";
3920
+ CommandResult[CommandResult["InputAlreadyFocused"] = 30] = "InputAlreadyFocused";
3921
+ CommandResult[CommandResult["MaximumRangesReached"] = 31] = "MaximumRangesReached";
3922
+ CommandResult[CommandResult["InvalidChartDefinition"] = 32] = "InvalidChartDefinition";
3923
+ CommandResult[CommandResult["InvalidDataSet"] = 33] = "InvalidDataSet";
3924
+ CommandResult[CommandResult["InvalidLabelRange"] = 34] = "InvalidLabelRange";
3925
+ CommandResult[CommandResult["InvalidScorecardKeyValue"] = 35] = "InvalidScorecardKeyValue";
3926
+ CommandResult[CommandResult["InvalidScorecardBaseline"] = 36] = "InvalidScorecardBaseline";
3927
+ CommandResult[CommandResult["InvalidGaugeDataRange"] = 37] = "InvalidGaugeDataRange";
3928
+ CommandResult[CommandResult["EmptyGaugeRangeMin"] = 38] = "EmptyGaugeRangeMin";
3929
+ CommandResult[CommandResult["GaugeRangeMinNaN"] = 39] = "GaugeRangeMinNaN";
3930
+ CommandResult[CommandResult["EmptyGaugeRangeMax"] = 40] = "EmptyGaugeRangeMax";
3931
+ CommandResult[CommandResult["GaugeRangeMaxNaN"] = 41] = "GaugeRangeMaxNaN";
3932
+ CommandResult[CommandResult["GaugeRangeMinBiggerThanRangeMax"] = 42] = "GaugeRangeMinBiggerThanRangeMax";
3933
+ CommandResult[CommandResult["GaugeLowerInflectionPointNaN"] = 43] = "GaugeLowerInflectionPointNaN";
3934
+ CommandResult[CommandResult["GaugeUpperInflectionPointNaN"] = 44] = "GaugeUpperInflectionPointNaN";
3935
+ CommandResult[CommandResult["GaugeLowerBiggerThanUpper"] = 45] = "GaugeLowerBiggerThanUpper";
3936
+ CommandResult[CommandResult["InvalidAutofillSelection"] = 46] = "InvalidAutofillSelection";
3937
+ CommandResult[CommandResult["WrongComposerSelection"] = 47] = "WrongComposerSelection";
3938
+ CommandResult[CommandResult["MinBiggerThanMax"] = 48] = "MinBiggerThanMax";
3939
+ CommandResult[CommandResult["LowerBiggerThanUpper"] = 49] = "LowerBiggerThanUpper";
3940
+ CommandResult[CommandResult["MidBiggerThanMax"] = 50] = "MidBiggerThanMax";
3941
+ CommandResult[CommandResult["MinBiggerThanMid"] = 51] = "MinBiggerThanMid";
3942
+ CommandResult[CommandResult["FirstArgMissing"] = 52] = "FirstArgMissing";
3943
+ CommandResult[CommandResult["SecondArgMissing"] = 53] = "SecondArgMissing";
3944
+ CommandResult[CommandResult["MinNaN"] = 54] = "MinNaN";
3945
+ CommandResult[CommandResult["MidNaN"] = 55] = "MidNaN";
3946
+ CommandResult[CommandResult["MaxNaN"] = 56] = "MaxNaN";
3947
+ CommandResult[CommandResult["ValueUpperInflectionNaN"] = 57] = "ValueUpperInflectionNaN";
3948
+ CommandResult[CommandResult["ValueLowerInflectionNaN"] = 58] = "ValueLowerInflectionNaN";
3949
+ CommandResult[CommandResult["MinInvalidFormula"] = 59] = "MinInvalidFormula";
3950
+ CommandResult[CommandResult["MidInvalidFormula"] = 60] = "MidInvalidFormula";
3951
+ CommandResult[CommandResult["MaxInvalidFormula"] = 61] = "MaxInvalidFormula";
3952
+ CommandResult[CommandResult["ValueUpperInvalidFormula"] = 62] = "ValueUpperInvalidFormula";
3953
+ CommandResult[CommandResult["ValueLowerInvalidFormula"] = 63] = "ValueLowerInvalidFormula";
3954
+ CommandResult[CommandResult["InvalidSortZone"] = 64] = "InvalidSortZone";
3955
+ CommandResult[CommandResult["WaitingSessionConfirmation"] = 65] = "WaitingSessionConfirmation";
3956
+ CommandResult[CommandResult["MergeOverlap"] = 66] = "MergeOverlap";
3957
+ CommandResult[CommandResult["TooManyHiddenElements"] = 67] = "TooManyHiddenElements";
3958
+ CommandResult[CommandResult["Readonly"] = 68] = "Readonly";
3959
+ CommandResult[CommandResult["InvalidViewportSize"] = 69] = "InvalidViewportSize";
3960
+ CommandResult[CommandResult["InvalidScrollingDirection"] = 70] = "InvalidScrollingDirection";
3961
+ CommandResult[CommandResult["FigureDoesNotExist"] = 71] = "FigureDoesNotExist";
3962
+ CommandResult[CommandResult["InvalidConditionalFormatId"] = 72] = "InvalidConditionalFormatId";
3963
+ CommandResult[CommandResult["InvalidCellPopover"] = 73] = "InvalidCellPopover";
3964
+ CommandResult[CommandResult["EmptyTarget"] = 74] = "EmptyTarget";
3965
+ CommandResult[CommandResult["InvalidFreezeQuantity"] = 75] = "InvalidFreezeQuantity";
3966
+ CommandResult[CommandResult["FrozenPaneOverlap"] = 76] = "FrozenPaneOverlap";
3967
+ CommandResult[CommandResult["ValuesNotChanged"] = 77] = "ValuesNotChanged";
3968
+ CommandResult[CommandResult["InvalidFilterZone"] = 78] = "InvalidFilterZone";
3969
+ CommandResult[CommandResult["FilterOverlap"] = 79] = "FilterOverlap";
3970
+ CommandResult[CommandResult["FilterNotFound"] = 80] = "FilterNotFound";
3971
+ CommandResult[CommandResult["MergeInFilter"] = 81] = "MergeInFilter";
3972
+ CommandResult[CommandResult["NonContinuousTargets"] = 82] = "NonContinuousTargets";
3973
+ CommandResult[CommandResult["DuplicatedFigureId"] = 83] = "DuplicatedFigureId";
3974
+ CommandResult[CommandResult["InvalidSelectionStep"] = 84] = "InvalidSelectionStep";
3975
+ CommandResult[CommandResult["DuplicatedChartId"] = 85] = "DuplicatedChartId";
3976
+ CommandResult[CommandResult["ChartDoesNotExist"] = 86] = "ChartDoesNotExist";
3977
+ CommandResult[CommandResult["InvalidHeaderIndex"] = 87] = "InvalidHeaderIndex";
3978
+ CommandResult[CommandResult["InvalidQuantity"] = 88] = "InvalidQuantity";
3979
+ CommandResult[CommandResult["MoreThanOneColumnSelected"] = 89] = "MoreThanOneColumnSelected";
3980
+ CommandResult[CommandResult["EmptySplitSeparator"] = 90] = "EmptySplitSeparator";
3981
+ CommandResult[CommandResult["SplitWillOverwriteContent"] = 91] = "SplitWillOverwriteContent";
3982
+ CommandResult[CommandResult["NoSplitSeparatorInSelection"] = 92] = "NoSplitSeparatorInSelection";
3983
+ CommandResult[CommandResult["NoActiveSheet"] = 93] = "NoActiveSheet";
3984
+ })(exports.CommandResult || (exports.CommandResult = {}));
3985
+
3986
+ const borderStyles = ["thin", "medium", "thick", "dashed", "dotted"];
3987
+ function isMatrix(x) {
3988
+ return Array.isArray(x) && Array.isArray(x[0]);
3989
+ }
3990
+ var DIRECTION;
3991
+ (function (DIRECTION) {
3992
+ DIRECTION["UP"] = "up";
3993
+ DIRECTION["DOWN"] = "down";
3994
+ DIRECTION["LEFT"] = "left";
3995
+ DIRECTION["RIGHT"] = "right";
3996
+ })(DIRECTION || (DIRECTION = {}));
3997
+
3998
+ var LAYERS;
3999
+ (function (LAYERS) {
4000
+ LAYERS[LAYERS["Background"] = 0] = "Background";
4001
+ LAYERS[LAYERS["Highlights"] = 1] = "Highlights";
4002
+ LAYERS[LAYERS["Clipboard"] = 2] = "Clipboard";
4003
+ LAYERS[LAYERS["Search"] = 3] = "Search";
4004
+ LAYERS[LAYERS["Chart"] = 4] = "Chart";
4005
+ LAYERS[LAYERS["Autofill"] = 5] = "Autofill";
4006
+ LAYERS[LAYERS["Selection"] = 6] = "Selection";
4007
+ LAYERS[LAYERS["Headers"] = 7] = "Headers";
4008
+ })(LAYERS || (LAYERS = {}));
4009
+
3711
4010
  // HELPERS
3712
4011
  const SORT_TYPES_ORDER = ["number", "string", "boolean", "undefined"];
3713
4012
  function assert(condition, message) {
@@ -3749,6 +4048,9 @@ function strictToNumber(value) {
3749
4048
  }
3750
4049
  return toNumber(value);
3751
4050
  }
4051
+ function toInteger(value) {
4052
+ return Math.trunc(toNumber(value));
4053
+ }
3752
4054
  function strictToInteger(value) {
3753
4055
  return Math.trunc(strictToNumber(value));
3754
4056
  }
@@ -3851,16 +4153,25 @@ function visitNumbers(args, cb) {
3851
4153
  // -----------------------------------------------------------------------------
3852
4154
  // REDUCE FUNCTIONS
3853
4155
  // -----------------------------------------------------------------------------
3854
- function reduceArgs(args, cellCb, dataCb, initialValue) {
4156
+ function reduceArgs(args, cellCb, dataCb, initialValue, dir = "rowFirst") {
3855
4157
  let val = initialValue;
3856
4158
  for (let arg of args) {
3857
4159
  if (Array.isArray(arg)) {
3858
4160
  // arg is ref to a Cell/Range
3859
- const lenRow = arg.length;
3860
- const lenCol = arg[0].length;
3861
- for (let y = 0; y < lenCol; y++) {
3862
- for (let x = 0; x < lenRow; x++) {
3863
- val = cellCb(val, arg[x][y]);
4161
+ const numberOfCols = arg.length;
4162
+ const numberOfRows = arg[0].length;
4163
+ if (dir === "rowFirst") {
4164
+ for (let row = 0; row < numberOfRows; row++) {
4165
+ for (let col = 0; col < numberOfCols; col++) {
4166
+ val = cellCb(val, arg[col][row]);
4167
+ }
4168
+ }
4169
+ }
4170
+ else {
4171
+ for (let col = 0; col < numberOfCols; col++) {
4172
+ for (let row = 0; row < numberOfRows; row++) {
4173
+ val = cellCb(val, arg[col][row]);
4174
+ }
3864
4175
  }
3865
4176
  }
3866
4177
  }
@@ -3871,8 +4182,8 @@ function reduceArgs(args, cellCb, dataCb, initialValue) {
3871
4182
  }
3872
4183
  return val;
3873
4184
  }
3874
- function reduceAny(args, cb, initialValue) {
3875
- return reduceArgs(args, cb, cb, initialValue);
4185
+ function reduceAny(args, cb, initialValue, dir = "rowFirst") {
4186
+ return reduceArgs(args, cb, cb, initialValue, dir);
3876
4187
  }
3877
4188
  function reduceNumbers(args, cb, initialValue) {
3878
4189
  return reduceArgs(args, (acc, ArgValue) => {
@@ -4249,290 +4560,57 @@ function compareCellValues(left, right) {
4249
4560
  }
4250
4561
  }
4251
4562
  return typeOrder;
4252
- }
4253
-
4254
- var CellValueType;
4255
- (function (CellValueType) {
4256
- CellValueType["boolean"] = "boolean";
4257
- CellValueType["number"] = "number";
4258
- CellValueType["text"] = "text";
4259
- CellValueType["empty"] = "empty";
4260
- CellValueType["error"] = "error";
4261
- })(CellValueType || (CellValueType = {}));
4262
-
4263
- var ClipboardMIMEType;
4264
- (function (ClipboardMIMEType) {
4265
- ClipboardMIMEType["PlainText"] = "text/plain";
4266
- ClipboardMIMEType["Html"] = "text/html";
4267
- })(ClipboardMIMEType || (ClipboardMIMEType = {}));
4268
-
4269
- function isSheetDependent(cmd) {
4270
- return "sheetId" in cmd;
4271
- }
4272
- function isGridDependent(cmd) {
4273
- return "dimension" in cmd && "sheetId" in cmd;
4274
4563
  }
4275
- function isTargetDependent(cmd) {
4276
- return "target" in cmd && "sheetId" in cmd;
4277
- }
4278
- function isRangeDependant(cmd) {
4279
- return "ranges" in cmd;
4564
+ function matrixMap(matrix, fn) {
4565
+ let result = new Array(matrix.length);
4566
+ for (let i = 0; i < matrix.length; i++) {
4567
+ result[i] = new Array(matrix[i].length);
4568
+ for (let j = 0; j < matrix[i].length; j++) {
4569
+ result[i][j] = fn(matrix[i][j]);
4570
+ }
4571
+ }
4572
+ return result;
4280
4573
  }
4281
- function isPositionDependent(cmd) {
4282
- return "col" in cmd && "row" in cmd && "sheetId" in cmd;
4574
+ function toCellValueMatrix(values) {
4575
+ return matrixMap(values, toCellValue);
4283
4576
  }
4284
- const invalidateEvaluationCommands = new Set([
4285
- "RENAME_SHEET",
4286
- "DELETE_SHEET",
4287
- "CREATE_SHEET",
4288
- "ADD_COLUMNS_ROWS",
4289
- "REMOVE_COLUMNS_ROWS",
4290
- "UNDO",
4291
- "REDO",
4292
- "ADD_MERGE",
4293
- ]);
4294
- const invalidateDependenciesCommands = new Set([
4295
- ...invalidateEvaluationCommands,
4296
- "MOVE_RANGES",
4297
- ]);
4298
- const invalidateCFEvaluationCommands = new Set([
4299
- ...invalidateEvaluationCommands,
4300
- "DUPLICATE_SHEET",
4301
- "EVALUATE_CELLS",
4302
- "ADD_CONDITIONAL_FORMAT",
4303
- "REMOVE_CONDITIONAL_FORMAT",
4304
- "MOVE_CONDITIONAL_FORMAT",
4305
- ]);
4306
- const readonlyAllowedCommands = new Set([
4307
- "START",
4308
- "ACTIVATE_SHEET",
4309
- "COPY",
4310
- "PREPARE_SELECTION_INPUT_EXPANSION",
4311
- "STOP_SELECTION_INPUT",
4312
- "RESIZE_SHEETVIEW",
4313
- "SET_VIEWPORT_OFFSET",
4314
- "SELECT_SEARCH_NEXT_MATCH",
4315
- "SELECT_SEARCH_PREVIOUS_MATCH",
4316
- "REFRESH_SEARCH",
4317
- "UPDATE_SEARCH",
4318
- "CLEAR_SEARCH",
4319
- "EVALUATE_CELLS",
4320
- "SET_CURRENT_CONTENT",
4321
- "SET_FORMULA_VISIBILITY",
4322
- "OPEN_CELL_POPOVER",
4323
- "CLOSE_CELL_POPOVER",
4324
- "UPDATE_FILTER",
4325
- ]);
4326
- const coreTypes = new Set([
4327
- /** CELLS */
4328
- "UPDATE_CELL",
4329
- "UPDATE_CELL_POSITION",
4330
- "CLEAR_CELL",
4331
- "DELETE_CONTENT",
4332
- /** GRID SHAPE */
4333
- "ADD_COLUMNS_ROWS",
4334
- "REMOVE_COLUMNS_ROWS",
4335
- "RESIZE_COLUMNS_ROWS",
4336
- "HIDE_COLUMNS_ROWS",
4337
- "UNHIDE_COLUMNS_ROWS",
4338
- "SET_GRID_LINES_VISIBILITY",
4339
- "UNFREEZE_COLUMNS",
4340
- "UNFREEZE_ROWS",
4341
- "FREEZE_COLUMNS",
4342
- "FREEZE_ROWS",
4343
- "UNFREEZE_COLUMNS_ROWS",
4344
- /** MERGE */
4345
- "ADD_MERGE",
4346
- "REMOVE_MERGE",
4347
- /** SHEETS MANIPULATION */
4348
- "CREATE_SHEET",
4349
- "DELETE_SHEET",
4350
- "DUPLICATE_SHEET",
4351
- "MOVE_SHEET",
4352
- "RENAME_SHEET",
4353
- "HIDE_SHEET",
4354
- "SHOW_SHEET",
4355
- /** RANGES MANIPULATION */
4356
- "MOVE_RANGES",
4357
- /** CONDITIONAL FORMAT */
4358
- "ADD_CONDITIONAL_FORMAT",
4359
- "REMOVE_CONDITIONAL_FORMAT",
4360
- "MOVE_CONDITIONAL_FORMAT",
4361
- /** FIGURES */
4362
- "CREATE_FIGURE",
4363
- "DELETE_FIGURE",
4364
- "UPDATE_FIGURE",
4365
- /** FORMATTING */
4366
- "SET_FORMATTING",
4367
- "CLEAR_FORMATTING",
4368
- "SET_BORDER",
4369
- "SET_ZONE_BORDERS",
4370
- /** CHART */
4371
- "CREATE_CHART",
4372
- "UPDATE_CHART",
4373
- /** FILTERS */
4374
- "CREATE_FILTER_TABLE",
4375
- "REMOVE_FILTER_TABLE",
4376
- /** IMAGE */
4377
- "CREATE_IMAGE",
4378
- ]);
4379
- function isCoreCommand(cmd) {
4380
- return coreTypes.has(cmd.type);
4577
+ function toCellValue(value) {
4578
+ if (value === null || value === undefined)
4579
+ return 0;
4580
+ if (typeof value === "number")
4581
+ return value;
4582
+ if (typeof value === "string")
4583
+ return value;
4584
+ if (typeof value === "boolean")
4585
+ return value;
4586
+ return String(value);
4381
4587
  }
4382
- function canExecuteInReadonly(cmd) {
4383
- return readonlyAllowedCommands.has(cmd.type);
4588
+ function toMatrixArgValue(values) {
4589
+ if (isMatrix(values))
4590
+ return values;
4591
+ return [[values === null ? 0 : values]];
4384
4592
  }
4385
4593
  /**
4386
- * Holds the result of a command dispatch.
4387
- * The command may have been successfully dispatched or cancelled
4388
- * for one or more reasons.
4594
+ * Flatten an array of items, where each item can be a single value or a 2D array, and apply the
4595
+ * callback to each element.
4596
+ *
4597
+ * The 2D array are flattened row first.
4389
4598
  */
4390
- class DispatchResult {
4391
- reasons;
4392
- constructor(results = []) {
4393
- if (!Array.isArray(results)) {
4394
- results = [results];
4599
+ function flattenRowFirst(items, callback) {
4600
+ const flattened = [];
4601
+ for (const item of items) {
4602
+ if (!Array.isArray(item)) {
4603
+ flattened.push(callback(item));
4604
+ continue;
4605
+ }
4606
+ for (let row = 0; row < item[0].length; row++) {
4607
+ for (let col = 0; col < item.length; col++) {
4608
+ flattened.push(callback(item[col][row]));
4609
+ }
4395
4610
  }
4396
- results = [...new Set(results)];
4397
- this.reasons = results.filter((result) => result !== 0 /* CommandResult.Success */);
4398
- }
4399
- /**
4400
- * Static helper which returns a successful DispatchResult
4401
- */
4402
- static get Success() {
4403
- return new DispatchResult();
4404
- }
4405
- get isSuccessful() {
4406
- return this.reasons.length === 0;
4407
- }
4408
- /**
4409
- * Check if the dispatch has been cancelled because of
4410
- * the given reason.
4411
- */
4412
- isCancelledBecause(reason) {
4413
- return this.reasons.includes(reason);
4414
4611
  }
4415
- }
4416
- exports.CommandResult = void 0;
4417
- (function (CommandResult) {
4418
- CommandResult[CommandResult["Success"] = 0] = "Success";
4419
- CommandResult[CommandResult["CancelledForUnknownReason"] = 1] = "CancelledForUnknownReason";
4420
- CommandResult[CommandResult["WillRemoveExistingMerge"] = 2] = "WillRemoveExistingMerge";
4421
- CommandResult[CommandResult["MergeIsDestructive"] = 3] = "MergeIsDestructive";
4422
- CommandResult[CommandResult["CellIsMerged"] = 4] = "CellIsMerged";
4423
- CommandResult[CommandResult["InvalidTarget"] = 5] = "InvalidTarget";
4424
- CommandResult[CommandResult["EmptyUndoStack"] = 6] = "EmptyUndoStack";
4425
- CommandResult[CommandResult["EmptyRedoStack"] = 7] = "EmptyRedoStack";
4426
- CommandResult[CommandResult["NotEnoughElements"] = 8] = "NotEnoughElements";
4427
- CommandResult[CommandResult["NotEnoughSheets"] = 9] = "NotEnoughSheets";
4428
- CommandResult[CommandResult["MissingSheetName"] = 10] = "MissingSheetName";
4429
- CommandResult[CommandResult["DuplicatedSheetName"] = 11] = "DuplicatedSheetName";
4430
- CommandResult[CommandResult["DuplicatedSheetId"] = 12] = "DuplicatedSheetId";
4431
- CommandResult[CommandResult["ForbiddenCharactersInSheetName"] = 13] = "ForbiddenCharactersInSheetName";
4432
- CommandResult[CommandResult["WrongSheetMove"] = 14] = "WrongSheetMove";
4433
- CommandResult[CommandResult["WrongSheetPosition"] = 15] = "WrongSheetPosition";
4434
- CommandResult[CommandResult["InvalidAnchorZone"] = 16] = "InvalidAnchorZone";
4435
- CommandResult[CommandResult["SelectionOutOfBound"] = 17] = "SelectionOutOfBound";
4436
- CommandResult[CommandResult["TargetOutOfSheet"] = 18] = "TargetOutOfSheet";
4437
- CommandResult[CommandResult["WrongCutSelection"] = 19] = "WrongCutSelection";
4438
- CommandResult[CommandResult["WrongPasteSelection"] = 20] = "WrongPasteSelection";
4439
- CommandResult[CommandResult["WrongPasteOption"] = 21] = "WrongPasteOption";
4440
- CommandResult[CommandResult["WrongFigurePasteOption"] = 22] = "WrongFigurePasteOption";
4441
- CommandResult[CommandResult["EmptyClipboard"] = 23] = "EmptyClipboard";
4442
- CommandResult[CommandResult["EmptyRange"] = 24] = "EmptyRange";
4443
- CommandResult[CommandResult["InvalidRange"] = 25] = "InvalidRange";
4444
- CommandResult[CommandResult["InvalidZones"] = 26] = "InvalidZones";
4445
- CommandResult[CommandResult["InvalidSheetId"] = 27] = "InvalidSheetId";
4446
- CommandResult[CommandResult["InvalidFigureId"] = 28] = "InvalidFigureId";
4447
- CommandResult[CommandResult["InputAlreadyFocused"] = 29] = "InputAlreadyFocused";
4448
- CommandResult[CommandResult["MaximumRangesReached"] = 30] = "MaximumRangesReached";
4449
- CommandResult[CommandResult["InvalidChartDefinition"] = 31] = "InvalidChartDefinition";
4450
- CommandResult[CommandResult["InvalidDataSet"] = 32] = "InvalidDataSet";
4451
- CommandResult[CommandResult["InvalidLabelRange"] = 33] = "InvalidLabelRange";
4452
- CommandResult[CommandResult["InvalidScorecardKeyValue"] = 34] = "InvalidScorecardKeyValue";
4453
- CommandResult[CommandResult["InvalidScorecardBaseline"] = 35] = "InvalidScorecardBaseline";
4454
- CommandResult[CommandResult["InvalidGaugeDataRange"] = 36] = "InvalidGaugeDataRange";
4455
- CommandResult[CommandResult["EmptyGaugeRangeMin"] = 37] = "EmptyGaugeRangeMin";
4456
- CommandResult[CommandResult["GaugeRangeMinNaN"] = 38] = "GaugeRangeMinNaN";
4457
- CommandResult[CommandResult["EmptyGaugeRangeMax"] = 39] = "EmptyGaugeRangeMax";
4458
- CommandResult[CommandResult["GaugeRangeMaxNaN"] = 40] = "GaugeRangeMaxNaN";
4459
- CommandResult[CommandResult["GaugeRangeMinBiggerThanRangeMax"] = 41] = "GaugeRangeMinBiggerThanRangeMax";
4460
- CommandResult[CommandResult["GaugeLowerInflectionPointNaN"] = 42] = "GaugeLowerInflectionPointNaN";
4461
- CommandResult[CommandResult["GaugeUpperInflectionPointNaN"] = 43] = "GaugeUpperInflectionPointNaN";
4462
- CommandResult[CommandResult["GaugeLowerBiggerThanUpper"] = 44] = "GaugeLowerBiggerThanUpper";
4463
- CommandResult[CommandResult["InvalidAutofillSelection"] = 45] = "InvalidAutofillSelection";
4464
- CommandResult[CommandResult["WrongComposerSelection"] = 46] = "WrongComposerSelection";
4465
- CommandResult[CommandResult["MinBiggerThanMax"] = 47] = "MinBiggerThanMax";
4466
- CommandResult[CommandResult["LowerBiggerThanUpper"] = 48] = "LowerBiggerThanUpper";
4467
- CommandResult[CommandResult["MidBiggerThanMax"] = 49] = "MidBiggerThanMax";
4468
- CommandResult[CommandResult["MinBiggerThanMid"] = 50] = "MinBiggerThanMid";
4469
- CommandResult[CommandResult["FirstArgMissing"] = 51] = "FirstArgMissing";
4470
- CommandResult[CommandResult["SecondArgMissing"] = 52] = "SecondArgMissing";
4471
- CommandResult[CommandResult["MinNaN"] = 53] = "MinNaN";
4472
- CommandResult[CommandResult["MidNaN"] = 54] = "MidNaN";
4473
- CommandResult[CommandResult["MaxNaN"] = 55] = "MaxNaN";
4474
- CommandResult[CommandResult["ValueUpperInflectionNaN"] = 56] = "ValueUpperInflectionNaN";
4475
- CommandResult[CommandResult["ValueLowerInflectionNaN"] = 57] = "ValueLowerInflectionNaN";
4476
- CommandResult[CommandResult["MinInvalidFormula"] = 58] = "MinInvalidFormula";
4477
- CommandResult[CommandResult["MidInvalidFormula"] = 59] = "MidInvalidFormula";
4478
- CommandResult[CommandResult["MaxInvalidFormula"] = 60] = "MaxInvalidFormula";
4479
- CommandResult[CommandResult["ValueUpperInvalidFormula"] = 61] = "ValueUpperInvalidFormula";
4480
- CommandResult[CommandResult["ValueLowerInvalidFormula"] = 62] = "ValueLowerInvalidFormula";
4481
- CommandResult[CommandResult["InvalidSortZone"] = 63] = "InvalidSortZone";
4482
- CommandResult[CommandResult["WaitingSessionConfirmation"] = 64] = "WaitingSessionConfirmation";
4483
- CommandResult[CommandResult["MergeOverlap"] = 65] = "MergeOverlap";
4484
- CommandResult[CommandResult["TooManyHiddenElements"] = 66] = "TooManyHiddenElements";
4485
- CommandResult[CommandResult["Readonly"] = 67] = "Readonly";
4486
- CommandResult[CommandResult["InvalidViewportSize"] = 68] = "InvalidViewportSize";
4487
- CommandResult[CommandResult["InvalidScrollingDirection"] = 69] = "InvalidScrollingDirection";
4488
- CommandResult[CommandResult["FigureDoesNotExist"] = 70] = "FigureDoesNotExist";
4489
- CommandResult[CommandResult["InvalidConditionalFormatId"] = 71] = "InvalidConditionalFormatId";
4490
- CommandResult[CommandResult["InvalidCellPopover"] = 72] = "InvalidCellPopover";
4491
- CommandResult[CommandResult["EmptyTarget"] = 73] = "EmptyTarget";
4492
- CommandResult[CommandResult["InvalidFreezeQuantity"] = 74] = "InvalidFreezeQuantity";
4493
- CommandResult[CommandResult["FrozenPaneOverlap"] = 75] = "FrozenPaneOverlap";
4494
- CommandResult[CommandResult["ValuesNotChanged"] = 76] = "ValuesNotChanged";
4495
- CommandResult[CommandResult["InvalidFilterZone"] = 77] = "InvalidFilterZone";
4496
- CommandResult[CommandResult["FilterOverlap"] = 78] = "FilterOverlap";
4497
- CommandResult[CommandResult["FilterNotFound"] = 79] = "FilterNotFound";
4498
- CommandResult[CommandResult["MergeInFilter"] = 80] = "MergeInFilter";
4499
- CommandResult[CommandResult["NonContinuousTargets"] = 81] = "NonContinuousTargets";
4500
- CommandResult[CommandResult["DuplicatedFigureId"] = 82] = "DuplicatedFigureId";
4501
- CommandResult[CommandResult["InvalidSelectionStep"] = 83] = "InvalidSelectionStep";
4502
- CommandResult[CommandResult["DuplicatedChartId"] = 84] = "DuplicatedChartId";
4503
- CommandResult[CommandResult["ChartDoesNotExist"] = 85] = "ChartDoesNotExist";
4504
- CommandResult[CommandResult["InvalidHeaderIndex"] = 86] = "InvalidHeaderIndex";
4505
- CommandResult[CommandResult["InvalidQuantity"] = 87] = "InvalidQuantity";
4506
- CommandResult[CommandResult["MoreThanOneColumnSelected"] = 88] = "MoreThanOneColumnSelected";
4507
- CommandResult[CommandResult["EmptySplitSeparator"] = 89] = "EmptySplitSeparator";
4508
- CommandResult[CommandResult["SplitWillOverwriteContent"] = 90] = "SplitWillOverwriteContent";
4509
- CommandResult[CommandResult["NoSplitSeparatorInSelection"] = 91] = "NoSplitSeparatorInSelection";
4510
- CommandResult[CommandResult["NoActiveSheet"] = 92] = "NoActiveSheet";
4511
- })(exports.CommandResult || (exports.CommandResult = {}));
4512
-
4513
- const borderStyles = ["thin", "medium", "thick", "dashed", "dotted"];
4514
- function isMatrix(x) {
4515
- return Array.isArray(x) && Array.isArray(x[0]);
4516
- }
4517
- var DIRECTION;
4518
- (function (DIRECTION) {
4519
- DIRECTION["UP"] = "up";
4520
- DIRECTION["DOWN"] = "down";
4521
- DIRECTION["LEFT"] = "left";
4522
- DIRECTION["RIGHT"] = "right";
4523
- })(DIRECTION || (DIRECTION = {}));
4524
-
4525
- var LAYERS;
4526
- (function (LAYERS) {
4527
- LAYERS[LAYERS["Background"] = 0] = "Background";
4528
- LAYERS[LAYERS["Highlights"] = 1] = "Highlights";
4529
- LAYERS[LAYERS["Clipboard"] = 2] = "Clipboard";
4530
- LAYERS[LAYERS["Search"] = 3] = "Search";
4531
- LAYERS[LAYERS["Chart"] = 4] = "Chart";
4532
- LAYERS[LAYERS["Autofill"] = 5] = "Autofill";
4533
- LAYERS[LAYERS["Selection"] = 6] = "Selection";
4534
- LAYERS[LAYERS["Headers"] = 7] = "Headers";
4535
- })(LAYERS || (LAYERS = {}));
4612
+ return flattened;
4613
+ }
4536
4614
 
4537
4615
  function evaluateLiteral(content, format) {
4538
4616
  return createEvaluatedCell(parseLiteral(content || ""), format);
@@ -5113,10 +5191,10 @@ class FilterMenu extends owl.Component {
5113
5191
  this.state.selectedValue = value.string;
5114
5192
  }
5115
5193
  selectAll() {
5116
- this.state.values.forEach((value) => (value.checked = true));
5194
+ this.displayedValues.forEach((value) => (value.checked = true));
5117
5195
  }
5118
5196
  clearAll() {
5119
- this.state.values.forEach((value) => (value.checked = false));
5197
+ this.displayedValues.forEach((value) => (value.checked = false));
5120
5198
  }
5121
5199
  get filterTable() {
5122
5200
  const sheetId = this.env.model.getters.getActiveSheetId();
@@ -6579,11 +6657,11 @@ function checkDataset(definition) {
6579
6657
  if (definition.dataSets) {
6580
6658
  const invalidRanges = definition.dataSets.find((range) => !rangeReference.test(range)) !== undefined;
6581
6659
  if (invalidRanges) {
6582
- return 32 /* CommandResult.InvalidDataSet */;
6660
+ return 33 /* CommandResult.InvalidDataSet */;
6583
6661
  }
6584
6662
  const zones = definition.dataSets.map(toUnboundedZone);
6585
6663
  if (zones.some((zone) => zone.top !== zone.bottom && isFullRow(zone))) {
6586
- return 32 /* CommandResult.InvalidDataSet */;
6664
+ return 33 /* CommandResult.InvalidDataSet */;
6587
6665
  }
6588
6666
  }
6589
6667
  return 0 /* CommandResult.Success */;
@@ -6592,7 +6670,7 @@ function checkLabelRange(definition) {
6592
6670
  if (definition.labelRange) {
6593
6671
  const invalidLabels = !rangeReference.test(definition.labelRange || "");
6594
6672
  if (invalidLabels) {
6595
- return 33 /* CommandResult.InvalidLabelRange */;
6673
+ return 34 /* CommandResult.InvalidLabelRange */;
6596
6674
  }
6597
6675
  }
6598
6676
  return 0 /* CommandResult.Success */;
@@ -6678,24 +6756,24 @@ function getChartPositionAtCenterOfViewport(getters, chartSize) {
6678
6756
 
6679
6757
  const CfTerms = {
6680
6758
  Errors: {
6681
- [25 /* CommandResult.InvalidRange */]: _lt("The range is invalid"),
6682
- [51 /* CommandResult.FirstArgMissing */]: _lt("The argument is missing. Please provide a value"),
6683
- [52 /* CommandResult.SecondArgMissing */]: _lt("The second argument is missing. Please provide a value"),
6684
- [53 /* CommandResult.MinNaN */]: _lt("The minpoint must be a number"),
6685
- [54 /* CommandResult.MidNaN */]: _lt("The midpoint must be a number"),
6686
- [55 /* CommandResult.MaxNaN */]: _lt("The maxpoint must be a number"),
6687
- [56 /* CommandResult.ValueUpperInflectionNaN */]: _lt("The first value must be a number"),
6688
- [57 /* CommandResult.ValueLowerInflectionNaN */]: _lt("The second value must be a number"),
6689
- [47 /* CommandResult.MinBiggerThanMax */]: _lt("Minimum must be smaller then Maximum"),
6690
- [50 /* CommandResult.MinBiggerThanMid */]: _lt("Minimum must be smaller then Midpoint"),
6691
- [49 /* CommandResult.MidBiggerThanMax */]: _lt("Midpoint must be smaller then Maximum"),
6692
- [48 /* CommandResult.LowerBiggerThanUpper */]: _lt("Lower inflection point must be smaller than upper inflection point"),
6693
- [58 /* CommandResult.MinInvalidFormula */]: _lt("Invalid Minpoint formula"),
6694
- [60 /* CommandResult.MaxInvalidFormula */]: _lt("Invalid Maxpoint formula"),
6695
- [59 /* CommandResult.MidInvalidFormula */]: _lt("Invalid Midpoint formula"),
6696
- [61 /* CommandResult.ValueUpperInvalidFormula */]: _lt("Invalid upper inflection point formula"),
6697
- [62 /* CommandResult.ValueLowerInvalidFormula */]: _lt("Invalid lower inflection point formula"),
6698
- [24 /* CommandResult.EmptyRange */]: _lt("A range needs to be defined"),
6759
+ [26 /* CommandResult.InvalidRange */]: _lt("The range is invalid"),
6760
+ [52 /* CommandResult.FirstArgMissing */]: _lt("The argument is missing. Please provide a value"),
6761
+ [53 /* CommandResult.SecondArgMissing */]: _lt("The second argument is missing. Please provide a value"),
6762
+ [54 /* CommandResult.MinNaN */]: _lt("The minpoint must be a number"),
6763
+ [55 /* CommandResult.MidNaN */]: _lt("The midpoint must be a number"),
6764
+ [56 /* CommandResult.MaxNaN */]: _lt("The maxpoint must be a number"),
6765
+ [57 /* CommandResult.ValueUpperInflectionNaN */]: _lt("The first value must be a number"),
6766
+ [58 /* CommandResult.ValueLowerInflectionNaN */]: _lt("The second value must be a number"),
6767
+ [48 /* CommandResult.MinBiggerThanMax */]: _lt("Minimum must be smaller then Maximum"),
6768
+ [51 /* CommandResult.MinBiggerThanMid */]: _lt("Minimum must be smaller then Midpoint"),
6769
+ [50 /* CommandResult.MidBiggerThanMax */]: _lt("Midpoint must be smaller then Maximum"),
6770
+ [49 /* CommandResult.LowerBiggerThanUpper */]: _lt("Lower inflection point must be smaller than upper inflection point"),
6771
+ [59 /* CommandResult.MinInvalidFormula */]: _lt("Invalid Minpoint formula"),
6772
+ [61 /* CommandResult.MaxInvalidFormula */]: _lt("Invalid Maxpoint formula"),
6773
+ [60 /* CommandResult.MidInvalidFormula */]: _lt("Invalid Midpoint formula"),
6774
+ [62 /* CommandResult.ValueUpperInvalidFormula */]: _lt("Invalid upper inflection point formula"),
6775
+ [63 /* CommandResult.ValueLowerInvalidFormula */]: _lt("Invalid lower inflection point formula"),
6776
+ [25 /* CommandResult.EmptyRange */]: _lt("A range needs to be defined"),
6699
6777
  Unexpected: _lt("The rule is invalid for an unknown reason"),
6700
6778
  },
6701
6779
  ColorScale: _lt("Color scale"),
@@ -6722,20 +6800,20 @@ const ChartTerms = {
6722
6800
  Errors: {
6723
6801
  Unexpected: _lt("The chart definition is invalid for an unknown reason"),
6724
6802
  // BASIC CHART ERRORS (LINE | BAR | PIE)
6725
- [32 /* CommandResult.InvalidDataSet */]: _lt("The dataset is invalid"),
6726
- [33 /* CommandResult.InvalidLabelRange */]: _lt("Labels are invalid"),
6803
+ [33 /* CommandResult.InvalidDataSet */]: _lt("The dataset is invalid"),
6804
+ [34 /* CommandResult.InvalidLabelRange */]: _lt("Labels are invalid"),
6727
6805
  // SCORECARD CHART ERRORS
6728
- [34 /* CommandResult.InvalidScorecardKeyValue */]: _lt("The key value is invalid"),
6729
- [35 /* CommandResult.InvalidScorecardBaseline */]: _lt("The baseline value is invalid"),
6806
+ [35 /* CommandResult.InvalidScorecardKeyValue */]: _lt("The key value is invalid"),
6807
+ [36 /* CommandResult.InvalidScorecardBaseline */]: _lt("The baseline value is invalid"),
6730
6808
  // GAUGE CHART ERRORS
6731
- [36 /* CommandResult.InvalidGaugeDataRange */]: _lt("The data range is invalid"),
6732
- [37 /* CommandResult.EmptyGaugeRangeMin */]: _lt("A minimum range limit value is needed"),
6733
- [38 /* CommandResult.GaugeRangeMinNaN */]: _lt("The minimum range limit value must be a number"),
6734
- [39 /* CommandResult.EmptyGaugeRangeMax */]: _lt("A maximum range limit value is needed"),
6735
- [40 /* CommandResult.GaugeRangeMaxNaN */]: _lt("The maximum range limit value must be a number"),
6736
- [41 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */]: _lt("Minimum range limit must be smaller than maximum range limit"),
6737
- [42 /* CommandResult.GaugeLowerInflectionPointNaN */]: _lt("The lower inflection point value must be a number"),
6738
- [43 /* CommandResult.GaugeUpperInflectionPointNaN */]: _lt("The upper inflection point value must be a number"),
6809
+ [37 /* CommandResult.InvalidGaugeDataRange */]: _lt("The data range is invalid"),
6810
+ [38 /* CommandResult.EmptyGaugeRangeMin */]: _lt("A minimum range limit value is needed"),
6811
+ [39 /* CommandResult.GaugeRangeMinNaN */]: _lt("The minimum range limit value must be a number"),
6812
+ [40 /* CommandResult.EmptyGaugeRangeMax */]: _lt("A maximum range limit value is needed"),
6813
+ [41 /* CommandResult.GaugeRangeMaxNaN */]: _lt("The maximum range limit value must be a number"),
6814
+ [42 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */]: _lt("Minimum range limit must be smaller than maximum range limit"),
6815
+ [43 /* CommandResult.GaugeLowerInflectionPointNaN */]: _lt("The lower inflection point value must be a number"),
6816
+ [44 /* CommandResult.GaugeUpperInflectionPointNaN */]: _lt("The upper inflection point value must be a number"),
6739
6817
  },
6740
6818
  };
6741
6819
  const CustomCurrencyTerms = {
@@ -6745,9 +6823,9 @@ const MergeErrorMessage = _lt("Merged cells are preventing this operation. Unmer
6745
6823
  const SplitToColumnsTerms = {
6746
6824
  Errors: {
6747
6825
  Unexpected: _lt("Cannot split the selection for an unknown reason"),
6748
- [91 /* CommandResult.NoSplitSeparatorInSelection */]: _lt("There is no match for the selected separator in the selection"),
6749
- [88 /* CommandResult.MoreThanOneColumnSelected */]: _lt("Only a selection from a single column can be split"),
6750
- [90 /* CommandResult.SplitWillOverwriteContent */]: _lt("Splitting will overwrite existing content"),
6826
+ [92 /* CommandResult.NoSplitSeparatorInSelection */]: _lt("There is no match for the selected separator in the selection"),
6827
+ [89 /* CommandResult.MoreThanOneColumnSelected */]: _lt("Only a selection from a single column can be split"),
6828
+ [91 /* CommandResult.SplitWillOverwriteContent */]: _lt("Splitting will overwrite existing content"),
6751
6829
  },
6752
6830
  };
6753
6831
 
@@ -7151,7 +7229,7 @@ function createBarChartRuntime(chart, getters) {
7151
7229
 
7152
7230
  function isDataRangeValid(definition) {
7153
7231
  return definition.dataRange && !rangeReference.test(definition.dataRange)
7154
- ? 36 /* CommandResult.InvalidGaugeDataRange */
7232
+ ? 37 /* CommandResult.InvalidGaugeDataRange */
7155
7233
  : 0 /* CommandResult.Success */;
7156
7234
  }
7157
7235
  function checkRangeLimits(check, batchValidations) {
@@ -7183,7 +7261,7 @@ function checkInflectionPointsValue(check, batchValidations) {
7183
7261
  function checkRangeMinBiggerThanRangeMax(definition) {
7184
7262
  if (definition.sectionRule) {
7185
7263
  if (Number(definition.sectionRule.rangeMin) >= Number(definition.sectionRule.rangeMax)) {
7186
- return 41 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */;
7264
+ return 42 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */;
7187
7265
  }
7188
7266
  }
7189
7267
  return 0 /* CommandResult.Success */;
@@ -7192,9 +7270,9 @@ function checkEmpty(value, valueName) {
7192
7270
  if (value === "") {
7193
7271
  switch (valueName) {
7194
7272
  case "rangeMin":
7195
- return 37 /* CommandResult.EmptyGaugeRangeMin */;
7273
+ return 38 /* CommandResult.EmptyGaugeRangeMin */;
7196
7274
  case "rangeMax":
7197
- return 39 /* CommandResult.EmptyGaugeRangeMax */;
7275
+ return 40 /* CommandResult.EmptyGaugeRangeMax */;
7198
7276
  }
7199
7277
  }
7200
7278
  return 0 /* CommandResult.Success */;
@@ -7203,13 +7281,13 @@ function checkNaN(value, valueName) {
7203
7281
  if (isNaN(value)) {
7204
7282
  switch (valueName) {
7205
7283
  case "rangeMin":
7206
- return 38 /* CommandResult.GaugeRangeMinNaN */;
7284
+ return 39 /* CommandResult.GaugeRangeMinNaN */;
7207
7285
  case "rangeMax":
7208
- return 40 /* CommandResult.GaugeRangeMaxNaN */;
7286
+ return 41 /* CommandResult.GaugeRangeMaxNaN */;
7209
7287
  case "lowerInflectionPointValue":
7210
- return 42 /* CommandResult.GaugeLowerInflectionPointNaN */;
7288
+ return 43 /* CommandResult.GaugeLowerInflectionPointNaN */;
7211
7289
  case "upperInflectionPointValue":
7212
- return 43 /* CommandResult.GaugeUpperInflectionPointNaN */;
7290
+ return 44 /* CommandResult.GaugeUpperInflectionPointNaN */;
7213
7291
  }
7214
7292
  }
7215
7293
  return 0 /* CommandResult.Success */;
@@ -7985,12 +8063,12 @@ function createPieChartRuntime(chart, getters) {
7985
8063
 
7986
8064
  function checkKeyValue(definition) {
7987
8065
  return definition.keyValue && !rangeReference.test(definition.keyValue)
7988
- ? 34 /* CommandResult.InvalidScorecardKeyValue */
8066
+ ? 35 /* CommandResult.InvalidScorecardKeyValue */
7989
8067
  : 0 /* CommandResult.Success */;
7990
8068
  }
7991
8069
  function checkBaseline(definition) {
7992
8070
  return definition.baseline && !rangeReference.test(definition.baseline)
7993
- ? 35 /* CommandResult.InvalidScorecardBaseline */
8071
+ ? 36 /* CommandResult.InvalidScorecardBaseline */
7994
8072
  : 0 /* CommandResult.Success */;
7995
8073
  }
7996
8074
  class ScorecardChart extends AbstractChart {
@@ -8490,13 +8568,22 @@ function inverseUnhideColumnsRows(cmd) {
8490
8568
  ];
8491
8569
  }
8492
8570
 
8571
+ function interactiveCut(env) {
8572
+ const result = env.model.dispatch("CUT");
8573
+ if (!result.isSuccessful) {
8574
+ if (result.isCancelledBecause(20 /* CommandResult.WrongCutSelection */)) {
8575
+ env.raiseError(_lt("This operation is not allowed with multiple selections."));
8576
+ }
8577
+ }
8578
+ }
8579
+
8493
8580
  const AddMergeInteractiveContent = {
8494
8581
  MergeIsDestructive: _lt("Merging these cells will only preserve the top-leftmost value. Merge anyway?"),
8495
8582
  MergeInFilter: _lt("You can't merge cells inside of an existing filter."),
8496
8583
  };
8497
8584
  function interactiveAddMerge(env, sheetId, target) {
8498
8585
  const result = env.model.dispatch("ADD_MERGE", { sheetId, target });
8499
- if (result.isCancelledBecause(80 /* CommandResult.MergeInFilter */)) {
8586
+ if (result.isCancelledBecause(81 /* CommandResult.MergeInFilter */)) {
8500
8587
  env.raiseError(AddMergeInteractiveContent.MergeInFilter);
8501
8588
  }
8502
8589
  else if (result.isCancelledBecause(3 /* CommandResult.MergeIsDestructive */)) {
@@ -8506,279 +8593,6 @@ function interactiveAddMerge(env, sheetId, target) {
8506
8593
  }
8507
8594
  }
8508
8595
 
8509
- /**
8510
- * Create a function used to create a Chart based on the definition
8511
- */
8512
- function chartFactory(getters) {
8513
- const builders = chartRegistry.getAll().sort((a, b) => a.sequence - b.sequence);
8514
- function createChart(id, definition, sheetId) {
8515
- const builder = builders.find((builder) => builder.match(definition.type));
8516
- if (!builder) {
8517
- throw new Error(`No builder for this chart: ${definition.type}`);
8518
- }
8519
- return builder.createChart(definition, sheetId, getters);
8520
- }
8521
- return createChart;
8522
- }
8523
- /**
8524
- * Create a function used to create a Chart Runtime based on the chart class
8525
- * instance
8526
- */
8527
- function chartRuntimeFactory(getters) {
8528
- const builders = chartRegistry.getAll().sort((a, b) => a.sequence - b.sequence);
8529
- function createRuntimeChart(chart) {
8530
- const builder = builders.find((builder) => builder.match(chart.type));
8531
- if (!builder) {
8532
- throw new Error("No runtime builder for this chart.");
8533
- }
8534
- return builder.getChartRuntime(chart, getters);
8535
- }
8536
- return createRuntimeChart;
8537
- }
8538
- /**
8539
- * Validate the chart definition given in arguments
8540
- */
8541
- function validateChartDefinition(validator, definition) {
8542
- const validators = chartRegistry.getAll().find((validator) => validator.match(definition.type));
8543
- if (!validators) {
8544
- throw new Error("Unknown chart type.");
8545
- }
8546
- return validators.validateChartDefinition(validator, definition);
8547
- }
8548
- /**
8549
- * Get a new chart definition transformed with the executed command. This
8550
- * functions will be called during operational transform process
8551
- */
8552
- function transformDefinition(definition, executed) {
8553
- const transformation = chartRegistry.getAll().find((factory) => factory.match(definition.type));
8554
- if (!transformation) {
8555
- throw new Error("Unknown chart type.");
8556
- }
8557
- return transformation.transformDefinition(definition, executed);
8558
- }
8559
- /**
8560
- * Get an empty definition based on the given context and the given type
8561
- */
8562
- function getChartDefinitionFromContextCreation(context, type) {
8563
- const chartClass = chartRegistry.get(type);
8564
- return chartClass.getChartDefinitionFromContextCreation(context);
8565
- }
8566
- function getChartTypes() {
8567
- const result = {};
8568
- for (const key of chartRegistry.getKeys()) {
8569
- result[key] = chartRegistry.get(key).name;
8570
- }
8571
- return result;
8572
- }
8573
- /**
8574
- * Return a "smart" chart definition in the given zone. The definition is "smart" because it will
8575
- * use the best type of chart to display the data of the zone.
8576
- *
8577
- * It will also try to find labels and datasets in the range, and try to find title for the datasets.
8578
- *
8579
- * The type of chart will be :
8580
- * - If the zone is a single non-empty cell, returns a scorecard
8581
- * - If the all the labels are numbers/date, returns a line chart
8582
- * - Else returns a bar chart
8583
- */
8584
- function getSmartChartDefinition(zone, getters) {
8585
- let dataSetZone = zone;
8586
- if (zone.left !== zone.right) {
8587
- dataSetZone = { ...zone, left: zone.left + 1 };
8588
- }
8589
- const dataSets = [zoneToXc(dataSetZone)];
8590
- const sheetId = getters.getActiveSheetId();
8591
- const topLeftCell = getters.getCell({ sheetId, col: zone.left, row: zone.top });
8592
- if (getZoneArea(zone) === 1 && topLeftCell?.content) {
8593
- return {
8594
- type: "scorecard",
8595
- title: "",
8596
- background: topLeftCell.style?.fillColor || undefined,
8597
- keyValue: zoneToXc(zone),
8598
- baselineMode: DEFAULT_SCORECARD_BASELINE_MODE,
8599
- baselineColorUp: DEFAULT_SCORECARD_BASELINE_COLOR_UP,
8600
- baselineColorDown: DEFAULT_SCORECARD_BASELINE_COLOR_DOWN,
8601
- };
8602
- }
8603
- let title = "";
8604
- const cellsInFirstRow = getters.getEvaluatedCellsInZone(sheetId, {
8605
- ...dataSetZone,
8606
- bottom: dataSetZone.top,
8607
- });
8608
- const dataSetsHaveTitle = !!cellsInFirstRow.find((cell) => cell.type !== CellValueType.empty && cell.type !== CellValueType.number);
8609
- if (dataSetsHaveTitle) {
8610
- const texts = cellsInFirstRow
8611
- .filter((cell) => cell.type !== CellValueType.error && cell.type !== CellValueType.empty)
8612
- .map((cell) => cell.formattedValue);
8613
- const lastElement = texts.splice(-1)[0];
8614
- title = texts.join(", ");
8615
- if (lastElement) {
8616
- title += (title ? " " + _t("and") + " " : "") + lastElement;
8617
- }
8618
- }
8619
- let labelRangeXc;
8620
- if (zone.left !== zone.right) {
8621
- labelRangeXc = zoneToXc({
8622
- ...zone,
8623
- right: zone.left,
8624
- });
8625
- }
8626
- // Only display legend for several datasets.
8627
- const newLegendPos = dataSetZone.right === dataSetZone.left ? "none" : "top";
8628
- const labelRange = labelRangeXc ? getters.getRangeFromSheetXC(sheetId, labelRangeXc) : undefined;
8629
- if (canChartParseLabels(labelRange, getters)) {
8630
- return {
8631
- title,
8632
- dataSets,
8633
- labelsAsText: false,
8634
- stacked: false,
8635
- aggregated: false,
8636
- labelRange: labelRangeXc,
8637
- type: "line",
8638
- dataSetsHaveTitle,
8639
- verticalAxisPosition: "left",
8640
- legendPosition: newLegendPos,
8641
- };
8642
- }
8643
- return {
8644
- title,
8645
- dataSets,
8646
- labelRange: labelRangeXc,
8647
- type: "bar",
8648
- stacked: false,
8649
- aggregated: false,
8650
- dataSetsHaveTitle,
8651
- verticalAxisPosition: "left",
8652
- legendPosition: newLegendPos,
8653
- };
8654
- }
8655
-
8656
- const SORT_TYPES = [
8657
- CellValueType.number,
8658
- CellValueType.error,
8659
- CellValueType.text,
8660
- CellValueType.boolean,
8661
- ];
8662
- function sortCells(cells, sortDirection, emptyCellAsZero) {
8663
- const cellsWithIndex = cells.map((cell, index) => ({
8664
- index,
8665
- type: cell.type,
8666
- value: cell.value,
8667
- }));
8668
- let emptyCells = cellsWithIndex.filter((x) => x.type === CellValueType.empty);
8669
- let nonEmptyCells = cellsWithIndex.filter((x) => x.type !== CellValueType.empty);
8670
- if (emptyCellAsZero) {
8671
- nonEmptyCells.push(...emptyCells.map((emptyCell) => ({ ...emptyCell, type: CellValueType.number, value: 0 })));
8672
- emptyCells = [];
8673
- }
8674
- const inverse = sortDirection === "descending" ? -1 : 1;
8675
- return nonEmptyCells
8676
- .sort((left, right) => {
8677
- let typeOrder = SORT_TYPES.indexOf(left.type) - SORT_TYPES.indexOf(right.type);
8678
- if (typeOrder === 0) {
8679
- if (left.type === CellValueType.text || left.type === CellValueType.error) {
8680
- typeOrder = left.value.localeCompare(right.value);
8681
- }
8682
- else
8683
- typeOrder = left.value - right.value;
8684
- }
8685
- return inverse * typeOrder;
8686
- })
8687
- .concat(emptyCells);
8688
- }
8689
- function interactiveSortSelection(env, sheetId, anchor, zone, sortDirection) {
8690
- let result = DispatchResult.Success;
8691
- //several columns => bypass the contiguity check
8692
- let multiColumns = zone.right > zone.left;
8693
- if (env.model.getters.doesIntersectMerge(sheetId, zone)) {
8694
- multiColumns = false;
8695
- let table;
8696
- for (let row = zone.top; row <= zone.bottom; row++) {
8697
- table = [];
8698
- for (let col = zone.left; col <= zone.right; col++) {
8699
- let merge = env.model.getters.getMerge({ sheetId, col, row });
8700
- if (merge && !table.includes(merge.id.toString())) {
8701
- table.push(merge.id.toString());
8702
- }
8703
- }
8704
- if (table.length >= 2) {
8705
- multiColumns = true;
8706
- break;
8707
- }
8708
- }
8709
- }
8710
- const { col, row } = anchor;
8711
- if (multiColumns) {
8712
- result = env.model.dispatch("SORT_CELLS", { sheetId, col, row, zone, sortDirection });
8713
- }
8714
- else {
8715
- // check contiguity
8716
- const contiguousZone = env.model.getters.getContiguousZone(sheetId, zone);
8717
- if (isEqual(contiguousZone, zone)) {
8718
- // merge as it is
8719
- result = env.model.dispatch("SORT_CELLS", {
8720
- sheetId,
8721
- col,
8722
- row,
8723
- zone,
8724
- sortDirection,
8725
- });
8726
- }
8727
- else {
8728
- 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?"), () => {
8729
- zone = contiguousZone;
8730
- result = env.model.dispatch("SORT_CELLS", {
8731
- sheetId,
8732
- col,
8733
- row,
8734
- zone,
8735
- sortDirection,
8736
- });
8737
- }, () => {
8738
- result = env.model.dispatch("SORT_CELLS", {
8739
- sheetId,
8740
- col,
8741
- row,
8742
- zone,
8743
- sortDirection,
8744
- });
8745
- });
8746
- }
8747
- }
8748
- if (result.isCancelledBecause(63 /* CommandResult.InvalidSortZone */)) {
8749
- const { col, row } = anchor;
8750
- env.model.selection.selectZone({ cell: { col, row }, zone });
8751
- env.raiseError(_lt("Cannot sort. To sort, select only cells or only merges that have the same size."));
8752
- }
8753
- }
8754
-
8755
- function interactiveCut(env) {
8756
- const result = env.model.dispatch("CUT");
8757
- if (!result.isSuccessful) {
8758
- if (result.isCancelledBecause(19 /* CommandResult.WrongCutSelection */)) {
8759
- env.raiseError(_lt("This operation is not allowed with multiple selections."));
8760
- }
8761
- }
8762
- }
8763
-
8764
- const AddFilterInteractiveContent = {
8765
- filterOverlap: _lt("You cannot create overlapping filters."),
8766
- nonContinuousTargets: _lt("A filter can only be created on a continuous selection."),
8767
- mergeInFilter: _lt("You can't create a filter over a range that contains a merge."),
8768
- };
8769
- function interactiveAddFilter(env, sheetId, target) {
8770
- const result = env.model.dispatch("CREATE_FILTER_TABLE", { target, sheetId });
8771
- if (result.isCancelledBecause(78 /* CommandResult.FilterOverlap */)) {
8772
- env.raiseError(AddFilterInteractiveContent.filterOverlap);
8773
- }
8774
- else if (result.isCancelledBecause(80 /* CommandResult.MergeInFilter */)) {
8775
- env.raiseError(AddFilterInteractiveContent.mergeInFilter);
8776
- }
8777
- else if (result.isCancelledBecause(81 /* CommandResult.NonContinuousTargets */)) {
8778
- env.raiseError(AddFilterInteractiveContent.nonContinuousTargets);
8779
- }
8780
- }
8781
-
8782
8596
  const PasteInteractiveContent = {
8783
8597
  wrongPasteSelection: _lt("This operation is not allowed with multiple selections."),
8784
8598
  willRemoveExistingMerge: _lt("This operation is not possible due to a merge. Please remove the merges first than try again."),
@@ -8787,16 +8601,16 @@ const PasteInteractiveContent = {
8787
8601
  };
8788
8602
  function handlePasteResult(env, result) {
8789
8603
  if (!result.isSuccessful) {
8790
- if (result.reasons.includes(20 /* CommandResult.WrongPasteSelection */)) {
8604
+ if (result.reasons.includes(21 /* CommandResult.WrongPasteSelection */)) {
8791
8605
  env.raiseError(PasteInteractiveContent.wrongPasteSelection);
8792
8606
  }
8793
8607
  else if (result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
8794
8608
  env.raiseError(PasteInteractiveContent.willRemoveExistingMerge);
8795
8609
  }
8796
- else if (result.reasons.includes(22 /* CommandResult.WrongFigurePasteOption */)) {
8610
+ else if (result.reasons.includes(23 /* CommandResult.WrongFigurePasteOption */)) {
8797
8611
  env.raiseError(PasteInteractiveContent.wrongFigurePasteOption);
8798
8612
  }
8799
- else if (result.reasons.includes(75 /* CommandResult.FrozenPaneOverlap */)) {
8613
+ else if (result.reasons.includes(76 /* CommandResult.FrozenPaneOverlap */)) {
8800
8614
  env.raiseError(PasteInteractiveContent.frozenPaneOverlap);
8801
8615
  }
8802
8616
  }
@@ -8805,34 +8619,161 @@ function interactivePaste(env, target, pasteOption) {
8805
8619
  const result = env.model.dispatch("PASTE", { target, pasteOption });
8806
8620
  handlePasteResult(env, result);
8807
8621
  }
8808
- function interactivePasteFromOS(env, target, text) {
8809
- const result = env.model.dispatch("PASTE_FROM_OS_CLIPBOARD", { target, text });
8622
+ function interactivePasteFromOS(env, target, text, pasteOption) {
8623
+ const result = env.model.dispatch("PASTE_FROM_OS_CLIPBOARD", { target, text, pasteOption });
8810
8624
  handlePasteResult(env, result);
8811
8625
  }
8812
8626
 
8813
- //------------------------------------------------------------------------------
8814
- // Helpers
8815
- //------------------------------------------------------------------------------
8816
- function getColumnsNumber(env) {
8817
- const activeCols = env.model.getters.getActiveCols();
8818
- if (activeCols.size) {
8819
- return activeCols.size;
8627
+ /**
8628
+ * Create a function used to create a Chart based on the definition
8629
+ */
8630
+ function chartFactory(getters) {
8631
+ const builders = chartRegistry.getAll().sort((a, b) => a.sequence - b.sequence);
8632
+ function createChart(id, definition, sheetId) {
8633
+ const builder = builders.find((builder) => builder.match(definition.type));
8634
+ if (!builder) {
8635
+ throw new Error(`No builder for this chart: ${definition.type}`);
8636
+ }
8637
+ return builder.createChart(definition, sheetId, getters);
8820
8638
  }
8821
- else {
8822
- const zone = env.model.getters.getSelectedZones()[0];
8823
- return zone.right - zone.left + 1;
8639
+ return createChart;
8640
+ }
8641
+ /**
8642
+ * Create a function used to create a Chart Runtime based on the chart class
8643
+ * instance
8644
+ */
8645
+ function chartRuntimeFactory(getters) {
8646
+ const builders = chartRegistry.getAll().sort((a, b) => a.sequence - b.sequence);
8647
+ function createRuntimeChart(chart) {
8648
+ const builder = builders.find((builder) => builder.match(chart.type));
8649
+ if (!builder) {
8650
+ throw new Error("No runtime builder for this chart.");
8651
+ }
8652
+ return builder.getChartRuntime(chart, getters);
8824
8653
  }
8654
+ return createRuntimeChart;
8825
8655
  }
8826
- function getRowsNumber(env) {
8827
- const activeRows = env.model.getters.getActiveRows();
8828
- if (activeRows.size) {
8829
- return activeRows.size;
8656
+ /**
8657
+ * Validate the chart definition given in arguments
8658
+ */
8659
+ function validateChartDefinition(validator, definition) {
8660
+ const validators = chartRegistry.getAll().find((validator) => validator.match(definition.type));
8661
+ if (!validators) {
8662
+ throw new Error("Unknown chart type.");
8830
8663
  }
8831
- else {
8832
- const zone = env.model.getters.getSelectedZones()[0];
8833
- return zone.bottom - zone.top + 1;
8664
+ return validators.validateChartDefinition(validator, definition);
8665
+ }
8666
+ /**
8667
+ * Get a new chart definition transformed with the executed command. This
8668
+ * functions will be called during operational transform process
8669
+ */
8670
+ function transformDefinition(definition, executed) {
8671
+ const transformation = chartRegistry.getAll().find((factory) => factory.match(definition.type));
8672
+ if (!transformation) {
8673
+ throw new Error("Unknown chart type.");
8674
+ }
8675
+ return transformation.transformDefinition(definition, executed);
8676
+ }
8677
+ /**
8678
+ * Get an empty definition based on the given context and the given type
8679
+ */
8680
+ function getChartDefinitionFromContextCreation(context, type) {
8681
+ const chartClass = chartRegistry.get(type);
8682
+ return chartClass.getChartDefinitionFromContextCreation(context);
8683
+ }
8684
+ function getChartTypes() {
8685
+ const result = {};
8686
+ for (const key of chartRegistry.getKeys()) {
8687
+ result[key] = chartRegistry.get(key).name;
8834
8688
  }
8689
+ return result;
8835
8690
  }
8691
+ /**
8692
+ * Return a "smart" chart definition in the given zone. The definition is "smart" because it will
8693
+ * use the best type of chart to display the data of the zone.
8694
+ *
8695
+ * It will also try to find labels and datasets in the range, and try to find title for the datasets.
8696
+ *
8697
+ * The type of chart will be :
8698
+ * - If the zone is a single non-empty cell, returns a scorecard
8699
+ * - If the all the labels are numbers/date, returns a line chart
8700
+ * - Else returns a bar chart
8701
+ */
8702
+ function getSmartChartDefinition(zone, getters) {
8703
+ let dataSetZone = zone;
8704
+ if (zone.left !== zone.right) {
8705
+ dataSetZone = { ...zone, left: zone.left + 1 };
8706
+ }
8707
+ const dataSets = [zoneToXc(dataSetZone)];
8708
+ const sheetId = getters.getActiveSheetId();
8709
+ const topLeftCell = getters.getCell({ sheetId, col: zone.left, row: zone.top });
8710
+ if (getZoneArea(zone) === 1 && topLeftCell?.content) {
8711
+ return {
8712
+ type: "scorecard",
8713
+ title: "",
8714
+ background: topLeftCell.style?.fillColor || undefined,
8715
+ keyValue: zoneToXc(zone),
8716
+ baselineMode: DEFAULT_SCORECARD_BASELINE_MODE,
8717
+ baselineColorUp: DEFAULT_SCORECARD_BASELINE_COLOR_UP,
8718
+ baselineColorDown: DEFAULT_SCORECARD_BASELINE_COLOR_DOWN,
8719
+ };
8720
+ }
8721
+ let title = "";
8722
+ const cellsInFirstRow = getters.getEvaluatedCellsInZone(sheetId, {
8723
+ ...dataSetZone,
8724
+ bottom: dataSetZone.top,
8725
+ });
8726
+ const dataSetsHaveTitle = !!cellsInFirstRow.find((cell) => cell.type !== CellValueType.empty && cell.type !== CellValueType.number);
8727
+ if (dataSetsHaveTitle) {
8728
+ const texts = cellsInFirstRow
8729
+ .filter((cell) => cell.type !== CellValueType.error && cell.type !== CellValueType.empty)
8730
+ .map((cell) => cell.formattedValue);
8731
+ const lastElement = texts.splice(-1)[0];
8732
+ title = texts.join(", ");
8733
+ if (lastElement) {
8734
+ title += (title ? " " + _t("and") + " " : "") + lastElement;
8735
+ }
8736
+ }
8737
+ let labelRangeXc;
8738
+ if (zone.left !== zone.right) {
8739
+ labelRangeXc = zoneToXc({
8740
+ ...zone,
8741
+ right: zone.left,
8742
+ });
8743
+ }
8744
+ // Only display legend for several datasets.
8745
+ const newLegendPos = dataSetZone.right === dataSetZone.left ? "none" : "top";
8746
+ const labelRange = labelRangeXc ? getters.getRangeFromSheetXC(sheetId, labelRangeXc) : undefined;
8747
+ if (canChartParseLabels(labelRange, getters)) {
8748
+ return {
8749
+ title,
8750
+ dataSets,
8751
+ labelsAsText: false,
8752
+ stacked: false,
8753
+ aggregated: false,
8754
+ labelRange: labelRangeXc,
8755
+ type: "line",
8756
+ dataSetsHaveTitle,
8757
+ verticalAxisPosition: "left",
8758
+ legendPosition: newLegendPos,
8759
+ };
8760
+ }
8761
+ return {
8762
+ title,
8763
+ dataSets,
8764
+ labelRange: labelRangeXc,
8765
+ type: "bar",
8766
+ stacked: false,
8767
+ aggregated: false,
8768
+ dataSetsHaveTitle,
8769
+ verticalAxisPosition: "left",
8770
+ legendPosition: newLegendPos,
8771
+ };
8772
+ }
8773
+
8774
+ //------------------------------------------------------------------------------
8775
+ // Helpers
8776
+ //------------------------------------------------------------------------------
8836
8777
  function setFormatter(env, format) {
8837
8778
  env.model.dispatch("SET_FORMATTING", {
8838
8779
  sheetId: env.model.getters.getActiveSheetId(),
@@ -8850,16 +8791,6 @@ function setStyle(env, style) {
8850
8791
  //------------------------------------------------------------------------------
8851
8792
  // Simple actions
8852
8793
  //------------------------------------------------------------------------------
8853
- const UNDO_ACTION = (env) => env.model.dispatch("REQUEST_UNDO");
8854
- const REDO_ACTION = (env) => env.model.dispatch("REQUEST_REDO");
8855
- const COPY_ACTION = async (env) => {
8856
- env.model.dispatch("COPY");
8857
- await env.clipboard.write(env.model.getters.getClipboardContent());
8858
- };
8859
- const CUT_ACTION = async (env) => {
8860
- interactiveCut(env);
8861
- await env.clipboard.write(env.model.getters.getClipboardContent());
8862
- };
8863
8794
  const PASTE_ACTION = async (env) => paste$1(env);
8864
8795
  const PASTE_VALUE_ACTION = async (env) => paste$1(env, "onlyValue");
8865
8796
  async function paste$1(env, pasteOption) {
@@ -8869,11 +8800,14 @@ async function paste$1(env, pasteOption) {
8869
8800
  case "ok":
8870
8801
  const target = env.model.getters.getSelectedZones();
8871
8802
  if (osClipboard && osClipboard.content !== spreadsheetClipboard) {
8872
- interactivePasteFromOS(env, target, osClipboard.content);
8803
+ interactivePasteFromOS(env, target, osClipboard.content, pasteOption);
8873
8804
  }
8874
8805
  else {
8875
8806
  interactivePaste(env, target, pasteOption);
8876
8807
  }
8808
+ if (env.model.getters.isCutOperation() && pasteOption !== "onlyValue") {
8809
+ await env.clipboard.write({ [ClipboardMIMEType.PlainText]: "" });
8810
+ }
8877
8811
  break;
8878
8812
  case "notImplemented":
8879
8813
  env.raiseError(_lt("Pasting from the context menu is not supported in this browser. Use keyboard shortcuts ctrl+c / ctrl+v instead."));
@@ -8883,22 +8817,7 @@ async function paste$1(env, pasteOption) {
8883
8817
  break;
8884
8818
  }
8885
8819
  }
8886
- const PASTE_FORMAT_ACTION = (env) => interactivePaste(env, env.model.getters.getSelectedZones(), "onlyFormat");
8887
- const DELETE_CONTENT_ACTION = (env) => env.model.dispatch("DELETE_CONTENT", {
8888
- sheetId: env.model.getters.getActiveSheetId(),
8889
- target: env.model.getters.getSelectedZones(),
8890
- });
8891
- const SET_FORMULA_VISIBILITY_ACTION = (env) => env.model.dispatch("SET_FORMULA_VISIBILITY", { show: !env.model.getters.shouldShowFormulas() });
8892
- const SET_GRID_LINES_VISIBILITY_ACTION = (env) => {
8893
- const sheetId = env.model.getters.getActiveSheetId();
8894
- env.model.dispatch("SET_GRID_LINES_VISIBILITY", {
8895
- sheetId,
8896
- areGridLinesVisible: !env.model.getters.getGridLinesVisibility(sheetId),
8897
- });
8898
- };
8899
- const IS_NOT_CUT_OPERATION = (env) => {
8900
- return !env.model.getters.isCutOperation();
8901
- };
8820
+ const PASTE_FORMAT_ACTION = (env) => paste$1(env, "onlyFormat");
8902
8821
  //------------------------------------------------------------------------------
8903
8822
  // Grid manipulations
8904
8823
  //------------------------------------------------------------------------------
@@ -9040,48 +8959,6 @@ const NOT_ALL_VISIBLE_COLS_SELECTED = (env) => {
9040
8959
  const selectedCols = env.model.getters.getElementsFromSelection("COL");
9041
8960
  return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
9042
8961
  };
9043
- const INSERT_CELL_SHIFT_DOWN = (env) => {
9044
- const zone = env.model.getters.getSelectedZone();
9045
- const result = env.model.dispatch("INSERT_CELL", { zone, shiftDimension: "ROW" });
9046
- handlePasteResult(env, result);
9047
- };
9048
- const INSERT_CELL_SHIFT_RIGHT = (env) => {
9049
- const zone = env.model.getters.getSelectedZone();
9050
- const result = env.model.dispatch("INSERT_CELL", { zone, shiftDimension: "COL" });
9051
- handlePasteResult(env, result);
9052
- };
9053
- const DELETE_CELL_SHIFT_UP = (env) => {
9054
- const zone = env.model.getters.getSelectedZone();
9055
- const result = env.model.dispatch("DELETE_CELL", { zone, shiftDimension: "ROW" });
9056
- handlePasteResult(env, result);
9057
- };
9058
- const DELETE_CELL_SHIFT_LEFT = (env) => {
9059
- const zone = env.model.getters.getSelectedZone();
9060
- const result = env.model.dispatch("DELETE_CELL", { zone, shiftDimension: "COL" });
9061
- handlePasteResult(env, result);
9062
- };
9063
- const MENU_INSERT_ROWS_NAME = (env) => {
9064
- const number = getRowsNumber(env);
9065
- return number === 1 ? _lt("Insert row") : _lt("Insert %s rows", number.toString());
9066
- };
9067
- const MENU_INSERT_ROWS_BEFORE_NAME = (env) => {
9068
- const number = getRowsNumber(env);
9069
- if (number === 1) {
9070
- return _lt("Row above");
9071
- }
9072
- return _lt("%s Rows above", number.toString());
9073
- };
9074
- const ROW_INSERT_ROWS_BEFORE_NAME = (env) => {
9075
- const number = getRowsNumber(env);
9076
- return number === 1 ? _lt("Insert row above") : _lt("Insert %s rows above", number.toString());
9077
- };
9078
- const CELL_INSERT_ROWS_BEFORE_NAME = (env) => {
9079
- const number = getRowsNumber(env);
9080
- if (number === 1) {
9081
- return _lt("Insert row");
9082
- }
9083
- return _lt("Insert %s rows", number.toString());
9084
- };
9085
8962
  const INSERT_ROWS_BEFORE_ACTION = (env) => {
9086
8963
  const activeRows = env.model.getters.getActiveRows();
9087
8964
  let row;
@@ -9103,17 +8980,6 @@ const INSERT_ROWS_BEFORE_ACTION = (env) => {
9103
8980
  dimension: "ROW",
9104
8981
  });
9105
8982
  };
9106
- const MENU_INSERT_ROWS_AFTER_NAME = (env) => {
9107
- const number = getRowsNumber(env);
9108
- if (number === 1) {
9109
- return _lt("Row below");
9110
- }
9111
- return _lt("%s Rows below", number.toString());
9112
- };
9113
- const ROW_INSERT_ROWS_AFTER_NAME = (env) => {
9114
- const number = getRowsNumber(env);
9115
- return number === 1 ? _lt("Insert row below") : _lt("Insert %s rows below", number.toString());
9116
- };
9117
8983
  const INSERT_ROWS_AFTER_ACTION = (env) => {
9118
8984
  const activeRows = env.model.getters.getActiveRows();
9119
8985
  let row;
@@ -9135,30 +9001,6 @@ const INSERT_ROWS_AFTER_ACTION = (env) => {
9135
9001
  dimension: "ROW",
9136
9002
  });
9137
9003
  };
9138
- const MENU_INSERT_COLUMNS_BEFORE_NAME = (env) => {
9139
- const number = getColumnsNumber(env);
9140
- if (number === 1) {
9141
- return _lt("Column left");
9142
- }
9143
- return _lt("%s Columns left", number.toString());
9144
- };
9145
- const MENU_INSERT_COLUMNS_NAME = (env) => {
9146
- const number = getColumnsNumber(env);
9147
- return number === 1 ? _lt("Insert column") : _lt("Insert %s columns", number.toString());
9148
- };
9149
- const COLUMN_INSERT_COLUMNS_BEFORE_NAME = (env) => {
9150
- const number = getColumnsNumber(env);
9151
- return number === 1
9152
- ? _lt("Insert column left")
9153
- : _lt("Insert %s columns left", number.toString());
9154
- };
9155
- const CELL_INSERT_COLUMNS_BEFORE_NAME = (env) => {
9156
- const number = getColumnsNumber(env);
9157
- if (number === 1) {
9158
- return _lt("Insert column");
9159
- }
9160
- return _lt("Insert %s columns", number.toString());
9161
- };
9162
9004
  const INSERT_COLUMNS_BEFORE_ACTION = (env) => {
9163
9005
  const activeCols = env.model.getters.getActiveCols();
9164
9006
  let column;
@@ -9180,19 +9022,6 @@ const INSERT_COLUMNS_BEFORE_ACTION = (env) => {
9180
9022
  quantity,
9181
9023
  });
9182
9024
  };
9183
- const MENU_INSERT_COLUMNS_AFTER_NAME = (env) => {
9184
- const number = getColumnsNumber(env);
9185
- if (number === 1) {
9186
- return _lt("Column right");
9187
- }
9188
- return _lt("%s Columns right", number.toString());
9189
- };
9190
- const COLUMN_INSERT_COLUMNS_AFTER_NAME = (env) => {
9191
- const number = getColumnsNumber(env);
9192
- return number === 1
9193
- ? _lt("Insert column right")
9194
- : _lt("Insert %s columns right", number.toString());
9195
- };
9196
9025
  const INSERT_COLUMNS_AFTER_ACTION = (env) => {
9197
9026
  const activeCols = env.model.getters.getActiveCols();
9198
9027
  let column;
@@ -9228,30 +9057,6 @@ const HIDE_COLUMNS_NAME = (env) => {
9228
9057
  return _lt("Hide columns");
9229
9058
  }
9230
9059
  };
9231
- const HIDE_COLUMNS_ACTION = (env) => {
9232
- const columns = env.model.getters.getElementsFromSelection("COL");
9233
- env.model.dispatch("HIDE_COLUMNS_ROWS", {
9234
- sheetId: env.model.getters.getActiveSheetId(),
9235
- dimension: "COL",
9236
- elements: columns,
9237
- });
9238
- };
9239
- const UNHIDE_ALL_COLUMNS_ACTION = (env) => {
9240
- const sheetId = env.model.getters.getActiveSheetId();
9241
- env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
9242
- sheetId,
9243
- dimension: "COL",
9244
- elements: Array.from(Array(env.model.getters.getNumberCols(sheetId)).keys()),
9245
- });
9246
- };
9247
- const UNHIDE_COLUMNS_ACTION = (env) => {
9248
- const columns = env.model.getters.getElementsFromSelection("COL");
9249
- env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
9250
- sheetId: env.model.getters.getActiveSheetId(),
9251
- dimension: "COL",
9252
- elements: columns,
9253
- });
9254
- };
9255
9060
  const HIDE_ROWS_NAME = (env) => {
9256
9061
  const rows = env.model.getters.getElementsFromSelection("ROW");
9257
9062
  let first = rows[0];
@@ -9266,40 +9071,6 @@ const HIDE_ROWS_NAME = (env) => {
9266
9071
  return _lt("Hide rows");
9267
9072
  }
9268
9073
  };
9269
- const HIDE_ROWS_ACTION = (env) => {
9270
- const rows = env.model.getters.getElementsFromSelection("ROW");
9271
- env.model.dispatch("HIDE_COLUMNS_ROWS", {
9272
- sheetId: env.model.getters.getActiveSheetId(),
9273
- dimension: "ROW",
9274
- elements: rows,
9275
- });
9276
- };
9277
- const UNHIDE_ALL_ROWS_ACTION = (env) => {
9278
- const sheetId = env.model.getters.getActiveSheetId();
9279
- env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
9280
- sheetId,
9281
- dimension: "ROW",
9282
- elements: Array.from(Array(env.model.getters.getNumberRows(sheetId)).keys()),
9283
- });
9284
- };
9285
- const UNHIDE_ROWS_ACTION = (env) => {
9286
- const columns = env.model.getters.getElementsFromSelection("ROW");
9287
- env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
9288
- sheetId: env.model.getters.getActiveSheetId(),
9289
- dimension: "ROW",
9290
- elements: columns,
9291
- });
9292
- };
9293
- //------------------------------------------------------------------------------
9294
- // Sheets
9295
- //------------------------------------------------------------------------------
9296
- const CREATE_SHEET_ACTION = (env) => {
9297
- const activeSheetId = env.model.getters.getActiveSheetId();
9298
- const position = env.model.getters.getSheetIds().indexOf(activeSheetId) + 1;
9299
- const sheetId = env.model.uuidGenerator.uuidv4();
9300
- env.model.dispatch("CREATE_SHEET", { sheetId, position });
9301
- env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
9302
- };
9303
9074
  //------------------------------------------------------------------------------
9304
9075
  // Charts
9305
9076
  //------------------------------------------------------------------------------
@@ -9358,37 +9129,13 @@ const CREATE_IMAGE = async (env) => {
9358
9129
  //------------------------------------------------------------------------------
9359
9130
  // Style/Format
9360
9131
  //------------------------------------------------------------------------------
9361
- const FORMAT_AUTOMATIC_ACTION = (env) => setFormatter(env, "");
9362
- const FORMAT_NUMBER_ACTION = (env) => setFormatter(env, "#,##0.00");
9363
9132
  const FORMAT_PERCENT_ACTION = (env) => setFormatter(env, "0.00%");
9364
- const FORMAT_CURRENCY_ACTION = (env) => setFormatter(env, "[$$]#,##0.00");
9365
- const FORMAT_CURRENCY_ROUNDED_ACTION = (env) => setFormatter(env, "[$$]#,##0");
9366
- const FORMAT_DATE_ACTION = (env) => setFormatter(env, "m/d/yyyy");
9367
- const FORMAT_TIME_ACTION = (env) => setFormatter(env, "hh:mm:ss a");
9368
- const FORMAT_DATE_TIME_ACTION = (env) => setFormatter(env, "m/d/yyyy hh:mm:ss");
9369
- const FORMAT_DURATION_ACTION = (env) => setFormatter(env, "hhhh:mm:ss");
9370
- const FORMAT_BOLD_ACTION = (env) => setStyle(env, { bold: !env.model.getters.getCurrentStyle().bold });
9371
- const FORMAT_ITALIC_ACTION = (env) => setStyle(env, { italic: !env.model.getters.getCurrentStyle().italic });
9372
- const FORMAT_STRIKETHROUGH_ACTION = (env) => setStyle(env, { strikethrough: !env.model.getters.getCurrentStyle().strikethrough });
9373
- const FORMAT_UNDERLINE_ACTION = (env) => setStyle(env, { underline: !env.model.getters.getCurrentStyle().underline });
9374
- const FORMAT_CLEARFORMAT_ACTION = (env) => {
9375
- env.model.dispatch("CLEAR_FORMATTING", {
9376
- sheetId: env.model.getters.getActiveSheetId(),
9377
- target: env.model.getters.getSelectedZones(),
9378
- });
9379
- };
9380
9133
  //------------------------------------------------------------------------------
9381
9134
  // Side panel
9382
9135
  //------------------------------------------------------------------------------
9383
9136
  const OPEN_CF_SIDEPANEL_ACTION = (env) => {
9384
9137
  env.openSidePanel("ConditionalFormatting", { selection: env.model.getters.getSelectedZones() });
9385
9138
  };
9386
- const OPEN_FAR_SIDEPANEL_ACTION = (env) => {
9387
- env.openSidePanel("FindAndReplace", {});
9388
- };
9389
- const OPEN_CUSTOM_CURRENCY_SIDEPANEL_ACTION = (env) => {
9390
- env.openSidePanel("CustomCurrency", {});
9391
- };
9392
9139
  const INSERT_LINK = (env) => {
9393
9140
  let { col, row } = env.model.getters.getActivePosition();
9394
9141
  env.model.dispatch("OPEN_CELL_POPOVER", { col, row, popoverType: "LinkEditor" });
@@ -9396,40 +9143,14 @@ const INSERT_LINK = (env) => {
9396
9143
  //------------------------------------------------------------------------------
9397
9144
  // Filters action
9398
9145
  //------------------------------------------------------------------------------
9399
- const FILTERS_CREATE_FILTER_TABLE = (env) => {
9400
- const sheetId = env.model.getters.getActiveSheetId();
9401
- const selection = env.model.getters.getSelection().zones;
9402
- interactiveAddFilter(env, sheetId, selection);
9403
- };
9404
- const FILTERS_REMOVE_FILTER_TABLE = (env) => {
9405
- const sheetId = env.model.getters.getActiveSheetId();
9406
- env.model.dispatch("REMOVE_FILTER_TABLE", {
9407
- sheetId,
9408
- target: env.model.getters.getSelectedZones(),
9409
- });
9410
- };
9411
9146
  const SELECTION_CONTAINS_FILTER = (env) => {
9412
9147
  const sheetId = env.model.getters.getActiveSheetId();
9413
9148
  const selectedZones = env.model.getters.getSelectedZones();
9414
9149
  return env.model.getters.doesZonesContainFilter(sheetId, selectedZones);
9415
9150
  };
9416
- const SELECTION_IS_CONTINUOUS = (env) => {
9417
- const selectedZones = env.model.getters.getSelectedZones();
9418
- return areZonesContinuous(...selectedZones);
9419
- };
9420
9151
  //------------------------------------------------------------------------------
9421
9152
  // Sorting action
9422
9153
  //------------------------------------------------------------------------------
9423
- const SORT_CELLS_ASCENDING = (env) => {
9424
- const { anchor, zones } = env.model.getters.getSelection();
9425
- const sheetId = env.model.getters.getActiveSheetId();
9426
- interactiveSortSelection(env, sheetId, anchor.cell, zones[0], "ascending");
9427
- };
9428
- const SORT_CELLS_DESCENDING = (env) => {
9429
- const { anchor, zones } = env.model.getters.getSelection();
9430
- const sheetId = env.model.getters.getActiveSheetId();
9431
- interactiveSortSelection(env, sheetId, anchor.cell, zones[0], "descending");
9432
- };
9433
9154
  const IS_ONLY_ONE_RANGE = (env) => {
9434
9155
  return env.model.getters.getSelectedZones().length === 1;
9435
9156
  };
@@ -9437,14 +9158,14 @@ const IS_ONLY_ONE_RANGE = (env) => {
9437
9158
  const undo = {
9438
9159
  name: _lt("Undo"),
9439
9160
  description: "Ctrl+Z",
9440
- execute: UNDO_ACTION,
9161
+ execute: (env) => env.model.dispatch("REQUEST_UNDO"),
9441
9162
  isEnabled: (env) => env.model.getters.canUndo(),
9442
9163
  icon: "o-spreadsheet-Icon.UNDO",
9443
9164
  };
9444
9165
  const redo = {
9445
9166
  name: _lt("Redo"),
9446
9167
  description: "Ctrl+Y",
9447
- execute: REDO_ACTION,
9168
+ execute: (env) => env.model.dispatch("REQUEST_REDO"),
9448
9169
  isEnabled: (env) => env.model.getters.canRedo(),
9449
9170
  icon: "o-spreadsheet-Icon.REDO",
9450
9171
  };
@@ -9452,13 +9173,19 @@ const copy = {
9452
9173
  name: _lt("Copy"),
9453
9174
  description: "Ctrl+C",
9454
9175
  isReadonlyAllowed: true,
9455
- execute: COPY_ACTION,
9176
+ execute: async (env) => {
9177
+ env.model.dispatch("COPY");
9178
+ await env.clipboard.write(env.model.getters.getClipboardContent());
9179
+ },
9456
9180
  icon: "o-spreadsheet-Icon.COPY",
9457
9181
  };
9458
9182
  const cut = {
9459
9183
  name: _lt("Cut"),
9460
9184
  description: "Ctrl+X",
9461
- execute: CUT_ACTION,
9185
+ execute: async (env) => {
9186
+ interactiveCut(env);
9187
+ await env.clipboard.write(env.model.getters.getClipboardContent());
9188
+ },
9462
9189
  icon: "o-spreadsheet-Icon.CUT",
9463
9190
  };
9464
9191
  const paste = {
@@ -9469,7 +9196,9 @@ const paste = {
9469
9196
  };
9470
9197
  const pasteSpecial = {
9471
9198
  name: _lt("Paste special"),
9472
- isVisible: IS_NOT_CUT_OPERATION,
9199
+ isVisible: (env) => {
9200
+ return !env.model.getters.isCutOperation();
9201
+ },
9473
9202
  icon: "o-spreadsheet-Icon.PASTE",
9474
9203
  };
9475
9204
  const pasteSpecialValue = {
@@ -9485,12 +9214,17 @@ const findAndReplace = {
9485
9214
  name: _lt("Find and replace"),
9486
9215
  description: "Ctrl+H",
9487
9216
  isReadonlyAllowed: true,
9488
- execute: OPEN_FAR_SIDEPANEL_ACTION,
9217
+ execute: (env) => {
9218
+ env.openSidePanel("FindAndReplace", {});
9219
+ },
9489
9220
  icon: "o-spreadsheet-Icon.FIND_AND_REPLACE",
9490
9221
  };
9491
9222
  const deleteValues = {
9492
9223
  name: _lt("Delete values"),
9493
- execute: DELETE_CONTENT_ACTION,
9224
+ execute: (env) => env.model.dispatch("DELETE_CONTENT", {
9225
+ sheetId: env.model.getters.getActiveSheetId(),
9226
+ target: env.model.getters.getSelectedZones(),
9227
+ }),
9494
9228
  };
9495
9229
  const deleteRows = {
9496
9230
  name: REMOVE_ROWS_NAME,
@@ -9524,11 +9258,19 @@ const deleteCells = {
9524
9258
  };
9525
9259
  const deleteCellShiftUp = {
9526
9260
  name: _lt("Delete cell and shift up"),
9527
- execute: DELETE_CELL_SHIFT_UP,
9261
+ execute: (env) => {
9262
+ const zone = env.model.getters.getSelectedZone();
9263
+ const result = env.model.dispatch("DELETE_CELL", { zone, shiftDimension: "ROW" });
9264
+ handlePasteResult(env, result);
9265
+ },
9528
9266
  };
9529
9267
  const deleteCellShiftLeft = {
9530
9268
  name: _lt("Delete cell and shift left"),
9531
- execute: DELETE_CELL_SHIFT_LEFT,
9269
+ execute: (env) => {
9270
+ const zone = env.model.getters.getSelectedZone();
9271
+ const result = env.model.dispatch("DELETE_CELL", { zone, shiftDimension: "COL" });
9272
+ handlePasteResult(env, result);
9273
+ },
9532
9274
  };
9533
9275
  const mergeCells = {
9534
9276
  name: _lt("Merge cells"),
@@ -9613,9 +9355,9 @@ const ARG_TYPES = [
9613
9355
  "META",
9614
9356
  ];
9615
9357
  function arg(definition, description = "") {
9616
- return makeArg(`${definition} ${description}`);
9358
+ return makeArg(definition, description);
9617
9359
  }
9618
- function makeArg(str) {
9360
+ function makeArg(str, description) {
9619
9361
  let parts = str.match(ARG_REGEXP);
9620
9362
  let name = parts[1].trim();
9621
9363
  let types = [];
@@ -9645,7 +9387,6 @@ function makeArg(str) {
9645
9387
  defaultValue = param.trim().slice(8);
9646
9388
  }
9647
9389
  }
9648
- let description = parts[3].trim();
9649
9390
  const result = {
9650
9391
  name,
9651
9392
  description,
@@ -9759,6 +9500,740 @@ function validateArguments(args) {
9759
9500
  }
9760
9501
  }
9761
9502
 
9503
+ function assertSingleColOrRow(errorStr, arg) {
9504
+ assert(() => arg.length === 1 || arg[0].length === 1, errorStr);
9505
+ }
9506
+ function assertSameDimensions(errorStr, ...args) {
9507
+ if (args.every(isMatrix)) {
9508
+ const cols = args[0].length;
9509
+ const rows = args[0][0].length;
9510
+ for (const arg of args) {
9511
+ assert(() => arg.length === cols && arg[0].length === rows, errorStr);
9512
+ }
9513
+ return;
9514
+ }
9515
+ if (args.some((arg) => Array.isArray(arg) && (arg.length !== 1 || arg[0].length !== 1))) {
9516
+ throw new Error(errorStr);
9517
+ }
9518
+ }
9519
+ function assertPositive(errorStr, arg) {
9520
+ assert(() => arg > 0, errorStr);
9521
+ }
9522
+ function assertSquareMatrix(errorStr, arg) {
9523
+ assert(() => arg.length === arg[0].length, errorStr);
9524
+ }
9525
+ function isNumberMatrix(arg) {
9526
+ return arg.every((row) => row.every((val) => typeof val === "number"));
9527
+ }
9528
+
9529
+ function getUnitMatrix(n) {
9530
+ const matrix = Array(n);
9531
+ for (let i = 0; i < n; i++) {
9532
+ matrix[i] = Array(n).fill(0);
9533
+ matrix[i][i] = 1;
9534
+ }
9535
+ return matrix;
9536
+ }
9537
+ /**
9538
+ * Invert a matrix and compute its determinant using Gaussian Elimination.
9539
+ *
9540
+ * The Matrix should be a square matrix, and should be indexed [col][row] instead of the
9541
+ * standard mathematical indexing [row][col].
9542
+ */
9543
+ function invertMatrix(M) {
9544
+ // Use Gaussian Elimination to calculate the inverse:
9545
+ // (1) 'augment' the matrix (left) by the identity (on the right)
9546
+ // (2) Turn the matrix on the left into the identity using elementary row operations
9547
+ // (3) The matrix on the right becomes the inverse (was the identity matrix)
9548
+ //
9549
+ // There are 3 elementary row operations:
9550
+ // (a) Swap 2 rows. This multiply the determinant by -1.
9551
+ // (b) Multiply a row by a scalar. This multiply the determinant by that scalar.
9552
+ // (c) Add to a row a multiple of another row. This does not change the determinant.
9553
+ if (M.length !== M[0].length) {
9554
+ throw new Error(`Function [[FUNCTION_NAME]] invert matrix error, only square matrices are invertible`);
9555
+ }
9556
+ let determinant = 1;
9557
+ const dim = M.length;
9558
+ const I = getUnitMatrix(dim);
9559
+ const C = M.map((row) => row.slice());
9560
+ // Perform elementary row operations
9561
+ for (let pivot = 0; pivot < dim; pivot++) {
9562
+ let diagonalElement = C[pivot][pivot];
9563
+ // if we have a 0 on the diagonal we'll need to swap with a lower row
9564
+ if (diagonalElement == 0) {
9565
+ //look through every row below the i'th row
9566
+ for (let row = pivot + 1; row < dim; row++) {
9567
+ //if the ii'th row has a non-0 in the i'th col, swap it with that row
9568
+ if (C[pivot][row] != 0) {
9569
+ swapMatrixRows(C, pivot, row);
9570
+ swapMatrixRows(I, pivot, row);
9571
+ determinant *= -1;
9572
+ break;
9573
+ }
9574
+ }
9575
+ diagonalElement = C[pivot][pivot];
9576
+ //if it's still 0, matrix isn't invertible
9577
+ if (diagonalElement === 0) {
9578
+ return { determinant: 0 };
9579
+ }
9580
+ }
9581
+ // Scale this row down by e (so we have a 1 on the diagonal)
9582
+ for (let col = 0; col < dim; col++) {
9583
+ C[col][pivot] = C[col][pivot] / diagonalElement;
9584
+ I[col][pivot] = I[col][pivot] / diagonalElement;
9585
+ }
9586
+ determinant *= diagonalElement;
9587
+ // Subtract a multiple of the current row from ALL of
9588
+ // the other rows so that there will be 0's in this column in the
9589
+ // rows above and below this one
9590
+ for (let row = 0; row < dim; row++) {
9591
+ if (row == pivot) {
9592
+ continue;
9593
+ }
9594
+ // We want to change this element to 0
9595
+ const e = C[pivot][row];
9596
+ // Subtract (the row above(or below) scaled by e) from (the
9597
+ // current row) but start at the i'th column and assume all the
9598
+ // stuff left of diagonal is 0 (which it should be if we made this
9599
+ // algorithm correctly)
9600
+ for (let col = 0; col < dim; col++) {
9601
+ C[col][row] -= e * C[col][pivot];
9602
+ I[col][row] -= e * I[col][pivot];
9603
+ }
9604
+ }
9605
+ }
9606
+ // We've done all operations, C should be the identity matrix I should be the inverse
9607
+ return { inverted: I, determinant };
9608
+ }
9609
+ function swapMatrixRows(matrix, row1, row2) {
9610
+ for (let i = 0; i < matrix.length; i++) {
9611
+ const tmp = matrix[i][row1];
9612
+ matrix[i][row1] = matrix[i][row2];
9613
+ matrix[i][row2] = tmp;
9614
+ }
9615
+ }
9616
+ /**
9617
+ * Matrix multiplication of 2 matrices.
9618
+ * ex: matrix1 : n x l, matrix2 : m x n => result : m x l
9619
+ *
9620
+ * Note: we use indexing [col][row] instead of the standard mathematical notation [row][col]
9621
+ */
9622
+ function multiplyMatrices(matrix1, matrix2) {
9623
+ if (matrix1.length !== matrix2[0].length) {
9624
+ throw new Error(_lt("Cannot multiply matrices : incompatible matrices size."));
9625
+ }
9626
+ const rowsM1 = matrix1[0].length;
9627
+ const colsM2 = matrix2.length;
9628
+ const n = matrix1.length;
9629
+ const result = Array(colsM2);
9630
+ for (let col = 0; col < colsM2; col++) {
9631
+ result[col] = Array(rowsM1);
9632
+ for (let row = 0; row < rowsM1; row++) {
9633
+ let sum = 0;
9634
+ for (let k = 0; k < n; k++) {
9635
+ sum += matrix1[k][row] * matrix2[col][k];
9636
+ }
9637
+ result[col][row] = sum;
9638
+ }
9639
+ }
9640
+ return result;
9641
+ }
9642
+
9643
+ // -----------------------------------------------------------------------------
9644
+ // ARRAY_CONSTRAIN
9645
+ // -----------------------------------------------------------------------------
9646
+ const ARRAY_CONSTRAIN = {
9647
+ description: _lt("Returns a result array constrained to a specific width and height."),
9648
+ args: [
9649
+ arg("input_range (any, range<any>)", _lt("The range to constrain.")),
9650
+ arg("rows (number)", _lt("The number of rows in the constrained array.")),
9651
+ arg("columns (number)", _lt("The number of columns in the constrained array.")),
9652
+ ],
9653
+ returns: ["RANGE<ANY>"],
9654
+ //TODO computeFormat
9655
+ compute: function (array, rows, columns) {
9656
+ const _array = toMatrixArgValue(array);
9657
+ const _rowsArg = toInteger(rows);
9658
+ const _columnsArg = toInteger(columns);
9659
+ assertPositive(_lt("The rows argument (%s) must be strictly positive.", _rowsArg.toString()), _rowsArg);
9660
+ assertPositive(_lt("The columns argument (%s) must be strictly positive.", _rowsArg.toString()), _columnsArg);
9661
+ const _rows = Math.min(_rowsArg, _array[0].length);
9662
+ const _columns = Math.min(_columnsArg, _array.length);
9663
+ const result = Array(_columns);
9664
+ for (let col = 0; col < _columns; col++) {
9665
+ result[col] = Array(_rows);
9666
+ for (let row = 0; row < _rows; row++) {
9667
+ result[col][row] = toCellValue(_array[col][row]);
9668
+ }
9669
+ }
9670
+ return result;
9671
+ },
9672
+ isExported: false,
9673
+ };
9674
+ // -----------------------------------------------------------------------------
9675
+ // CHOOSECOLS
9676
+ // -----------------------------------------------------------------------------
9677
+ const CHOOSECOLS = {
9678
+ description: _lt("Creates a new array from the selected columns in the existing range."),
9679
+ args: [
9680
+ arg("array (any, range<any>)", _lt("The array that contains the columns to be returned.")),
9681
+ arg("col_num (number, range<number>)", _lt("The first column index of the columns to be returned.")),
9682
+ arg("col_num2 (number, range<number>, repeating)", _lt("The columns indexes of the columns to be returned.")),
9683
+ ],
9684
+ returns: ["RANGE<ANY>"],
9685
+ //TODO computeFormat
9686
+ compute: function (array, ...columns) {
9687
+ const _array = toMatrixArgValue(array);
9688
+ const _columns = flattenRowFirst(columns, toInteger);
9689
+ 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()));
9690
+ const result = Array(_columns.length);
9691
+ for (let i = 0; i < _columns.length; i++) {
9692
+ const colIndex = _columns[i] - 1; // -1 because columns arguments are 1-indexed
9693
+ result[i] = _array[colIndex];
9694
+ }
9695
+ return toCellValueMatrix(result);
9696
+ },
9697
+ isExported: true,
9698
+ };
9699
+ // -----------------------------------------------------------------------------
9700
+ // CHOOSEROWS
9701
+ // -----------------------------------------------------------------------------
9702
+ const CHOOSEROWS = {
9703
+ description: _lt("Creates a new array from the selected rows in the existing range."),
9704
+ args: [
9705
+ arg("array (any, range<any>)", _lt("The array that contains the rows to be returned.")),
9706
+ arg("row_num (number, range<number>)", _lt("The first row index of the rows to be returned.")),
9707
+ arg("row_num2 (number, range<number>, repeating)", _lt("The rows indexes of the rows to be returned.")),
9708
+ ],
9709
+ returns: ["RANGE<ANY>"],
9710
+ //TODO computeFormat
9711
+ compute: function (array, ...rows) {
9712
+ const _array = toMatrixArgValue(array);
9713
+ const _rows = flattenRowFirst(rows, toInteger);
9714
+ 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()));
9715
+ const result = Array(_array.length);
9716
+ for (let col = 0; col < _array.length; col++) {
9717
+ result[col] = Array(_rows.length);
9718
+ for (let row = 0; row < _rows.length; row++) {
9719
+ const rowIndex = _rows[row] - 1; // -1 because rows arguments are 1-indexed
9720
+ result[col][row] = toCellValue(_array[col][rowIndex]);
9721
+ }
9722
+ }
9723
+ return result;
9724
+ },
9725
+ isExported: true,
9726
+ };
9727
+ // -----------------------------------------------------------------------------
9728
+ // EXPAND
9729
+ // -----------------------------------------------------------------------------
9730
+ const EXPAND = {
9731
+ description: _lt("Expands or pads an array to specified row and column dimensions."),
9732
+ args: [
9733
+ arg("array (any, range<any>)", _lt("The array to expand.")),
9734
+ arg("rows (number)", _lt("The number of rows in the expanded array. If missing, rows will not be expanded.")),
9735
+ arg("columns (number, optional)", _lt("The number of columns in the expanded array. If missing, columns will not be expanded.")),
9736
+ arg("pad_with (any, default=0)", _lt("The value with which to pad.")), // @compatibility: on Excel, pad with #N/A
9737
+ ],
9738
+ returns: ["RANGE<ANY>"],
9739
+ //TODO computeFormat
9740
+ compute: function (array, rows, columns, padWith = 0) {
9741
+ const _array = toMatrixArgValue(array);
9742
+ const _rows = toInteger(rows);
9743
+ const _columns = columns !== undefined ? toInteger(columns) : _array.length;
9744
+ const _padWith = padWith !== undefined && padWith !== null ? padWith : 0; // TODO : Replace with #N/A errors once it's supported
9745
+ 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()));
9746
+ assert(() => _columns >= _array.length, _lt("The columns arguments (%s) must be greater or equal than the number of columns of the array.", _columns.toString()));
9747
+ const result = [];
9748
+ for (let col = 0; col < _columns; col++) {
9749
+ result[col] = [];
9750
+ for (let row = 0; row < _rows; row++) {
9751
+ if (col >= _array.length || row >= _array[col].length) {
9752
+ result[col][row] = _padWith;
9753
+ }
9754
+ else {
9755
+ result[col][row] = _array[col][row] ?? 0;
9756
+ }
9757
+ }
9758
+ }
9759
+ return result;
9760
+ },
9761
+ isExported: true,
9762
+ };
9763
+ // -----------------------------------------------------------------------------
9764
+ // FLATTEN
9765
+ // -----------------------------------------------------------------------------
9766
+ const FLATTEN = {
9767
+ description: _lt("Flattens all the values from one or more ranges into a single column."),
9768
+ args: [
9769
+ arg("range (any, range<any>)", _lt("The first range to flatten.")),
9770
+ arg("range2 (any, range<any>, repeating)", _lt("Additional ranges to flatten.")),
9771
+ ],
9772
+ returns: ["RANGE<ANY>"],
9773
+ compute: function (...ranges) {
9774
+ return [flattenRowFirst(ranges, toCellValue)];
9775
+ },
9776
+ isExported: false,
9777
+ };
9778
+ // -----------------------------------------------------------------------------
9779
+ // FREQUENCY
9780
+ // -----------------------------------------------------------------------------
9781
+ const FREQUENCY = {
9782
+ description: _lt("Calculates the frequency distribution of a range."),
9783
+ args: [
9784
+ arg("data (range<number>)", _lt("The array of ranges containing the values to be counted.")),
9785
+ arg("classes (number, range<number>)", _lt("The range containing the set of classes.")),
9786
+ ],
9787
+ returns: ["RANGE<NUMBER>"],
9788
+ compute: function (data, classes) {
9789
+ const _data = flattenRowFirst([data], (val) => val).filter((val) => typeof val === "number");
9790
+ const _classes = flattenRowFirst([classes], (val) => val).filter((val) => typeof val === "number");
9791
+ /**
9792
+ * Returns the frequency distribution of the data in the classes, ie. the number of elements in the range
9793
+ * between each classes.
9794
+ *
9795
+ * For example:
9796
+ * - data = [1, 3, 2, 5, 4]
9797
+ * - classes = [3, 5, 1]
9798
+ *
9799
+ * The result will be:
9800
+ * - 2 ==> number of elements 1 > el >= 3
9801
+ * - 2 ==> number of elements 3 > el >= 5
9802
+ * - 1 ==> number of elements <= 1
9803
+ * - 0 ==> number of elements > 5
9804
+ *
9805
+ * @compatibility: GSheet sort the input classes. We do the implemntation of Excel, where we kee the classes unsorted.
9806
+ */
9807
+ const sortedClasses = _classes
9808
+ .map((value, index) => ({ initialIndex: index, value, count: 0 }))
9809
+ .sort((a, b) => a.value - b.value);
9810
+ sortedClasses.push({ initialIndex: sortedClasses.length, value: Infinity, count: 0 });
9811
+ const sortedData = _data.sort((a, b) => a - b);
9812
+ let index = 0;
9813
+ for (const val of sortedData) {
9814
+ while (val > sortedClasses[index].value && index < sortedClasses.length - 1) {
9815
+ index++;
9816
+ }
9817
+ sortedClasses[index].count++;
9818
+ }
9819
+ const result = sortedClasses
9820
+ .sort((a, b) => a.initialIndex - b.initialIndex)
9821
+ .map((val) => val.count);
9822
+ return [result];
9823
+ },
9824
+ isExported: true,
9825
+ };
9826
+ // -----------------------------------------------------------------------------
9827
+ // HSTACK
9828
+ // -----------------------------------------------------------------------------
9829
+ const HSTACK = {
9830
+ description: _lt("Appends ranges horizontally and in sequence to return a larger array."),
9831
+ args: [
9832
+ arg("range1 (any, range<any>)", _lt("The first range to be appended.")),
9833
+ arg("range2 (any, range<any>, repeating)", _lt("Additional ranges to add to range1.")),
9834
+ ],
9835
+ returns: ["RANGE<ANY>"],
9836
+ //TODO computeFormat
9837
+ compute: function (...ranges) {
9838
+ const _ranges = ranges.map((range) => toMatrixArgValue(range));
9839
+ const nRows = Math.max(..._ranges.map((range) => range[0].length));
9840
+ const colArray = [];
9841
+ for (const range of _ranges) {
9842
+ for (const col of range) {
9843
+ //TODO: fill with #N/A for unavailable values instead of zeroes
9844
+ const paddedCol = Array(nRows).fill(0);
9845
+ for (let i = 0; i < col.length; i++) {
9846
+ paddedCol[i] = toCellValue(col[i]);
9847
+ }
9848
+ colArray.push(paddedCol);
9849
+ }
9850
+ }
9851
+ return colArray;
9852
+ },
9853
+ isExported: true,
9854
+ };
9855
+ // -----------------------------------------------------------------------------
9856
+ // MDETERM
9857
+ // -----------------------------------------------------------------------------
9858
+ const MDETERM = {
9859
+ description: _lt("Returns the matrix determinant of a square matrix."),
9860
+ args: [
9861
+ 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.")),
9862
+ ],
9863
+ returns: ["NUMBER"],
9864
+ compute: function (matrix) {
9865
+ const _matrix = toMatrixArgValue(matrix);
9866
+ assertSquareMatrix(_lt("The argument square_matrix must have the same number of columns and rows."), _matrix);
9867
+ if (!isNumberMatrix(_matrix)) {
9868
+ throw new Error(_lt("The argument square_matrix must be a matrix of numbers."));
9869
+ }
9870
+ const { determinant } = invertMatrix(_matrix);
9871
+ return determinant;
9872
+ },
9873
+ isExported: true,
9874
+ };
9875
+ // -----------------------------------------------------------------------------
9876
+ // MINVERSE
9877
+ // -----------------------------------------------------------------------------
9878
+ const MINVERSE = {
9879
+ description: _lt("Returns the multiplicative inverse of a square matrix."),
9880
+ args: [
9881
+ 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.")),
9882
+ ],
9883
+ returns: ["RANGE<NUMBER>"],
9884
+ compute: function (matrix) {
9885
+ const _matrix = toMatrixArgValue(matrix);
9886
+ assertSquareMatrix(_lt("The argument square_matrix must have the same number of columns and rows."), _matrix);
9887
+ if (!isNumberMatrix(_matrix)) {
9888
+ throw new Error(_lt("The argument square_matrix must be a matrix of numbers."));
9889
+ }
9890
+ const { inverted } = invertMatrix(_matrix);
9891
+ if (!inverted) {
9892
+ throw new Error(_lt("The matrix is not invertible."));
9893
+ }
9894
+ return inverted;
9895
+ },
9896
+ isExported: true,
9897
+ };
9898
+ // -----------------------------------------------------------------------------
9899
+ // MMULT
9900
+ // -----------------------------------------------------------------------------
9901
+ const MMULT = {
9902
+ description: _lt("Calculates the matrix product of two matrices."),
9903
+ args: [
9904
+ arg("matrix1 (number, range<number>)", _lt("The first matrix in the matrix multiplication operation.")),
9905
+ arg("matrix2 (number, range<number>)", _lt("The second matrix in the matrix multiplication operation.")),
9906
+ ],
9907
+ returns: ["RANGE<NUMBER>"],
9908
+ compute: function (matrix1, matrix2) {
9909
+ const _matrix1 = toMatrixArgValue(matrix1);
9910
+ const _matrix2 = toMatrixArgValue(matrix2);
9911
+ assert(() => _matrix1.length === _matrix2[0].length, _lt("In [[FUNCTION_NAME]], the number of columns of the first matrix (%s) must be equal to the \
9912
+ number of rows of the second matrix (%s).", _matrix1.length.toString(), _matrix2[0].length.toString()));
9913
+ if (!isNumberMatrix(_matrix1) || !isNumberMatrix(_matrix2)) {
9914
+ throw new Error(_lt("The arguments matrix1 and matrix2 must be matrices of numbers."));
9915
+ }
9916
+ return multiplyMatrices(_matrix1, _matrix2);
9917
+ },
9918
+ isExported: true,
9919
+ };
9920
+ // -----------------------------------------------------------------------------
9921
+ // SUMPRODUCT
9922
+ // -----------------------------------------------------------------------------
9923
+ const SUMPRODUCT = {
9924
+ description: _lt("Calculates the sum of the products of corresponding entries in equal-sized ranges."),
9925
+ args: [
9926
+ arg("range1 (number, range<number>)", _lt("The first range whose entries will be multiplied with corresponding entries in the other ranges.")),
9927
+ arg("range2 (number, range<number>, repeating)", _lt("The other range whose entries will be multiplied with corresponding entries in the other ranges.")),
9928
+ ],
9929
+ returns: ["NUMBER"],
9930
+ compute: function (...args) {
9931
+ assertSameDimensions(_lt("All the ranges must have the same dimensions."), ...args);
9932
+ const _args = args.map(toMatrixArgValue);
9933
+ let result = 0;
9934
+ for (let i = 0; i < _args[0].length; i++) {
9935
+ for (let j = 0; j < _args[0][i].length; j++) {
9936
+ if (!_args.every((range) => typeof range[i][j] === "number")) {
9937
+ continue;
9938
+ }
9939
+ let product = 1;
9940
+ for (const range of _args) {
9941
+ product *= toNumber(range[i][j]);
9942
+ }
9943
+ result += product;
9944
+ }
9945
+ }
9946
+ return result;
9947
+ },
9948
+ isExported: true,
9949
+ };
9950
+ // -----------------------------------------------------------------------------
9951
+ // SUMX2MY2
9952
+ // -----------------------------------------------------------------------------
9953
+ /**
9954
+ * Return the sum of the callback applied to each pair of values in the two arrays.
9955
+ *
9956
+ * Ignore the pairs X,Y where one of the value isn't a number. Throw an error if no pair of numbers is found.
9957
+ */
9958
+ function getSumXAndY(arrayX, arrayY, cb) {
9959
+ assertSameDimensions("The arguments array_x and array_y must have the same dimensions.", arrayX, arrayY);
9960
+ const _arrayX = toMatrixArgValue(arrayX);
9961
+ const _arrayY = toMatrixArgValue(arrayY);
9962
+ let validPairFound = false;
9963
+ let result = 0;
9964
+ for (const i in _arrayX) {
9965
+ for (const j in _arrayX[i]) {
9966
+ const arrayXValue = _arrayX[i][j];
9967
+ const arrayYValue = _arrayY[i][j];
9968
+ if (typeof arrayXValue !== "number" || typeof arrayYValue !== "number") {
9969
+ continue;
9970
+ }
9971
+ validPairFound = true;
9972
+ result += cb(arrayXValue, arrayYValue);
9973
+ }
9974
+ }
9975
+ if (!validPairFound) {
9976
+ throw new Error("The arguments array_x and array_y must contain at least one pair of numbers.");
9977
+ }
9978
+ return result;
9979
+ }
9980
+ const SUMX2MY2 = {
9981
+ description: _lt("Calculates the sum of the difference of the squares of the values in two array."),
9982
+ args: [
9983
+ 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.")),
9984
+ 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.")),
9985
+ ],
9986
+ returns: ["NUMBER"],
9987
+ compute: function (arrayX, arrayY) {
9988
+ return getSumXAndY(arrayX, arrayY, (x, y) => x ** 2 - y ** 2);
9989
+ },
9990
+ isExported: true,
9991
+ };
9992
+ // -----------------------------------------------------------------------------
9993
+ // SUMX2PY2
9994
+ // -----------------------------------------------------------------------------
9995
+ const SUMX2PY2 = {
9996
+ description: _lt("Calculates the sum of the sum of the squares of the values in two array."),
9997
+ args: [
9998
+ 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.")),
9999
+ 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.")),
10000
+ ],
10001
+ returns: ["NUMBER"],
10002
+ compute: function (arrayX, arrayY) {
10003
+ return getSumXAndY(arrayX, arrayY, (x, y) => x ** 2 + y ** 2);
10004
+ },
10005
+ isExported: true,
10006
+ };
10007
+ // -----------------------------------------------------------------------------
10008
+ // SUMXMY2
10009
+ // -----------------------------------------------------------------------------
10010
+ const SUMXMY2 = {
10011
+ description: _lt("Calculates the sum of squares of the differences of values in two array."),
10012
+ args: [
10013
+ 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.")),
10014
+ 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.")),
10015
+ ],
10016
+ returns: ["NUMBER"],
10017
+ compute: function (arrayX, arrayY) {
10018
+ return getSumXAndY(arrayX, arrayY, (x, y) => (x - y) ** 2);
10019
+ },
10020
+ isExported: true,
10021
+ };
10022
+ // -----------------------------------------------------------------------------
10023
+ // TOCOL
10024
+ // -----------------------------------------------------------------------------
10025
+ const TO_COL_ROW_DEFAULT_IGNORE = 0;
10026
+ const TO_COL_ROW_DEFAULT_SCAN = false;
10027
+ const TO_COL_ROW_ARGS = [
10028
+ arg("array (any, range<any>)", _lt("The array which will be transformed.")),
10029
+ 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.")),
10030
+ 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) \
10031
+ scans the array by row.")),
10032
+ ];
10033
+ const TOCOL = {
10034
+ description: _lt("Transforms a range of cells into a single column."),
10035
+ args: TO_COL_ROW_ARGS,
10036
+ returns: ["RANGE<ANY>"],
10037
+ //TODO compute format
10038
+ compute: function (array, ignore = TO_COL_ROW_DEFAULT_IGNORE, scanByColumn = TO_COL_ROW_DEFAULT_SCAN) {
10039
+ const _array = toMatrixArgValue(array);
10040
+ const _ignore = toInteger(ignore);
10041
+ const _scanByColumn = toBoolean(scanByColumn);
10042
+ assert(() => _ignore >= 0 && _ignore <= 3, _lt("Argument ignore must be between 0 and 3"));
10043
+ const mappedFn = (acc, item) => {
10044
+ // TODO : implement ignore value 2 (ignore error) & 3 (ignore blanks and errors) once we can have errors in
10045
+ // the array w/o crashing
10046
+ if ((_ignore === 1 || _ignore === 3) && (item === undefined || item === null)) {
10047
+ return acc;
10048
+ }
10049
+ acc.push(toCellValue(item));
10050
+ return acc;
10051
+ };
10052
+ const result = reduceAny([_array], mappedFn, [], _scanByColumn ? "colFirst" : "rowFirst");
10053
+ if (result.length === 0) {
10054
+ throw new NotAvailableError(_lt("No results for the given arguments of TOCOL."));
10055
+ }
10056
+ return [result];
10057
+ },
10058
+ isExported: true,
10059
+ };
10060
+ // -----------------------------------------------------------------------------
10061
+ // TOROW
10062
+ // -----------------------------------------------------------------------------
10063
+ const TOROW = {
10064
+ description: _lt("Transforms a range of cells into a single row."),
10065
+ args: TO_COL_ROW_ARGS,
10066
+ returns: ["RANGE<ANY>"],
10067
+ //TODO compute format
10068
+ compute: function (array, ignore = TO_COL_ROW_DEFAULT_IGNORE, scanByColumn = TO_COL_ROW_DEFAULT_SCAN) {
10069
+ const _array = toMatrixArgValue(array);
10070
+ const _ignore = toInteger(ignore);
10071
+ const _scanByColumn = toBoolean(scanByColumn);
10072
+ assert(() => _ignore >= 0 && _ignore <= 3, _lt("Argument ignore must be between 0 and 3"));
10073
+ const mappedFn = (acc, item) => {
10074
+ // TODO : implement ignore value 2 (ignore error) & 3 (ignore blanks and errors) once we can have errors in
10075
+ // the array w/o crashing
10076
+ if ((_ignore === 1 || _ignore === 3) && (item === undefined || item === null)) {
10077
+ return acc;
10078
+ }
10079
+ acc.push([toCellValue(item)]);
10080
+ return acc;
10081
+ };
10082
+ const result = reduceAny([_array], mappedFn, [], _scanByColumn ? "colFirst" : "rowFirst");
10083
+ if (result.length === 0 || result[0].length === 0) {
10084
+ throw new NotAvailableError(_lt("No results for the given arguments of TOROW."));
10085
+ }
10086
+ return result;
10087
+ },
10088
+ isExported: true,
10089
+ };
10090
+ // -----------------------------------------------------------------------------
10091
+ // TRANSPOSE
10092
+ // -----------------------------------------------------------------------------
10093
+ const TRANSPOSE = {
10094
+ description: _lt("Transposes the rows and columns of a range."),
10095
+ args: [arg("range (any, range<any>)", _lt("The range to be transposed."))],
10096
+ returns: ["RANGE<ANY>"],
10097
+ computeFormat: (values) => {
10098
+ if (!values.format) {
10099
+ return undefined;
10100
+ }
10101
+ if (!isMatrix(values.format)) {
10102
+ return values.format;
10103
+ }
10104
+ return transpose2dArray(values.format);
10105
+ },
10106
+ compute: function (values) {
10107
+ const _values = toMatrixArgValue(values);
10108
+ return transpose2dArray(_values, toCellValue);
10109
+ },
10110
+ isExported: true,
10111
+ };
10112
+ // -----------------------------------------------------------------------------
10113
+ // VSTACK
10114
+ // -----------------------------------------------------------------------------
10115
+ const VSTACK = {
10116
+ description: _lt("Appends ranges vertically and in sequence to return a larger array."),
10117
+ args: [
10118
+ arg("range1 (any, range<any>)", _lt("The first range to be appended.")),
10119
+ arg("range2 (any, range<any>, repeating)", _lt("Additional ranges to add to range1.")),
10120
+ ],
10121
+ returns: ["RANGE<ANY>"],
10122
+ //TODO computeFormat
10123
+ compute: function (...ranges) {
10124
+ const _ranges = ranges.map((range) => toMatrixArgValue(range));
10125
+ const nCols = Math.max(..._ranges.map((range) => range.length));
10126
+ const nRows = _ranges.reduce((acc, range) => acc + range[0].length, 0);
10127
+ const result = Array(nCols)
10128
+ .fill([])
10129
+ .map(() => Array(nRows).fill(0)); // TODO fill with #N/A
10130
+ let currentRow = 0;
10131
+ for (const range of _ranges) {
10132
+ for (let col = 0; col < range.length; col++) {
10133
+ for (let row = 0; row < range[col].length; row++) {
10134
+ result[col][currentRow + row] = toCellValue(range[col][row]);
10135
+ }
10136
+ }
10137
+ currentRow += range[0].length;
10138
+ }
10139
+ return result;
10140
+ },
10141
+ isExported: true,
10142
+ };
10143
+ // -----------------------------------------------------------------------------
10144
+ // WRAPCOLS
10145
+ // -----------------------------------------------------------------------------
10146
+ const WRAPCOLS = {
10147
+ description: _lt("Wraps the provided row or column of cells by columns after a specified number of elements to form a new array."),
10148
+ args: [
10149
+ arg("range (any, range<any>)", _lt("The range to wrap.")),
10150
+ arg("wrap_count (number)", _lt("The maximum number of cells for each column, rounded down to the nearest whole number.")),
10151
+ arg("pad_with (any, default=0)", // TODO : replace with #N/A
10152
+ _lt("The value with which to fill the extra cells in the range.")),
10153
+ ],
10154
+ returns: ["RANGE<ANY>"],
10155
+ //TODO computeFormat
10156
+ compute: function (range, wrapCount, padWith = 0) {
10157
+ const _range = toMatrixArgValue(range);
10158
+ const nOfRows = toInteger(wrapCount);
10159
+ const _padWith = padWith === null ? 0 : padWith;
10160
+ assertSingleColOrRow(_lt("Argument range must be a single row or column."), _range);
10161
+ const values = _range.flat();
10162
+ const nOfCols = Math.ceil(values.length / nOfRows);
10163
+ const result = Array(nOfCols);
10164
+ for (let col = 0; col < nOfCols; col++) {
10165
+ result[col] = Array(nOfRows).fill(_padWith);
10166
+ for (let row = 0; row < nOfRows; row++) {
10167
+ const index = col * nOfRows + row;
10168
+ if (index < values.length) {
10169
+ result[col][row] = toCellValue(values[index]);
10170
+ }
10171
+ }
10172
+ }
10173
+ return result;
10174
+ },
10175
+ isExported: true,
10176
+ };
10177
+ // -----------------------------------------------------------------------------
10178
+ // WRAPROWS
10179
+ // -----------------------------------------------------------------------------
10180
+ const WRAPROWS = {
10181
+ description: _lt("Wraps the provided row or column of cells by rows after a specified number of elements to form a new array."),
10182
+ args: [
10183
+ arg("range (any, range<any>)", _lt("The range to wrap.")),
10184
+ arg("wrap_count (number)", _lt("The maximum number of cells for each row, rounded down to the nearest whole number.")),
10185
+ arg("pad_with (any, default=0)", // TODO : replace with #N/A
10186
+ _lt("The value with which to fill the extra cells in the range.")),
10187
+ ],
10188
+ returns: ["RANGE<ANY>"],
10189
+ //TODO computeFormat
10190
+ compute: function (range, wrapCount, padWith = 0) {
10191
+ const _range = toMatrixArgValue(range);
10192
+ const nOfCols = toInteger(wrapCount);
10193
+ const _padWith = padWith === null ? 0 : padWith;
10194
+ assertSingleColOrRow(_lt("Argument range must be a single row or column."), _range);
10195
+ const values = _range.flat();
10196
+ const nOfRows = Math.ceil(values.length / nOfCols);
10197
+ const result = Array(nOfCols)
10198
+ .fill([])
10199
+ .map(() => Array(nOfRows).fill(_padWith));
10200
+ for (let row = 0; row < nOfRows; row++) {
10201
+ for (let col = 0; col < nOfCols; col++) {
10202
+ const index = row * nOfCols + col;
10203
+ if (index < values.length) {
10204
+ result[col][row] = toCellValue(values[index]);
10205
+ }
10206
+ }
10207
+ }
10208
+ return result;
10209
+ },
10210
+ isExported: true,
10211
+ };
10212
+
10213
+ var array = /*#__PURE__*/Object.freeze({
10214
+ __proto__: null,
10215
+ ARRAY_CONSTRAIN: ARRAY_CONSTRAIN,
10216
+ CHOOSECOLS: CHOOSECOLS,
10217
+ CHOOSEROWS: CHOOSEROWS,
10218
+ EXPAND: EXPAND,
10219
+ FLATTEN: FLATTEN,
10220
+ FREQUENCY: FREQUENCY,
10221
+ HSTACK: HSTACK,
10222
+ MDETERM: MDETERM,
10223
+ MINVERSE: MINVERSE,
10224
+ MMULT: MMULT,
10225
+ SUMPRODUCT: SUMPRODUCT,
10226
+ SUMX2MY2: SUMX2MY2,
10227
+ SUMX2PY2: SUMX2PY2,
10228
+ SUMXMY2: SUMXMY2,
10229
+ TOCOL: TOCOL,
10230
+ TOROW: TOROW,
10231
+ TRANSPOSE: TRANSPOSE,
10232
+ VSTACK: VSTACK,
10233
+ WRAPCOLS: WRAPCOLS,
10234
+ WRAPROWS: WRAPROWS
10235
+ });
10236
+
9762
10237
  // -----------------------------------------------------------------------------
9763
10238
  // FORMAT.LARGE.NUMBER
9764
10239
  // -----------------------------------------------------------------------------
@@ -10414,6 +10889,22 @@ const MOD = {
10414
10889
  isExported: true,
10415
10890
  };
10416
10891
  // -----------------------------------------------------------------------------
10892
+ // MUNIT
10893
+ // -----------------------------------------------------------------------------
10894
+ const MUNIT = {
10895
+ description: _lt("Returns a n x n unit matrix, where n is the input dimension."),
10896
+ args: [
10897
+ arg("dimension (number)", _lt("An integer specifying the dimension size of the unit matrix. It must be positive.")),
10898
+ ],
10899
+ returns: ["RANGE<NUMBER>"],
10900
+ compute: function (n) {
10901
+ const _n = toInteger(n);
10902
+ assertPositive(_lt("The argument dimension must be positive"), _n);
10903
+ return getUnitMatrix(_n);
10904
+ },
10905
+ isExported: true,
10906
+ };
10907
+ // -----------------------------------------------------------------------------
10417
10908
  // ODD
10418
10909
  // -----------------------------------------------------------------------------
10419
10910
  const ODD = {
@@ -10512,6 +11003,47 @@ const RAND = {
10512
11003
  isExported: true,
10513
11004
  };
10514
11005
  // -----------------------------------------------------------------------------
11006
+ // RANDARRAY
11007
+ // -----------------------------------------------------------------------------
11008
+ const RANDARRAY = {
11009
+ description: _lt("Returns a grid of random numbers between 0 inclusive and 1 exclusive."),
11010
+ args: [
11011
+ arg("rows (number, default=1)", _lt("The number of rows to be returned.")),
11012
+ arg("columns (number, default=1)", _lt("The number of columns to be returned.")),
11013
+ arg("min (number, default=0)", _lt("The minimum number you would like returned.")),
11014
+ arg("max (number, default=1)", _lt("The maximum number you would like returned.")),
11015
+ arg("whole_number (number, default=FALSE)", _lt("Return a whole number or a decimal value.")),
11016
+ ],
11017
+ returns: ["RANGE<NUMBER>"],
11018
+ compute: function (rows = 1, columns = 1, min = 0, max = 1, whole_number = false) {
11019
+ const _cols = toInteger(columns);
11020
+ const _rows = toInteger(rows);
11021
+ const _min = toNumber(min);
11022
+ const _max = toNumber(max);
11023
+ const _whole_number = toBoolean(whole_number);
11024
+ assertPositive(_lt("The number columns (%s) must be positive.", _cols.toString()), _cols);
11025
+ assertPositive(_lt("The number rows (%s) must be positive.", _rows.toString()), _rows);
11026
+ assert(() => _min <= _max, _lt("The maximum (%s) must be greater than or equal to the minimum (%s).", _max.toString(), _min.toString()));
11027
+ if (_whole_number) {
11028
+ 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()));
11029
+ }
11030
+ const result = Array(_cols);
11031
+ for (let col = 0; col < _cols; col++) {
11032
+ result[col] = Array(_rows);
11033
+ for (let row = 0; row < _rows; row++) {
11034
+ if (!_whole_number) {
11035
+ result[col][row] = _min + Math.random() * (_max - _min);
11036
+ }
11037
+ else {
11038
+ result[col][row] = Math.floor(Math.random() * (_max - _min + 1) + _min);
11039
+ }
11040
+ }
11041
+ }
11042
+ return result;
11043
+ },
11044
+ isExported: true,
11045
+ };
11046
+ // -----------------------------------------------------------------------------
10515
11047
  // RANDBETWEEN
10516
11048
  // -----------------------------------------------------------------------------
10517
11049
  const RANDBETWEEN = {
@@ -10841,11 +11373,13 @@ var math = /*#__PURE__*/Object.freeze({
10841
11373
  ISODD: ISODD,
10842
11374
  LN: LN,
10843
11375
  MOD: MOD,
11376
+ MUNIT: MUNIT,
10844
11377
  ODD: ODD,
10845
11378
  PI: PI,
10846
11379
  POWER: POWER,
10847
11380
  PRODUCT: PRODUCT,
10848
11381
  RAND: RAND,
11382
+ RANDARRAY: RANDARRAY,
10849
11383
  RANDBETWEEN: RANDBETWEEN,
10850
11384
  ROUND: ROUND,
10851
11385
  ROUNDDOWN: ROUNDDOWN,
@@ -12872,6 +13406,89 @@ var engineering = /*#__PURE__*/Object.freeze({
12872
13406
  DELTA: DELTA
12873
13407
  });
12874
13408
 
13409
+ // -----------------------------------------------------------------------------
13410
+ // FILTER
13411
+ // -----------------------------------------------------------------------------
13412
+ const FILTER = {
13413
+ description: _lt("Returns a filtered version of the source range, returning only rows or columns that meet the specified conditions."),
13414
+ // TODO modify args description when vectorization on formulas is available
13415
+ args: [
13416
+ arg("range (any, range<any>)", _lt("The data to be filtered.")),
13417
+ arg("condition1 (boolean, range<boolean>)", _lt("A column or row containing true or false values corresponding to the first column or row of range.")),
13418
+ arg("condition2 (boolean, range<boolean>, repeating)", _lt("Additional column or row containing true or false values.")),
13419
+ ],
13420
+ returns: ["RANGE<ANY>"],
13421
+ //TODO computeFormat
13422
+ compute: function (range, ...conditions) {
13423
+ let _range = toMatrixArgValue(range);
13424
+ const _conditionsMatrices = conditions.map((cond) => toMatrixArgValue(cond));
13425
+ _conditionsMatrices.map((c) => assertSingleColOrRow(_lt("The arguments condition must be a single column or row."), c));
13426
+ assertSameDimensions(_lt("The arguments conditions must have the same dimensions."), ..._conditionsMatrices);
13427
+ const _conditions = _conditionsMatrices.map((c) => c.flat());
13428
+ const mode = _conditionsMatrices[0].length === 1 ? "row" : "col";
13429
+ _range = mode === "row" ? transpose2dArray(_range) : _range;
13430
+ assert(() => _conditions.every((cond) => cond.length === _range.length), _lt(`FILTER has mismatched sizes on the range and conditions.`));
13431
+ const results = [];
13432
+ for (let i = 0; i < _range.length; i++) {
13433
+ const row = _range[i];
13434
+ if (_conditions.every((c) => c[i])) {
13435
+ results.push(row);
13436
+ }
13437
+ }
13438
+ if (!results.length) {
13439
+ throw new NotAvailableError(_lt("No match found in FILTER evaluation"));
13440
+ }
13441
+ return toCellValueMatrix(mode === "row" ? transpose2dArray(results) : results);
13442
+ },
13443
+ isExported: true,
13444
+ };
13445
+ // -----------------------------------------------------------------------------
13446
+ // UNIQUE
13447
+ // -----------------------------------------------------------------------------
13448
+ const UNIQUE = {
13449
+ description: _lt("Unique rows in the provided source range."),
13450
+ args: [
13451
+ arg("range (any, range<any>)", _lt("The data to filter by unique entries.")),
13452
+ arg("by_column (boolean, default=FALSE)", _lt("Whether to filter the data by columns or by rows.")),
13453
+ arg("exactly_once (boolean, default=FALSE)", _lt("Whether to return only entries with no duplicates.")),
13454
+ ],
13455
+ returns: ["RANGE<NUMBER>"],
13456
+ // TODO computeFormat
13457
+ compute: function (range, byColumn, exactlyOnce) {
13458
+ if (!isMatrix(range)) {
13459
+ return toCellValue(range);
13460
+ }
13461
+ const _byColumn = toBoolean(byColumn) || false;
13462
+ const _exactlyOnce = toBoolean(exactlyOnce) || false;
13463
+ if (!_byColumn)
13464
+ range = transpose2dArray(range);
13465
+ const map = new Map();
13466
+ for (const row of range) {
13467
+ const key = JSON.stringify(row);
13468
+ const occurrence = map.get(key);
13469
+ if (!occurrence) {
13470
+ map.set(key, { val: row, count: 1 });
13471
+ }
13472
+ else {
13473
+ occurrence.count++;
13474
+ }
13475
+ }
13476
+ const results = _exactlyOnce
13477
+ ? [...map.values()].filter((v) => v.count === 1).map((v) => v.val)
13478
+ : [...map.values()].map((v) => v.val);
13479
+ if (!results.length)
13480
+ throw new Error(_lt("No unique values found"));
13481
+ return toCellValueMatrix(_byColumn ? results : transpose2dArray(results));
13482
+ },
13483
+ isExported: true,
13484
+ };
13485
+
13486
+ var filter = /*#__PURE__*/Object.freeze({
13487
+ __proto__: null,
13488
+ FILTER: FILTER,
13489
+ UNIQUE: UNIQUE
13490
+ });
13491
+
12875
13492
  /** Assert maturity date > settlement date */
12876
13493
  function assertMaturityAndSettlementDatesAreValid(settlement, maturity) {
12877
13494
  assert(() => settlement < maturity, _lt("The maturity (%s) must be strictly greater than the settlement (%s).", maturity.toString(), settlement.toString()));
@@ -15567,13 +16184,16 @@ const XLOOKUP = {
15567
16184
  const _searchMode = Math.trunc(toNumber(searchMode));
15568
16185
  const _searchKey = normalizeValue(searchKey);
15569
16186
  assert(() => lookupRange.length === 1 || lookupRange[0].length === 1, _lt("lookup_range should be either a single row or single column."));
15570
- assert(() => returnRange.length === 1 || returnRange[0].length === 1, _lt("return_range should be either a single row or single column."));
15571
- assert(() => returnRange.length === lookupRange.length &&
15572
- returnRange[0].length === lookupRange[0].length, _lt("return_range should have the same dimensions as lookup_range."));
15573
16187
  assert(() => [-1, 1, -2, 2].includes(_searchMode), _lt("searchMode should be a value in [-1, 1, -2, 2]."));
15574
16188
  assert(() => [-1, 0, 1].includes(_matchMode), _lt("matchMode should be a value in [-1, 0, 1]."));
15575
- const getElement = lookupRange.length === 1 ? getNormalizedValueFromColumnRange : getNormalizedValueFromRowRange;
15576
- const rangeLen = lookupRange.length === 1 ? lookupRange[0].length : lookupRange.length;
16189
+ const lookupDirection = lookupRange.length === 1 ? "col" : "row";
16190
+ assert(() => lookupDirection === "col"
16191
+ ? returnRange[0].length === lookupRange[0].length
16192
+ : returnRange.length === lookupRange.length, _lt("return_range should have the same dimensions as lookup_range."));
16193
+ const getElement = lookupDirection === "col"
16194
+ ? getNormalizedValueFromColumnRange
16195
+ : getNormalizedValueFromRowRange;
16196
+ const rangeLen = lookupDirection === "col" ? lookupRange[0].length : lookupRange.length;
15577
16197
  const mode = _matchMode === 0 ? "strict" : _matchMode === 1 ? "nextGreater" : "nextSmaller";
15578
16198
  const reverseSearch = _searchMode === -1;
15579
16199
  let index;
@@ -15585,7 +16205,7 @@ const XLOOKUP = {
15585
16205
  index = linearSearch(lookupRange, _searchKey, mode, rangeLen, getElement, reverseSearch);
15586
16206
  }
15587
16207
  if (index !== -1) {
15588
- return (lookupRange.length === 1 ? returnRange[0][index] : returnRange[index][0]);
16208
+ return toCellValueMatrix(lookupDirection === "col" ? returnRange.map((col) => [col[index]]) : [returnRange[index]]);
15589
16209
  }
15590
16210
  const _defaultValue = defaultValue?.();
15591
16211
  assertAvailable(_defaultValue, searchKey);
@@ -16126,6 +16746,36 @@ const SEARCH = {
16126
16746
  isExported: true,
16127
16747
  };
16128
16748
  // -----------------------------------------------------------------------------
16749
+ // SPLIT
16750
+ // -----------------------------------------------------------------------------
16751
+ const SPLIT_DEFAULT_SPLIT_BY_EACH = true;
16752
+ const SPLIT_DEFAULT_REMOVE_EMPTY_TEXT = true;
16753
+ const SPLIT = {
16754
+ description: _lt("Split text by specific character delimiter(s)."),
16755
+ args: [
16756
+ arg("text (string)", _lt("The text to divide.")),
16757
+ arg("delimiter (string)", _lt("The character or characters to use to split text.")),
16758
+ arg(`split_by_each (boolean, default=${SPLIT_DEFAULT_SPLIT_BY_EACH}})`, _lt("Whether or not to divide text around each character contained in delimiter.")),
16759
+ 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 \
16760
+ consecutive delimiters as one (if TRUE). If FALSE, empty cells values are added between consecutive delimiters.")),
16761
+ ],
16762
+ returns: ["RANGE<STRING>"],
16763
+ compute: function (text, delimiter, splitByEach = SPLIT_DEFAULT_SPLIT_BY_EACH, removeEmptyText = SPLIT_DEFAULT_REMOVE_EMPTY_TEXT) {
16764
+ const _text = toString(text);
16765
+ const _delimiter = escapeRegExp(toString(delimiter));
16766
+ const _splitByEach = toBoolean(splitByEach);
16767
+ const _removeEmptyText = toBoolean(removeEmptyText);
16768
+ assert(() => _delimiter.length > 0, _lt("The _delimiter (%s) must be not be empty.", _delimiter));
16769
+ const regex = _splitByEach ? new RegExp(`[${_delimiter}]`, "g") : new RegExp(_delimiter, "g");
16770
+ let result = _text.split(regex);
16771
+ if (_removeEmptyText) {
16772
+ result = result.filter((text) => text !== "");
16773
+ }
16774
+ return transpose2dArray([result]);
16775
+ },
16776
+ isExported: true,
16777
+ };
16778
+ // -----------------------------------------------------------------------------
16129
16779
  // SUBSTITUTE
16130
16780
  // -----------------------------------------------------------------------------
16131
16781
  const SUBSTITUTE = {
@@ -16234,6 +16884,7 @@ var text = /*#__PURE__*/Object.freeze({
16234
16884
  REPLACE: REPLACE,
16235
16885
  RIGHT: RIGHT,
16236
16886
  SEARCH: SEARCH,
16887
+ SPLIT: SPLIT,
16237
16888
  SUBSTITUTE: SUBSTITUTE,
16238
16889
  TEXTJOIN: TEXTJOIN,
16239
16890
  TRIM: TRIM,
@@ -16267,8 +16918,10 @@ var web = /*#__PURE__*/Object.freeze({
16267
16918
  });
16268
16919
 
16269
16920
  const categories = [
16921
+ { name: _lt("Array"), functions: array },
16270
16922
  { name: _lt("Database"), functions: database },
16271
16923
  { name: _lt("Date"), functions: date },
16924
+ { name: _lt("Filter"), functions: filter },
16272
16925
  { name: _lt("Financial"), functions: financial },
16273
16926
  { name: _lt("Info"), functions: info },
16274
16927
  { name: _lt("Lookup"), functions: lookup },
@@ -16341,14 +16994,20 @@ for (let category of categories) {
16341
16994
  }
16342
16995
 
16343
16996
  const insertRow = {
16344
- name: MENU_INSERT_ROWS_NAME,
16997
+ name: (env) => {
16998
+ const number = getRowsNumber(env);
16999
+ return number === 1 ? _lt("Insert row") : _lt("Insert %s rows", number.toString());
17000
+ },
16345
17001
  isVisible: (env) => isConsecutive(env.model.getters.getActiveRows()) &&
16346
17002
  IS_ONLY_ONE_RANGE(env) &&
16347
17003
  env.model.getters.getActiveCols().size === 0,
16348
17004
  icon: "o-spreadsheet-Icon.INSERT_ROW",
16349
17005
  };
16350
17006
  const rowInsertRowBefore = {
16351
- name: ROW_INSERT_ROWS_BEFORE_NAME,
17007
+ name: (env) => {
17008
+ const number = getRowsNumber(env);
17009
+ return number === 1 ? _lt("Insert row above") : _lt("Insert %s rows above", number.toString());
17010
+ },
16352
17011
  execute: INSERT_ROWS_BEFORE_ACTION,
16353
17012
  isVisible: (env) => isConsecutive(env.model.getters.getActiveRows()) &&
16354
17013
  IS_ONLY_ONE_RANGE(env) &&
@@ -16357,17 +17016,32 @@ const rowInsertRowBefore = {
16357
17016
  };
16358
17017
  const topBarInsertRowsBefore = {
16359
17018
  ...rowInsertRowBefore,
16360
- name: MENU_INSERT_ROWS_BEFORE_NAME,
17019
+ name: (env) => {
17020
+ const number = getRowsNumber(env);
17021
+ if (number === 1) {
17022
+ return _lt("Row above");
17023
+ }
17024
+ return _lt("%s Rows above", number.toString());
17025
+ },
16361
17026
  };
16362
17027
  const cellInsertRowsBefore = {
16363
17028
  ...rowInsertRowBefore,
16364
- name: CELL_INSERT_ROWS_BEFORE_NAME,
17029
+ name: (env) => {
17030
+ const number = getRowsNumber(env);
17031
+ if (number === 1) {
17032
+ return _lt("Insert row");
17033
+ }
17034
+ return _lt("Insert %s rows", number.toString());
17035
+ },
16365
17036
  isVisible: IS_ONLY_ONE_RANGE,
16366
17037
  icon: "o-spreadsheet-Icon.INSERT_ROW_BEFORE",
16367
17038
  };
16368
17039
  const rowInsertRowsAfter = {
16369
17040
  execute: INSERT_ROWS_AFTER_ACTION,
16370
- name: ROW_INSERT_ROWS_AFTER_NAME,
17041
+ name: (env) => {
17042
+ const number = getRowsNumber(env);
17043
+ return number === 1 ? _lt("Insert row below") : _lt("Insert %s rows below", number.toString());
17044
+ },
16371
17045
  isVisible: (env) => isConsecutive(env.model.getters.getActiveRows()) &&
16372
17046
  IS_ONLY_ONE_RANGE(env) &&
16373
17047
  env.model.getters.getActiveCols().size === 0,
@@ -16375,17 +17049,31 @@ const rowInsertRowsAfter = {
16375
17049
  };
16376
17050
  const topBarInsertRowsAfter = {
16377
17051
  ...rowInsertRowsAfter,
16378
- name: MENU_INSERT_ROWS_AFTER_NAME,
17052
+ name: (env) => {
17053
+ const number = getRowsNumber(env);
17054
+ if (number === 1) {
17055
+ return _lt("Row below");
17056
+ }
17057
+ return _lt("%s Rows below", number.toString());
17058
+ },
16379
17059
  };
16380
17060
  const insertCol = {
16381
- name: MENU_INSERT_COLUMNS_NAME,
17061
+ name: (env) => {
17062
+ const number = getColumnsNumber(env);
17063
+ return number === 1 ? _lt("Insert column") : _lt("Insert %s columns", number.toString());
17064
+ },
16382
17065
  isVisible: (env) => isConsecutive(env.model.getters.getActiveCols()) &&
16383
17066
  IS_ONLY_ONE_RANGE(env) &&
16384
17067
  env.model.getters.getActiveRows().size === 0,
16385
17068
  icon: "o-spreadsheet-Icon.INSERT_COL",
16386
17069
  };
16387
17070
  const colInsertColsBefore = {
16388
- name: COLUMN_INSERT_COLUMNS_BEFORE_NAME,
17071
+ name: (env) => {
17072
+ const number = getColumnsNumber(env);
17073
+ return number === 1
17074
+ ? _lt("Insert column left")
17075
+ : _lt("Insert %s columns left", number.toString());
17076
+ },
16389
17077
  execute: INSERT_COLUMNS_BEFORE_ACTION,
16390
17078
  isVisible: (env) => isConsecutive(env.model.getters.getActiveCols()) &&
16391
17079
  IS_ONLY_ONE_RANGE(env) &&
@@ -16394,16 +17082,33 @@ const colInsertColsBefore = {
16394
17082
  };
16395
17083
  const topBarInsertColsBefore = {
16396
17084
  ...colInsertColsBefore,
16397
- name: MENU_INSERT_COLUMNS_BEFORE_NAME,
17085
+ name: (env) => {
17086
+ const number = getColumnsNumber(env);
17087
+ if (number === 1) {
17088
+ return _lt("Column left");
17089
+ }
17090
+ return _lt("%s Columns left", number.toString());
17091
+ },
16398
17092
  };
16399
17093
  const cellInsertColsBefore = {
16400
17094
  ...colInsertColsBefore,
16401
- name: CELL_INSERT_COLUMNS_BEFORE_NAME,
17095
+ name: (env) => {
17096
+ const number = getColumnsNumber(env);
17097
+ if (number === 1) {
17098
+ return _lt("Insert column");
17099
+ }
17100
+ return _lt("Insert %s columns", number.toString());
17101
+ },
16402
17102
  isVisible: IS_ONLY_ONE_RANGE,
16403
17103
  icon: "o-spreadsheet-Icon.INSERT_COL_BEFORE",
16404
17104
  };
16405
17105
  const colInsertColsAfter = {
16406
- name: COLUMN_INSERT_COLUMNS_AFTER_NAME,
17106
+ name: (env) => {
17107
+ const number = getColumnsNumber(env);
17108
+ return number === 1
17109
+ ? _lt("Insert column right")
17110
+ : _lt("Insert %s columns right", number.toString());
17111
+ },
16407
17112
  execute: INSERT_COLUMNS_AFTER_ACTION,
16408
17113
  isVisible: (env) => isConsecutive(env.model.getters.getActiveCols()) &&
16409
17114
  IS_ONLY_ONE_RANGE(env) &&
@@ -16412,7 +17117,13 @@ const colInsertColsAfter = {
16412
17117
  };
16413
17118
  const topBarInsertColsAfter = {
16414
17119
  ...colInsertColsAfter,
16415
- name: MENU_INSERT_COLUMNS_AFTER_NAME,
17120
+ name: (env) => {
17121
+ const number = getColumnsNumber(env);
17122
+ if (number === 1) {
17123
+ return _lt("Column right");
17124
+ }
17125
+ return _lt("%s Columns right", number.toString());
17126
+ },
16416
17127
  execute: INSERT_COLUMNS_AFTER_ACTION,
16417
17128
  };
16418
17129
  const insertCell = {
@@ -16424,13 +17135,21 @@ const insertCell = {
16424
17135
  };
16425
17136
  const insertCellShiftDown = {
16426
17137
  name: _lt("Insert cells and shift down"),
16427
- execute: INSERT_CELL_SHIFT_DOWN,
17138
+ execute: (env) => {
17139
+ const zone = env.model.getters.getSelectedZone();
17140
+ const result = env.model.dispatch("INSERT_CELL", { zone, shiftDimension: "ROW" });
17141
+ handlePasteResult(env, result);
17142
+ },
16428
17143
  isVisible: (env) => env.model.getters.getActiveRows().size === 0 && env.model.getters.getActiveCols().size === 0,
16429
17144
  icon: "o-spreadsheet-Icon.INSERT_CELL_SHIFT_DOWN",
16430
17145
  };
16431
17146
  const insertCellShiftRight = {
16432
17147
  name: _lt("Insert cells and shift right"),
16433
- execute: INSERT_CELL_SHIFT_RIGHT,
17148
+ execute: (env) => {
17149
+ const zone = env.model.getters.getSelectedZone();
17150
+ const result = env.model.dispatch("INSERT_CELL", { zone, shiftDimension: "COL" });
17151
+ handlePasteResult(env, result);
17152
+ },
16434
17153
  isVisible: (env) => env.model.getters.getActiveRows().size === 0 && env.model.getters.getActiveCols().size === 0,
16435
17154
  icon: "o-spreadsheet-Icon.INSERT_CELL_SHIFT_RIGHT",
16436
17155
  };
@@ -16496,7 +17215,13 @@ const insertLink = {
16496
17215
  };
16497
17216
  const insertSheet = {
16498
17217
  name: _lt("Insert sheet"),
16499
- execute: CREATE_SHEET_ACTION,
17218
+ execute: (env) => {
17219
+ const activeSheetId = env.model.getters.getActiveSheetId();
17220
+ const position = env.model.getters.getSheetIds().indexOf(activeSheetId) + 1;
17221
+ const sheetId = env.model.uuidGenerator.uuidv4();
17222
+ env.model.dispatch("CREATE_SHEET", { sheetId, position });
17223
+ env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
17224
+ },
16500
17225
  icon: "o-spreadsheet-Icon.INSERT_SHEET",
16501
17226
  };
16502
17227
  function createFormulaFunctions(fnNames) {
@@ -16507,6 +17232,26 @@ function createFormulaFunctions(fnNames) {
16507
17232
  execute: (env) => env.startCellEdition(`=${fnName}(`),
16508
17233
  };
16509
17234
  });
17235
+ }
17236
+ function getRowsNumber(env) {
17237
+ const activeRows = env.model.getters.getActiveRows();
17238
+ if (activeRows.size) {
17239
+ return activeRows.size;
17240
+ }
17241
+ else {
17242
+ const zone = env.model.getters.getSelectedZones()[0];
17243
+ return zone.bottom - zone.top + 1;
17244
+ }
17245
+ }
17246
+ function getColumnsNumber(env) {
17247
+ const activeCols = env.model.getters.getActiveCols();
17248
+ if (activeCols.size) {
17249
+ return activeCols.size;
17250
+ }
17251
+ else {
17252
+ const zone = env.model.getters.getSelectedZones()[0];
17253
+ return zone.right - zone.left + 1;
17254
+ }
16510
17255
  }
16511
17256
 
16512
17257
  //------------------------------------------------------------------------------
@@ -16597,6 +17342,123 @@ cellMenuRegistry
16597
17342
  separator: true,
16598
17343
  });
16599
17344
 
17345
+ const SORT_TYPES = [
17346
+ CellValueType.number,
17347
+ CellValueType.error,
17348
+ CellValueType.text,
17349
+ CellValueType.boolean,
17350
+ ];
17351
+ function sortCells(cells, sortDirection, emptyCellAsZero) {
17352
+ const cellsWithIndex = cells.map((cell, index) => ({
17353
+ index,
17354
+ type: cell.type,
17355
+ value: cell.value,
17356
+ }));
17357
+ let emptyCells = cellsWithIndex.filter((x) => x.type === CellValueType.empty);
17358
+ let nonEmptyCells = cellsWithIndex.filter((x) => x.type !== CellValueType.empty);
17359
+ if (emptyCellAsZero) {
17360
+ nonEmptyCells.push(...emptyCells.map((emptyCell) => ({ ...emptyCell, type: CellValueType.number, value: 0 })));
17361
+ emptyCells = [];
17362
+ }
17363
+ const inverse = sortDirection === "descending" ? -1 : 1;
17364
+ return nonEmptyCells
17365
+ .sort((left, right) => {
17366
+ let typeOrder = SORT_TYPES.indexOf(left.type) - SORT_TYPES.indexOf(right.type);
17367
+ if (typeOrder === 0) {
17368
+ if (left.type === CellValueType.text || left.type === CellValueType.error) {
17369
+ typeOrder = left.value.localeCompare(right.value);
17370
+ }
17371
+ else
17372
+ typeOrder = left.value - right.value;
17373
+ }
17374
+ return inverse * typeOrder;
17375
+ })
17376
+ .concat(emptyCells);
17377
+ }
17378
+ function interactiveSortSelection(env, sheetId, anchor, zone, sortDirection) {
17379
+ let result = DispatchResult.Success;
17380
+ //several columns => bypass the contiguity check
17381
+ let multiColumns = zone.right > zone.left;
17382
+ if (env.model.getters.doesIntersectMerge(sheetId, zone)) {
17383
+ multiColumns = false;
17384
+ let table;
17385
+ for (let row = zone.top; row <= zone.bottom; row++) {
17386
+ table = [];
17387
+ for (let col = zone.left; col <= zone.right; col++) {
17388
+ let merge = env.model.getters.getMerge({ sheetId, col, row });
17389
+ if (merge && !table.includes(merge.id.toString())) {
17390
+ table.push(merge.id.toString());
17391
+ }
17392
+ }
17393
+ if (table.length >= 2) {
17394
+ multiColumns = true;
17395
+ break;
17396
+ }
17397
+ }
17398
+ }
17399
+ const { col, row } = anchor;
17400
+ if (multiColumns) {
17401
+ result = env.model.dispatch("SORT_CELLS", { sheetId, col, row, zone, sortDirection });
17402
+ }
17403
+ else {
17404
+ // check contiguity
17405
+ const contiguousZone = env.model.getters.getContiguousZone(sheetId, zone);
17406
+ if (isEqual(contiguousZone, zone)) {
17407
+ // merge as it is
17408
+ result = env.model.dispatch("SORT_CELLS", {
17409
+ sheetId,
17410
+ col,
17411
+ row,
17412
+ zone,
17413
+ sortDirection,
17414
+ });
17415
+ }
17416
+ else {
17417
+ 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?"), () => {
17418
+ zone = contiguousZone;
17419
+ result = env.model.dispatch("SORT_CELLS", {
17420
+ sheetId,
17421
+ col,
17422
+ row,
17423
+ zone,
17424
+ sortDirection,
17425
+ });
17426
+ }, () => {
17427
+ result = env.model.dispatch("SORT_CELLS", {
17428
+ sheetId,
17429
+ col,
17430
+ row,
17431
+ zone,
17432
+ sortDirection,
17433
+ });
17434
+ });
17435
+ }
17436
+ }
17437
+ if (result.isCancelledBecause(64 /* CommandResult.InvalidSortZone */)) {
17438
+ const { col, row } = anchor;
17439
+ env.model.selection.selectZone({ cell: { col, row }, zone });
17440
+ env.raiseError(_lt("Cannot sort. To sort, select only cells or only merges that have the same size."));
17441
+ }
17442
+ }
17443
+
17444
+ const AddFilterInteractiveContent = {
17445
+ filterOverlap: _lt("You cannot create overlapping filters."),
17446
+ nonContinuousTargets: _lt("A filter can only be created on a continuous selection."),
17447
+ mergeInFilter: _lt("You can't create a filter over a range that contains a merge."),
17448
+ };
17449
+ function interactiveAddFilter(env, sheetId, target) {
17450
+ const result = env.model.dispatch("CREATE_FILTER_TABLE", { target, sheetId });
17451
+ if (result.isCancelledBecause(79 /* CommandResult.FilterOverlap */)) {
17452
+ env.raiseError(AddFilterInteractiveContent.filterOverlap);
17453
+ }
17454
+ else if (result.isCancelledBecause(81 /* CommandResult.MergeInFilter */)) {
17455
+ env.raiseError(AddFilterInteractiveContent.mergeInFilter);
17456
+ }
17457
+ else if (result.isCancelledBecause(82 /* CommandResult.NonContinuousTargets */)) {
17458
+ env.raiseError(AddFilterInteractiveContent.nonContinuousTargets);
17459
+ }
17460
+ }
17461
+
16600
17462
  const sortRange = {
16601
17463
  name: _lt("Sort range"),
16602
17464
  isVisible: IS_ONLY_ONE_RANGE,
@@ -16604,24 +17466,45 @@ const sortRange = {
16604
17466
  };
16605
17467
  const sortAscending = {
16606
17468
  name: _lt("Ascending (A ⟶ Z)"),
16607
- execute: SORT_CELLS_ASCENDING,
17469
+ execute: (env) => {
17470
+ const { anchor, zones } = env.model.getters.getSelection();
17471
+ const sheetId = env.model.getters.getActiveSheetId();
17472
+ interactiveSortSelection(env, sheetId, anchor.cell, zones[0], "ascending");
17473
+ },
16608
17474
  icon: "o-spreadsheet-Icon.SORT_ASCENDING",
16609
17475
  };
16610
17476
  const sortDescending = {
16611
17477
  name: _lt("Descending (Z ⟶ A)"),
16612
- execute: SORT_CELLS_DESCENDING,
17478
+ execute: (env) => {
17479
+ const { anchor, zones } = env.model.getters.getSelection();
17480
+ const sheetId = env.model.getters.getActiveSheetId();
17481
+ interactiveSortSelection(env, sheetId, anchor.cell, zones[0], "descending");
17482
+ },
16613
17483
  icon: "o-spreadsheet-Icon.SORT_DESCENDING",
16614
17484
  };
16615
17485
  const addDataFilter = {
16616
17486
  name: _lt("Create filter"),
16617
- execute: FILTERS_CREATE_FILTER_TABLE,
17487
+ execute: (env) => {
17488
+ const sheetId = env.model.getters.getActiveSheetId();
17489
+ const selection = env.model.getters.getSelection().zones;
17490
+ interactiveAddFilter(env, sheetId, selection);
17491
+ },
16618
17492
  isVisible: (env) => !SELECTION_CONTAINS_FILTER(env),
16619
- isEnabled: (env) => SELECTION_IS_CONTINUOUS(env),
17493
+ isEnabled: (env) => {
17494
+ const selectedZones = env.model.getters.getSelectedZones();
17495
+ return areZonesContinuous(...selectedZones);
17496
+ },
16620
17497
  icon: "o-spreadsheet-Icon.MENU_FILTER_ICON",
16621
17498
  };
16622
17499
  const removeDataFilter = {
16623
17500
  name: _lt("Remove filter"),
16624
- execute: FILTERS_REMOVE_FILTER_TABLE,
17501
+ execute: (env) => {
17502
+ const sheetId = env.model.getters.getActiveSheetId();
17503
+ env.model.dispatch("REMOVE_FILTER_TABLE", {
17504
+ sheetId,
17505
+ target: env.model.getters.getSelectedZones(),
17506
+ });
17507
+ },
16625
17508
  isVisible: SELECTION_CONTAINS_FILTER,
16626
17509
  icon: "o-spreadsheet-Icon.MENU_FILTER_ICON",
16627
17510
  };
@@ -16635,13 +17518,13 @@ const splitToColumns = {
16635
17518
 
16636
17519
  const formatNumberAutomatic = {
16637
17520
  name: _lt("Automatic"),
16638
- execute: FORMAT_AUTOMATIC_ACTION,
17521
+ execute: (env) => setFormatter(env, ""),
16639
17522
  isActive: (env) => isAutomaticFormatSelected(env),
16640
17523
  };
16641
17524
  const formatNumberNumber = {
16642
17525
  name: _lt("Number"),
16643
17526
  description: "1,000.12",
16644
- execute: FORMAT_NUMBER_ACTION,
17527
+ execute: (env) => setFormatter(env, "#,##0.00"),
16645
17528
  isActive: (env) => isFormatSelected(env, "#,##0.00"),
16646
17529
  };
16647
17530
  const formatPercent = {
@@ -16658,42 +17541,42 @@ const formatNumberPercent = {
16658
17541
  const formatNumberCurrency = {
16659
17542
  name: _lt("Currency"),
16660
17543
  description: "$1,000.12",
16661
- execute: FORMAT_CURRENCY_ACTION,
17544
+ execute: (env) => setFormatter(env, "[$$]#,##0.00"),
16662
17545
  isActive: (env) => isFormatSelected(env, "[$$]#,##0.00"),
16663
17546
  };
16664
17547
  const formatNumberCurrencyRounded = {
16665
17548
  name: _lt("Currency rounded"),
16666
17549
  description: "$1,000",
16667
- execute: FORMAT_CURRENCY_ROUNDED_ACTION,
17550
+ execute: (env) => setFormatter(env, "[$$]#,##0"),
16668
17551
  isActive: (env) => isFormatSelected(env, "[$$]#,##0"),
16669
17552
  };
16670
17553
  const formatCustomCurrency = {
16671
17554
  name: _lt("Custom currency"),
16672
17555
  isVisible: (env) => env.loadCurrencies !== undefined,
16673
- execute: OPEN_CUSTOM_CURRENCY_SIDEPANEL_ACTION,
17556
+ execute: (env) => env.openSidePanel("CustomCurrency", {}),
16674
17557
  };
16675
17558
  const formatNumberDate = {
16676
17559
  name: _lt("Date"),
16677
17560
  description: "9/26/2008",
16678
- execute: FORMAT_DATE_ACTION,
17561
+ execute: (env) => setFormatter(env, "m/d/yyyy"),
16679
17562
  isActive: (env) => isFormatSelected(env, "m/d/yyyy"),
16680
17563
  };
16681
17564
  const formatNumberTime = {
16682
17565
  name: _lt("Time"),
16683
17566
  description: "10:43:00 PM",
16684
- execute: FORMAT_TIME_ACTION,
17567
+ execute: (env) => setFormatter(env, "hh:mm:ss a"),
16685
17568
  isActive: (env) => isFormatSelected(env, "hh:mm:ss a"),
16686
17569
  };
16687
17570
  const formatNumberDateTime = {
16688
17571
  name: _lt("Date time"),
16689
17572
  description: "9/26/2008 22:43:00",
16690
- execute: FORMAT_DATE_TIME_ACTION,
17573
+ execute: (env) => setFormatter(env, "m/d/yyyy hh:mm:ss"),
16691
17574
  isActive: (env) => isFormatSelected(env, "m/d/yyyy hh:mm:ss"),
16692
17575
  };
16693
17576
  const formatNumberDuration = {
16694
17577
  name: _lt("Duration"),
16695
17578
  description: "27:51:38",
16696
- execute: FORMAT_DURATION_ACTION,
17579
+ execute: (env) => setFormatter(env, "hhhh:mm:ss"),
16697
17580
  isActive: (env) => isFormatSelected(env, "hhhh:mm:ss"),
16698
17581
  };
16699
17582
  const incraseDecimalPlaces = {
@@ -16717,27 +17600,27 @@ const decraseDecimalPlaces = {
16717
17600
  const formatBold = {
16718
17601
  name: _lt("Bold"),
16719
17602
  description: "Ctrl+B",
16720
- execute: FORMAT_BOLD_ACTION,
17603
+ execute: (env) => setStyle(env, { bold: !env.model.getters.getCurrentStyle().bold }),
16721
17604
  icon: "o-spreadsheet-Icon.BOLD",
16722
17605
  isActive: (env) => !!env.model.getters.getCurrentStyle().bold,
16723
17606
  };
16724
17607
  const formatItalic = {
16725
17608
  name: _lt("Italic"),
16726
17609
  description: "Ctrl+I",
16727
- execute: FORMAT_ITALIC_ACTION,
17610
+ execute: (env) => setStyle(env, { italic: !env.model.getters.getCurrentStyle().italic }),
16728
17611
  icon: "o-spreadsheet-Icon.ITALIC",
16729
17612
  isActive: (env) => !!env.model.getters.getCurrentStyle().italic,
16730
17613
  };
16731
17614
  const formatUnderline = {
16732
17615
  name: _lt("Underline"),
16733
17616
  description: "Ctrl+U",
16734
- execute: FORMAT_UNDERLINE_ACTION,
17617
+ execute: (env) => setStyle(env, { underline: !env.model.getters.getCurrentStyle().underline }),
16735
17618
  icon: "o-spreadsheet-Icon.UNDERLINE",
16736
17619
  isActive: (env) => !!env.model.getters.getCurrentStyle().underline,
16737
17620
  };
16738
17621
  const formatStrikethrough = {
16739
17622
  name: _lt("Strikethrough"),
16740
- execute: FORMAT_STRIKETHROUGH_ACTION,
17623
+ execute: (env) => setStyle(env, { strikethrough: !env.model.getters.getCurrentStyle().strikethrough }),
16741
17624
  icon: "o-spreadsheet-Icon.STRIKE",
16742
17625
  isActive: (env) => !!env.model.getters.getCurrentStyle().strikethrough,
16743
17626
  };
@@ -16843,7 +17726,10 @@ const paintFormat = {
16843
17726
  const clearFormat = {
16844
17727
  name: _lt("Clear formatting"),
16845
17728
  description: "Ctrl+<",
16846
- execute: FORMAT_CLEARFORMAT_ACTION,
17729
+ execute: (env) => env.model.dispatch("CLEAR_FORMATTING", {
17730
+ sheetId: env.model.getters.getActiveSheetId(),
17731
+ target: env.model.getters.getSelectedZones(),
17732
+ }),
16847
17733
  icon: "o-spreadsheet-Icon.CLEAR_FORMAT",
16848
17734
  };
16849
17735
  function fontSizeMenuBuilder() {
@@ -16922,20 +17808,34 @@ function interactiveFreezeColumnsRows(env, dimension, base) {
16922
17808
  const sheetId = env.model.getters.getActiveSheetId();
16923
17809
  const cmd = dimension === "COL" ? "FREEZE_COLUMNS" : "FREEZE_ROWS";
16924
17810
  const result = env.model.dispatch(cmd, { sheetId, quantity: base });
16925
- if (result.isCancelledBecause(65 /* CommandResult.MergeOverlap */)) {
17811
+ if (result.isCancelledBecause(66 /* CommandResult.MergeOverlap */)) {
16926
17812
  env.raiseError(MergeErrorMessage);
16927
17813
  }
16928
17814
  }
16929
17815
 
16930
17816
  const hideCols = {
16931
17817
  name: HIDE_COLUMNS_NAME,
16932
- execute: HIDE_COLUMNS_ACTION,
17818
+ execute: (env) => {
17819
+ const columns = env.model.getters.getElementsFromSelection("COL");
17820
+ env.model.dispatch("HIDE_COLUMNS_ROWS", {
17821
+ sheetId: env.model.getters.getActiveSheetId(),
17822
+ dimension: "COL",
17823
+ elements: columns,
17824
+ });
17825
+ },
16933
17826
  isVisible: NOT_ALL_VISIBLE_COLS_SELECTED,
16934
17827
  icon: "o-spreadsheet-Icon.HIDE_COL",
16935
17828
  };
16936
17829
  const unhideCols = {
16937
17830
  name: _lt("Unhide columns"),
16938
- execute: UNHIDE_COLUMNS_ACTION,
17831
+ execute: (env) => {
17832
+ const columns = env.model.getters.getElementsFromSelection("COL");
17833
+ env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
17834
+ sheetId: env.model.getters.getActiveSheetId(),
17835
+ dimension: "COL",
17836
+ elements: columns,
17837
+ });
17838
+ },
16939
17839
  isVisible: (env) => {
16940
17840
  const hiddenCols = env.model.getters
16941
17841
  .getHiddenColsGroups(env.model.getters.getActiveSheetId())
@@ -16946,18 +17846,39 @@ const unhideCols = {
16946
17846
  };
16947
17847
  const unhideAllCols = {
16948
17848
  name: _lt("Unhide all columns"),
16949
- execute: UNHIDE_ALL_COLUMNS_ACTION,
17849
+ execute: (env) => {
17850
+ const sheetId = env.model.getters.getActiveSheetId();
17851
+ env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
17852
+ sheetId,
17853
+ dimension: "COL",
17854
+ elements: Array.from(Array(env.model.getters.getNumberCols(sheetId)).keys()),
17855
+ });
17856
+ },
16950
17857
  isVisible: (env) => env.model.getters.getHiddenColsGroups(env.model.getters.getActiveSheetId()).length > 0,
16951
17858
  };
16952
17859
  const hideRows = {
16953
17860
  name: HIDE_ROWS_NAME,
16954
- execute: HIDE_ROWS_ACTION,
17861
+ execute: (env) => {
17862
+ const rows = env.model.getters.getElementsFromSelection("ROW");
17863
+ env.model.dispatch("HIDE_COLUMNS_ROWS", {
17864
+ sheetId: env.model.getters.getActiveSheetId(),
17865
+ dimension: "ROW",
17866
+ elements: rows,
17867
+ });
17868
+ },
16955
17869
  isVisible: NOT_ALL_VISIBLE_ROWS_SELECTED,
16956
17870
  icon: "o-spreadsheet-Icon.HIDE_ROW",
16957
17871
  };
16958
17872
  const unhideRows = {
16959
17873
  name: _lt("Unhide rows"),
16960
- execute: UNHIDE_ROWS_ACTION,
17874
+ execute: (env) => {
17875
+ const columns = env.model.getters.getElementsFromSelection("ROW");
17876
+ env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
17877
+ sheetId: env.model.getters.getActiveSheetId(),
17878
+ dimension: "ROW",
17879
+ elements: columns,
17880
+ });
17881
+ },
16961
17882
  isVisible: (env) => {
16962
17883
  const hiddenRows = env.model.getters
16963
17884
  .getHiddenRowsGroups(env.model.getters.getActiveSheetId())
@@ -16968,7 +17889,14 @@ const unhideRows = {
16968
17889
  };
16969
17890
  const unhideAllRows = {
16970
17891
  name: _lt("Unhide all rows"),
16971
- execute: UNHIDE_ALL_ROWS_ACTION,
17892
+ execute: (env) => {
17893
+ const sheetId = env.model.getters.getActiveSheetId();
17894
+ env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
17895
+ sheetId,
17896
+ dimension: "ROW",
17897
+ elements: Array.from(Array(env.model.getters.getNumberRows(sheetId)).keys()),
17898
+ });
17899
+ },
16972
17900
  isVisible: (env) => env.model.getters.getHiddenRowsGroups(env.model.getters.getActiveSheetId()).length > 0,
16973
17901
  };
16974
17902
  const unFreezePane = {
@@ -17042,12 +17970,18 @@ const viewGridlines = {
17042
17970
  name: (env) => env.model.getters.getGridLinesVisibility(env.model.getters.getActiveSheetId())
17043
17971
  ? _lt("Hide gridlines")
17044
17972
  : _lt("Show gridlines"),
17045
- execute: SET_GRID_LINES_VISIBILITY_ACTION,
17973
+ execute: (env) => {
17974
+ const sheetId = env.model.getters.getActiveSheetId();
17975
+ env.model.dispatch("SET_GRID_LINES_VISIBILITY", {
17976
+ sheetId,
17977
+ areGridLinesVisible: !env.model.getters.getGridLinesVisibility(sheetId),
17978
+ });
17979
+ },
17046
17980
  icon: "o-spreadsheet-Icon.SHOW_HIDE_GRID",
17047
17981
  };
17048
17982
  const viewFormulas = {
17049
17983
  name: (env) => env.model.getters.shouldShowFormulas() ? _lt("Hide formulas") : _lt("Show formulas"),
17050
- execute: SET_FORMULA_VISIBILITY_ACTION,
17984
+ execute: (env) => env.model.dispatch("SET_FORMULA_VISIBILITY", { show: !env.model.getters.shouldShowFormulas() }),
17051
17985
  isReadonlyAllowed: true,
17052
17986
  icon: "o-spreadsheet-Icon.SHOW_HIDE_FORMULA",
17053
17987
  };
@@ -18011,10 +18945,10 @@ class LineBarPieConfigPanel extends owl.Component {
18011
18945
  return cancelledReasons.map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
18012
18946
  }
18013
18947
  get isDatasetInvalid() {
18014
- return !!this.state.datasetDispatchResult?.isCancelledBecause(32 /* CommandResult.InvalidDataSet */);
18948
+ return !!this.state.datasetDispatchResult?.isCancelledBecause(33 /* CommandResult.InvalidDataSet */);
18015
18949
  }
18016
18950
  get isLabelInvalid() {
18017
- return !!this.state.labelsDispatchResult?.isCancelledBecause(33 /* CommandResult.InvalidLabelRange */);
18951
+ return !!this.state.labelsDispatchResult?.isCancelledBecause(34 /* CommandResult.InvalidLabelRange */);
18018
18952
  }
18019
18953
  onUpdateDataSetsHaveTitle(ev) {
18020
18954
  this.props.updateChart(this.props.figureId, {
@@ -18645,12 +19579,14 @@ class LineBarPieDesignPanel extends owl.Component {
18645
19579
  static template = "o-spreadsheet-LineBarPieDesignPanel";
18646
19580
  static components = { ColorPickerWidget };
18647
19581
  state = owl.useState({
19582
+ title: "",
18648
19583
  fillColorTool: false,
18649
19584
  });
18650
19585
  onClick(ev) {
18651
19586
  this.state.fillColorTool = false;
18652
19587
  }
18653
19588
  setup() {
19589
+ this.state.title = _t(this.props.definition.title);
18654
19590
  owl.useExternalListener(window, "click", this.onClick);
18655
19591
  }
18656
19592
  toggleColorPicker() {
@@ -18661,9 +19597,9 @@ class LineBarPieDesignPanel extends owl.Component {
18661
19597
  background: color,
18662
19598
  });
18663
19599
  }
18664
- updateTitle(ev) {
19600
+ updateTitle() {
18665
19601
  this.props.updateChart(this.props.figureId, {
18666
- title: ev.target.value,
19602
+ title: this.state.title,
18667
19603
  });
18668
19604
  }
18669
19605
  updateSelect(attr, ev) {
@@ -18695,7 +19631,7 @@ class GaugeChartConfigPanel extends owl.Component {
18695
19631
  return cancelledReasons.map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
18696
19632
  }
18697
19633
  get isDataRangeInvalid() {
18698
- return !!this.state.dataRangeDispatchResult?.isCancelledBecause(36 /* CommandResult.InvalidGaugeDataRange */);
19634
+ return !!this.state.dataRangeDispatchResult?.isCancelledBecause(37 /* CommandResult.InvalidGaugeDataRange */);
18699
19635
  }
18700
19636
  onDataRangeChanged(ranges) {
18701
19637
  this.dataRange = ranges[0];
@@ -18754,11 +19690,13 @@ class GaugeChartDesignPanel extends owl.Component {
18754
19690
  static template = "o-spreadsheet-GaugeChartDesignPanel";
18755
19691
  static components = { ColorPickerWidget, SidePanelErrors };
18756
19692
  state = owl.useState({
19693
+ title: "",
18757
19694
  openedMenu: undefined,
18758
19695
  sectionRuleDispatchResult: undefined,
18759
19696
  sectionRule: deepCopy(this.props.definition.sectionRule),
18760
19697
  });
18761
19698
  setup() {
19699
+ this.state.title = _t(this.props.definition.title);
18762
19700
  owl.useExternalListener(window, "click", this.closeMenus);
18763
19701
  }
18764
19702
  get designErrorMessages() {
@@ -18771,31 +19709,31 @@ class GaugeChartDesignPanel extends owl.Component {
18771
19709
  background: color,
18772
19710
  });
18773
19711
  }
18774
- updateTitle(ev) {
19712
+ updateTitle() {
18775
19713
  this.props.updateChart(this.props.figureId, {
18776
- title: ev.target.value,
19714
+ title: this.state.title,
18777
19715
  });
18778
19716
  }
18779
19717
  isRangeMinInvalid() {
18780
- return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(37 /* CommandResult.EmptyGaugeRangeMin */) ||
18781
- this.state.sectionRuleDispatchResult?.isCancelledBecause(38 /* CommandResult.GaugeRangeMinNaN */) ||
18782
- this.state.sectionRuleDispatchResult?.isCancelledBecause(41 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */));
19718
+ return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(38 /* CommandResult.EmptyGaugeRangeMin */) ||
19719
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(39 /* CommandResult.GaugeRangeMinNaN */) ||
19720
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(42 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */));
18783
19721
  }
18784
19722
  isRangeMaxInvalid() {
18785
- return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(39 /* CommandResult.EmptyGaugeRangeMax */) ||
18786
- this.state.sectionRuleDispatchResult?.isCancelledBecause(40 /* CommandResult.GaugeRangeMaxNaN */) ||
18787
- this.state.sectionRuleDispatchResult?.isCancelledBecause(41 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */));
19723
+ return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(40 /* CommandResult.EmptyGaugeRangeMax */) ||
19724
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(41 /* CommandResult.GaugeRangeMaxNaN */) ||
19725
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(42 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */));
18788
19726
  }
18789
19727
  // ---------------------------------------------------------------------------
18790
19728
  // COLOR_SECTION_TEMPLATE
18791
19729
  // ---------------------------------------------------------------------------
18792
19730
  get isLowerInflectionPointInvalid() {
18793
- return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(42 /* CommandResult.GaugeLowerInflectionPointNaN */) ||
18794
- this.state.sectionRuleDispatchResult?.isCancelledBecause(44 /* CommandResult.GaugeLowerBiggerThanUpper */));
19731
+ return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(43 /* CommandResult.GaugeLowerInflectionPointNaN */) ||
19732
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(45 /* CommandResult.GaugeLowerBiggerThanUpper */));
18795
19733
  }
18796
19734
  get isUpperInflectionPointInvalid() {
18797
- return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(43 /* CommandResult.GaugeUpperInflectionPointNaN */) ||
18798
- this.state.sectionRuleDispatchResult?.isCancelledBecause(44 /* CommandResult.GaugeLowerBiggerThanUpper */));
19735
+ return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(44 /* CommandResult.GaugeUpperInflectionPointNaN */) ||
19736
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(45 /* CommandResult.GaugeLowerBiggerThanUpper */));
18799
19737
  }
18800
19738
  updateSectionColor(target, color) {
18801
19739
  const sectionRule = deepCopy(this.state.sectionRule);
@@ -18878,10 +19816,10 @@ class ScorecardChartConfigPanel extends owl.Component {
18878
19816
  return cancelledReasons.map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
18879
19817
  }
18880
19818
  get isKeyValueInvalid() {
18881
- return !!this.state.keyValueDispatchResult?.isCancelledBecause(34 /* CommandResult.InvalidScorecardKeyValue */);
19819
+ return !!this.state.keyValueDispatchResult?.isCancelledBecause(35 /* CommandResult.InvalidScorecardKeyValue */);
18882
19820
  }
18883
19821
  get isBaselineInvalid() {
18884
- return !!this.state.keyValueDispatchResult?.isCancelledBecause(35 /* CommandResult.InvalidScorecardBaseline */);
19822
+ return !!this.state.keyValueDispatchResult?.isCancelledBecause(36 /* CommandResult.InvalidScorecardBaseline */);
18885
19823
  }
18886
19824
  onKeyValueRangeChanged(ranges) {
18887
19825
  this.keyValue = ranges[0];
@@ -18926,14 +19864,16 @@ class ScorecardChartDesignPanel extends owl.Component {
18926
19864
  static template = "o-spreadsheet-ScorecardChartDesignPanel";
18927
19865
  static components = { ColorPickerWidget };
18928
19866
  state = owl.useState({
19867
+ title: "",
18929
19868
  openedColorPicker: undefined,
18930
19869
  });
18931
19870
  setup() {
19871
+ this.state.title = _t(this.props.definition.title);
18932
19872
  owl.useExternalListener(window, "click", this.closeMenus);
18933
19873
  }
18934
- updateTitle(ev) {
19874
+ updateTitle() {
18935
19875
  this.props.updateChart(this.props.figureId, {
18936
- title: ev.target.value,
19876
+ title: this.state.title,
18937
19877
  });
18938
19878
  }
18939
19879
  updateBaselineDescr(ev) {
@@ -19555,7 +20495,7 @@ class ConditionalFormattingPanel extends owl.Component {
19555
20495
  return this.env.model.getters.getConditionalFormats(this.env.model.getters.getActiveSheetId());
19556
20496
  }
19557
20497
  get isRangeValid() {
19558
- return this.state.errors.includes(24 /* CommandResult.EmptyRange */);
20498
+ return this.state.errors.includes(25 /* CommandResult.EmptyRange */);
19559
20499
  }
19560
20500
  errorMessage(error) {
19561
20501
  return CfTerms.Errors[error] || CfTerms.Errors.Unexpected;
@@ -19614,7 +20554,7 @@ class ConditionalFormattingPanel extends owl.Component {
19614
20554
  if (this.state.currentCF) {
19615
20555
  const invalidRanges = this.state.currentCF.ranges.some((xc) => !xc.match(rangeReference));
19616
20556
  if (invalidRanges) {
19617
- this.state.errors = [25 /* CommandResult.InvalidRange */];
20557
+ this.state.errors = [26 /* CommandResult.InvalidRange */];
19618
20558
  return;
19619
20559
  }
19620
20560
  const sheetId = this.env.model.getters.getActiveSheetId();
@@ -19769,10 +20709,10 @@ class ConditionalFormattingPanel extends owl.Component {
19769
20709
  * Cell Is Rule
19770
20710
  ****************************************************************************/
19771
20711
  get isValue1Invalid() {
19772
- return !!this.state.errors?.includes(51 /* CommandResult.FirstArgMissing */);
20712
+ return !!this.state.errors?.includes(52 /* CommandResult.FirstArgMissing */);
19773
20713
  }
19774
20714
  get isValue2Invalid() {
19775
- return !!this.state.errors?.includes(52 /* CommandResult.SecondArgMissing */);
20715
+ return !!this.state.errors?.includes(53 /* CommandResult.SecondArgMissing */);
19776
20716
  }
19777
20717
  toggleStyle(tool) {
19778
20718
  const style = this.state.rules.cellIs.style;
@@ -19789,17 +20729,17 @@ class ConditionalFormattingPanel extends owl.Component {
19789
20729
  isValueInvalid(threshold) {
19790
20730
  switch (threshold) {
19791
20731
  case "minimum":
19792
- return (this.state.errors.includes(58 /* CommandResult.MinInvalidFormula */) ||
19793
- this.state.errors.includes(50 /* CommandResult.MinBiggerThanMid */) ||
19794
- this.state.errors.includes(47 /* CommandResult.MinBiggerThanMax */) ||
19795
- this.state.errors.includes(53 /* CommandResult.MinNaN */));
20732
+ return (this.state.errors.includes(59 /* CommandResult.MinInvalidFormula */) ||
20733
+ this.state.errors.includes(51 /* CommandResult.MinBiggerThanMid */) ||
20734
+ this.state.errors.includes(48 /* CommandResult.MinBiggerThanMax */) ||
20735
+ this.state.errors.includes(54 /* CommandResult.MinNaN */));
19796
20736
  case "midpoint":
19797
- return (this.state.errors.includes(59 /* CommandResult.MidInvalidFormula */) ||
19798
- this.state.errors.includes(54 /* CommandResult.MidNaN */) ||
19799
- this.state.errors.includes(49 /* CommandResult.MidBiggerThanMax */));
20737
+ return (this.state.errors.includes(60 /* CommandResult.MidInvalidFormula */) ||
20738
+ this.state.errors.includes(55 /* CommandResult.MidNaN */) ||
20739
+ this.state.errors.includes(50 /* CommandResult.MidBiggerThanMax */));
19800
20740
  case "maximum":
19801
- return (this.state.errors.includes(60 /* CommandResult.MaxInvalidFormula */) ||
19802
- this.state.errors.includes(55 /* CommandResult.MaxNaN */));
20741
+ return (this.state.errors.includes(61 /* CommandResult.MaxInvalidFormula */) ||
20742
+ this.state.errors.includes(56 /* CommandResult.MaxNaN */));
19803
20743
  default:
19804
20744
  return false;
19805
20745
  }
@@ -19847,13 +20787,13 @@ class ConditionalFormattingPanel extends owl.Component {
19847
20787
  isInflectionPointInvalid(inflectionPoint) {
19848
20788
  switch (inflectionPoint) {
19849
20789
  case "lowerInflectionPoint":
19850
- return (this.state.errors.includes(57 /* CommandResult.ValueLowerInflectionNaN */) ||
19851
- this.state.errors.includes(62 /* CommandResult.ValueLowerInvalidFormula */) ||
19852
- this.state.errors.includes(48 /* CommandResult.LowerBiggerThanUpper */));
20790
+ return (this.state.errors.includes(58 /* CommandResult.ValueLowerInflectionNaN */) ||
20791
+ this.state.errors.includes(63 /* CommandResult.ValueLowerInvalidFormula */) ||
20792
+ this.state.errors.includes(49 /* CommandResult.LowerBiggerThanUpper */));
19853
20793
  case "upperInflectionPoint":
19854
- return (this.state.errors.includes(56 /* CommandResult.ValueUpperInflectionNaN */) ||
19855
- this.state.errors.includes(61 /* CommandResult.ValueUpperInvalidFormula */) ||
19856
- this.state.errors.includes(48 /* CommandResult.LowerBiggerThanUpper */));
20794
+ return (this.state.errors.includes(57 /* CommandResult.ValueUpperInflectionNaN */) ||
20795
+ this.state.errors.includes(62 /* CommandResult.ValueUpperInvalidFormula */) ||
20796
+ this.state.errors.includes(49 /* CommandResult.LowerBiggerThanUpper */));
19857
20797
  default:
19858
20798
  return true;
19859
20799
  }
@@ -20163,7 +21103,7 @@ const SplitToColumnsInteractiveContent = {
20163
21103
  };
20164
21104
  function interactiveSplitToColumns(env, separator, addNewColumns) {
20165
21105
  let result = env.model.dispatch("SPLIT_TEXT_INTO_COLUMNS", { separator, addNewColumns });
20166
- if (result.isCancelledBecause(90 /* CommandResult.SplitWillOverwriteContent */)) {
21106
+ if (result.isCancelledBecause(91 /* CommandResult.SplitWillOverwriteContent */)) {
20167
21107
  env.askConfirmation(SplitToColumnsInteractiveContent.SplitIsDestructive, () => {
20168
21108
  result = env.model.dispatch("SPLIT_TEXT_INTO_COLUMNS", {
20169
21109
  separator,
@@ -20227,8 +21167,8 @@ class SplitIntoColumnsPanel extends owl.Component {
20227
21167
  const errors = new Set();
20228
21168
  for (const reason of cancelledReasons) {
20229
21169
  switch (reason) {
20230
- case 90 /* CommandResult.SplitWillOverwriteContent */:
20231
- case 89 /* CommandResult.EmptySplitSeparator */:
21170
+ case 91 /* CommandResult.SplitWillOverwriteContent */:
21171
+ case 90 /* CommandResult.EmptySplitSeparator */:
20232
21172
  break;
20233
21173
  default:
20234
21174
  errors.add(SplitToColumnsTerms.Errors[reason] || SplitToColumnsTerms.Errors.Unexpected);
@@ -20243,8 +21183,8 @@ class SplitIntoColumnsPanel extends owl.Component {
20243
21183
  addNewColumns: this.state.addNewColumns,
20244
21184
  force: false,
20245
21185
  }).reasons;
20246
- if (cancelledReasons.includes(90 /* CommandResult.SplitWillOverwriteContent */)) {
20247
- warnings.push(SplitToColumnsTerms.Errors[90 /* CommandResult.SplitWillOverwriteContent */]);
21186
+ if (cancelledReasons.includes(91 /* CommandResult.SplitWillOverwriteContent */)) {
21187
+ warnings.push(SplitToColumnsTerms.Errors[91 /* CommandResult.SplitWillOverwriteContent */]);
20248
21188
  }
20249
21189
  return warnings;
20250
21190
  }
@@ -20897,6 +21837,13 @@ class ContentEditableHelper {
20897
21837
  const element = focusedNode instanceof HTMLElement ? focusedNode : focusedNode.parentElement;
20898
21838
  element?.scrollIntoView({ block: "nearest" });
20899
21839
  }
21840
+ /**
21841
+ * remove the current selection of the user
21842
+ * */
21843
+ removeSelection() {
21844
+ let selection = window.getSelection();
21845
+ selection.removeAllRanges();
21846
+ }
20900
21847
  removeAll() {
20901
21848
  if (this.el) {
20902
21849
  while (this.el.firstChild) {
@@ -21383,6 +22330,21 @@ class Composer extends owl.Component {
21383
22330
  this.autoCompleteState.values = values.slice(0, 10);
21384
22331
  this.autoCompleteState.selectedIndex = 0;
21385
22332
  }
22333
+ /**
22334
+ * This is required to ensure the content helper selection is
22335
+ * properly updated on "onclick" events. Depending on the browser,
22336
+ * the callback onClick from the composer will be executed before
22337
+ * the selection was updated in the dom, which means we capture an
22338
+ * wrong selection which is then forced upon the content helper on
22339
+ * patchContent.
22340
+ */
22341
+ onMousedown(ev) {
22342
+ if (ev.button > 0) {
22343
+ // not main button, probably a context menu
22344
+ return;
22345
+ }
22346
+ this.contentHelper.removeSelection();
22347
+ }
21386
22348
  onClick() {
21387
22349
  if (this.env.model.getters.isReadonly()) {
21388
22350
  return;
@@ -21395,6 +22357,29 @@ class Composer extends owl.Component {
21395
22357
  this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", newSelection);
21396
22358
  this.processTokenAtCursor();
21397
22359
  }
22360
+ onDblClick() {
22361
+ if (this.env.model.getters.isReadonly()) {
22362
+ return;
22363
+ }
22364
+ const composerContent = this.env.model.getters.getCurrentContent();
22365
+ const isValidFormula = composerContent.startsWith("=");
22366
+ if (isValidFormula) {
22367
+ const tokens = this.env.model.getters.getCurrentTokens();
22368
+ const currentSelection = this.contentHelper.getCurrentSelection();
22369
+ if (currentSelection.start === currentSelection.end)
22370
+ return;
22371
+ const currentSelectedText = composerContent.substring(currentSelection.start, currentSelection.end);
22372
+ const token = tokens.filter((token) => token.value.includes(currentSelectedText) &&
22373
+ token.start <= currentSelection.start &&
22374
+ token.end >= currentSelection.end)[0];
22375
+ if (token.type === "REFERENCE") {
22376
+ this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", {
22377
+ start: token.start,
22378
+ end: token.end,
22379
+ });
22380
+ }
22381
+ }
22382
+ }
21398
22383
  // ---------------------------------------------------------------------------
21399
22384
  // Private
21400
22385
  // ---------------------------------------------------------------------------
@@ -21423,7 +22408,7 @@ class Composer extends owl.Component {
21423
22408
  */
21424
22409
  getContentLines() {
21425
22410
  let value = this.env.model.getters.getCurrentContent();
21426
- const isValidFormula = value.startsWith("=") && this.env.model.getters.getCurrentTokens().length > 0;
22411
+ const isValidFormula = value.startsWith("=");
21427
22412
  if (value === "") {
21428
22413
  return [];
21429
22414
  }
@@ -24132,7 +25117,7 @@ class Grid extends owl.Component {
24132
25117
  }
24133
25118
  ev.preventDefault();
24134
25119
  }
24135
- paste(ev) {
25120
+ async paste(ev) {
24136
25121
  if (!this.gridEl.contains(document.activeElement)) {
24137
25122
  return;
24138
25123
  }
@@ -24152,6 +25137,9 @@ class Grid extends owl.Component {
24152
25137
  else {
24153
25138
  interactivePasteFromOS(this.env, target, content);
24154
25139
  }
25140
+ if (this.env.model.getters.isCutOperation()) {
25141
+ await this.env.clipboard.write({ [ClipboardMIMEType.PlainText]: "" });
25142
+ }
24155
25143
  }
24156
25144
  }
24157
25145
  displayWarningCopyPasteNotSupported() {
@@ -30091,9 +31079,9 @@ class CellPlugin extends CorePlugin {
30091
31079
  checkCellOutOfSheet(sheetId, col, row) {
30092
31080
  const sheet = this.getters.tryGetSheet(sheetId);
30093
31081
  if (!sheet)
30094
- return 27 /* CommandResult.InvalidSheetId */;
31082
+ return 28 /* CommandResult.InvalidSheetId */;
30095
31083
  const sheetZone = this.getters.getSheetZone(sheetId);
30096
- return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
31084
+ return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 19 /* CommandResult.TargetOutOfSheet */;
30097
31085
  }
30098
31086
  }
30099
31087
  class FormulaCellWithDependencies {
@@ -30316,13 +31304,13 @@ class ChartPlugin extends CorePlugin {
30316
31304
  }
30317
31305
  checkChartDuplicate(cmd) {
30318
31306
  return this.getters.getFigureSheetId(cmd.id)
30319
- ? 84 /* CommandResult.DuplicatedChartId */
31307
+ ? 85 /* CommandResult.DuplicatedChartId */
30320
31308
  : 0 /* CommandResult.Success */;
30321
31309
  }
30322
31310
  checkChartExists(cmd) {
30323
31311
  return this.getters.getFigureSheetId(cmd.id)
30324
31312
  ? 0 /* CommandResult.Success */
30325
- : 85 /* CommandResult.ChartDoesNotExist */;
31313
+ : 86 /* CommandResult.ChartDoesNotExist */;
30326
31314
  }
30327
31315
  }
30328
31316
 
@@ -30531,18 +31519,18 @@ class ConditionalFormatPlugin extends CorePlugin {
30531
31519
  }
30532
31520
  checkValidReordering(cfId, direction, sheetId) {
30533
31521
  if (!this.cfRules[sheetId])
30534
- return 27 /* CommandResult.InvalidSheetId */;
31522
+ return 28 /* CommandResult.InvalidSheetId */;
30535
31523
  const ruleIndex = this.cfRules[sheetId].findIndex((cf) => cf.id === cfId);
30536
31524
  if (ruleIndex === -1)
30537
- return 71 /* CommandResult.InvalidConditionalFormatId */;
31525
+ return 72 /* CommandResult.InvalidConditionalFormatId */;
30538
31526
  const cfIndex2 = direction === "up" ? ruleIndex - 1 : ruleIndex + 1;
30539
31527
  if (cfIndex2 < 0 || cfIndex2 >= this.cfRules[sheetId].length) {
30540
- return 71 /* CommandResult.InvalidConditionalFormatId */;
31528
+ return 72 /* CommandResult.InvalidConditionalFormatId */;
30541
31529
  }
30542
31530
  return 0 /* CommandResult.Success */;
30543
31531
  }
30544
31532
  checkEmptyRange(cmd) {
30545
- return cmd.ranges.length ? 0 /* CommandResult.Success */ : 24 /* CommandResult.EmptyRange */;
31533
+ return cmd.ranges.length ? 0 /* CommandResult.Success */ : 25 /* CommandResult.EmptyRange */;
30546
31534
  }
30547
31535
  checkCFRule(cmd) {
30548
31536
  const rule = cmd.cf.rule;
@@ -30578,10 +31566,10 @@ class ConditionalFormatPlugin extends CorePlugin {
30578
31566
  const errors = [];
30579
31567
  const isEmpty = (value) => value === undefined || value === "";
30580
31568
  if (expectedNumber >= 1 && isEmpty(rule.values[0])) {
30581
- errors.push(51 /* CommandResult.FirstArgMissing */);
31569
+ errors.push(52 /* CommandResult.FirstArgMissing */);
30582
31570
  }
30583
31571
  if (expectedNumber >= 2 && isEmpty(rule.values[1])) {
30584
- errors.push(52 /* CommandResult.SecondArgMissing */);
31572
+ errors.push(53 /* CommandResult.SecondArgMissing */);
30585
31573
  }
30586
31574
  return errors.length ? errors : 0 /* CommandResult.Success */;
30587
31575
  }
@@ -30593,15 +31581,15 @@ class ConditionalFormatPlugin extends CorePlugin {
30593
31581
  (threshold.value === "" || isNaN(threshold.value))) {
30594
31582
  switch (thresholdName) {
30595
31583
  case "min":
30596
- return 53 /* CommandResult.MinNaN */;
31584
+ return 54 /* CommandResult.MinNaN */;
30597
31585
  case "max":
30598
- return 55 /* CommandResult.MaxNaN */;
31586
+ return 56 /* CommandResult.MaxNaN */;
30599
31587
  case "mid":
30600
- return 54 /* CommandResult.MidNaN */;
31588
+ return 55 /* CommandResult.MidNaN */;
30601
31589
  case "upperInflectionPoint":
30602
- return 56 /* CommandResult.ValueUpperInflectionNaN */;
31590
+ return 57 /* CommandResult.ValueUpperInflectionNaN */;
30603
31591
  case "lowerInflectionPoint":
30604
- return 57 /* CommandResult.ValueLowerInflectionNaN */;
31592
+ return 58 /* CommandResult.ValueLowerInflectionNaN */;
30605
31593
  }
30606
31594
  }
30607
31595
  return 0 /* CommandResult.Success */;
@@ -30615,15 +31603,15 @@ class ConditionalFormatPlugin extends CorePlugin {
30615
31603
  catch (error) {
30616
31604
  switch (thresholdName) {
30617
31605
  case "min":
30618
- return 58 /* CommandResult.MinInvalidFormula */;
31606
+ return 59 /* CommandResult.MinInvalidFormula */;
30619
31607
  case "max":
30620
- return 60 /* CommandResult.MaxInvalidFormula */;
31608
+ return 61 /* CommandResult.MaxInvalidFormula */;
30621
31609
  case "mid":
30622
- return 59 /* CommandResult.MidInvalidFormula */;
31610
+ return 60 /* CommandResult.MidInvalidFormula */;
30623
31611
  case "upperInflectionPoint":
30624
- return 61 /* CommandResult.ValueUpperInvalidFormula */;
31612
+ return 62 /* CommandResult.ValueUpperInvalidFormula */;
30625
31613
  case "lowerInflectionPoint":
30626
- return 62 /* CommandResult.ValueLowerInvalidFormula */;
31614
+ return 63 /* CommandResult.ValueLowerInvalidFormula */;
30627
31615
  }
30628
31616
  }
30629
31617
  return 0 /* CommandResult.Success */;
@@ -30640,7 +31628,7 @@ class ConditionalFormatPlugin extends CorePlugin {
30640
31628
  if (["number", "percentage", "percentile"].includes(rule.lowerInflectionPoint.type) &&
30641
31629
  rule.lowerInflectionPoint.type === rule.upperInflectionPoint.type &&
30642
31630
  Number(minValue) > Number(maxValue)) {
30643
- return 48 /* CommandResult.LowerBiggerThanUpper */;
31631
+ return 49 /* CommandResult.LowerBiggerThanUpper */;
30644
31632
  }
30645
31633
  return 0 /* CommandResult.Success */;
30646
31634
  }
@@ -30650,7 +31638,7 @@ class ConditionalFormatPlugin extends CorePlugin {
30650
31638
  if (["number", "percentage", "percentile"].includes(rule.minimum.type) &&
30651
31639
  rule.minimum.type === rule.maximum.type &&
30652
31640
  stringToNumber(minValue) >= stringToNumber(maxValue)) {
30653
- return 47 /* CommandResult.MinBiggerThanMax */;
31641
+ return 48 /* CommandResult.MinBiggerThanMax */;
30654
31642
  }
30655
31643
  return 0 /* CommandResult.Success */;
30656
31644
  }
@@ -30661,7 +31649,7 @@ class ConditionalFormatPlugin extends CorePlugin {
30661
31649
  ["number", "percentage", "percentile"].includes(rule.midpoint.type) &&
30662
31650
  rule.midpoint.type === rule.maximum.type &&
30663
31651
  stringToNumber(midValue) >= stringToNumber(maxValue)) {
30664
- return 49 /* CommandResult.MidBiggerThanMax */;
31652
+ return 50 /* CommandResult.MidBiggerThanMax */;
30665
31653
  }
30666
31654
  return 0 /* CommandResult.Success */;
30667
31655
  }
@@ -30672,7 +31660,7 @@ class ConditionalFormatPlugin extends CorePlugin {
30672
31660
  ["number", "percentage", "percentile"].includes(rule.midpoint.type) &&
30673
31661
  rule.minimum.type === rule.midpoint.type &&
30674
31662
  stringToNumber(minValue) >= stringToNumber(midValue)) {
30675
- return 50 /* CommandResult.MinBiggerThanMid */;
31663
+ return 51 /* CommandResult.MinBiggerThanMid */;
30676
31664
  }
30677
31665
  return 0 /* CommandResult.Success */;
30678
31666
  }
@@ -30802,13 +31790,13 @@ class FigurePlugin extends CorePlugin {
30802
31790
  }
30803
31791
  checkFigureExists(sheetId, figureId) {
30804
31792
  if (this.figures[sheetId]?.[figureId] === undefined) {
30805
- return 70 /* CommandResult.FigureDoesNotExist */;
31793
+ return 71 /* CommandResult.FigureDoesNotExist */;
30806
31794
  }
30807
31795
  return 0 /* CommandResult.Success */;
30808
31796
  }
30809
31797
  checkFigureDuplicate(figureId) {
30810
31798
  if (Object.values(this.figures).find((sheet) => sheet?.[figureId])) {
30811
- return 82 /* CommandResult.DuplicatedFigureId */;
31799
+ return 83 /* CommandResult.DuplicatedFigureId */;
30812
31800
  }
30813
31801
  return 0 /* CommandResult.Success */;
30814
31802
  }
@@ -30920,12 +31908,12 @@ class FiltersPlugin extends CorePlugin {
30920
31908
  switch (cmd.type) {
30921
31909
  case "CREATE_FILTER_TABLE":
30922
31910
  if (!areZonesContinuous(...cmd.target)) {
30923
- return 81 /* CommandResult.NonContinuousTargets */;
31911
+ return 82 /* CommandResult.NonContinuousTargets */;
30924
31912
  }
30925
31913
  const zone = union(...cmd.target);
30926
31914
  const checkFilterOverlap = () => {
30927
31915
  if (this.getFilterTables(cmd.sheetId).some((filter) => overlap(filter.zone, zone))) {
30928
- return 78 /* CommandResult.FilterOverlap */;
31916
+ return 79 /* CommandResult.FilterOverlap */;
30929
31917
  }
30930
31918
  return 0 /* CommandResult.Success */;
30931
31919
  };
@@ -30933,7 +31921,7 @@ class FiltersPlugin extends CorePlugin {
30933
31921
  const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, zone);
30934
31922
  for (let merge of mergesInTarget) {
30935
31923
  if (overlap(zone, merge)) {
30936
- return 80 /* CommandResult.MergeInFilter */;
31924
+ return 81 /* CommandResult.MergeInFilter */;
30937
31925
  }
30938
31926
  }
30939
31927
  return 0 /* CommandResult.Success */;
@@ -30943,7 +31931,7 @@ class FiltersPlugin extends CorePlugin {
30943
31931
  for (let merge of cmd.target) {
30944
31932
  for (let filterTable of this.getFilterTables(cmd.sheetId)) {
30945
31933
  if (overlap(filterTable.zone, merge)) {
30946
- return 80 /* CommandResult.MergeInFilter */;
31934
+ return 81 /* CommandResult.MergeInFilter */;
30947
31935
  }
30948
31936
  }
30949
31937
  }
@@ -30962,7 +31950,14 @@ class FiltersPlugin extends CorePlugin {
30962
31950
  this.history.update("tables", filterTables);
30963
31951
  break;
30964
31952
  case "DUPLICATE_SHEET":
30965
- this.history.update("tables", cmd.sheetIdTo, deepCopy(this.tables[cmd.sheetId]));
31953
+ const tables = {};
31954
+ for (const filterTable of Object.values(this.tables[cmd.sheetId] || {})) {
31955
+ if (filterTable) {
31956
+ const newFilterTable = deepCopy(filterTable);
31957
+ tables[newFilterTable.id] = newFilterTable;
31958
+ }
31959
+ }
31960
+ this.history.update("tables", cmd.sheetIdTo, tables);
30966
31961
  break;
30967
31962
  case "ADD_COLUMNS_ROWS":
30968
31963
  this.onAddColumnsRows(cmd);
@@ -31414,7 +32409,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
31414
32409
  switch (cmd.type) {
31415
32410
  case "HIDE_COLUMNS_ROWS": {
31416
32411
  if (!this.getters.tryGetSheet(cmd.sheetId)) {
31417
- return 27 /* CommandResult.InvalidSheetId */;
32412
+ return 28 /* CommandResult.InvalidSheetId */;
31418
32413
  }
31419
32414
  const hiddenGroup = cmd.dimension === "COL"
31420
32415
  ? this.getHiddenColsGroups(cmd.sheetId)
@@ -31424,10 +32419,10 @@ class HeaderVisibilityPlugin extends CorePlugin {
31424
32419
  : this.getters.getNumberRows(cmd.sheetId);
31425
32420
  const hiddenElements = new Set((hiddenGroup || []).flat().concat(cmd.elements));
31426
32421
  if (hiddenElements.size >= elements) {
31427
- return 66 /* CommandResult.TooManyHiddenElements */;
32422
+ return 67 /* CommandResult.TooManyHiddenElements */;
31428
32423
  }
31429
32424
  else if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
31430
- return 86 /* CommandResult.InvalidHeaderIndex */;
32425
+ return 87 /* CommandResult.InvalidHeaderIndex */;
31431
32426
  }
31432
32427
  else {
31433
32428
  return 0 /* CommandResult.Success */;
@@ -31435,7 +32430,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
31435
32430
  }
31436
32431
  case "REMOVE_COLUMNS_ROWS":
31437
32432
  if (!this.getters.tryGetSheet(cmd.sheetId)) {
31438
- return 27 /* CommandResult.InvalidSheetId */;
32433
+ return 28 /* CommandResult.InvalidSheetId */;
31439
32434
  }
31440
32435
  if (!this.canRemoveHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
31441
32436
  return 8 /* CommandResult.NotEnoughElements */;
@@ -31603,7 +32598,7 @@ class ImagePlugin extends CorePlugin {
31603
32598
  switch (cmd.type) {
31604
32599
  case "CREATE_IMAGE":
31605
32600
  if (this.getters.getFigure(cmd.sheetId, cmd.figureId)) {
31606
- return 28 /* CommandResult.InvalidFigureId */;
32601
+ return 29 /* CommandResult.InvalidFigureId */;
31607
32602
  }
31608
32603
  return 0 /* CommandResult.Success */;
31609
32604
  default:
@@ -31991,7 +32986,7 @@ class MergePlugin extends CorePlugin {
31991
32986
  for (const zone of target) {
31992
32987
  for (const zone2 of target) {
31993
32988
  if (zone !== zone2 && overlap(zone, zone2)) {
31994
- return 65 /* CommandResult.MergeOverlap */;
32989
+ return 66 /* CommandResult.MergeOverlap */;
31995
32990
  }
31996
32991
  }
31997
32992
  }
@@ -32005,7 +33000,7 @@ class MergePlugin extends CorePlugin {
32005
33000
  for (const zone of target) {
32006
33001
  if ((zone.left < xSplit && zone.right >= xSplit) ||
32007
33002
  (zone.top < ySplit && zone.bottom >= ySplit)) {
32008
- return 75 /* CommandResult.FrozenPaneOverlap */;
33003
+ return 76 /* CommandResult.FrozenPaneOverlap */;
32009
33004
  }
32010
33005
  }
32011
33006
  return 0 /* CommandResult.Success */;
@@ -32199,7 +33194,7 @@ class RangeAdapter {
32199
33194
  // ---------------------------------------------------------------------------
32200
33195
  allowDispatch(cmd) {
32201
33196
  if (cmd.type === "MOVE_RANGES") {
32202
- return cmd.target.length === 1 ? 0 /* CommandResult.Success */ : 26 /* CommandResult.InvalidZones */;
33197
+ return cmd.target.length === 1 ? 0 /* CommandResult.Success */ : 27 /* CommandResult.InvalidZones */;
32203
33198
  }
32204
33199
  return 0 /* CommandResult.Success */;
32205
33200
  }
@@ -32624,7 +33619,7 @@ class SheetPlugin extends CorePlugin {
32624
33619
  return 0 /* CommandResult.Success */;
32625
33620
  }
32626
33621
  catch (e) {
32627
- return 14 /* CommandResult.WrongSheetMove */;
33622
+ return 15 /* CommandResult.WrongSheetMove */;
32628
33623
  }
32629
33624
  case "RENAME_SHEET":
32630
33625
  return this.isRenameAllowed(cmd);
@@ -32637,10 +33632,10 @@ class SheetPlugin extends CorePlugin {
32637
33632
  ? this.getNumberCols(cmd.sheetId)
32638
33633
  : this.getNumberRows(cmd.sheetId);
32639
33634
  if (cmd.base < 0 || cmd.base > elements) {
32640
- return 86 /* CommandResult.InvalidHeaderIndex */;
33635
+ return 87 /* CommandResult.InvalidHeaderIndex */;
32641
33636
  }
32642
33637
  else if (cmd.quantity <= 0) {
32643
- return 87 /* CommandResult.InvalidQuantity */;
33638
+ return 88 /* CommandResult.InvalidQuantity */;
32644
33639
  }
32645
33640
  return 0 /* CommandResult.Success */;
32646
33641
  case "REMOVE_COLUMNS_ROWS": {
@@ -32648,7 +33643,7 @@ class SheetPlugin extends CorePlugin {
32648
33643
  ? this.getNumberCols(cmd.sheetId)
32649
33644
  : this.getNumberRows(cmd.sheetId);
32650
33645
  if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
32651
- return 86 /* CommandResult.InvalidHeaderIndex */;
33646
+ return 87 /* CommandResult.InvalidHeaderIndex */;
32652
33647
  }
32653
33648
  else {
32654
33649
  return 0 /* CommandResult.Success */;
@@ -32975,12 +33970,12 @@ class SheetPlugin extends CorePlugin {
32975
33970
  */
32976
33971
  checkZonesExistInSheet(sheetId, zones) {
32977
33972
  if (!zones.every(isZoneValid))
32978
- return 25 /* CommandResult.InvalidRange */;
33973
+ return 26 /* CommandResult.InvalidRange */;
32979
33974
  if (zones.length) {
32980
33975
  const sheetZone = this.getSheetZone(sheetId);
32981
33976
  return zones.every((zone) => isZoneInside(zone, sheetZone))
32982
33977
  ? 0 /* CommandResult.Success */
32983
- : 18 /* CommandResult.TargetOutOfSheet */;
33978
+ : 19 /* CommandResult.TargetOutOfSheet */;
32984
33979
  }
32985
33980
  return 0 /* CommandResult.Success */;
32986
33981
  }
@@ -33087,38 +34082,42 @@ class SheetPlugin extends CorePlugin {
33087
34082
  throw new Error(_lt("There is not enough visible sheets"));
33088
34083
  }
33089
34084
  checkSheetName(cmd) {
34085
+ const originalSheetName = this.getters.tryGetSheetName(cmd.sheetId);
34086
+ if (originalSheetName !== undefined && cmd.name === originalSheetName) {
34087
+ return 11 /* CommandResult.UnchangedSheetName */;
34088
+ }
33090
34089
  const { orderedSheetIds, sheets } = this;
33091
34090
  const name = cmd.name && cmd.name.trim().toLowerCase();
33092
- if (orderedSheetIds.find((id) => sheets[id]?.name.toLowerCase() === name)) {
33093
- return 11 /* CommandResult.DuplicatedSheetName */;
34091
+ if (orderedSheetIds.find((id) => sheets[id]?.name.toLowerCase() === name && id !== cmd.sheetId)) {
34092
+ return 12 /* CommandResult.DuplicatedSheetName */;
33094
34093
  }
33095
34094
  if (FORBIDDEN_IN_EXCEL_REGEX.test(name)) {
33096
- return 13 /* CommandResult.ForbiddenCharactersInSheetName */;
34095
+ return 14 /* CommandResult.ForbiddenCharactersInSheetName */;
33097
34096
  }
33098
34097
  return 0 /* CommandResult.Success */;
33099
34098
  }
33100
34099
  checkSheetPosition(cmd) {
33101
34100
  const { orderedSheetIds } = this;
33102
34101
  if (cmd.position > orderedSheetIds.length || cmd.position < 0) {
33103
- return 15 /* CommandResult.WrongSheetPosition */;
34102
+ return 16 /* CommandResult.WrongSheetPosition */;
33104
34103
  }
33105
34104
  return 0 /* CommandResult.Success */;
33106
34105
  }
33107
34106
  checkRowFreezeQuantity(cmd) {
33108
34107
  return cmd.quantity >= 1 && cmd.quantity < this.getNumberRows(cmd.sheetId)
33109
34108
  ? 0 /* CommandResult.Success */
33110
- : 74 /* CommandResult.InvalidFreezeQuantity */;
34109
+ : 75 /* CommandResult.InvalidFreezeQuantity */;
33111
34110
  }
33112
34111
  checkColFreezeQuantity(cmd) {
33113
34112
  return cmd.quantity >= 1 && cmd.quantity < this.getNumberCols(cmd.sheetId)
33114
34113
  ? 0 /* CommandResult.Success */
33115
- : 74 /* CommandResult.InvalidFreezeQuantity */;
34114
+ : 75 /* CommandResult.InvalidFreezeQuantity */;
33116
34115
  }
33117
34116
  checkRowFreezeOverlapMerge(cmd) {
33118
34117
  const merges = this.getters.getMerges(cmd.sheetId);
33119
34118
  for (let merge of merges) {
33120
34119
  if (merge.top < cmd.quantity && cmd.quantity <= merge.bottom) {
33121
- return 65 /* CommandResult.MergeOverlap */;
34120
+ return 66 /* CommandResult.MergeOverlap */;
33122
34121
  }
33123
34122
  }
33124
34123
  return 0 /* CommandResult.Success */;
@@ -33127,7 +34126,7 @@ class SheetPlugin extends CorePlugin {
33127
34126
  const merges = this.getters.getMerges(cmd.sheetId);
33128
34127
  for (let merge of merges) {
33129
34128
  if (merge.left < cmd.quantity && cmd.quantity <= merge.right) {
33130
- return 65 /* CommandResult.MergeOverlap */;
34129
+ return 66 /* CommandResult.MergeOverlap */;
33131
34130
  }
33132
34131
  }
33133
34132
  return 0 /* CommandResult.Success */;
@@ -33143,8 +34142,8 @@ class SheetPlugin extends CorePlugin {
33143
34142
  const oldName = sheet.name;
33144
34143
  this.history.update("sheets", sheet.id, "name", name.trim());
33145
34144
  const sheetIdsMapName = Object.assign({}, this.sheetIdsMapName);
33146
- sheetIdsMapName[name] = sheet.id;
33147
34145
  delete sheetIdsMapName[oldName];
34146
+ sheetIdsMapName[name] = sheet.id;
33148
34147
  this.history.update("sheetIdsMapName", sheetIdsMapName);
33149
34148
  }
33150
34149
  hideSheet(sheetId) {
@@ -33438,10 +34437,10 @@ class SheetPlugin extends CorePlugin {
33438
34437
  */
33439
34438
  checkSheetExists(cmd) {
33440
34439
  if (cmd.type !== "CREATE_SHEET" && "sheetId" in cmd && this.sheets[cmd.sheetId] === undefined) {
33441
- return 27 /* CommandResult.InvalidSheetId */;
34440
+ return 28 /* CommandResult.InvalidSheetId */;
33442
34441
  }
33443
34442
  else if (cmd.type === "CREATE_SHEET" && this.sheets[cmd.sheetId] !== undefined) {
33444
- return 12 /* CommandResult.DuplicatedSheetId */;
34443
+ return 13 /* CommandResult.DuplicatedSheetId */;
33445
34444
  }
33446
34445
  return 0 /* CommandResult.Success */;
33447
34446
  }
@@ -35002,7 +36001,7 @@ class AutofillPlugin extends UIPlugin {
35002
36001
  if (this.lastCellSelected.col !== undefined && this.lastCellSelected.row !== undefined) {
35003
36002
  return 0 /* CommandResult.Success */;
35004
36003
  }
35005
- return 45 /* CommandResult.InvalidAutofillSelection */;
36004
+ return 46 /* CommandResult.InvalidAutofillSelection */;
35006
36005
  case "AUTOFILL_AUTO":
35007
36006
  const zone = this.getters.getSelectedZone();
35008
36007
  return zone.top === zone.bottom
@@ -35619,7 +36618,7 @@ class CellPopoverPlugin extends UIPlugin {
35619
36618
  cellPopoverRegistry.get(cmd.popoverType);
35620
36619
  }
35621
36620
  catch (error) {
35622
- return 72 /* CommandResult.InvalidCellPopover */;
36621
+ return 73 /* CommandResult.InvalidCellPopover */;
35623
36622
  }
35624
36623
  return 0 /* CommandResult.Success */;
35625
36624
  default:
@@ -37749,12 +38748,12 @@ class SelectionInputPlugin extends UIPlugin {
37749
38748
  case "ADD_RANGE":
37750
38749
  case "ADD_EMPTY_RANGE":
37751
38750
  if (this.inputHasSingleRange && this.ranges.length === 1) {
37752
- return 30 /* CommandResult.MaximumRangesReached */;
38751
+ return 31 /* CommandResult.MaximumRangesReached */;
37753
38752
  }
37754
38753
  break;
37755
38754
  case "CHANGE_RANGE":
37756
38755
  if (this.inputHasSingleRange && cmd.value.split(",").length > 1) {
37757
- return 30 /* CommandResult.MaximumRangesReached */;
38756
+ return 31 /* CommandResult.MaximumRangesReached */;
37758
38757
  }
37759
38758
  break;
37760
38759
  }
@@ -37983,7 +38982,7 @@ class SelectionInputsManagerPlugin extends UIPlugin {
37983
38982
  case "FOCUS_RANGE":
37984
38983
  const index = this.currentInput?.getIndex(cmd.rangeId);
37985
38984
  if (this.focusedInputId === cmd.id && this.currentInput?.focusedRangeIndex === index) {
37986
- return 29 /* CommandResult.InputAlreadyFocused */;
38985
+ return 30 /* CommandResult.InputAlreadyFocused */;
37987
38986
  }
37988
38987
  break;
37989
38988
  }
@@ -38115,7 +39114,7 @@ class SortPlugin extends UIPlugin {
38115
39114
  /*Test the presence of single cells*/
38116
39115
  const singleCells = positions(zone).some(({ col, row }) => !this.getters.isInMerge({ sheetId, col, row }));
38117
39116
  if (singleCells) {
38118
- return 63 /* CommandResult.InvalidSortZone */;
39117
+ return 64 /* CommandResult.InvalidSortZone */;
38119
39118
  }
38120
39119
  return 0 /* CommandResult.Success */;
38121
39120
  }
@@ -38134,7 +39133,7 @@ class SortPlugin extends UIPlugin {
38134
39133
  ];
38135
39134
  return widthCurrent === widthFirst && heightCurrent === heightFirst;
38136
39135
  })) {
38137
- return 63 /* CommandResult.InvalidSortZone */;
39136
+ return 64 /* CommandResult.InvalidSortZone */;
38138
39137
  }
38139
39138
  return 0 /* CommandResult.Success */;
38140
39139
  }
@@ -38627,7 +39626,7 @@ class SheetUIPlugin extends UIPlugin {
38627
39626
  */
38628
39627
  checkSheetExists(cmd) {
38629
39628
  if ("sheetId" in cmd && this.getters.tryGetSheet(cmd.sheetId) === undefined) {
38630
- return 27 /* CommandResult.InvalidSheetId */;
39629
+ return 28 /* CommandResult.InvalidSheetId */;
38631
39630
  }
38632
39631
  return 0 /* CommandResult.Success */;
38633
39632
  }
@@ -38639,7 +39638,7 @@ class SheetUIPlugin extends UIPlugin {
38639
39638
  const sheetId = "sheetId" in cmd ? cmd.sheetId : this.getters.tryGetActiveSheetId();
38640
39639
  const zones = this.getters.getCommandZones(cmd);
38641
39640
  if (!sheetId && zones.length > 0) {
38642
- return 92 /* CommandResult.NoActiveSheet */;
39641
+ return 93 /* CommandResult.NoActiveSheet */;
38643
39642
  }
38644
39643
  if (sheetId && zones.length > 0) {
38645
39644
  return this.getters.checkZonesExistInSheet(sheetId, zones);
@@ -39121,13 +40120,13 @@ class SplitToColumnsPlugin extends UIPlugin {
39121
40120
  }
39122
40121
  checkSingleColSelected() {
39123
40122
  if (!this.getters.isSingleColSelected()) {
39124
- return 88 /* CommandResult.MoreThanOneColumnSelected */;
40123
+ return 89 /* CommandResult.MoreThanOneColumnSelected */;
39125
40124
  }
39126
40125
  return 0 /* CommandResult.Success */;
39127
40126
  }
39128
40127
  checkNonEmptySelector(cmd) {
39129
40128
  if (cmd.separator === "") {
39130
- return 89 /* CommandResult.EmptySplitSeparator */;
40129
+ return 90 /* CommandResult.EmptySplitSeparator */;
39131
40130
  }
39132
40131
  return 0 /* CommandResult.Success */;
39133
40132
  }
@@ -39138,7 +40137,7 @@ class SplitToColumnsPlugin extends UIPlugin {
39138
40137
  const selection = this.getters.getSelectedZones()[0];
39139
40138
  const splitted = this.getSplittedCols(selection, cmd.separator);
39140
40139
  if (this.willSplittedColsOverwriteContent(selection, splitted)) {
39141
- return 90 /* CommandResult.SplitWillOverwriteContent */;
40140
+ return 91 /* CommandResult.SplitWillOverwriteContent */;
39142
40141
  }
39143
40142
  return 0 /* CommandResult.Success */;
39144
40143
  }
@@ -39149,7 +40148,7 @@ class SplitToColumnsPlugin extends UIPlugin {
39149
40148
  return 0 /* CommandResult.Success */;
39150
40149
  }
39151
40150
  }
39152
- return 91 /* CommandResult.NoSplitSeparatorInSelection */;
40151
+ return 92 /* CommandResult.NoSplitSeparatorInSelection */;
39153
40152
  }
39154
40153
  }
39155
40154
 
@@ -39264,7 +40263,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
39264
40263
  }
39265
40264
  isCutAllowed(target) {
39266
40265
  if (target.length !== 1) {
39267
- return 19 /* CommandResult.WrongCutSelection */;
40266
+ return 20 /* CommandResult.WrongCutSelection */;
39268
40267
  }
39269
40268
  return 0 /* CommandResult.Success */;
39270
40269
  }
@@ -39272,13 +40271,13 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
39272
40271
  const sheetId = this.getters.getActiveSheetId();
39273
40272
  if (this.operation === "CUT" && clipboardOption?.pasteOption !== undefined) {
39274
40273
  // cannot paste only format or only value if the previous operation is a CUT
39275
- return 21 /* CommandResult.WrongPasteOption */;
40274
+ return 22 /* CommandResult.WrongPasteOption */;
39276
40275
  }
39277
40276
  if (target.length > 1) {
39278
40277
  // cannot paste if we have a clipped zone larger than a cell and multiple
39279
40278
  // zones selected
39280
40279
  if (this.cells.length > 1 || this.cells[0].length > 1) {
39281
- return 20 /* CommandResult.WrongPasteSelection */;
40280
+ return 21 /* CommandResult.WrongPasteSelection */;
39282
40281
  }
39283
40282
  }
39284
40283
  const clipboardHeight = this.cells.length;
@@ -39296,7 +40295,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
39296
40295
  for (const zone of this.getPasteZones(target)) {
39297
40296
  if ((zone.left < xSplit && zone.right >= xSplit) ||
39298
40297
  (zone.top < ySplit && zone.bottom >= ySplit)) {
39299
- return 75 /* CommandResult.FrozenPaneOverlap */;
40298
+ return 76 /* CommandResult.FrozenPaneOverlap */;
39300
40299
  }
39301
40300
  }
39302
40301
  return 0 /* CommandResult.Success */;
@@ -39364,6 +40363,13 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
39364
40363
  });
39365
40364
  }
39366
40365
  this.pasteCopiedTables(target);
40366
+ this.cells.forEach((row) => {
40367
+ row.forEach((c) => {
40368
+ if (c.cell) {
40369
+ c.cell = undefined;
40370
+ }
40371
+ });
40372
+ });
39367
40373
  }
39368
40374
  /**
39369
40375
  * The clipped zone is copied as many times as it fits in the target.
@@ -39596,7 +40602,9 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
39596
40602
  return (this.cells
39597
40603
  .map((cells) => {
39598
40604
  return cells
39599
- .map((c) => c.cell ? this.getters.getCellText(c.position, this.getters.shouldShowFormulas()) : "")
40605
+ .map((c) => this.getters.shouldShowFormulas() && c.cell?.isFormula
40606
+ ? c.cell?.content || ""
40607
+ : c.evaluatedCell?.formattedValue || "")
39600
40608
  .join("\t");
39601
40609
  })
39602
40610
  .join("\n") || "\t");
@@ -39727,10 +40735,10 @@ class ClipboardFigureState {
39727
40735
  }
39728
40736
  isPasteAllowed(target, option) {
39729
40737
  if (target.length === 0) {
39730
- return 73 /* CommandResult.EmptyTarget */;
40738
+ return 74 /* CommandResult.EmptyTarget */;
39731
40739
  }
39732
40740
  if (option?.pasteOption !== undefined) {
39733
- return 22 /* CommandResult.WrongFigurePasteOption */;
40741
+ return 23 /* CommandResult.WrongFigurePasteOption */;
39734
40742
  }
39735
40743
  return 0 /* CommandResult.Success */;
39736
40744
  }
@@ -39832,7 +40840,10 @@ class ClipboardOsState extends ClipboardCellsAbstractState {
39832
40840
  }
39833
40841
  return 0 /* CommandResult.Success */;
39834
40842
  }
39835
- paste(target) {
40843
+ paste(target, clipboardOption) {
40844
+ if (clipboardOption?.pasteOption === "onlyFormat") {
40845
+ return;
40846
+ }
39836
40847
  const values = this.values;
39837
40848
  const pasteZone = this.getPasteZone(target);
39838
40849
  const { left: activeCol, top: activeRow } = pasteZone;
@@ -39893,6 +40904,7 @@ class ClipboardPlugin extends UIPlugin {
39893
40904
  state;
39894
40905
  lastPasteState;
39895
40906
  _isPaintingFormat = false;
40907
+ originSheetId;
39896
40908
  // ---------------------------------------------------------------------------
39897
40909
  // Command Handling
39898
40910
  // ---------------------------------------------------------------------------
@@ -39904,13 +40916,13 @@ class ClipboardPlugin extends UIPlugin {
39904
40916
  return state.isCutAllowed(zones);
39905
40917
  case "PASTE":
39906
40918
  if (!this.state) {
39907
- return 23 /* CommandResult.EmptyClipboard */;
40919
+ return 24 /* CommandResult.EmptyClipboard */;
39908
40920
  }
39909
40921
  const pasteOption = cmd.pasteOption || (this._isPaintingFormat ? "onlyFormat" : undefined);
39910
40922
  return this.state.isPasteAllowed(cmd.target, { pasteOption });
39911
40923
  case "PASTE_FROM_OS_CLIPBOARD": {
39912
40924
  const state = new ClipboardOsState(cmd.text, this.getters, this.dispatch, this.selection);
39913
- return state.isPasteAllowed(cmd.target);
40925
+ return state.isPasteAllowed(cmd.target, { pasteOption: cmd.pasteOption });
39914
40926
  }
39915
40927
  case "INSERT_CELL": {
39916
40928
  const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
@@ -39932,6 +40944,7 @@ class ClipboardPlugin extends UIPlugin {
39932
40944
  const zones = ("cutTarget" in cmd && cmd.cutTarget) || this.getters.getSelectedZones();
39933
40945
  this.state = this.getClipboardState(zones, cmd.type);
39934
40946
  this.status = "visible";
40947
+ this.originSheetId = this.getters.getActiveSheetId();
39935
40948
  break;
39936
40949
  case "PASTE":
39937
40950
  if (!this.state) {
@@ -39940,9 +40953,6 @@ class ClipboardPlugin extends UIPlugin {
39940
40953
  const pasteOption = cmd.pasteOption || (this._isPaintingFormat ? "onlyFormat" : undefined);
39941
40954
  this._isPaintingFormat = false;
39942
40955
  this.state.paste(cmd.target, { pasteOption, shouldPasteCF: true, selectTarget: true });
39943
- if (this.state.operation === "CUT") {
39944
- this.state = undefined;
39945
- }
39946
40956
  this.lastPasteState = this.state;
39947
40957
  this.status = "invisible";
39948
40958
  break;
@@ -39997,7 +41007,7 @@ class ClipboardPlugin extends UIPlugin {
39997
41007
  }
39998
41008
  case "PASTE_FROM_OS_CLIPBOARD":
39999
41009
  this.state = new ClipboardOsState(cmd.text, this.getters, this.dispatch, this.selection);
40000
- this.state.paste(cmd.target);
41010
+ this.state.paste(cmd.target, { pasteOption: cmd.pasteOption });
40001
41011
  this.lastPasteState = this.state;
40002
41012
  this.status = "invisible";
40003
41013
  break;
@@ -40016,6 +41026,15 @@ class ClipboardPlugin extends UIPlugin {
40016
41026
  this.status = "visible";
40017
41027
  break;
40018
41028
  }
41029
+ case "DELETE_SHEET":
41030
+ if (this.state?.operation !== "CUT") {
41031
+ return;
41032
+ }
41033
+ if (this.originSheetId === cmd.sheetId) {
41034
+ this.state = undefined;
41035
+ this.status = "invisible";
41036
+ }
41037
+ break;
40019
41038
  default:
40020
41039
  if (isCoreCommand(cmd)) {
40021
41040
  this.status = "invisible";
@@ -40474,7 +41493,7 @@ class EditionPlugin extends UIPlugin {
40474
41493
  validateSelection(length, start, end) {
40475
41494
  return start >= 0 && start <= length && end >= 0 && end <= length
40476
41495
  ? 0 /* CommandResult.Success */
40477
- : 46 /* CommandResult.WrongComposerSelection */;
41496
+ : 47 /* CommandResult.WrongComposerSelection */;
40478
41497
  }
40479
41498
  onColumnsRemoved(cmd) {
40480
41499
  if (cmd.elements.includes(this.col) && this.mode !== "inactive") {
@@ -40850,7 +41869,7 @@ class FilterEvaluationPlugin extends UIPlugin {
40850
41869
  switch (cmd.type) {
40851
41870
  case "UPDATE_FILTER":
40852
41871
  if (!this.getters.getFilterId(cmd)) {
40853
- return 79 /* CommandResult.FilterNotFound */;
41872
+ return 80 /* CommandResult.FilterNotFound */;
40854
41873
  }
40855
41874
  break;
40856
41875
  }
@@ -40991,6 +42010,7 @@ class FilterEvaluationPlugin extends UIPlugin {
40991
42010
  }
40992
42011
  exportForExcel(data) {
40993
42012
  for (const sheetData of data.sheets) {
42013
+ const sheetId = sheetData.id;
40994
42014
  for (const tableData of sheetData.filterTables) {
40995
42015
  const tableZone = toZone(tableData.range);
40996
42016
  const filters = [];
@@ -41006,20 +42026,20 @@ class FilterEvaluationPlugin extends UIPlugin {
41006
42026
  if (!filter)
41007
42027
  continue;
41008
42028
  const valuesInFilterZone = filter.filteredZone
41009
- ? positions(filter.filteredZone)
41010
- .map(({ col, row }) => this.getters.getEvaluatedCell({ sheetId: sheetData.id, col, row }))
41011
- .filter((cell) => cell.type !== CellValueType.empty)
41012
- .map((cell) => cell.formattedValue)
42029
+ ? positions(filter.filteredZone).map((position) => this.getters.getEvaluatedCell({ sheetId, ...position }).formattedValue)
41013
42030
  : [];
41014
- // In xlsx, filtered values = values that are displayed, not values that are hidden
41015
- const xlsxFilteredValues = valuesInFilterZone.filter((val) => !filteredValues.includes(val));
41016
- filters.push({ colId: i, filteredValues: [...new Set(xlsxFilteredValues)] });
41017
- // In xlsx, filter header should ALWAYS be a string and should be unique
41018
- const headerPosition = {
41019
- col: filter.col,
41020
- row: filter.zoneWithHeaders.top,
41021
- sheetId: sheetData.id,
41022
- };
42031
+ if (filteredValues.length) {
42032
+ const xlsxDisplayedValues = valuesInFilterZone
42033
+ .filter((val) => val)
42034
+ .filter((val) => !filteredValues.includes(val));
42035
+ filters.push({
42036
+ colId: i,
42037
+ displayedValues: [...new Set(xlsxDisplayedValues)],
42038
+ displayBlanks: !filteredValues.includes("") && valuesInFilterZone.some((val) => !val),
42039
+ });
42040
+ }
42041
+ // In xlsx, filter header should ALWAYS be a string and should be unique in the table
42042
+ const headerPosition = { col: filter.col, row: filter.zoneWithHeaders.top, sheetId };
41023
42043
  const headerString = this.getters.getEvaluatedCell(headerPosition).formattedValue;
41024
42044
  const headerName = this.getUniqueColNameForExcel(i, headerString, headerNames);
41025
42045
  headerNames.push(headerName);
@@ -41138,7 +42158,7 @@ class GridSelectionPlugin extends UIPlugin {
41138
42158
  break;
41139
42159
  }
41140
42160
  catch (error) {
41141
- return 27 /* CommandResult.InvalidSheetId */;
42161
+ return 28 /* CommandResult.InvalidSheetId */;
41142
42162
  }
41143
42163
  case "MOVE_COLUMNS_ROWS":
41144
42164
  return this.isMoveElementAllowed(cmd);
@@ -42441,7 +43461,7 @@ class SheetViewPlugin extends UIPlugin {
42441
43461
  }
42442
43462
  checkPositiveDimension(cmd) {
42443
43463
  if (cmd.width < 0 || cmd.height < 0) {
42444
- return 68 /* CommandResult.InvalidViewportSize */;
43464
+ return 69 /* CommandResult.InvalidViewportSize */;
42445
43465
  }
42446
43466
  return 0 /* CommandResult.Success */;
42447
43467
  }
@@ -42451,7 +43471,7 @@ class SheetViewPlugin extends UIPlugin {
42451
43471
  cmd.gridOffsetY === this.gridOffsetY &&
42452
43472
  cmd.width === width &&
42453
43473
  cmd.height === height) {
42454
- return 76 /* CommandResult.ValuesNotChanged */;
43474
+ return 77 /* CommandResult.ValuesNotChanged */;
42455
43475
  }
42456
43476
  return 0 /* CommandResult.Success */;
42457
43477
  }
@@ -42459,7 +43479,7 @@ class SheetViewPlugin extends UIPlugin {
42459
43479
  const pane = this.getMainInternalViewport(this.getters.getActiveSheetId());
42460
43480
  if ((!pane.canScrollHorizontally && offsetX > 0) ||
42461
43481
  (!pane.canScrollVertically && offsetY > 0)) {
42462
- return 69 /* CommandResult.InvalidScrollingDirection */;
43482
+ return 70 /* CommandResult.InvalidScrollingDirection */;
42463
43483
  }
42464
43484
  return 0 /* CommandResult.Success */;
42465
43485
  }
@@ -42886,17 +43906,14 @@ Ripple.props = {
42886
43906
  };
42887
43907
 
42888
43908
  function interactiveRenameSheet(env, sheetId, name, errorCallback) {
42889
- const originalSheetName = env.model.getters.getSheetName(sheetId);
42890
- if (name === null || name === originalSheetName)
42891
- return;
42892
43909
  const result = env.model.dispatch("RENAME_SHEET", { sheetId, name });
42893
43910
  if (result.reasons.includes(10 /* CommandResult.MissingSheetName */)) {
42894
43911
  env.raiseError(_lt("The sheet name cannot be empty."), errorCallback);
42895
43912
  }
42896
- else if (result.reasons.includes(11 /* CommandResult.DuplicatedSheetName */)) {
43913
+ else if (result.reasons.includes(12 /* CommandResult.DuplicatedSheetName */)) {
42897
43914
  env.raiseError(_lt("A sheet with the name %s already exists. Please select another name.", name), errorCallback);
42898
43915
  }
42899
- else if (result.reasons.includes(13 /* CommandResult.ForbiddenCharactersInSheetName */)) {
43916
+ else if (result.reasons.includes(14 /* CommandResult.ForbiddenCharactersInSheetName */)) {
42900
43917
  env.raiseError(_lt("Some used characters are not allowed in a sheet name (Forbidden characters are %s).", FORBIDDEN_SHEET_CHARS.join(" ")), errorCallback);
42901
43918
  }
42902
43919
  }
@@ -44225,11 +45242,9 @@ TopBarComposer.props = {
44225
45242
  onComposerContentFocused: Function,
44226
45243
  };
44227
45244
 
44228
- // -----------------------------------------------------------------------------
44229
- // TopBar
44230
- // -----------------------------------------------------------------------------
44231
45245
  css /* scss */ `
44232
45246
  .o-font-size-editor {
45247
+ height: calc(100% - 4px);
44233
45248
  input.o-font-size {
44234
45249
  outline-color: ${SELECTION_BORDER_COLOR};
44235
45250
  height: 20px;
@@ -44242,13 +45257,13 @@ css /* scss */ `
44242
45257
  input::-webkit-inner-spin-button {
44243
45258
  -webkit-appearance: none;
44244
45259
  }
44245
-
44246
- .o-text-options > div {
44247
- line-height: 26px;
44248
- padding: 3px 12px;
44249
- &:hover {
44250
- background-color: rgba(0, 0, 0, 0.08);
44251
- }
45260
+ }
45261
+ .o-text-options > div {
45262
+ cursor: pointer;
45263
+ line-height: 26px;
45264
+ padding: 3px 12px;
45265
+ &:hover {
45266
+ background-color: rgba(0, 0, 0, 0.08);
44252
45267
  }
44253
45268
  }
44254
45269
  `;
@@ -44313,6 +45328,7 @@ class FontSizeEditor extends owl.Component {
44313
45328
  FontSizeEditor.props = {
44314
45329
  onToggle: Function,
44315
45330
  dropdownStyle: String,
45331
+ class: String,
44316
45332
  };
44317
45333
 
44318
45334
  // -----------------------------------------------------------------------------
@@ -45885,7 +46901,7 @@ class SelectionStreamProcessorImpl {
45885
46901
  */
45886
46902
  moveAnchorCell(direction, step = 1) {
45887
46903
  if (step !== "end" && step <= 0) {
45888
- return new DispatchResult(83 /* CommandResult.InvalidSelectionStep */);
46904
+ return new DispatchResult(84 /* CommandResult.InvalidSelectionStep */);
45889
46905
  }
45890
46906
  const { col, row } = this.getNextAvailablePosition(direction, step);
45891
46907
  return this.selectCell(col, row);
@@ -45931,7 +46947,7 @@ class SelectionStreamProcessorImpl {
45931
46947
  */
45932
46948
  resizeAnchorZone(direction, step = 1) {
45933
46949
  if (step !== "end" && step <= 0) {
45934
- return new DispatchResult(83 /* CommandResult.InvalidSelectionStep */);
46950
+ return new DispatchResult(84 /* CommandResult.InvalidSelectionStep */);
45935
46951
  }
45936
46952
  const sheetId = this.getters.getActiveSheetId();
45937
46953
  const anchor = this.anchor;
@@ -46125,20 +47141,20 @@ class SelectionStreamProcessorImpl {
46125
47141
  checkAnchorZone(anchor) {
46126
47142
  const { cell, zone } = anchor;
46127
47143
  if (!isInside(cell.col, cell.row, zone)) {
46128
- return 16 /* CommandResult.InvalidAnchorZone */;
47144
+ return 17 /* CommandResult.InvalidAnchorZone */;
46129
47145
  }
46130
47146
  const { left, right, top, bottom } = zone;
46131
47147
  const sheetId = this.getters.getActiveSheetId();
46132
47148
  const refCol = this.getters.findVisibleHeader(sheetId, "COL", left, right);
46133
47149
  const refRow = this.getters.findVisibleHeader(sheetId, "ROW", top, bottom);
46134
47150
  if (refRow === undefined || refCol === undefined) {
46135
- return 17 /* CommandResult.SelectionOutOfBound */;
47151
+ return 18 /* CommandResult.SelectionOutOfBound */;
46136
47152
  }
46137
47153
  return 0 /* CommandResult.Success */;
46138
47154
  }
46139
47155
  checkAnchorZoneOrThrow(anchor) {
46140
47156
  const result = this.checkAnchorZone(anchor);
46141
- if (result === 16 /* CommandResult.InvalidAnchorZone */) {
47157
+ if (result === 17 /* CommandResult.InvalidAnchorZone */) {
46142
47158
  throw new Error(_t("The provided anchor is invalid. The cell must be part of the zone."));
46143
47159
  }
46144
47160
  }
@@ -47481,15 +48497,10 @@ function addAutoFilter(table) {
47481
48497
  `;
47482
48498
  }
47483
48499
  function addFilterColumns(table) {
47484
- const tableZone = toZone(table.range);
47485
48500
  const columns = [];
47486
- for (const i of range(0, zoneToDimension(tableZone).numberOfCols)) {
47487
- const filter = table.filters[i];
47488
- if (!filter || !filter.filteredValues.length) {
47489
- continue;
47490
- }
48501
+ for (const filter of table.filters) {
47491
48502
  const colXml = escapeXml /*xml*/ `
47492
- <filterColumn ${formatAttributes([["colId", i]])}>
48503
+ <filterColumn ${formatAttributes([["colId", filter.colId]])}>
47493
48504
  ${addFilter(filter)}
47494
48505
  </filterColumn>
47495
48506
  `;
@@ -47498,9 +48509,10 @@ function addFilterColumns(table) {
47498
48509
  return columns;
47499
48510
  }
47500
48511
  function addFilter(filter) {
47501
- const filterValues = filter.filteredValues.map((val) => escapeXml /*xml*/ `<filter ${formatAttributes([["val", val]])}/>`);
48512
+ const filterValues = filter.displayedValues.map((val) => escapeXml /*xml*/ `<filter ${formatAttributes([["val", val]])}/>`);
48513
+ const filterAttributes = filter.displayBlanks ? [["blank", 1]] : [];
47502
48514
  return escapeXml /*xml*/ `
47503
- <filters>
48515
+ <filters ${formatAttributes(filterAttributes)}>
47504
48516
  ${joinXmlNodes(filterValues)}
47505
48517
  </filters>
47506
48518
  `;
@@ -47619,8 +48631,13 @@ function addHyperlinks(construct, data, sheetIndex) {
47619
48631
  const sheetId = parseSheetUrl(url);
47620
48632
  const sheet = data.sheets.find((sheet) => sheet.id === sheetId);
47621
48633
  const location = sheet ? `${sheet.name}!A1` : INCORRECT_RANGE_STRING;
48634
+ const hyperlinkAttributes = [
48635
+ ["display", label],
48636
+ ["location", location],
48637
+ ["ref", xc],
48638
+ ];
47622
48639
  linkNodes.push(escapeXml /*xml*/ `
47623
- <hyperlink display="${label}" location="${location}" ref="${xc}"/>
48640
+ <hyperlink ${formatAttributes(hyperlinkAttributes)}/>
47624
48641
  `);
47625
48642
  }
47626
48643
  else {
@@ -47629,8 +48646,12 @@ function addHyperlinks(construct, data, sheetIndex) {
47629
48646
  type: XLSX_RELATION_TYPE.hyperlink,
47630
48647
  targetMode: "External",
47631
48648
  });
48649
+ const hyperlinkAttributes = [
48650
+ ["r:id", linkRelId],
48651
+ ["ref", xc],
48652
+ ];
47632
48653
  linkNodes.push(escapeXml /*xml*/ `
47633
- <hyperlink r:id="${linkRelId}" ref="${xc}"/>
48654
+ <hyperlink ${formatAttributes(hyperlinkAttributes)}/>
47634
48655
  `);
47635
48656
  }
47636
48657
  }
@@ -48254,10 +49275,10 @@ class Model extends EventBus {
48254
49275
  const command = createCommand(type, payload);
48255
49276
  let status = this.status;
48256
49277
  if (this.getters.isReadonly() && !canExecuteInReadonly(command)) {
48257
- return new DispatchResult(67 /* CommandResult.Readonly */);
49278
+ return new DispatchResult(68 /* CommandResult.Readonly */);
48258
49279
  }
48259
49280
  if (!this.session.canApplyOptimisticUpdate()) {
48260
- return new DispatchResult(64 /* CommandResult.WaitingSessionConfirmation */);
49281
+ return new DispatchResult(65 /* CommandResult.WaitingSessionConfirmation */);
48261
49282
  }
48262
49283
  switch (status) {
48263
49284
  case 0 /* Status.Ready */:
@@ -48538,6 +49559,6 @@ exports.setTranslationMethod = setTranslationMethod;
48538
49559
  exports.tokenize = tokenize;
48539
49560
 
48540
49561
 
48541
- __info__.version = '16.4.0-alpha.4';
48542
- __info__.date = '2023-06-12T13:55:29.711Z';
48543
- __info__.hash = '251a52e';
49562
+ __info__.version = '16.4.0-alpha.5';
49563
+ __info__.date = '2023-06-26T14:35:24.001Z';
49564
+ __info__.hash = '3b0b6f1';