@odoo/o-spreadsheet 16.1.19 → 16.1.23

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.
@@ -321,7 +321,16 @@ const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY;
321
321
  const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
322
322
  const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
323
323
  const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
324
+ const CACHE = {};
324
325
  function parseDateTime(str) {
326
+ if (str in CACHE) {
327
+ return CACHE[str];
328
+ }
329
+ const date = _parseDateTime(str);
330
+ CACHE[str] = date;
331
+ return date;
332
+ }
333
+ function _parseDateTime(str) {
325
334
  str = str.trim();
326
335
  let time;
327
336
  const timeMatch = str.match(timeRegexp);
@@ -1006,13 +1015,17 @@ function getAddHeaderStartIndex(position, base) {
1006
1015
  return position === "after" ? base + 1 : base;
1007
1016
  }
1008
1017
  /**
1009
- * Compare two objects.
1018
+ * Compares two objects.
1010
1019
  */
1011
1020
  function deepEquals(o1, o2) {
1012
1021
  if (o1 === o2)
1013
1022
  return true;
1014
1023
  if ((o1 && !o2) || (o2 && !o1))
1015
1024
  return false;
1025
+ if (typeof o1 !== typeof o2)
1026
+ return false;
1027
+ if (typeof o1 !== "object")
1028
+ return o1 === o2;
1016
1029
  // Objects can have different keys if the values are undefined
1017
1030
  const keys = new Set();
1018
1031
  Object.keys(o1).forEach((key) => keys.add(key));
@@ -2121,8 +2134,9 @@ class RangeImpl {
2121
2134
  }
2122
2135
  get zone() {
2123
2136
  const { left, top, bottom, right } = this._zone;
2124
- if (right !== undefined && bottom !== undefined)
2125
- return { left, top, right, bottom };
2137
+ if (right !== undefined && bottom !== undefined) {
2138
+ return this._zone;
2139
+ }
2126
2140
  else if (bottom === undefined && right !== undefined) {
2127
2141
  return { right, top, left, bottom: this.getSheetSize(this.sheetId).height - 1 };
2128
2142
  }
@@ -3648,6 +3662,9 @@ exports.CommandResult = void 0;
3648
3662
  CommandResult[CommandResult["InvalidQuantity"] = 87] = "InvalidQuantity";
3649
3663
  })(exports.CommandResult || (exports.CommandResult = {}));
3650
3664
 
3665
+ function isMatrix(x) {
3666
+ return Array.isArray(x) && Array.isArray(x[0]);
3667
+ }
3651
3668
  var DIRECTION;
3652
3669
  (function (DIRECTION) {
3653
3670
  DIRECTION["UP"] = "up";
@@ -4830,6 +4847,7 @@ class LineChart extends AbstractChart {
4830
4847
  this.labelsAsText = definition.labelsAsText;
4831
4848
  this.stacked = definition.stacked;
4832
4849
  this.aggregated = definition.aggregated;
4850
+ this.cumulative = definition.cumulative;
4833
4851
  }
4834
4852
  static validateChartDefinition(validator, definition) {
4835
4853
  return validator.checkValidations(definition, checkDataset, checkLabelRange);
@@ -4850,6 +4868,7 @@ class LineChart extends AbstractChart {
4850
4868
  labelRange: context.auxiliaryRange || undefined,
4851
4869
  stacked: false,
4852
4870
  aggregated: false,
4871
+ cumulative: false,
4853
4872
  };
4854
4873
  }
4855
4874
  getDefinition() {
@@ -4870,6 +4889,7 @@ class LineChart extends AbstractChart {
4870
4889
  labelsAsText: this.labelsAsText,
4871
4890
  stacked: this.stacked,
4872
4891
  aggregated: this.aggregated,
4892
+ cumulative: this.cumulative,
4873
4893
  };
4874
4894
  }
4875
4895
  getContextCreation() {
@@ -5063,6 +5083,16 @@ function createLineChartRuntime(chart, getters) {
5063
5083
  if (chart.stacked) {
5064
5084
  backgroundRGBA.a = LINE_FILL_TRANSPARENCY;
5065
5085
  }
5086
+ if (chart.cumulative) {
5087
+ let accumulator = 0;
5088
+ data = data.map((value) => {
5089
+ if (!isNaN(value)) {
5090
+ accumulator += parseFloat(value);
5091
+ return accumulator;
5092
+ }
5093
+ return value;
5094
+ });
5095
+ }
5066
5096
  const backgroundColor = rgbaToHex(backgroundRGBA);
5067
5097
  const dataset = {
5068
5098
  label,
@@ -6404,6 +6434,7 @@ function getSmartChartDefinition(zone, getters) {
6404
6434
  labelsAsText: false,
6405
6435
  stacked: false,
6406
6436
  aggregated: false,
6437
+ cumulative: false,
6407
6438
  labelRange: labelRangeXc,
6408
6439
  type: "line",
6409
6440
  dataSetsHaveTitle,
@@ -6757,6 +6788,13 @@ const REMOVE_ROWS_ACTION = (env) => {
6757
6788
  elements: rows,
6758
6789
  });
6759
6790
  };
6791
+ const CAN_REMOVE_COLUMNS_ROWS = (dimension, env) => {
6792
+ const sheetId = env.model.getters.getActiveSheetId();
6793
+ const selectedElements = env.model.getters.getElementsFromSelection(dimension);
6794
+ const includesAllVisibleHeaders = env.model.getters.checkElementsIncludeAllVisibleHeaders(sheetId, dimension, selectedElements);
6795
+ const includesAllNonFrozenHeaders = env.model.getters.checkElementsIncludeAllNonFrozenHeaders(sheetId, dimension, selectedElements);
6796
+ return !includesAllVisibleHeaders && !includesAllNonFrozenHeaders;
6797
+ };
6760
6798
  const REMOVE_COLUMNS_NAME = (env) => {
6761
6799
  if (env.model.getters.getSelectedZones().length > 1) {
6762
6800
  return _lt("Delete columns");
@@ -7347,11 +7385,7 @@ colMenuRegistry
7347
7385
  name: REMOVE_COLUMNS_NAME,
7348
7386
  sequence: 90,
7349
7387
  action: REMOVE_COLUMNS_ACTION,
7350
- isVisible: (env) => {
7351
- const sheetId = env.model.getters.getActiveSheetId();
7352
- const selectedCols = env.model.getters.getElementsFromSelection("COL");
7353
- return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
7354
- },
7388
+ isVisible: (env) => CAN_REMOVE_COLUMNS_ROWS("COL", env),
7355
7389
  })
7356
7390
  .add("clear_column", {
7357
7391
  name: DELETE_CONTENT_COLUMNS_NAME,
@@ -7365,7 +7399,7 @@ colMenuRegistry
7365
7399
  isVisible: (env) => {
7366
7400
  const sheetId = env.model.getters.getActiveSheetId();
7367
7401
  const selectedCols = env.model.getters.getElementsFromSelection("COL");
7368
- return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
7402
+ return !env.model.getters.checkElementsIncludeAllVisibleHeaders(sheetId, "COL", selectedCols);
7369
7403
  },
7370
7404
  separator: true,
7371
7405
  })
@@ -7439,11 +7473,7 @@ rowMenuRegistry
7439
7473
  name: REMOVE_ROWS_NAME,
7440
7474
  sequence: 70,
7441
7475
  action: REMOVE_ROWS_ACTION,
7442
- isVisible: (env) => {
7443
- const sheetId = env.model.getters.getActiveSheetId();
7444
- const selectedRows = env.model.getters.getElementsFromSelection("ROW");
7445
- return env.model.getters.canRemoveHeaders(sheetId, "ROW", selectedRows);
7446
- },
7476
+ isVisible: (env) => CAN_REMOVE_COLUMNS_ROWS("ROW", env),
7447
7477
  })
7448
7478
  .add("clear_row", {
7449
7479
  name: DELETE_CONTENT_ROWS_NAME,
@@ -7457,7 +7487,7 @@ rowMenuRegistry
7457
7487
  isVisible: (env) => {
7458
7488
  const sheetId = env.model.getters.getActiveSheetId();
7459
7489
  const selectedRows = env.model.getters.getElementsFromSelection("ROW");
7460
- return env.model.getters.canRemoveHeaders(sheetId, "ROW", selectedRows);
7490
+ return !env.model.getters.checkElementsIncludeAllVisibleHeaders(sheetId, "ROW", selectedRows);
7461
7491
  },
7462
7492
  separator: true,
7463
7493
  })
@@ -14104,6 +14134,36 @@ const HLOOKUP = {
14104
14134
  isExported: true,
14105
14135
  };
14106
14136
  // -----------------------------------------------------------------------------
14137
+ // INDEX
14138
+ // -----------------------------------------------------------------------------
14139
+ const INDEX = {
14140
+ description: _lt(`Returns the content of a cell, specified by row and column offset.`),
14141
+ args: args(`
14142
+ reference (any, range) ${_lt("The range of cells from which the value is returned.")}
14143
+ row (number) ${_lt("The index of the row to be returned from within the reference range of cells.")}
14144
+ column (number) ${_lt("The index of the column to be returned from within the reference range of cells.")}
14145
+ `),
14146
+ returns: ["ANY"],
14147
+ computeFormat: (reference, row, column) => {
14148
+ var _a;
14149
+ const _row = toNumber(row.value);
14150
+ const _column = toNumber(column.value);
14151
+ return (_a = reference[_column - 1][_row - 1]) === null || _a === void 0 ? void 0 : _a.format;
14152
+ },
14153
+ compute: function (reference, row, column) {
14154
+ const _reference = isMatrix(reference) ? reference : [[reference]];
14155
+ const _row = toNumber(row);
14156
+ const _column = toNumber(column);
14157
+ assert(() => _column >= 0 &&
14158
+ _column - 1 < _reference.length &&
14159
+ _row >= 0 &&
14160
+ _row - 1 < _reference[0].length, _lt("Index out of range."));
14161
+ assert(() => row !== 0 && column !== 0, _lt("This function can only return a single cell value, not an array. Provide valid row and column indices."));
14162
+ return _reference[_column - 1][_row - 1];
14163
+ },
14164
+ isExported: true,
14165
+ };
14166
+ // -----------------------------------------------------------------------------
14107
14167
  // LOOKUP
14108
14168
  // -----------------------------------------------------------------------------
14109
14169
  const LOOKUP = {
@@ -14297,6 +14357,7 @@ var lookup = /*#__PURE__*/Object.freeze({
14297
14357
  COLUMN: COLUMN,
14298
14358
  COLUMNS: COLUMNS,
14299
14359
  HLOOKUP: HLOOKUP,
14360
+ INDEX: INDEX,
14300
14361
  LOOKUP: LOOKUP,
14301
14362
  MATCH: MATCH,
14302
14363
  ROW: ROW,
@@ -18274,6 +18335,7 @@ css /* scss */ `
18274
18335
  padding: 10px;
18275
18336
  width: ${ERROR_TOOLTIP_WIDTH}px;
18276
18337
  box-sizing: border-box !important;
18338
+ overflow-wrap: break-word;
18277
18339
  }
18278
18340
  `;
18279
18341
  class ErrorToolTip extends owl.Component {
@@ -18454,6 +18516,9 @@ class FilterMenu extends owl.Component {
18454
18516
  });
18455
18517
  this.state.values = this.getFilterValues(this.props.filterPosition);
18456
18518
  }
18519
+ get isReadonly() {
18520
+ return this.env.model.getters.isReadonly();
18521
+ }
18457
18522
  getFilterValues(position) {
18458
18523
  const sheetId = this.env.model.getters.getActiveSheetId();
18459
18524
  const filter = this.env.model.getters.getFilter({ sheetId, ...position });
@@ -19334,11 +19399,13 @@ topbarMenuRegistry
19334
19399
  name: REMOVE_ROWS_NAME,
19335
19400
  sequence: 80,
19336
19401
  action: REMOVE_ROWS_ACTION,
19402
+ isVisible: (env) => CAN_REMOVE_COLUMNS_ROWS("ROW", env),
19337
19403
  })
19338
19404
  .addChild("edit_delete_column", ["edit"], {
19339
19405
  name: REMOVE_COLUMNS_NAME,
19340
19406
  sequence: 90,
19341
19407
  action: REMOVE_COLUMNS_ACTION,
19408
+ isVisible: (env) => CAN_REMOVE_COLUMNS_ROWS("COL", env),
19342
19409
  })
19343
19410
  .addChild("edit_delete_cell_shift_up", ["edit"], {
19344
19411
  name: _lt("Delete cell and shift up"),
@@ -20518,6 +20585,11 @@ class LineConfigPanel extends LineBarPieConfigPanel {
20518
20585
  aggregated: ev.target.checked,
20519
20586
  });
20520
20587
  }
20588
+ onUpdateCumulative(ev) {
20589
+ this.props.updateChart(this.props.figureId, {
20590
+ cumulative: ev.target.checked,
20591
+ });
20592
+ }
20521
20593
  }
20522
20594
  LineConfigPanel.template = "o-spreadsheet-LineConfigPanel";
20523
20595
 
@@ -21709,9 +21781,9 @@ class FindAndReplacePanel extends owl.Component {
21709
21781
  }
21710
21782
  setup() {
21711
21783
  this.showFormulaState = this.env.model.getters.shouldShowFormulas();
21712
- this.debouncedUpdateSearch = debounce(this.updateSearch.bind(this), 200);
21713
21784
  owl.onMounted(() => this.focusInput());
21714
21785
  owl.onWillUnmount(() => {
21786
+ clearTimeout(this.debounceTimeoutId);
21715
21787
  this.env.model.dispatch("CLEAR_SEARCH");
21716
21788
  this.env.model.dispatch("SET_FORMULA_VISIBILITY", { show: this.showFormulaState });
21717
21789
  });
@@ -21756,6 +21828,13 @@ class FindAndReplacePanel extends owl.Component {
21756
21828
  searchOptions: this.state.searchOptions,
21757
21829
  });
21758
21830
  }
21831
+ debouncedUpdateSearch() {
21832
+ clearTimeout(this.debounceTimeoutId);
21833
+ this.debounceTimeoutId = setTimeout(() => {
21834
+ this.updateSearch();
21835
+ this.debounceTimeoutId = undefined;
21836
+ }, 200);
21837
+ }
21759
21838
  replace() {
21760
21839
  this.env.model.dispatch("REPLACE_SEARCH", {
21761
21840
  replaceWith: this.state.replaceWith,
@@ -22406,9 +22485,11 @@ function useCellHovered(env, gridRef, callback) {
22406
22485
  }
22407
22486
  }
22408
22487
  function updateMousePosition(e) {
22409
- x = e.offsetX;
22410
- y = e.offsetY;
22411
- lastMoved = Date.now();
22488
+ if (gridRef.el === e.target) {
22489
+ x = e.offsetX;
22490
+ y = e.offsetY;
22491
+ lastMoved = Date.now();
22492
+ }
22412
22493
  }
22413
22494
  function recompute() {
22414
22495
  const { col, row } = getPosition();
@@ -22691,7 +22772,14 @@ class AbstractResizer extends owl.Component {
22691
22772
  return;
22692
22773
  }
22693
22774
  if (this.state.waitingForMove === true) {
22694
- this.startMovement(ev);
22775
+ if (!this.env.model.getters.isGridSelectionActive()) {
22776
+ this._selectElement(index, false);
22777
+ }
22778
+ else {
22779
+ // FIXME: Consider reintroducing this feature for all type of selection if we find
22780
+ // a way to have the grid selection follow the other selections evolution
22781
+ this.startMovement(ev);
22782
+ }
22695
22783
  return;
22696
22784
  }
22697
22785
  if (this.env.model.getters.getEditionMode() === "editing") {
@@ -25488,6 +25576,7 @@ function convertChartData(chartData) {
25488
25576
  legendPosition: chartData.legendPosition,
25489
25577
  stacked: chartData.stacked || false,
25490
25578
  aggregated: false,
25579
+ cumulative: chartData.cumulative || false,
25491
25580
  labelsAsText: false,
25492
25581
  };
25493
25582
  }
@@ -28524,10 +28613,11 @@ class CellPlugin extends CorePlugin {
28524
28613
  * Reconstructs the original formula string based on a normalized form and its dependencies
28525
28614
  */
28526
28615
  buildFormulaContent(sheetId, cell, dependencies) {
28527
- const ranges = dependencies || [...cell.dependencies];
28616
+ const ranges = dependencies || cell.dependencies;
28617
+ let rangeIndex = 0;
28528
28618
  return concat(cell.compiledFormula.tokens.map((token) => {
28529
28619
  if (token.type === "REFERENCE") {
28530
- const range = ranges.shift();
28620
+ const range = ranges[rangeIndex++];
28531
28621
  return this.getters.getRangeString(range, sheetId);
28532
28622
  }
28533
28623
  return token.value;
@@ -30052,7 +30142,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
30052
30142
  if (!this.getters.tryGetSheet(cmd.sheetId)) {
30053
30143
  return 27 /* CommandResult.InvalidSheetId */;
30054
30144
  }
30055
- if (!this.canRemoveHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
30145
+ if (this.checkElementsIncludeAllVisibleHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
30056
30146
  return 8 /* CommandResult.NotEnoughElements */;
30057
30147
  }
30058
30148
  return 0 /* CommandResult.Success */;
@@ -30102,9 +30192,9 @@ class HeaderVisibilityPlugin extends CorePlugin {
30102
30192
  }
30103
30193
  return;
30104
30194
  }
30105
- canRemoveHeaders(sheetId, dimension, elements) {
30195
+ checkElementsIncludeAllVisibleHeaders(sheetId, dimension, elements) {
30106
30196
  const visibleHeaders = this.getAllVisibleHeaders(sheetId, dimension);
30107
- return !includesAll(elements, visibleHeaders);
30197
+ return includesAll(elements, visibleHeaders);
30108
30198
  }
30109
30199
  isRowHiddenByUser(sheetId, index) {
30110
30200
  return this.hiddenHeaders[sheetId].ROW[index];
@@ -30200,7 +30290,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
30200
30290
  }
30201
30291
  }
30202
30292
  HeaderVisibilityPlugin.getters = [
30203
- "canRemoveHeaders",
30293
+ "checkElementsIncludeAllVisibleHeaders",
30204
30294
  "getHiddenColsGroups",
30205
30295
  "getHiddenRowsGroups",
30206
30296
  "isRowHiddenByUser",
@@ -31228,6 +31318,9 @@ class SheetPlugin extends CorePlugin {
31228
31318
  if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
31229
31319
  return 86 /* CommandResult.InvalidHeaderIndex */;
31230
31320
  }
31321
+ else if (this.checkElementsIncludeAllNonFrozenHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
31322
+ return 8 /* CommandResult.NotEnoughElements */;
31323
+ }
31231
31324
  else {
31232
31325
  return 0 /* CommandResult.Success */;
31233
31326
  }
@@ -31514,6 +31607,20 @@ class SheetPlugin extends CorePlugin {
31514
31607
  }
31515
31608
  this.history.update("sheets", sheetId, "panes", panes);
31516
31609
  }
31610
+ /**
31611
+ * Checks if all non-frozen header indices are present in the provided elements of selected rows/columns.
31612
+ * This validation ensures that all rows or columns cannot be deleted when frozen panes exist.
31613
+ */
31614
+ checkElementsIncludeAllNonFrozenHeaders(sheetId, dimension, elements) {
31615
+ const paneDivisions = this.getters.getPaneDivisions(sheetId);
31616
+ const startIndex = dimension === "ROW" ? paneDivisions.ySplit : paneDivisions.xSplit;
31617
+ const endIndex = this.getters.getNumberHeaders(sheetId, dimension);
31618
+ if (!startIndex) {
31619
+ return false;
31620
+ }
31621
+ const indicesToCheck = range(startIndex, endIndex);
31622
+ return includesAll(elements, indicesToCheck);
31623
+ }
31517
31624
  // ---------------------------------------------------------------------------
31518
31625
  // Row/Col manipulation
31519
31626
  // ---------------------------------------------------------------------------
@@ -32046,6 +32153,7 @@ SheetPlugin.getters = [
32046
32153
  "getSheetSize",
32047
32154
  "getSheetZone",
32048
32155
  "getPaneDivisions",
32156
+ "checkElementsIncludeAllNonFrozenHeaders",
32049
32157
  ];
32050
32158
 
32051
32159
  /**
@@ -32584,6 +32692,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
32584
32692
  // stores the computed styles in the format of computedStyles.sheetName[col][row] = Style
32585
32693
  this.computedStyles = {};
32586
32694
  this.computedIcons = {};
32695
+ this.uuidGenerator = new UuidGenerator();
32587
32696
  /**
32588
32697
  * Execute the predicate to know if a conditional formatting rule should be applied to a cell
32589
32698
  */
@@ -32936,13 +33045,20 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
32936
33045
  this.adaptRules(origin.sheetId, cf, [xc], toRemoveRange);
32937
33046
  }
32938
33047
  else {
32939
- this.adaptRules(target.sheetId, cf, [xc], []);
32940
33048
  this.adaptRules(origin.sheetId, cf, [], toRemoveRange);
33049
+ const cfToCopyTo = this.getCFToCopyTo(target.sheetId, cf);
33050
+ this.adaptRules(target.sheetId, cfToCopyTo, [xc], []);
32941
33051
  }
32942
33052
  }
32943
33053
  }
32944
33054
  }
32945
33055
  }
33056
+ getCFToCopyTo(targetSheetId, originCF) {
33057
+ const cfInTarget = this.getters
33058
+ .getConditionalFormats(targetSheetId)
33059
+ .find((cf) => cf.stopIfTrue === originCF.stopIfTrue && deepEquals(cf.rule, originCF.rule));
33060
+ return cfInTarget ? cfInTarget : { ...originCF, id: this.uuidGenerator.uuidv4(), ranges: [] };
33061
+ }
32946
33062
  }
32947
33063
  EvaluationConditionalFormatPlugin.getters = ["getConditionalIcon", "getCellComputedStyle"];
32948
33064
 
@@ -33290,30 +33406,26 @@ class InternalViewport {
33290
33406
  const { end } = this.getters.getColDimensions(sheetId, targetCol);
33291
33407
  const maxCol = this.getters.getNumberCols(sheetId);
33292
33408
  if (this.offsetX + this.offsetCorrectionX + this.viewportWidth < end) {
33293
- for (let col = this.left; this.offsetX + this.offsetCorrectionX + this.viewportWidth < end; col++) {
33294
- if (col > maxCol) {
33295
- break;
33296
- }
33297
- if (this.getters.isColHidden(sheetId, col)) {
33298
- continue;
33299
- }
33300
- this.offsetX = this.getters.getColDimensions(sheetId, col).end - this.offsetCorrectionX;
33301
- this.offsetScrollbarX = this.offsetX;
33302
- this.adjustViewportZoneX();
33409
+ let finalTarget = targetCol;
33410
+ while (this.getters.isColHidden(sheetId, finalTarget) && targetCol < maxCol) {
33411
+ finalTarget++;
33303
33412
  }
33413
+ const finalTargetEnd = this.getters.getColDimensions(sheetId, finalTarget).end;
33414
+ const startIndex = this.searchHeaderIndex("COL", finalTargetEnd - this.viewportWidth - this.offsetCorrectionX, this.boundaries.left, true);
33415
+ this.offsetX =
33416
+ this.getters.getColDimensions(sheetId, startIndex).end - this.offsetCorrectionX;
33417
+ this.offsetScrollbarX = this.offsetX;
33418
+ this.adjustViewportZoneX();
33304
33419
  }
33305
33420
  else if (this.left > targetCol) {
33306
- for (let col = this.left; col >= targetCol; col--) {
33307
- if (col < 0) {
33308
- break;
33309
- }
33310
- if (this.getters.isColHidden(sheetId, col)) {
33311
- continue;
33312
- }
33313
- this.offsetX = this.getters.getColDimensions(sheetId, col).start - this.offsetCorrectionX;
33314
- this.offsetScrollbarX = this.offsetX;
33315
- this.adjustViewportZoneX();
33421
+ let finalTarget = targetCol;
33422
+ while (this.getters.isColHidden(sheetId, finalTarget) && targetCol > 0) {
33423
+ finalTarget--;
33316
33424
  }
33425
+ this.offsetX =
33426
+ this.getters.getColDimensions(sheetId, finalTarget).start - this.offsetCorrectionX;
33427
+ this.offsetScrollbarX = this.offsetX;
33428
+ this.adjustViewportZoneX();
33317
33429
  }
33318
33430
  }
33319
33431
  adjustPositionY(targetRow) {
@@ -33321,30 +33433,26 @@ class InternalViewport {
33321
33433
  const { end } = this.getters.getRowDimensions(sheetId, targetRow);
33322
33434
  const maxRow = this.getters.getNumberRows(sheetId);
33323
33435
  if (this.offsetY + this.viewportHeight + this.offsetCorrectionY < end) {
33324
- for (let row = this.top; this.offsetY + this.viewportHeight + this.offsetCorrectionY < end; row++) {
33325
- if (row > maxRow) {
33326
- break;
33327
- }
33328
- if (this.getters.isRowHidden(sheetId, row)) {
33329
- continue;
33330
- }
33331
- this.offsetY = this.getters.getRowDimensions(sheetId, row).end - this.offsetCorrectionY;
33332
- this.offsetScrollbarY = this.offsetY;
33333
- this.adjustViewportZoneY();
33436
+ let finalTarget = targetRow;
33437
+ while (this.getters.isRowHidden(sheetId, finalTarget) && targetRow < maxRow) {
33438
+ finalTarget++;
33334
33439
  }
33440
+ const finalTargetEnd = this.getters.getRowDimensions(sheetId, finalTarget).end;
33441
+ const startIndex = this.searchHeaderIndex("ROW", finalTargetEnd - this.viewportHeight - this.offsetCorrectionY, this.boundaries.top, true);
33442
+ this.offsetY =
33443
+ this.getters.getRowDimensions(sheetId, startIndex).end - this.offsetCorrectionY;
33444
+ this.offsetScrollbarY = this.offsetY;
33445
+ this.adjustViewportZoneY();
33335
33446
  }
33336
33447
  else if (this.top > targetRow) {
33337
- for (let row = this.top; row >= targetRow; row--) {
33338
- if (row < 0) {
33339
- break;
33340
- }
33341
- if (this.getters.isRowHidden(sheetId, row)) {
33342
- continue;
33343
- }
33344
- this.offsetY = this.getters.getRowDimensions(sheetId, row).start - this.offsetCorrectionY;
33345
- this.offsetScrollbarY = this.offsetY;
33346
- this.adjustViewportZoneY();
33448
+ let finalTarget = targetRow;
33449
+ while (this.getters.isRowHidden(sheetId, finalTarget) && targetRow > 0) {
33450
+ finalTarget--;
33347
33451
  }
33452
+ this.offsetY =
33453
+ this.getters.getRowDimensions(sheetId, finalTarget).start - this.offsetCorrectionY;
33454
+ this.offsetScrollbarY = this.offsetY;
33455
+ this.adjustViewportZoneY();
33348
33456
  }
33349
33457
  }
33350
33458
  setViewportOffset(offsetX, offsetY) {
@@ -33464,6 +33572,9 @@ class InternalViewport {
33464
33572
  const sheetId = this.sheetId;
33465
33573
  this.left = this.searchHeaderIndex("COL", this.offsetScrollbarX, this.boundaries.left);
33466
33574
  this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.viewportWidth, this.left));
33575
+ if (this.left === -1) {
33576
+ this.left = this.boundaries.left;
33577
+ }
33467
33578
  if (this.right === -1) {
33468
33579
  this.right = this.getters.getNumberCols(sheetId) - 1;
33469
33580
  }
@@ -33477,6 +33588,9 @@ class InternalViewport {
33477
33588
  const sheetId = this.sheetId;
33478
33589
  this.top = this.searchHeaderIndex("ROW", this.offsetScrollbarY, this.boundaries.top);
33479
33590
  this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.viewportHeight, this.top));
33591
+ if (this.top === -1) {
33592
+ this.top = this.boundaries.top;
33593
+ }
33480
33594
  if (this.bottom === -1) {
33481
33595
  this.bottom = this.getters.getNumberRows(sheetId) - 1;
33482
33596
  }
@@ -34912,14 +35026,10 @@ class FindAndReplacePlugin extends UIPlugin {
34912
35026
  case "REPLACE_ALL_SEARCH":
34913
35027
  this.replaceAll(cmd.replaceWith);
34914
35028
  break;
34915
- case "EVALUATE_CELLS":
34916
- case "UPDATE_CELL":
34917
- case "REMOVE_FILTER_TABLE":
34918
- case "UPDATE_FILTER":
34919
- this.isSearchDirty = true;
34920
- break;
34921
35029
  case "UNDO":
34922
35030
  case "REDO":
35031
+ case "REMOVE_FILTER_TABLE":
35032
+ case "UPDATE_FILTER":
34923
35033
  case "REMOVE_COLUMNS_ROWS":
34924
35034
  case "HIDE_COLUMNS_ROWS":
34925
35035
  case "UNHIDE_COLUMNS_ROWS":
@@ -37911,7 +38021,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
37911
38021
  });
37912
38022
  for (const filterTable of this.copiedTables) {
37913
38023
  this.dispatch("REMOVE_FILTER_TABLE", {
37914
- sheetId: this.getters.getActiveSheetId(),
38024
+ sheetId: this.sheetId,
37915
38025
  target: [filterTable.zone],
37916
38026
  });
37917
38027
  }
@@ -38389,7 +38499,7 @@ class ClipboardPlugin extends UIPlugin {
38389
38499
  allowDispatch(cmd) {
38390
38500
  switch (cmd.type) {
38391
38501
  case "CUT":
38392
- const zones = cmd.target || this.getters.getSelectedZones();
38502
+ const zones = this.getters.getSelectedZones();
38393
38503
  const state = this.getClipboardState(zones, cmd.type);
38394
38504
  return state.isCutAllowed(zones);
38395
38505
  case "PASTE":
@@ -38420,7 +38530,7 @@ class ClipboardPlugin extends UIPlugin {
38420
38530
  switch (cmd.type) {
38421
38531
  case "COPY":
38422
38532
  case "CUT":
38423
- const zones = ("target" in cmd && cmd.target) || this.getters.getSelectedZones();
38533
+ const zones = this.getters.getSelectedZones();
38424
38534
  this.state = this.getClipboardState(zones, cmd.type);
38425
38535
  this.status = "visible";
38426
38536
  break;
@@ -38851,6 +38961,9 @@ class GridSelectionPlugin extends UIPlugin {
38851
38961
  // ---------------------------------------------------------------------------
38852
38962
  // Getters
38853
38963
  // ---------------------------------------------------------------------------
38964
+ isGridSelectionActive() {
38965
+ return this.selection.isListening(this);
38966
+ }
38854
38967
  getActiveSheet() {
38855
38968
  return this.activeSheet;
38856
38969
  }
@@ -39081,26 +39194,24 @@ class GridSelectionPlugin extends UIPlugin {
39081
39194
  const isBasedBefore = cmd.base < start;
39082
39195
  const deltaCol = isBasedBefore && isCol ? thickness : 0;
39083
39196
  const deltaRow = isBasedBefore && !isCol ? thickness : 0;
39084
- this.dispatch("CUT", {
39085
- target: [
39086
- {
39087
- left: isCol ? start + deltaCol : 0,
39088
- right: isCol ? end + deltaCol : this.getters.getNumberCols(cmd.sheetId) - 1,
39089
- top: !isCol ? start + deltaRow : 0,
39090
- bottom: !isCol ? end + deltaRow : this.getters.getNumberRows(cmd.sheetId) - 1,
39091
- },
39092
- ],
39093
- });
39094
- this.dispatch("PASTE", {
39095
- target: [
39096
- {
39097
- left: isCol ? cmd.base : 0,
39098
- right: isCol ? cmd.base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
39099
- top: !isCol ? cmd.base : 0,
39100
- bottom: !isCol ? cmd.base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
39101
- },
39102
- ],
39103
- });
39197
+ const target = [
39198
+ {
39199
+ left: isCol ? start + deltaCol : 0,
39200
+ right: isCol ? end + deltaCol : this.getters.getNumberCols(cmd.sheetId) - 1,
39201
+ top: !isCol ? start + deltaRow : 0,
39202
+ bottom: !isCol ? end + deltaRow : this.getters.getNumberRows(cmd.sheetId) - 1,
39203
+ },
39204
+ ];
39205
+ const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
39206
+ const pasteTarget = [
39207
+ {
39208
+ left: isCol ? cmd.base : 0,
39209
+ right: isCol ? cmd.base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
39210
+ top: !isCol ? cmd.base : 0,
39211
+ bottom: !isCol ? cmd.base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
39212
+ },
39213
+ ];
39214
+ state.paste(pasteTarget, { selectTarget: true });
39104
39215
  const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
39105
39216
  let currentIndex = cmd.base;
39106
39217
  for (const element of toRemove) {
@@ -39227,6 +39338,7 @@ GridSelectionPlugin.getters = [
39227
39338
  "getSheetPosition",
39228
39339
  "isSelected",
39229
39340
  "getElementsFromSelection",
39341
+ "isGridSelectionActive",
39230
39342
  ];
39231
39343
 
39232
39344
  const corePluginRegistry = new Registry()
@@ -42019,6 +42131,9 @@ class SelectionStreamProcessor {
42019
42131
  anchor: { zone, cell: this.anchor.cell },
42020
42132
  });
42021
42133
  }
42134
+ isListening(owner) {
42135
+ return this.stream.isListening(owner);
42136
+ }
42022
42137
  /**
42023
42138
  * Process a new anchor selection event. If the new anchor is inside
42024
42139
  * the sheet boundaries, the event is pushed to the event stream to
@@ -44305,6 +44420,6 @@ exports.setTranslationMethod = setTranslationMethod;
44305
44420
  exports.tokenize = tokenize;
44306
44421
 
44307
44422
 
44308
- __info__.version = '16.1.19';
44309
- __info__.date = '2023-08-29T13:54:21.626Z';
44310
- __info__.hash = '053a843';
44423
+ __info__.version = '16.1.23';
44424
+ __info__.date = '2023-10-10T07:27:03.376Z';
44425
+ __info__.hash = '13bfa8f';