@odoo/o-spreadsheet 17.0.23 → 17.0.27

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,18 +2,19 @@
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 17.0.23
6
- * @date 2024-05-24T11:27:27.416Z
7
- * @hash 6c10fec
5
+ * @version 17.0.27
6
+ * @date 2024-07-02T09:01:48.383Z
7
+ * @hash c1c2d01
8
8
  */
9
9
 
10
10
  'use strict';
11
11
 
12
12
  var owl = require('@odoo/owl');
13
13
 
14
- // define a mock translation function, when o-spreadsheet runs in standalone it doesn't translate any string
15
- let _translate = (s) => s;
16
- let _loaded = () => false;
14
+ const defaultTranslate = (s) => s;
15
+ const defaultLoaded = () => false;
16
+ let _translate = defaultTranslate;
17
+ let _loaded = defaultLoaded;
17
18
  function sprintf(s, ...values) {
18
19
  if (values.length === 1 && typeof values[0] === "object" && !(values[0] instanceof String)) {
19
20
  const valuesDict = values[0];
@@ -25,7 +26,8 @@ function sprintf(s, ...values) {
25
26
  return s;
26
27
  }
27
28
  /***
28
- * Allow to inject a translation function from outside o-spreadsheet.
29
+ * Allow to inject a translation function from outside o-spreadsheet. This should be called before instantiating
30
+ * a model.
29
31
  * @param tfn the function that will do the translation
30
32
  * @param loaded a function that returns true when the translation is loaded
31
33
  */
@@ -33,6 +35,18 @@ function setTranslationMethod(tfn, loaded = () => true) {
33
35
  _translate = tfn;
34
36
  _loaded = loaded;
35
37
  }
38
+ /**
39
+ * If no translation function has been set, this will mark the translation are loaded.
40
+ *
41
+ * By default, the translations should not be set as loaded, otherwise top-level translated constants will never be
42
+ * translated. But if by the time the model is instantiated no custom translation function has been set, we can set
43
+ * the default translation function as loaded so o-spreadsheet can be run in standalone with no translations.
44
+ */
45
+ function setDefaultTranslationMethod() {
46
+ if (_translate === defaultTranslate && _loaded === defaultLoaded) {
47
+ _loaded = () => true;
48
+ }
49
+ }
36
50
  const _t = function (s, ...values) {
37
51
  if (!_loaded()) {
38
52
  return new LazyTranslatedString(s, values);
@@ -394,7 +408,10 @@ function deepCopy(obj) {
394
408
  * Check if the object is a plain old javascript object.
395
409
  */
396
410
  function isPlainObject(obj) {
397
- return typeof obj === "object" && obj?.constructor === Object;
411
+ return (typeof obj === "object" &&
412
+ obj !== null &&
413
+ // obj.constructor can be undefined when there's no prototype (`Object.create(null, {})`)
414
+ (obj?.constructor === Object || obj?.constructor === undefined));
398
415
  }
399
416
  /**
400
417
  * Sanitize the name of a sheet, by eventually removing quotes
@@ -4306,8 +4323,11 @@ function copyRangeWithNewSheetId(sheetIdFrom, sheetIdTo, range) {
4306
4323
  /**
4307
4324
  * Create a range from a xc. If the xc is empty, this function returns undefined.
4308
4325
  */
4309
- function createRange(getters, sheetId, range) {
4310
- return range ? getters.getRangeFromSheetXC(sheetId, range) : undefined;
4326
+ function createValidRange(getters, sheetId, xc) {
4327
+ if (!xc)
4328
+ return;
4329
+ const range = getters.getRangeFromSheetXC(sheetId, xc);
4330
+ return !(range.invalidSheetName || range.invalidXc) ? range : undefined;
4311
4331
  }
4312
4332
  /**
4313
4333
  * Spread multiple colrows zone to one row/col zone and add a many new input range as needed.
@@ -5235,8 +5255,8 @@ let ScorecardChart$1 = class ScorecardChart extends AbstractChart {
5235
5255
  type = "scorecard";
5236
5256
  constructor(definition, sheetId, getters) {
5237
5257
  super(definition, sheetId, getters);
5238
- this.keyValue = createRange(getters, sheetId, definition.keyValue);
5239
- this.baseline = createRange(getters, sheetId, definition.baseline);
5258
+ this.keyValue = createValidRange(getters, sheetId, definition.keyValue);
5259
+ this.baseline = createValidRange(getters, sheetId, definition.baseline);
5240
5260
  this.baselineMode = definition.baselineMode;
5241
5261
  this.baselineDescr = definition.baselineDescr;
5242
5262
  this.background = definition.background;
@@ -6707,6 +6727,7 @@ const FilterMenuPopoverBuilder = {
6707
6727
  };
6708
6728
 
6709
6729
  const macRegex = /Mac/i;
6730
+ const MODIFIER_KEYS$1 = ["Shift", "Control", "Alt", "Meta"];
6710
6731
  /**
6711
6732
  * Return true if the event was triggered from
6712
6733
  * a child element.
@@ -6745,6 +6766,31 @@ function* iterateChildren(el) {
6745
6766
  function getOpenedMenus() {
6746
6767
  return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
6747
6768
  }
6769
+ const letterRegex = /^[a-zA-Z]$/;
6770
+ /**
6771
+ * Transform a keyboard event into a shortcut string that represent this event. The letters keys will be uppercased.
6772
+ *
6773
+ * @argument ev - The keyboard event to transform
6774
+ * @argument mode - Use either ev.key of ev.code to get the string shortcut
6775
+ *
6776
+ * @example
6777
+ * event : { ctrlKey: true, key: "a" } => "Ctrl+A"
6778
+ * event : { shift: true, alt: true, key: "Home" } => "Alt+Shift+Home"
6779
+ */
6780
+ function keyboardEventToShortcutString(ev, mode = "key") {
6781
+ let keyDownString = "";
6782
+ if (!MODIFIER_KEYS$1.includes(ev.key)) {
6783
+ if (isCtrlKey(ev))
6784
+ keyDownString += "Ctrl+";
6785
+ if (ev.altKey)
6786
+ keyDownString += "Alt+";
6787
+ if (ev.shiftKey)
6788
+ keyDownString += "Shift+";
6789
+ }
6790
+ const key = mode === "key" ? ev.key : ev.code;
6791
+ keyDownString += letterRegex.test(key) ? key.toUpperCase() : key;
6792
+ return keyDownString;
6793
+ }
6748
6794
  function isMacOS() {
6749
6795
  return Boolean(macRegex.test(navigator.userAgent));
6750
6796
  }
@@ -6763,8 +6809,7 @@ function isCtrlKey(ev) {
6763
6809
  */
6764
6810
  function useSpreadsheetRect() {
6765
6811
  const position = owl.useState({ x: 0, y: 0, width: 0, height: 0 });
6766
- let spreadsheetElement = document.querySelector(".o-spreadsheet");
6767
- updatePosition();
6812
+ let spreadsheetElement = null;
6768
6813
  function updatePosition() {
6769
6814
  if (!spreadsheetElement) {
6770
6815
  spreadsheetElement = document.querySelector(".o-spreadsheet");
@@ -6902,7 +6947,7 @@ class Popover extends owl.Component {
6902
6947
  if (!anchor)
6903
6948
  return;
6904
6949
  const propsMaxSize = { width: this.props.maxWidth, height: this.props.maxHeight };
6905
- const elDims = {
6950
+ let elDims = {
6906
6951
  width: el.getBoundingClientRect().width,
6907
6952
  height: el.getBoundingClientRect().height,
6908
6953
  };
@@ -6910,7 +6955,14 @@ class Popover extends owl.Component {
6910
6955
  const popoverPositionHelper = this.props.positioning === "BottomLeft"
6911
6956
  ? new BottomLeftPopoverContext(anchor, this.containerRect, propsMaxSize, spreadsheetRect)
6912
6957
  : new TopRightPopoverContext(anchor, this.containerRect, propsMaxSize, spreadsheetRect);
6913
- const style = popoverPositionHelper.getCss(elDims, this.props.verticalOffset);
6958
+ el.style["max-height"] = popoverPositionHelper.getMaxHeight(elDims.height) + "px";
6959
+ el.style["max-width"] = popoverPositionHelper.getMaxWidth(elDims.width) + "px";
6960
+ // Re-compute the dimensions after setting the max-width and max-height
6961
+ elDims = {
6962
+ width: el.getBoundingClientRect().width,
6963
+ height: el.getBoundingClientRect().height,
6964
+ };
6965
+ let style = popoverPositionHelper.getCss(elDims, this.props.verticalOffset);
6914
6966
  for (const property of Object.keys(style)) {
6915
6967
  el.style[property] = style[property];
6916
6968
  }
@@ -6986,8 +7038,6 @@ class PopoverPositionContext {
6986
7038
  const shouldRenderAtRight = this.shouldRenderAtRight(elDims.width);
6987
7039
  verticalOffset = shouldRenderAtBottom ? verticalOffset : -verticalOffset;
6988
7040
  const cssProperties = {
6989
- "max-height": maxHeight + "px",
6990
- "max-width": maxWidth + "px",
6991
7041
  top: this.getTopCoordinate(actualHeight, shouldRenderAtBottom) -
6992
7042
  this.spreadsheetOffset.y -
6993
7043
  verticalOffset +
@@ -8537,7 +8587,7 @@ function chartToImage(runtime, figure, type) {
8537
8587
  if ("chartJsConfig" in runtime) {
8538
8588
  runtime.chartJsConfig.plugins = [backgroundColorChartJSPlugin];
8539
8589
  // @ts-ignore
8540
- const chart = new window.Chart(canvas, runtime.chartJsConfig);
8590
+ const chart = new window.Chart(canvas, deepCopy(runtime.chartJsConfig));
8541
8591
  const imgContent = chart.toBase64Image();
8542
8592
  chart.destroy();
8543
8593
  div.remove();
@@ -8581,7 +8631,7 @@ class BarChart extends AbstractChart {
8581
8631
  constructor(definition, sheetId, getters) {
8582
8632
  super(definition, sheetId, getters);
8583
8633
  this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
8584
- this.labelRange = createRange(getters, sheetId, definition.labelRange);
8634
+ this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
8585
8635
  this.background = definition.background;
8586
8636
  this.verticalAxisPosition = definition.verticalAxisPosition;
8587
8637
  this.legendPosition = definition.legendPosition;
@@ -8824,7 +8874,7 @@ class GaugeChart extends AbstractChart {
8824
8874
  type = "gauge";
8825
8875
  constructor(definition, sheetId, getters) {
8826
8876
  super(definition, sheetId, getters);
8827
- this.dataRange = createRange(this.getters, this.sheetId, definition.dataRange);
8877
+ this.dataRange = createValidRange(this.getters, this.sheetId, definition.dataRange);
8828
8878
  this.sectionRule = definition.sectionRule;
8829
8879
  this.background = definition.background;
8830
8880
  }
@@ -9158,7 +9208,7 @@ class LineChart extends AbstractChart {
9158
9208
  constructor(definition, sheetId, getters) {
9159
9209
  super(definition, sheetId, getters);
9160
9210
  this.dataSets = createDataSets(this.getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
9161
- this.labelRange = createRange(this.getters, sheetId, definition.labelRange);
9211
+ this.labelRange = createValidRange(this.getters, sheetId, definition.labelRange);
9162
9212
  this.background = definition.background;
9163
9213
  this.verticalAxisPosition = definition.verticalAxisPosition;
9164
9214
  this.legendPosition = definition.legendPosition;
@@ -9478,7 +9528,7 @@ class PieChart extends AbstractChart {
9478
9528
  constructor(definition, sheetId, getters) {
9479
9529
  super(definition, sheetId, getters);
9480
9530
  this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
9481
- this.labelRange = createRange(getters, sheetId, definition.labelRange);
9531
+ this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
9482
9532
  this.background = definition.background;
9483
9533
  this.legendPosition = definition.legendPosition;
9484
9534
  this.aggregated = definition.aggregated;
@@ -21725,7 +21775,7 @@ class LineBarPieConfigPanel extends owl.Component {
21725
21775
  }
21726
21776
  const getters = this.env.model.getters;
21727
21777
  const sheetId = getters.getActiveSheetId();
21728
- const labelRange = createRange(getters, sheetId, this.labelRange);
21778
+ const labelRange = createValidRange(getters, sheetId, this.labelRange);
21729
21779
  const dataSets = createDataSets(getters, this.dataSeriesRanges, sheetId, this.props.definition.dataSetsHaveTitle);
21730
21780
  if (dataSets.length) {
21731
21781
  return dataSets[0].dataRange.zone.top + 1;
@@ -24946,13 +24996,17 @@ SplitIntoColumnsPanel.props = {
24946
24996
  class SelectMenu extends owl.Component {
24947
24997
  static template = "o-spreadsheet-SelectMenu";
24948
24998
  static components = { Menu };
24999
+ menuId = new UuidGenerator().uuidv4();
24949
25000
  selectRef = owl.useRef("select");
24950
25001
  selectRect = useAbsoluteBoundingRect(this.selectRef);
24951
25002
  state = owl.useState({
24952
25003
  isMenuOpen: false,
24953
25004
  });
24954
- onClick() {
24955
- this.state.isMenuOpen = true;
25005
+ onClick(ev) {
25006
+ if (ev.closedMenuId === this.menuId) {
25007
+ return;
25008
+ }
25009
+ this.state.isMenuOpen = !this.state.isMenuOpen;
24956
25010
  }
24957
25011
  onMenuClosed() {
24958
25012
  this.state.isMenuOpen = false;
@@ -24960,7 +25014,7 @@ class SelectMenu extends owl.Component {
24960
25014
  get menuPosition() {
24961
25015
  return {
24962
25016
  x: this.selectRect.x,
24963
- y: this.selectRect.y,
25017
+ y: this.selectRect.y + this.selectRect.height,
24964
25018
  };
24965
25019
  }
24966
25020
  }
@@ -25767,14 +25821,14 @@ class FigureComponent extends owl.Component {
25767
25821
  }
25768
25822
  onKeyDown(ev) {
25769
25823
  const figure = this.props.figure;
25770
- switch (ev.key) {
25824
+ const keyDownShortcut = keyboardEventToShortcutString(ev);
25825
+ switch (keyDownShortcut) {
25771
25826
  case "Delete":
25772
25827
  this.env.model.dispatch("DELETE_FIGURE", {
25773
25828
  sheetId: this.env.model.getters.getActiveSheetId(),
25774
25829
  id: figure.id,
25775
25830
  });
25776
25831
  this.props.onFigureDeleted();
25777
- ev.stopPropagation();
25778
25832
  ev.preventDefault();
25779
25833
  ev.stopPropagation();
25780
25834
  break;
@@ -25795,7 +25849,22 @@ class FigureComponent extends owl.Component {
25795
25849
  x: figure.x + delta[0],
25796
25850
  y: figure.y + delta[1],
25797
25851
  });
25852
+ ev.preventDefault();
25853
+ ev.stopPropagation();
25854
+ break;
25855
+ case "Ctrl+A":
25856
+ // Maybe in the future we will implement a way to select all figures
25857
+ ev.preventDefault();
25798
25858
  ev.stopPropagation();
25859
+ break;
25860
+ case "Ctrl+Y":
25861
+ case "Ctrl+Z":
25862
+ if (keyDownShortcut === "Ctrl+Y") {
25863
+ this.env.model.dispatch("REQUEST_REDO");
25864
+ }
25865
+ else if (keyDownShortcut === "Ctrl+Z") {
25866
+ this.env.model.dispatch("REQUEST_UNDO");
25867
+ }
25799
25868
  ev.preventDefault();
25800
25869
  ev.stopPropagation();
25801
25870
  break;
@@ -26815,8 +26884,15 @@ class Composer extends owl.Component {
26815
26884
  }
26816
26885
  onPaste(ev) {
26817
26886
  if (this.env.model.getters.getEditionMode() !== "inactive") {
26887
+ // let the browser clipboard work
26818
26888
  ev.stopPropagation();
26819
26889
  }
26890
+ else {
26891
+ // the user meant to paste in the sheet, not open the composer with the pasted content
26892
+ // While we're not editing, we still have the focus and should therefore prevent
26893
+ // the native "paste" to occur.
26894
+ ev.preventDefault();
26895
+ }
26820
26896
  }
26821
26897
  /*
26822
26898
  * Triggered automatically by the content-editable between the keydown and key up
@@ -26825,10 +26901,6 @@ class Composer extends owl.Component {
26825
26901
  if (!this.shouldProcessInputEvents) {
26826
26902
  return;
26827
26903
  }
26828
- if (ev.inputType === "insertFromPaste" &&
26829
- this.env.model.getters.getEditionMode() === "inactive") {
26830
- return;
26831
- }
26832
26904
  ev.stopPropagation();
26833
26905
  let content;
26834
26906
  if (this.env.model.getters.getEditionMode() === "inactive") {
@@ -27276,10 +27348,7 @@ class GridComposer extends owl.Component {
27276
27348
  }
27277
27349
  get containerStyle() {
27278
27350
  if (this.env.model.getters.getEditionMode() === "inactive" || !this.rect) {
27279
- return `
27280
- position: absolute;
27281
- z-index: -1000;
27282
- `;
27351
+ return `z-index: -1000;`;
27283
27352
  }
27284
27353
  const isFormula = this.env.model.getters.getCurrentContent().startsWith("=");
27285
27354
  const cell = this.env.model.getters.getActiveCell();
@@ -27976,7 +28045,7 @@ class FiguresContainer extends owl.Component {
27976
28045
  });
27977
28046
  }
27978
28047
  getContainerRect(container) {
27979
- const { width: viewWidth, height: viewHeight } = this.env.model.getters.getMainViewportRect();
28048
+ const { width: viewWidth, height: viewHeight } = this.env.model.getters.getSheetViewDimension();
27980
28049
  const { x: viewportX, y: viewportY } = this.env.model.getters.getMainViewportCoordinates();
27981
28050
  const x = ["bottomRight", "topRight"].includes(container) ? viewportX : 0;
27982
28051
  const width = viewWidth - x;
@@ -38572,6 +38641,9 @@ class RangeAdapter {
38572
38641
  if (range.invalidXc) {
38573
38642
  return range.invalidXc;
38574
38643
  }
38644
+ if (!this.getters.tryGetSheet(range.sheetId)) {
38645
+ return INCORRECT_RANGE_STRING;
38646
+ }
38575
38647
  if (range.zone.bottom - range.zone.top < 0 || range.zone.right - range.zone.left < 0) {
38576
38648
  return INCORRECT_RANGE_STRING;
38577
38649
  }
@@ -42023,16 +42095,22 @@ class EvaluationPlugin extends UIPlugin {
42023
42095
  let newContent = undefined;
42024
42096
  let newFormat = undefined;
42025
42097
  let isExported = true;
42098
+ const exportedSheetData = data.sheets.find((sheet) => sheet.id === position.sheetId);
42026
42099
  const formulaCell = this.getCorrespondingFormulaCell(position);
42027
42100
  if (formulaCell) {
42028
42101
  isExported = isExportableToExcel(formulaCell.compiledFormula.tokens);
42029
42102
  isFormula = isExported;
42030
42103
  if (!isExported) {
42031
- newContent = value.toString();
42032
- newFormat = evaluatedCell.format;
42104
+ // If the cell contains a non-exported formula and that is evaluates to
42105
+ // nothing* ,we don't export it.
42106
+ // * non-falsy value are relevant and so are 0 and FALSE, which only leaves
42107
+ // the empty string.
42108
+ if (value !== "") {
42109
+ newContent = value.toString();
42110
+ newFormat = evaluatedCell.format;
42111
+ }
42033
42112
  }
42034
42113
  }
42035
- const exportedSheetData = data.sheets.find((sheet) => sheet.id === position.sheetId);
42036
42114
  const exportedCellData = exportedSheetData.cells[xc] || {};
42037
42115
  const format = newFormat
42038
42116
  ? getItemId(newFormat, data.formats)
@@ -44292,7 +44370,10 @@ class Session extends EventBus {
44292
44370
  /**
44293
44371
  * Notify the server that the user client left the collaborative session
44294
44372
  */
44295
- leave() {
44373
+ leave(data) {
44374
+ if (Object.keys(this.clients).length === 1 && this.processedRevisions.size) {
44375
+ this.snapshot(data);
44376
+ }
44296
44377
  delete this.clients[this.clientId];
44297
44378
  this.transportService.leave(this.clientId);
44298
44379
  this.transportService.sendMessage({
@@ -44305,6 +44386,9 @@ class Session extends EventBus {
44305
44386
  * Send a snapshot of the spreadsheet to the collaboration server
44306
44387
  */
44307
44388
  snapshot(data) {
44389
+ if (this.pendingMessages.length !== 0) {
44390
+ return;
44391
+ }
44308
44392
  const snapshotId = this.uuidGenerator.uuidv4();
44309
44393
  this.transportService.sendMessage({
44310
44394
  type: "SNAPSHOT",
@@ -49085,10 +49169,8 @@ class EditionPlugin extends UIPlugin {
49085
49169
  const refRange = this.getters.getRangeFromSheetXC(activeSheetId, xc);
49086
49170
  return isEqual(this.getters.expandZone(activeSheetId, refRange.zone), oldZone);
49087
49171
  });
49088
- // this function assumes that the previous range is always found because
49089
- // it's called when changing a highlight, which exists by definition
49090
49172
  if (!previousRefToken) {
49091
- throw new Error("Previous range not found");
49173
+ return;
49092
49174
  }
49093
49175
  const previousRange = this.getters.getRangeFromSheetXC(activeSheetId, previousRefToken.value);
49094
49176
  this.selectionStart = previousRefToken.start;
@@ -51644,12 +51726,14 @@ class BottomBarSheet extends owl.Component {
51644
51726
  if (ev.key === "Enter") {
51645
51727
  ev.preventDefault();
51646
51728
  this.stopEdition();
51729
+ this.env.focusableElement.focus();
51647
51730
  }
51648
51731
  if (ev.key === "Escape") {
51649
51732
  this.cancelEdition();
51733
+ this.env.focusableElement.focus();
51650
51734
  }
51651
51735
  }
51652
- onClickSheetName(ev) {
51736
+ onMouseEventSheetName(ev) {
51653
51737
  if (this.state.isEditing)
51654
51738
  ev.stopPropagation();
51655
51739
  }
@@ -56395,7 +56479,11 @@ function addRows(construct, data, sheet) {
56395
56479
  let cellNode = escapeXml ``;
56396
56480
  // Either formula or static value inside the cell
56397
56481
  if (cell.isFormula) {
56398
- ({ attrs: additionalAttrs, node: cellNode } = addFormula(cell));
56482
+ const res = addFormula(cell);
56483
+ if (!res) {
56484
+ continue;
56485
+ }
56486
+ ({ attrs: additionalAttrs, node: cellNode } = res);
56399
56487
  }
56400
56488
  else if (cell.content && isMarkdownLink(cell.content)) {
56401
56489
  const { label } = parseMarkdownLink(cell.content);
@@ -56838,6 +56926,7 @@ class Model extends EventBus {
56838
56926
  coreHandlers = [];
56839
56927
  constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = true) {
56840
56928
  super();
56929
+ setDefaultTranslationMethod();
56841
56930
  stateUpdateMessages = repairInitialMessages(data, stateUpdateMessages);
56842
56931
  const workbookData = load(data, verboseImport);
56843
56932
  this.state = new StateObserver();
@@ -56913,7 +57002,7 @@ class Model extends EventBus {
56913
57002
  this.session.join(this.config.client);
56914
57003
  }
56915
57004
  leaveSession() {
56916
- this.session.leave();
57005
+ this.session.leave(this.exportData());
56917
57006
  }
56918
57007
  setupUiPlugin(Plugin) {
56919
57008
  const plugin = new Plugin(this.uiPluginConfig);
@@ -57337,6 +57426,7 @@ const helpers = {
57337
57426
  createAction,
57338
57427
  createActions,
57339
57428
  transformRangeData,
57429
+ deepEquals,
57340
57430
  };
57341
57431
  const links = {
57342
57432
  isMarkdownLink,
@@ -57415,6 +57505,6 @@ exports.setTranslationMethod = setTranslationMethod;
57415
57505
  exports.tokenize = tokenize;
57416
57506
 
57417
57507
 
57418
- __info__.version = "17.0.23";
57419
- __info__.date = "2024-05-24T11:27:27.416Z";
57420
- __info__.hash = "6c10fec";
57508
+ __info__.version = "17.0.27";
57509
+ __info__.date = "2024-07-02T09:01:48.383Z";
57510
+ __info__.hash = "c1c2d01";
@@ -852,7 +852,7 @@ declare class Session extends EventBus<CollaborativeEvent> {
852
852
  /**
853
853
  * Notify the server that the user client left the collaborative session
854
854
  */
855
- leave(): void;
855
+ leave(data: WorkbookData): void;
856
856
  /**
857
857
  * Send a snapshot of the spreadsheet to the collaboration server
858
858
  */
@@ -993,6 +993,10 @@ declare function isDefined<T>(argument: T | undefined): argument is T;
993
993
  * Lazy value computed by the provided function.
994
994
  */
995
995
  declare function lazy<T>(fn: (() => T) | T): Lazy<T>;
996
+ /**
997
+ * Compares two objects.
998
+ */
999
+ declare function deepEquals(o1: any, o2: any, ignoreFunctions?: "ignoreFunctions"): boolean;
996
1000
 
997
1001
  interface ConstructorArgs {
998
1002
  readonly zone: Readonly<Zone | UnboundedZone>;
@@ -6189,7 +6193,7 @@ declare class BottomBarSheet extends Component<Props$v, SpreadsheetChildEnv> {
6189
6193
  private activateSheet;
6190
6194
  onDblClick(): void;
6191
6195
  onKeyDown(ev: KeyboardEvent): void;
6192
- onClickSheetName(ev: MouseEvent): void;
6196
+ onMouseEventSheetName(ev: MouseEvent): void;
6193
6197
  private startEdition;
6194
6198
  private stopEdition;
6195
6199
  private cancelEdition;
@@ -7819,7 +7823,8 @@ type SprintfValues = (string | String | number)[] | [{
7819
7823
  }];
7820
7824
  type TranslationFunction = (string: string, ...values: SprintfValues) => string;
7821
7825
  /***
7822
- * Allow to inject a translation function from outside o-spreadsheet.
7826
+ * Allow to inject a translation function from outside o-spreadsheet. This should be called before instantiating
7827
+ * a model.
7823
7828
  * @param tfn the function that will do the translation
7824
7829
  * @param loaded a function that returns true when the translation is loaded
7825
7830
  */
@@ -7934,6 +7939,7 @@ declare const helpers: {
7934
7939
  createAction: typeof createAction;
7935
7940
  createActions: typeof createActions;
7936
7941
  transformRangeData: typeof transformRangeData;
7942
+ deepEquals: typeof deepEquals;
7937
7943
  };
7938
7944
  declare const links: {
7939
7945
  isMarkdownLink: typeof isMarkdownLink;