@odoo/o-spreadsheet 18.3.9 → 18.3.11

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 18.3.9
6
- * @date 2025-06-19T18:24:02.754Z
7
- * @hash a820230
5
+ * @version 18.3.11
6
+ * @date 2025-06-27T09:13:07.206Z
7
+ * @hash 460d5d0
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -141,6 +141,7 @@ const FROZEN_PANE_HEADER_BORDER_COLOR = "#BCBCBC";
141
141
  const FROZEN_PANE_BORDER_COLOR = "#DADFE8";
142
142
  const COMPOSER_ASSISTANT_COLOR = "#9B359B";
143
143
  const COLOR_TRANSPARENT = "#00000000";
144
+ const TABLE_HOVER_BACKGROUND_COLOR = "#017E8414";
144
145
  const CHART_WATERFALL_POSITIVE_COLOR = "#4EA7F2";
145
146
  const CHART_WATERFALL_NEGATIVE_COLOR = "#EA6175";
146
147
  const CHART_WATERFALL_SUBTOTAL_COLOR = "#AAAAAA";
@@ -7120,6 +7121,63 @@ function parseOSClipboardContent(content, clipboardId) {
7120
7121
  };
7121
7122
  return osClipboardContent;
7122
7123
  }
7124
+ /**
7125
+ * Applies each clipboard handler to paste its corresponding data into the target.
7126
+ */
7127
+ const applyClipboardHandlersPaste = (handlers, copiedData, target, options) => {
7128
+ handlers.forEach(({ handlerName, handler }) => {
7129
+ const data = copiedData[handlerName];
7130
+ if (data) {
7131
+ handler.paste(target, data, options);
7132
+ }
7133
+ });
7134
+ };
7135
+ /**
7136
+ * Returns the paste target based on clipboard handlers.
7137
+ * Also includes the full affected zone and the list of pasted zones for selection.
7138
+ */
7139
+ function getPasteTargetFromHandlers(sheetId, zones, copiedData, handlers, options) {
7140
+ let zone = undefined;
7141
+ let selectedZones = [];
7142
+ let target = {
7143
+ sheetId,
7144
+ zones,
7145
+ };
7146
+ for (const { handlerName, handler } of handlers) {
7147
+ const handlerData = copiedData[handlerName];
7148
+ if (!handlerData) {
7149
+ continue;
7150
+ }
7151
+ const currentTarget = handler.getPasteTarget(sheetId, zones, handlerData, options);
7152
+ if (currentTarget.figureId) {
7153
+ target.figureId = currentTarget.figureId;
7154
+ }
7155
+ for (const targetZone of currentTarget.zones) {
7156
+ selectedZones.push(targetZone);
7157
+ if (zone === undefined) {
7158
+ zone = targetZone;
7159
+ continue;
7160
+ }
7161
+ zone = union(zone, targetZone);
7162
+ }
7163
+ }
7164
+ return {
7165
+ target,
7166
+ zone,
7167
+ selectedZones,
7168
+ };
7169
+ }
7170
+ /**
7171
+ * Updates the selection after a paste operation.
7172
+ */
7173
+ const selectPastedZone = (selection, sourceZones, pastedZones) => {
7174
+ const anchorCell = {
7175
+ col: sourceZones[0].left,
7176
+ row: sourceZones[0].top,
7177
+ };
7178
+ selection.getBackToDefault();
7179
+ selection.selectZone({ cell: anchorCell, zone: union(...pastedZones) }, { scrollIntoView: false });
7180
+ };
7123
7181
 
7124
7182
  class ClipboardHandler {
7125
7183
  getters;
@@ -23037,7 +23095,7 @@ class AbstractComposerStore extends SpreadsheetStore {
23037
23095
  }
23038
23096
  captureSelection(zone, col, row) {
23039
23097
  this.model.selection.capture(this, {
23040
- cell: { col: col || zone.left, row: row || zone.right },
23098
+ cell: { col: col ?? zone.left, row: row ?? zone.right },
23041
23099
  zone,
23042
23100
  }, {
23043
23101
  handleEvent: this.handleEvent.bind(this),
@@ -45798,6 +45856,9 @@ class ConditionalFormattingPanel extends Component {
45798
45856
  this.switchToList();
45799
45857
  }
45800
45858
  }
45859
+ else if (!this.editedCF) {
45860
+ this.switchToList();
45861
+ }
45801
45862
  });
45802
45863
  }
45803
45864
  get conditionalFormats() {
@@ -49821,7 +49882,7 @@ class SpreadsheetPivot {
49821
49882
  }
49822
49883
  getTypeFromZone(sheetId, zone) {
49823
49884
  const cells = this.getters.getEvaluatedCellsInZone(sheetId, zone);
49824
- const nonEmptyCells = cells.filter((cell) => cell.type !== CellValueType.empty);
49885
+ const nonEmptyCells = cells.filter((cell) => !(cell.type === CellValueType.empty || cell.value === ""));
49825
49886
  if (nonEmptyCells.length === 0) {
49826
49887
  return "integer";
49827
49888
  }
@@ -53538,15 +53599,16 @@ class GridAddRowsFooter extends Component {
53538
53599
  }
53539
53600
  }
53540
53601
 
53602
+ const PAINT_FORMAT_HANDLER_KEYS = [
53603
+ "cell",
53604
+ "border",
53605
+ "table",
53606
+ "conditionalFormat",
53607
+ "merge",
53608
+ ];
53541
53609
  class PaintFormatStore extends SpreadsheetStore {
53542
53610
  mutators = ["activate", "cancel", "pasteFormat"];
53543
53611
  highlightStore = this.get(HighlightStore);
53544
- clipboardHandlers = [
53545
- new CellClipboardHandler(this.getters, this.model.dispatch),
53546
- new BorderClipboardHandler(this.getters, this.model.dispatch),
53547
- new TableClipboardHandler(this.getters, this.model.dispatch),
53548
- new ConditionalFormatClipboardHandler(this.getters, this.model.dispatch),
53549
- ];
53550
53612
  status = "inactive";
53551
53613
  copiedData;
53552
53614
  constructor(get) {
@@ -53577,24 +53639,38 @@ class PaintFormatStore extends SpreadsheetStore {
53577
53639
  get isActive() {
53578
53640
  return this.status !== "inactive";
53579
53641
  }
53642
+ get clipboardHandlers() {
53643
+ return PAINT_FORMAT_HANDLER_KEYS.map((handlerName) => {
53644
+ const HandlerClass = clipboardHandlersRegistries.cellHandlers.get(handlerName);
53645
+ return {
53646
+ handlerName,
53647
+ handler: new HandlerClass(this.getters, this.model.dispatch),
53648
+ };
53649
+ });
53650
+ }
53580
53651
  copyFormats() {
53581
53652
  const sheetId = this.getters.getActiveSheetId();
53582
53653
  const zones = this.getters.getSelectedZones();
53583
- const copiedData = {};
53584
- for (const handler of this.clipboardHandlers) {
53585
- Object.assign(copiedData, handler.copy(getClipboardDataPositions(sheetId, zones), false));
53654
+ const copiedData = { zones, sheetId };
53655
+ for (const { handlerName, handler } of this.clipboardHandlers) {
53656
+ const handlerResult = handler.copy(getClipboardDataPositions(sheetId, zones), false);
53657
+ if (handlerResult !== undefined) {
53658
+ copiedData[handlerName] = handlerResult;
53659
+ }
53586
53660
  }
53587
53661
  return copiedData;
53588
53662
  }
53589
53663
  paintFormat(sheetId, target) {
53590
- if (this.copiedData) {
53591
- for (const handler of this.clipboardHandlers) {
53592
- handler.paste({ zones: target, sheetId }, this.copiedData, {
53593
- isCutOperation: false,
53594
- pasteOption: "onlyFormat",
53595
- });
53596
- }
53664
+ if (!this.copiedData) {
53665
+ return;
53597
53666
  }
53667
+ const options = {
53668
+ isCutOperation: false,
53669
+ pasteOption: "onlyFormat",
53670
+ };
53671
+ const { target: pasteTarget, selectedZones } = getPasteTargetFromHandlers(sheetId, target, this.copiedData, this.clipboardHandlers, options);
53672
+ applyClipboardHandlersPaste(this.clipboardHandlers, this.copiedData, pasteTarget, options);
53673
+ selectPastedZone(this.model.selection, target, selectedZones);
53598
53674
  if (this.status === "oneOff") {
53599
53675
  this.cancel();
53600
53676
  }
@@ -53641,12 +53717,8 @@ class HoveredTableStore extends SpreadsheetStore {
53641
53717
  this.row = undefined;
53642
53718
  }
53643
53719
  computeOverlay() {
53644
- if (!this.getters.isDashboard()) {
53645
- return;
53646
- }
53647
53720
  this.overlayColors = new PositionMap();
53648
- const col = this.col;
53649
- const row = this.row;
53721
+ const { col, row } = this;
53650
53722
  if (col === undefined || row === undefined) {
53651
53723
  return;
53652
53724
  }
@@ -53655,9 +53727,16 @@ class HoveredTableStore extends SpreadsheetStore {
53655
53727
  if (!table) {
53656
53728
  return;
53657
53729
  }
53658
- const { left, right } = table.range.zone;
53659
- for (let c = left; c <= right; c++) {
53660
- this.overlayColors.set({ sheetId, col: c, row }, setColorAlpha("#017E84", 0.08));
53730
+ const { left, right, top } = table.range.zone;
53731
+ const isTableHeader = row < top + table.config.numberOfHeaders;
53732
+ const doesTableRowHaveContent = range(left, right + 1).some((col) => {
53733
+ return (!this.getters.isColHidden(sheetId, col) &&
53734
+ this.getters.getEvaluatedCell({ sheetId, col, row }).formattedValue);
53735
+ });
53736
+ if (!isTableHeader && doesTableRowHaveContent) {
53737
+ for (let col = left; col <= right; col++) {
53738
+ this.overlayColors.set({ sheetId, col, row }, TABLE_HOVER_BACKGROUND_COLOR);
53739
+ }
53661
53740
  }
53662
53741
  }
53663
53742
  }
@@ -59004,7 +59083,7 @@ class DataValidationPlugin extends CorePlugin {
59004
59083
  else if (newRule.criterion.type === "isValueInList") {
59005
59084
  newRule.criterion.values = Array.from(new Set(newRule.criterion.values));
59006
59085
  }
59007
- const adaptedRules = this.removeRangesFromRules(sheetId, newRule.ranges, rules);
59086
+ const adaptedRules = this.removeRangesFromRules(sheetId, newRule.ranges, rules, newRule.id);
59008
59087
  const ruleIndex = adaptedRules.findIndex((rule) => rule.id === newRule.id);
59009
59088
  if (ruleIndex !== -1) {
59010
59089
  adaptedRules[ruleIndex] = newRule;
@@ -59014,9 +59093,12 @@ class DataValidationPlugin extends CorePlugin {
59014
59093
  this.history.update("rules", sheetId, [...adaptedRules, newRule]);
59015
59094
  }
59016
59095
  }
59017
- removeRangesFromRules(sheetId, ranges, rules) {
59096
+ removeRangesFromRules(sheetId, ranges, rules, editingRuleId) {
59018
59097
  rules = deepCopy(rules);
59019
59098
  for (const rule of rules) {
59099
+ if (rule.id === editingRuleId) {
59100
+ continue; // Skip the rule being edited to preserve its place in the list
59101
+ }
59020
59102
  rule.ranges = this.getters.recomputeRanges(rule.ranges, ranges);
59021
59103
  }
59022
59104
  return rules.filter((rule) => rule.ranges.length > 0);
@@ -70844,49 +70926,17 @@ class ClipboardPlugin extends UIPlugin {
70844
70926
  if (!copiedData) {
70845
70927
  return;
70846
70928
  }
70847
- let zone = undefined;
70848
- let selectedZones = [];
70849
70929
  const sheetId = this.getters.getActiveSheetId();
70850
- let target = {
70851
- sheetId,
70852
- zones,
70853
- };
70854
70930
  const handlers = this.selectClipboardHandlers(copiedData);
70855
- for (const { handlerName, handler } of handlers) {
70856
- const handlerData = copiedData[handlerName];
70857
- if (!handlerData) {
70858
- continue;
70859
- }
70860
- const currentTarget = handler.getPasteTarget(sheetId, zones, handlerData, options);
70861
- if (currentTarget.figureId) {
70862
- target.figureId = currentTarget.figureId;
70863
- }
70864
- for (const targetZone of currentTarget.zones) {
70865
- selectedZones.push(targetZone);
70866
- if (zone === undefined) {
70867
- zone = targetZone;
70868
- continue;
70869
- }
70870
- zone = union(zone, targetZone);
70871
- }
70872
- }
70931
+ const { target, zone, selectedZones } = getPasteTargetFromHandlers(sheetId, zones, copiedData, handlers, options);
70873
70932
  if (zone !== undefined) {
70874
- this.addMissingDimensions(this.getters.getActiveSheetId(), zone.right - zone.left + 1, zone.bottom - zone.top + 1, zone.left, zone.top);
70933
+ this.addMissingDimensions(sheetId, zone.right - zone.left + 1, zone.bottom - zone.top + 1, zone.left, zone.top);
70875
70934
  }
70876
- handlers.forEach(({ handlerName, handler }) => {
70877
- const handlerData = copiedData[handlerName];
70878
- if (handlerData) {
70879
- handler.paste(target, handlerData, options);
70880
- }
70881
- });
70935
+ applyClipboardHandlersPaste(handlers, copiedData, target, options);
70882
70936
  if (!options?.selectTarget) {
70883
70937
  return;
70884
70938
  }
70885
- const selection = zones[0];
70886
- const col = selection.left;
70887
- const row = selection.top;
70888
- this.selection.getBackToDefault();
70889
- this.selection.selectZone({ cell: { col, row }, zone: union(...selectedZones) }, { scrollIntoView: false });
70939
+ selectPastedZone(this.selection, zones, selectedZones);
70890
70940
  }
70891
70941
  /**
70892
70942
  * Add columns and/or rows to ensure that col + width and row + height are still
@@ -77293,26 +77343,28 @@ class SelectionStreamProcessorImpl {
77293
77343
  bottom: Math.min(this.getters.getNumberRows(sheetId) - 1, bottom),
77294
77344
  };
77295
77345
  };
77296
- const { col: refCol, row: refRow } = this.getReferencePosition();
77346
+ const { cell: refCell, zone: refZone } = this.getReferenceAnchor();
77347
+ const { col: refCol, row: refRow } = refCell;
77297
77348
  // check if we can shrink selection
77298
77349
  let n = 0;
77299
77350
  while (result !== null) {
77300
77351
  n++;
77301
77352
  if (deltaCol < 0) {
77302
77353
  const newRight = this.getNextAvailableCol(deltaCol, right - (n - 1), refRow);
77303
- result = refCol <= right - n ? expand({ top, left, bottom, right: newRight }) : null;
77354
+ result = refZone.right <= right - n ? expand({ top, left, bottom, right: newRight }) : null;
77304
77355
  }
77305
77356
  if (deltaCol > 0) {
77306
77357
  const newLeft = this.getNextAvailableCol(deltaCol, left + (n - 1), refRow);
77307
- result = left + n <= refCol ? expand({ top, left: newLeft, bottom, right }) : null;
77358
+ result = left + n <= refZone.left ? expand({ top, left: newLeft, bottom, right }) : null;
77308
77359
  }
77309
77360
  if (deltaRow < 0) {
77310
77361
  const newBottom = this.getNextAvailableRow(deltaRow, refCol, bottom - (n - 1));
77311
- result = refRow <= bottom - n ? expand({ top, left, bottom: newBottom, right }) : null;
77362
+ result =
77363
+ refZone.bottom <= bottom - n ? expand({ top, left, bottom: newBottom, right }) : null;
77312
77364
  }
77313
77365
  if (deltaRow > 0) {
77314
77366
  const newTop = this.getNextAvailableRow(deltaRow, refCol, top + (n - 1));
77315
- result = top + n <= refRow ? expand({ top: newTop, left, bottom, right }) : null;
77367
+ result = top + n <= refZone.top ? expand({ top: newTop, left, bottom, right }) : null;
77316
77368
  }
77317
77369
  result = result ? reorderZone(result) : result;
77318
77370
  if (result && !isEqual(result, anchor.zone)) {
@@ -77542,18 +77594,26 @@ class SelectionStreamProcessorImpl {
77542
77594
  * If the anchor is hidden, browses from left to right and top to bottom to
77543
77595
  * find a visible cell.
77544
77596
  */
77545
- getReferencePosition() {
77597
+ getReferenceAnchor() {
77546
77598
  const sheetId = this.getters.getActiveSheetId();
77547
77599
  const anchor = this.anchor;
77548
77600
  const { left, right, top, bottom } = anchor.zone;
77549
77601
  const { col: anchorCol, row: anchorRow } = anchor.cell;
77602
+ const col = this.getters.isColHidden(sheetId, anchorCol)
77603
+ ? this.getters.findVisibleHeader(sheetId, "COL", left, right) || anchorCol
77604
+ : anchorCol;
77605
+ const row = this.getters.isRowHidden(sheetId, anchorRow)
77606
+ ? this.getters.findVisibleHeader(sheetId, "ROW", top, bottom) || anchorRow
77607
+ : anchorRow;
77608
+ const zone = this.getters.expandZone(sheetId, {
77609
+ left: col,
77610
+ right: col,
77611
+ top: row,
77612
+ bottom: row,
77613
+ });
77550
77614
  return {
77551
- col: this.getters.isColHidden(sheetId, anchorCol)
77552
- ? this.getters.findVisibleHeader(sheetId, "COL", left, right) || anchorCol
77553
- : anchorCol,
77554
- row: this.getters.isRowHidden(sheetId, anchorRow)
77555
- ? this.getters.findVisibleHeader(sheetId, "ROW", top, bottom) || anchorRow
77556
- : anchorRow,
77615
+ cell: { col, row },
77616
+ zone,
77557
77617
  };
77558
77618
  }
77559
77619
  deltaToTarget(position, direction, step) {
@@ -80663,6 +80723,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
80663
80723
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
80664
80724
 
80665
80725
 
80666
- __info__.version = "18.3.9";
80667
- __info__.date = "2025-06-19T18:24:02.754Z";
80668
- __info__.hash = "a820230";
80726
+ __info__.version = "18.3.11";
80727
+ __info__.date = "2025-06-27T09:13:07.206Z";
80728
+ __info__.hash = "460d5d0";