@odoo/o-spreadsheet 16.4.5 → 16.4.7

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.
@@ -610,13 +610,17 @@ function getAddHeaderStartIndex(position, base) {
610
610
  return position === "after" ? base + 1 : base;
611
611
  }
612
612
  /**
613
- * Compare two objects.
613
+ * Compares two objects.
614
614
  */
615
615
  function deepEquals(o1, o2) {
616
616
  if (o1 === o2)
617
617
  return true;
618
618
  if ((o1 && !o2) || (o2 && !o1))
619
619
  return false;
620
+ if (typeof o1 !== typeof o2)
621
+ return false;
622
+ if (typeof o1 !== "object")
623
+ return o1 === o2;
620
624
  // Objects can have different keys if the values are undefined
621
625
  const keys = new Set();
622
626
  Object.keys(o1).forEach((key) => keys.add(key));
@@ -5261,6 +5265,7 @@ css /* scss */ `
5261
5265
  padding: 10px;
5262
5266
  width: ${ERROR_TOOLTIP_WIDTH}px;
5263
5267
  box-sizing: border-box !important;
5268
+ overflow-wrap: break-word;
5264
5269
  }
5265
5270
  `;
5266
5271
  class ErrorToolTip extends Component {
@@ -15116,13 +15121,42 @@ function isValidLocale(locale) {
15116
15121
  }
15117
15122
  return true;
15118
15123
  }
15119
- /** Change a content string to its canonical form (en_US locale) */
15124
+ /**
15125
+ * Change a content string from the given locale to its canonical form (en_US locale). Don't convert date string.
15126
+ *
15127
+ * @example
15128
+ * canonicalizeNumberContent("=SUM(1,5; 02/12/2012)", FR_LOCALE) // "=SUM(1.5, 02/12/2012)"
15129
+ * canonicalizeNumberContent("125,9", FR_LOCALE) // "125.9"
15130
+ * canonicalizeNumberContent("02/12/2012", FR_LOCALE) // "02/12/2012"
15131
+ */
15132
+ function canonicalizeNumberContent(content, locale) {
15133
+ return content.startsWith("=")
15134
+ ? canonicalizeFormula$1(content, locale)
15135
+ : canonicalizeNumberLiteral(content, locale);
15136
+ }
15137
+ /**
15138
+ * Change a content string from the given locale to its canonical form (en_US locale). Also convert date string.
15139
+ * This is destructive and won't preserve the original format.
15140
+ *
15141
+ * @example
15142
+ * canonicalizeContent("=SUM(1,5; 5)", FR_LOCALE) // "=SUM(1.5, 5)"
15143
+ * canonicalizeContent("125,9", FR_LOCALE) // "125.9"
15144
+ * canonicalizeContent("02/12/2012", FR_LOCALE) // "12/02/2012"
15145
+ * canonicalizeContent("02-12-2012", FR_LOCALE) // "12/02/2012"
15146
+ */
15120
15147
  function canonicalizeContent(content, locale) {
15121
15148
  return content.startsWith("=")
15122
15149
  ? canonicalizeFormula$1(content, locale)
15123
- : toCanonicalNumberString(content, locale);
15150
+ : canonicalizeLiteral(content, locale);
15124
15151
  }
15125
- /** Change the content of a cell to its canonical form (en_US locale) */
15152
+ /**
15153
+ * Change a content string from its canonical form (en_US locale) to the given locale. Also convert date string.
15154
+ *
15155
+ * @example
15156
+ * localizeContent("=SUM(1.5, 5)", FR_LOCALE) // "=SUM(1,5; 5)"
15157
+ * localizeContent("125.9", FR_LOCALE) // "125,9"
15158
+ * localizeContent("12/02/2012", FR_LOCALE) // "02/12/2012"
15159
+ */
15126
15160
  function localizeContent(content, locale) {
15127
15161
  return content.startsWith("=")
15128
15162
  ? localizeFormula(content, locale)
@@ -15157,24 +15191,75 @@ function _localizeFormula$1(formula, fromLocale, toLocale) {
15157
15191
  return localizedFormula;
15158
15192
  }
15159
15193
  /**
15160
- * Replace localized number with localized decimal separator by a number with "." as decimal separator
15194
+ * Change a literal string from the given locale to its canonical form (en_US locale). Don't convert date string.
15195
+ *
15196
+ * @example
15197
+ * canonicalizeNumberLiteral("125,9", FR_LOCALE) // "125.9"
15198
+ * canonicalizeNumberLiteral("02/12/2012", FR_LOCALE) // "02/12/2012"
15161
15199
  */
15162
- function toCanonicalNumberString(content, locale) {
15200
+ function canonicalizeNumberLiteral(content, locale) {
15163
15201
  if (locale.decimalSeparator === "." || !isNumber(content, locale)) {
15164
15202
  return content;
15165
15203
  }
15166
15204
  return content.replace(locale.decimalSeparator, ".");
15167
15205
  }
15168
- function localizeLiteral(content, locale) {
15169
- if (locale.decimalSeparator === "." || !isNumber(content, DEFAULT_LOCALE)) {
15170
- return content;
15206
+ /**
15207
+ * Change a content string from the given locale to its canonical form (en_US locale). Also convert date string.
15208
+ * This is destructive and won't preserve the original format.
15209
+ *
15210
+ * @example
15211
+ * canonicalizeLiteral("125,9", FR_LOCALE) // "125.9"
15212
+ * canonicalizeLiteral("02/12/2012", FR_LOCALE) // "12/02/2012"
15213
+ * canonicalizeLiteral("02-12-2012", FR_LOCALE) // "12/02/2012"
15214
+ */
15215
+ function canonicalizeLiteral(content, locale) {
15216
+ if (isDateTime(content, locale)) {
15217
+ const dateNumber = toNumber(content, locale);
15218
+ let format = DEFAULT_LOCALE.dateFormat;
15219
+ if (!Number.isInteger(dateNumber)) {
15220
+ format += " " + DEFAULT_LOCALE.timeFormat;
15221
+ }
15222
+ return formatValue(dateNumber, { locale: DEFAULT_LOCALE, format });
15223
+ }
15224
+ return canonicalizeNumberLiteral(content, locale);
15225
+ }
15226
+ /**
15227
+ * Change a literal string from its canonical form (en_US locale) to the given locale. Don't convert date string.
15228
+ * This is destructive and won't preserve the original format.
15229
+ *
15230
+ * @example
15231
+ * localizeNumberLiteral("125.9", FR_LOCALE) // "125,9"
15232
+ * localizeNumberLiteral("12/02/2012", FR_LOCALE) // "12/02/2012"
15233
+ * localizeNumberLiteral("12-02-2012", FR_LOCALE) // "12/02/2012"
15234
+ */
15235
+ function localizeNumberLiteral(literal, locale) {
15236
+ if (locale.decimalSeparator === "." || !isNumber(literal, DEFAULT_LOCALE)) {
15237
+ return literal;
15171
15238
  }
15172
15239
  const decimalNumberRegex = getDecimalNumberRegex(DEFAULT_LOCALE);
15173
- const localized = content.replace(decimalNumberRegex, (match) => {
15240
+ const localized = literal.replace(decimalNumberRegex, (match) => {
15174
15241
  return match.replace(".", locale.decimalSeparator);
15175
15242
  });
15176
15243
  return localized;
15177
15244
  }
15245
+ /**
15246
+ * Change a literal string from its canonical form (en_US locale) to the given locale. Also convert date string.
15247
+ *
15248
+ * @example
15249
+ * localizeLiteral("125.9", FR_LOCALE) // "125,9"
15250
+ * localizeLiteral("12/02/2012", FR_LOCALE) // "02/12/2012"
15251
+ */
15252
+ function localizeLiteral(literal, locale) {
15253
+ if (isDateTime(literal, DEFAULT_LOCALE)) {
15254
+ const dateNumber = toNumber(literal, DEFAULT_LOCALE);
15255
+ let format = locale.dateFormat;
15256
+ if (!Number.isInteger(dateNumber)) {
15257
+ format += " " + locale.timeFormat;
15258
+ }
15259
+ return formatValue(dateNumber, { locale, format });
15260
+ }
15261
+ return localizeNumberLiteral(literal, locale);
15262
+ }
15178
15263
  function canonicalizeCFRule(cf, locale) {
15179
15264
  return changeCFRuleLocale(cf, (content) => canonicalizeContent(content, locale));
15180
15265
  }
@@ -15531,7 +15616,9 @@ class LinkEditor extends Component {
15531
15616
  save() {
15532
15617
  const { col, row } = this.props.cellPosition;
15533
15618
  const locale = this.env.model.getters.getLocale();
15534
- const label = this.link.label ? canonicalizeContent(this.link.label, locale) : this.link.url;
15619
+ const label = this.link.label
15620
+ ? canonicalizeNumberContent(this.link.label, locale)
15621
+ : this.link.url;
15535
15622
  this.env.model.dispatch("UPDATE_CELL", {
15536
15623
  col: col,
15537
15624
  row: row,
@@ -16874,6 +16961,7 @@ class LineChart extends AbstractChart {
16874
16961
  aggregated;
16875
16962
  type = "line";
16876
16963
  dataSetsHaveTitle;
16964
+ cumulative;
16877
16965
  constructor(definition, sheetId, getters) {
16878
16966
  super(definition, sheetId, getters);
16879
16967
  this.dataSets = createDataSets(this.getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
@@ -16885,6 +16973,7 @@ class LineChart extends AbstractChart {
16885
16973
  this.stacked = definition.stacked;
16886
16974
  this.aggregated = definition.aggregated;
16887
16975
  this.dataSetsHaveTitle = definition.dataSetsHaveTitle;
16976
+ this.cumulative = definition.cumulative;
16888
16977
  }
16889
16978
  static validateChartDefinition(validator, definition) {
16890
16979
  return validator.checkValidations(definition, checkDataset, checkLabelRange);
@@ -16905,6 +16994,7 @@ class LineChart extends AbstractChart {
16905
16994
  labelRange: context.auxiliaryRange || undefined,
16906
16995
  stacked: false,
16907
16996
  aggregated: false,
16997
+ cumulative: false,
16908
16998
  };
16909
16999
  }
16910
17000
  getDefinition() {
@@ -16925,6 +17015,7 @@ class LineChart extends AbstractChart {
16925
17015
  labelsAsText: this.labelsAsText,
16926
17016
  stacked: this.stacked,
16927
17017
  aggregated: this.aggregated,
17018
+ cumulative: this.cumulative,
16928
17019
  };
16929
17020
  }
16930
17021
  getContextCreation() {
@@ -17135,6 +17226,16 @@ function createLineChartRuntime(chart, getters) {
17135
17226
  if (chart.stacked) {
17136
17227
  backgroundRGBA.a = LINE_FILL_TRANSPARENCY;
17137
17228
  }
17229
+ if (chart.cumulative) {
17230
+ let accumulator = 0;
17231
+ data = data.map((value) => {
17232
+ if (!isNaN(value)) {
17233
+ accumulator += parseFloat(value);
17234
+ return accumulator;
17235
+ }
17236
+ return value;
17237
+ });
17238
+ }
17138
17239
  const backgroundColor = rgbaToHex(backgroundRGBA);
17139
17240
  const dataset = {
17140
17241
  label,
@@ -18009,6 +18110,7 @@ function getSmartChartDefinition(zone, getters) {
18009
18110
  labelsAsText: false,
18010
18111
  stacked: false,
18011
18112
  aggregated: false,
18113
+ cumulative: false,
18012
18114
  labelRange: labelRangeXc,
18013
18115
  type: "line",
18014
18116
  dataSetsHaveTitle,
@@ -18172,6 +18274,13 @@ const REMOVE_ROWS_ACTION = (env) => {
18172
18274
  elements: rows,
18173
18275
  });
18174
18276
  };
18277
+ const CAN_REMOVE_COLUMNS_ROWS = (dimension, env) => {
18278
+ const sheetId = env.model.getters.getActiveSheetId();
18279
+ const selectedElements = env.model.getters.getElementsFromSelection(dimension);
18280
+ const includesAllVisibleHeaders = env.model.getters.checkElementsIncludeAllVisibleHeaders(sheetId, dimension, selectedElements);
18281
+ const includesAllNonFrozenHeaders = env.model.getters.checkElementsIncludeAllNonFrozenHeaders(sheetId, dimension, selectedElements);
18282
+ return !includesAllVisibleHeaders && !includesAllNonFrozenHeaders;
18283
+ };
18175
18284
  const REMOVE_COLUMNS_NAME = (env) => {
18176
18285
  if (env.model.getters.getSelectedZones().length > 1) {
18177
18286
  return _lt("Delete columns");
@@ -18196,7 +18305,7 @@ const REMOVE_COLUMNS_NAME = (env) => {
18196
18305
  const NOT_ALL_VISIBLE_ROWS_SELECTED = (env) => {
18197
18306
  const sheetId = env.model.getters.getActiveSheetId();
18198
18307
  const selectedRows = env.model.getters.getElementsFromSelection("ROW");
18199
- return env.model.getters.canRemoveHeaders(sheetId, "ROW", selectedRows);
18308
+ return !env.model.getters.checkElementsIncludeAllVisibleHeaders(sheetId, "ROW", selectedRows);
18200
18309
  };
18201
18310
  const REMOVE_COLUMNS_ACTION = (env) => {
18202
18311
  let columns = [...env.model.getters.getActiveCols()];
@@ -18215,7 +18324,7 @@ const REMOVE_COLUMNS_ACTION = (env) => {
18215
18324
  const NOT_ALL_VISIBLE_COLS_SELECTED = (env) => {
18216
18325
  const sheetId = env.model.getters.getActiveSheetId();
18217
18326
  const selectedCols = env.model.getters.getElementsFromSelection("COL");
18218
- return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
18327
+ return !env.model.getters.checkElementsIncludeAllVisibleHeaders(sheetId, "COL", selectedCols);
18219
18328
  };
18220
18329
  const INSERT_ROWS_BEFORE_ACTION = (env) => {
18221
18330
  const activeRows = env.model.getters.getActiveRows();
@@ -18487,7 +18596,7 @@ const deleteValues = {
18487
18596
  const deleteRows = {
18488
18597
  name: REMOVE_ROWS_NAME,
18489
18598
  execute: REMOVE_ROWS_ACTION,
18490
- isVisible: NOT_ALL_VISIBLE_ROWS_SELECTED,
18599
+ isVisible: (env) => CAN_REMOVE_COLUMNS_ROWS("ROW", env),
18491
18600
  };
18492
18601
  const deleteRow = {
18493
18602
  ...deleteRows,
@@ -18500,7 +18609,7 @@ const clearRows = {
18500
18609
  const deleteCols = {
18501
18610
  name: REMOVE_COLUMNS_NAME,
18502
18611
  execute: REMOVE_COLUMNS_ACTION,
18503
- isVisible: NOT_ALL_VISIBLE_COLS_SELECTED,
18612
+ isVisible: (env) => CAN_REMOVE_COLUMNS_ROWS("COL", env),
18504
18613
  };
18505
18614
  const deleteCol = {
18506
18615
  ...deleteCols,
@@ -21475,6 +21584,11 @@ class LineConfigPanel extends LineBarPieConfigPanel {
21475
21584
  aggregated: ev.target.checked,
21476
21585
  });
21477
21586
  }
21587
+ onUpdateCumulative(ev) {
21588
+ this.props.updateChart(this.props.figureId, {
21589
+ cumulative: ev.target.checked,
21590
+ });
21591
+ }
21478
21592
  }
21479
21593
 
21480
21594
  class LineChartDesignPanel extends LineBarPieDesignPanel {
@@ -25274,9 +25388,11 @@ function useCellHovered(env, gridRef, callback) {
25274
25388
  }
25275
25389
  }
25276
25390
  function updateMousePosition(e) {
25277
- x = e.offsetX;
25278
- y = e.offsetY;
25279
- lastMoved = Date.now();
25391
+ if (gridRef.el === e.target) {
25392
+ x = e.offsetX;
25393
+ y = e.offsetY;
25394
+ lastMoved = Date.now();
25395
+ }
25280
25396
  }
25281
25397
  function recompute() {
25282
25398
  const { col, row } = getPosition();
@@ -28448,6 +28564,7 @@ function convertChartData(chartData) {
28448
28564
  legendPosition: chartData.legendPosition,
28449
28565
  stacked: chartData.stacked || false,
28450
28566
  aggregated: false,
28567
+ cumulative: chartData.cumulative || false,
28451
28568
  labelsAsText: false,
28452
28569
  };
28453
28570
  }
@@ -33108,7 +33225,7 @@ class HeaderSizePlugin extends CorePlugin {
33108
33225
 
33109
33226
  class HeaderVisibilityPlugin extends CorePlugin {
33110
33227
  static getters = [
33111
- "canRemoveHeaders",
33228
+ "checkElementsIncludeAllVisibleHeaders",
33112
33229
  "getHiddenColsGroups",
33113
33230
  "getHiddenRowsGroups",
33114
33231
  "isRowHiddenByUser",
@@ -33142,7 +33259,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
33142
33259
  if (!this.getters.tryGetSheet(cmd.sheetId)) {
33143
33260
  return 28 /* CommandResult.InvalidSheetId */;
33144
33261
  }
33145
- if (!this.canRemoveHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
33262
+ if (this.checkElementsIncludeAllVisibleHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
33146
33263
  return 8 /* CommandResult.NotEnoughElements */;
33147
33264
  }
33148
33265
  return 0 /* CommandResult.Success */;
@@ -33192,9 +33309,9 @@ class HeaderVisibilityPlugin extends CorePlugin {
33192
33309
  }
33193
33310
  return;
33194
33311
  }
33195
- canRemoveHeaders(sheetId, dimension, elements) {
33312
+ checkElementsIncludeAllVisibleHeaders(sheetId, dimension, elements) {
33196
33313
  const visibleHeaders = this.getAllVisibleHeaders(sheetId, dimension);
33197
- return !includesAll(elements, visibleHeaders);
33314
+ return includesAll(elements, visibleHeaders);
33198
33315
  }
33199
33316
  isRowHiddenByUser(sheetId, index) {
33200
33317
  return this.hiddenHeaders[sheetId].ROW[index];
@@ -34299,6 +34416,7 @@ class SheetPlugin extends CorePlugin {
34299
34416
  "checkZonesExistInSheet",
34300
34417
  "getCommandZones",
34301
34418
  "getUnboundedZone",
34419
+ "checkElementsIncludeAllNonFrozenHeaders",
34302
34420
  ];
34303
34421
  sheetIdsMapName = {};
34304
34422
  orderedSheetIds = [];
@@ -34355,6 +34473,9 @@ class SheetPlugin extends CorePlugin {
34355
34473
  if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
34356
34474
  return 87 /* CommandResult.InvalidHeaderIndex */;
34357
34475
  }
34476
+ else if (this.checkElementsIncludeAllNonFrozenHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
34477
+ return 8 /* CommandResult.NotEnoughElements */;
34478
+ }
34358
34479
  else {
34359
34480
  return 0 /* CommandResult.Success */;
34360
34481
  }
@@ -34647,6 +34768,20 @@ class SheetPlugin extends CorePlugin {
34647
34768
  }
34648
34769
  this.history.update("sheets", sheetId, "panes", panes);
34649
34770
  }
34771
+ /**
34772
+ * Checks if all non-frozen header indices are present in the provided elements of selected rows/columns.
34773
+ * This validation ensures that all rows or columns cannot be deleted when frozen panes exist.
34774
+ */
34775
+ checkElementsIncludeAllNonFrozenHeaders(sheetId, dimension, elements) {
34776
+ const paneDivisions = this.getters.getPaneDivisions(sheetId);
34777
+ const startIndex = dimension === "ROW" ? paneDivisions.ySplit : paneDivisions.xSplit;
34778
+ const endIndex = this.getters.getNumberHeaders(sheetId, dimension);
34779
+ if (!startIndex) {
34780
+ return false;
34781
+ }
34782
+ const indicesToCheck = range(startIndex, endIndex);
34783
+ return includesAll(elements, indicesToCheck);
34784
+ }
34650
34785
  // ---------------------------------------------------------------------------
34651
34786
  // Row/Col manipulation
34652
34787
  // ---------------------------------------------------------------------------
@@ -36630,8 +36765,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
36630
36765
  if (cell.type === CellValueType.error) {
36631
36766
  return false;
36632
36767
  }
36633
- const locale = this.getters.getLocale();
36634
- const values = rule.values.map((val) => parseLiteral(val, locale));
36768
+ const values = rule.values.map((val) => parseLiteral(val, DEFAULT_LOCALE));
36635
36769
  switch (rule.operator) {
36636
36770
  case "IsEmpty":
36637
36771
  return cell.value.toString().trim() === "";
@@ -38715,7 +38849,7 @@ class FindAndReplacePlugin extends UIPlugin {
38715
38849
  const replaceRegex = new RegExp(this.currentSearchRegex.source, this.currentSearchRegex.flags + "g");
38716
38850
  const toReplace = this.getSearchableString({ sheetId, col, row });
38717
38851
  const content = toReplace.replace(replaceRegex, replaceWith);
38718
- const canonicalContent = canonicalizeContent(content, this.getters.getLocale());
38852
+ const canonicalContent = canonicalizeNumberContent(content, this.getters.getLocale());
38719
38853
  this.dispatch("UPDATE_CELL", { sheetId, col, row, content: canonicalContent });
38720
38854
  }
38721
38855
  /**
@@ -40889,7 +41023,7 @@ class SplitToColumnsPlugin extends UIPlugin {
40889
41023
  sheetId,
40890
41024
  col: col + index,
40891
41025
  row,
40892
- content: canonicalizeContent(content, this.getters.getLocale()),
41026
+ content: canonicalizeNumberContent(content, this.getters.getLocale()),
40893
41027
  format: "",
40894
41028
  style: mainCell?.style || null,
40895
41029
  });
@@ -41075,6 +41209,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
41075
41209
  cells;
41076
41210
  copiedTables;
41077
41211
  zones;
41212
+ uuidGenerator = new UuidGenerator();
41078
41213
  constructor(zones, operation, getters, dispatch, selection) {
41079
41214
  super(operation, getters, dispatch, selection);
41080
41215
  if (!zones.length) {
@@ -41536,8 +41671,9 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
41536
41671
  this.adaptCFRules(origin.sheetId, cf, [xc], toRemoveRange);
41537
41672
  }
41538
41673
  else {
41539
- this.adaptCFRules(target.sheetId, cf, [xc], []);
41540
41674
  this.adaptCFRules(origin.sheetId, cf, [], toRemoveRange);
41675
+ const cfToCopyTo = this.getCFToCopyTo(target.sheetId, cf);
41676
+ this.adaptCFRules(target.sheetId, cfToCopyTo, [xc], []);
41541
41677
  }
41542
41678
  }
41543
41679
  }
@@ -41561,6 +41697,12 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
41561
41697
  sheetId,
41562
41698
  });
41563
41699
  }
41700
+ getCFToCopyTo(targetSheetId, originCF) {
41701
+ const cfInTarget = this.getters
41702
+ .getConditionalFormats(targetSheetId)
41703
+ .find((cf) => cf.stopIfTrue === originCF.stopIfTrue && deepEquals(cf.rule, originCF.rule));
41704
+ return cfInTarget ? cfInTarget : { ...originCF, id: this.uuidGenerator.uuidv4(), ranges: [] };
41705
+ }
41564
41706
  }
41565
41707
 
41566
41708
  /** State of the clipboard when copying/cutting figures */
@@ -41692,7 +41834,7 @@ class ClipboardFigureImage {
41692
41834
  function canonicalizeNumberValue(content, locale) {
41693
41835
  return content.startsWith("=")
41694
41836
  ? canonicalizeFormula(content, locale)
41695
- : toCanonicalNumberString(content, locale);
41837
+ : canonicalizeNumberLiteral(content, locale);
41696
41838
  }
41697
41839
  /** Change a formula to its canonical form (en_US locale) */
41698
41840
  function canonicalizeFormula(formula, locale) {
@@ -41809,7 +41951,7 @@ class ClipboardPlugin extends UIPlugin {
41809
41951
  allowDispatch(cmd) {
41810
41952
  switch (cmd.type) {
41811
41953
  case "CUT":
41812
- const zones = cmd.cutTarget || this.getters.getSelectedZones();
41954
+ const zones = this.getters.getSelectedZones();
41813
41955
  const state = this.getClipboardState(zones, cmd.type);
41814
41956
  return state.isCutAllowed(zones);
41815
41957
  case "PASTE":
@@ -41844,7 +41986,7 @@ class ClipboardPlugin extends UIPlugin {
41844
41986
  switch (cmd.type) {
41845
41987
  case "COPY":
41846
41988
  case "CUT":
41847
- const zones = ("cutTarget" in cmd && cmd.cutTarget) || this.getters.getSelectedZones();
41989
+ const zones = this.getters.getSelectedZones();
41848
41990
  this.state = this.getClipboardState(zones, cmd.type);
41849
41991
  this.status = "visible";
41850
41992
  this.originSheetId = this.getters.getActiveSheetId();
@@ -42494,7 +42636,7 @@ class EditionPlugin extends UIPlugin {
42494
42636
  if (content) {
42495
42637
  const sheetId = this.getters.getActiveSheetId();
42496
42638
  const cell = this.getters.getEvaluatedCell({ sheetId, col: this.col, row: this.row });
42497
- content = canonicalizeContent(content, this.getters.getLocale());
42639
+ content = canonicalizeNumberContent(content, this.getters.getLocale());
42498
42640
  if (content.startsWith("=")) {
42499
42641
  const left = this.currentTokens.filter((t) => t.type === "LEFT_PAREN").length;
42500
42642
  const right = this.currentTokens.filter((t) => t.type === "RIGHT_PAREN").length;
@@ -43515,26 +43657,24 @@ class GridSelectionPlugin extends UIPlugin {
43515
43657
  const isBasedBefore = cmd.base < start;
43516
43658
  const deltaCol = isBasedBefore && isCol ? thickness : 0;
43517
43659
  const deltaRow = isBasedBefore && !isCol ? thickness : 0;
43518
- this.dispatch("CUT", {
43519
- cutTarget: [
43520
- {
43521
- left: isCol ? start + deltaCol : 0,
43522
- right: isCol ? end + deltaCol : this.getters.getNumberCols(cmd.sheetId) - 1,
43523
- top: !isCol ? start + deltaRow : 0,
43524
- bottom: !isCol ? end + deltaRow : this.getters.getNumberRows(cmd.sheetId) - 1,
43525
- },
43526
- ],
43527
- });
43528
- this.dispatch("PASTE", {
43529
- target: [
43530
- {
43531
- left: isCol ? cmd.base : 0,
43532
- right: isCol ? cmd.base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
43533
- top: !isCol ? cmd.base : 0,
43534
- bottom: !isCol ? cmd.base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
43535
- },
43536
- ],
43537
- });
43660
+ const target = [
43661
+ {
43662
+ left: isCol ? start + deltaCol : 0,
43663
+ right: isCol ? end + deltaCol : this.getters.getNumberCols(cmd.sheetId) - 1,
43664
+ top: !isCol ? start + deltaRow : 0,
43665
+ bottom: !isCol ? end + deltaRow : this.getters.getNumberRows(cmd.sheetId) - 1,
43666
+ },
43667
+ ];
43668
+ const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
43669
+ const pasteTarget = [
43670
+ {
43671
+ left: isCol ? cmd.base : 0,
43672
+ right: isCol ? cmd.base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
43673
+ top: !isCol ? cmd.base : 0,
43674
+ bottom: !isCol ? cmd.base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
43675
+ },
43676
+ ];
43677
+ state.paste(pasteTarget, { selectTarget: true });
43538
43678
  const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
43539
43679
  let currentIndex = cmd.base;
43540
43680
  for (const element of toRemove) {
@@ -43933,6 +44073,9 @@ class InternalViewport {
43933
44073
  const sheetId = this.sheetId;
43934
44074
  this.left = this.searchHeaderIndex("COL", this.offsetScrollbarX, this.boundaries.left);
43935
44075
  this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.viewportWidth, this.left));
44076
+ if (this.left === -1) {
44077
+ this.left = this.boundaries.left;
44078
+ }
43936
44079
  if (this.right === -1) {
43937
44080
  this.right = this.getters.getNumberCols(sheetId) - 1;
43938
44081
  }
@@ -43946,6 +44089,9 @@ class InternalViewport {
43946
44089
  const sheetId = this.sheetId;
43947
44090
  this.top = this.searchHeaderIndex("ROW", this.offsetScrollbarY, this.boundaries.top);
43948
44091
  this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.viewportHeight, this.top));
44092
+ if (this.top === -1) {
44093
+ this.top = this.boundaries.top;
44094
+ }
43949
44095
  if (this.bottom === -1) {
43950
44096
  this.bottom = this.getters.getNumberRows(sheetId) - 1;
43951
44097
  }
@@ -50514,6 +50660,6 @@ const constants = {
50514
50660
  export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
50515
50661
 
50516
50662
 
50517
- __info__.version = '16.4.5';
50518
- __info__.date = '2023-08-29T13:55:58.527Z';
50519
- __info__.hash = '105c130';
50663
+ __info__.version = '16.4.7';
50664
+ __info__.date = '2023-09-21T15:58:11.039Z';
50665
+ __info__.hash = 'eccdcce';