@odoo/o-spreadsheet 16.4.6 → 16.4.8

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 {
@@ -5440,6 +5445,9 @@ class FilterMenu extends Component {
5440
5445
  });
5441
5446
  this.state.values = this.getFilterValues(this.props.filterPosition);
5442
5447
  }
5448
+ get isReadonly() {
5449
+ return this.env.model.getters.isReadonly();
5450
+ }
5443
5451
  getFilterValues(position) {
5444
5452
  const sheetId = this.env.model.getters.getActiveSheetId();
5445
5453
  const filter = this.env.model.getters.getFilter({ sheetId, ...position });
@@ -15116,13 +15124,42 @@ function isValidLocale(locale) {
15116
15124
  }
15117
15125
  return true;
15118
15126
  }
15119
- /** Change a content string to its canonical form (en_US locale) */
15127
+ /**
15128
+ * Change a content string from the given locale to its canonical form (en_US locale). Don't convert date string.
15129
+ *
15130
+ * @example
15131
+ * canonicalizeNumberContent("=SUM(1,5; 02/12/2012)", FR_LOCALE) // "=SUM(1.5, 02/12/2012)"
15132
+ * canonicalizeNumberContent("125,9", FR_LOCALE) // "125.9"
15133
+ * canonicalizeNumberContent("02/12/2012", FR_LOCALE) // "02/12/2012"
15134
+ */
15135
+ function canonicalizeNumberContent(content, locale) {
15136
+ return content.startsWith("=")
15137
+ ? canonicalizeFormula$1(content, locale)
15138
+ : canonicalizeNumberLiteral(content, locale);
15139
+ }
15140
+ /**
15141
+ * Change a content string from the given locale to its canonical form (en_US locale). Also convert date string.
15142
+ * This is destructive and won't preserve the original format.
15143
+ *
15144
+ * @example
15145
+ * canonicalizeContent("=SUM(1,5; 5)", FR_LOCALE) // "=SUM(1.5, 5)"
15146
+ * canonicalizeContent("125,9", FR_LOCALE) // "125.9"
15147
+ * canonicalizeContent("02/12/2012", FR_LOCALE) // "12/02/2012"
15148
+ * canonicalizeContent("02-12-2012", FR_LOCALE) // "12/02/2012"
15149
+ */
15120
15150
  function canonicalizeContent(content, locale) {
15121
15151
  return content.startsWith("=")
15122
15152
  ? canonicalizeFormula$1(content, locale)
15123
- : toCanonicalNumberString(content, locale);
15153
+ : canonicalizeLiteral(content, locale);
15124
15154
  }
15125
- /** Change the content of a cell to its canonical form (en_US locale) */
15155
+ /**
15156
+ * Change a content string from its canonical form (en_US locale) to the given locale. Also convert date string.
15157
+ *
15158
+ * @example
15159
+ * localizeContent("=SUM(1.5, 5)", FR_LOCALE) // "=SUM(1,5; 5)"
15160
+ * localizeContent("125.9", FR_LOCALE) // "125,9"
15161
+ * localizeContent("12/02/2012", FR_LOCALE) // "02/12/2012"
15162
+ */
15126
15163
  function localizeContent(content, locale) {
15127
15164
  return content.startsWith("=")
15128
15165
  ? localizeFormula(content, locale)
@@ -15157,24 +15194,75 @@ function _localizeFormula$1(formula, fromLocale, toLocale) {
15157
15194
  return localizedFormula;
15158
15195
  }
15159
15196
  /**
15160
- * Replace localized number with localized decimal separator by a number with "." as decimal separator
15197
+ * Change a literal string from the given locale to its canonical form (en_US locale). Don't convert date string.
15198
+ *
15199
+ * @example
15200
+ * canonicalizeNumberLiteral("125,9", FR_LOCALE) // "125.9"
15201
+ * canonicalizeNumberLiteral("02/12/2012", FR_LOCALE) // "02/12/2012"
15161
15202
  */
15162
- function toCanonicalNumberString(content, locale) {
15203
+ function canonicalizeNumberLiteral(content, locale) {
15163
15204
  if (locale.decimalSeparator === "." || !isNumber(content, locale)) {
15164
15205
  return content;
15165
15206
  }
15166
15207
  return content.replace(locale.decimalSeparator, ".");
15167
15208
  }
15168
- function localizeLiteral(content, locale) {
15169
- if (locale.decimalSeparator === "." || !isNumber(content, DEFAULT_LOCALE)) {
15170
- return content;
15209
+ /**
15210
+ * Change a content string from the given locale to its canonical form (en_US locale). Also convert date string.
15211
+ * This is destructive and won't preserve the original format.
15212
+ *
15213
+ * @example
15214
+ * canonicalizeLiteral("125,9", FR_LOCALE) // "125.9"
15215
+ * canonicalizeLiteral("02/12/2012", FR_LOCALE) // "12/02/2012"
15216
+ * canonicalizeLiteral("02-12-2012", FR_LOCALE) // "12/02/2012"
15217
+ */
15218
+ function canonicalizeLiteral(content, locale) {
15219
+ if (isDateTime(content, locale)) {
15220
+ const dateNumber = toNumber(content, locale);
15221
+ let format = DEFAULT_LOCALE.dateFormat;
15222
+ if (!Number.isInteger(dateNumber)) {
15223
+ format += " " + DEFAULT_LOCALE.timeFormat;
15224
+ }
15225
+ return formatValue(dateNumber, { locale: DEFAULT_LOCALE, format });
15226
+ }
15227
+ return canonicalizeNumberLiteral(content, locale);
15228
+ }
15229
+ /**
15230
+ * Change a literal string from its canonical form (en_US locale) to the given locale. Don't convert date string.
15231
+ * This is destructive and won't preserve the original format.
15232
+ *
15233
+ * @example
15234
+ * localizeNumberLiteral("125.9", FR_LOCALE) // "125,9"
15235
+ * localizeNumberLiteral("12/02/2012", FR_LOCALE) // "12/02/2012"
15236
+ * localizeNumberLiteral("12-02-2012", FR_LOCALE) // "12/02/2012"
15237
+ */
15238
+ function localizeNumberLiteral(literal, locale) {
15239
+ if (locale.decimalSeparator === "." || !isNumber(literal, DEFAULT_LOCALE)) {
15240
+ return literal;
15171
15241
  }
15172
15242
  const decimalNumberRegex = getDecimalNumberRegex(DEFAULT_LOCALE);
15173
- const localized = content.replace(decimalNumberRegex, (match) => {
15243
+ const localized = literal.replace(decimalNumberRegex, (match) => {
15174
15244
  return match.replace(".", locale.decimalSeparator);
15175
15245
  });
15176
15246
  return localized;
15177
15247
  }
15248
+ /**
15249
+ * Change a literal string from its canonical form (en_US locale) to the given locale. Also convert date string.
15250
+ *
15251
+ * @example
15252
+ * localizeLiteral("125.9", FR_LOCALE) // "125,9"
15253
+ * localizeLiteral("12/02/2012", FR_LOCALE) // "02/12/2012"
15254
+ */
15255
+ function localizeLiteral(literal, locale) {
15256
+ if (isDateTime(literal, DEFAULT_LOCALE)) {
15257
+ const dateNumber = toNumber(literal, DEFAULT_LOCALE);
15258
+ let format = locale.dateFormat;
15259
+ if (!Number.isInteger(dateNumber)) {
15260
+ format += " " + locale.timeFormat;
15261
+ }
15262
+ return formatValue(dateNumber, { locale, format });
15263
+ }
15264
+ return localizeNumberLiteral(literal, locale);
15265
+ }
15178
15266
  function canonicalizeCFRule(cf, locale) {
15179
15267
  return changeCFRuleLocale(cf, (content) => canonicalizeContent(content, locale));
15180
15268
  }
@@ -15531,7 +15619,9 @@ class LinkEditor extends Component {
15531
15619
  save() {
15532
15620
  const { col, row } = this.props.cellPosition;
15533
15621
  const locale = this.env.model.getters.getLocale();
15534
- const label = this.link.label ? canonicalizeContent(this.link.label, locale) : this.link.url;
15622
+ const label = this.link.label
15623
+ ? canonicalizeNumberContent(this.link.label, locale)
15624
+ : this.link.url;
15535
15625
  this.env.model.dispatch("UPDATE_CELL", {
15536
15626
  col: col,
15537
15627
  row: row,
@@ -22707,7 +22797,6 @@ class FindAndReplacePanel extends Component {
22707
22797
  state = useState(this.initialState());
22708
22798
  debounceTimeoutId;
22709
22799
  showFormulaState = false;
22710
- debouncedUpdateSearch;
22711
22800
  findAndReplaceRef = useRef("findAndReplace");
22712
22801
  get hasSearchResult() {
22713
22802
  return this.env.model.getters.getCurrentSelectedMatchIndex() !== null;
@@ -22717,9 +22806,9 @@ class FindAndReplacePanel extends Component {
22717
22806
  }
22718
22807
  setup() {
22719
22808
  this.showFormulaState = this.env.model.getters.shouldShowFormulas();
22720
- this.debouncedUpdateSearch = debounce(this.updateSearch.bind(this), 200);
22721
22809
  onMounted(() => this.focusInput());
22722
22810
  onWillUnmount(() => {
22811
+ clearTimeout(this.debounceTimeoutId);
22723
22812
  this.env.model.dispatch("CLEAR_SEARCH");
22724
22813
  this.env.model.dispatch("SET_FORMULA_VISIBILITY", { show: this.showFormulaState });
22725
22814
  });
@@ -22764,6 +22853,13 @@ class FindAndReplacePanel extends Component {
22764
22853
  searchOptions: this.state.searchOptions,
22765
22854
  });
22766
22855
  }
22856
+ debouncedUpdateSearch() {
22857
+ clearTimeout(this.debounceTimeoutId);
22858
+ this.debounceTimeoutId = setTimeout(() => {
22859
+ this.updateSearch();
22860
+ this.debounceTimeoutId = undefined;
22861
+ }, 200);
22862
+ }
22767
22863
  replace() {
22768
22864
  this.env.model.dispatch("REPLACE_SEARCH", {
22769
22865
  replaceWith: this.state.replaceWith,
@@ -25301,9 +25397,11 @@ function useCellHovered(env, gridRef, callback) {
25301
25397
  }
25302
25398
  }
25303
25399
  function updateMousePosition(e) {
25304
- x = e.offsetX;
25305
- y = e.offsetY;
25306
- lastMoved = Date.now();
25400
+ if (gridRef.el === e.target) {
25401
+ x = e.offsetX;
25402
+ y = e.offsetY;
25403
+ lastMoved = Date.now();
25404
+ }
25307
25405
  }
25308
25406
  function recompute() {
25309
25407
  const { col, row } = getPosition();
@@ -36676,8 +36774,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
36676
36774
  if (cell.type === CellValueType.error) {
36677
36775
  return false;
36678
36776
  }
36679
- const locale = this.getters.getLocale();
36680
- const values = rule.values.map((val) => parseLiteral(val, locale));
36777
+ const values = rule.values.map((val) => parseLiteral(val, DEFAULT_LOCALE));
36681
36778
  switch (rule.operator) {
36682
36779
  case "IsEmpty":
36683
36780
  return cell.value.toString().trim() === "";
@@ -38602,14 +38699,10 @@ class FindAndReplacePlugin extends UIPlugin {
38602
38699
  case "REPLACE_ALL_SEARCH":
38603
38700
  this.replaceAll(cmd.replaceWith);
38604
38701
  break;
38605
- case "EVALUATE_CELLS":
38606
- case "UPDATE_CELL":
38607
- case "REMOVE_FILTER_TABLE":
38608
- case "UPDATE_FILTER":
38609
- this.isSearchDirty = true;
38610
- break;
38611
38702
  case "UNDO":
38612
38703
  case "REDO":
38704
+ case "REMOVE_FILTER_TABLE":
38705
+ case "UPDATE_FILTER":
38613
38706
  case "REMOVE_COLUMNS_ROWS":
38614
38707
  case "HIDE_COLUMNS_ROWS":
38615
38708
  case "UNHIDE_COLUMNS_ROWS":
@@ -38761,7 +38854,7 @@ class FindAndReplacePlugin extends UIPlugin {
38761
38854
  const replaceRegex = new RegExp(this.currentSearchRegex.source, this.currentSearchRegex.flags + "g");
38762
38855
  const toReplace = this.getSearchableString({ sheetId, col, row });
38763
38856
  const content = toReplace.replace(replaceRegex, replaceWith);
38764
- const canonicalContent = canonicalizeContent(content, this.getters.getLocale());
38857
+ const canonicalContent = canonicalizeNumberContent(content, this.getters.getLocale());
38765
38858
  this.dispatch("UPDATE_CELL", { sheetId, col, row, content: canonicalContent });
38766
38859
  }
38767
38860
  /**
@@ -40935,7 +41028,7 @@ class SplitToColumnsPlugin extends UIPlugin {
40935
41028
  sheetId,
40936
41029
  col: col + index,
40937
41030
  row,
40938
- content: canonicalizeContent(content, this.getters.getLocale()),
41031
+ content: canonicalizeNumberContent(content, this.getters.getLocale()),
40939
41032
  format: "",
40940
41033
  style: mainCell?.style || null,
40941
41034
  });
@@ -41121,6 +41214,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
41121
41214
  cells;
41122
41215
  copiedTables;
41123
41216
  zones;
41217
+ uuidGenerator = new UuidGenerator();
41124
41218
  constructor(zones, operation, getters, dispatch, selection) {
41125
41219
  super(operation, getters, dispatch, selection);
41126
41220
  if (!zones.length) {
@@ -41269,7 +41363,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
41269
41363
  });
41270
41364
  for (const filterTable of this.copiedTables) {
41271
41365
  this.dispatch("REMOVE_FILTER_TABLE", {
41272
- sheetId: this.getters.getActiveSheetId(),
41366
+ sheetId: this.sheetId,
41273
41367
  target: [filterTable.zone],
41274
41368
  });
41275
41369
  }
@@ -41582,8 +41676,9 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
41582
41676
  this.adaptCFRules(origin.sheetId, cf, [xc], toRemoveRange);
41583
41677
  }
41584
41678
  else {
41585
- this.adaptCFRules(target.sheetId, cf, [xc], []);
41586
41679
  this.adaptCFRules(origin.sheetId, cf, [], toRemoveRange);
41680
+ const cfToCopyTo = this.getCFToCopyTo(target.sheetId, cf);
41681
+ this.adaptCFRules(target.sheetId, cfToCopyTo, [xc], []);
41587
41682
  }
41588
41683
  }
41589
41684
  }
@@ -41607,6 +41702,12 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
41607
41702
  sheetId,
41608
41703
  });
41609
41704
  }
41705
+ getCFToCopyTo(targetSheetId, originCF) {
41706
+ const cfInTarget = this.getters
41707
+ .getConditionalFormats(targetSheetId)
41708
+ .find((cf) => cf.stopIfTrue === originCF.stopIfTrue && deepEquals(cf.rule, originCF.rule));
41709
+ return cfInTarget ? cfInTarget : { ...originCF, id: this.uuidGenerator.uuidv4(), ranges: [] };
41710
+ }
41610
41711
  }
41611
41712
 
41612
41713
  /** State of the clipboard when copying/cutting figures */
@@ -41738,7 +41839,7 @@ class ClipboardFigureImage {
41738
41839
  function canonicalizeNumberValue(content, locale) {
41739
41840
  return content.startsWith("=")
41740
41841
  ? canonicalizeFormula(content, locale)
41741
- : toCanonicalNumberString(content, locale);
41842
+ : canonicalizeNumberLiteral(content, locale);
41742
41843
  }
41743
41844
  /** Change a formula to its canonical form (en_US locale) */
41744
41845
  function canonicalizeFormula(formula, locale) {
@@ -41855,7 +41956,7 @@ class ClipboardPlugin extends UIPlugin {
41855
41956
  allowDispatch(cmd) {
41856
41957
  switch (cmd.type) {
41857
41958
  case "CUT":
41858
- const zones = cmd.cutTarget || this.getters.getSelectedZones();
41959
+ const zones = this.getters.getSelectedZones();
41859
41960
  const state = this.getClipboardState(zones, cmd.type);
41860
41961
  return state.isCutAllowed(zones);
41861
41962
  case "PASTE":
@@ -41890,7 +41991,7 @@ class ClipboardPlugin extends UIPlugin {
41890
41991
  switch (cmd.type) {
41891
41992
  case "COPY":
41892
41993
  case "CUT":
41893
- const zones = ("cutTarget" in cmd && cmd.cutTarget) || this.getters.getSelectedZones();
41994
+ const zones = this.getters.getSelectedZones();
41894
41995
  this.state = this.getClipboardState(zones, cmd.type);
41895
41996
  this.status = "visible";
41896
41997
  this.originSheetId = this.getters.getActiveSheetId();
@@ -42540,7 +42641,7 @@ class EditionPlugin extends UIPlugin {
42540
42641
  if (content) {
42541
42642
  const sheetId = this.getters.getActiveSheetId();
42542
42643
  const cell = this.getters.getEvaluatedCell({ sheetId, col: this.col, row: this.row });
42543
- content = canonicalizeContent(content, this.getters.getLocale());
42644
+ content = canonicalizeNumberContent(content, this.getters.getLocale());
42544
42645
  if (content.startsWith("=")) {
42545
42646
  const left = this.currentTokens.filter((t) => t.type === "LEFT_PAREN").length;
42546
42647
  const right = this.currentTokens.filter((t) => t.type === "RIGHT_PAREN").length;
@@ -43561,26 +43662,24 @@ class GridSelectionPlugin extends UIPlugin {
43561
43662
  const isBasedBefore = cmd.base < start;
43562
43663
  const deltaCol = isBasedBefore && isCol ? thickness : 0;
43563
43664
  const deltaRow = isBasedBefore && !isCol ? thickness : 0;
43564
- this.dispatch("CUT", {
43565
- cutTarget: [
43566
- {
43567
- left: isCol ? start + deltaCol : 0,
43568
- right: isCol ? end + deltaCol : this.getters.getNumberCols(cmd.sheetId) - 1,
43569
- top: !isCol ? start + deltaRow : 0,
43570
- bottom: !isCol ? end + deltaRow : this.getters.getNumberRows(cmd.sheetId) - 1,
43571
- },
43572
- ],
43573
- });
43574
- this.dispatch("PASTE", {
43575
- target: [
43576
- {
43577
- left: isCol ? cmd.base : 0,
43578
- right: isCol ? cmd.base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
43579
- top: !isCol ? cmd.base : 0,
43580
- bottom: !isCol ? cmd.base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
43581
- },
43582
- ],
43583
- });
43665
+ const target = [
43666
+ {
43667
+ left: isCol ? start + deltaCol : 0,
43668
+ right: isCol ? end + deltaCol : this.getters.getNumberCols(cmd.sheetId) - 1,
43669
+ top: !isCol ? start + deltaRow : 0,
43670
+ bottom: !isCol ? end + deltaRow : this.getters.getNumberRows(cmd.sheetId) - 1,
43671
+ },
43672
+ ];
43673
+ const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
43674
+ const pasteTarget = [
43675
+ {
43676
+ left: isCol ? cmd.base : 0,
43677
+ right: isCol ? cmd.base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
43678
+ top: !isCol ? cmd.base : 0,
43679
+ bottom: !isCol ? cmd.base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
43680
+ },
43681
+ ];
43682
+ state.paste(pasteTarget, { selectTarget: true });
43584
43683
  const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
43585
43684
  let currentIndex = cmd.base;
43586
43685
  for (const element of toRemove) {
@@ -43805,30 +43904,26 @@ class InternalViewport {
43805
43904
  const { end } = this.getters.getColDimensions(sheetId, targetCol);
43806
43905
  const maxCol = this.getters.getNumberCols(sheetId);
43807
43906
  if (this.offsetX + this.offsetCorrectionX + this.viewportWidth < end) {
43808
- for (let col = this.left; this.offsetX + this.offsetCorrectionX + this.viewportWidth < end; col++) {
43809
- if (col > maxCol) {
43810
- break;
43811
- }
43812
- if (this.getters.isColHidden(sheetId, col)) {
43813
- continue;
43814
- }
43815
- this.offsetX = this.getters.getColDimensions(sheetId, col).end - this.offsetCorrectionX;
43816
- this.offsetScrollbarX = this.offsetX;
43817
- this.adjustViewportZoneX();
43907
+ let finalTarget = targetCol;
43908
+ while (this.getters.isColHidden(sheetId, finalTarget) && targetCol < maxCol) {
43909
+ finalTarget++;
43818
43910
  }
43911
+ const finalTargetEnd = this.getters.getColDimensions(sheetId, finalTarget).end;
43912
+ const startIndex = this.searchHeaderIndex("COL", finalTargetEnd - this.viewportWidth - this.offsetCorrectionX, this.boundaries.left, true);
43913
+ this.offsetX =
43914
+ this.getters.getColDimensions(sheetId, startIndex).end - this.offsetCorrectionX;
43915
+ this.offsetScrollbarX = this.offsetX;
43916
+ this.adjustViewportZoneX();
43819
43917
  }
43820
43918
  else if (this.left > targetCol) {
43821
- for (let col = this.left; col >= targetCol; col--) {
43822
- if (col < 0) {
43823
- break;
43824
- }
43825
- if (this.getters.isColHidden(sheetId, col)) {
43826
- continue;
43827
- }
43828
- this.offsetX = this.getters.getColDimensions(sheetId, col).start - this.offsetCorrectionX;
43829
- this.offsetScrollbarX = this.offsetX;
43830
- this.adjustViewportZoneX();
43919
+ let finalTarget = targetCol;
43920
+ while (this.getters.isColHidden(sheetId, finalTarget) && targetCol > 0) {
43921
+ finalTarget--;
43831
43922
  }
43923
+ this.offsetX =
43924
+ this.getters.getColDimensions(sheetId, finalTarget).start - this.offsetCorrectionX;
43925
+ this.offsetScrollbarX = this.offsetX;
43926
+ this.adjustViewportZoneX();
43832
43927
  }
43833
43928
  }
43834
43929
  adjustPositionY(targetRow) {
@@ -43836,30 +43931,26 @@ class InternalViewport {
43836
43931
  const { end } = this.getters.getRowDimensions(sheetId, targetRow);
43837
43932
  const maxRow = this.getters.getNumberRows(sheetId);
43838
43933
  if (this.offsetY + this.viewportHeight + this.offsetCorrectionY < end) {
43839
- for (let row = this.top; this.offsetY + this.viewportHeight + this.offsetCorrectionY < end; row++) {
43840
- if (row > maxRow) {
43841
- break;
43842
- }
43843
- if (this.getters.isRowHidden(sheetId, row)) {
43844
- continue;
43845
- }
43846
- this.offsetY = this.getters.getRowDimensions(sheetId, row).end - this.offsetCorrectionY;
43847
- this.offsetScrollbarY = this.offsetY;
43848
- this.adjustViewportZoneY();
43934
+ let finalTarget = targetRow;
43935
+ while (this.getters.isRowHidden(sheetId, finalTarget) && targetRow < maxRow) {
43936
+ finalTarget++;
43849
43937
  }
43938
+ const finalTargetEnd = this.getters.getRowDimensions(sheetId, finalTarget).end;
43939
+ const startIndex = this.searchHeaderIndex("ROW", finalTargetEnd - this.viewportHeight - this.offsetCorrectionY, this.boundaries.top, true);
43940
+ this.offsetY =
43941
+ this.getters.getRowDimensions(sheetId, startIndex).end - this.offsetCorrectionY;
43942
+ this.offsetScrollbarY = this.offsetY;
43943
+ this.adjustViewportZoneY();
43850
43944
  }
43851
43945
  else if (this.top > targetRow) {
43852
- for (let row = this.top; row >= targetRow; row--) {
43853
- if (row < 0) {
43854
- break;
43855
- }
43856
- if (this.getters.isRowHidden(sheetId, row)) {
43857
- continue;
43858
- }
43859
- this.offsetY = this.getters.getRowDimensions(sheetId, row).start - this.offsetCorrectionY;
43860
- this.offsetScrollbarY = this.offsetY;
43861
- this.adjustViewportZoneY();
43946
+ let finalTarget = targetRow;
43947
+ while (this.getters.isRowHidden(sheetId, finalTarget) && targetRow > 0) {
43948
+ finalTarget--;
43862
43949
  }
43950
+ this.offsetY =
43951
+ this.getters.getRowDimensions(sheetId, finalTarget).start - this.offsetCorrectionY;
43952
+ this.offsetScrollbarY = this.offsetY;
43953
+ this.adjustViewportZoneY();
43863
43954
  }
43864
43955
  }
43865
43956
  setViewportOffset(offsetX, offsetY) {
@@ -50566,6 +50657,6 @@ const constants = {
50566
50657
  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 };
50567
50658
 
50568
50659
 
50569
- __info__.version = '16.4.6';
50570
- __info__.date = '2023-09-12T11:43:54.243Z';
50571
- __info__.hash = '5746355';
50660
+ __info__.version = '16.4.8';
50661
+ __info__.date = '2023-10-03T12:45:33.807Z';
50662
+ __info__.hash = 'c614d64';