@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.
@@ -317,7 +317,16 @@ const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY;
317
317
  const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
318
318
  const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
319
319
  const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
320
+ const CACHE = {};
320
321
  function parseDateTime(str) {
322
+ if (str in CACHE) {
323
+ return CACHE[str];
324
+ }
325
+ const date = _parseDateTime(str);
326
+ CACHE[str] = date;
327
+ return date;
328
+ }
329
+ function _parseDateTime(str) {
321
330
  str = str.trim();
322
331
  let time;
323
332
  const timeMatch = str.match(timeRegexp);
@@ -1002,13 +1011,17 @@ function getAddHeaderStartIndex(position, base) {
1002
1011
  return position === "after" ? base + 1 : base;
1003
1012
  }
1004
1013
  /**
1005
- * Compare two objects.
1014
+ * Compares two objects.
1006
1015
  */
1007
1016
  function deepEquals(o1, o2) {
1008
1017
  if (o1 === o2)
1009
1018
  return true;
1010
1019
  if ((o1 && !o2) || (o2 && !o1))
1011
1020
  return false;
1021
+ if (typeof o1 !== typeof o2)
1022
+ return false;
1023
+ if (typeof o1 !== "object")
1024
+ return o1 === o2;
1012
1025
  // Objects can have different keys if the values are undefined
1013
1026
  const keys = new Set();
1014
1027
  Object.keys(o1).forEach((key) => keys.add(key));
@@ -2117,8 +2130,9 @@ class RangeImpl {
2117
2130
  }
2118
2131
  get zone() {
2119
2132
  const { left, top, bottom, right } = this._zone;
2120
- if (right !== undefined && bottom !== undefined)
2121
- return { left, top, right, bottom };
2133
+ if (right !== undefined && bottom !== undefined) {
2134
+ return this._zone;
2135
+ }
2122
2136
  else if (bottom === undefined && right !== undefined) {
2123
2137
  return { right, top, left, bottom: this.getSheetSize(this.sheetId).height - 1 };
2124
2138
  }
@@ -3644,6 +3658,9 @@ var CommandResult;
3644
3658
  CommandResult[CommandResult["InvalidQuantity"] = 87] = "InvalidQuantity";
3645
3659
  })(CommandResult || (CommandResult = {}));
3646
3660
 
3661
+ function isMatrix(x) {
3662
+ return Array.isArray(x) && Array.isArray(x[0]);
3663
+ }
3647
3664
  var DIRECTION;
3648
3665
  (function (DIRECTION) {
3649
3666
  DIRECTION["UP"] = "up";
@@ -4826,6 +4843,7 @@ class LineChart extends AbstractChart {
4826
4843
  this.labelsAsText = definition.labelsAsText;
4827
4844
  this.stacked = definition.stacked;
4828
4845
  this.aggregated = definition.aggregated;
4846
+ this.cumulative = definition.cumulative;
4829
4847
  }
4830
4848
  static validateChartDefinition(validator, definition) {
4831
4849
  return validator.checkValidations(definition, checkDataset, checkLabelRange);
@@ -4846,6 +4864,7 @@ class LineChart extends AbstractChart {
4846
4864
  labelRange: context.auxiliaryRange || undefined,
4847
4865
  stacked: false,
4848
4866
  aggregated: false,
4867
+ cumulative: false,
4849
4868
  };
4850
4869
  }
4851
4870
  getDefinition() {
@@ -4866,6 +4885,7 @@ class LineChart extends AbstractChart {
4866
4885
  labelsAsText: this.labelsAsText,
4867
4886
  stacked: this.stacked,
4868
4887
  aggregated: this.aggregated,
4888
+ cumulative: this.cumulative,
4869
4889
  };
4870
4890
  }
4871
4891
  getContextCreation() {
@@ -5059,6 +5079,16 @@ function createLineChartRuntime(chart, getters) {
5059
5079
  if (chart.stacked) {
5060
5080
  backgroundRGBA.a = LINE_FILL_TRANSPARENCY;
5061
5081
  }
5082
+ if (chart.cumulative) {
5083
+ let accumulator = 0;
5084
+ data = data.map((value) => {
5085
+ if (!isNaN(value)) {
5086
+ accumulator += parseFloat(value);
5087
+ return accumulator;
5088
+ }
5089
+ return value;
5090
+ });
5091
+ }
5062
5092
  const backgroundColor = rgbaToHex(backgroundRGBA);
5063
5093
  const dataset = {
5064
5094
  label,
@@ -6400,6 +6430,7 @@ function getSmartChartDefinition(zone, getters) {
6400
6430
  labelsAsText: false,
6401
6431
  stacked: false,
6402
6432
  aggregated: false,
6433
+ cumulative: false,
6403
6434
  labelRange: labelRangeXc,
6404
6435
  type: "line",
6405
6436
  dataSetsHaveTitle,
@@ -6753,6 +6784,13 @@ const REMOVE_ROWS_ACTION = (env) => {
6753
6784
  elements: rows,
6754
6785
  });
6755
6786
  };
6787
+ const CAN_REMOVE_COLUMNS_ROWS = (dimension, env) => {
6788
+ const sheetId = env.model.getters.getActiveSheetId();
6789
+ const selectedElements = env.model.getters.getElementsFromSelection(dimension);
6790
+ const includesAllVisibleHeaders = env.model.getters.checkElementsIncludeAllVisibleHeaders(sheetId, dimension, selectedElements);
6791
+ const includesAllNonFrozenHeaders = env.model.getters.checkElementsIncludeAllNonFrozenHeaders(sheetId, dimension, selectedElements);
6792
+ return !includesAllVisibleHeaders && !includesAllNonFrozenHeaders;
6793
+ };
6756
6794
  const REMOVE_COLUMNS_NAME = (env) => {
6757
6795
  if (env.model.getters.getSelectedZones().length > 1) {
6758
6796
  return _lt("Delete columns");
@@ -7343,11 +7381,7 @@ colMenuRegistry
7343
7381
  name: REMOVE_COLUMNS_NAME,
7344
7382
  sequence: 90,
7345
7383
  action: REMOVE_COLUMNS_ACTION,
7346
- isVisible: (env) => {
7347
- const sheetId = env.model.getters.getActiveSheetId();
7348
- const selectedCols = env.model.getters.getElementsFromSelection("COL");
7349
- return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
7350
- },
7384
+ isVisible: (env) => CAN_REMOVE_COLUMNS_ROWS("COL", env),
7351
7385
  })
7352
7386
  .add("clear_column", {
7353
7387
  name: DELETE_CONTENT_COLUMNS_NAME,
@@ -7361,7 +7395,7 @@ colMenuRegistry
7361
7395
  isVisible: (env) => {
7362
7396
  const sheetId = env.model.getters.getActiveSheetId();
7363
7397
  const selectedCols = env.model.getters.getElementsFromSelection("COL");
7364
- return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
7398
+ return !env.model.getters.checkElementsIncludeAllVisibleHeaders(sheetId, "COL", selectedCols);
7365
7399
  },
7366
7400
  separator: true,
7367
7401
  })
@@ -7435,11 +7469,7 @@ rowMenuRegistry
7435
7469
  name: REMOVE_ROWS_NAME,
7436
7470
  sequence: 70,
7437
7471
  action: REMOVE_ROWS_ACTION,
7438
- isVisible: (env) => {
7439
- const sheetId = env.model.getters.getActiveSheetId();
7440
- const selectedRows = env.model.getters.getElementsFromSelection("ROW");
7441
- return env.model.getters.canRemoveHeaders(sheetId, "ROW", selectedRows);
7442
- },
7472
+ isVisible: (env) => CAN_REMOVE_COLUMNS_ROWS("ROW", env),
7443
7473
  })
7444
7474
  .add("clear_row", {
7445
7475
  name: DELETE_CONTENT_ROWS_NAME,
@@ -7453,7 +7483,7 @@ rowMenuRegistry
7453
7483
  isVisible: (env) => {
7454
7484
  const sheetId = env.model.getters.getActiveSheetId();
7455
7485
  const selectedRows = env.model.getters.getElementsFromSelection("ROW");
7456
- return env.model.getters.canRemoveHeaders(sheetId, "ROW", selectedRows);
7486
+ return !env.model.getters.checkElementsIncludeAllVisibleHeaders(sheetId, "ROW", selectedRows);
7457
7487
  },
7458
7488
  separator: true,
7459
7489
  })
@@ -14100,6 +14130,36 @@ const HLOOKUP = {
14100
14130
  isExported: true,
14101
14131
  };
14102
14132
  // -----------------------------------------------------------------------------
14133
+ // INDEX
14134
+ // -----------------------------------------------------------------------------
14135
+ const INDEX = {
14136
+ description: _lt(`Returns the content of a cell, specified by row and column offset.`),
14137
+ args: args(`
14138
+ reference (any, range) ${_lt("The range of cells from which the value is returned.")}
14139
+ row (number) ${_lt("The index of the row to be returned from within the reference range of cells.")}
14140
+ column (number) ${_lt("The index of the column to be returned from within the reference range of cells.")}
14141
+ `),
14142
+ returns: ["ANY"],
14143
+ computeFormat: (reference, row, column) => {
14144
+ var _a;
14145
+ const _row = toNumber(row.value);
14146
+ const _column = toNumber(column.value);
14147
+ return (_a = reference[_column - 1][_row - 1]) === null || _a === void 0 ? void 0 : _a.format;
14148
+ },
14149
+ compute: function (reference, row, column) {
14150
+ const _reference = isMatrix(reference) ? reference : [[reference]];
14151
+ const _row = toNumber(row);
14152
+ const _column = toNumber(column);
14153
+ assert(() => _column >= 0 &&
14154
+ _column - 1 < _reference.length &&
14155
+ _row >= 0 &&
14156
+ _row - 1 < _reference[0].length, _lt("Index out of range."));
14157
+ assert(() => row !== 0 && column !== 0, _lt("This function can only return a single cell value, not an array. Provide valid row and column indices."));
14158
+ return _reference[_column - 1][_row - 1];
14159
+ },
14160
+ isExported: true,
14161
+ };
14162
+ // -----------------------------------------------------------------------------
14103
14163
  // LOOKUP
14104
14164
  // -----------------------------------------------------------------------------
14105
14165
  const LOOKUP = {
@@ -14293,6 +14353,7 @@ var lookup = /*#__PURE__*/Object.freeze({
14293
14353
  COLUMN: COLUMN,
14294
14354
  COLUMNS: COLUMNS,
14295
14355
  HLOOKUP: HLOOKUP,
14356
+ INDEX: INDEX,
14296
14357
  LOOKUP: LOOKUP,
14297
14358
  MATCH: MATCH,
14298
14359
  ROW: ROW,
@@ -18270,6 +18331,7 @@ css /* scss */ `
18270
18331
  padding: 10px;
18271
18332
  width: ${ERROR_TOOLTIP_WIDTH}px;
18272
18333
  box-sizing: border-box !important;
18334
+ overflow-wrap: break-word;
18273
18335
  }
18274
18336
  `;
18275
18337
  class ErrorToolTip extends Component {
@@ -18450,6 +18512,9 @@ class FilterMenu extends Component {
18450
18512
  });
18451
18513
  this.state.values = this.getFilterValues(this.props.filterPosition);
18452
18514
  }
18515
+ get isReadonly() {
18516
+ return this.env.model.getters.isReadonly();
18517
+ }
18453
18518
  getFilterValues(position) {
18454
18519
  const sheetId = this.env.model.getters.getActiveSheetId();
18455
18520
  const filter = this.env.model.getters.getFilter({ sheetId, ...position });
@@ -19330,11 +19395,13 @@ topbarMenuRegistry
19330
19395
  name: REMOVE_ROWS_NAME,
19331
19396
  sequence: 80,
19332
19397
  action: REMOVE_ROWS_ACTION,
19398
+ isVisible: (env) => CAN_REMOVE_COLUMNS_ROWS("ROW", env),
19333
19399
  })
19334
19400
  .addChild("edit_delete_column", ["edit"], {
19335
19401
  name: REMOVE_COLUMNS_NAME,
19336
19402
  sequence: 90,
19337
19403
  action: REMOVE_COLUMNS_ACTION,
19404
+ isVisible: (env) => CAN_REMOVE_COLUMNS_ROWS("COL", env),
19338
19405
  })
19339
19406
  .addChild("edit_delete_cell_shift_up", ["edit"], {
19340
19407
  name: _lt("Delete cell and shift up"),
@@ -20514,6 +20581,11 @@ class LineConfigPanel extends LineBarPieConfigPanel {
20514
20581
  aggregated: ev.target.checked,
20515
20582
  });
20516
20583
  }
20584
+ onUpdateCumulative(ev) {
20585
+ this.props.updateChart(this.props.figureId, {
20586
+ cumulative: ev.target.checked,
20587
+ });
20588
+ }
20517
20589
  }
20518
20590
  LineConfigPanel.template = "o-spreadsheet-LineConfigPanel";
20519
20591
 
@@ -21705,9 +21777,9 @@ class FindAndReplacePanel extends Component {
21705
21777
  }
21706
21778
  setup() {
21707
21779
  this.showFormulaState = this.env.model.getters.shouldShowFormulas();
21708
- this.debouncedUpdateSearch = debounce(this.updateSearch.bind(this), 200);
21709
21780
  onMounted(() => this.focusInput());
21710
21781
  onWillUnmount(() => {
21782
+ clearTimeout(this.debounceTimeoutId);
21711
21783
  this.env.model.dispatch("CLEAR_SEARCH");
21712
21784
  this.env.model.dispatch("SET_FORMULA_VISIBILITY", { show: this.showFormulaState });
21713
21785
  });
@@ -21752,6 +21824,13 @@ class FindAndReplacePanel extends Component {
21752
21824
  searchOptions: this.state.searchOptions,
21753
21825
  });
21754
21826
  }
21827
+ debouncedUpdateSearch() {
21828
+ clearTimeout(this.debounceTimeoutId);
21829
+ this.debounceTimeoutId = setTimeout(() => {
21830
+ this.updateSearch();
21831
+ this.debounceTimeoutId = undefined;
21832
+ }, 200);
21833
+ }
21755
21834
  replace() {
21756
21835
  this.env.model.dispatch("REPLACE_SEARCH", {
21757
21836
  replaceWith: this.state.replaceWith,
@@ -22402,9 +22481,11 @@ function useCellHovered(env, gridRef, callback) {
22402
22481
  }
22403
22482
  }
22404
22483
  function updateMousePosition(e) {
22405
- x = e.offsetX;
22406
- y = e.offsetY;
22407
- lastMoved = Date.now();
22484
+ if (gridRef.el === e.target) {
22485
+ x = e.offsetX;
22486
+ y = e.offsetY;
22487
+ lastMoved = Date.now();
22488
+ }
22408
22489
  }
22409
22490
  function recompute() {
22410
22491
  const { col, row } = getPosition();
@@ -22687,7 +22768,14 @@ class AbstractResizer extends Component {
22687
22768
  return;
22688
22769
  }
22689
22770
  if (this.state.waitingForMove === true) {
22690
- this.startMovement(ev);
22771
+ if (!this.env.model.getters.isGridSelectionActive()) {
22772
+ this._selectElement(index, false);
22773
+ }
22774
+ else {
22775
+ // FIXME: Consider reintroducing this feature for all type of selection if we find
22776
+ // a way to have the grid selection follow the other selections evolution
22777
+ this.startMovement(ev);
22778
+ }
22691
22779
  return;
22692
22780
  }
22693
22781
  if (this.env.model.getters.getEditionMode() === "editing") {
@@ -25484,6 +25572,7 @@ function convertChartData(chartData) {
25484
25572
  legendPosition: chartData.legendPosition,
25485
25573
  stacked: chartData.stacked || false,
25486
25574
  aggregated: false,
25575
+ cumulative: chartData.cumulative || false,
25487
25576
  labelsAsText: false,
25488
25577
  };
25489
25578
  }
@@ -28520,10 +28609,11 @@ class CellPlugin extends CorePlugin {
28520
28609
  * Reconstructs the original formula string based on a normalized form and its dependencies
28521
28610
  */
28522
28611
  buildFormulaContent(sheetId, cell, dependencies) {
28523
- const ranges = dependencies || [...cell.dependencies];
28612
+ const ranges = dependencies || cell.dependencies;
28613
+ let rangeIndex = 0;
28524
28614
  return concat(cell.compiledFormula.tokens.map((token) => {
28525
28615
  if (token.type === "REFERENCE") {
28526
- const range = ranges.shift();
28616
+ const range = ranges[rangeIndex++];
28527
28617
  return this.getters.getRangeString(range, sheetId);
28528
28618
  }
28529
28619
  return token.value;
@@ -30048,7 +30138,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
30048
30138
  if (!this.getters.tryGetSheet(cmd.sheetId)) {
30049
30139
  return 27 /* CommandResult.InvalidSheetId */;
30050
30140
  }
30051
- if (!this.canRemoveHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
30141
+ if (this.checkElementsIncludeAllVisibleHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
30052
30142
  return 8 /* CommandResult.NotEnoughElements */;
30053
30143
  }
30054
30144
  return 0 /* CommandResult.Success */;
@@ -30098,9 +30188,9 @@ class HeaderVisibilityPlugin extends CorePlugin {
30098
30188
  }
30099
30189
  return;
30100
30190
  }
30101
- canRemoveHeaders(sheetId, dimension, elements) {
30191
+ checkElementsIncludeAllVisibleHeaders(sheetId, dimension, elements) {
30102
30192
  const visibleHeaders = this.getAllVisibleHeaders(sheetId, dimension);
30103
- return !includesAll(elements, visibleHeaders);
30193
+ return includesAll(elements, visibleHeaders);
30104
30194
  }
30105
30195
  isRowHiddenByUser(sheetId, index) {
30106
30196
  return this.hiddenHeaders[sheetId].ROW[index];
@@ -30196,7 +30286,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
30196
30286
  }
30197
30287
  }
30198
30288
  HeaderVisibilityPlugin.getters = [
30199
- "canRemoveHeaders",
30289
+ "checkElementsIncludeAllVisibleHeaders",
30200
30290
  "getHiddenColsGroups",
30201
30291
  "getHiddenRowsGroups",
30202
30292
  "isRowHiddenByUser",
@@ -31224,6 +31314,9 @@ class SheetPlugin extends CorePlugin {
31224
31314
  if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
31225
31315
  return 86 /* CommandResult.InvalidHeaderIndex */;
31226
31316
  }
31317
+ else if (this.checkElementsIncludeAllNonFrozenHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
31318
+ return 8 /* CommandResult.NotEnoughElements */;
31319
+ }
31227
31320
  else {
31228
31321
  return 0 /* CommandResult.Success */;
31229
31322
  }
@@ -31510,6 +31603,20 @@ class SheetPlugin extends CorePlugin {
31510
31603
  }
31511
31604
  this.history.update("sheets", sheetId, "panes", panes);
31512
31605
  }
31606
+ /**
31607
+ * Checks if all non-frozen header indices are present in the provided elements of selected rows/columns.
31608
+ * This validation ensures that all rows or columns cannot be deleted when frozen panes exist.
31609
+ */
31610
+ checkElementsIncludeAllNonFrozenHeaders(sheetId, dimension, elements) {
31611
+ const paneDivisions = this.getters.getPaneDivisions(sheetId);
31612
+ const startIndex = dimension === "ROW" ? paneDivisions.ySplit : paneDivisions.xSplit;
31613
+ const endIndex = this.getters.getNumberHeaders(sheetId, dimension);
31614
+ if (!startIndex) {
31615
+ return false;
31616
+ }
31617
+ const indicesToCheck = range(startIndex, endIndex);
31618
+ return includesAll(elements, indicesToCheck);
31619
+ }
31513
31620
  // ---------------------------------------------------------------------------
31514
31621
  // Row/Col manipulation
31515
31622
  // ---------------------------------------------------------------------------
@@ -32042,6 +32149,7 @@ SheetPlugin.getters = [
32042
32149
  "getSheetSize",
32043
32150
  "getSheetZone",
32044
32151
  "getPaneDivisions",
32152
+ "checkElementsIncludeAllNonFrozenHeaders",
32045
32153
  ];
32046
32154
 
32047
32155
  /**
@@ -32580,6 +32688,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
32580
32688
  // stores the computed styles in the format of computedStyles.sheetName[col][row] = Style
32581
32689
  this.computedStyles = {};
32582
32690
  this.computedIcons = {};
32691
+ this.uuidGenerator = new UuidGenerator();
32583
32692
  /**
32584
32693
  * Execute the predicate to know if a conditional formatting rule should be applied to a cell
32585
32694
  */
@@ -32932,13 +33041,20 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
32932
33041
  this.adaptRules(origin.sheetId, cf, [xc], toRemoveRange);
32933
33042
  }
32934
33043
  else {
32935
- this.adaptRules(target.sheetId, cf, [xc], []);
32936
33044
  this.adaptRules(origin.sheetId, cf, [], toRemoveRange);
33045
+ const cfToCopyTo = this.getCFToCopyTo(target.sheetId, cf);
33046
+ this.adaptRules(target.sheetId, cfToCopyTo, [xc], []);
32937
33047
  }
32938
33048
  }
32939
33049
  }
32940
33050
  }
32941
33051
  }
33052
+ getCFToCopyTo(targetSheetId, originCF) {
33053
+ const cfInTarget = this.getters
33054
+ .getConditionalFormats(targetSheetId)
33055
+ .find((cf) => cf.stopIfTrue === originCF.stopIfTrue && deepEquals(cf.rule, originCF.rule));
33056
+ return cfInTarget ? cfInTarget : { ...originCF, id: this.uuidGenerator.uuidv4(), ranges: [] };
33057
+ }
32942
33058
  }
32943
33059
  EvaluationConditionalFormatPlugin.getters = ["getConditionalIcon", "getCellComputedStyle"];
32944
33060
 
@@ -33286,30 +33402,26 @@ class InternalViewport {
33286
33402
  const { end } = this.getters.getColDimensions(sheetId, targetCol);
33287
33403
  const maxCol = this.getters.getNumberCols(sheetId);
33288
33404
  if (this.offsetX + this.offsetCorrectionX + this.viewportWidth < end) {
33289
- for (let col = this.left; this.offsetX + this.offsetCorrectionX + this.viewportWidth < end; col++) {
33290
- if (col > maxCol) {
33291
- break;
33292
- }
33293
- if (this.getters.isColHidden(sheetId, col)) {
33294
- continue;
33295
- }
33296
- this.offsetX = this.getters.getColDimensions(sheetId, col).end - this.offsetCorrectionX;
33297
- this.offsetScrollbarX = this.offsetX;
33298
- this.adjustViewportZoneX();
33405
+ let finalTarget = targetCol;
33406
+ while (this.getters.isColHidden(sheetId, finalTarget) && targetCol < maxCol) {
33407
+ finalTarget++;
33299
33408
  }
33409
+ const finalTargetEnd = this.getters.getColDimensions(sheetId, finalTarget).end;
33410
+ const startIndex = this.searchHeaderIndex("COL", finalTargetEnd - this.viewportWidth - this.offsetCorrectionX, this.boundaries.left, true);
33411
+ this.offsetX =
33412
+ this.getters.getColDimensions(sheetId, startIndex).end - this.offsetCorrectionX;
33413
+ this.offsetScrollbarX = this.offsetX;
33414
+ this.adjustViewportZoneX();
33300
33415
  }
33301
33416
  else if (this.left > targetCol) {
33302
- for (let col = this.left; col >= targetCol; col--) {
33303
- if (col < 0) {
33304
- break;
33305
- }
33306
- if (this.getters.isColHidden(sheetId, col)) {
33307
- continue;
33308
- }
33309
- this.offsetX = this.getters.getColDimensions(sheetId, col).start - this.offsetCorrectionX;
33310
- this.offsetScrollbarX = this.offsetX;
33311
- this.adjustViewportZoneX();
33417
+ let finalTarget = targetCol;
33418
+ while (this.getters.isColHidden(sheetId, finalTarget) && targetCol > 0) {
33419
+ finalTarget--;
33312
33420
  }
33421
+ this.offsetX =
33422
+ this.getters.getColDimensions(sheetId, finalTarget).start - this.offsetCorrectionX;
33423
+ this.offsetScrollbarX = this.offsetX;
33424
+ this.adjustViewportZoneX();
33313
33425
  }
33314
33426
  }
33315
33427
  adjustPositionY(targetRow) {
@@ -33317,30 +33429,26 @@ class InternalViewport {
33317
33429
  const { end } = this.getters.getRowDimensions(sheetId, targetRow);
33318
33430
  const maxRow = this.getters.getNumberRows(sheetId);
33319
33431
  if (this.offsetY + this.viewportHeight + this.offsetCorrectionY < end) {
33320
- for (let row = this.top; this.offsetY + this.viewportHeight + this.offsetCorrectionY < end; row++) {
33321
- if (row > maxRow) {
33322
- break;
33323
- }
33324
- if (this.getters.isRowHidden(sheetId, row)) {
33325
- continue;
33326
- }
33327
- this.offsetY = this.getters.getRowDimensions(sheetId, row).end - this.offsetCorrectionY;
33328
- this.offsetScrollbarY = this.offsetY;
33329
- this.adjustViewportZoneY();
33432
+ let finalTarget = targetRow;
33433
+ while (this.getters.isRowHidden(sheetId, finalTarget) && targetRow < maxRow) {
33434
+ finalTarget++;
33330
33435
  }
33436
+ const finalTargetEnd = this.getters.getRowDimensions(sheetId, finalTarget).end;
33437
+ const startIndex = this.searchHeaderIndex("ROW", finalTargetEnd - this.viewportHeight - this.offsetCorrectionY, this.boundaries.top, true);
33438
+ this.offsetY =
33439
+ this.getters.getRowDimensions(sheetId, startIndex).end - this.offsetCorrectionY;
33440
+ this.offsetScrollbarY = this.offsetY;
33441
+ this.adjustViewportZoneY();
33331
33442
  }
33332
33443
  else if (this.top > targetRow) {
33333
- for (let row = this.top; row >= targetRow; row--) {
33334
- if (row < 0) {
33335
- break;
33336
- }
33337
- if (this.getters.isRowHidden(sheetId, row)) {
33338
- continue;
33339
- }
33340
- this.offsetY = this.getters.getRowDimensions(sheetId, row).start - this.offsetCorrectionY;
33341
- this.offsetScrollbarY = this.offsetY;
33342
- this.adjustViewportZoneY();
33444
+ let finalTarget = targetRow;
33445
+ while (this.getters.isRowHidden(sheetId, finalTarget) && targetRow > 0) {
33446
+ finalTarget--;
33343
33447
  }
33448
+ this.offsetY =
33449
+ this.getters.getRowDimensions(sheetId, finalTarget).start - this.offsetCorrectionY;
33450
+ this.offsetScrollbarY = this.offsetY;
33451
+ this.adjustViewportZoneY();
33344
33452
  }
33345
33453
  }
33346
33454
  setViewportOffset(offsetX, offsetY) {
@@ -33460,6 +33568,9 @@ class InternalViewport {
33460
33568
  const sheetId = this.sheetId;
33461
33569
  this.left = this.searchHeaderIndex("COL", this.offsetScrollbarX, this.boundaries.left);
33462
33570
  this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.viewportWidth, this.left));
33571
+ if (this.left === -1) {
33572
+ this.left = this.boundaries.left;
33573
+ }
33463
33574
  if (this.right === -1) {
33464
33575
  this.right = this.getters.getNumberCols(sheetId) - 1;
33465
33576
  }
@@ -33473,6 +33584,9 @@ class InternalViewport {
33473
33584
  const sheetId = this.sheetId;
33474
33585
  this.top = this.searchHeaderIndex("ROW", this.offsetScrollbarY, this.boundaries.top);
33475
33586
  this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.viewportHeight, this.top));
33587
+ if (this.top === -1) {
33588
+ this.top = this.boundaries.top;
33589
+ }
33476
33590
  if (this.bottom === -1) {
33477
33591
  this.bottom = this.getters.getNumberRows(sheetId) - 1;
33478
33592
  }
@@ -34908,14 +35022,10 @@ class FindAndReplacePlugin extends UIPlugin {
34908
35022
  case "REPLACE_ALL_SEARCH":
34909
35023
  this.replaceAll(cmd.replaceWith);
34910
35024
  break;
34911
- case "EVALUATE_CELLS":
34912
- case "UPDATE_CELL":
34913
- case "REMOVE_FILTER_TABLE":
34914
- case "UPDATE_FILTER":
34915
- this.isSearchDirty = true;
34916
- break;
34917
35025
  case "UNDO":
34918
35026
  case "REDO":
35027
+ case "REMOVE_FILTER_TABLE":
35028
+ case "UPDATE_FILTER":
34919
35029
  case "REMOVE_COLUMNS_ROWS":
34920
35030
  case "HIDE_COLUMNS_ROWS":
34921
35031
  case "UNHIDE_COLUMNS_ROWS":
@@ -37907,7 +38017,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
37907
38017
  });
37908
38018
  for (const filterTable of this.copiedTables) {
37909
38019
  this.dispatch("REMOVE_FILTER_TABLE", {
37910
- sheetId: this.getters.getActiveSheetId(),
38020
+ sheetId: this.sheetId,
37911
38021
  target: [filterTable.zone],
37912
38022
  });
37913
38023
  }
@@ -38385,7 +38495,7 @@ class ClipboardPlugin extends UIPlugin {
38385
38495
  allowDispatch(cmd) {
38386
38496
  switch (cmd.type) {
38387
38497
  case "CUT":
38388
- const zones = cmd.target || this.getters.getSelectedZones();
38498
+ const zones = this.getters.getSelectedZones();
38389
38499
  const state = this.getClipboardState(zones, cmd.type);
38390
38500
  return state.isCutAllowed(zones);
38391
38501
  case "PASTE":
@@ -38416,7 +38526,7 @@ class ClipboardPlugin extends UIPlugin {
38416
38526
  switch (cmd.type) {
38417
38527
  case "COPY":
38418
38528
  case "CUT":
38419
- const zones = ("target" in cmd && cmd.target) || this.getters.getSelectedZones();
38529
+ const zones = this.getters.getSelectedZones();
38420
38530
  this.state = this.getClipboardState(zones, cmd.type);
38421
38531
  this.status = "visible";
38422
38532
  break;
@@ -38847,6 +38957,9 @@ class GridSelectionPlugin extends UIPlugin {
38847
38957
  // ---------------------------------------------------------------------------
38848
38958
  // Getters
38849
38959
  // ---------------------------------------------------------------------------
38960
+ isGridSelectionActive() {
38961
+ return this.selection.isListening(this);
38962
+ }
38850
38963
  getActiveSheet() {
38851
38964
  return this.activeSheet;
38852
38965
  }
@@ -39077,26 +39190,24 @@ class GridSelectionPlugin extends UIPlugin {
39077
39190
  const isBasedBefore = cmd.base < start;
39078
39191
  const deltaCol = isBasedBefore && isCol ? thickness : 0;
39079
39192
  const deltaRow = isBasedBefore && !isCol ? thickness : 0;
39080
- this.dispatch("CUT", {
39081
- target: [
39082
- {
39083
- left: isCol ? start + deltaCol : 0,
39084
- right: isCol ? end + deltaCol : this.getters.getNumberCols(cmd.sheetId) - 1,
39085
- top: !isCol ? start + deltaRow : 0,
39086
- bottom: !isCol ? end + deltaRow : this.getters.getNumberRows(cmd.sheetId) - 1,
39087
- },
39088
- ],
39089
- });
39090
- this.dispatch("PASTE", {
39091
- target: [
39092
- {
39093
- left: isCol ? cmd.base : 0,
39094
- right: isCol ? cmd.base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
39095
- top: !isCol ? cmd.base : 0,
39096
- bottom: !isCol ? cmd.base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
39097
- },
39098
- ],
39099
- });
39193
+ const target = [
39194
+ {
39195
+ left: isCol ? start + deltaCol : 0,
39196
+ right: isCol ? end + deltaCol : this.getters.getNumberCols(cmd.sheetId) - 1,
39197
+ top: !isCol ? start + deltaRow : 0,
39198
+ bottom: !isCol ? end + deltaRow : this.getters.getNumberRows(cmd.sheetId) - 1,
39199
+ },
39200
+ ];
39201
+ const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
39202
+ const pasteTarget = [
39203
+ {
39204
+ left: isCol ? cmd.base : 0,
39205
+ right: isCol ? cmd.base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
39206
+ top: !isCol ? cmd.base : 0,
39207
+ bottom: !isCol ? cmd.base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
39208
+ },
39209
+ ];
39210
+ state.paste(pasteTarget, { selectTarget: true });
39100
39211
  const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
39101
39212
  let currentIndex = cmd.base;
39102
39213
  for (const element of toRemove) {
@@ -39223,6 +39334,7 @@ GridSelectionPlugin.getters = [
39223
39334
  "getSheetPosition",
39224
39335
  "isSelected",
39225
39336
  "getElementsFromSelection",
39337
+ "isGridSelectionActive",
39226
39338
  ];
39227
39339
 
39228
39340
  const corePluginRegistry = new Registry()
@@ -42015,6 +42127,9 @@ class SelectionStreamProcessor {
42015
42127
  anchor: { zone, cell: this.anchor.cell },
42016
42128
  });
42017
42129
  }
42130
+ isListening(owner) {
42131
+ return this.stream.isListening(owner);
42132
+ }
42018
42133
  /**
42019
42134
  * Process a new anchor selection event. If the new anchor is inside
42020
42135
  * the sheet boundaries, the event is pushed to the event stream to
@@ -44273,6 +44388,6 @@ function addFunction(functionName, functionDescription) {
44273
44388
  export { AbstractChart, CommandResult, CorePlugin, DATETIME_FORMAT, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, links, load, parse, readonlyAllowedCommands, registries, setTranslationMethod, tokenize };
44274
44389
 
44275
44390
 
44276
- __info__.version = '16.1.19';
44277
- __info__.date = '2023-08-29T13:54:21.626Z';
44278
- __info__.hash = '053a843';
44391
+ __info__.version = '16.1.23';
44392
+ __info__.date = '2023-10-10T07:27:03.376Z';
44393
+ __info__.hash = '13bfa8f';