@odoo/o-spreadsheet 19.3.13 → 19.3.15

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 19.3.13
6
- * @date 2026-07-23T07:41:06.182Z
7
- * @hash 2059bd0
5
+ * @version 19.3.15
6
+ * @date 2026-08-10T12:32:40.247Z
7
+ * @hash 25f760e
8
8
  */
9
9
 
10
10
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
@@ -4259,19 +4259,58 @@ function applyVectorization(formula, args, acceptToVectorize = void 0) {
4259
4259
  }
4260
4260
  }
4261
4261
  if (countVectorizedCol === 1 && countVectorizedRow === 1) return formula(...args);
4262
- const getArgOffset = (i, j) => args.map((arg, index) => {
4263
- switch (vectorArgsType?.[index]) {
4264
- case "matrix": return arg[i][j];
4265
- case "horizontal": return arg[i][0];
4266
- case "vertical": return arg[0][j];
4267
- case void 0: return arg;
4262
+ const argsBuffer = new Array(args.length);
4263
+ const argGetters = [];
4264
+ const vectorizedIndices = [];
4265
+ for (let k = 0; k < args.length; k++) {
4266
+ const arg = args[k];
4267
+ switch (vectorArgsType?.[k]) {
4268
+ case "matrix":
4269
+ argGetters.push((i, j) => arg[i][j]);
4270
+ vectorizedIndices.push(k);
4271
+ break;
4272
+ case "horizontal":
4273
+ argGetters.push((i) => arg[i][0]);
4274
+ vectorizedIndices.push(k);
4275
+ break;
4276
+ case "vertical":
4277
+ argGetters.push((_i, j) => arg[0][j]);
4278
+ vectorizedIndices.push(k);
4279
+ break;
4280
+ case void 0:
4281
+ argsBuffer[k] = arg;
4282
+ break;
4268
4283
  }
4269
- });
4270
- return generateMatrix(countVectorizedCol, countVectorizedRow, (col, row) => {
4271
- if (col > vectorizedColLimit - 1 || row > vectorizedRowLimit - 1) return new NotAvailableError(_t("Array arguments to [[FUNCTION_NAME]] are of different size."));
4272
- const singleCellComputeResult = formula(...getArgOffset(col, row));
4273
- return isMatrix(singleCellComputeResult) ? singleCellComputeResult[0][0] : singleCellComputeResult;
4274
- });
4284
+ }
4285
+ const nbVectorized = vectorizedIndices.length;
4286
+ let callFormula;
4287
+ switch (argsBuffer.length) {
4288
+ case 1:
4289
+ callFormula = () => formula(argsBuffer[0]);
4290
+ break;
4291
+ case 2:
4292
+ callFormula = () => formula(argsBuffer[0], argsBuffer[1]);
4293
+ break;
4294
+ case 3:
4295
+ callFormula = () => formula(argsBuffer[0], argsBuffer[1], argsBuffer[2]);
4296
+ break;
4297
+ default: callFormula = () => formula(...argsBuffer);
4298
+ }
4299
+ const result = new Array(countVectorizedCol);
4300
+ for (let col = 0; col < countVectorizedCol; col++) {
4301
+ const column = new Array(countVectorizedRow);
4302
+ result[col] = column;
4303
+ for (let row = 0; row < countVectorizedRow; row++) {
4304
+ if (col > vectorizedColLimit - 1 || row > vectorizedRowLimit - 1) {
4305
+ column[row] = new NotAvailableError(_t("Array arguments to [[FUNCTION_NAME]] are of different size."));
4306
+ continue;
4307
+ }
4308
+ for (let k = 0; k < nbVectorized; k++) argsBuffer[vectorizedIndices[k]] = argGetters[k](col, row);
4309
+ const singleCellComputeResult = callFormula();
4310
+ column[row] = isMatrix(singleCellComputeResult) ? singleCellComputeResult[0][0] : singleCellComputeResult;
4311
+ }
4312
+ }
4313
+ return result;
4275
4314
  }
4276
4315
  /**
4277
4316
  * This function allows to visit arguments and stop the visit if necessary.
@@ -4618,12 +4657,15 @@ function emptyDataErrorMessage(argName) {
4618
4657
  //#endregion
4619
4658
  //#region src/functions/create_compute_function.ts
4620
4659
  function createComputeFunction(descr) {
4660
+ let currentArgDefinitions = [];
4621
4661
  function vectorizedCompute(...args) {
4622
4662
  const acceptToVectorize = [];
4663
+ currentArgDefinitions = new Array(args.length);
4623
4664
  const argsToFocus = argTargeting(descr, args.length);
4624
4665
  for (let i = 0; i < args.length; i++) {
4625
4666
  const argIndex = argsToFocus[i].index;
4626
4667
  const argDefinition = descr.args[argIndex];
4668
+ currentArgDefinitions[i] = argDefinition;
4627
4669
  const arg = args[i];
4628
4670
  if (!isMatrix(arg) && argDefinition.acceptMatrixOnly) throw new BadExpressionError(_t("Function %s expects the parameter '%s' to be reference to a cell or range.", descr.name, (i + 1).toString()));
4629
4671
  acceptToVectorize.push(!argDefinition.acceptMatrix);
@@ -4636,10 +4678,9 @@ function createComputeFunction(descr) {
4636
4678
  return result;
4637
4679
  }
4638
4680
  function errorHandlingCompute(...args) {
4639
- const argsToFocus = argTargeting(descr, args.length);
4640
4681
  for (let i = 0; i < args.length; i++) {
4641
4682
  const arg = args[i];
4642
- if (!descr.args[argsToFocus[i].index].acceptErrors && !isMatrix(arg) && isEvaluationError(arg?.value)) return arg;
4683
+ if (!currentArgDefinitions[i].acceptErrors && !isMatrix(arg) && isEvaluationError(arg?.value)) return arg;
4643
4684
  }
4644
4685
  try {
4645
4686
  return computeFunctionToObject.apply(this, args);
@@ -8968,6 +9009,25 @@ const funnelTooltipPositioner = function(elements) {
8968
9009
  };
8969
9010
  };
8970
9011
 
9012
+ //#endregion
9013
+ //#region src/components/figures/chart/chartJs/chartjs_geo_projection_plugin.ts
9014
+ /**
9015
+ * ChartJS plugin to apply custom changes to a d3 projection.
9016
+ *
9017
+ * We pass the projection as a string instead of a customized d3 object so
9018
+ * Chart.js creates a fresh projection instance. Custom changes (e.g. rotation)
9019
+ * are then applied in `beforeUpdate`.
9020
+ *
9021
+ * This is important because Chart.js mutates the projection instance at runtime,
9022
+ * and a customize d3 projection object would not be copied during deepCopy.
9023
+ */
9024
+ const geoProjectionPlugin = {
9025
+ id: "geoProjection",
9026
+ beforeUpdate(chart) {
9027
+ if (chart.options?.scales?.projection?.projection === "conicConformal") chart.scales?.projection?.projection?.rotate([100, 0]);
9028
+ }
9029
+ };
9030
+
8971
9031
  //#endregion
8972
9032
  //#region src/components/figures/chart/chartJs/chartjs_minor_grid_plugin.ts
8973
9033
  const chartMinorGridPlugin = {
@@ -10025,7 +10085,7 @@ function getGeoChartScales(definition, args) {
10025
10085
  const format = axisFormats?.y || axisFormats?.y1;
10026
10086
  return {
10027
10087
  projection: {
10028
- projection: getGeoChartProjection(region?.defaultProjection || "mercator"),
10088
+ projection: region?.defaultProjection || "mercator",
10029
10089
  axis: "x"
10030
10090
  },
10031
10091
  color: {
@@ -10077,10 +10137,6 @@ function getFunnelChartScales(definition, args) {
10077
10137
  }
10078
10138
  };
10079
10139
  }
10080
- function getGeoChartProjection(projection) {
10081
- if (projection === "conicConformal") return globalThis.ChartGeo.geoConicConformal().rotate([100, 0]);
10082
- return projection;
10083
- }
10084
10140
  function getChartAxisTitleRuntime(design) {
10085
10141
  if (design?.title?.text) {
10086
10142
  const { text, color, align, italic, bold } = design.title;
@@ -10252,7 +10308,7 @@ function getCalendarChartDatasetAndLabels(definition, args) {
10252
10308
  borderWidth: 1,
10253
10309
  barPercentage: 1,
10254
10310
  categoryPercentage: 1,
10255
- values: dataSetValues.data.map((cell) => isNumberResult(cell) ? cell.value : NaN)
10311
+ values: dataSetValues.data.map((cell) => isNumberResult(cell) ? cell.value : void 0)
10256
10312
  });
10257
10313
  return {
10258
10314
  labels,
@@ -10965,6 +11021,10 @@ chartJsExtensionRegistry.add("chartBackgroundPlugin", {
10965
11021
  register: (Chart) => Chart.register(chartBackgroundPlugin),
10966
11022
  unregister: (Chart) => Chart.unregister(chartBackgroundPlugin)
10967
11023
  });
11024
+ chartJsExtensionRegistry.add("geoProjectionPlugin", {
11025
+ register: (Chart) => Chart.register(geoProjectionPlugin),
11026
+ unregister: (Chart) => Chart.unregister(geoProjectionPlugin)
11027
+ });
10968
11028
  var ChartJsComponent = class extends _odoo_owl.Component {
10969
11029
  static template = "o-spreadsheet-ChartJsComponent";
10970
11030
  static props = {
@@ -11822,6 +11882,19 @@ function isOtherMobileOS() {
11822
11882
  function isMobileOS() {
11823
11883
  return isAndroid() || isIOS() || isOtherMobileOS();
11824
11884
  }
11885
+ const INTERACTIVE_ELEMENT_SELECTOR = "select, input, textarea, button, .o-select, .os-input, .o-input, .o-button, .o-button-icon, .o-button-link, .o-composer";
11886
+ /** Check if there is an interactive element (input, select, button, ...) between the event.target and event.currentTarget (inclusive)*/
11887
+ function hasInteractiveElementInEventTree(event) {
11888
+ const target = event.target;
11889
+ const root = event.currentTarget;
11890
+ if (!root || !target || !root.contains(target)) return false;
11891
+ let node = target;
11892
+ while (node && node !== root) {
11893
+ if (node.matches(INTERACTIVE_ELEMENT_SELECTOR)) return true;
11894
+ node = node.parentElement;
11895
+ }
11896
+ return root.matches(INTERACTIVE_ELEMENT_SELECTOR);
11897
+ }
11825
11898
 
11826
11899
  //#endregion
11827
11900
  //#region src/components/helpers/zoom.ts
@@ -18279,7 +18352,7 @@ var FigureComponent = class extends _odoo_owl.Component {
18279
18352
  case "ArrowLeft":
18280
18353
  case "ArrowRight":
18281
18354
  case "ArrowUp":
18282
- const { col, row, offset } = this.postionInBoundary(this.props.figureUI, ev.key);
18355
+ const { col, row, offset } = this.postionInBoundary(this.env.model.getters.getActiveSheetId(), this.props.figureUI, ev.key);
18283
18356
  this.env.model.dispatch("UPDATE_FIGURE", {
18284
18357
  sheetId: this.env.model.getters.getActiveSheetId(),
18285
18358
  figureId: this.props.figureUI.id,
@@ -18303,34 +18376,52 @@ var FigureComponent = class extends _odoo_owl.Component {
18303
18376
  break;
18304
18377
  }
18305
18378
  }
18306
- postionInBoundary(position, key) {
18307
- const sheetId = this.env.model.getters.getActiveSheetId();
18308
- let { col, row, offset } = position;
18379
+ postionInBoundary(sheetId, figure, key) {
18380
+ let { col, row, offset } = figure;
18309
18381
  offset = { ...offset };
18382
+ const maxAnchor = this.env.model.getters.getMaxAnchorOffset(sheetId, figure.height, figure.width);
18310
18383
  switch (key) {
18311
18384
  case "ArrowUp":
18312
18385
  if (offset.y === 0) {
18313
18386
  row--;
18387
+ while (row > 0 && this.env.model.getters.isRowHiddenByUser(sheetId, row)) row--;
18314
18388
  offset.y = this.env.model.getters.getRowSize(sheetId, row) - 1;
18315
18389
  } else offset.y--;
18316
18390
  break;
18317
18391
  case "ArrowLeft":
18318
18392
  if (offset.x === 0) {
18319
18393
  col--;
18394
+ while (col > 0 && this.env.model.getters.isColHiddenByUser(sheetId, col)) col--;
18320
18395
  offset.x = this.env.model.getters.getColSize(sheetId, col) - 1;
18321
18396
  } else offset.x--;
18322
18397
  break;
18323
18398
  case "ArrowDown":
18324
18399
  if (offset.y === this.env.model.getters.getRowSize(sheetId, row)) {
18325
18400
  row++;
18401
+ while (row <= maxAnchor.row && this.env.model.getters.isRowHiddenByUser(sheetId, row)) row++;
18326
18402
  offset.y = 0;
18327
18403
  } else offset.y++;
18328
18404
  break;
18329
18405
  case "ArrowRight": if (offset.x === this.env.model.getters.getColSize(sheetId, row)) {
18330
18406
  col++;
18407
+ while (col <= maxAnchor.col && this.env.model.getters.isColHiddenByUser(sheetId, col)) col++;
18331
18408
  offset.x = 0;
18332
18409
  } else offset.x++;
18333
18410
  }
18411
+ if (col < 0) {
18412
+ col = 0;
18413
+ offset.x = 0;
18414
+ } else if (col > maxAnchor.col || col === maxAnchor.col && offset.x > maxAnchor.offset.x) {
18415
+ col = maxAnchor.col;
18416
+ offset.x = maxAnchor.offset.x;
18417
+ }
18418
+ if (row < 0) {
18419
+ row = 0;
18420
+ offset.y = 0;
18421
+ } else if (row > maxAnchor.row || row === maxAnchor.row && offset.y > maxAnchor.offset.y) {
18422
+ row = maxAnchor.row;
18423
+ offset.y = maxAnchor.offset.y;
18424
+ }
18334
18425
  return {
18335
18426
  col,
18336
18427
  row,
@@ -38041,13 +38132,9 @@ var PivotLayoutConfigurator = class extends _odoo_owl.Component {
38041
38132
  dimensionsRef = (0, _odoo_owl.useRef)("pivot-dimensions");
38042
38133
  dragAndDrop = useDragAndDropListItems();
38043
38134
  AGGREGATORS = AGGREGATORS;
38044
- composerFocus;
38045
38135
  isDateOrDatetimeField = isDateOrDatetimeField;
38046
- setup() {
38047
- this.composerFocus = useStore(ComposerFocusStore);
38048
- }
38049
38136
  startDragAndDrop(dimension, event) {
38050
- if (event.button !== 0 || event.target.tagName === "SELECT") return;
38137
+ if (event.button !== 0 || hasInteractiveElementInEventTree(event)) return;
38051
38138
  const rects = this.getDimensionElementsRects();
38052
38139
  const { columns, rows } = this.props.definition;
38053
38140
  const draggableIds = [
@@ -38087,7 +38174,7 @@ var PivotLayoutConfigurator = class extends _odoo_owl.Component {
38087
38174
  return field.type === "date" ? this.props.dateGranularities : this.props.datetimeGranularities;
38088
38175
  }
38089
38176
  startDragAndDropMeasures(measure, event) {
38090
- if (event.button !== 0 || event.target.tagName === "SELECT" || event.target.tagName === "INPUT" || this.composerFocus.focusMode !== "inactive") return;
38177
+ if (event.button !== 0 || hasInteractiveElementInEventTree(event)) return;
38091
38178
  const rects = this.getDimensionElementsRects();
38092
38179
  const { measures, columns, rows } = this.props.definition;
38093
38180
  const draggableIds = measures.map((m) => m.id);
@@ -44674,7 +44761,13 @@ var CellComposerStore = class extends AbstractComposerStore {
44674
44761
  const cell = this.getters.getEvaluatedCell(position);
44675
44762
  if (cell.link && !isFormula(content)) content = markdownLink(content, cell.link.url);
44676
44763
  const currentFormat = this.getters.getCell(position)?.format;
44677
- const afterFormat = currentFormat === "@" || currentFormat && isDateTimeFormat(currentFormat) ? void 0 : detectDateFormat(content, this.getters.getLocale());
44764
+ const isCurrentFormatDate = currentFormat && isDateTimeFormat(currentFormat);
44765
+ const contentDateFormat = detectDateFormat(content, this.getters.getLocale());
44766
+ let afterFormat;
44767
+ if (currentFormat !== "@") {
44768
+ if (contentDateFormat && !isCurrentFormatDate) afterFormat = contentDateFormat;
44769
+ else if (isCurrentFormatDate && isNumber(content, this.getters.getLocale())) afterFormat = "";
44770
+ }
44678
44771
  this.addHeadersForSpreadingFormula(content);
44679
44772
  result = this.model.dispatch("UPDATE_CELL", {
44680
44773
  ...this.currentEditedCell,
@@ -62565,7 +62658,7 @@ var SheetUIPlugin = class extends UIPlugin {
62565
62658
  if (contentWidth === 0) return 0;
62566
62659
  contentWidth += 2 * 4;
62567
62660
  if (style.wrapping === "wrap") {
62568
- const colWidth = this.getters.getColSize(this.getters.getActiveSheetId(), position.col);
62661
+ const colWidth = this.getters.getColSize(position.sheetId, position.col);
62569
62662
  return Math.min(colWidth, contentWidth);
62570
62663
  }
62571
62664
  return contentWidth;
@@ -66388,6 +66481,10 @@ function inverseCreateFigure(cmd) {
66388
66481
  }
66389
66482
  function inverseCreateChart(cmd) {
66390
66483
  return [{
66484
+ type: "DELETE_CHART",
66485
+ chartId: cmd.chartId,
66486
+ sheetId: cmd.sheetId
66487
+ }, {
66391
66488
  type: "DELETE_FIGURE",
66392
66489
  figureId: cmd.figureId,
66393
66490
  sheetId: cmd.sheetId
@@ -68252,6 +68349,7 @@ var SpreadsheetDashboard = class extends _odoo_owl.Component {
68252
68349
  return (0, _odoo_owl.toRaw)(this.clickableCellsStore.clickableCells);
68253
68350
  }
68254
68351
  selectClickableCell(ev, clickableCell) {
68352
+ if (![0, 1].includes(ev.button)) return;
68255
68353
  const { position, action } = clickableCell;
68256
68354
  action(position, this.env, isMiddleClickOrCtrlClick(ev));
68257
68355
  }
@@ -84851,6 +84949,6 @@ exports.stores = stores;
84851
84949
  exports.tokenColors = tokenColors;
84852
84950
  exports.tokenize = tokenize;
84853
84951
 
84854
- __info__.version = "19.3.13";
84855
- __info__.date = "2026-07-23T07:41:06.182Z";
84856
- __info__.hash = "2059bd0";
84952
+ __info__.version = "19.3.15";
84953
+ __info__.date = "2026-08-10T12:32:40.247Z";
84954
+ __info__.hash = "25f760e";
@@ -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 19.3.13
6
- * @date 2026-07-23T07:41:07.881Z
7
- * @hash 2059bd0
5
+ * @version 19.3.15
6
+ * @date 2026-08-10T12:32:41.948Z
7
+ * @hash 25f760e
8
8
  */
9
9
  :root {
10
10
  --os-gray-100: light-dark(#f9fafb, #1b1d26);