@odoo/o-spreadsheet 19.0.9 → 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.9
6
- * @date 2025-11-03T12:32:15.473Z
7
- * @hash 10359f4
5
+ * @version 19.0.11
6
+ * @date 2025-11-24T07:46:47.685Z
7
+ * @hash f5bdbcc
8
8
  */
9
9
 
10
10
  'use strict';
@@ -864,7 +864,7 @@ const PIVOT_TABLE_CONFIG = {
864
864
  };
865
865
  const PIVOT_INDENT = 15;
866
866
  const PIVOT_COLLAPSE_ICON_SIZE = 12;
867
- const PIVOT_MAX_NUMBER_OF_CELLS = 1e5;
867
+ const PIVOT_MAX_NUMBER_OF_CELLS = 5e5;
868
868
  const DEFAULT_CURRENCY = {
869
869
  symbol: "$",
870
870
  position: "before",
@@ -2501,7 +2501,10 @@ function isInside(col, row, zone) {
2501
2501
  * Check if a zone is inside another
2502
2502
  */
2503
2503
  function isZoneInside(smallZone, biggerZone) {
2504
- return isEqual(union(biggerZone, smallZone), biggerZone);
2504
+ return (smallZone.left >= biggerZone.left &&
2505
+ smallZone.right <= biggerZone.right &&
2506
+ smallZone.top >= biggerZone.top &&
2507
+ smallZone.bottom <= biggerZone.bottom);
2505
2508
  }
2506
2509
  function zoneToDimension(zone) {
2507
2510
  return {
@@ -6904,7 +6907,7 @@ function getRangeString(range, forSheetId, getSheetName, options = { useBoundedR
6904
6907
  let sheetName = "";
6905
6908
  if (prefixSheet) {
6906
6909
  if (range.invalidSheetName) {
6907
- sheetName = range.invalidSheetName;
6910
+ sheetName = getCanonicalSymbolName(range.invalidSheetName);
6908
6911
  }
6909
6912
  else {
6910
6913
  sheetName = getCanonicalSymbolName(getSheetName(range.sheetId));
@@ -13347,7 +13350,7 @@ const SUBTOTAL = {
13347
13350
  if (!acceptHiddenCells && this.getters.isRowHiddenByUser(sheetId, row))
13348
13351
  continue;
13349
13352
  for (let col = left; col <= right; col++) {
13350
- const cell = this.getters.getCell({ sheetId, col, row });
13353
+ const cell = this.getters.getCorrespondingFormulaCell({ sheetId, col, row });
13351
13354
  if (!cell || !isSubtotalCell(cell)) {
13352
13355
  evaluatedCellToKeep.push(this.getters.getEvaluatedCell({ sheetId, col, row }));
13353
13356
  }
@@ -19343,7 +19346,7 @@ function getTokenNextReferenceType(xc) {
19343
19346
  function setXcToFixedReferenceType(xc, referenceType) {
19344
19347
  let sheetName;
19345
19348
  ({ sheetName, xc } = splitReference(xc));
19346
- sheetName = sheetName ? sheetName + "!" : "";
19349
+ sheetName = sheetName ? getCanonicalSymbolName(sheetName) + "!" : "";
19347
19350
  xc = xc.replace(/\$/g, "");
19348
19351
  const splitIndex = xc.indexOf(":");
19349
19352
  if (splitIndex >= 0) {
@@ -24420,7 +24423,7 @@ let ScorecardChart$1 = class ScorecardChart extends AbstractChart {
24420
24423
  return {
24421
24424
  background: context.background,
24422
24425
  type: "scorecard",
24423
- keyValue: context.range ? context.range[0].dataRange : undefined,
24426
+ keyValue: context.range?.[0]?.dataRange,
24424
24427
  title: context.title || { text: "" },
24425
24428
  baselineMode: DEFAULT_SCORECARD_BASELINE_MODE,
24426
24429
  baselineColorUp: DEFAULT_SCORECARD_BASELINE_COLOR_UP,
@@ -29129,7 +29132,7 @@ class GaugeChart extends AbstractChart {
29129
29132
  background: context.background,
29130
29133
  title: context.title || { text: "" },
29131
29134
  type: "gauge",
29132
- dataRange: context.range ? context.range[0].dataRange : undefined,
29135
+ dataRange: context.range?.[0]?.dataRange,
29133
29136
  sectionRule: {
29134
29137
  colors: {
29135
29138
  lowerColor: DEFAULT_GAUGE_LOWER_COLOR,
@@ -31021,8 +31024,7 @@ function generateMasterChartConfig(chartJsConfig) {
31021
31024
  .filter((ds) => !isTrendLineAxis(ds["xAxisID"]))
31022
31025
  .map((ds) => ({
31023
31026
  ...ds,
31024
- pointRadius: 0,
31025
- showLine: true,
31027
+ pointRadius: ds.showLine === false ? 2 : 0, // Show points only for scatter plots
31026
31028
  })),
31027
31029
  },
31028
31030
  options: {
@@ -34523,16 +34525,12 @@ class Composer extends owl.Component {
34523
34525
  processTabKey(ev, direction) {
34524
34526
  ev.preventDefault();
34525
34527
  ev.stopPropagation();
34526
- if (!this.assistant.forcedClosed) {
34527
- this.props.composerStore.autoCompleteOrStop(direction);
34528
- }
34528
+ this.props.composerStore.autoCompleteOrStop(direction, this.assistant.forcedClosed);
34529
34529
  }
34530
34530
  processEnterKey(ev, direction) {
34531
34531
  ev.preventDefault();
34532
34532
  ev.stopPropagation();
34533
- if (!this.assistant.forcedClosed) {
34534
- this.props.composerStore.autoCompleteOrStop(direction);
34535
- }
34533
+ this.props.composerStore.autoCompleteOrStop(direction, this.assistant.forcedClosed);
34536
34534
  }
34537
34535
  processNewLineEvent(ev) {
34538
34536
  ev.preventDefault();
@@ -34708,7 +34706,6 @@ class Composer extends owl.Component {
34708
34706
  return;
34709
34707
  }
34710
34708
  const newSelection = this.contentHelper.getCurrentSelection();
34711
- this.props.composerStore.stopComposerRangeSelection();
34712
34709
  const isCurrentlyInactive = this.props.composerStore.editionMode === "inactive";
34713
34710
  this.props.onComposerContentFocused(newSelection);
34714
34711
  if (!isCurrentlyInactive) {
@@ -35164,6 +35161,7 @@ class AbstractComposerStore extends SpreadsheetStore {
35164
35161
  this.highlightStore.register(this);
35165
35162
  this.onDispose(() => {
35166
35163
  this.highlightStore.unRegister(this);
35164
+ this._cancelEdition();
35167
35165
  });
35168
35166
  }
35169
35167
  handleEvent(event) {
@@ -35198,6 +35196,7 @@ class AbstractComposerStore extends SpreadsheetStore {
35198
35196
  }
35199
35197
  this.selectionStart = start;
35200
35198
  this.selectionEnd = end;
35199
+ this.editionMode = "editing";
35201
35200
  this.computeFormulaCursorContext();
35202
35201
  this.computeParenthesisRelatedToCursor();
35203
35202
  this.updateAutoCompleteProvider();
@@ -35868,10 +35867,13 @@ class AbstractComposerStore extends SpreadsheetStore {
35868
35867
  hideHelp() {
35869
35868
  this.autoComplete.hide();
35870
35869
  }
35871
- autoCompleteOrStop(direction) {
35870
+ autoCompleteOrStop(direction, assistantForcedClosed = false) {
35872
35871
  if (this.editionMode !== "inactive") {
35873
35872
  const autoComplete = this.autoComplete;
35874
- if (autoComplete.provider && autoComplete.selectedIndex !== undefined) {
35873
+ const suppressAutocomplete = assistantForcedClosed && this.canBeToggled;
35874
+ if (!suppressAutocomplete &&
35875
+ autoComplete.provider &&
35876
+ autoComplete.selectedIndex !== undefined) {
35875
35877
  const autoCompleteValue = autoComplete.provider.proposals[autoComplete.selectedIndex]?.text;
35876
35878
  if (autoCompleteValue) {
35877
35879
  this.autoComplete.provider?.selectProposal(autoCompleteValue);
@@ -51562,10 +51564,11 @@ class AbstractResizer extends owl.Component {
51562
51564
  this.state.waitingForMove = false;
51563
51565
  }
51564
51566
  onMouseMove(ev) {
51565
- if (this.env.isMobile()) {
51566
- return;
51567
- }
51568
- if (this.state.isResizing || this.state.isMoving || this.state.isSelecting) {
51567
+ if (this.env.isMobile() ||
51568
+ this.env.model.getters.isReadonly() ||
51569
+ this.state.isResizing ||
51570
+ this.state.isMoving ||
51571
+ this.state.isSelecting) {
51569
51572
  return;
51570
51573
  }
51571
51574
  this._computeHandleDisplay(ev);
@@ -51632,6 +51635,10 @@ class AbstractResizer extends owl.Component {
51632
51635
  if (index < 0) {
51633
51636
  return;
51634
51637
  }
51638
+ if (this.env.model.getters.isReadonly()) {
51639
+ this._selectElement(index, false);
51640
+ return;
51641
+ }
51635
51642
  if (this.state.waitingForMove) {
51636
51643
  if (!this.env.model.getters.isGridSelectionActive()) {
51637
51644
  this._selectElement(index, false);
@@ -52191,6 +52198,9 @@ class GridRenderer extends SpreadsheetStore {
52191
52198
  break;
52192
52199
  }
52193
52200
  }
52201
+ finalize() {
52202
+ this.zonesWithPreventedAnimationsInNextFrame = recomputeZones(this.zonesWithPreventedAnimationsInNextFrame);
52203
+ }
52194
52204
  get renderingLayers() {
52195
52205
  return ["Background", "Headers"];
52196
52206
  }
@@ -52990,7 +53000,7 @@ const friction = 0.95;
52990
53000
  const verticalScrollFactor = 1;
52991
53001
  const horizontalScrollFactor = 1;
52992
53002
  const resetTimeoutDuration = 100;
52993
- function useTouchScroll(ref, updateScroll, canMoveUp) {
53003
+ function useTouchScroll(ref, updateScroll, canMoveUp, canMoveDown) {
52994
53004
  let lastX = 0;
52995
53005
  let lastY = 0;
52996
53006
  let velocityX = 0;
@@ -53027,7 +53037,7 @@ function useTouchScroll(ref, updateScroll, canMoveUp) {
53027
53037
  lastX = clientX;
53028
53038
  lastY = clientY;
53029
53039
  lastTime = currentTime;
53030
- if (canMoveUp()) {
53040
+ if ((deltaY < 0 && canMoveUp()) || (deltaY > 0 && canMoveDown())) {
53031
53041
  if (event.cancelable) {
53032
53042
  event.preventDefault();
53033
53043
  }
@@ -59265,7 +59275,6 @@ function insertTokenAfterArgSeparator(tokenAtCursor, value) {
59265
59275
  // replace the whole token
59266
59276
  start = tokenAtCursor.start;
59267
59277
  }
59268
- this.composer.stopComposerRangeSelection();
59269
59278
  this.composer.changeComposerCursorSelection(start, end);
59270
59279
  this.composer.replaceComposerCursorSelection(value);
59271
59280
  }
@@ -59283,7 +59292,6 @@ function insertTokenAfterLeftParenthesis(tokenAtCursor, value) {
59283
59292
  // replace the whole token
59284
59293
  start = tokenAtCursor.start;
59285
59294
  }
59286
- this.composer.stopComposerRangeSelection();
59287
59295
  this.composer.changeComposerCursorSelection(start, end);
59288
59296
  this.composer.replaceComposerCursorSelection(value);
59289
59297
  }
@@ -60744,6 +60752,7 @@ class SidePanelStore extends SpreadsheetStore {
60744
60752
  getPanelProps(panelInfo) {
60745
60753
  const state = this.computeState(panelInfo);
60746
60754
  if (state.isOpen) {
60755
+ panelInfo.currentPanelProps = state.props ?? panelInfo.currentPanelProps;
60747
60756
  return state.props ?? {};
60748
60757
  }
60749
60758
  return {};
@@ -60755,11 +60764,11 @@ class SidePanelStore extends SpreadsheetStore {
60755
60764
  }
60756
60765
  return undefined;
60757
60766
  }
60758
- open(componentTag, initialPanelProps = {}) {
60767
+ open(componentTag, currentPanelProps = {}) {
60759
60768
  if (this.screenWidthStore.isSmall) {
60760
60769
  return;
60761
60770
  }
60762
- const newPanelInfo = { initialPanelProps, componentTag, size: DEFAULT_SIDE_PANEL_SIZE };
60771
+ const newPanelInfo = { currentPanelProps, componentTag, size: DEFAULT_SIDE_PANEL_SIZE };
60763
60772
  const state = this.computeState(newPanelInfo);
60764
60773
  if (!state.isOpen) {
60765
60774
  return;
@@ -60783,8 +60792,8 @@ class SidePanelStore extends SpreadsheetStore {
60783
60792
  }
60784
60793
  this._openPanel("secondaryPanel", newPanelInfo, state);
60785
60794
  }
60786
- replace(componentTag, currentPanelKey, initialPanelProps = {}) {
60787
- const newPanelInfo = { initialPanelProps, componentTag, size: DEFAULT_SIDE_PANEL_SIZE };
60795
+ replace(componentTag, currentPanelKey, currentPanelProps = {}) {
60796
+ const newPanelInfo = { currentPanelProps, componentTag, size: DEFAULT_SIDE_PANEL_SIZE };
60788
60797
  const state = this.computeState(newPanelInfo);
60789
60798
  if (!state.isOpen) {
60790
60799
  return;
@@ -60814,10 +60823,10 @@ class SidePanelStore extends SpreadsheetStore {
60814
60823
  _openPanel(panel, newPanel, state) {
60815
60824
  const currentPanel = this[panel];
60816
60825
  if (currentPanel && newPanel.componentTag !== currentPanel.componentTag) {
60817
- currentPanel.initialPanelProps?.onCloseSidePanel?.();
60826
+ currentPanel.currentPanelProps?.onCloseSidePanel?.();
60818
60827
  }
60819
60828
  this[panel] = {
60820
- initialPanelProps: state.props ?? {},
60829
+ currentPanelProps: state.props ?? {},
60821
60830
  componentTag: newPanel.componentTag,
60822
60831
  size: currentPanel?.size || DEFAULT_SIDE_PANEL_SIZE,
60823
60832
  isCollapsed: currentPanel?.isCollapsed || false,
@@ -60839,16 +60848,16 @@ class SidePanelStore extends SpreadsheetStore {
60839
60848
  close() {
60840
60849
  if (this.mainPanel?.isPinned) {
60841
60850
  if (this.secondaryPanel) {
60842
- this.secondaryPanel.initialPanelProps.onCloseSidePanel?.();
60851
+ this.secondaryPanel.currentPanelProps.onCloseSidePanel?.();
60843
60852
  this.secondaryPanel = undefined;
60844
60853
  }
60845
60854
  return;
60846
60855
  }
60847
- this.mainPanel?.initialPanelProps.onCloseSidePanel?.();
60856
+ this.mainPanel?.currentPanelProps.onCloseSidePanel?.();
60848
60857
  this.mainPanel = undefined;
60849
60858
  }
60850
60859
  closeMainPanel() {
60851
- this.mainPanel?.initialPanelProps.onCloseSidePanel?.();
60860
+ this.mainPanel?.currentPanelProps.onCloseSidePanel?.();
60852
60861
  this.mainPanel = this.secondaryPanel || undefined;
60853
60862
  this.secondaryPanel = undefined;
60854
60863
  }
@@ -60880,7 +60889,7 @@ class SidePanelStore extends SpreadsheetStore {
60880
60889
  }
60881
60890
  this.mainPanel.isPinned = !this.mainPanel.isPinned;
60882
60891
  if (!this.mainPanel.isPinned && this.secondaryPanel) {
60883
- this.secondaryPanel?.initialPanelProps.onCloseSidePanel?.();
60892
+ this.secondaryPanel?.currentPanelProps.onCloseSidePanel?.();
60884
60893
  this.mainPanel = this.secondaryPanel;
60885
60894
  this.secondaryPanel = undefined;
60886
60895
  }
@@ -60899,7 +60908,7 @@ class SidePanelStore extends SpreadsheetStore {
60899
60908
  panelInfo.size = COLLAPSED_SIDE_PANEL_SIZE;
60900
60909
  }
60901
60910
  }
60902
- computeState({ componentTag, initialPanelProps }) {
60911
+ computeState({ componentTag, currentPanelProps: initialPanelProps, }) {
60903
60912
  const customComputeState = sidePanelRegistry.get(componentTag).computeState;
60904
60913
  const state = customComputeState
60905
60914
  ? customComputeState(this.getters, initialPanelProps)
@@ -60909,7 +60918,7 @@ class SidePanelStore extends SpreadsheetStore {
60909
60918
  changeSpreadsheetWidth(width) {
60910
60919
  this.availableWidth = width - MIN_SHEET_VIEW_WIDTH;
60911
60920
  if (this.secondaryPanel && width - this.totalPanelSize < MIN_SHEET_VIEW_WIDTH) {
60912
- this.secondaryPanel?.initialPanelProps.onCloseSidePanel?.();
60921
+ this.secondaryPanel?.currentPanelProps.onCloseSidePanel?.();
60913
60922
  this.secondaryPanel = undefined;
60914
60923
  }
60915
60924
  if (this.mainPanel && width - this.totalPanelSize < MIN_SHEET_VIEW_WIDTH) {
@@ -61069,6 +61078,10 @@ class Grid extends owl.Component {
61069
61078
  useTouchScroll(this.gridRef, this.moveCanvas.bind(this), () => {
61070
61079
  const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
61071
61080
  return scrollY > 0;
61081
+ }, () => {
61082
+ const { maxOffsetY } = this.env.model.getters.getMaximumSheetOffset();
61083
+ const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
61084
+ return scrollY < maxOffsetY;
61072
61085
  });
61073
61086
  }
61074
61087
  get highlights() {
@@ -62361,22 +62374,34 @@ class BordersPlugin extends CorePlugin {
62361
62374
  addBorder(sheetId, zone, newBorder, force = false) {
62362
62375
  const borders = [];
62363
62376
  const plannedBorder = newBorder ? { zone, style: newBorder } : undefined;
62364
- const sideToClear = {
62365
- left: force || !!newBorder?.left,
62366
- right: force || !!newBorder?.right,
62367
- top: force || !!newBorder?.top,
62368
- bottom: force || !!newBorder?.bottom,
62377
+ // For each side, decide if we must clear the border on the *adjacent*
62378
+ // existing cell when we draw on the opposite side of the new zone.
62379
+ //
62380
+ // Example:
62381
+ // - newBorder.right is set → we draw border on the RIGHT side of `zone`
62382
+ // - the cell on the right may already have a LEFT border on that edge
62383
+ // In that case we clear that LEFT border, so only the new RIGHT border
62384
+ // remains on the shared edge.
62385
+ //
62386
+ // existingBorderSideToClear[side] = true means we should clear the border on that
62387
+ // side of the existing adjacent zone before adding the new border.
62388
+ const existingBorderSideToClear = {
62389
+ left: force || !!newBorder?.right,
62390
+ right: force || !!newBorder?.left,
62391
+ top: force || !!newBorder?.bottom,
62392
+ bottom: force || !!newBorder?.top,
62369
62393
  };
62370
62394
  let editingZone = [zone];
62371
62395
  for (const existingBorder of this.borders[sheetId] ?? []) {
62372
62396
  const inter = intersection(existingBorder.zone, zone);
62373
62397
  if (!inter) {
62374
- // Clear adjacent borders on which you write
62398
+ // Check if the existing border is adjacent to the new zone
62375
62399
  const adjacentEdge = adjacent(existingBorder.zone, zone);
62376
- if (adjacentEdge && sideToClear[adjacentEdge.position]) {
62400
+ if (adjacentEdge && existingBorderSideToClear[adjacentEdge.position]) {
62377
62401
  for (const newZone of splitIfAdjacent(existingBorder.zone, zone)) {
62378
62402
  const border = this.computeBorderFromZone(newZone, existingBorder);
62379
62403
  const adjacentEdge = adjacent(newZone, zone);
62404
+ // Clear the existing border on the side that touches the new zone
62380
62405
  switch (adjacentEdge?.position) {
62381
62406
  case "left":
62382
62407
  border.style.left = undefined;
@@ -78670,6 +78695,7 @@ class SheetViewPlugin extends UIPlugin {
78670
78695
  "getFigureUI",
78671
78696
  "getPositionAnchorOffset",
78672
78697
  "getGridOffset",
78698
+ "getMaximumSheetOffset",
78673
78699
  ];
78674
78700
  viewports = {};
78675
78701
  /**
@@ -80488,6 +80514,7 @@ topbarMenuRegistry
80488
80514
  .add("file", {
80489
80515
  name: _t("File"),
80490
80516
  sequence: 10,
80517
+ isReadonlyAllowed: true,
80491
80518
  })
80492
80519
  .addChild("settings", ["file"], {
80493
80520
  name: _t("Settings"),
@@ -80502,6 +80529,7 @@ topbarMenuRegistry
80502
80529
  .add("edit", {
80503
80530
  name: _t("Edit"),
80504
80531
  sequence: 20,
80532
+ isReadonlyAllowed: true,
80505
80533
  })
80506
80534
  .addChild("undo", ["edit"], {
80507
80535
  ...undo,
@@ -80586,6 +80614,7 @@ topbarMenuRegistry
80586
80614
  .add("view", {
80587
80615
  name: _t("View"),
80588
80616
  sequence: 30,
80617
+ isReadonlyAllowed: true,
80589
80618
  })
80590
80619
  .addChild("unfreeze_panes", ["view"], {
80591
80620
  ...unFreezePane,
@@ -80677,6 +80706,7 @@ topbarMenuRegistry
80677
80706
  .add("insert", {
80678
80707
  name: _t("Insert"),
80679
80708
  sequence: 40,
80709
+ isReadonlyAllowed: true,
80680
80710
  })
80681
80711
  .addChild("insert_row", ["insert"], {
80682
80712
  ...insertRow,
@@ -80788,7 +80818,11 @@ topbarMenuRegistry
80788
80818
  // ---------------------------------------------------------------------
80789
80819
  // FORMAT MENU ITEMS
80790
80820
  // ---------------------------------------------------------------------
80791
- .add("format", { name: _t("Format"), sequence: 50 })
80821
+ .add("format", {
80822
+ name: _t("Format"),
80823
+ sequence: 50,
80824
+ isReadonlyAllowed: true,
80825
+ })
80792
80826
  .addChild("format_number", ["format"], {
80793
80827
  ...formatNumberMenuItemSpec,
80794
80828
  name: _t("Number"),
@@ -80880,6 +80914,7 @@ topbarMenuRegistry
80880
80914
  .add("data", {
80881
80915
  name: _t("Data"),
80882
80916
  sequence: 60,
80917
+ isReadonlyAllowed: true,
80883
80918
  })
80884
80919
  .addChild("sort_range", ["data"], {
80885
80920
  ...sortRange,
@@ -81972,6 +82007,10 @@ class SpreadsheetDashboard extends owl.Component {
81972
82007
  useTouchScroll(this.gridRef, this.moveCanvas.bind(this), () => {
81973
82008
  const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
81974
82009
  return scrollY > 0;
82010
+ }, () => {
82011
+ const { maxOffsetY } = this.env.model.getters.getMaximumSheetOffset();
82012
+ const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
82013
+ return scrollY < maxOffsetY;
81975
82014
  });
81976
82015
  }
81977
82016
  get gridContainer() {
@@ -84016,7 +84055,7 @@ css /* scss */ `
84016
84055
  border-radius: 4px;
84017
84056
  font-weight: 500;
84018
84057
  font-size: 14px;
84019
- height: 32px;
84058
+ min-height: 32px;
84020
84059
  line-height: 16px;
84021
84060
  flex-grow: 1;
84022
84061
  background-color: ${BUTTON_BG};
@@ -88969,6 +89008,6 @@ exports.tokenColors = tokenColors;
88969
89008
  exports.tokenize = tokenize;
88970
89009
 
88971
89010
 
88972
- __info__.version = "19.0.9";
88973
- __info__.date = "2025-11-03T12:32:15.473Z";
88974
- __info__.hash = "10359f4";
89011
+ __info__.version = "19.0.11";
89012
+ __info__.date = "2025-11-24T07:46:47.685Z";
89013
+ __info__.hash = "f5bdbcc";