@odoo/o-spreadsheet 16.3.0-alpha.8 → 16.3.1

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.
@@ -4396,6 +4396,7 @@ var CommandResult;
4396
4396
  CommandResult[CommandResult["EmptySplitSeparator"] = 89] = "EmptySplitSeparator";
4397
4397
  CommandResult[CommandResult["SplitWillOverwriteContent"] = 90] = "SplitWillOverwriteContent";
4398
4398
  CommandResult[CommandResult["NoSplitSeparatorInSelection"] = 91] = "NoSplitSeparatorInSelection";
4399
+ CommandResult[CommandResult["NoActiveSheet"] = 92] = "NoActiveSheet";
4399
4400
  })(CommandResult || (CommandResult = {}));
4400
4401
 
4401
4402
  const borderStyles = ["thin", "medium", "thick", "dashed", "dotted"];
@@ -16868,6 +16869,7 @@ const unFreezePane = {
16868
16869
  execute: (env) => env.model.dispatch("UNFREEZE_COLUMNS_ROWS", {
16869
16870
  sheetId: env.model.getters.getActiveSheetId(),
16870
16871
  }),
16872
+ icon: "o-spreadsheet-Icon.UNFREEZE",
16871
16873
  };
16872
16874
  const freezePane = {
16873
16875
  name: _lt("Freeze"),
@@ -17545,7 +17547,7 @@ topbarMenuRegistry
17545
17547
  })
17546
17548
  .addChild("sort_range", ["data"], {
17547
17549
  ...sortRange,
17548
- sequence: 20,
17550
+ sequence: 10,
17549
17551
  separator: true,
17550
17552
  })
17551
17553
  .addChild("sort_ascending", ["data", "sort_range"], {
@@ -17558,16 +17560,16 @@ topbarMenuRegistry
17558
17560
  })
17559
17561
  .addChild("split_to_columns", ["data"], {
17560
17562
  ...splitToColumns,
17561
- sequence: 10,
17563
+ sequence: 20,
17562
17564
  separator: true,
17563
17565
  })
17564
17566
  .addChild("add_data_filter", ["data"], {
17565
17567
  ...addDataFilter,
17566
- sequence: 10,
17568
+ sequence: 30,
17567
17569
  })
17568
17570
  .addChild("remove_data_filter", ["data"], {
17569
17571
  ...removeDataFilter,
17570
- sequence: 10,
17572
+ sequence: 30,
17571
17573
  });
17572
17574
 
17573
17575
  class OTRegistry extends Registry {
@@ -17939,6 +17941,18 @@ css /* scss */ `
17939
17941
  grid-template-columns: repeat(${ITEMS_PER_LINE}, 1fr);
17940
17942
  grid-gap: ${ITEM_HORIZONTAL_MARGIN * 2}px;
17941
17943
  }
17944
+ .o-color-picker-toggler-button {
17945
+ display: flex;
17946
+ .o-color-picker-toggler-sign {
17947
+ margin: auto auto;
17948
+ width: 55%;
17949
+ height: 55%;
17950
+ .o-icon {
17951
+ width: 100%;
17952
+ height: 100%;
17953
+ }
17954
+ }
17955
+ }
17942
17956
  .o-color-picker-line-item {
17943
17957
  width: ${ITEM_EDGE_LENGTH}px;
17944
17958
  height: ${ITEM_EDGE_LENGTH}px;
@@ -18674,6 +18688,18 @@ ChartPanel.props = {
18674
18688
  onCloseSidePanel: Function,
18675
18689
  };
18676
18690
 
18691
+ css /* scss */ `
18692
+ .o-spreadsheet {
18693
+ .o-icon {
18694
+ .small-text {
18695
+ font: bold 9px sans-serif;
18696
+ }
18697
+ .heavy-text {
18698
+ font: bold 16px sans-serif;
18699
+ }
18700
+ }
18701
+ }
18702
+ `;
18677
18703
  // -----------------------------------------------------------------------------
18678
18704
  // We need here the svg of the icons that we need to convert to images for the renderer
18679
18705
  // -----------------------------------------------------------------------------
@@ -20599,7 +20625,14 @@ class ContentEditableHelper {
20599
20625
  current = it.next();
20600
20626
  }
20601
20627
  if (current.value !== nodeToFind) {
20602
- throw new Error("Cannot find the node in the children of the element");
20628
+ /** This situation can happen if the code is called while the selection is not currently on the ContentEditableHelper.
20629
+ * In this case, we return 0 because we don't know the size of the text before the selection.
20630
+ *
20631
+ * A known occurence is triggered since the introduction of commit d4663158 (PR #2038).
20632
+ *
20633
+ * FIXME: find a way to test eventhough the selection API is not available in jsDOM.
20634
+ */
20635
+ return 0;
20603
20636
  }
20604
20637
  else {
20605
20638
  if (!current.value.hasChildNodes()) {
@@ -32190,6 +32223,8 @@ class SheetPlugin extends CorePlugin {
32190
32223
  "getSheetSize",
32191
32224
  "getSheetZone",
32192
32225
  "getPaneDivisions",
32226
+ "checkZonesExistInSheet",
32227
+ "getCommandZones",
32193
32228
  ];
32194
32229
  sheetIdsMapName = {};
32195
32230
  orderedSheetIds = [];
@@ -32199,7 +32234,7 @@ class SheetPlugin extends CorePlugin {
32199
32234
  // Command Handling
32200
32235
  // ---------------------------------------------------------------------------
32201
32236
  allowDispatch(cmd) {
32202
- const genericChecks = this.chainValidations(this.checkSheetExists, this.checkZones)(cmd);
32237
+ const genericChecks = this.chainValidations(this.checkSheetExists, this.checkZonesAreInSheet)(cmd);
32203
32238
  if (genericChecks !== 0 /* CommandResult.Success */) {
32204
32239
  return genericChecks;
32205
32240
  }
@@ -32539,6 +32574,37 @@ class SheetPlugin extends CorePlugin {
32539
32574
  .map(({ col, row }) => this.getCell({ sheetId, col, row }))
32540
32575
  .every((cell) => !cell || cell.content === "");
32541
32576
  }
32577
+ getCommandZones(cmd) {
32578
+ const zones = [];
32579
+ if ("zone" in cmd) {
32580
+ zones.push(cmd.zone);
32581
+ }
32582
+ if ("target" in cmd) {
32583
+ zones.push(...cmd.target);
32584
+ }
32585
+ if ("ranges" in cmd) {
32586
+ zones.push(...cmd.ranges.map((rangeData) => this.getters.getRangeFromRangeData(rangeData).zone));
32587
+ }
32588
+ if ("col" in cmd && "row" in cmd) {
32589
+ zones.push({ top: cmd.row, left: cmd.col, bottom: cmd.row, right: cmd.col });
32590
+ }
32591
+ return zones;
32592
+ }
32593
+ /**
32594
+ * Check if zones in the command are well formed and
32595
+ * not outside the sheet.
32596
+ */
32597
+ checkZonesExistInSheet(sheetId, zones) {
32598
+ if (!zones.every(isZoneValid))
32599
+ return 25 /* CommandResult.InvalidRange */;
32600
+ if (zones.length) {
32601
+ const sheetZone = this.getSheetZone(sheetId);
32602
+ return zones.every((zone) => isZoneInside(zone, sheetZone))
32603
+ ? 0 /* CommandResult.Success */
32604
+ : 18 /* CommandResult.TargetOutOfSheet */;
32605
+ }
32606
+ return 0 /* CommandResult.Success */;
32607
+ }
32542
32608
  updateCellPosition(cmd) {
32543
32609
  const { sheetId, cellId, col, row } = cmd;
32544
32610
  if (cellId) {
@@ -32987,9 +33053,6 @@ class SheetPlugin extends CorePlugin {
32987
33053
  }
32988
33054
  return { rowNumber, colNumber };
32989
33055
  }
32990
- // ----------------------------------------------------
32991
- // HIDE / SHOW
32992
- // ----------------------------------------------------
32993
33056
  /**
32994
33057
  * Check that any "sheetId" in the command matches an existing
32995
33058
  * sheet.
@@ -33007,27 +33070,10 @@ class SheetPlugin extends CorePlugin {
33007
33070
  * Check if zones in the command are well formed and
33008
33071
  * not outside the sheet.
33009
33072
  */
33010
- checkZones(cmd) {
33011
- const zones = [];
33012
- if ("zone" in cmd) {
33013
- zones.push(cmd.zone);
33014
- }
33015
- if ("target" in cmd && Array.isArray(cmd.target)) {
33016
- zones.push(...cmd.target);
33017
- }
33018
- if ("ranges" in cmd && Array.isArray(cmd.ranges)) {
33019
- zones.push(...cmd.ranges.map((rangeData) => this.getters.getRangeFromRangeData(rangeData).zone));
33020
- }
33021
- if (!zones.every(isZoneValid)) {
33022
- return 25 /* CommandResult.InvalidRange */;
33023
- }
33024
- else if (zones.length && "sheetId" in cmd) {
33025
- const sheetZone = this.getSheetZone(cmd.sheetId);
33026
- return zones.every((zone) => isZoneInside(zone, sheetZone))
33027
- ? 0 /* CommandResult.Success */
33028
- : 18 /* CommandResult.TargetOutOfSheet */;
33029
- }
33030
- return 0 /* CommandResult.Success */;
33073
+ checkZonesAreInSheet(cmd) {
33074
+ if (!("sheetId" in cmd))
33075
+ return 0 /* CommandResult.Success */;
33076
+ return this.checkZonesExistInSheet(cmd.sheetId, this.getCommandZones(cmd));
33031
33077
  }
33032
33078
  }
33033
33079
 
@@ -33618,7 +33664,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
33618
33664
  }
33619
33665
  break;
33620
33666
  case "PASTE_CONDITIONAL_FORMAT":
33621
- this.pasteCf(cmd.origin, cmd.target, cmd.operation);
33667
+ this.pasteCf(cmd.originPosition, cmd.targetPosition, cmd.operation);
33622
33668
  break;
33623
33669
  }
33624
33670
  }
@@ -38603,18 +38649,7 @@ class SheetUIPlugin extends UIPlugin {
38603
38649
  // Command Handling
38604
38650
  // ---------------------------------------------------------------------------
38605
38651
  allowDispatch(cmd) {
38606
- switch (cmd.type) {
38607
- case "AUTORESIZE_ROWS":
38608
- case "AUTORESIZE_COLUMNS":
38609
- try {
38610
- this.getters.getSheet(cmd.sheetId);
38611
- break;
38612
- }
38613
- catch (error) {
38614
- return 27 /* CommandResult.InvalidSheetId */;
38615
- }
38616
- }
38617
- return 0 /* CommandResult.Success */;
38652
+ return this.chainValidations(this.checkSheetExists, this.checkZonesAreInSheet)(cmd);
38618
38653
  }
38619
38654
  handle(cmd) {
38620
38655
  switch (cmd.type) {
@@ -38649,7 +38684,8 @@ class SheetUIPlugin extends UIPlugin {
38649
38684
  getCellWidth(position) {
38650
38685
  const text = this.getCellText(position);
38651
38686
  const style = this.getters.getCellComputedStyle(position);
38652
- let contentWidth = this.getTextWidth(text, style);
38687
+ const multiLineText = text.split(NEWLINE);
38688
+ let contentWidth = Math.max(...multiLineText.map((line) => this.getTextWidth(line, style)));
38653
38689
  const icon = this.getters.getConditionalIcon(position);
38654
38690
  if (icon) {
38655
38691
  contentWidth += computeIconWidth(this.getters.getCellStyle(position));
@@ -38814,6 +38850,31 @@ class SheetUIPlugin extends UIPlugin {
38814
38850
  splitWord.push(wordPart);
38815
38851
  return splitWord;
38816
38852
  }
38853
+ /**
38854
+ * Check that any "sheetId" in the command matches an existing
38855
+ * sheet.
38856
+ */
38857
+ checkSheetExists(cmd) {
38858
+ if ("sheetId" in cmd && this.getters.tryGetSheet(cmd.sheetId) === undefined) {
38859
+ return 27 /* CommandResult.InvalidSheetId */;
38860
+ }
38861
+ return 0 /* CommandResult.Success */;
38862
+ }
38863
+ /**
38864
+ * Check if zones in the command are well formed and
38865
+ * not outside the sheet.
38866
+ */
38867
+ checkZonesAreInSheet(cmd) {
38868
+ const sheetId = "sheetId" in cmd ? cmd.sheetId : this.getters.tryGetActiveSheetId();
38869
+ const zones = this.getters.getCommandZones(cmd);
38870
+ if (!sheetId && zones.length > 0) {
38871
+ return 92 /* CommandResult.NoActiveSheet */;
38872
+ }
38873
+ if (sheetId && zones.length > 0) {
38874
+ return this.getters.checkZonesExistInSheet(sheetId, zones);
38875
+ }
38876
+ return 0 /* CommandResult.Success */;
38877
+ }
38817
38878
  }
38818
38879
 
38819
38880
  const genericRepeatsTransforms = [
@@ -39638,8 +39699,8 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
39638
39699
  this.pasteCell(origin, position, this.operation, clipboardOptions);
39639
39700
  if (shouldPasteCF) {
39640
39701
  this.dispatch("PASTE_CONDITIONAL_FORMAT", {
39641
- origin: origin.position,
39642
- target: position,
39702
+ originPosition: origin.position,
39703
+ targetPosition: position,
39643
39704
  operation: this.operation,
39644
39705
  });
39645
39706
  }
@@ -40030,7 +40091,7 @@ class ClipboardPlugin extends UIPlugin {
40030
40091
  allowDispatch(cmd) {
40031
40092
  switch (cmd.type) {
40032
40093
  case "CUT":
40033
- const zones = cmd.target || this.getters.getSelectedZones();
40094
+ const zones = cmd.cutTarget || this.getters.getSelectedZones();
40034
40095
  const state = this.getClipboardState(zones, cmd.type);
40035
40096
  return state.isCutAllowed(zones);
40036
40097
  case "PASTE":
@@ -40060,7 +40121,7 @@ class ClipboardPlugin extends UIPlugin {
40060
40121
  switch (cmd.type) {
40061
40122
  case "COPY":
40062
40123
  case "CUT":
40063
- const zones = ("target" in cmd && cmd.target) || this.getters.getSelectedZones();
40124
+ const zones = ("cutTarget" in cmd && cmd.cutTarget) || this.getters.getSelectedZones();
40064
40125
  this.state = this.getClipboardState(zones, cmd.type);
40065
40126
  this.status = "visible";
40066
40127
  break;
@@ -41016,6 +41077,7 @@ class GridSelectionPlugin extends UIPlugin {
41016
41077
  "isSelected",
41017
41078
  "isSingleColSelected",
41018
41079
  "getElementsFromSelection",
41080
+ "tryGetActiveSheetId",
41019
41081
  ];
41020
41082
  gridSelection = {
41021
41083
  anchor: {
@@ -41231,6 +41293,9 @@ class GridSelectionPlugin extends UIPlugin {
41231
41293
  getActiveSheetId() {
41232
41294
  return this.activeSheet.id;
41233
41295
  }
41296
+ tryGetActiveSheetId() {
41297
+ return this.activeSheet?.id;
41298
+ }
41234
41299
  getActiveCell() {
41235
41300
  return this.getters.getEvaluatedCell(this.getActivePosition());
41236
41301
  }
@@ -41477,7 +41542,7 @@ class GridSelectionPlugin extends UIPlugin {
41477
41542
  const deltaCol = isBasedBefore && isCol ? thickness : 0;
41478
41543
  const deltaRow = isBasedBefore && !isCol ? thickness : 0;
41479
41544
  this.dispatch("CUT", {
41480
- target: [
41545
+ cutTarget: [
41481
41546
  {
41482
41547
  left: isCol ? start + deltaCol : 0,
41483
41548
  right: isCol ? end + deltaCol : this.getters.getNumberCols(cmd.sheetId) - 1,
@@ -43749,6 +43814,10 @@ class Spreadsheet extends Component {
43749
43814
  }
43750
43815
  checkViewportSize() {
43751
43816
  const { xRatio, yRatio } = this.env.model.getters.getFrozenSheetViewRatio(this.env.model.getters.getActiveSheetId());
43817
+ if (!isFinite(xRatio) || !isFinite(yRatio)) {
43818
+ // before mounting, the ratios can be NaN or Infinity if the viewport size is 0
43819
+ return;
43820
+ }
43752
43821
  if (yRatio > MAXIMAL_FREEZABLE_RATIO || xRatio > MAXIMAL_FREEZABLE_RATIO) {
43753
43822
  if (this.isViewportTooSmall) {
43754
43823
  return;
@@ -46971,6 +47040,7 @@ class Model extends EventBus {
46971
47040
  coreGetters;
46972
47041
  uuidGenerator;
46973
47042
  handlers = [];
47043
+ uiHandlers = [];
46974
47044
  coreHandlers = [];
46975
47045
  constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = true) {
46976
47046
  super();
@@ -47010,17 +47080,20 @@ class Model extends EventBus {
47010
47080
  const plugin = this.setupUiPlugin(Plugin);
47011
47081
  this.statefulUIPlugins.push(plugin);
47012
47082
  this.handlers.push(plugin);
47083
+ this.uiHandlers.push(plugin);
47013
47084
  }
47014
47085
  for (let Plugin of coreViewsPluginRegistry.getAll()) {
47015
47086
  const plugin = this.setupUiPlugin(Plugin);
47016
47087
  this.coreViewsPlugins.push(plugin);
47017
47088
  this.handlers.push(plugin);
47089
+ this.uiHandlers.push(plugin);
47018
47090
  this.coreHandlers.push(plugin);
47019
47091
  }
47020
47092
  for (let Plugin of featurePluginRegistry.getAll()) {
47021
47093
  const plugin = this.setupUiPlugin(Plugin);
47022
47094
  this.featurePlugins.push(plugin);
47023
47095
  this.handlers.push(plugin);
47096
+ this.uiHandlers.push(plugin);
47024
47097
  }
47025
47098
  this.uuidGenerator.setIsFastStrategy(false);
47026
47099
  // starting plugins
@@ -47189,7 +47262,7 @@ class Model extends EventBus {
47189
47262
  return new DispatchResult(results.flat());
47190
47263
  }
47191
47264
  checkDispatchAllowedLocalCommand(command) {
47192
- const results = this.handlers.map((handler) => handler.allowDispatch(command));
47265
+ const results = this.uiHandlers.map((handler) => handler.allowDispatch(command));
47193
47266
  return new DispatchResult(results.flat());
47194
47267
  }
47195
47268
  finalize() {
@@ -47478,6 +47551,6 @@ function addFunction(functionName, functionDescription) {
47478
47551
  export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, links, load, parse, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
47479
47552
 
47480
47553
 
47481
- __info__.version = '16.3.0-alpha.8';
47482
- __info__.date = '2023-05-12T10:59:42.550Z';
47483
- __info__.hash = 'afee7d5';
47554
+ __info__.version = '16.3.1';
47555
+ __info__.date = '2023-05-25T13:00:27.320Z';
47556
+ __info__.hash = 'b3cfd2c';