@odoo/o-spreadsheet 16.0.17 → 16.0.19

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.
@@ -1006,13 +1006,17 @@ function getAddHeaderStartIndex(position, base) {
1006
1006
  return position === "after" ? base + 1 : base;
1007
1007
  }
1008
1008
  /**
1009
- * Compare two objects.
1009
+ * Compares two objects.
1010
1010
  */
1011
1011
  function deepEquals(o1, o2) {
1012
1012
  if (o1 === o2)
1013
1013
  return true;
1014
1014
  if ((o1 && !o2) || (o2 && !o1))
1015
1015
  return false;
1016
+ if (typeof o1 !== typeof o2)
1017
+ return false;
1018
+ if (typeof o1 !== "object")
1019
+ return o1 === o2;
1016
1020
  // Objects can have different keys if the values are undefined
1017
1021
  const keys = new Set();
1018
1022
  Object.keys(o1).forEach((key) => keys.add(key));
@@ -3515,6 +3519,7 @@ css /* scss */ `
3515
3519
  background-color: white;
3516
3520
  border-left: 3px solid red;
3517
3521
  padding: 10px;
3522
+ overflow-wrap: break-word;
3518
3523
  }
3519
3524
  `;
3520
3525
  class ErrorToolTip extends Component {
@@ -5031,6 +5036,13 @@ const REMOVE_ROWS_ACTION = (env) => {
5031
5036
  elements: rows,
5032
5037
  });
5033
5038
  };
5039
+ const CAN_REMOVE_COLUMNS_ROWS = (dimension, env) => {
5040
+ const sheetId = env.model.getters.getActiveSheetId();
5041
+ const selectedElements = env.model.getters.getElementsFromSelection(dimension);
5042
+ const includesAllVisibleHeaders = env.model.getters.checkElementsIncludeAllVisibleHeaders(sheetId, dimension, selectedElements);
5043
+ const includesAllNonFrozenHeaders = env.model.getters.checkElementsIncludeAllNonFrozenHeaders(sheetId, dimension, selectedElements);
5044
+ return !includesAllVisibleHeaders && !includesAllNonFrozenHeaders;
5045
+ };
5034
5046
  const REMOVE_COLUMNS_NAME = (env) => {
5035
5047
  if (env.model.getters.getSelectedZones().length > 1) {
5036
5048
  return _lt("Delete columns");
@@ -5635,11 +5647,7 @@ colMenuRegistry
5635
5647
  name: REMOVE_COLUMNS_NAME,
5636
5648
  sequence: 90,
5637
5649
  action: REMOVE_COLUMNS_ACTION,
5638
- isVisible: (env) => {
5639
- const sheetId = env.model.getters.getActiveSheetId();
5640
- const selectedCols = env.model.getters.getElementsFromSelection("COL");
5641
- return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
5642
- },
5650
+ isVisible: (env) => CAN_REMOVE_COLUMNS_ROWS("COL", env),
5643
5651
  })
5644
5652
  .add("clear_column", {
5645
5653
  name: DELETE_CONTENT_COLUMNS_NAME,
@@ -5653,7 +5661,7 @@ colMenuRegistry
5653
5661
  isVisible: (env) => {
5654
5662
  const sheetId = env.model.getters.getActiveSheetId();
5655
5663
  const selectedCols = env.model.getters.getElementsFromSelection("COL");
5656
- return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
5664
+ return !env.model.getters.checkElementsIncludeAllVisibleHeaders(sheetId, "COL", selectedCols);
5657
5665
  },
5658
5666
  separator: true,
5659
5667
  })
@@ -5727,11 +5735,7 @@ rowMenuRegistry
5727
5735
  name: REMOVE_ROWS_NAME,
5728
5736
  sequence: 70,
5729
5737
  action: REMOVE_ROWS_ACTION,
5730
- isVisible: (env) => {
5731
- const sheetId = env.model.getters.getActiveSheetId();
5732
- const selectedRows = env.model.getters.getElementsFromSelection("ROW");
5733
- return env.model.getters.canRemoveHeaders(sheetId, "ROW", selectedRows);
5734
- },
5738
+ isVisible: (env) => CAN_REMOVE_COLUMNS_ROWS("ROW", env),
5735
5739
  })
5736
5740
  .add("clear_row", {
5737
5741
  name: DELETE_CONTENT_ROWS_NAME,
@@ -5745,7 +5749,7 @@ rowMenuRegistry
5745
5749
  isVisible: (env) => {
5746
5750
  const sheetId = env.model.getters.getActiveSheetId();
5747
5751
  const selectedRows = env.model.getters.getElementsFromSelection("ROW");
5748
- return env.model.getters.canRemoveHeaders(sheetId, "ROW", selectedRows);
5752
+ return !env.model.getters.checkElementsIncludeAllVisibleHeaders(sheetId, "ROW", selectedRows);
5749
5753
  },
5750
5754
  separator: true,
5751
5755
  })
@@ -6039,11 +6043,13 @@ topbarMenuRegistry
6039
6043
  name: REMOVE_ROWS_NAME,
6040
6044
  sequence: 80,
6041
6045
  action: REMOVE_ROWS_ACTION,
6046
+ isVisible: (env) => CAN_REMOVE_COLUMNS_ROWS("ROW", env),
6042
6047
  })
6043
6048
  .addChild("edit_delete_column", ["edit"], {
6044
6049
  name: REMOVE_COLUMNS_NAME,
6045
6050
  sequence: 90,
6046
6051
  action: REMOVE_COLUMNS_ACTION,
6052
+ isVisible: (env) => CAN_REMOVE_COLUMNS_ROWS("COL", env),
6047
6053
  })
6048
6054
  .addChild("edit_delete_cell_shift_up", ["edit"], {
6049
6055
  name: _lt("Delete cell and shift up"),
@@ -7810,6 +7816,7 @@ class LineChart extends AbstractChart {
7810
7816
  this.legendPosition = definition.legendPosition;
7811
7817
  this.labelsAsText = definition.labelsAsText;
7812
7818
  this.stacked = definition.stacked;
7819
+ this.cumulative = definition.cumulative;
7813
7820
  }
7814
7821
  static validateChartDefinition(validator, definition) {
7815
7822
  return validator.checkValidations(definition, checkDataset, checkLabelRange);
@@ -7829,6 +7836,7 @@ class LineChart extends AbstractChart {
7829
7836
  verticalAxisPosition: "left",
7830
7837
  labelRange: context.auxiliaryRange || undefined,
7831
7838
  stacked: false,
7839
+ cumulative: false,
7832
7840
  };
7833
7841
  }
7834
7842
  getDefinition() {
@@ -7848,6 +7856,7 @@ class LineChart extends AbstractChart {
7848
7856
  title: this.title,
7849
7857
  labelsAsText: this.labelsAsText,
7850
7858
  stacked: this.stacked,
7859
+ cumulative: this.cumulative,
7851
7860
  };
7852
7861
  }
7853
7862
  getContextCreation() {
@@ -8032,6 +8041,16 @@ function createLineChartRuntime(chart, getters) {
8032
8041
  if (chart.stacked) {
8033
8042
  backgroundRGBA.a = LINE_FILL_TRANSPARENCY;
8034
8043
  }
8044
+ if (chart.cumulative) {
8045
+ let accumulator = 0;
8046
+ data = data.map((value) => {
8047
+ if (!isNaN(value)) {
8048
+ accumulator += parseFloat(value);
8049
+ return accumulator;
8050
+ }
8051
+ return value;
8052
+ });
8053
+ }
8035
8054
  const backgroundColor = rgbaToHex(backgroundRGBA);
8036
8055
  const dataset = {
8037
8056
  label,
@@ -8817,6 +8836,11 @@ class LineConfigPanel extends LineBarPieConfigPanel {
8817
8836
  stacked: ev.target.checked,
8818
8837
  });
8819
8838
  }
8839
+ onUpdateCumulative(ev) {
8840
+ this.props.updateChart(this.props.figureId, {
8841
+ cumulative: ev.target.checked,
8842
+ });
8843
+ }
8820
8844
  }
8821
8845
  LineConfigPanel.template = "o-spreadsheet-LineConfigPanel";
8822
8846
 
@@ -21276,9 +21300,11 @@ function useCellHovered(env, gridRef, callback) {
21276
21300
  }
21277
21301
  }
21278
21302
  function updateMousePosition(e) {
21279
- x = e.offsetX;
21280
- y = e.offsetY;
21281
- lastMoved = Date.now();
21303
+ if (gridRef.el === e.target) {
21304
+ x = e.offsetX;
21305
+ y = e.offsetY;
21306
+ lastMoved = Date.now();
21307
+ }
21282
21308
  }
21283
21309
  function recompute() {
21284
21310
  const { col, row } = getPosition();
@@ -24646,6 +24672,7 @@ function convertChartData(chartData) {
24646
24672
  verticalAxisPosition: chartData.verticalAxisPosition,
24647
24673
  legendPosition: chartData.legendPosition,
24648
24674
  stacked: chartData.stacked || false,
24675
+ cumulative: chartData.cumulative || false,
24649
24676
  labelsAsText: false,
24650
24677
  };
24651
24678
  }
@@ -28921,7 +28948,11 @@ class HeaderSizePlugin extends CorePlugin {
28921
28948
  let sizes = [...this.sizes[cmd.sheetId][cmd.dimension]];
28922
28949
  const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
28923
28950
  const baseSize = sizes[cmd.base];
28924
- sizes.splice(addIndex, 0, ...Array(cmd.quantity).fill(baseSize));
28951
+ const sizesToInsert = range(0, cmd.quantity).map(() => ({
28952
+ manualSize: baseSize.manualSize,
28953
+ computedSize: lazy(baseSize.computedSize()),
28954
+ }));
28955
+ sizes.splice(addIndex, 0, ...sizesToInsert);
28925
28956
  sizes = sizes.map((size, row) => {
28926
28957
  if (cmd.dimension === "ROW" && row > cmd.base + cmd.quantity) {
28927
28958
  // invalidate sizes
@@ -29138,7 +29169,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
29138
29169
  if (!this.getters.tryGetSheet(cmd.sheetId)) {
29139
29170
  return 27 /* CommandResult.InvalidSheetId */;
29140
29171
  }
29141
- if (!this.canRemoveHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
29172
+ if (this.checkElementsIncludeAllVisibleHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
29142
29173
  return 8 /* CommandResult.NotEnoughElements */;
29143
29174
  }
29144
29175
  return 0 /* CommandResult.Success */;
@@ -29188,9 +29219,9 @@ class HeaderVisibilityPlugin extends CorePlugin {
29188
29219
  }
29189
29220
  return;
29190
29221
  }
29191
- canRemoveHeaders(sheetId, dimension, elements) {
29222
+ checkElementsIncludeAllVisibleHeaders(sheetId, dimension, elements) {
29192
29223
  const visibleHeaders = this.getAllVisibleHeaders(sheetId, dimension);
29193
- return !includesAll(elements, visibleHeaders);
29224
+ return includesAll(elements, visibleHeaders);
29194
29225
  }
29195
29226
  isRowHiddenByUser(sheetId, index) {
29196
29227
  return this.hiddenHeaders[sheetId].ROW[index];
@@ -29286,7 +29317,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
29286
29317
  }
29287
29318
  }
29288
29319
  HeaderVisibilityPlugin.getters = [
29289
- "canRemoveHeaders",
29320
+ "checkElementsIncludeAllVisibleHeaders",
29290
29321
  "getHiddenColsGroups",
29291
29322
  "getHiddenRowsGroups",
29292
29323
  "isRowHiddenByUser",
@@ -29805,6 +29836,9 @@ class SheetPlugin extends CorePlugin {
29805
29836
  if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
29806
29837
  return 85 /* CommandResult.InvalidHeaderIndex */;
29807
29838
  }
29839
+ else if (this.checkElementsIncludeAllNonFrozenHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
29840
+ return 8 /* CommandResult.NotEnoughElements */;
29841
+ }
29808
29842
  else {
29809
29843
  return 0 /* CommandResult.Success */;
29810
29844
  }
@@ -30104,6 +30138,20 @@ class SheetPlugin extends CorePlugin {
30104
30138
  }
30105
30139
  this.history.update("sheets", sheetId, "panes", panes);
30106
30140
  }
30141
+ /**
30142
+ * Checks if all non-frozen header indices are present in the provided elements of selected rows/columns.
30143
+ * This validation ensures that all rows or columns cannot be deleted when frozen panes exist.
30144
+ */
30145
+ checkElementsIncludeAllNonFrozenHeaders(sheetId, dimension, elements) {
30146
+ const paneDivisions = this.getters.getPaneDivisions(sheetId);
30147
+ const startIndex = dimension === "ROW" ? paneDivisions.ySplit : paneDivisions.xSplit;
30148
+ const endIndex = this.getters.getNumberHeaders(sheetId, dimension);
30149
+ if (!startIndex) {
30150
+ return false;
30151
+ }
30152
+ const indicesToCheck = range(startIndex, endIndex);
30153
+ return includesAll(elements, indicesToCheck);
30154
+ }
30107
30155
  // ---------------------------------------------------------------------------
30108
30156
  // Row/Col manipulation
30109
30157
  // ---------------------------------------------------------------------------
@@ -30638,6 +30686,7 @@ SheetPlugin.getters = [
30638
30686
  "getSheetSize",
30639
30687
  "getSheetZone",
30640
30688
  "getPaneDivisions",
30689
+ "checkElementsIncludeAllNonFrozenHeaders",
30641
30690
  ];
30642
30691
 
30643
30692
  /**
@@ -32019,7 +32068,7 @@ class ClipboardPlugin extends UIPlugin {
32019
32068
  allowDispatch(cmd) {
32020
32069
  switch (cmd.type) {
32021
32070
  case "CUT":
32022
- const zones = cmd.target || this.getters.getSelectedZones();
32071
+ const zones = this.getters.getSelectedZones();
32023
32072
  const state = this.getClipboardState(zones, cmd.type);
32024
32073
  return state.isCutAllowed(zones);
32025
32074
  case "PASTE":
@@ -32050,7 +32099,7 @@ class ClipboardPlugin extends UIPlugin {
32050
32099
  switch (cmd.type) {
32051
32100
  case "COPY":
32052
32101
  case "CUT":
32053
- const zones = ("target" in cmd && cmd.target) || this.getters.getSelectedZones();
32102
+ const zones = this.getters.getSelectedZones();
32054
32103
  this.state = this.getClipboardState(zones, cmd.type);
32055
32104
  this.status = "visible";
32056
32105
  break;
@@ -32668,6 +32717,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
32668
32717
  // stores the computed styles in the format of computedStyles.sheetName[col][row] = Style
32669
32718
  this.computedStyles = {};
32670
32719
  this.computedIcons = {};
32720
+ this.uuidGenerator = new UuidGenerator();
32671
32721
  /**
32672
32722
  * Execute the predicate to know if a conditional formatting rule should be applied to a cell
32673
32723
  */
@@ -33019,8 +33069,9 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
33019
33069
  this.adaptRules(origin.sheetId, cf, [xc], toRemoveRange);
33020
33070
  }
33021
33071
  else {
33022
- this.adaptRules(target.sheetId, cf, [xc], []);
33023
33072
  this.adaptRules(origin.sheetId, cf, [], toRemoveRange);
33073
+ const cfToCopyTo = this.getCFToCopyTo(target.sheetId, cf);
33074
+ this.adaptRules(target.sheetId, cfToCopyTo, [xc], []);
33024
33075
  }
33025
33076
  }
33026
33077
  }
@@ -33029,6 +33080,12 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
33029
33080
  isCellValueNumber(value) {
33030
33081
  return typeof value === "number";
33031
33082
  }
33083
+ getCFToCopyTo(targetSheetId, originCF) {
33084
+ const cfInTarget = this.getters
33085
+ .getConditionalFormats(targetSheetId)
33086
+ .find((cf) => cf.stopIfTrue === originCF.stopIfTrue && deepEquals(cf.rule, originCF.rule));
33087
+ return cfInTarget ? cfInTarget : { ...originCF, id: this.uuidGenerator.uuidv4(), ranges: [] };
33088
+ }
33032
33089
  }
33033
33090
  EvaluationConditionalFormatPlugin.getters = ["getConditionalIcon", "getCellComputedStyle"];
33034
33091
 
@@ -34796,26 +34853,24 @@ class GridSelectionPlugin extends UIPlugin {
34796
34853
  const isBasedBefore = cmd.base < start;
34797
34854
  const deltaCol = isBasedBefore && isCol ? thickness : 0;
34798
34855
  const deltaRow = isBasedBefore && !isCol ? thickness : 0;
34799
- this.dispatch("CUT", {
34800
- target: [
34801
- {
34802
- left: isCol ? start + deltaCol : 0,
34803
- right: isCol ? end + deltaCol : this.getters.getNumberCols(cmd.sheetId) - 1,
34804
- top: !isCol ? start + deltaRow : 0,
34805
- bottom: !isCol ? end + deltaRow : this.getters.getNumberRows(cmd.sheetId) - 1,
34806
- },
34807
- ],
34808
- });
34809
- this.dispatch("PASTE", {
34810
- target: [
34811
- {
34812
- left: isCol ? cmd.base : 0,
34813
- right: isCol ? cmd.base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
34814
- top: !isCol ? cmd.base : 0,
34815
- bottom: !isCol ? cmd.base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
34816
- },
34817
- ],
34818
- });
34856
+ const target = [
34857
+ {
34858
+ left: isCol ? start + deltaCol : 0,
34859
+ right: isCol ? end + deltaCol : this.getters.getNumberCols(cmd.sheetId) - 1,
34860
+ top: !isCol ? start + deltaRow : 0,
34861
+ bottom: !isCol ? end + deltaRow : this.getters.getNumberRows(cmd.sheetId) - 1,
34862
+ },
34863
+ ];
34864
+ const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
34865
+ const pasteTarget = [
34866
+ {
34867
+ left: isCol ? cmd.base : 0,
34868
+ right: isCol ? cmd.base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
34869
+ top: !isCol ? cmd.base : 0,
34870
+ bottom: !isCol ? cmd.base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
34871
+ },
34872
+ ];
34873
+ state.paste(pasteTarget, { selectTarget: true });
34819
34874
  const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
34820
34875
  let currentIndex = cmd.base;
34821
34876
  for (const element of toRemove) {
@@ -36431,6 +36486,9 @@ class InternalViewport {
36431
36486
  const sheetId = this.sheetId;
36432
36487
  this.left = this.searchHeaderIndex("COL", this.offsetScrollbarX, this.boundaries.left);
36433
36488
  this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.viewportWidth, this.left));
36489
+ if (this.left === -1) {
36490
+ this.left = this.boundaries.left;
36491
+ }
36434
36492
  if (this.right === -1) {
36435
36493
  this.right = this.getters.getNumberCols(sheetId) - 1;
36436
36494
  }
@@ -36444,6 +36502,9 @@ class InternalViewport {
36444
36502
  const sheetId = this.sheetId;
36445
36503
  this.top = this.searchHeaderIndex("ROW", this.offsetScrollbarY, this.boundaries.top);
36446
36504
  this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.viewportHeight, this.top));
36505
+ if (this.top === -1) {
36506
+ this.top = this.boundaries.top;
36507
+ }
36447
36508
  if (this.bottom === -1) {
36448
36509
  this.bottom = this.getters.getNumberRows(sheetId) - 1;
36449
36510
  }
@@ -42829,6 +42890,6 @@ function addFunction(functionName, functionDescription) {
42829
42890
  export { AbstractChart, CommandResult, CorePlugin, DATETIME_FORMAT, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, cellTypes, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, load, parse, readonlyAllowedCommands, registries, setTranslationMethod, tokenize };
42830
42891
 
42831
42892
 
42832
- __info__.version = '16.0.17';
42833
- __info__.date = '2023-08-17T11:08:00.168Z';
42834
- __info__.hash = '34011c3';
42893
+ __info__.version = '16.0.19';
42894
+ __info__.date = '2023-09-21T15:56:31.776Z';
42895
+ __info__.hash = '229c563';