@odoo/o-spreadsheet 17.2.21 → 17.2.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,9 +3,9 @@
3
3
  /**
4
4
  * This file is generated by o-spreadsheet build tools. Do not edit it.
5
5
  * @see https://github.com/odoo/o-spreadsheet
6
- * @version 17.2.21
7
- * @date 2024-08-19T08:10:10.580Z
8
- * @hash fb17f9c
6
+ * @version 17.2.23
7
+ * @date 2024-09-05T09:32:03.325Z
8
+ * @hash e5e2be8
9
9
  */
10
10
 
11
11
  'use strict';
@@ -5787,9 +5787,11 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
5787
5787
  const targetCell = this.getters.getEvaluatedCell(target);
5788
5788
  const originFormat = origin.cell?.format ?? origin.evaluatedCell.format;
5789
5789
  if (clipboardOption?.pasteOption === "asValue") {
5790
- const locale = this.getters.getLocale();
5791
- const content = formatValue(origin.evaluatedCell.value, { locale });
5792
- this.dispatch("UPDATE_CELL", { ...target, content, format: originFormat });
5790
+ this.dispatch("UPDATE_CELL", {
5791
+ ...target,
5792
+ content: origin.evaluatedCell.value?.toString() || "",
5793
+ format: originFormat,
5794
+ });
5793
5795
  return;
5794
5796
  }
5795
5797
  if (clipboardOption?.pasteOption === "onlyFormat") {
@@ -29878,7 +29880,6 @@ class FindAndReplaceStore extends SpreadsheetStore {
29878
29880
  searchScope: "allSheets",
29879
29881
  specificRange: undefined,
29880
29882
  };
29881
- updateSearchContent = debounce(this._updateSearchContent.bind(this), 200);
29882
29883
  constructor(get) {
29883
29884
  super(get);
29884
29885
  this.initialShowFormulaState = this.model.getters.shouldShowFormulas();
@@ -29887,7 +29888,6 @@ class FindAndReplaceStore extends SpreadsheetStore {
29887
29888
  highlightStore.register(this);
29888
29889
  this.onDispose(() => {
29889
29890
  this.model.dispatch("SET_FORMULA_VISIBILITY", { show: this.initialShowFormulaState });
29890
- this.updateSearchContent.stopDebounce();
29891
29891
  highlightStore.unRegister(this);
29892
29892
  });
29893
29893
  }
@@ -29901,7 +29901,7 @@ class FindAndReplaceStore extends SpreadsheetStore {
29901
29901
  return this.specificRangeMatches;
29902
29902
  }
29903
29903
  }
29904
- _updateSearchContent(toSearch) {
29904
+ updateSearchContent(toSearch) {
29905
29905
  this._updateSearch(toSearch, this.searchOptions);
29906
29906
  }
29907
29907
  updateSearchOptions(searchOptions) {
@@ -29917,9 +29917,6 @@ class FindAndReplaceStore extends SpreadsheetStore {
29917
29917
  selectNextMatch() {
29918
29918
  this.selectNextCell(Direction.next);
29919
29919
  }
29920
- get pendingSearch() {
29921
- return this.updateSearchContent.isDebouncePending();
29922
- }
29923
29920
  handle(cmd) {
29924
29921
  switch (cmd.type) {
29925
29922
  case "SET_FORMULA_VISIBILITY":
@@ -30197,6 +30194,7 @@ class FindAndReplacePanel extends owl.Component {
30197
30194
  searchInput = owl.useRef("searchInput");
30198
30195
  store;
30199
30196
  state;
30197
+ updateSearchContent;
30200
30198
  get hasSearchResult() {
30201
30199
  return this.store.selectedMatchIndex !== null;
30202
30200
  }
@@ -30228,12 +30226,14 @@ class FindAndReplacePanel extends owl.Component {
30228
30226
  this.store = useLocalStore(FindAndReplaceStore);
30229
30227
  this.state = owl.useState({ dataRange: "" });
30230
30228
  owl.onMounted(() => this.searchInput.el?.focus());
30229
+ owl.onWillUnmount(() => this.updateSearchContent.stopDebounce());
30230
+ this.updateSearchContent = debounce(this.store.updateSearchContent, 200);
30231
30231
  }
30232
30232
  onFocusSearch() {
30233
30233
  this.updateDataRange();
30234
30234
  }
30235
30235
  onSearchInput(ev) {
30236
- this.store.updateSearchContent(ev.target?.value || "");
30236
+ this.updateSearchContent(ev.target.value);
30237
30237
  }
30238
30238
  onKeydownSearch(ev) {
30239
30239
  if (ev.key === "Enter") {
@@ -30272,6 +30272,9 @@ class FindAndReplacePanel extends owl.Component {
30272
30272
  const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.state.dataRange);
30273
30273
  this.store.updateSearchOptions({ specificRange });
30274
30274
  }
30275
+ get pendingSearch() {
30276
+ return this.updateSearchContent.isDebouncePending();
30277
+ }
30275
30278
  }
30276
30279
 
30277
30280
  css /* scss */ `
@@ -31074,10 +31077,6 @@ class TablePanel extends owl.Component {
31074
31077
  });
31075
31078
  }
31076
31079
  onRangeChanged(ranges) {
31077
- if (!ranges[0] || !ranges[0].match(rangeReference)) {
31078
- this.state.tableZoneErrors = ["InvalidRange" /* CommandResult.InvalidRange */];
31079
- return;
31080
- }
31081
31080
  const sheetId = this.env.model.getters.getActiveSheetId();
31082
31081
  this.state.tableXc = ranges[0];
31083
31082
  this.state.tableZoneErrors = this.env.model.canDispatch("UPDATE_TABLE", {
@@ -31101,10 +31100,6 @@ class TablePanel extends owl.Component {
31101
31100
  cell: position,
31102
31101
  });
31103
31102
  }
31104
- this.state.tableZoneErrors = [];
31105
- this.state.tableXc = result.isSuccessful
31106
- ? this.state.tableXc
31107
- : this.env.model.getters.getRangeString(this.props.table.range, sheetId);
31108
31103
  }
31109
31104
  deleteTable() {
31110
31105
  const sheetId = this.env.model.getters.getActiveSheetId();
@@ -37597,6 +37592,18 @@ function convertOperator(operator) {
37597
37592
  // -------------------------------------
37598
37593
  // WORKSHEET HELPERS
37599
37594
  // -------------------------------------
37595
+ function getCellType(value) {
37596
+ switch (typeof value) {
37597
+ case "boolean":
37598
+ return "b";
37599
+ case "string":
37600
+ return "str";
37601
+ case "number":
37602
+ return "n";
37603
+ default:
37604
+ return undefined;
37605
+ }
37606
+ }
37600
37607
  function convertHeightToExcel(height) {
37601
37608
  return Math.round(HEIGHT_FACTOR * height * 100) / 100;
37602
37609
  }
@@ -42998,7 +43005,10 @@ class HeaderSizePlugin extends CorePlugin {
42998
43005
  handle(cmd) {
42999
43006
  switch (cmd.type) {
43000
43007
  case "CREATE_SHEET": {
43001
- this.history.update("sizes", cmd.sheetId, { COL: [], ROW: [] });
43008
+ this.history.update("sizes", cmd.sheetId, {
43009
+ COL: Array(this.getters.getNumberCols(cmd.sheetId)).fill(undefined),
43010
+ ROW: Array(this.getters.getNumberRows(cmd.sheetId)).fill(undefined),
43011
+ });
43002
43012
  break;
43003
43013
  }
43004
43014
  case "DUPLICATE_SHEET":
@@ -50429,9 +50439,9 @@ class Session extends EventBus {
50429
50439
  /**
50430
50440
  * Notify the server that the user client left the collaborative session
50431
50441
  */
50432
- leave(data) {
50442
+ async leave(data) {
50433
50443
  if (Object.keys(this.clients).length === 1 && this.processedRevisions.size) {
50434
- this.snapshot(data());
50444
+ await this.snapshot(data());
50435
50445
  }
50436
50446
  delete this.clients[this.clientId];
50437
50447
  this.transportService.leave(this.clientId);
@@ -50444,12 +50454,12 @@ class Session extends EventBus {
50444
50454
  /**
50445
50455
  * Send a snapshot of the spreadsheet to the collaboration server
50446
50456
  */
50447
- snapshot(data) {
50457
+ async snapshot(data) {
50448
50458
  if (this.pendingMessages.length !== 0) {
50449
50459
  return;
50450
50460
  }
50451
50461
  const snapshotId = this.uuidGenerator.uuidv4();
50452
- this.transportService.sendMessage({
50462
+ await this.transportService.sendMessage({
50453
50463
  type: "SNAPSHOT",
50454
50464
  nextRevisionId: snapshotId,
50455
50465
  serverRevisionId: this.serverRevisionId,
@@ -52364,6 +52374,7 @@ class ClipboardPlugin extends UIPlugin {
52364
52374
  this.status = "invisible";
52365
52375
  if (this._isCutOperation) {
52366
52376
  this.copiedData = undefined;
52377
+ this._isCutOperation = false;
52367
52378
  }
52368
52379
  break;
52369
52380
  }
@@ -52461,6 +52472,7 @@ class ClipboardPlugin extends UIPlugin {
52461
52472
  }
52462
52473
  case "ACTIVATE_PAINT_FORMAT": {
52463
52474
  const zones = this.getters.getSelectedZones();
52475
+ this._isCutOperation = false;
52464
52476
  this.copiedData = this.copy(zones);
52465
52477
  this.status = "visible";
52466
52478
  if (cmd.persistent) {
@@ -53216,6 +53228,8 @@ class GridSelectionPlugin extends UIPlugin {
53216
53228
  this.selectedFigureId = null;
53217
53229
  break;
53218
53230
  }
53231
+ }
53232
+ finalize() {
53219
53233
  /** Any change to the selection has to be reflected in the selection processor. */
53220
53234
  this.selection.resetDefaultAnchor(this, deepCopy(this.gridSelection.anchor));
53221
53235
  }
@@ -54044,7 +54058,6 @@ class SheetViewPlugin extends UIPlugin {
54044
54058
  }
54045
54059
  }
54046
54060
  handle(cmd) {
54047
- this.cleanViewports();
54048
54061
  // changing the evaluation can hide/show rows because of data filters
54049
54062
  if (invalidateEvaluationCommands.has(cmd.type)) {
54050
54063
  for (const sheetId of this.getters.getSheetIds()) {
@@ -54060,6 +54073,7 @@ class SheetViewPlugin extends UIPlugin {
54060
54073
  break;
54061
54074
  case "UNDO":
54062
54075
  case "REDO":
54076
+ this.cleanViewports();
54063
54077
  for (const sheetId of this.getters.getSheetIds()) {
54064
54078
  this.sheetsWithDirtyViewports.add(sheetId);
54065
54079
  }
@@ -54114,6 +54128,9 @@ class SheetViewPlugin extends UIPlugin {
54114
54128
  }
54115
54129
  }
54116
54130
  break;
54131
+ case "DELETE_SHEET":
54132
+ this.cleanViewports();
54133
+ break;
54117
54134
  case "ACTIVATE_SHEET":
54118
54135
  this.sheetsWithDirtyViewports.add(cmd.sheetIdTo);
54119
54136
  break;
@@ -55274,6 +55291,17 @@ css /* scss */ `
55274
55291
  .o-bottom-bar-fade-in {
55275
55292
  background-image: linear-gradient(90deg, #cfcfcf, transparent 1%);
55276
55293
  }
55294
+
55295
+ .o-sheet-list {
55296
+ overflow-y: hidden;
55297
+ overflow-x: auto;
55298
+
55299
+ &::-webkit-scrollbar {
55300
+ display: none; /* Chrome */
55301
+ }
55302
+ -ms-overflow-style: none; /* IE and Edge */
55303
+ scrollbar-width: none; /* Firefox */
55304
+ }
55277
55305
  }
55278
55306
 
55279
55307
  .o-bottom-bar-arrows {
@@ -57170,7 +57198,7 @@ class Spreadsheet extends owl.Component {
57170
57198
 
57171
57199
  class LocalTransportService {
57172
57200
  listeners = [];
57173
- sendMessage(message) {
57201
+ async sendMessage(message) {
57174
57202
  for (const { callback } of this.listeners) {
57175
57203
  callback(message);
57176
57204
  }
@@ -59007,17 +59035,13 @@ function addFormula(cell) {
59007
59035
  if (!formula) {
59008
59036
  return { attrs: [], node: escapeXml `` };
59009
59037
  }
59010
- const attrs = [];
59011
- let node = escapeXml ``;
59012
- let cycle = escapeXml ``;
59013
- const XlsxFormula = adaptFormulaToExcel(formula);
59014
- // hack for cycles : if we don't set a value (be it 0 or #VALUE!), it will appear as invisible on excel,
59015
- // Making it very hard for the client to find where the recursion is.
59016
- if (cell.value === CellErrorType.CircularDependency) {
59017
- attrs.push(["t", "str"]);
59018
- cycle = escapeXml /*xml*/ `<v>${cell.value}</v>`;
59038
+ const type = getCellType(cell.value);
59039
+ if (type === undefined) {
59040
+ return { attrs: [], node: escapeXml `` };
59019
59041
  }
59020
- node = escapeXml /*xml*/ `<f>${XlsxFormula}</f>${cycle}`;
59042
+ const attrs = [["t", type]];
59043
+ const XlsxFormula = adaptFormulaToExcel(formula);
59044
+ const node = escapeXml /*xml*/ `<f>${XlsxFormula}</f><v>${cell.value}</v>`;
59021
59045
  return { attrs, node };
59022
59046
  }
59023
59047
  function addContent(content, sharedStrings, forceString = false) {
@@ -60369,8 +60393,8 @@ class Model extends EventBus {
60369
60393
  joinSession() {
60370
60394
  this.session.join(this.config.client);
60371
60395
  }
60372
- leaveSession() {
60373
- this.session.leave(lazy(() => this.exportData()));
60396
+ async leaveSession() {
60397
+ await this.session.leave(lazy(() => this.exportData()));
60374
60398
  }
60375
60399
  setupUiPlugin(Plugin) {
60376
60400
  const plugin = new Plugin(this.uiPluginConfig);
@@ -60924,6 +60948,6 @@ exports.tokenColors = tokenColors;
60924
60948
  exports.tokenize = tokenize;
60925
60949
 
60926
60950
 
60927
- __info__.version = "17.2.21";
60928
- __info__.date = "2024-08-19T08:10:10.580Z";
60929
- __info__.hash = "fb17f9c";
60951
+ __info__.version = "17.2.23";
60952
+ __info__.date = "2024-09-05T09:32:03.325Z";
60953
+ __info__.hash = "e5e2be8";
@@ -3354,7 +3354,7 @@ interface TransportService<T = any> {
3354
3354
  /**
3355
3355
  * Send a message to all clients
3356
3356
  */
3357
- sendMessage: (message: T) => void;
3357
+ sendMessage: (message: T) => Promise<void>;
3358
3358
  /**
3359
3359
  * Register a callback function which will be called each time
3360
3360
  * a new message is received.
@@ -3451,11 +3451,11 @@ declare class Session extends EventBus<CollaborativeEvent> {
3451
3451
  /**
3452
3452
  * Notify the server that the user client left the collaborative session
3453
3453
  */
3454
- leave(data: Lazy<WorkbookData>): void;
3454
+ leave(data: Lazy<WorkbookData>): Promise<void>;
3455
3455
  /**
3456
3456
  * Send a snapshot of the spreadsheet to the collaboration server
3457
3457
  */
3458
- snapshot(data: WorkbookData): void;
3458
+ snapshot(data: WorkbookData): Promise<void>;
3459
3459
  getClient(): Client;
3460
3460
  getConnectedClients(): Set<Client>;
3461
3461
  getRevisionId(): UID;
@@ -4227,6 +4227,7 @@ declare class GridSelectionPlugin extends UIPlugin {
4227
4227
  allowDispatch(cmd: LocalCommand): CommandResult;
4228
4228
  private handleEvent;
4229
4229
  handle(cmd: Command): void;
4230
+ finalize(): void;
4230
4231
  isGridSelectionActive(): boolean;
4231
4232
  getActiveSheet(): Readonly<Sheet>;
4232
4233
  getActiveSheetId(): UID;
@@ -5167,7 +5168,7 @@ declare class Model extends EventBus<any> implements CommandDispatcher {
5167
5168
  private readonly coreHandlers;
5168
5169
  constructor(data?: any, config?: Partial<ModelConfig>, stateUpdateMessages?: StateUpdateMessage[], uuidGenerator?: UuidGenerator, verboseImport?: boolean);
5169
5170
  joinSession(): void;
5170
- leaveSession(): void;
5171
+ leaveSession(): Promise<void>;
5171
5172
  private setupUiPlugin;
5172
5173
  /**
5173
5174
  * Initialize and properly configure a plugin.
@@ -7968,15 +7969,13 @@ declare class FindAndReplaceStore extends SpreadsheetStore implements HighlightP
7968
7969
  toSearch: string;
7969
7970
  toReplace: string;
7970
7971
  searchOptions: SearchOptions;
7971
- updateSearchContent: DebouncedFunction<(toSearch: string) => void>;
7972
7972
  constructor(get: Get);
7973
7973
  get searchMatches(): CellPosition[];
7974
- private _updateSearchContent;
7974
+ updateSearchContent(toSearch: string): void;
7975
7975
  updateSearchOptions(searchOptions: Partial<SearchOptions>): void;
7976
7976
  searchFormulas(showFormula: boolean): void;
7977
7977
  selectPreviousMatch(): void;
7978
7978
  selectNextMatch(): void;
7979
- get pendingSearch(): boolean;
7980
7979
  handle(cmd: Command): void;
7981
7980
  finalize(): void;
7982
7981
  get allSheetMatchesCount(): number;
@@ -3,9 +3,9 @@
3
3
  /**
4
4
  * This file is generated by o-spreadsheet build tools. Do not edit it.
5
5
  * @see https://github.com/odoo/o-spreadsheet
6
- * @version 17.2.21
7
- * @date 2024-08-19T08:10:10.580Z
8
- * @hash fb17f9c
6
+ * @version 17.2.23
7
+ * @date 2024-09-05T09:32:03.325Z
8
+ * @hash e5e2be8
9
9
  */
10
10
 
11
11
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw } from '@odoo/owl';
@@ -5785,9 +5785,11 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
5785
5785
  const targetCell = this.getters.getEvaluatedCell(target);
5786
5786
  const originFormat = origin.cell?.format ?? origin.evaluatedCell.format;
5787
5787
  if (clipboardOption?.pasteOption === "asValue") {
5788
- const locale = this.getters.getLocale();
5789
- const content = formatValue(origin.evaluatedCell.value, { locale });
5790
- this.dispatch("UPDATE_CELL", { ...target, content, format: originFormat });
5788
+ this.dispatch("UPDATE_CELL", {
5789
+ ...target,
5790
+ content: origin.evaluatedCell.value?.toString() || "",
5791
+ format: originFormat,
5792
+ });
5791
5793
  return;
5792
5794
  }
5793
5795
  if (clipboardOption?.pasteOption === "onlyFormat") {
@@ -29876,7 +29878,6 @@ class FindAndReplaceStore extends SpreadsheetStore {
29876
29878
  searchScope: "allSheets",
29877
29879
  specificRange: undefined,
29878
29880
  };
29879
- updateSearchContent = debounce(this._updateSearchContent.bind(this), 200);
29880
29881
  constructor(get) {
29881
29882
  super(get);
29882
29883
  this.initialShowFormulaState = this.model.getters.shouldShowFormulas();
@@ -29885,7 +29886,6 @@ class FindAndReplaceStore extends SpreadsheetStore {
29885
29886
  highlightStore.register(this);
29886
29887
  this.onDispose(() => {
29887
29888
  this.model.dispatch("SET_FORMULA_VISIBILITY", { show: this.initialShowFormulaState });
29888
- this.updateSearchContent.stopDebounce();
29889
29889
  highlightStore.unRegister(this);
29890
29890
  });
29891
29891
  }
@@ -29899,7 +29899,7 @@ class FindAndReplaceStore extends SpreadsheetStore {
29899
29899
  return this.specificRangeMatches;
29900
29900
  }
29901
29901
  }
29902
- _updateSearchContent(toSearch) {
29902
+ updateSearchContent(toSearch) {
29903
29903
  this._updateSearch(toSearch, this.searchOptions);
29904
29904
  }
29905
29905
  updateSearchOptions(searchOptions) {
@@ -29915,9 +29915,6 @@ class FindAndReplaceStore extends SpreadsheetStore {
29915
29915
  selectNextMatch() {
29916
29916
  this.selectNextCell(Direction.next);
29917
29917
  }
29918
- get pendingSearch() {
29919
- return this.updateSearchContent.isDebouncePending();
29920
- }
29921
29918
  handle(cmd) {
29922
29919
  switch (cmd.type) {
29923
29920
  case "SET_FORMULA_VISIBILITY":
@@ -30195,6 +30192,7 @@ class FindAndReplacePanel extends Component {
30195
30192
  searchInput = useRef("searchInput");
30196
30193
  store;
30197
30194
  state;
30195
+ updateSearchContent;
30198
30196
  get hasSearchResult() {
30199
30197
  return this.store.selectedMatchIndex !== null;
30200
30198
  }
@@ -30226,12 +30224,14 @@ class FindAndReplacePanel extends Component {
30226
30224
  this.store = useLocalStore(FindAndReplaceStore);
30227
30225
  this.state = useState({ dataRange: "" });
30228
30226
  onMounted(() => this.searchInput.el?.focus());
30227
+ onWillUnmount(() => this.updateSearchContent.stopDebounce());
30228
+ this.updateSearchContent = debounce(this.store.updateSearchContent, 200);
30229
30229
  }
30230
30230
  onFocusSearch() {
30231
30231
  this.updateDataRange();
30232
30232
  }
30233
30233
  onSearchInput(ev) {
30234
- this.store.updateSearchContent(ev.target?.value || "");
30234
+ this.updateSearchContent(ev.target.value);
30235
30235
  }
30236
30236
  onKeydownSearch(ev) {
30237
30237
  if (ev.key === "Enter") {
@@ -30270,6 +30270,9 @@ class FindAndReplacePanel extends Component {
30270
30270
  const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.state.dataRange);
30271
30271
  this.store.updateSearchOptions({ specificRange });
30272
30272
  }
30273
+ get pendingSearch() {
30274
+ return this.updateSearchContent.isDebouncePending();
30275
+ }
30273
30276
  }
30274
30277
 
30275
30278
  css /* scss */ `
@@ -31072,10 +31075,6 @@ class TablePanel extends Component {
31072
31075
  });
31073
31076
  }
31074
31077
  onRangeChanged(ranges) {
31075
- if (!ranges[0] || !ranges[0].match(rangeReference)) {
31076
- this.state.tableZoneErrors = ["InvalidRange" /* CommandResult.InvalidRange */];
31077
- return;
31078
- }
31079
31078
  const sheetId = this.env.model.getters.getActiveSheetId();
31080
31079
  this.state.tableXc = ranges[0];
31081
31080
  this.state.tableZoneErrors = this.env.model.canDispatch("UPDATE_TABLE", {
@@ -31099,10 +31098,6 @@ class TablePanel extends Component {
31099
31098
  cell: position,
31100
31099
  });
31101
31100
  }
31102
- this.state.tableZoneErrors = [];
31103
- this.state.tableXc = result.isSuccessful
31104
- ? this.state.tableXc
31105
- : this.env.model.getters.getRangeString(this.props.table.range, sheetId);
31106
31101
  }
31107
31102
  deleteTable() {
31108
31103
  const sheetId = this.env.model.getters.getActiveSheetId();
@@ -37595,6 +37590,18 @@ function convertOperator(operator) {
37595
37590
  // -------------------------------------
37596
37591
  // WORKSHEET HELPERS
37597
37592
  // -------------------------------------
37593
+ function getCellType(value) {
37594
+ switch (typeof value) {
37595
+ case "boolean":
37596
+ return "b";
37597
+ case "string":
37598
+ return "str";
37599
+ case "number":
37600
+ return "n";
37601
+ default:
37602
+ return undefined;
37603
+ }
37604
+ }
37598
37605
  function convertHeightToExcel(height) {
37599
37606
  return Math.round(HEIGHT_FACTOR * height * 100) / 100;
37600
37607
  }
@@ -42996,7 +43003,10 @@ class HeaderSizePlugin extends CorePlugin {
42996
43003
  handle(cmd) {
42997
43004
  switch (cmd.type) {
42998
43005
  case "CREATE_SHEET": {
42999
- this.history.update("sizes", cmd.sheetId, { COL: [], ROW: [] });
43006
+ this.history.update("sizes", cmd.sheetId, {
43007
+ COL: Array(this.getters.getNumberCols(cmd.sheetId)).fill(undefined),
43008
+ ROW: Array(this.getters.getNumberRows(cmd.sheetId)).fill(undefined),
43009
+ });
43000
43010
  break;
43001
43011
  }
43002
43012
  case "DUPLICATE_SHEET":
@@ -50427,9 +50437,9 @@ class Session extends EventBus {
50427
50437
  /**
50428
50438
  * Notify the server that the user client left the collaborative session
50429
50439
  */
50430
- leave(data) {
50440
+ async leave(data) {
50431
50441
  if (Object.keys(this.clients).length === 1 && this.processedRevisions.size) {
50432
- this.snapshot(data());
50442
+ await this.snapshot(data());
50433
50443
  }
50434
50444
  delete this.clients[this.clientId];
50435
50445
  this.transportService.leave(this.clientId);
@@ -50442,12 +50452,12 @@ class Session extends EventBus {
50442
50452
  /**
50443
50453
  * Send a snapshot of the spreadsheet to the collaboration server
50444
50454
  */
50445
- snapshot(data) {
50455
+ async snapshot(data) {
50446
50456
  if (this.pendingMessages.length !== 0) {
50447
50457
  return;
50448
50458
  }
50449
50459
  const snapshotId = this.uuidGenerator.uuidv4();
50450
- this.transportService.sendMessage({
50460
+ await this.transportService.sendMessage({
50451
50461
  type: "SNAPSHOT",
50452
50462
  nextRevisionId: snapshotId,
50453
50463
  serverRevisionId: this.serverRevisionId,
@@ -52362,6 +52372,7 @@ class ClipboardPlugin extends UIPlugin {
52362
52372
  this.status = "invisible";
52363
52373
  if (this._isCutOperation) {
52364
52374
  this.copiedData = undefined;
52375
+ this._isCutOperation = false;
52365
52376
  }
52366
52377
  break;
52367
52378
  }
@@ -52459,6 +52470,7 @@ class ClipboardPlugin extends UIPlugin {
52459
52470
  }
52460
52471
  case "ACTIVATE_PAINT_FORMAT": {
52461
52472
  const zones = this.getters.getSelectedZones();
52473
+ this._isCutOperation = false;
52462
52474
  this.copiedData = this.copy(zones);
52463
52475
  this.status = "visible";
52464
52476
  if (cmd.persistent) {
@@ -53214,6 +53226,8 @@ class GridSelectionPlugin extends UIPlugin {
53214
53226
  this.selectedFigureId = null;
53215
53227
  break;
53216
53228
  }
53229
+ }
53230
+ finalize() {
53217
53231
  /** Any change to the selection has to be reflected in the selection processor. */
53218
53232
  this.selection.resetDefaultAnchor(this, deepCopy(this.gridSelection.anchor));
53219
53233
  }
@@ -54042,7 +54056,6 @@ class SheetViewPlugin extends UIPlugin {
54042
54056
  }
54043
54057
  }
54044
54058
  handle(cmd) {
54045
- this.cleanViewports();
54046
54059
  // changing the evaluation can hide/show rows because of data filters
54047
54060
  if (invalidateEvaluationCommands.has(cmd.type)) {
54048
54061
  for (const sheetId of this.getters.getSheetIds()) {
@@ -54058,6 +54071,7 @@ class SheetViewPlugin extends UIPlugin {
54058
54071
  break;
54059
54072
  case "UNDO":
54060
54073
  case "REDO":
54074
+ this.cleanViewports();
54061
54075
  for (const sheetId of this.getters.getSheetIds()) {
54062
54076
  this.sheetsWithDirtyViewports.add(sheetId);
54063
54077
  }
@@ -54112,6 +54126,9 @@ class SheetViewPlugin extends UIPlugin {
54112
54126
  }
54113
54127
  }
54114
54128
  break;
54129
+ case "DELETE_SHEET":
54130
+ this.cleanViewports();
54131
+ break;
54115
54132
  case "ACTIVATE_SHEET":
54116
54133
  this.sheetsWithDirtyViewports.add(cmd.sheetIdTo);
54117
54134
  break;
@@ -55272,6 +55289,17 @@ css /* scss */ `
55272
55289
  .o-bottom-bar-fade-in {
55273
55290
  background-image: linear-gradient(90deg, #cfcfcf, transparent 1%);
55274
55291
  }
55292
+
55293
+ .o-sheet-list {
55294
+ overflow-y: hidden;
55295
+ overflow-x: auto;
55296
+
55297
+ &::-webkit-scrollbar {
55298
+ display: none; /* Chrome */
55299
+ }
55300
+ -ms-overflow-style: none; /* IE and Edge */
55301
+ scrollbar-width: none; /* Firefox */
55302
+ }
55275
55303
  }
55276
55304
 
55277
55305
  .o-bottom-bar-arrows {
@@ -57168,7 +57196,7 @@ class Spreadsheet extends Component {
57168
57196
 
57169
57197
  class LocalTransportService {
57170
57198
  listeners = [];
57171
- sendMessage(message) {
57199
+ async sendMessage(message) {
57172
57200
  for (const { callback } of this.listeners) {
57173
57201
  callback(message);
57174
57202
  }
@@ -59005,17 +59033,13 @@ function addFormula(cell) {
59005
59033
  if (!formula) {
59006
59034
  return { attrs: [], node: escapeXml `` };
59007
59035
  }
59008
- const attrs = [];
59009
- let node = escapeXml ``;
59010
- let cycle = escapeXml ``;
59011
- const XlsxFormula = adaptFormulaToExcel(formula);
59012
- // hack for cycles : if we don't set a value (be it 0 or #VALUE!), it will appear as invisible on excel,
59013
- // Making it very hard for the client to find where the recursion is.
59014
- if (cell.value === CellErrorType.CircularDependency) {
59015
- attrs.push(["t", "str"]);
59016
- cycle = escapeXml /*xml*/ `<v>${cell.value}</v>`;
59036
+ const type = getCellType(cell.value);
59037
+ if (type === undefined) {
59038
+ return { attrs: [], node: escapeXml `` };
59017
59039
  }
59018
- node = escapeXml /*xml*/ `<f>${XlsxFormula}</f>${cycle}`;
59040
+ const attrs = [["t", type]];
59041
+ const XlsxFormula = adaptFormulaToExcel(formula);
59042
+ const node = escapeXml /*xml*/ `<f>${XlsxFormula}</f><v>${cell.value}</v>`;
59019
59043
  return { attrs, node };
59020
59044
  }
59021
59045
  function addContent(content, sharedStrings, forceString = false) {
@@ -60367,8 +60391,8 @@ class Model extends EventBus {
60367
60391
  joinSession() {
60368
60392
  this.session.join(this.config.client);
60369
60393
  }
60370
- leaveSession() {
60371
- this.session.leave(lazy(() => this.exportData()));
60394
+ async leaveSession() {
60395
+ await this.session.leave(lazy(() => this.exportData()));
60372
60396
  }
60373
60397
  setupUiPlugin(Plugin) {
60374
60398
  const plugin = new Plugin(this.uiPluginConfig);
@@ -60881,6 +60905,6 @@ const constants = {
60881
60905
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
60882
60906
 
60883
60907
 
60884
- __info__.version = "17.2.21";
60885
- __info__.date = "2024-08-19T08:10:10.580Z";
60886
- __info__.hash = "fb17f9c";
60908
+ __info__.version = "17.2.23";
60909
+ __info__.date = "2024-09-05T09:32:03.325Z";
60910
+ __info__.hash = "e5e2be8";