@odoo/o-spreadsheet 16.1.14 → 16.1.16

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.
@@ -109,7 +109,7 @@ const SELECTION_BORDER_COLOR = "#3266ca";
109
109
  const HEADER_BORDER_COLOR = "#C0C0C0";
110
110
  const CELL_BORDER_COLOR = "#E2E3E3";
111
111
  const BACKGROUND_CHART_COLOR = "#FFFFFF";
112
- const MENU_ITEM_DISABLED_COLOR = "#CACACA";
112
+ const DISABLED_TEXT_COLOR = "#CACACA";
113
113
  const DEFAULT_COLOR_SCALE_MIDPOINT_COLOR = 0xb6d7a8;
114
114
  const LINK_COLOR = "#01666b";
115
115
  const FILTERS_COLOR = "#188038";
@@ -726,12 +726,20 @@ function getDefaultCellHeight(style) {
726
726
  return computeTextLinesHeight(fontSize) + 2 * PADDING_AUTORESIZE_VERTICAL;
727
727
  }
728
728
  function computeTextWidth(context, text, style) {
729
- context.save();
730
- context.font = computeTextFont(style);
731
- const textWidth = context.measureText(text).width;
732
- context.restore();
733
- return textWidth;
729
+ const font = computeTextFont(style);
730
+ if (!textWidthCache[font]) {
731
+ textWidthCache[font] = {};
732
+ }
733
+ if (textWidthCache[font][text] === undefined) {
734
+ context.save();
735
+ context.font = font;
736
+ const textWidth = context.measureText(text).width;
737
+ context.restore();
738
+ textWidthCache[font][text] = textWidth;
739
+ }
740
+ return textWidthCache[font][text];
734
741
  }
742
+ const textWidthCache = {};
735
743
  function computeTextFont(style) {
736
744
  const italic = style.italic ? "italic " : "";
737
745
  const weight = style.bold ? "bold" : DEFAULT_FONT_WEIGHT;
@@ -3451,7 +3459,6 @@ const readonlyAllowedCommands = new Set([
3451
3459
  "SET_VIEWPORT_OFFSET",
3452
3460
  "SELECT_SEARCH_NEXT_MATCH",
3453
3461
  "SELECT_SEARCH_PREVIOUS_MATCH",
3454
- "REFRESH_SEARCH",
3455
3462
  "UPDATE_SEARCH",
3456
3463
  "CLEAR_SEARCH",
3457
3464
  "EVALUATE_CELLS",
@@ -5959,7 +5966,7 @@ css /* scss */ `
5959
5966
  }
5960
5967
  }
5961
5968
  &.disabled {
5962
- color: ${MENU_ITEM_DISABLED_COLOR};
5969
+ color: ${DISABLED_TEXT_COLOR};
5963
5970
  cursor: not-allowed;
5964
5971
  }
5965
5972
  }
@@ -21711,11 +21718,16 @@ class FindAndReplacePanel extends owl.Component {
21711
21718
  }
21712
21719
  setup() {
21713
21720
  this.showFormulaState = this.env.model.getters.shouldShowFormulas();
21721
+ this.debouncedUpdateSearch = debounce(this.updateSearch.bind(this), 200);
21714
21722
  owl.onMounted(() => this.focusInput());
21715
21723
  owl.onWillUnmount(() => {
21716
21724
  this.env.model.dispatch("CLEAR_SEARCH");
21717
21725
  this.env.model.dispatch("SET_FORMULA_VISIBILITY", { show: this.showFormulaState });
21718
21726
  });
21727
+ owl.useEffect(() => {
21728
+ this.state.searchOptions.searchFormulas = this.env.model.getters.shouldShowFormulas();
21729
+ this.searchFormulas();
21730
+ }, () => [this.env.model.getters.shouldShowFormulas()]);
21719
21731
  }
21720
21732
  onInput(ev) {
21721
21733
  this.state.toSearch = ev.target.value;
@@ -21735,10 +21747,6 @@ class FindAndReplacePanel extends owl.Component {
21735
21747
  this.replace();
21736
21748
  }
21737
21749
  }
21738
- onFocusSidePanel() {
21739
- this.state.searchOptions.searchFormulas = this.env.model.getters.shouldShowFormulas();
21740
- this.env.model.dispatch("REFRESH_SEARCH");
21741
- }
21742
21750
  searchFormulas() {
21743
21751
  this.env.model.dispatch("SET_FORMULA_VISIBILITY", {
21744
21752
  show: this.state.searchOptions.searchFormulas,
@@ -21757,13 +21765,6 @@ class FindAndReplacePanel extends owl.Component {
21757
21765
  searchOptions: this.state.searchOptions,
21758
21766
  });
21759
21767
  }
21760
- debouncedUpdateSearch() {
21761
- clearTimeout(this.debounceTimeoutId);
21762
- this.debounceTimeoutId = setTimeout(() => {
21763
- this.updateSearch();
21764
- this.debounceTimeoutId = undefined;
21765
- }, 400);
21766
- }
21767
21768
  replace() {
21768
21769
  this.env.model.dispatch("REPLACE_SEARCH", {
21769
21770
  replaceWith: this.state.replaceWith,
@@ -22267,6 +22268,14 @@ class FiguresContainer extends owl.Component {
22267
22268
  if (dirY < 0) {
22268
22269
  this.dnd.y = dndInitialY + figure.height * fraction;
22269
22270
  }
22271
+ if (this.dnd.x < 0) {
22272
+ this.dnd.width += this.dnd.x;
22273
+ this.dnd.x = 0;
22274
+ }
22275
+ if (this.dnd.y < 0) {
22276
+ this.dnd.height += this.dnd.y;
22277
+ this.dnd.y = 0;
22278
+ }
22270
22279
  };
22271
22280
  }
22272
22281
  else {
@@ -22282,6 +22291,14 @@ class FiguresContainer extends owl.Component {
22282
22291
  if (dirY < 0) {
22283
22292
  this.dnd.y = dndInitialY - deltaY;
22284
22293
  }
22294
+ if (this.dnd.x < 0) {
22295
+ this.dnd.width += this.dnd.x;
22296
+ this.dnd.x = 0;
22297
+ }
22298
+ if (this.dnd.y < 0) {
22299
+ this.dnd.height += this.dnd.y;
22300
+ this.dnd.y = 0;
22301
+ }
22285
22302
  };
22286
22303
  }
22287
22304
  const onMouseUp = (ev) => {
@@ -29560,7 +29577,14 @@ class FiltersPlugin extends CorePlugin {
29560
29577
  this.history.update("tables", filterTables);
29561
29578
  break;
29562
29579
  case "DUPLICATE_SHEET":
29563
- this.history.update("tables", cmd.sheetIdTo, deepCopy(this.tables[cmd.sheetId]));
29580
+ const tables = {};
29581
+ for (const filterTable of Object.values(this.tables[cmd.sheetId] || {})) {
29582
+ if (filterTable) {
29583
+ const newFilterTable = deepCopy(filterTable);
29584
+ tables[newFilterTable.id] = newFilterTable;
29585
+ }
29586
+ }
29587
+ this.history.update("tables", cmd.sheetIdTo, tables);
29564
29588
  break;
29565
29589
  case "ADD_COLUMNS_ROWS":
29566
29590
  this.onAddColumnsRows(cmd);
@@ -33104,6 +33128,7 @@ class FilterEvaluationPlugin extends UIPlugin {
33104
33128
  }
33105
33129
  exportForExcel(data) {
33106
33130
  for (const sheetData of data.sheets) {
33131
+ const sheetId = sheetData.id;
33107
33132
  for (const tableData of sheetData.filterTables) {
33108
33133
  const tableZone = toZone(tableData.range);
33109
33134
  const filters = [];
@@ -33119,20 +33144,20 @@ class FilterEvaluationPlugin extends UIPlugin {
33119
33144
  if (!filter)
33120
33145
  continue;
33121
33146
  const valuesInFilterZone = filter.filteredZone
33122
- ? positions(filter.filteredZone)
33123
- .map(({ col, row }) => this.getters.getEvaluatedCell({ sheetId: sheetData.id, col, row }))
33124
- .filter((cell) => cell.type !== CellValueType.empty)
33125
- .map((cell) => cell.formattedValue)
33147
+ ? positions(filter.filteredZone).map((position) => this.getters.getEvaluatedCell({ sheetId, ...position }).formattedValue)
33126
33148
  : [];
33127
- // In xlsx, filtered values = values that are displayed, not values that are hidden
33128
- const xlsxFilteredValues = valuesInFilterZone.filter((val) => !filteredValues.includes(val));
33129
- filters.push({ colId: i, filteredValues: [...new Set(xlsxFilteredValues)] });
33130
- // In xlsx, filter header should ALWAYS be a string and should be unique
33131
- const headerPosition = {
33132
- col: filter.col,
33133
- row: filter.zoneWithHeaders.top,
33134
- sheetId: sheetData.id,
33135
- };
33149
+ if (filteredValues.length) {
33150
+ const xlsxDisplayedValues = valuesInFilterZone
33151
+ .filter((val) => val)
33152
+ .filter((val) => !filteredValues.includes(val));
33153
+ filters.push({
33154
+ colId: i,
33155
+ displayedValues: [...new Set(xlsxDisplayedValues)],
33156
+ displayBlanks: !filteredValues.includes("") && valuesInFilterZone.some((val) => !val),
33157
+ });
33158
+ }
33159
+ // In xlsx, filter header should ALWAYS be a string and should be unique in the table
33160
+ const headerPosition = { col: filter.col, row: filter.zoneWithHeaders.top, sheetId };
33136
33161
  const headerString = this.getters.getEvaluatedCell(headerPosition).formattedValue;
33137
33162
  const headerName = this.getUniqueColNameForExcel(i, headerString, headerNames);
33138
33163
  headerNames.push(headerName);
@@ -34868,6 +34893,7 @@ class FindAndReplacePlugin extends UIPlugin {
34868
34893
  searchFormulas: false,
34869
34894
  };
34870
34895
  this.toSearch = "";
34896
+ this.isSearchDirty = false;
34871
34897
  }
34872
34898
  // ---------------------------------------------------------------------------
34873
34899
  // Command Handling
@@ -34896,14 +34922,21 @@ class FindAndReplacePlugin extends UIPlugin {
34896
34922
  case "REDO":
34897
34923
  case "REMOVE_COLUMNS_ROWS":
34898
34924
  case "ADD_COLUMNS_ROWS":
34899
- this.clearSearch();
34925
+ case "EVALUATE_CELLS":
34926
+ case "UPDATE_CELL":
34927
+ this.isSearchDirty = true;
34900
34928
  break;
34901
34929
  case "ACTIVATE_SHEET":
34902
- case "REFRESH_SEARCH":
34903
34930
  this.refreshSearch();
34904
34931
  break;
34905
34932
  }
34906
34933
  }
34934
+ finalize() {
34935
+ if (this.isSearchDirty) {
34936
+ this.refreshSearch();
34937
+ this.isSearchDirty = false;
34938
+ }
34939
+ }
34907
34940
  // ---------------------------------------------------------------------------
34908
34941
  // Getters
34909
34942
  // ---------------------------------------------------------------------------
@@ -34959,6 +34992,11 @@ class FindAndReplacePlugin extends UIPlugin {
34959
34992
  if (this.toSearch) {
34960
34993
  for (const cell of Object.values(cells)) {
34961
34994
  const { col, row } = this.getters.getCellPosition(cell.id);
34995
+ const isColHidden = this.getters.isColHidden(sheetId, col);
34996
+ const isRowHidden = this.getters.isRowHidden(sheetId, row);
34997
+ if (isColHidden || isRowHidden) {
34998
+ continue;
34999
+ }
34962
35000
  if (cell &&
34963
35001
  this.currentSearchRegex &&
34964
35002
  this.currentSearchRegex.test(this.getSearchableString({ sheetId, col, row }))) {
@@ -36161,15 +36199,15 @@ SelectionInputPlugin.getters = [];
36161
36199
  * This plugin handles this internal state.
36162
36200
  */
36163
36201
  class SelectionInputsManagerPlugin extends UIPlugin {
36202
+ get currentInput() {
36203
+ return this.focusedInputId ? this.inputs[this.focusedInputId] : null;
36204
+ }
36164
36205
  constructor(config) {
36165
36206
  super(config);
36166
36207
  this.config = config;
36167
36208
  this.inputs = {};
36168
36209
  this.focusedInputId = null;
36169
36210
  }
36170
- get currentInput() {
36171
- return this.focusedInputId ? this.inputs[this.focusedInputId] : null;
36172
- }
36173
36211
  // ---------------------------------------------------------------------------
36174
36212
  // Command Handling
36175
36213
  // ---------------------------------------------------------------------------
@@ -37401,10 +37439,8 @@ class SortPlugin extends UIPlugin {
37401
37439
  }
37402
37440
  updateCellCommands.push(newCellValues);
37403
37441
  }
37404
- for (const cmd of updateCellCommands) {
37405
- this.dispatch("UPDATE_CELL", cmd);
37406
- }
37407
37442
  }
37443
+ updateCellCommands.forEach((cmdPayload) => this.dispatch("UPDATE_CELL", cmdPayload));
37408
37444
  }
37409
37445
  /**
37410
37446
  * Return the distances between main merge cells in the zone.
@@ -39731,6 +39767,11 @@ css /* scss */ `
39731
39767
  .o-sidePanelButton:enabled {
39732
39768
  cursor: pointer;
39733
39769
  }
39770
+
39771
+ .o-sidePanelButton:disabled {
39772
+ color: ${DISABLED_TEXT_COLOR};
39773
+ }
39774
+
39734
39775
  .o-sidePanelButton:last-child {
39735
39776
  margin-right: 0px;
39736
39777
  }
@@ -43300,15 +43341,10 @@ function addAutoFilter(table) {
43300
43341
  `;
43301
43342
  }
43302
43343
  function addFilterColumns(table) {
43303
- const tableZone = toZone(table.range);
43304
43344
  const columns = [];
43305
- for (const i of range(0, zoneToDimension(tableZone).width)) {
43306
- const filter = table.filters[i];
43307
- if (!filter || !filter.filteredValues.length) {
43308
- continue;
43309
- }
43345
+ for (const filter of table.filters) {
43310
43346
  const colXml = escapeXml /*xml*/ `
43311
- <filterColumn ${formatAttributes([["colId", i]])}>
43347
+ <filterColumn ${formatAttributes([["colId", filter.colId]])}>
43312
43348
  ${addFilter(filter)}
43313
43349
  </filterColumn>
43314
43350
  `;
@@ -43317,9 +43353,10 @@ function addFilterColumns(table) {
43317
43353
  return columns;
43318
43354
  }
43319
43355
  function addFilter(filter) {
43320
- const filterValues = filter.filteredValues.map((val) => escapeXml /*xml*/ `<filter ${formatAttributes([["val", val]])}/>`);
43356
+ const filterValues = filter.displayedValues.map((val) => escapeXml /*xml*/ `<filter ${formatAttributes([["val", val]])}/>`);
43357
+ const filterAttributes = filter.displayBlanks ? [["blank", 1]] : [];
43321
43358
  return escapeXml /*xml*/ `
43322
- <filters>
43359
+ <filters ${formatAttributes(filterAttributes)}>
43323
43360
  ${joinXmlNodes(filterValues)}
43324
43361
  </filters>
43325
43362
  `;
@@ -44272,6 +44309,6 @@ exports.setTranslationMethod = setTranslationMethod;
44272
44309
  exports.tokenize = tokenize;
44273
44310
 
44274
44311
 
44275
- __info__.version = '16.1.14';
44276
- __info__.date = '2023-06-12T13:50:13.693Z';
44277
- __info__.hash = 'a51d9fa';
44312
+ __info__.version = '16.1.16';
44313
+ __info__.date = '2023-07-26T12:09:57.059Z';
44314
+ __info__.hash = '96f5f09';