@odoo/o-spreadsheet 17.4.2 → 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.2
6
- * @date 2024-07-24T10:26:00.237Z
7
- * @hash f5ede5b
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 {
@@ -47216,12 +47238,13 @@ class BordersPlugin extends CorePlugin {
47216
47238
  this.clearBorders(cmd.sheetId, cmd.target);
47217
47239
  break;
47218
47240
  case "REMOVE_COLUMNS_ROWS":
47219
- 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)) {
47220
47243
  if (cmd.dimension === "COL") {
47221
- this.shiftBordersHorizontally(cmd.sheetId, el + 1, -1);
47244
+ this.shiftBordersHorizontally(cmd.sheetId, group[group.length - 1] + 1, -group.length);
47222
47245
  }
47223
47246
  else {
47224
- this.shiftBordersVertically(cmd.sheetId, el + 1, -1);
47247
+ this.shiftBordersVertically(cmd.sheetId, group[group.length - 1] + 1, -group.length);
47225
47248
  }
47226
47249
  }
47227
47250
  break;
@@ -51282,12 +51305,7 @@ class SheetPlugin extends CorePlugin {
51282
51305
  });
51283
51306
  }
51284
51307
  if (colIndex > deletedColumn) {
51285
- this.dispatch("UPDATE_CELL_POSITION", {
51286
- sheetId: sheet.id,
51287
- cellId: cellId,
51288
- col: colIndex - 1,
51289
- row: rowIndex,
51290
- });
51308
+ this.setNewPosition(cellId, sheet.id, colIndex - 1, rowIndex);
51291
51309
  }
51292
51310
  }
51293
51311
  }
@@ -51297,7 +51315,7 @@ class SheetPlugin extends CorePlugin {
51297
51315
  * Move the cells after a column or rows insertion
51298
51316
  */
51299
51317
  moveCellsOnAddition(sheet, addedElement, quantity, dimension) {
51300
- const commands = [];
51318
+ const updates = [];
51301
51319
  for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
51302
51320
  const row = sheet.rows[rowIndex];
51303
51321
  if (dimension !== "rows" || rowIndex >= addedElement) {
@@ -51306,20 +51324,20 @@ class SheetPlugin extends CorePlugin {
51306
51324
  const cellId = row.cells[i];
51307
51325
  if (cellId) {
51308
51326
  if (dimension === "rows" || colIndex >= addedElement) {
51309
- commands.push({
51310
- type: "UPDATE_CELL_POSITION",
51327
+ updates.push({
51311
51328
  sheetId: sheet.id,
51312
51329
  cellId: cellId,
51313
51330
  col: colIndex + (dimension === "columns" ? quantity : 0),
51314
51331
  row: rowIndex + (dimension === "rows" ? quantity : 0),
51332
+ type: "UPDATE_CELL_POSITION",
51315
51333
  });
51316
51334
  }
51317
51335
  }
51318
51336
  }
51319
51337
  }
51320
51338
  }
51321
- for (let cmd of commands.reverse()) {
51322
- this.dispatch(cmd.type, cmd);
51339
+ for (let update of updates.reverse()) {
51340
+ this.updateCellPosition(update);
51323
51341
  }
51324
51342
  }
51325
51343
  /**
@@ -51352,12 +51370,7 @@ class SheetPlugin extends CorePlugin {
51352
51370
  const colIndex = Number(i);
51353
51371
  const cellId = row.cells[i];
51354
51372
  if (cellId) {
51355
- this.dispatch("UPDATE_CELL_POSITION", {
51356
- sheetId: sheet.id,
51357
- cellId: cellId,
51358
- col: colIndex,
51359
- row: rowIndex - numberRows,
51360
- });
51373
+ this.setNewPosition(cellId, sheet.id, colIndex, rowIndex - numberRows);
51361
51374
  }
51362
51375
  }
51363
51376
  }
@@ -54123,6 +54136,9 @@ class Evaluator {
54123
54136
  if (!this.blockedArrayFormulas.has(position)) {
54124
54137
  this.invalidateSpreading(position);
54125
54138
  }
54139
+ if (this.spreadingRelations.isArrayFormula(position)) {
54140
+ this.spreadingRelations.removeNode(position);
54141
+ }
54126
54142
  const cell = this.getters.getCell(position);
54127
54143
  if (cell === undefined) {
54128
54144
  return EMPTY_CELL;
@@ -54165,7 +54181,6 @@ class Evaluator {
54165
54181
  this.assertSheetHasEnoughSpaceToSpreadFormulaResult(formulaPosition, formulaReturn);
54166
54182
  const nbColumns = formulaReturn.length;
54167
54183
  const nbRows = formulaReturn[0].length;
54168
- this.spreadingRelations.removeNode(formulaPosition);
54169
54184
  forEachSpreadPositionInMatrix(nbColumns, nbRows, this.updateSpreadRelation(formulaPosition));
54170
54185
  this.assertNoMergedCellsInSpreadZone(formulaPosition, formulaReturn);
54171
54186
  forEachSpreadPositionInMatrix(nbColumns, nbRows, this.checkCollision(formulaPosition));
@@ -63090,6 +63105,8 @@ css /* scss */ `
63090
63105
 
63091
63106
  .o-sidePanel-handle-container {
63092
63107
  width: 8px;
63108
+ position: fixed;
63109
+ top: 50%;
63093
63110
  }
63094
63111
  .o-sidePanel-handle {
63095
63112
  cursor: col-resize;
@@ -65709,7 +65726,7 @@ function createEmptyStructure(node) {
65709
65726
  }
65710
65727
 
65711
65728
  class StateObserver {
65712
- changes = [];
65729
+ changes;
65713
65730
  commands = [];
65714
65731
  /**
65715
65732
  * Record the changes which could happen in the given callback, save them in a
@@ -65741,7 +65758,7 @@ class StateObserver {
65741
65758
  if (value[key] === val) {
65742
65759
  return;
65743
65760
  }
65744
- this.changes.push({
65761
+ this.changes?.push({
65745
65762
  key,
65746
65763
  target: value,
65747
65764
  before: value[key],
@@ -68407,6 +68424,6 @@ exports.tokenColors = tokenColors;
68407
68424
  exports.tokenize = tokenize;
68408
68425
 
68409
68426
 
68410
- __info__.version = "17.4.2";
68411
- __info__.date = "2024-07-24T10:26:00.237Z";
68412
- __info__.hash = "f5ede5b";
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[];