@odoo/o-spreadsheet 17.0.59 → 17.0.61

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 17.0.59
6
- * @date 2025-04-25T08:04:05.375Z
7
- * @hash eb92388
5
+ * @version 17.0.61
6
+ * @date 2025-05-12T05:21:02.159Z
7
+ * @hash 0368641
8
8
  */
9
9
 
10
10
  'use strict';
@@ -4486,6 +4486,25 @@ function moveHeaderIndexesOnHeaderDeletion(deletedHeaders, headers) {
4486
4486
  })
4487
4487
  .filter(isDefined$1);
4488
4488
  }
4489
+ function getNextSheetName(existingNames, baseName = "Sheet") {
4490
+ let i = 1;
4491
+ let name = `${baseName}${i}`;
4492
+ while (existingNames.includes(name)) {
4493
+ name = `${baseName}${i}`;
4494
+ i++;
4495
+ }
4496
+ return name;
4497
+ }
4498
+ function getDuplicateSheetName(nameToDuplicate, existingNames) {
4499
+ let i = 1;
4500
+ const baseName = _t("Copy of %s", nameToDuplicate);
4501
+ let name = baseName.toString();
4502
+ while (existingNames.includes(name)) {
4503
+ name = `${baseName} (${i})`;
4504
+ i++;
4505
+ }
4506
+ return name;
4507
+ }
4489
4508
 
4490
4509
  function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
4491
4510
  return numberOfLines * (textLineHeight + MIN_CELL_TEXT_MARGIN) - MIN_CELL_TEXT_MARGIN;
@@ -8028,10 +8047,13 @@ const duplicateSheet = {
8028
8047
  name: _t("Duplicate"),
8029
8048
  execute: (env) => {
8030
8049
  const sheetIdFrom = env.model.getters.getActiveSheetId();
8050
+ const sheetNameFrom = env.model.getters.getSheetName(sheetIdFrom);
8031
8051
  const sheetIdTo = env.model.uuidGenerator.smallUuid();
8052
+ const sheetNameTo = env.model.getters.getDuplicateSheetName(sheetNameFrom);
8032
8053
  env.model.dispatch("DUPLICATE_SHEET", {
8033
8054
  sheetId: sheetIdFrom,
8034
8055
  sheetIdTo,
8056
+ sheetNameTo,
8035
8057
  });
8036
8058
  env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom, sheetIdTo });
8037
8059
  },
@@ -8791,9 +8813,6 @@ class BarChart extends AbstractChart {
8791
8813
  };
8792
8814
  }
8793
8815
  getDefinitionForExcel() {
8794
- // Excel does not support aggregating labels
8795
- if (this.aggregated)
8796
- return undefined;
8797
8816
  const dataSets = this.dataSets
8798
8817
  .map((ds) => toExcelDataset(this.getters, ds))
8799
8818
  .filter((ds) => ds.range !== "" && ds.range !== INCORRECT_RANGE_STRING);
@@ -9370,9 +9389,6 @@ class LineChart extends AbstractChart {
9370
9389
  return new LineChart(definition, this.sheetId, this.getters);
9371
9390
  }
9372
9391
  getDefinitionForExcel() {
9373
- // Excel does not support aggregating labels
9374
- if (this.aggregated)
9375
- return undefined;
9376
9392
  const dataSets = this.dataSets
9377
9393
  .map((ds) => toExcelDataset(this.getters, ds))
9378
9394
  .filter((ds) => ds.range !== "" && ds.range !== INCORRECT_RANGE_STRING);
@@ -9678,9 +9694,6 @@ class PieChart extends AbstractChart {
9678
9694
  return new PieChart(definition, sheetId, this.getters);
9679
9695
  }
9680
9696
  getDefinitionForExcel() {
9681
- // Excel does not support aggregating labels
9682
- if (this.aggregated)
9683
- return undefined;
9684
9697
  const dataSets = this.dataSets
9685
9698
  .map((ds) => toExcelDataset(this.getters, ds))
9686
9699
  .filter((ds) => ds.range !== "" && ds.range !== INCORRECT_RANGE_STRING);
@@ -27158,6 +27171,13 @@ class Composer extends owl.Component {
27158
27171
  this.props.onInputContextMenu?.(ev);
27159
27172
  }
27160
27173
  }
27174
+ onWheel(event) {
27175
+ // detect if scrollbar is available
27176
+ if (this.composerRef.el &&
27177
+ this.composerRef.el.scrollHeight > this.composerRef.el.clientHeight) {
27178
+ event.stopPropagation();
27179
+ }
27180
+ }
27161
27181
  // ---------------------------------------------------------------------------
27162
27182
  // Private
27163
27183
  // ---------------------------------------------------------------------------
@@ -27466,12 +27486,15 @@ class GridComposer extends owl.Component {
27466
27486
  });
27467
27487
  }
27468
27488
  get composerProps() {
27489
+ // Remove the wrapper border width
27490
+ const maxHeight = this.props.gridDims.height - this.rect.y - 2 * COMPOSER_BORDER_WIDTH;
27469
27491
  return {
27470
27492
  focus: this.props.focus,
27471
27493
  isDefaultFocus: true,
27472
27494
  onComposerContentFocused: this.props.onComposerContentFocused,
27473
27495
  onComposerCellFocused: this.props.onComposerCellFocused,
27474
27496
  onInputContextMenu: this.props.onInputContextMenu,
27497
+ inputStyle: `max-height: ${maxHeight}px;`,
27475
27498
  };
27476
27499
  }
27477
27500
  get containerStyle() {
@@ -28484,18 +28507,28 @@ function useRefListener(ref, ...listener) {
28484
28507
  function useInterval(callback, delay) {
28485
28508
  let intervalId;
28486
28509
  const { setInterval, clearInterval } = window;
28510
+ const pause = () => {
28511
+ clearInterval(intervalId);
28512
+ intervalId = undefined;
28513
+ };
28514
+ const safeCallback = () => {
28515
+ try {
28516
+ callback();
28517
+ }
28518
+ catch (e) {
28519
+ pause();
28520
+ throw e;
28521
+ }
28522
+ };
28487
28523
  owl.useEffect(() => {
28488
- intervalId = setInterval(callback, delay);
28524
+ intervalId = setInterval(safeCallback, delay);
28489
28525
  return () => clearInterval(intervalId);
28490
28526
  }, () => [delay]);
28491
28527
  return {
28492
- pause: () => {
28493
- clearInterval(intervalId);
28494
- intervalId = undefined;
28495
- },
28528
+ pause,
28496
28529
  resume: () => {
28497
28530
  if (intervalId === undefined) {
28498
- intervalId = setInterval(callback, delay);
28531
+ intervalId = setInterval(safeCallback, delay);
28499
28532
  }
28500
28533
  },
28501
28534
  };
@@ -28940,7 +28973,7 @@ css /* scss */ `
28940
28973
  position: absolute;
28941
28974
  top: 0;
28942
28975
  left: ${HEADER_WIDTH}px;
28943
- right: 0;
28976
+ right: ${SCROLLBAR_WIDTH}px;
28944
28977
  height: ${HEADER_HEIGHT}px;
28945
28978
  &.o-dragging {
28946
28979
  cursor: grabbing;
@@ -29115,9 +29148,8 @@ css /* scss */ `
29115
29148
  position: absolute;
29116
29149
  top: ${HEADER_HEIGHT}px;
29117
29150
  left: 0;
29118
- right: 0;
29151
+ bottom: ${SCROLLBAR_WIDTH}px;
29119
29152
  width: ${HEADER_WIDTH}px;
29120
- height: calc(100% - ${HEADER_HEIGHT + SCROLLBAR_WIDTH}px);
29121
29153
  &.o-dragging {
29122
29154
  cursor: grabbing;
29123
29155
  }
@@ -34355,6 +34387,7 @@ function repairInitialMessages(data, initialMessages) {
34355
34387
  initialMessages = dropCommands(initialMessages, "SORT_CELLS");
34356
34388
  initialMessages = dropCommands(initialMessages, "SET_DECIMAL");
34357
34389
  initialMessages = fixChartDefinitions(data, initialMessages);
34390
+ initialMessages = fixTranslatedDuplicateSheetName(data, initialMessages);
34358
34391
  return initialMessages;
34359
34392
  }
34360
34393
  /**
@@ -34474,6 +34507,40 @@ function fixOverlappingFilters(data) {
34474
34507
  }
34475
34508
  return data;
34476
34509
  }
34510
+ function fixTranslatedDuplicateSheetName(data, initialMessages) {
34511
+ const sheetNames = {};
34512
+ for (const sheet of data.sheets || []) {
34513
+ sheetNames[sheet.id] = sheet.name;
34514
+ }
34515
+ const messages = [];
34516
+ for (const message of initialMessages) {
34517
+ if (message.type === "REMOTE_REVISION") {
34518
+ const commands = [];
34519
+ for (const cmd of message.commands) {
34520
+ switch (cmd.type) {
34521
+ case "DUPLICATE_SHEET":
34522
+ cmd.sheetNameTo =
34523
+ cmd.sheetNameTo ??
34524
+ getDuplicateSheetName(sheetNames[cmd.sheetId], Object.values(sheetNames));
34525
+ break;
34526
+ case "CREATE_SHEET":
34527
+ case "RENAME_SHEET":
34528
+ sheetNames[cmd.sheetId] = cmd.name || getNextSheetName(Object.values(sheetNames));
34529
+ break;
34530
+ }
34531
+ commands.push(cmd);
34532
+ }
34533
+ messages.push({
34534
+ ...message,
34535
+ commands,
34536
+ });
34537
+ }
34538
+ else {
34539
+ messages.push(message);
34540
+ }
34541
+ }
34542
+ return initialMessages;
34543
+ }
34477
34544
  // -----------------------------------------------------------------------------
34478
34545
  // Helpers
34479
34546
  // -----------------------------------------------------------------------------
@@ -36704,9 +36771,7 @@ class ChartPlugin extends CorePlugin {
36704
36771
  : "Success" /* CommandResult.Success */;
36705
36772
  }
36706
36773
  checkChartExists(cmd) {
36707
- return this.getters.getFigureSheetId(cmd.id)
36708
- ? "Success" /* CommandResult.Success */
36709
- : "ChartDoesNotExist" /* CommandResult.ChartDoesNotExist */;
36774
+ return this.isChartDefined(cmd.id) ? "Success" /* CommandResult.Success */ : "ChartDoesNotExist" /* CommandResult.ChartDoesNotExist */;
36710
36775
  }
36711
36776
  }
36712
36777
 
@@ -39505,6 +39570,7 @@ class SheetPlugin extends CorePlugin {
39505
39570
  "getCommandZones",
39506
39571
  "getUnboundedZone",
39507
39572
  "checkElementsIncludeAllNonFrozenHeaders",
39573
+ "getDuplicateSheetName",
39508
39574
  ];
39509
39575
  sheetIdsMapName = {};
39510
39576
  orderedSheetIds = [];
@@ -39529,7 +39595,11 @@ class SheetPlugin extends CorePlugin {
39529
39595
  return this.checkValidations(cmd, this.checkSheetName, this.checkSheetPosition);
39530
39596
  }
39531
39597
  case "DUPLICATE_SHEET": {
39532
- return this.sheets[cmd.sheetIdTo] ? "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */ : "Success" /* CommandResult.Success */;
39598
+ if (this.sheets[cmd.sheetIdTo])
39599
+ return "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */;
39600
+ if (this.orderedSheetIds.map(this.getSheetName.bind(this)).includes(cmd.sheetNameTo))
39601
+ return "DuplicatedSheetName" /* CommandResult.DuplicatedSheetName */;
39602
+ return "Success" /* CommandResult.Success */;
39533
39603
  }
39534
39604
  case "MOVE_SHEET":
39535
39605
  try {
@@ -39602,7 +39672,7 @@ class SheetPlugin extends CorePlugin {
39602
39672
  this.showSheet(cmd.sheetId);
39603
39673
  break;
39604
39674
  case "DUPLICATE_SHEET":
39605
- this.duplicateSheet(cmd.sheetId, cmd.sheetIdTo);
39675
+ this.duplicateSheet(cmd.sheetId, cmd.sheetIdTo, cmd.sheetNameTo);
39606
39676
  break;
39607
39677
  case "DELETE_SHEET":
39608
39678
  this.deleteSheet(this.sheets[cmd.sheetId]);
@@ -39812,14 +39882,8 @@ class SheetPlugin extends CorePlugin {
39812
39882
  return dimension === "COL" ? this.getNumberCols(sheetId) : this.getNumberRows(sheetId);
39813
39883
  }
39814
39884
  getNextSheetName(baseName = "Sheet") {
39815
- let i = 1;
39816
39885
  const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
39817
- let name = `${baseName}${i}`;
39818
- while (names.includes(name)) {
39819
- name = `${baseName}${i}`;
39820
- i++;
39821
- }
39822
- return name;
39886
+ return getNextSheetName(names, baseName);
39823
39887
  }
39824
39888
  getSheetSize(sheetId) {
39825
39889
  return {
@@ -40079,9 +40143,8 @@ class SheetPlugin extends CorePlugin {
40079
40143
  showSheet(sheetId) {
40080
40144
  this.history.update("sheets", sheetId, "isVisible", true);
40081
40145
  }
40082
- duplicateSheet(fromId, toId) {
40146
+ duplicateSheet(fromId, toId, toName) {
40083
40147
  const sheet = this.getSheet(fromId);
40084
- const toName = this.getDuplicateSheetName(sheet.name);
40085
40148
  const newSheet = deepCopy(sheet);
40086
40149
  newSheet.id = toId;
40087
40150
  newSheet.name = toName;
@@ -40113,15 +40176,8 @@ class SheetPlugin extends CorePlugin {
40113
40176
  this.history.update("sheetIdsMapName", sheetIdsMapName);
40114
40177
  }
40115
40178
  getDuplicateSheetName(sheetName) {
40116
- let i = 1;
40117
40179
  const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
40118
- const baseName = _t("Copy of %s", sheetName);
40119
- let name = baseName.toString();
40120
- while (names.includes(name)) {
40121
- name = `${baseName} (${i})`;
40122
- i++;
40123
- }
40124
- return name;
40180
+ return getDuplicateSheetName(sheetName, names);
40125
40181
  }
40126
40182
  deleteSheet(sheet) {
40127
40183
  const name = sheet.name;
@@ -50605,6 +50661,8 @@ class GridSelectionPlugin extends UIPlugin {
50605
50661
  });
50606
50662
  this.selectCell(col, row);
50607
50663
  }
50664
+ const { col, row } = this.gridSelection.anchor.cell;
50665
+ this.moveClient({ sheetId: this.activeSheet.id, col, row });
50608
50666
  }
50609
50667
  /**
50610
50668
  * Ensure selections are not outside sheet boundaries.
@@ -51344,8 +51402,11 @@ class SheetViewPlugin extends UIPlugin {
51344
51402
  }
51345
51403
  case "REMOVE_FILTER_TABLE":
51346
51404
  case "UPDATE_FILTER":
51347
- this.sheetsWithDirtyViewports.add(cmd.sheetId);
51348
- break;
51405
+ case "UNFREEZE_ROWS":
51406
+ case "UNFREEZE_COLUMNS":
51407
+ case "FREEZE_COLUMNS":
51408
+ case "FREEZE_ROWS":
51409
+ case "UNFREEZE_COLUMNS_ROWS":
51349
51410
  case "REMOVE_COLUMNS_ROWS":
51350
51411
  case "RESIZE_COLUMNS_ROWS":
51351
51412
  case "HIDE_COLUMNS_ROWS":
@@ -51358,11 +51419,9 @@ class SheetViewPlugin extends UIPlugin {
51358
51419
  case "FOLD_HEADER_GROUPS_IN_ZONE":
51359
51420
  case "UNFOLD_HEADER_GROUPS_IN_ZONE":
51360
51421
  case "UNFOLD_ALL_HEADER_GROUPS":
51361
- case "FOLD_ALL_HEADER_GROUPS": {
51362
- const sheetId = "sheetId" in cmd ? cmd.sheetId : this.getters.getActiveSheetId();
51363
- this.sheetsWithDirtyViewports.add(sheetId);
51422
+ case "FOLD_ALL_HEADER_GROUPS":
51423
+ this.sheetsWithDirtyViewports.add(cmd.sheetId);
51364
51424
  break;
51365
- }
51366
51425
  case "UPDATE_CELL":
51367
51426
  // update cell content or format can change hidden rows because of data filters
51368
51427
  if ("content" in cmd || "format" in cmd || cmd.style?.fontSize !== undefined) {
@@ -51378,13 +51437,6 @@ class SheetViewPlugin extends UIPlugin {
51378
51437
  case "ACTIVATE_SHEET":
51379
51438
  this.sheetsWithDirtyViewports.add(cmd.sheetIdTo);
51380
51439
  break;
51381
- case "UNFREEZE_ROWS":
51382
- case "UNFREEZE_COLUMNS":
51383
- case "FREEZE_COLUMNS":
51384
- case "FREEZE_ROWS":
51385
- case "UNFREEZE_COLUMNS_ROWS":
51386
- this.resetViewports(this.getters.getActiveSheetId());
51387
- break;
51388
51440
  case "DELETE_SHEET":
51389
51441
  this.sheetsWithDirtyViewports.delete(cmd.sheetId);
51390
51442
  break;
@@ -58256,6 +58308,6 @@ exports.setTranslationMethod = setTranslationMethod;
58256
58308
  exports.tokenize = tokenize;
58257
58309
 
58258
58310
 
58259
- __info__.version = "17.0.59";
58260
- __info__.date = "2025-04-25T08:04:05.375Z";
58261
- __info__.hash = "eb92388";
58311
+ __info__.version = "17.0.61";
58312
+ __info__.date = "2025-05-12T05:21:02.159Z";
58313
+ __info__.hash = "0368641";
@@ -1892,6 +1892,7 @@ interface DeleteSheetCommand extends SheetDependentCommand {
1892
1892
  interface DuplicateSheetCommand extends SheetDependentCommand {
1893
1893
  type: "DUPLICATE_SHEET";
1894
1894
  sheetIdTo: UID;
1895
+ sheetNameTo: string;
1895
1896
  }
1896
1897
  interface MoveSheetCommand extends SheetDependentCommand {
1897
1898
  type: "MOVE_SHEET";
@@ -4030,7 +4031,7 @@ interface SheetState {
4030
4031
  readonly cellPosition: Record<UID, CellPosition | undefined>;
4031
4032
  }
4032
4033
  declare class SheetPlugin extends CorePlugin<SheetState> implements SheetState {
4033
- static getters: readonly ["getSheetName", "tryGetSheetName", "getSheet", "tryGetSheet", "getSheetIdByName", "getSheetIds", "getVisibleSheetIds", "isSheetVisible", "getEvaluationSheets", "doesHeaderExist", "doesHeadersExist", "getCell", "getCellPosition", "getColsZone", "getRowCells", "getRowsZone", "getNumberCols", "getNumberRows", "getNumberHeaders", "getGridLinesVisibility", "getNextSheetName", "getSheetSize", "getSheetZone", "getPaneDivisions", "checkZonesExistInSheet", "getCommandZones", "getUnboundedZone", "checkElementsIncludeAllNonFrozenHeaders"];
4034
+ static getters: readonly ["getSheetName", "tryGetSheetName", "getSheet", "tryGetSheet", "getSheetIdByName", "getSheetIds", "getVisibleSheetIds", "isSheetVisible", "getEvaluationSheets", "doesHeaderExist", "doesHeadersExist", "getCell", "getCellPosition", "getColsZone", "getRowCells", "getRowsZone", "getNumberCols", "getNumberRows", "getNumberHeaders", "getGridLinesVisibility", "getNextSheetName", "getSheetSize", "getSheetZone", "getPaneDivisions", "checkZonesExistInSheet", "getCommandZones", "getUnboundedZone", "checkElementsIncludeAllNonFrozenHeaders", "getDuplicateSheetName"];
4034
4035
  readonly sheetIdsMapName: Record<string, UID | undefined>;
4035
4036
  readonly orderedSheetIds: UID[];
4036
4037
  readonly sheets: Record<UID, Sheet | undefined>;
@@ -4110,7 +4111,7 @@ declare class SheetPlugin extends CorePlugin<SheetState> implements SheetState {
4110
4111
  private hideSheet;
4111
4112
  private showSheet;
4112
4113
  private duplicateSheet;
4113
- private getDuplicateSheetName;
4114
+ getDuplicateSheetName(sheetName: string): string;
4114
4115
  private deleteSheet;
4115
4116
  /**
4116
4117
  * Delete column. This requires a lot of handling:
@@ -7342,6 +7343,7 @@ declare class Composer extends Component<ComposerProps, SpreadsheetChildEnv> {
7342
7343
  onClick(): void;
7343
7344
  onDblClick(): void;
7344
7345
  onContextMenu(ev: MouseEvent): void;
7346
+ onWheel(event: WheelEvent): void;
7345
7347
  private processContent;
7346
7348
  /**
7347
7349
  * Get the HTML content corresponding to the current composer token, divided by lines.