@odoo/o-spreadsheet 17.4.1 → 17.4.3

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.4.1
6
- * @date 2024-07-18T14:25:54.421Z
7
- * @hash fd7deaa
5
+ * @version 17.4.3
6
+ * @date 2024-08-02T08:23:56.573Z
7
+ * @hash 40ecd1e
8
8
  */
9
9
 
10
10
  'use strict';
@@ -2767,13 +2767,16 @@ const wildcardToRegExp = memoize(function wildcardToRegExp(operand) {
2767
2767
  }
2768
2768
  return new RegExp("^" + exp + "$", "i");
2769
2769
  });
2770
- function evaluatePredicate(value = "", criterion) {
2770
+ function evaluatePredicate(value = "", criterion, locale) {
2771
2771
  const { operator, operand } = criterion;
2772
2772
  if (operand === undefined || value === null || operand === null) {
2773
2773
  return false;
2774
2774
  }
2775
2775
  if (typeof operand === "number" && operator === "=") {
2776
- return value.toString() === operand.toString();
2776
+ if (typeof value === "string" && (isNumber(value, locale) || isDateTime(value, locale))) {
2777
+ return toNumber(value, locale) === operand;
2778
+ }
2779
+ return value === operand;
2777
2780
  }
2778
2781
  if (operator === "<>" || operator === "=") {
2779
2782
  let result;
@@ -2855,7 +2858,7 @@ function visitMatchingRanges(args, cb, locale, isQuery = false) {
2855
2858
  for (let k = 0; k < countArg - 1; k += 2) {
2856
2859
  const criteriaValue = toMatrix(args[k])[i][j].value;
2857
2860
  const criterion = predicates[k / 2];
2858
- validatedPredicates = evaluatePredicate(criteriaValue ?? undefined, criterion);
2861
+ validatedPredicates = evaluatePredicate(criteriaValue ?? undefined, criterion, locale);
2859
2862
  if (!validatedPredicates) {
2860
2863
  break;
2861
2864
  }
@@ -6546,6 +6549,9 @@ function toNormalizedPivotValue(dimension, groupValue) {
6546
6549
  const groupValueString = typeof groupValue === "boolean"
6547
6550
  ? toString(groupValue).toLocaleLowerCase()
6548
6551
  : toString(groupValue);
6552
+ if (groupValueString === "null") {
6553
+ return null;
6554
+ }
6549
6555
  if (!pivotNormalizationValueRegistry.contains(dimension.type)) {
6550
6556
  throw new EvaluationError(_t("Field %(field)s is not supported because of its type (%(type)s)", {
6551
6557
  field: dimension.displayName,
@@ -6566,6 +6572,9 @@ function normalizeDateTime(value, granularity) {
6566
6572
  return pivotTimeAdapter(granularity).normalizeFunctionValue(value);
6567
6573
  }
6568
6574
  function toFunctionPivotValue(value, dimension) {
6575
+ if (value === null) {
6576
+ return `"null"`;
6577
+ }
6569
6578
  if (!pivotToFunctionValueRegistry.contains(dimension.type)) {
6570
6579
  return `"${value}"`;
6571
6580
  }
@@ -20781,6 +20790,78 @@ function isCtrlKey(ev) {
20781
20790
  return isMacOS() ? ev.metaKey : ev.ctrlKey;
20782
20791
  }
20783
20792
 
20793
+ /**
20794
+ * Return the o-spreadsheet element position relative
20795
+ * to the browser viewport.
20796
+ */
20797
+ function useSpreadsheetRect() {
20798
+ const position = owl.useState({ x: 0, y: 0, width: 0, height: 0 });
20799
+ let spreadsheetElement = null;
20800
+ function updatePosition() {
20801
+ if (!spreadsheetElement) {
20802
+ spreadsheetElement = document.querySelector(".o-spreadsheet");
20803
+ }
20804
+ if (spreadsheetElement) {
20805
+ const { top, left, width, height } = spreadsheetElement.getBoundingClientRect();
20806
+ position.x = left;
20807
+ position.y = top;
20808
+ position.width = width;
20809
+ position.height = height;
20810
+ }
20811
+ }
20812
+ owl.onMounted(updatePosition);
20813
+ owl.onPatched(updatePosition);
20814
+ return position;
20815
+ }
20816
+ /**
20817
+ * Return the component (or ref's component) BoundingRect, relative
20818
+ * to the upper left corner of the screen (<body> element).
20819
+ *
20820
+ * Note: when used with a <Portal/> component, it will
20821
+ * return the portal position, not the teleported position.
20822
+ */
20823
+ function useAbsoluteBoundingRect(ref) {
20824
+ const rect = owl.useState({ x: 0, y: 0, width: 0, height: 0 });
20825
+ function updateElRect() {
20826
+ const el = ref.el;
20827
+ if (el === null) {
20828
+ return;
20829
+ }
20830
+ const { top, left, width, height } = el.getBoundingClientRect();
20831
+ rect.x = left;
20832
+ rect.y = top;
20833
+ rect.width = width;
20834
+ rect.height = height;
20835
+ }
20836
+ owl.onMounted(updateElRect);
20837
+ owl.onPatched(updateElRect);
20838
+ return rect;
20839
+ }
20840
+ /**
20841
+ * Get the rectangle inside which a popover should stay when being displayed.
20842
+ * It's the value defined in `env.getPopoverContainerRect`, or the Rect of the "o-spreadsheet"
20843
+ * element by default.
20844
+ *
20845
+ * Coordinates are expressed expressed as absolute DOM position.
20846
+ */
20847
+ function usePopoverContainer() {
20848
+ const container = owl.useState({ x: 0, y: 0, width: 0, height: 0 });
20849
+ const component = owl.useComponent();
20850
+ const spreadsheetRect = useSpreadsheetRect();
20851
+ function updateRect() {
20852
+ const env = component.env;
20853
+ const newRect = "getPopoverContainerRect" in env ? env.getPopoverContainerRect() : spreadsheetRect;
20854
+ container.x = newRect.x;
20855
+ container.y = newRect.y;
20856
+ container.width = newRect.width;
20857
+ container.height = newRect.height;
20858
+ }
20859
+ updateRect();
20860
+ owl.onMounted(updateRect);
20861
+ owl.onPatched(updateRect);
20862
+ return container;
20863
+ }
20864
+
20784
20865
  const arrowMap = {
20785
20866
  ArrowDown: "down",
20786
20867
  ArrowLeft: "left",
@@ -21370,7 +21451,9 @@ class Composer extends owl.Component {
21370
21451
  argToFocus: 0,
21371
21452
  });
21372
21453
  compositionActive = false;
21454
+ spreadsheetRect = useSpreadsheetRect();
21373
21455
  get assistantStyle() {
21456
+ const composerRect = this.composerRef.el.getBoundingClientRect();
21374
21457
  const assistantStyle = {};
21375
21458
  assistantStyle["min-width"] = `${this.props.rect?.width || ASSISTANT_WIDTH}px`;
21376
21459
  const proposals = this.autoCompleteState.provider?.proposals;
@@ -21397,6 +21480,9 @@ class Composer extends owl.Component {
21397
21480
  }
21398
21481
  else if (this.props.delimitation) {
21399
21482
  assistantStyle["max-height"] = `${this.props.delimitation.height}px`;
21483
+ if (composerRect.left + ASSISTANT_WIDTH > this.spreadsheetRect.width) {
21484
+ assistantStyle.right = `0px`;
21485
+ }
21400
21486
  }
21401
21487
  return cssPropertiesToCss(assistantStyle);
21402
21488
  }
@@ -26239,78 +26325,6 @@ function zoneToRect(zone) {
26239
26325
  };
26240
26326
  }
26241
26327
 
26242
- /**
26243
- * Return the o-spreadsheet element position relative
26244
- * to the browser viewport.
26245
- */
26246
- function useSpreadsheetRect() {
26247
- const position = owl.useState({ x: 0, y: 0, width: 0, height: 0 });
26248
- let spreadsheetElement = null;
26249
- function updatePosition() {
26250
- if (!spreadsheetElement) {
26251
- spreadsheetElement = document.querySelector(".o-spreadsheet");
26252
- }
26253
- if (spreadsheetElement) {
26254
- const { top, left, width, height } = spreadsheetElement.getBoundingClientRect();
26255
- position.x = left;
26256
- position.y = top;
26257
- position.width = width;
26258
- position.height = height;
26259
- }
26260
- }
26261
- owl.onMounted(updatePosition);
26262
- owl.onPatched(updatePosition);
26263
- return position;
26264
- }
26265
- /**
26266
- * Return the component (or ref's component) BoundingRect, relative
26267
- * to the upper left corner of the screen (<body> element).
26268
- *
26269
- * Note: when used with a <Portal/> component, it will
26270
- * return the portal position, not the teleported position.
26271
- */
26272
- function useAbsoluteBoundingRect(ref) {
26273
- const rect = owl.useState({ x: 0, y: 0, width: 0, height: 0 });
26274
- function updateElRect() {
26275
- const el = ref.el;
26276
- if (el === null) {
26277
- return;
26278
- }
26279
- const { top, left, width, height } = el.getBoundingClientRect();
26280
- rect.x = left;
26281
- rect.y = top;
26282
- rect.width = width;
26283
- rect.height = height;
26284
- }
26285
- owl.onMounted(updateElRect);
26286
- owl.onPatched(updateElRect);
26287
- return rect;
26288
- }
26289
- /**
26290
- * Get the rectangle inside which a popover should stay when being displayed.
26291
- * It's the value defined in `env.getPopoverContainerRect`, or the Rect of the "o-spreadsheet"
26292
- * element by default.
26293
- *
26294
- * Coordinates are expressed expressed as absolute DOM position.
26295
- */
26296
- function usePopoverContainer() {
26297
- const container = owl.useState({ x: 0, y: 0, width: 0, height: 0 });
26298
- const component = owl.useComponent();
26299
- const spreadsheetRect = useSpreadsheetRect();
26300
- function updateRect() {
26301
- const env = component.env;
26302
- const newRect = "getPopoverContainerRect" in env ? env.getPopoverContainerRect() : spreadsheetRect;
26303
- container.x = newRect.x;
26304
- container.y = newRect.y;
26305
- container.width = newRect.width;
26306
- container.height = newRect.height;
26307
- }
26308
- updateRect();
26309
- owl.onMounted(updateRect);
26310
- owl.onPatched(updateRect);
26311
- return container;
26312
- }
26313
-
26314
26328
  css /* scss */ `
26315
26329
  .o-popover {
26316
26330
  position: absolute;
@@ -35809,6 +35823,14 @@ css /* scss */ `
35809
35823
  .pivot-dim-operator-label {
35810
35824
  min-width: 120px;
35811
35825
  }
35826
+
35827
+ &.pivot-dimension-invalid {
35828
+ background-color: #ffdddd;
35829
+ border-color: red !important;
35830
+ select {
35831
+ background-color: #ffdddd;
35832
+ }
35833
+ }
35812
35834
  }
35813
35835
  `;
35814
35836
  class PivotDimension extends owl.Component {
@@ -35871,6 +35893,7 @@ class PivotLayoutConfigurator extends owl.Component {
35871
35893
  "__rows_title__",
35872
35894
  ...rows.map((row) => row.nameWithGranularity),
35873
35895
  ];
35896
+ const allDimensions = columns.concat(rows);
35874
35897
  const offset = 1; // column title
35875
35898
  const draggableItems = draggableIds.map((id, index) => ({
35876
35899
  id,
@@ -35893,8 +35916,12 @@ class PivotLayoutConfigurator extends owl.Component {
35893
35916
  const columns = draggedItems.slice(0, draggedItems.indexOf("__rows_title__"));
35894
35917
  const rows = draggedItems.slice(draggedItems.indexOf("__rows_title__") + 1);
35895
35918
  this.props.onDimensionsUpdated({
35896
- columns: columns.map(parseDimension),
35897
- rows: rows.map(parseDimension),
35919
+ columns: columns
35920
+ .map((nameWithGranularity) => allDimensions.find((dimension) => dimension.nameWithGranularity === nameWithGranularity))
35921
+ .filter(isDefined),
35922
+ rows: rows
35923
+ .map((nameWithGranularity) => allDimensions.find((dimension) => dimension.nameWithGranularity === nameWithGranularity))
35924
+ .filter(isDefined),
35898
35925
  });
35899
35926
  },
35900
35927
  });
@@ -40207,10 +40234,13 @@ function useCellHovered(env, gridRef, callback) {
40207
40234
  row: undefined,
40208
40235
  };
40209
40236
  const { Date } = window;
40210
- let x = 0;
40211
- let y = 0;
40237
+ let x = undefined;
40238
+ let y = undefined;
40212
40239
  let lastMoved = 0;
40213
40240
  function getPosition() {
40241
+ if (x === undefined || y === undefined) {
40242
+ return { col: -1, row: -1 };
40243
+ }
40214
40244
  const col = env.model.getters.getColIndex(x);
40215
40245
  const row = env.model.getters.getRowIndex(y);
40216
40246
  return { col, row };
@@ -47208,12 +47238,13 @@ class BordersPlugin extends CorePlugin {
47208
47238
  this.clearBorders(cmd.sheetId, cmd.target);
47209
47239
  break;
47210
47240
  case "REMOVE_COLUMNS_ROWS":
47211
- for (let el of [...cmd.elements].sort((a, b) => b - a)) {
47241
+ const elements = [...cmd.elements].sort((a, b) => b - a);
47242
+ for (const group of groupConsecutive(elements)) {
47212
47243
  if (cmd.dimension === "COL") {
47213
- this.shiftBordersHorizontally(cmd.sheetId, el + 1, -1);
47244
+ this.shiftBordersHorizontally(cmd.sheetId, group[group.length - 1] + 1, -group.length);
47214
47245
  }
47215
47246
  else {
47216
- this.shiftBordersVertically(cmd.sheetId, el + 1, -1);
47247
+ this.shiftBordersVertically(cmd.sheetId, group[group.length - 1] + 1, -group.length);
47217
47248
  }
47218
47249
  }
47219
47250
  break;
@@ -51274,12 +51305,7 @@ class SheetPlugin extends CorePlugin {
51274
51305
  });
51275
51306
  }
51276
51307
  if (colIndex > deletedColumn) {
51277
- this.dispatch("UPDATE_CELL_POSITION", {
51278
- sheetId: sheet.id,
51279
- cellId: cellId,
51280
- col: colIndex - 1,
51281
- row: rowIndex,
51282
- });
51308
+ this.setNewPosition(cellId, sheet.id, colIndex - 1, rowIndex);
51283
51309
  }
51284
51310
  }
51285
51311
  }
@@ -51289,7 +51315,7 @@ class SheetPlugin extends CorePlugin {
51289
51315
  * Move the cells after a column or rows insertion
51290
51316
  */
51291
51317
  moveCellsOnAddition(sheet, addedElement, quantity, dimension) {
51292
- const commands = [];
51318
+ const updates = [];
51293
51319
  for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
51294
51320
  const row = sheet.rows[rowIndex];
51295
51321
  if (dimension !== "rows" || rowIndex >= addedElement) {
@@ -51298,20 +51324,20 @@ class SheetPlugin extends CorePlugin {
51298
51324
  const cellId = row.cells[i];
51299
51325
  if (cellId) {
51300
51326
  if (dimension === "rows" || colIndex >= addedElement) {
51301
- commands.push({
51302
- type: "UPDATE_CELL_POSITION",
51327
+ updates.push({
51303
51328
  sheetId: sheet.id,
51304
51329
  cellId: cellId,
51305
51330
  col: colIndex + (dimension === "columns" ? quantity : 0),
51306
51331
  row: rowIndex + (dimension === "rows" ? quantity : 0),
51332
+ type: "UPDATE_CELL_POSITION",
51307
51333
  });
51308
51334
  }
51309
51335
  }
51310
51336
  }
51311
51337
  }
51312
51338
  }
51313
- for (let cmd of commands.reverse()) {
51314
- this.dispatch(cmd.type, cmd);
51339
+ for (let update of updates.reverse()) {
51340
+ this.updateCellPosition(update);
51315
51341
  }
51316
51342
  }
51317
51343
  /**
@@ -51344,12 +51370,7 @@ class SheetPlugin extends CorePlugin {
51344
51370
  const colIndex = Number(i);
51345
51371
  const cellId = row.cells[i];
51346
51372
  if (cellId) {
51347
- this.dispatch("UPDATE_CELL_POSITION", {
51348
- sheetId: sheet.id,
51349
- cellId: cellId,
51350
- col: colIndex,
51351
- row: rowIndex - numberRows,
51352
- });
51373
+ this.setNewPosition(cellId, sheet.id, colIndex, rowIndex - numberRows);
51353
51374
  }
51354
51375
  }
51355
51376
  }
@@ -54115,6 +54136,9 @@ class Evaluator {
54115
54136
  if (!this.blockedArrayFormulas.has(position)) {
54116
54137
  this.invalidateSpreading(position);
54117
54138
  }
54139
+ if (this.spreadingRelations.isArrayFormula(position)) {
54140
+ this.spreadingRelations.removeNode(position);
54141
+ }
54118
54142
  const cell = this.getters.getCell(position);
54119
54143
  if (cell === undefined) {
54120
54144
  return EMPTY_CELL;
@@ -54157,7 +54181,6 @@ class Evaluator {
54157
54181
  this.assertSheetHasEnoughSpaceToSpreadFormulaResult(formulaPosition, formulaReturn);
54158
54182
  const nbColumns = formulaReturn.length;
54159
54183
  const nbRows = formulaReturn[0].length;
54160
- this.spreadingRelations.removeNode(formulaPosition);
54161
54184
  forEachSpreadPositionInMatrix(nbColumns, nbRows, this.updateSpreadRelation(formulaPosition));
54162
54185
  this.assertNoMergedCellsInSpreadZone(formulaPosition, formulaReturn);
54163
54186
  forEachSpreadPositionInMatrix(nbColumns, nbRows, this.checkCollision(formulaPosition));
@@ -63082,6 +63105,8 @@ css /* scss */ `
63082
63105
 
63083
63106
  .o-sidePanel-handle-container {
63084
63107
  width: 8px;
63108
+ position: fixed;
63109
+ top: 50%;
63085
63110
  }
63086
63111
  .o-sidePanel-handle {
63087
63112
  cursor: col-resize;
@@ -65701,7 +65726,7 @@ function createEmptyStructure(node) {
65701
65726
  }
65702
65727
 
65703
65728
  class StateObserver {
65704
- changes = [];
65729
+ changes;
65705
65730
  commands = [];
65706
65731
  /**
65707
65732
  * Record the changes which could happen in the given callback, save them in a
@@ -65733,7 +65758,7 @@ class StateObserver {
65733
65758
  if (value[key] === val) {
65734
65759
  return;
65735
65760
  }
65736
- this.changes.push({
65761
+ this.changes?.push({
65737
65762
  key,
65738
65763
  target: value,
65739
65764
  before: value[key],
@@ -68399,6 +68424,6 @@ exports.tokenColors = tokenColors;
68399
68424
  exports.tokenize = tokenize;
68400
68425
 
68401
68426
 
68402
- __info__.version = "17.4.1";
68403
- __info__.date = "2024-07-18T14:25:54.421Z";
68404
- __info__.hash = "fd7deaa";
68427
+ __info__.version = "17.4.3";
68428
+ __info__.date = "2024-08-02T08:23:56.573Z";
68429
+ __info__.hash = "40ecd1e";
@@ -7790,6 +7790,7 @@ declare class Composer extends Component<ComposerProps, SpreadsheetChildEnv> {
7790
7790
  autoCompleteState: Store<AutoCompleteStore>;
7791
7791
  functionDescriptionState: FunctionDescriptionState;
7792
7792
  private compositionActive;
7793
+ private spreadsheetRect;
7793
7794
  get assistantStyle(): string;
7794
7795
  shouldProcessInputEvents: boolean;
7795
7796
  tokens: EnrichedToken[];