@odoo/o-spreadsheet 19.0.10 → 19.0.11

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.
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 19.0.10
6
- * @date 2025-11-12T14:15:51.076Z
7
- * @hash 18ac688
5
+ * @version 19.0.11
6
+ * @date 2025-11-24T07:46:47.685Z
7
+ * @hash f5bdbcc
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, useExternalListener, onWillUpdateProps, onWillStart, onWillPatch, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -862,7 +862,7 @@ const PIVOT_TABLE_CONFIG = {
862
862
  };
863
863
  const PIVOT_INDENT = 15;
864
864
  const PIVOT_COLLAPSE_ICON_SIZE = 12;
865
- const PIVOT_MAX_NUMBER_OF_CELLS = 1e5;
865
+ const PIVOT_MAX_NUMBER_OF_CELLS = 5e5;
866
866
  const DEFAULT_CURRENCY = {
867
867
  symbol: "$",
868
868
  position: "before",
@@ -13348,7 +13348,7 @@ const SUBTOTAL = {
13348
13348
  if (!acceptHiddenCells && this.getters.isRowHiddenByUser(sheetId, row))
13349
13349
  continue;
13350
13350
  for (let col = left; col <= right; col++) {
13351
- const cell = this.getters.getCell({ sheetId, col, row });
13351
+ const cell = this.getters.getCorrespondingFormulaCell({ sheetId, col, row });
13352
13352
  if (!cell || !isSubtotalCell(cell)) {
13353
13353
  evaluatedCellToKeep.push(this.getters.getEvaluatedCell({ sheetId, col, row }));
13354
13354
  }
@@ -19344,7 +19344,7 @@ function getTokenNextReferenceType(xc) {
19344
19344
  function setXcToFixedReferenceType(xc, referenceType) {
19345
19345
  let sheetName;
19346
19346
  ({ sheetName, xc } = splitReference(xc));
19347
- sheetName = sheetName ? sheetName + "!" : "";
19347
+ sheetName = sheetName ? getCanonicalSymbolName(sheetName) + "!" : "";
19348
19348
  xc = xc.replace(/\$/g, "");
19349
19349
  const splitIndex = xc.indexOf(":");
19350
19350
  if (splitIndex >= 0) {
@@ -34523,16 +34523,12 @@ class Composer extends Component {
34523
34523
  processTabKey(ev, direction) {
34524
34524
  ev.preventDefault();
34525
34525
  ev.stopPropagation();
34526
- if (!this.assistant.forcedClosed) {
34527
- this.props.composerStore.autoCompleteOrStop(direction);
34528
- }
34526
+ this.props.composerStore.autoCompleteOrStop(direction, this.assistant.forcedClosed);
34529
34527
  }
34530
34528
  processEnterKey(ev, direction) {
34531
34529
  ev.preventDefault();
34532
34530
  ev.stopPropagation();
34533
- if (!this.assistant.forcedClosed) {
34534
- this.props.composerStore.autoCompleteOrStop(direction);
34535
- }
34531
+ this.props.composerStore.autoCompleteOrStop(direction, this.assistant.forcedClosed);
34536
34532
  }
34537
34533
  processNewLineEvent(ev) {
34538
34534
  ev.preventDefault();
@@ -34708,7 +34704,6 @@ class Composer extends Component {
34708
34704
  return;
34709
34705
  }
34710
34706
  const newSelection = this.contentHelper.getCurrentSelection();
34711
- this.props.composerStore.stopComposerRangeSelection();
34712
34707
  const isCurrentlyInactive = this.props.composerStore.editionMode === "inactive";
34713
34708
  this.props.onComposerContentFocused(newSelection);
34714
34709
  if (!isCurrentlyInactive) {
@@ -35199,6 +35194,7 @@ class AbstractComposerStore extends SpreadsheetStore {
35199
35194
  }
35200
35195
  this.selectionStart = start;
35201
35196
  this.selectionEnd = end;
35197
+ this.editionMode = "editing";
35202
35198
  this.computeFormulaCursorContext();
35203
35199
  this.computeParenthesisRelatedToCursor();
35204
35200
  this.updateAutoCompleteProvider();
@@ -35869,10 +35865,13 @@ class AbstractComposerStore extends SpreadsheetStore {
35869
35865
  hideHelp() {
35870
35866
  this.autoComplete.hide();
35871
35867
  }
35872
- autoCompleteOrStop(direction) {
35868
+ autoCompleteOrStop(direction, assistantForcedClosed = false) {
35873
35869
  if (this.editionMode !== "inactive") {
35874
35870
  const autoComplete = this.autoComplete;
35875
- if (autoComplete.provider && autoComplete.selectedIndex !== undefined) {
35871
+ const suppressAutocomplete = assistantForcedClosed && this.canBeToggled;
35872
+ if (!suppressAutocomplete &&
35873
+ autoComplete.provider &&
35874
+ autoComplete.selectedIndex !== undefined) {
35876
35875
  const autoCompleteValue = autoComplete.provider.proposals[autoComplete.selectedIndex]?.text;
35877
35876
  if (autoCompleteValue) {
35878
35877
  this.autoComplete.provider?.selectProposal(autoCompleteValue);
@@ -51563,10 +51562,11 @@ class AbstractResizer extends Component {
51563
51562
  this.state.waitingForMove = false;
51564
51563
  }
51565
51564
  onMouseMove(ev) {
51566
- if (this.env.isMobile()) {
51567
- return;
51568
- }
51569
- if (this.state.isResizing || this.state.isMoving || this.state.isSelecting) {
51565
+ if (this.env.isMobile() ||
51566
+ this.env.model.getters.isReadonly() ||
51567
+ this.state.isResizing ||
51568
+ this.state.isMoving ||
51569
+ this.state.isSelecting) {
51570
51570
  return;
51571
51571
  }
51572
51572
  this._computeHandleDisplay(ev);
@@ -51633,6 +51633,10 @@ class AbstractResizer extends Component {
51633
51633
  if (index < 0) {
51634
51634
  return;
51635
51635
  }
51636
+ if (this.env.model.getters.isReadonly()) {
51637
+ this._selectElement(index, false);
51638
+ return;
51639
+ }
51636
51640
  if (this.state.waitingForMove) {
51637
51641
  if (!this.env.model.getters.isGridSelectionActive()) {
51638
51642
  this._selectElement(index, false);
@@ -52994,7 +52998,7 @@ const friction = 0.95;
52994
52998
  const verticalScrollFactor = 1;
52995
52999
  const horizontalScrollFactor = 1;
52996
53000
  const resetTimeoutDuration = 100;
52997
- function useTouchScroll(ref, updateScroll, canMoveUp) {
53001
+ function useTouchScroll(ref, updateScroll, canMoveUp, canMoveDown) {
52998
53002
  let lastX = 0;
52999
53003
  let lastY = 0;
53000
53004
  let velocityX = 0;
@@ -53031,7 +53035,7 @@ function useTouchScroll(ref, updateScroll, canMoveUp) {
53031
53035
  lastX = clientX;
53032
53036
  lastY = clientY;
53033
53037
  lastTime = currentTime;
53034
- if (canMoveUp()) {
53038
+ if ((deltaY < 0 && canMoveUp()) || (deltaY > 0 && canMoveDown())) {
53035
53039
  if (event.cancelable) {
53036
53040
  event.preventDefault();
53037
53041
  }
@@ -59269,7 +59273,6 @@ function insertTokenAfterArgSeparator(tokenAtCursor, value) {
59269
59273
  // replace the whole token
59270
59274
  start = tokenAtCursor.start;
59271
59275
  }
59272
- this.composer.stopComposerRangeSelection();
59273
59276
  this.composer.changeComposerCursorSelection(start, end);
59274
59277
  this.composer.replaceComposerCursorSelection(value);
59275
59278
  }
@@ -59287,7 +59290,6 @@ function insertTokenAfterLeftParenthesis(tokenAtCursor, value) {
59287
59290
  // replace the whole token
59288
59291
  start = tokenAtCursor.start;
59289
59292
  }
59290
- this.composer.stopComposerRangeSelection();
59291
59293
  this.composer.changeComposerCursorSelection(start, end);
59292
59294
  this.composer.replaceComposerCursorSelection(value);
59293
59295
  }
@@ -60748,6 +60750,7 @@ class SidePanelStore extends SpreadsheetStore {
60748
60750
  getPanelProps(panelInfo) {
60749
60751
  const state = this.computeState(panelInfo);
60750
60752
  if (state.isOpen) {
60753
+ panelInfo.currentPanelProps = state.props ?? panelInfo.currentPanelProps;
60751
60754
  return state.props ?? {};
60752
60755
  }
60753
60756
  return {};
@@ -60759,11 +60762,11 @@ class SidePanelStore extends SpreadsheetStore {
60759
60762
  }
60760
60763
  return undefined;
60761
60764
  }
60762
- open(componentTag, initialPanelProps = {}) {
60765
+ open(componentTag, currentPanelProps = {}) {
60763
60766
  if (this.screenWidthStore.isSmall) {
60764
60767
  return;
60765
60768
  }
60766
- const newPanelInfo = { initialPanelProps, componentTag, size: DEFAULT_SIDE_PANEL_SIZE };
60769
+ const newPanelInfo = { currentPanelProps, componentTag, size: DEFAULT_SIDE_PANEL_SIZE };
60767
60770
  const state = this.computeState(newPanelInfo);
60768
60771
  if (!state.isOpen) {
60769
60772
  return;
@@ -60787,8 +60790,8 @@ class SidePanelStore extends SpreadsheetStore {
60787
60790
  }
60788
60791
  this._openPanel("secondaryPanel", newPanelInfo, state);
60789
60792
  }
60790
- replace(componentTag, currentPanelKey, initialPanelProps = {}) {
60791
- const newPanelInfo = { initialPanelProps, componentTag, size: DEFAULT_SIDE_PANEL_SIZE };
60793
+ replace(componentTag, currentPanelKey, currentPanelProps = {}) {
60794
+ const newPanelInfo = { currentPanelProps, componentTag, size: DEFAULT_SIDE_PANEL_SIZE };
60792
60795
  const state = this.computeState(newPanelInfo);
60793
60796
  if (!state.isOpen) {
60794
60797
  return;
@@ -60818,10 +60821,10 @@ class SidePanelStore extends SpreadsheetStore {
60818
60821
  _openPanel(panel, newPanel, state) {
60819
60822
  const currentPanel = this[panel];
60820
60823
  if (currentPanel && newPanel.componentTag !== currentPanel.componentTag) {
60821
- currentPanel.initialPanelProps?.onCloseSidePanel?.();
60824
+ currentPanel.currentPanelProps?.onCloseSidePanel?.();
60822
60825
  }
60823
60826
  this[panel] = {
60824
- initialPanelProps: state.props ?? {},
60827
+ currentPanelProps: state.props ?? {},
60825
60828
  componentTag: newPanel.componentTag,
60826
60829
  size: currentPanel?.size || DEFAULT_SIDE_PANEL_SIZE,
60827
60830
  isCollapsed: currentPanel?.isCollapsed || false,
@@ -60843,16 +60846,16 @@ class SidePanelStore extends SpreadsheetStore {
60843
60846
  close() {
60844
60847
  if (this.mainPanel?.isPinned) {
60845
60848
  if (this.secondaryPanel) {
60846
- this.secondaryPanel.initialPanelProps.onCloseSidePanel?.();
60849
+ this.secondaryPanel.currentPanelProps.onCloseSidePanel?.();
60847
60850
  this.secondaryPanel = undefined;
60848
60851
  }
60849
60852
  return;
60850
60853
  }
60851
- this.mainPanel?.initialPanelProps.onCloseSidePanel?.();
60854
+ this.mainPanel?.currentPanelProps.onCloseSidePanel?.();
60852
60855
  this.mainPanel = undefined;
60853
60856
  }
60854
60857
  closeMainPanel() {
60855
- this.mainPanel?.initialPanelProps.onCloseSidePanel?.();
60858
+ this.mainPanel?.currentPanelProps.onCloseSidePanel?.();
60856
60859
  this.mainPanel = this.secondaryPanel || undefined;
60857
60860
  this.secondaryPanel = undefined;
60858
60861
  }
@@ -60884,7 +60887,7 @@ class SidePanelStore extends SpreadsheetStore {
60884
60887
  }
60885
60888
  this.mainPanel.isPinned = !this.mainPanel.isPinned;
60886
60889
  if (!this.mainPanel.isPinned && this.secondaryPanel) {
60887
- this.secondaryPanel?.initialPanelProps.onCloseSidePanel?.();
60890
+ this.secondaryPanel?.currentPanelProps.onCloseSidePanel?.();
60888
60891
  this.mainPanel = this.secondaryPanel;
60889
60892
  this.secondaryPanel = undefined;
60890
60893
  }
@@ -60903,7 +60906,7 @@ class SidePanelStore extends SpreadsheetStore {
60903
60906
  panelInfo.size = COLLAPSED_SIDE_PANEL_SIZE;
60904
60907
  }
60905
60908
  }
60906
- computeState({ componentTag, initialPanelProps }) {
60909
+ computeState({ componentTag, currentPanelProps: initialPanelProps, }) {
60907
60910
  const customComputeState = sidePanelRegistry.get(componentTag).computeState;
60908
60911
  const state = customComputeState
60909
60912
  ? customComputeState(this.getters, initialPanelProps)
@@ -60913,7 +60916,7 @@ class SidePanelStore extends SpreadsheetStore {
60913
60916
  changeSpreadsheetWidth(width) {
60914
60917
  this.availableWidth = width - MIN_SHEET_VIEW_WIDTH;
60915
60918
  if (this.secondaryPanel && width - this.totalPanelSize < MIN_SHEET_VIEW_WIDTH) {
60916
- this.secondaryPanel?.initialPanelProps.onCloseSidePanel?.();
60919
+ this.secondaryPanel?.currentPanelProps.onCloseSidePanel?.();
60917
60920
  this.secondaryPanel = undefined;
60918
60921
  }
60919
60922
  if (this.mainPanel && width - this.totalPanelSize < MIN_SHEET_VIEW_WIDTH) {
@@ -61073,6 +61076,10 @@ class Grid extends Component {
61073
61076
  useTouchScroll(this.gridRef, this.moveCanvas.bind(this), () => {
61074
61077
  const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
61075
61078
  return scrollY > 0;
61079
+ }, () => {
61080
+ const { maxOffsetY } = this.env.model.getters.getMaximumSheetOffset();
61081
+ const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
61082
+ return scrollY < maxOffsetY;
61076
61083
  });
61077
61084
  }
61078
61085
  get highlights() {
@@ -62365,22 +62372,34 @@ class BordersPlugin extends CorePlugin {
62365
62372
  addBorder(sheetId, zone, newBorder, force = false) {
62366
62373
  const borders = [];
62367
62374
  const plannedBorder = newBorder ? { zone, style: newBorder } : undefined;
62368
- const sideToClear = {
62369
- left: force || !!newBorder?.left,
62370
- right: force || !!newBorder?.right,
62371
- top: force || !!newBorder?.top,
62372
- bottom: force || !!newBorder?.bottom,
62375
+ // For each side, decide if we must clear the border on the *adjacent*
62376
+ // existing cell when we draw on the opposite side of the new zone.
62377
+ //
62378
+ // Example:
62379
+ // - newBorder.right is set → we draw border on the RIGHT side of `zone`
62380
+ // - the cell on the right may already have a LEFT border on that edge
62381
+ // In that case we clear that LEFT border, so only the new RIGHT border
62382
+ // remains on the shared edge.
62383
+ //
62384
+ // existingBorderSideToClear[side] = true means we should clear the border on that
62385
+ // side of the existing adjacent zone before adding the new border.
62386
+ const existingBorderSideToClear = {
62387
+ left: force || !!newBorder?.right,
62388
+ right: force || !!newBorder?.left,
62389
+ top: force || !!newBorder?.bottom,
62390
+ bottom: force || !!newBorder?.top,
62373
62391
  };
62374
62392
  let editingZone = [zone];
62375
62393
  for (const existingBorder of this.borders[sheetId] ?? []) {
62376
62394
  const inter = intersection(existingBorder.zone, zone);
62377
62395
  if (!inter) {
62378
- // Clear adjacent borders on which you write
62396
+ // Check if the existing border is adjacent to the new zone
62379
62397
  const adjacentEdge = adjacent(existingBorder.zone, zone);
62380
- if (adjacentEdge && sideToClear[adjacentEdge.position]) {
62398
+ if (adjacentEdge && existingBorderSideToClear[adjacentEdge.position]) {
62381
62399
  for (const newZone of splitIfAdjacent(existingBorder.zone, zone)) {
62382
62400
  const border = this.computeBorderFromZone(newZone, existingBorder);
62383
62401
  const adjacentEdge = adjacent(newZone, zone);
62402
+ // Clear the existing border on the side that touches the new zone
62384
62403
  switch (adjacentEdge?.position) {
62385
62404
  case "left":
62386
62405
  border.style.left = undefined;
@@ -78674,6 +78693,7 @@ class SheetViewPlugin extends UIPlugin {
78674
78693
  "getFigureUI",
78675
78694
  "getPositionAnchorOffset",
78676
78695
  "getGridOffset",
78696
+ "getMaximumSheetOffset",
78677
78697
  ];
78678
78698
  viewports = {};
78679
78699
  /**
@@ -81985,6 +82005,10 @@ class SpreadsheetDashboard extends Component {
81985
82005
  useTouchScroll(this.gridRef, this.moveCanvas.bind(this), () => {
81986
82006
  const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
81987
82007
  return scrollY > 0;
82008
+ }, () => {
82009
+ const { maxOffsetY } = this.env.model.getters.getMaximumSheetOffset();
82010
+ const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
82011
+ return scrollY < maxOffsetY;
81988
82012
  });
81989
82013
  }
81990
82014
  get gridContainer() {
@@ -84029,7 +84053,7 @@ css /* scss */ `
84029
84053
  border-radius: 4px;
84030
84054
  font-weight: 500;
84031
84055
  font-size: 14px;
84032
- height: 32px;
84056
+ min-height: 32px;
84033
84057
  line-height: 16px;
84034
84058
  flex-grow: 1;
84035
84059
  background-color: ${BUTTON_BG};
@@ -88932,6 +88956,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
88932
88956
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, ClientDisconnectedError, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, LocalTransportService, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, getCaretDownSvg, getCaretUpSvg, helpers, hooks, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
88933
88957
 
88934
88958
 
88935
- __info__.version = "19.0.10";
88936
- __info__.date = "2025-11-12T14:15:51.076Z";
88937
- __info__.hash = "18ac688";
88959
+ __info__.version = "19.0.11";
88960
+ __info__.date = "2025-11-24T07:46:47.685Z";
88961
+ __info__.hash = "f5bdbcc";
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 19.0.10
6
- * @date 2025-11-12T14:15:51.076Z
7
- * @hash 18ac688
5
+ * @version 19.0.11
6
+ * @date 2025-11-24T07:46:47.685Z
7
+ * @hash f5bdbcc
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -863,7 +863,7 @@
863
863
  };
864
864
  const PIVOT_INDENT = 15;
865
865
  const PIVOT_COLLAPSE_ICON_SIZE = 12;
866
- const PIVOT_MAX_NUMBER_OF_CELLS = 1e5;
866
+ const PIVOT_MAX_NUMBER_OF_CELLS = 5e5;
867
867
  const DEFAULT_CURRENCY = {
868
868
  symbol: "$",
869
869
  position: "before",
@@ -13349,7 +13349,7 @@ stores.inject(MyMetaStore, storeInstance);
13349
13349
  if (!acceptHiddenCells && this.getters.isRowHiddenByUser(sheetId, row))
13350
13350
  continue;
13351
13351
  for (let col = left; col <= right; col++) {
13352
- const cell = this.getters.getCell({ sheetId, col, row });
13352
+ const cell = this.getters.getCorrespondingFormulaCell({ sheetId, col, row });
13353
13353
  if (!cell || !isSubtotalCell(cell)) {
13354
13354
  evaluatedCellToKeep.push(this.getters.getEvaluatedCell({ sheetId, col, row }));
13355
13355
  }
@@ -19345,7 +19345,7 @@ stores.inject(MyMetaStore, storeInstance);
19345
19345
  function setXcToFixedReferenceType(xc, referenceType) {
19346
19346
  let sheetName;
19347
19347
  ({ sheetName, xc } = splitReference(xc));
19348
- sheetName = sheetName ? sheetName + "!" : "";
19348
+ sheetName = sheetName ? getCanonicalSymbolName(sheetName) + "!" : "";
19349
19349
  xc = xc.replace(/\$/g, "");
19350
19350
  const splitIndex = xc.indexOf(":");
19351
19351
  if (splitIndex >= 0) {
@@ -34524,16 +34524,12 @@ stores.inject(MyMetaStore, storeInstance);
34524
34524
  processTabKey(ev, direction) {
34525
34525
  ev.preventDefault();
34526
34526
  ev.stopPropagation();
34527
- if (!this.assistant.forcedClosed) {
34528
- this.props.composerStore.autoCompleteOrStop(direction);
34529
- }
34527
+ this.props.composerStore.autoCompleteOrStop(direction, this.assistant.forcedClosed);
34530
34528
  }
34531
34529
  processEnterKey(ev, direction) {
34532
34530
  ev.preventDefault();
34533
34531
  ev.stopPropagation();
34534
- if (!this.assistant.forcedClosed) {
34535
- this.props.composerStore.autoCompleteOrStop(direction);
34536
- }
34532
+ this.props.composerStore.autoCompleteOrStop(direction, this.assistant.forcedClosed);
34537
34533
  }
34538
34534
  processNewLineEvent(ev) {
34539
34535
  ev.preventDefault();
@@ -34709,7 +34705,6 @@ stores.inject(MyMetaStore, storeInstance);
34709
34705
  return;
34710
34706
  }
34711
34707
  const newSelection = this.contentHelper.getCurrentSelection();
34712
- this.props.composerStore.stopComposerRangeSelection();
34713
34708
  const isCurrentlyInactive = this.props.composerStore.editionMode === "inactive";
34714
34709
  this.props.onComposerContentFocused(newSelection);
34715
34710
  if (!isCurrentlyInactive) {
@@ -35200,6 +35195,7 @@ stores.inject(MyMetaStore, storeInstance);
35200
35195
  }
35201
35196
  this.selectionStart = start;
35202
35197
  this.selectionEnd = end;
35198
+ this.editionMode = "editing";
35203
35199
  this.computeFormulaCursorContext();
35204
35200
  this.computeParenthesisRelatedToCursor();
35205
35201
  this.updateAutoCompleteProvider();
@@ -35870,10 +35866,13 @@ stores.inject(MyMetaStore, storeInstance);
35870
35866
  hideHelp() {
35871
35867
  this.autoComplete.hide();
35872
35868
  }
35873
- autoCompleteOrStop(direction) {
35869
+ autoCompleteOrStop(direction, assistantForcedClosed = false) {
35874
35870
  if (this.editionMode !== "inactive") {
35875
35871
  const autoComplete = this.autoComplete;
35876
- if (autoComplete.provider && autoComplete.selectedIndex !== undefined) {
35872
+ const suppressAutocomplete = assistantForcedClosed && this.canBeToggled;
35873
+ if (!suppressAutocomplete &&
35874
+ autoComplete.provider &&
35875
+ autoComplete.selectedIndex !== undefined) {
35877
35876
  const autoCompleteValue = autoComplete.provider.proposals[autoComplete.selectedIndex]?.text;
35878
35877
  if (autoCompleteValue) {
35879
35878
  this.autoComplete.provider?.selectProposal(autoCompleteValue);
@@ -51564,10 +51563,11 @@ stores.inject(MyMetaStore, storeInstance);
51564
51563
  this.state.waitingForMove = false;
51565
51564
  }
51566
51565
  onMouseMove(ev) {
51567
- if (this.env.isMobile()) {
51568
- return;
51569
- }
51570
- if (this.state.isResizing || this.state.isMoving || this.state.isSelecting) {
51566
+ if (this.env.isMobile() ||
51567
+ this.env.model.getters.isReadonly() ||
51568
+ this.state.isResizing ||
51569
+ this.state.isMoving ||
51570
+ this.state.isSelecting) {
51571
51571
  return;
51572
51572
  }
51573
51573
  this._computeHandleDisplay(ev);
@@ -51634,6 +51634,10 @@ stores.inject(MyMetaStore, storeInstance);
51634
51634
  if (index < 0) {
51635
51635
  return;
51636
51636
  }
51637
+ if (this.env.model.getters.isReadonly()) {
51638
+ this._selectElement(index, false);
51639
+ return;
51640
+ }
51637
51641
  if (this.state.waitingForMove) {
51638
51642
  if (!this.env.model.getters.isGridSelectionActive()) {
51639
51643
  this._selectElement(index, false);
@@ -52995,7 +52999,7 @@ stores.inject(MyMetaStore, storeInstance);
52995
52999
  const verticalScrollFactor = 1;
52996
53000
  const horizontalScrollFactor = 1;
52997
53001
  const resetTimeoutDuration = 100;
52998
- function useTouchScroll(ref, updateScroll, canMoveUp) {
53002
+ function useTouchScroll(ref, updateScroll, canMoveUp, canMoveDown) {
52999
53003
  let lastX = 0;
53000
53004
  let lastY = 0;
53001
53005
  let velocityX = 0;
@@ -53032,7 +53036,7 @@ stores.inject(MyMetaStore, storeInstance);
53032
53036
  lastX = clientX;
53033
53037
  lastY = clientY;
53034
53038
  lastTime = currentTime;
53035
- if (canMoveUp()) {
53039
+ if ((deltaY < 0 && canMoveUp()) || (deltaY > 0 && canMoveDown())) {
53036
53040
  if (event.cancelable) {
53037
53041
  event.preventDefault();
53038
53042
  }
@@ -59270,7 +59274,6 @@ stores.inject(MyMetaStore, storeInstance);
59270
59274
  // replace the whole token
59271
59275
  start = tokenAtCursor.start;
59272
59276
  }
59273
- this.composer.stopComposerRangeSelection();
59274
59277
  this.composer.changeComposerCursorSelection(start, end);
59275
59278
  this.composer.replaceComposerCursorSelection(value);
59276
59279
  }
@@ -59288,7 +59291,6 @@ stores.inject(MyMetaStore, storeInstance);
59288
59291
  // replace the whole token
59289
59292
  start = tokenAtCursor.start;
59290
59293
  }
59291
- this.composer.stopComposerRangeSelection();
59292
59294
  this.composer.changeComposerCursorSelection(start, end);
59293
59295
  this.composer.replaceComposerCursorSelection(value);
59294
59296
  }
@@ -60749,6 +60751,7 @@ stores.inject(MyMetaStore, storeInstance);
60749
60751
  getPanelProps(panelInfo) {
60750
60752
  const state = this.computeState(panelInfo);
60751
60753
  if (state.isOpen) {
60754
+ panelInfo.currentPanelProps = state.props ?? panelInfo.currentPanelProps;
60752
60755
  return state.props ?? {};
60753
60756
  }
60754
60757
  return {};
@@ -60760,11 +60763,11 @@ stores.inject(MyMetaStore, storeInstance);
60760
60763
  }
60761
60764
  return undefined;
60762
60765
  }
60763
- open(componentTag, initialPanelProps = {}) {
60766
+ open(componentTag, currentPanelProps = {}) {
60764
60767
  if (this.screenWidthStore.isSmall) {
60765
60768
  return;
60766
60769
  }
60767
- const newPanelInfo = { initialPanelProps, componentTag, size: DEFAULT_SIDE_PANEL_SIZE };
60770
+ const newPanelInfo = { currentPanelProps, componentTag, size: DEFAULT_SIDE_PANEL_SIZE };
60768
60771
  const state = this.computeState(newPanelInfo);
60769
60772
  if (!state.isOpen) {
60770
60773
  return;
@@ -60788,8 +60791,8 @@ stores.inject(MyMetaStore, storeInstance);
60788
60791
  }
60789
60792
  this._openPanel("secondaryPanel", newPanelInfo, state);
60790
60793
  }
60791
- replace(componentTag, currentPanelKey, initialPanelProps = {}) {
60792
- const newPanelInfo = { initialPanelProps, componentTag, size: DEFAULT_SIDE_PANEL_SIZE };
60794
+ replace(componentTag, currentPanelKey, currentPanelProps = {}) {
60795
+ const newPanelInfo = { currentPanelProps, componentTag, size: DEFAULT_SIDE_PANEL_SIZE };
60793
60796
  const state = this.computeState(newPanelInfo);
60794
60797
  if (!state.isOpen) {
60795
60798
  return;
@@ -60819,10 +60822,10 @@ stores.inject(MyMetaStore, storeInstance);
60819
60822
  _openPanel(panel, newPanel, state) {
60820
60823
  const currentPanel = this[panel];
60821
60824
  if (currentPanel && newPanel.componentTag !== currentPanel.componentTag) {
60822
- currentPanel.initialPanelProps?.onCloseSidePanel?.();
60825
+ currentPanel.currentPanelProps?.onCloseSidePanel?.();
60823
60826
  }
60824
60827
  this[panel] = {
60825
- initialPanelProps: state.props ?? {},
60828
+ currentPanelProps: state.props ?? {},
60826
60829
  componentTag: newPanel.componentTag,
60827
60830
  size: currentPanel?.size || DEFAULT_SIDE_PANEL_SIZE,
60828
60831
  isCollapsed: currentPanel?.isCollapsed || false,
@@ -60844,16 +60847,16 @@ stores.inject(MyMetaStore, storeInstance);
60844
60847
  close() {
60845
60848
  if (this.mainPanel?.isPinned) {
60846
60849
  if (this.secondaryPanel) {
60847
- this.secondaryPanel.initialPanelProps.onCloseSidePanel?.();
60850
+ this.secondaryPanel.currentPanelProps.onCloseSidePanel?.();
60848
60851
  this.secondaryPanel = undefined;
60849
60852
  }
60850
60853
  return;
60851
60854
  }
60852
- this.mainPanel?.initialPanelProps.onCloseSidePanel?.();
60855
+ this.mainPanel?.currentPanelProps.onCloseSidePanel?.();
60853
60856
  this.mainPanel = undefined;
60854
60857
  }
60855
60858
  closeMainPanel() {
60856
- this.mainPanel?.initialPanelProps.onCloseSidePanel?.();
60859
+ this.mainPanel?.currentPanelProps.onCloseSidePanel?.();
60857
60860
  this.mainPanel = this.secondaryPanel || undefined;
60858
60861
  this.secondaryPanel = undefined;
60859
60862
  }
@@ -60885,7 +60888,7 @@ stores.inject(MyMetaStore, storeInstance);
60885
60888
  }
60886
60889
  this.mainPanel.isPinned = !this.mainPanel.isPinned;
60887
60890
  if (!this.mainPanel.isPinned && this.secondaryPanel) {
60888
- this.secondaryPanel?.initialPanelProps.onCloseSidePanel?.();
60891
+ this.secondaryPanel?.currentPanelProps.onCloseSidePanel?.();
60889
60892
  this.mainPanel = this.secondaryPanel;
60890
60893
  this.secondaryPanel = undefined;
60891
60894
  }
@@ -60904,7 +60907,7 @@ stores.inject(MyMetaStore, storeInstance);
60904
60907
  panelInfo.size = COLLAPSED_SIDE_PANEL_SIZE;
60905
60908
  }
60906
60909
  }
60907
- computeState({ componentTag, initialPanelProps }) {
60910
+ computeState({ componentTag, currentPanelProps: initialPanelProps, }) {
60908
60911
  const customComputeState = sidePanelRegistry.get(componentTag).computeState;
60909
60912
  const state = customComputeState
60910
60913
  ? customComputeState(this.getters, initialPanelProps)
@@ -60914,7 +60917,7 @@ stores.inject(MyMetaStore, storeInstance);
60914
60917
  changeSpreadsheetWidth(width) {
60915
60918
  this.availableWidth = width - MIN_SHEET_VIEW_WIDTH;
60916
60919
  if (this.secondaryPanel && width - this.totalPanelSize < MIN_SHEET_VIEW_WIDTH) {
60917
- this.secondaryPanel?.initialPanelProps.onCloseSidePanel?.();
60920
+ this.secondaryPanel?.currentPanelProps.onCloseSidePanel?.();
60918
60921
  this.secondaryPanel = undefined;
60919
60922
  }
60920
60923
  if (this.mainPanel && width - this.totalPanelSize < MIN_SHEET_VIEW_WIDTH) {
@@ -61074,6 +61077,10 @@ stores.inject(MyMetaStore, storeInstance);
61074
61077
  useTouchScroll(this.gridRef, this.moveCanvas.bind(this), () => {
61075
61078
  const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
61076
61079
  return scrollY > 0;
61080
+ }, () => {
61081
+ const { maxOffsetY } = this.env.model.getters.getMaximumSheetOffset();
61082
+ const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
61083
+ return scrollY < maxOffsetY;
61077
61084
  });
61078
61085
  }
61079
61086
  get highlights() {
@@ -62366,22 +62373,34 @@ stores.inject(MyMetaStore, storeInstance);
62366
62373
  addBorder(sheetId, zone, newBorder, force = false) {
62367
62374
  const borders = [];
62368
62375
  const plannedBorder = newBorder ? { zone, style: newBorder } : undefined;
62369
- const sideToClear = {
62370
- left: force || !!newBorder?.left,
62371
- right: force || !!newBorder?.right,
62372
- top: force || !!newBorder?.top,
62373
- bottom: force || !!newBorder?.bottom,
62376
+ // For each side, decide if we must clear the border on the *adjacent*
62377
+ // existing cell when we draw on the opposite side of the new zone.
62378
+ //
62379
+ // Example:
62380
+ // - newBorder.right is set → we draw border on the RIGHT side of `zone`
62381
+ // - the cell on the right may already have a LEFT border on that edge
62382
+ // In that case we clear that LEFT border, so only the new RIGHT border
62383
+ // remains on the shared edge.
62384
+ //
62385
+ // existingBorderSideToClear[side] = true means we should clear the border on that
62386
+ // side of the existing adjacent zone before adding the new border.
62387
+ const existingBorderSideToClear = {
62388
+ left: force || !!newBorder?.right,
62389
+ right: force || !!newBorder?.left,
62390
+ top: force || !!newBorder?.bottom,
62391
+ bottom: force || !!newBorder?.top,
62374
62392
  };
62375
62393
  let editingZone = [zone];
62376
62394
  for (const existingBorder of this.borders[sheetId] ?? []) {
62377
62395
  const inter = intersection(existingBorder.zone, zone);
62378
62396
  if (!inter) {
62379
- // Clear adjacent borders on which you write
62397
+ // Check if the existing border is adjacent to the new zone
62380
62398
  const adjacentEdge = adjacent(existingBorder.zone, zone);
62381
- if (adjacentEdge && sideToClear[adjacentEdge.position]) {
62399
+ if (adjacentEdge && existingBorderSideToClear[adjacentEdge.position]) {
62382
62400
  for (const newZone of splitIfAdjacent(existingBorder.zone, zone)) {
62383
62401
  const border = this.computeBorderFromZone(newZone, existingBorder);
62384
62402
  const adjacentEdge = adjacent(newZone, zone);
62403
+ // Clear the existing border on the side that touches the new zone
62385
62404
  switch (adjacentEdge?.position) {
62386
62405
  case "left":
62387
62406
  border.style.left = undefined;
@@ -78675,6 +78694,7 @@ stores.inject(MyMetaStore, storeInstance);
78675
78694
  "getFigureUI",
78676
78695
  "getPositionAnchorOffset",
78677
78696
  "getGridOffset",
78697
+ "getMaximumSheetOffset",
78678
78698
  ];
78679
78699
  viewports = {};
78680
78700
  /**
@@ -81986,6 +82006,10 @@ stores.inject(MyMetaStore, storeInstance);
81986
82006
  useTouchScroll(this.gridRef, this.moveCanvas.bind(this), () => {
81987
82007
  const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
81988
82008
  return scrollY > 0;
82009
+ }, () => {
82010
+ const { maxOffsetY } = this.env.model.getters.getMaximumSheetOffset();
82011
+ const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
82012
+ return scrollY < maxOffsetY;
81989
82013
  });
81990
82014
  }
81991
82015
  get gridContainer() {
@@ -84030,7 +84054,7 @@ stores.inject(MyMetaStore, storeInstance);
84030
84054
  border-radius: 4px;
84031
84055
  font-weight: 500;
84032
84056
  font-size: 14px;
84033
- height: 32px;
84057
+ min-height: 32px;
84034
84058
  line-height: 16px;
84035
84059
  flex-grow: 1;
84036
84060
  background-color: ${BUTTON_BG};
@@ -88983,9 +89007,9 @@ stores.inject(MyMetaStore, storeInstance);
88983
89007
  exports.tokenize = tokenize;
88984
89008
 
88985
89009
 
88986
- __info__.version = "19.0.10";
88987
- __info__.date = "2025-11-12T14:15:51.076Z";
88988
- __info__.hash = "18ac688";
89010
+ __info__.version = "19.0.11";
89011
+ __info__.date = "2025-11-24T07:46:47.685Z";
89012
+ __info__.hash = "f5bdbcc";
88989
89013
 
88990
89014
 
88991
89015
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);