@odoo/o-spreadsheet 16.1.13 → 16.1.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.
@@ -722,12 +722,20 @@ function getDefaultCellHeight(style) {
722
722
  return computeTextLinesHeight(fontSize) + 2 * PADDING_AUTORESIZE_VERTICAL;
723
723
  }
724
724
  function computeTextWidth(context, text, style) {
725
- context.save();
726
- context.font = computeTextFont(style);
727
- const textWidth = context.measureText(text).width;
728
- context.restore();
729
- return textWidth;
725
+ const font = computeTextFont(style);
726
+ if (!textWidthCache[font]) {
727
+ textWidthCache[font] = {};
728
+ }
729
+ if (textWidthCache[font][text] === undefined) {
730
+ context.save();
731
+ context.font = font;
732
+ const textWidth = context.measureText(text).width;
733
+ context.restore();
734
+ textWidthCache[font][text] = textWidth;
735
+ }
736
+ return textWidthCache[font][text];
730
737
  }
738
+ const textWidthCache = {};
731
739
  function computeTextFont(style) {
732
740
  const italic = style.italic ? "italic " : "";
733
741
  const weight = style.bold ? "bold" : DEFAULT_FONT_WEIGHT;
@@ -1703,27 +1711,36 @@ function removeTrailingZeroes(numberString) {
1703
1711
  }
1704
1712
  return numberString.slice(0, i + 1) || undefined;
1705
1713
  }
1714
+ const leadingZeroesRegexp = /^0+/;
1706
1715
  /**
1707
1716
  * Limit the size of the decimal part of a number to the given number of digits.
1708
1717
  */
1709
1718
  function limitDecimalDigits(decimalDigits, maxDecimals) {
1719
+ var _a;
1710
1720
  let integerDigits = "0";
1711
1721
  let resultDecimalDigits = decimalDigits;
1712
1722
  // Note : we'd want to simply use number.toFixed() to handle the max digits & rounding,
1713
1723
  // but it has very strange behaviour. Ex: 12.345.toFixed(2) => "12.35", but 1.345.toFixed(2) => "1.34"
1714
1724
  let slicedDecimalDigits = decimalDigits.slice(0, maxDecimals);
1715
1725
  const i = maxDecimals;
1716
- if (Number(Number(decimalDigits[i]) < 5)) {
1726
+ if (Number(decimalDigits[i]) < 5) {
1717
1727
  return { integerDigits, decimalDigits: slicedDecimalDigits };
1718
1728
  }
1719
1729
  // round up
1730
+ const leadingZeroes = ((_a = slicedDecimalDigits.match(leadingZeroesRegexp)) === null || _a === void 0 ? void 0 : _a[0]) || "";
1720
1731
  const slicedRoundedUp = (Number(slicedDecimalDigits) + 1).toString();
1721
- if (slicedRoundedUp.length > slicedDecimalDigits.length) {
1722
- integerDigits = (Number(integerDigits) + 1).toString();
1732
+ const withoutLeadingZeroes = slicedDecimalDigits.slice(leadingZeroes.length);
1733
+ // e.g. carry over from 99 to 100
1734
+ const carryOver = slicedRoundedUp.length > withoutLeadingZeroes.length;
1735
+ if (carryOver && !leadingZeroes) {
1736
+ integerDigits = "1";
1723
1737
  resultDecimalDigits = undefined;
1724
1738
  }
1739
+ else if (carryOver) {
1740
+ resultDecimalDigits = leadingZeroes.slice(0, -1) + slicedRoundedUp;
1741
+ }
1725
1742
  else {
1726
- resultDecimalDigits = slicedRoundedUp;
1743
+ resultDecimalDigits = leadingZeroes + slicedRoundedUp;
1727
1744
  }
1728
1745
  return { integerDigits, decimalDigits: resultDecimalDigits };
1729
1746
  }
@@ -17341,6 +17358,7 @@ class Composer extends Component {
17341
17358
  (this.autoCompleteState.selectedIndex + 1) % this.autoCompleteState.values.length;
17342
17359
  }
17343
17360
  }
17361
+ this.updateCursorIfNeeded();
17344
17362
  }
17345
17363
  processTabKey(ev) {
17346
17364
  var _a;
@@ -17399,9 +17417,12 @@ class Composer extends Component {
17399
17417
  }
17400
17418
  else {
17401
17419
  ev.stopPropagation();
17420
+ this.updateCursorIfNeeded();
17402
17421
  }
17403
- const { start, end } = this.contentHelper.getCurrentSelection();
17422
+ }
17423
+ updateCursorIfNeeded() {
17404
17424
  if (!this.env.model.getters.isSelectingForComposer()) {
17425
+ const { start, end } = this.contentHelper.getCurrentSelection();
17405
17426
  this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", { start, end });
17406
17427
  this.isKeyStillDown = true;
17407
17428
  }
@@ -20032,6 +20053,7 @@ css /* scss */ `
20032
20053
  .o-color-picker-toggler {
20033
20054
  display: flex;
20034
20055
  .o-color-picker-toggler-sign {
20056
+ display: flex;
20035
20057
  margin: auto auto;
20036
20058
  width: 55%;
20037
20059
  height: 55%;
@@ -29542,7 +29564,14 @@ class FiltersPlugin extends CorePlugin {
29542
29564
  this.history.update("tables", filterTables);
29543
29565
  break;
29544
29566
  case "DUPLICATE_SHEET":
29545
- this.history.update("tables", cmd.sheetIdTo, deepCopy(this.tables[cmd.sheetId]));
29567
+ const tables = {};
29568
+ for (const filterTable of Object.values(this.tables[cmd.sheetId] || {})) {
29569
+ if (filterTable) {
29570
+ const newFilterTable = deepCopy(filterTable);
29571
+ tables[newFilterTable.id] = newFilterTable;
29572
+ }
29573
+ }
29574
+ this.history.update("tables", cmd.sheetIdTo, tables);
29546
29575
  break;
29547
29576
  case "ADD_COLUMNS_ROWS":
29548
29577
  this.onAddColumnsRows(cmd);
@@ -33086,6 +33115,7 @@ class FilterEvaluationPlugin extends UIPlugin {
33086
33115
  }
33087
33116
  exportForExcel(data) {
33088
33117
  for (const sheetData of data.sheets) {
33118
+ const sheetId = sheetData.id;
33089
33119
  for (const tableData of sheetData.filterTables) {
33090
33120
  const tableZone = toZone(tableData.range);
33091
33121
  const filters = [];
@@ -33101,20 +33131,20 @@ class FilterEvaluationPlugin extends UIPlugin {
33101
33131
  if (!filter)
33102
33132
  continue;
33103
33133
  const valuesInFilterZone = filter.filteredZone
33104
- ? positions(filter.filteredZone)
33105
- .map(({ col, row }) => this.getters.getEvaluatedCell({ sheetId: sheetData.id, col, row }))
33106
- .filter((cell) => cell.type !== CellValueType.empty)
33107
- .map((cell) => cell.formattedValue)
33134
+ ? positions(filter.filteredZone).map((position) => this.getters.getEvaluatedCell({ sheetId, ...position }).formattedValue)
33108
33135
  : [];
33109
- // In xlsx, filtered values = values that are displayed, not values that are hidden
33110
- const xlsxFilteredValues = valuesInFilterZone.filter((val) => !filteredValues.includes(val));
33111
- filters.push({ colId: i, filteredValues: [...new Set(xlsxFilteredValues)] });
33112
- // In xlsx, filter header should ALWAYS be a string and should be unique
33113
- const headerPosition = {
33114
- col: filter.col,
33115
- row: filter.zoneWithHeaders.top,
33116
- sheetId: sheetData.id,
33117
- };
33136
+ if (filteredValues.length) {
33137
+ const xlsxDisplayedValues = valuesInFilterZone
33138
+ .filter((val) => val)
33139
+ .filter((val) => !filteredValues.includes(val));
33140
+ filters.push({
33141
+ colId: i,
33142
+ displayedValues: [...new Set(xlsxDisplayedValues)],
33143
+ displayBlanks: !filteredValues.includes("") && valuesInFilterZone.some((val) => !val),
33144
+ });
33145
+ }
33146
+ // In xlsx, filter header should ALWAYS be a string and should be unique in the table
33147
+ const headerPosition = { col: filter.col, row: filter.zoneWithHeaders.top, sheetId };
33118
33148
  const headerString = this.getters.getEvaluatedCell(headerPosition).formattedValue;
33119
33149
  const headerName = this.getUniqueColNameForExcel(i, headerString, headerNames);
33120
33150
  headerNames.push(headerName);
@@ -36143,15 +36173,15 @@ SelectionInputPlugin.getters = [];
36143
36173
  * This plugin handles this internal state.
36144
36174
  */
36145
36175
  class SelectionInputsManagerPlugin extends UIPlugin {
36176
+ get currentInput() {
36177
+ return this.focusedInputId ? this.inputs[this.focusedInputId] : null;
36178
+ }
36146
36179
  constructor(config) {
36147
36180
  super(config);
36148
36181
  this.config = config;
36149
36182
  this.inputs = {};
36150
36183
  this.focusedInputId = null;
36151
36184
  }
36152
- get currentInput() {
36153
- return this.focusedInputId ? this.inputs[this.focusedInputId] : null;
36154
- }
36155
36185
  // ---------------------------------------------------------------------------
36156
36186
  // Command Handling
36157
36187
  // ---------------------------------------------------------------------------
@@ -43282,15 +43312,10 @@ function addAutoFilter(table) {
43282
43312
  `;
43283
43313
  }
43284
43314
  function addFilterColumns(table) {
43285
- const tableZone = toZone(table.range);
43286
43315
  const columns = [];
43287
- for (const i of range(0, zoneToDimension(tableZone).width)) {
43288
- const filter = table.filters[i];
43289
- if (!filter || !filter.filteredValues.length) {
43290
- continue;
43291
- }
43316
+ for (const filter of table.filters) {
43292
43317
  const colXml = escapeXml /*xml*/ `
43293
- <filterColumn ${formatAttributes([["colId", i]])}>
43318
+ <filterColumn ${formatAttributes([["colId", filter.colId]])}>
43294
43319
  ${addFilter(filter)}
43295
43320
  </filterColumn>
43296
43321
  `;
@@ -43299,9 +43324,10 @@ function addFilterColumns(table) {
43299
43324
  return columns;
43300
43325
  }
43301
43326
  function addFilter(filter) {
43302
- const filterValues = filter.filteredValues.map((val) => escapeXml /*xml*/ `<filter ${formatAttributes([["val", val]])}/>`);
43327
+ const filterValues = filter.displayedValues.map((val) => escapeXml /*xml*/ `<filter ${formatAttributes([["val", val]])}/>`);
43328
+ const filterAttributes = filter.displayBlanks ? [["blank", 1]] : [];
43303
43329
  return escapeXml /*xml*/ `
43304
- <filters>
43330
+ <filters ${formatAttributes(filterAttributes)}>
43305
43331
  ${joinXmlNodes(filterValues)}
43306
43332
  </filters>
43307
43333
  `;
@@ -44226,6 +44252,6 @@ function addFunction(functionName, functionDescription) {
44226
44252
  export { AbstractChart, CommandResult, CorePlugin, DATETIME_FORMAT, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, links, load, parse, readonlyAllowedCommands, registries, setTranslationMethod, tokenize };
44227
44253
 
44228
44254
 
44229
- __info__.version = '16.1.13';
44230
- __info__.date = '2023-06-02T10:12:21.173Z';
44231
- __info__.hash = '5386a5b';
44255
+ __info__.version = '16.1.15';
44256
+ __info__.date = '2023-06-26T14:33:07.859Z';
44257
+ __info__.hash = '2b264ad';
@@ -723,12 +723,20 @@
723
723
  return computeTextLinesHeight(fontSize) + 2 * PADDING_AUTORESIZE_VERTICAL;
724
724
  }
725
725
  function computeTextWidth(context, text, style) {
726
- context.save();
727
- context.font = computeTextFont(style);
728
- const textWidth = context.measureText(text).width;
729
- context.restore();
730
- return textWidth;
726
+ const font = computeTextFont(style);
727
+ if (!textWidthCache[font]) {
728
+ textWidthCache[font] = {};
729
+ }
730
+ if (textWidthCache[font][text] === undefined) {
731
+ context.save();
732
+ context.font = font;
733
+ const textWidth = context.measureText(text).width;
734
+ context.restore();
735
+ textWidthCache[font][text] = textWidth;
736
+ }
737
+ return textWidthCache[font][text];
731
738
  }
739
+ const textWidthCache = {};
732
740
  function computeTextFont(style) {
733
741
  const italic = style.italic ? "italic " : "";
734
742
  const weight = style.bold ? "bold" : DEFAULT_FONT_WEIGHT;
@@ -1704,27 +1712,36 @@
1704
1712
  }
1705
1713
  return numberString.slice(0, i + 1) || undefined;
1706
1714
  }
1715
+ const leadingZeroesRegexp = /^0+/;
1707
1716
  /**
1708
1717
  * Limit the size of the decimal part of a number to the given number of digits.
1709
1718
  */
1710
1719
  function limitDecimalDigits(decimalDigits, maxDecimals) {
1720
+ var _a;
1711
1721
  let integerDigits = "0";
1712
1722
  let resultDecimalDigits = decimalDigits;
1713
1723
  // Note : we'd want to simply use number.toFixed() to handle the max digits & rounding,
1714
1724
  // but it has very strange behaviour. Ex: 12.345.toFixed(2) => "12.35", but 1.345.toFixed(2) => "1.34"
1715
1725
  let slicedDecimalDigits = decimalDigits.slice(0, maxDecimals);
1716
1726
  const i = maxDecimals;
1717
- if (Number(Number(decimalDigits[i]) < 5)) {
1727
+ if (Number(decimalDigits[i]) < 5) {
1718
1728
  return { integerDigits, decimalDigits: slicedDecimalDigits };
1719
1729
  }
1720
1730
  // round up
1731
+ const leadingZeroes = ((_a = slicedDecimalDigits.match(leadingZeroesRegexp)) === null || _a === void 0 ? void 0 : _a[0]) || "";
1721
1732
  const slicedRoundedUp = (Number(slicedDecimalDigits) + 1).toString();
1722
- if (slicedRoundedUp.length > slicedDecimalDigits.length) {
1723
- integerDigits = (Number(integerDigits) + 1).toString();
1733
+ const withoutLeadingZeroes = slicedDecimalDigits.slice(leadingZeroes.length);
1734
+ // e.g. carry over from 99 to 100
1735
+ const carryOver = slicedRoundedUp.length > withoutLeadingZeroes.length;
1736
+ if (carryOver && !leadingZeroes) {
1737
+ integerDigits = "1";
1724
1738
  resultDecimalDigits = undefined;
1725
1739
  }
1740
+ else if (carryOver) {
1741
+ resultDecimalDigits = leadingZeroes.slice(0, -1) + slicedRoundedUp;
1742
+ }
1726
1743
  else {
1727
- resultDecimalDigits = slicedRoundedUp;
1744
+ resultDecimalDigits = leadingZeroes + slicedRoundedUp;
1728
1745
  }
1729
1746
  return { integerDigits, decimalDigits: resultDecimalDigits };
1730
1747
  }
@@ -17342,6 +17359,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
17342
17359
  (this.autoCompleteState.selectedIndex + 1) % this.autoCompleteState.values.length;
17343
17360
  }
17344
17361
  }
17362
+ this.updateCursorIfNeeded();
17345
17363
  }
17346
17364
  processTabKey(ev) {
17347
17365
  var _a;
@@ -17400,9 +17418,12 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
17400
17418
  }
17401
17419
  else {
17402
17420
  ev.stopPropagation();
17421
+ this.updateCursorIfNeeded();
17403
17422
  }
17404
- const { start, end } = this.contentHelper.getCurrentSelection();
17423
+ }
17424
+ updateCursorIfNeeded() {
17405
17425
  if (!this.env.model.getters.isSelectingForComposer()) {
17426
+ const { start, end } = this.contentHelper.getCurrentSelection();
17406
17427
  this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", { start, end });
17407
17428
  this.isKeyStillDown = true;
17408
17429
  }
@@ -20033,6 +20054,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
20033
20054
  .o-color-picker-toggler {
20034
20055
  display: flex;
20035
20056
  .o-color-picker-toggler-sign {
20057
+ display: flex;
20036
20058
  margin: auto auto;
20037
20059
  width: 55%;
20038
20060
  height: 55%;
@@ -29543,7 +29565,14 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
29543
29565
  this.history.update("tables", filterTables);
29544
29566
  break;
29545
29567
  case "DUPLICATE_SHEET":
29546
- this.history.update("tables", cmd.sheetIdTo, deepCopy(this.tables[cmd.sheetId]));
29568
+ const tables = {};
29569
+ for (const filterTable of Object.values(this.tables[cmd.sheetId] || {})) {
29570
+ if (filterTable) {
29571
+ const newFilterTable = deepCopy(filterTable);
29572
+ tables[newFilterTable.id] = newFilterTable;
29573
+ }
29574
+ }
29575
+ this.history.update("tables", cmd.sheetIdTo, tables);
29547
29576
  break;
29548
29577
  case "ADD_COLUMNS_ROWS":
29549
29578
  this.onAddColumnsRows(cmd);
@@ -33087,6 +33116,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
33087
33116
  }
33088
33117
  exportForExcel(data) {
33089
33118
  for (const sheetData of data.sheets) {
33119
+ const sheetId = sheetData.id;
33090
33120
  for (const tableData of sheetData.filterTables) {
33091
33121
  const tableZone = toZone(tableData.range);
33092
33122
  const filters = [];
@@ -33102,20 +33132,20 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
33102
33132
  if (!filter)
33103
33133
  continue;
33104
33134
  const valuesInFilterZone = filter.filteredZone
33105
- ? positions(filter.filteredZone)
33106
- .map(({ col, row }) => this.getters.getEvaluatedCell({ sheetId: sheetData.id, col, row }))
33107
- .filter((cell) => cell.type !== CellValueType.empty)
33108
- .map((cell) => cell.formattedValue)
33135
+ ? positions(filter.filteredZone).map((position) => this.getters.getEvaluatedCell({ sheetId, ...position }).formattedValue)
33109
33136
  : [];
33110
- // In xlsx, filtered values = values that are displayed, not values that are hidden
33111
- const xlsxFilteredValues = valuesInFilterZone.filter((val) => !filteredValues.includes(val));
33112
- filters.push({ colId: i, filteredValues: [...new Set(xlsxFilteredValues)] });
33113
- // In xlsx, filter header should ALWAYS be a string and should be unique
33114
- const headerPosition = {
33115
- col: filter.col,
33116
- row: filter.zoneWithHeaders.top,
33117
- sheetId: sheetData.id,
33118
- };
33137
+ if (filteredValues.length) {
33138
+ const xlsxDisplayedValues = valuesInFilterZone
33139
+ .filter((val) => val)
33140
+ .filter((val) => !filteredValues.includes(val));
33141
+ filters.push({
33142
+ colId: i,
33143
+ displayedValues: [...new Set(xlsxDisplayedValues)],
33144
+ displayBlanks: !filteredValues.includes("") && valuesInFilterZone.some((val) => !val),
33145
+ });
33146
+ }
33147
+ // In xlsx, filter header should ALWAYS be a string and should be unique in the table
33148
+ const headerPosition = { col: filter.col, row: filter.zoneWithHeaders.top, sheetId };
33119
33149
  const headerString = this.getters.getEvaluatedCell(headerPosition).formattedValue;
33120
33150
  const headerName = this.getUniqueColNameForExcel(i, headerString, headerNames);
33121
33151
  headerNames.push(headerName);
@@ -36144,15 +36174,15 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
36144
36174
  * This plugin handles this internal state.
36145
36175
  */
36146
36176
  class SelectionInputsManagerPlugin extends UIPlugin {
36177
+ get currentInput() {
36178
+ return this.focusedInputId ? this.inputs[this.focusedInputId] : null;
36179
+ }
36147
36180
  constructor(config) {
36148
36181
  super(config);
36149
36182
  this.config = config;
36150
36183
  this.inputs = {};
36151
36184
  this.focusedInputId = null;
36152
36185
  }
36153
- get currentInput() {
36154
- return this.focusedInputId ? this.inputs[this.focusedInputId] : null;
36155
- }
36156
36186
  // ---------------------------------------------------------------------------
36157
36187
  // Command Handling
36158
36188
  // ---------------------------------------------------------------------------
@@ -43283,15 +43313,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
43283
43313
  `;
43284
43314
  }
43285
43315
  function addFilterColumns(table) {
43286
- const tableZone = toZone(table.range);
43287
43316
  const columns = [];
43288
- for (const i of range(0, zoneToDimension(tableZone).width)) {
43289
- const filter = table.filters[i];
43290
- if (!filter || !filter.filteredValues.length) {
43291
- continue;
43292
- }
43317
+ for (const filter of table.filters) {
43293
43318
  const colXml = escapeXml /*xml*/ `
43294
- <filterColumn ${formatAttributes([["colId", i]])}>
43319
+ <filterColumn ${formatAttributes([["colId", filter.colId]])}>
43295
43320
  ${addFilter(filter)}
43296
43321
  </filterColumn>
43297
43322
  `;
@@ -43300,9 +43325,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
43300
43325
  return columns;
43301
43326
  }
43302
43327
  function addFilter(filter) {
43303
- const filterValues = filter.filteredValues.map((val) => escapeXml /*xml*/ `<filter ${formatAttributes([["val", val]])}/>`);
43328
+ const filterValues = filter.displayedValues.map((val) => escapeXml /*xml*/ `<filter ${formatAttributes([["val", val]])}/>`);
43329
+ const filterAttributes = filter.displayBlanks ? [["blank", 1]] : [];
43304
43330
  return escapeXml /*xml*/ `
43305
- <filters>
43331
+ <filters ${formatAttributes(filterAttributes)}>
43306
43332
  ${joinXmlNodes(filterValues)}
43307
43333
  </filters>
43308
43334
  `;
@@ -44257,9 +44283,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
44257
44283
  Object.defineProperty(exports, '__esModule', { value: true });
44258
44284
 
44259
44285
 
44260
- __info__.version = '16.1.13';
44261
- __info__.date = '2023-06-02T10:12:21.173Z';
44262
- __info__.hash = '5386a5b';
44286
+ __info__.version = '16.1.15';
44287
+ __info__.date = '2023-06-26T14:33:07.859Z';
44288
+ __info__.hash = '2b264ad';
44263
44289
 
44264
44290
 
44265
44291
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);