@odoo/o-spreadsheet 18.0.26 → 18.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,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 18.0.26
6
- * @date 2025-05-02T12:30:31.966Z
7
- * @hash 5bdf504
5
+ * @version 18.0.27
6
+ * @date 2025-05-12T05:25:47.149Z
7
+ * @hash 9b36340
8
8
  */
9
9
 
10
10
  'use strict';
@@ -6104,6 +6104,25 @@ function moveHeaderIndexesOnHeaderDeletion(deletedHeaders, headers) {
6104
6104
  })
6105
6105
  .filter(isDefined);
6106
6106
  }
6107
+ function getNextSheetName(existingNames, baseName = "Sheet") {
6108
+ let i = 1;
6109
+ let name = `${baseName}${i}`;
6110
+ while (existingNames.includes(name)) {
6111
+ name = `${baseName}${i}`;
6112
+ i++;
6113
+ }
6114
+ return name;
6115
+ }
6116
+ function getDuplicateSheetName(nameToDuplicate, existingNames) {
6117
+ let i = 1;
6118
+ const baseName = _t("Copy of %s", nameToDuplicate);
6119
+ let name = baseName.toString();
6120
+ while (existingNames.includes(name)) {
6121
+ name = `${baseName} (${i})`;
6122
+ i++;
6123
+ }
6124
+ return name;
6125
+ }
6107
6126
 
6108
6127
  function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
6109
6128
  return numberOfLines * (textLineHeight + MIN_CELL_TEXT_MARGIN) - MIN_CELL_TEXT_MARGIN;
@@ -7792,6 +7811,24 @@ const monthNumberAdapter = {
7792
7811
  return `${normalizedValue}`;
7793
7812
  },
7794
7813
  };
7814
+ /**
7815
+ * normalizes month number + year
7816
+ */
7817
+ const monthAdapter = {
7818
+ normalizeFunctionValue(value) {
7819
+ const date = toNumber(value, DEFAULT_LOCALE);
7820
+ return formatValue(date, { locale: DEFAULT_LOCALE, format: "mm/yyyy" });
7821
+ },
7822
+ toValueAndFormat(normalizedValue) {
7823
+ return {
7824
+ value: toNumber(normalizedValue, DEFAULT_LOCALE),
7825
+ format: "mmmm yyyy",
7826
+ };
7827
+ },
7828
+ toFunctionValue(normalizedValue) {
7829
+ return `"${normalizedValue}"`;
7830
+ },
7831
+ };
7795
7832
  /**
7796
7833
  * normalizes quarter number
7797
7834
  */
@@ -7922,6 +7959,7 @@ pivotTimeAdapterRegistry
7922
7959
  .add("day_of_month", nullHandlerDecorator(dayOfMonthAdapter))
7923
7960
  .add("iso_week_number", nullHandlerDecorator(isoWeekNumberAdapter))
7924
7961
  .add("month_number", nullHandlerDecorator(monthNumberAdapter))
7962
+ .add("month", nullHandlerDecorator(monthAdapter))
7925
7963
  .add("quarter_number", nullHandlerDecorator(quarterNumberAdapter))
7926
7964
  .add("day_of_week", nullHandlerDecorator(dayOfWeekAdapter))
7927
7965
  .add("hour_number", nullHandlerDecorator(hourNumberAdapter))
@@ -8102,10 +8140,7 @@ function toNormalizedPivotValue(dimension, groupValue) {
8102
8140
  return normalizer(groupValueString, dimension.granularity);
8103
8141
  }
8104
8142
  function normalizeDateTime(value, granularity) {
8105
- if (!granularity) {
8106
- throw new Error("Missing granularity");
8107
- }
8108
- return pivotTimeAdapter(granularity).normalizeFunctionValue(value);
8143
+ return pivotTimeAdapter(granularity ?? "month").normalizeFunctionValue(value);
8109
8144
  }
8110
8145
  function toFunctionPivotValue(value, dimension) {
8111
8146
  if (value === null) {
@@ -8117,10 +8152,7 @@ function toFunctionPivotValue(value, dimension) {
8117
8152
  return pivotToFunctionValueRegistry.get(dimension.type)(value, dimension.granularity);
8118
8153
  }
8119
8154
  function toFunctionValueDateTime(value, granularity) {
8120
- if (!granularity) {
8121
- throw new Error("Missing granularity");
8122
- }
8123
- return pivotTimeAdapter(granularity).toFunctionValue(value);
8155
+ return pivotTimeAdapter(granularity ?? "month").toFunctionValue(value);
8124
8156
  }
8125
8157
  const pivotNormalizationValueRegistry = new Registry();
8126
8158
  pivotNormalizationValueRegistry
@@ -15253,6 +15285,7 @@ function repairInitialMessages(data, initialMessages) {
15253
15285
  initialMessages = dropCommands(initialMessages, "SORT_CELLS");
15254
15286
  initialMessages = dropCommands(initialMessages, "SET_DECIMAL");
15255
15287
  initialMessages = fixChartDefinitions(data, initialMessages);
15288
+ initialMessages = fixTranslatedDuplicateSheetName(data, initialMessages);
15256
15289
  return initialMessages;
15257
15290
  }
15258
15291
  /**
@@ -15352,6 +15385,40 @@ function fixChartDefinitions(data, initialMessages) {
15352
15385
  }
15353
15386
  return messages;
15354
15387
  }
15388
+ function fixTranslatedDuplicateSheetName(data, initialMessages) {
15389
+ const sheetNames = {};
15390
+ for (const sheet of data.sheets || []) {
15391
+ sheetNames[sheet.id] = sheet.name;
15392
+ }
15393
+ const messages = [];
15394
+ for (const message of initialMessages) {
15395
+ if (message.type === "REMOTE_REVISION") {
15396
+ const commands = [];
15397
+ for (const cmd of message.commands) {
15398
+ switch (cmd.type) {
15399
+ case "DUPLICATE_SHEET":
15400
+ cmd.sheetNameTo =
15401
+ cmd.sheetNameTo ??
15402
+ getDuplicateSheetName(sheetNames[cmd.sheetId], Object.values(sheetNames));
15403
+ break;
15404
+ case "CREATE_SHEET":
15405
+ case "RENAME_SHEET":
15406
+ sheetNames[cmd.sheetId] = cmd.name || getNextSheetName(Object.values(sheetNames));
15407
+ break;
15408
+ }
15409
+ commands.push(cmd);
15410
+ }
15411
+ messages.push({
15412
+ ...message,
15413
+ commands,
15414
+ });
15415
+ }
15416
+ else {
15417
+ messages.push(message);
15418
+ }
15419
+ }
15420
+ return initialMessages;
15421
+ }
15355
15422
  // -----------------------------------------------------------------------------
15356
15423
  // Helpers
15357
15424
  // -----------------------------------------------------------------------------
@@ -24367,7 +24434,7 @@ const IF = {
24367
24434
  return { value: "" };
24368
24435
  }
24369
24436
  if (result.value === null) {
24370
- result.value = "";
24437
+ return { ...result, value: "" };
24371
24438
  }
24372
24439
  return result;
24373
24440
  },
@@ -24388,7 +24455,7 @@ const IFERROR = {
24388
24455
  return { value: "" };
24389
24456
  }
24390
24457
  if (result.value === null) {
24391
- result.value = "";
24458
+ return { ...result, value: "" };
24392
24459
  }
24393
24460
  return result;
24394
24461
  },
@@ -24409,7 +24476,7 @@ const IFNA = {
24409
24476
  return { value: "" };
24410
24477
  }
24411
24478
  if (result.value === null) {
24412
- result.value = "";
24479
+ return { ...result, value: "" };
24413
24480
  }
24414
24481
  return result;
24415
24482
  },
@@ -24435,7 +24502,7 @@ const IFS = {
24435
24502
  return { value: "" };
24436
24503
  }
24437
24504
  if (result.value === null) {
24438
- result.value = "";
24505
+ return { ...result, value: "" };
24439
24506
  }
24440
24507
  return result;
24441
24508
  }
@@ -24553,6 +24620,11 @@ function addPivotDependencies(evalContext, coreDefinition, forMeasures) {
24553
24620
  if (range === undefined || range.invalidXc || range.invalidSheetName) {
24554
24621
  throw new InvalidReferenceError();
24555
24622
  }
24623
+ if (evalContext.__originCellPosition &&
24624
+ range.sheetId === evalContext.__originSheetId &&
24625
+ isZoneInside(positionToZone(evalContext.__originCellPosition), zone)) {
24626
+ throw new CircularDependencyError();
24627
+ }
24556
24628
  dependencies.push(range);
24557
24629
  }
24558
24630
  for (const measure of forMeasures) {
@@ -27560,6 +27632,13 @@ class Composer extends owl.Component {
27560
27632
  openAssistant() {
27561
27633
  this.assistant.forcedClosed = false;
27562
27634
  }
27635
+ onWheel(event) {
27636
+ // detect if scrollbar is available
27637
+ if (this.composerRef.el &&
27638
+ this.composerRef.el.scrollHeight > this.composerRef.el.clientHeight) {
27639
+ event.stopPropagation();
27640
+ }
27641
+ }
27563
27642
  // ---------------------------------------------------------------------------
27564
27643
  // Private
27565
27644
  // ---------------------------------------------------------------------------
@@ -32559,10 +32638,13 @@ const duplicateSheet = {
32559
32638
  name: _t("Duplicate"),
32560
32639
  execute: (env) => {
32561
32640
  const sheetIdFrom = env.model.getters.getActiveSheetId();
32641
+ const sheetNameFrom = env.model.getters.getSheetName(sheetIdFrom);
32562
32642
  const sheetIdTo = env.model.uuidGenerator.smallUuid();
32643
+ const sheetNameTo = env.model.getters.getDuplicateSheetName(sheetNameFrom);
32563
32644
  env.model.dispatch("DUPLICATE_SHEET", {
32564
32645
  sheetId: sheetIdFrom,
32565
32646
  sheetIdTo,
32647
+ sheetNameTo,
32566
32648
  });
32567
32649
  env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom, sheetIdTo });
32568
32650
  },
@@ -43901,8 +43983,8 @@ function compareDimensionValues(dimension, a, b) {
43901
43983
 
43902
43984
  const NULL_SYMBOL = Symbol("NULL");
43903
43985
  function createDate(dimension, value, locale) {
43904
- const granularity = dimension.granularity;
43905
- if (!granularity || !(granularity in MAP_VALUE_DIMENSION_DATE)) {
43986
+ const granularity = dimension.granularity || "month";
43987
+ if (!(granularity in MAP_VALUE_DIMENSION_DATE)) {
43906
43988
  throw new Error(`Unknown date granularity: ${granularity}`);
43907
43989
  }
43908
43990
  const keyInMap = typeof value === "number" || typeof value === "string" ? value : NULL_SYMBOL;
@@ -43921,6 +44003,9 @@ function createDate(dimension, value, locale) {
43921
44003
  case "month_number":
43922
44004
  number = date.getMonth() + 1;
43923
44005
  break;
44006
+ case "month":
44007
+ number = Math.floor(toNumber(value, locale));
44008
+ break;
43924
44009
  case "iso_week_number":
43925
44010
  number = date.getIsoWeek();
43926
44011
  break;
@@ -44014,6 +44099,10 @@ const MAP_VALUE_DIMENSION_DATE = {
44014
44099
  set: new Set(),
44015
44100
  values: {},
44016
44101
  },
44102
+ month: {
44103
+ set: new Set(),
44104
+ values: {},
44105
+ },
44017
44106
  iso_week_number: {
44018
44107
  set: new Set(),
44019
44108
  values: {},
@@ -44224,7 +44313,7 @@ class SpreadsheetPivot {
44224
44313
  const cells = this.filterDataEntriesFromDomain(this.dataEntries, domain);
44225
44314
  const finalCell = cells[0]?.[dimension.nameWithGranularity];
44226
44315
  if (dimension.type === "datetime") {
44227
- const adapter = pivotTimeAdapter(dimension.granularity);
44316
+ const adapter = pivotTimeAdapter((dimension.granularity || "month"));
44228
44317
  return adapter.toValueAndFormat(lastNode.value, this.getters.getLocale());
44229
44318
  }
44230
44319
  if (!finalCell) {
@@ -44342,7 +44431,7 @@ class SpreadsheetPivot {
44342
44431
  if (nonEmptyCells.length === 0) {
44343
44432
  return "integer";
44344
44433
  }
44345
- if (nonEmptyCells.every((cell) => cell.format && isDateTimeFormat(cell.format))) {
44434
+ if (nonEmptyCells.every((cell) => cell.type === CellValueType.number && cell.format && isDateTimeFormat(cell.format))) {
44346
44435
  return "datetime";
44347
44436
  }
44348
44437
  if (nonEmptyCells.every((cell) => cell.type === CellValueType.boolean)) {
@@ -44437,7 +44526,7 @@ class SpreadsheetPivot {
44437
44526
  for (const entry of dataEntries) {
44438
44527
  for (const dimension of dateDimensions) {
44439
44528
  const value = createDate(dimension, entry[dimension.fieldName]?.value || null, this.getters.getLocale());
44440
- const adapter = pivotTimeAdapter(dimension.granularity);
44529
+ const adapter = pivotTimeAdapter((dimension.granularity || "month"));
44441
44530
  const { format, value: valueToFormat } = adapter.toValueAndFormat(value, locale);
44442
44531
  entry[dimension.nameWithGranularity] = {
44443
44532
  value,
@@ -44457,6 +44546,7 @@ const dateGranularities = [
44457
44546
  "year",
44458
44547
  "quarter_number",
44459
44548
  "month_number",
44549
+ "month",
44460
44550
  "iso_week_number",
44461
44551
  "day_of_month",
44462
44552
  "day",
@@ -44697,7 +44787,7 @@ class PivotSidePanelStore extends SpreadsheetStore {
44697
44787
  : this.datetimeGranularities);
44698
44788
  }
44699
44789
  for (const field of dateFields) {
44700
- granularitiesPerFields[field.fieldName].delete(field.granularity);
44790
+ granularitiesPerFields[field.fieldName].delete(field.granularity || "month");
44701
44791
  }
44702
44792
  return granularitiesPerFields;
44703
44793
  }
@@ -46855,6 +46945,8 @@ class GridComposer extends owl.Component {
46855
46945
  }
46856
46946
  get composerProps() {
46857
46947
  const { width, height } = this.env.model.getters.getSheetViewDimensionWithHeaders();
46948
+ // Remove the wrapper border width
46949
+ const maxHeight = this.props.gridDims.height - this.rect.y - 2 * COMPOSER_BORDER_WIDTH;
46858
46950
  return {
46859
46951
  rect: { ...this.rect },
46860
46952
  delimitation: {
@@ -46872,6 +46964,7 @@ class GridComposer extends owl.Component {
46872
46964
  }),
46873
46965
  onInputContextMenu: this.props.onInputContextMenu,
46874
46966
  composerStore: this.composerStore,
46967
+ inputStyle: `max-height: ${maxHeight}px;`,
46875
46968
  };
46876
46969
  }
46877
46970
  get containerStyle() {
@@ -52271,9 +52364,7 @@ class ChartPlugin extends CorePlugin {
52271
52364
  : "Success" /* CommandResult.Success */;
52272
52365
  }
52273
52366
  checkChartExists(cmd) {
52274
- return this.getters.getFigureSheetId(cmd.id)
52275
- ? "Success" /* CommandResult.Success */
52276
- : "ChartDoesNotExist" /* CommandResult.ChartDoesNotExist */;
52367
+ return this.isChartDefined(cmd.id) ? "Success" /* CommandResult.Success */ : "ChartDoesNotExist" /* CommandResult.ChartDoesNotExist */;
52277
52368
  }
52278
52369
  }
52279
52370
 
@@ -54534,6 +54625,7 @@ class SheetPlugin extends CorePlugin {
54534
54625
  "getCommandZones",
54535
54626
  "getUnboundedZone",
54536
54627
  "checkElementsIncludeAllNonFrozenHeaders",
54628
+ "getDuplicateSheetName",
54537
54629
  ];
54538
54630
  sheetIdsMapName = {};
54539
54631
  orderedSheetIds = [];
@@ -54558,7 +54650,11 @@ class SheetPlugin extends CorePlugin {
54558
54650
  return this.checkValidations(cmd, this.checkSheetName, this.checkSheetPosition);
54559
54651
  }
54560
54652
  case "DUPLICATE_SHEET": {
54561
- return this.sheets[cmd.sheetIdTo] ? "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */ : "Success" /* CommandResult.Success */;
54653
+ if (this.sheets[cmd.sheetIdTo])
54654
+ return "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */;
54655
+ if (this.orderedSheetIds.map(this.getSheetName.bind(this)).includes(cmd.sheetNameTo))
54656
+ return "DuplicatedSheetName" /* CommandResult.DuplicatedSheetName */;
54657
+ return "Success" /* CommandResult.Success */;
54562
54658
  }
54563
54659
  case "MOVE_SHEET":
54564
54660
  try {
@@ -54635,7 +54731,7 @@ class SheetPlugin extends CorePlugin {
54635
54731
  this.showSheet(cmd.sheetId);
54636
54732
  break;
54637
54733
  case "DUPLICATE_SHEET":
54638
- this.duplicateSheet(cmd.sheetId, cmd.sheetIdTo);
54734
+ this.duplicateSheet(cmd.sheetId, cmd.sheetIdTo, cmd.sheetNameTo);
54639
54735
  break;
54640
54736
  case "DELETE_SHEET":
54641
54737
  this.deleteSheet(this.sheets[cmd.sheetId]);
@@ -54841,14 +54937,8 @@ class SheetPlugin extends CorePlugin {
54841
54937
  return dimension === "COL" ? this.getNumberCols(sheetId) : this.getNumberRows(sheetId);
54842
54938
  }
54843
54939
  getNextSheetName(baseName = "Sheet") {
54844
- let i = 1;
54845
54940
  const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
54846
- let name = `${baseName}${i}`;
54847
- while (names.includes(name)) {
54848
- name = `${baseName}${i}`;
54849
- i++;
54850
- }
54851
- return name;
54941
+ return getNextSheetName(names, baseName);
54852
54942
  }
54853
54943
  getSheetSize(sheetId) {
54854
54944
  return {
@@ -55094,9 +55184,8 @@ class SheetPlugin extends CorePlugin {
55094
55184
  showSheet(sheetId) {
55095
55185
  this.history.update("sheets", sheetId, "isVisible", true);
55096
55186
  }
55097
- duplicateSheet(fromId, toId) {
55187
+ duplicateSheet(fromId, toId, toName) {
55098
55188
  const sheet = this.getSheet(fromId);
55099
- const toName = this.getDuplicateSheetName(sheet.name);
55100
55189
  const newSheet = deepCopy(sheet);
55101
55190
  newSheet.id = toId;
55102
55191
  newSheet.name = toName;
@@ -55128,15 +55217,8 @@ class SheetPlugin extends CorePlugin {
55128
55217
  this.history.update("sheetIdsMapName", sheetIdsMapName);
55129
55218
  }
55130
55219
  getDuplicateSheetName(sheetName) {
55131
- let i = 1;
55132
55220
  const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
55133
- const baseName = _t("Copy of %s", sheetName);
55134
- let name = baseName.toString();
55135
- while (names.includes(name)) {
55136
- name = `${baseName} (${i})`;
55137
- i++;
55138
- }
55139
- return name;
55221
+ return getDuplicateSheetName(sheetName, names);
55140
55222
  }
55141
55223
  deleteSheet(sheet) {
55142
55224
  const name = sheet.name;
@@ -57962,8 +58044,8 @@ class SpreadingRelation {
57962
58044
  const EMPTY_ARRAY = [];
57963
58045
 
57964
58046
  const MAX_ITERATION = 30;
57965
- const ERROR_CYCLE_CELL = createEvaluatedCell(new CircularDependencyError());
57966
- const EMPTY_CELL = createEvaluatedCell({ value: null });
58047
+ const ERROR_CYCLE_CELL = Object.freeze(createEvaluatedCell(new CircularDependencyError()));
58048
+ const EMPTY_CELL = Object.freeze(createEvaluatedCell({ value: null }));
57967
58049
  class Evaluator {
57968
58050
  context;
57969
58051
  getters;
@@ -73794,6 +73876,6 @@ exports.tokenColors = tokenColors;
73794
73876
  exports.tokenize = tokenize;
73795
73877
 
73796
73878
 
73797
- __info__.version = "18.0.26";
73798
- __info__.date = "2025-05-02T12:30:31.966Z";
73799
- __info__.hash = "5bdf504";
73879
+ __info__.version = "18.0.27";
73880
+ __info__.date = "2025-05-12T05:25:47.149Z";
73881
+ __info__.hash = "9b36340";
@@ -2059,6 +2059,7 @@ interface DeleteSheetCommand extends SheetDependentCommand {
2059
2059
  interface DuplicateSheetCommand extends SheetDependentCommand {
2060
2060
  type: "DUPLICATE_SHEET";
2061
2061
  sheetIdTo: UID;
2062
+ sheetNameTo: string;
2062
2063
  }
2063
2064
  interface MoveSheetCommand extends SheetDependentCommand {
2064
2065
  type: "MOVE_SHEET";
@@ -4314,7 +4315,7 @@ interface SheetState {
4314
4315
  readonly cellPosition: Record<UID, CellPosition | undefined>;
4315
4316
  }
4316
4317
  declare class SheetPlugin extends CorePlugin<SheetState> implements SheetState {
4317
- static getters: readonly ["getSheetName", "tryGetSheetName", "getSheet", "tryGetSheet", "getSheetIdByName", "getSheetIds", "getVisibleSheetIds", "isSheetVisible", "doesHeaderExist", "doesHeadersExist", "getCell", "getCellPosition", "getColsZone", "getRowCells", "getRowsZone", "getNumberCols", "getNumberRows", "getNumberHeaders", "getGridLinesVisibility", "getNextSheetName", "getSheetSize", "getSheetZone", "getPaneDivisions", "checkZonesExistInSheet", "getCommandZones", "getUnboundedZone", "checkElementsIncludeAllNonFrozenHeaders"];
4318
+ static getters: readonly ["getSheetName", "tryGetSheetName", "getSheet", "tryGetSheet", "getSheetIdByName", "getSheetIds", "getVisibleSheetIds", "isSheetVisible", "doesHeaderExist", "doesHeadersExist", "getCell", "getCellPosition", "getColsZone", "getRowCells", "getRowsZone", "getNumberCols", "getNumberRows", "getNumberHeaders", "getGridLinesVisibility", "getNextSheetName", "getSheetSize", "getSheetZone", "getPaneDivisions", "checkZonesExistInSheet", "getCommandZones", "getUnboundedZone", "checkElementsIncludeAllNonFrozenHeaders", "getDuplicateSheetName"];
4318
4319
  readonly sheetIdsMapName: Record<string, UID | undefined>;
4319
4320
  readonly orderedSheetIds: UID[];
4320
4321
  readonly sheets: Record<UID, Sheet | undefined>;
@@ -4391,7 +4392,7 @@ declare class SheetPlugin extends CorePlugin<SheetState> implements SheetState {
4391
4392
  private hideSheet;
4392
4393
  private showSheet;
4393
4394
  private duplicateSheet;
4394
- private getDuplicateSheetName;
4395
+ getDuplicateSheetName(sheetName: string): string;
4395
4396
  private deleteSheet;
4396
4397
  /**
4397
4398
  * Delete column. This requires a lot of handling:
@@ -8167,6 +8168,7 @@ declare class Composer extends Component<CellComposerProps, SpreadsheetChildEnv>
8167
8168
  onContextMenu(ev: MouseEvent): void;
8168
8169
  closeAssistant(): void;
8169
8170
  openAssistant(): void;
8171
+ onWheel(event: WheelEvent): void;
8170
8172
  private processContent;
8171
8173
  /**
8172
8174
  * Get the HTML content corresponding to the current composer token, divided by lines.