@odoo/o-spreadsheet 17.4.14 → 17.4.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.
@@ -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.14
6
- * @date 2024-11-28T09:08:12.462Z
7
- * @hash 81bf386
5
+ * @version 17.4.16
6
+ * @date 2024-12-19T07:50:04.021Z
7
+ * @hash 6b827fc
8
8
  */
9
9
 
10
10
  'use strict';
@@ -306,8 +306,8 @@ const LINE_FILL_TRANSPARENCY = 0.4;
306
306
  const DEBOUNCE_TIME = 200;
307
307
  const MESSAGE_VERSION = 1;
308
308
  // Sheets
309
- const FORBIDDEN_SHEET_CHARS = ["'", "*", "?", "/", "\\", "[", "]"];
310
- const FORBIDDEN_IN_EXCEL_REGEX = /'|\*|\?|\/|\\|\[|\]/;
309
+ const FORBIDDEN_SHEETNAME_CHARS = ["'", "*", "?", "/", "\\", "[", "]"];
310
+ const FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX = /'|\*|\?|\/|\\|\[|\]/;
311
311
  // Cells
312
312
  const FORMULA_REF_IDENTIFIER = "|";
313
313
  // Components
@@ -353,6 +353,7 @@ const PIVOT_TABLE_CONFIG = {
353
353
  //------------------------------------------------------------------------------
354
354
  // Miscellaneous
355
355
  //------------------------------------------------------------------------------
356
+ const sanitizeSheetNameRegex = new RegExp(FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX, "g");
356
357
  /**
357
358
  * Remove quotes from a quoted string
358
359
  * ```js
@@ -448,6 +449,10 @@ function getCanonicalSheetName(sheetName) {
448
449
  }
449
450
  return sheetName;
450
451
  }
452
+ /** Replace the excel-excluded characters of a sheetName */
453
+ function sanitizeSheetName(sheetName, replacementChar = " ") {
454
+ return sheetName.replace(sanitizeSheetNameRegex, replacementChar);
455
+ }
451
456
  function clip(val, min, max) {
452
457
  return val < min ? min : val > max ? max : val;
453
458
  }
@@ -763,6 +768,7 @@ function removeFalsyAttributes(obj) {
763
768
  * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes
764
769
  */
765
770
  const whiteSpaceSpecialCharacters = [
771
+ " ",
766
772
  "\t",
767
773
  "\f",
768
774
  "\v",
@@ -777,17 +783,15 @@ const whiteSpaceSpecialCharacters = [
777
783
  String.fromCharCode(parseInt("3000", 16)),
778
784
  String.fromCharCode(parseInt("feff", 16)),
779
785
  ];
780
- const whiteSpaceRegexp = new RegExp(whiteSpaceSpecialCharacters.join("|") + "|(\r\n|\r|\n)", "g");
786
+ const whiteSpaceRegexp = new RegExp(whiteSpaceSpecialCharacters.join("|"), "g");
787
+ const newLineRegexp = /(\r\n|\r)/g;
781
788
  /**
782
- * Replace all the special spaces in a string (non-breaking, tabs, ...) by normal spaces, and all the
783
- * different newlines types by \n.
789
+ * Replace all different newlines characters by \n
784
790
  */
785
- function replaceSpecialSpaces(text) {
791
+ function replaceNewLines(text) {
786
792
  if (!text)
787
793
  return "";
788
- if (!whiteSpaceRegexp.test(text))
789
- return text;
790
- return text.replace(whiteSpaceRegexp, (match, newLine) => (newLine ? NEWLINE : " "));
794
+ return text.replace(newLineRegexp, NEWLINE);
791
795
  }
792
796
  /**
793
797
  * Determine if the numbers are consecutive.
@@ -5679,7 +5683,7 @@ class BorderClipboardHandler extends AbstractCellClipboardHandler {
5679
5683
  const POSTFIX_UNARY_OPERATORS = ["%"];
5680
5684
  const OPERATORS = "+,-,*,/,:,=,<>,>=,>,<=,<,^,&".split(",").concat(POSTFIX_UNARY_OPERATORS);
5681
5685
  function tokenize(str, locale = DEFAULT_LOCALE) {
5682
- str = replaceSpecialSpaces(str);
5686
+ str = replaceNewLines(str);
5683
5687
  const chars = new TokenizingChars(str);
5684
5688
  const result = [];
5685
5689
  while (!chars.isOver()) {
@@ -5826,12 +5830,12 @@ function tokenizeSpace(chars) {
5826
5830
  if (length) {
5827
5831
  return { type: "SPACE", value: NEWLINE.repeat(length) };
5828
5832
  }
5829
- while (chars.current === " ") {
5830
- length++;
5831
- chars.shift();
5833
+ let spaces = "";
5834
+ while (chars.current && chars.current.match(whiteSpaceRegexp)) {
5835
+ spaces += chars.shift();
5832
5836
  }
5833
- if (length) {
5834
- return { type: "SPACE", value: " ".repeat(length) };
5837
+ if (spaces) {
5838
+ return { type: "SPACE", value: spaces };
5835
5839
  }
5836
5840
  return null;
5837
5841
  }
@@ -38561,6 +38565,7 @@ css /* scss */ `
38561
38565
  }
38562
38566
  }
38563
38567
  `;
38568
+ const DEFAULT_TABLE_STYLE_COLOR = "#3C78D8";
38564
38569
  class TableStyleEditorPanel extends owl.Component {
38565
38570
  static template = "o-spreadsheet-TableStyleEditorPanel";
38566
38571
  static components = { Section, RoundColorPicker, TableStylePreview };
@@ -38579,7 +38584,7 @@ class TableStyleEditorPanel extends owl.Component {
38579
38584
  : null;
38580
38585
  return {
38581
38586
  pickerOpened: false,
38582
- primaryColor: editedStyle?.primaryColor || "#3C78D8",
38587
+ primaryColor: editedStyle?.primaryColor || DEFAULT_TABLE_STYLE_COLOR,
38583
38588
  selectedTemplateName: editedStyle?.templateName || "lightColoredText",
38584
38589
  styleName: editedStyle?.displayName || this.env.model.getters.getNewCustomTableStyleName(),
38585
38590
  };
@@ -38588,7 +38593,7 @@ class TableStyleEditorPanel extends owl.Component {
38588
38593
  this.state.pickerOpened = !this.state.pickerOpened;
38589
38594
  }
38590
38595
  onColorPicked(color) {
38591
- this.state.primaryColor = color;
38596
+ this.state.primaryColor = isColorValid(color) ? color : DEFAULT_TABLE_STYLE_COLOR;
38592
38597
  this.state.pickerOpened = false;
38593
38598
  }
38594
38599
  onTemplatePicked(templateName) {
@@ -39935,6 +39940,7 @@ class FiguresContainer extends owl.Component {
39935
39940
  draggedFigure: undefined,
39936
39941
  horizontalSnap: undefined,
39937
39942
  verticalSnap: undefined,
39943
+ cancelDnd: undefined,
39938
39944
  });
39939
39945
  setup() {
39940
39946
  owl.onMounted(() => {
@@ -39947,12 +39953,28 @@ class FiguresContainer extends owl.Component {
39947
39953
  // new rendering
39948
39954
  this.render();
39949
39955
  });
39956
+ owl.onWillUpdateProps(() => {
39957
+ const sheetId = this.env.model.getters.getActiveSheetId();
39958
+ const draggedFigureId = this.dnd.draggedFigure?.id;
39959
+ if (draggedFigureId && !this.env.model.getters.getFigure(sheetId, draggedFigureId)) {
39960
+ if (this.dnd.cancelDnd) {
39961
+ this.dnd.cancelDnd();
39962
+ }
39963
+ this.dnd.draggedFigure = undefined;
39964
+ this.dnd.horizontalSnap = undefined;
39965
+ this.dnd.verticalSnap = undefined;
39966
+ this.dnd.cancelDnd = undefined;
39967
+ }
39968
+ });
39950
39969
  }
39951
39970
  getVisibleFigures() {
39952
39971
  const visibleFigures = this.env.model.getters.getVisibleFigures();
39953
39972
  if (this.dnd.draggedFigure &&
39954
39973
  !visibleFigures.some((figure) => figure.id === this.dnd.draggedFigure?.id)) {
39955
- visibleFigures.push(this.env.model.getters.getFigure(this.env.model.getters.getActiveSheetId(), this.dnd.draggedFigure?.id));
39974
+ const draggedFigure = this.env.model.getters.getFigure(this.env.model.getters.getActiveSheetId(), this.dnd.draggedFigure?.id);
39975
+ if (draggedFigure) {
39976
+ visibleFigures.push(draggedFigure);
39977
+ }
39956
39978
  }
39957
39979
  return visibleFigures;
39958
39980
  }
@@ -40071,7 +40093,7 @@ class FiguresContainer extends owl.Component {
40071
40093
  this.dnd.verticalSnap = undefined;
40072
40094
  this.env.model.dispatch("UPDATE_FIGURE", { sheetId, id: figure.id, x, y });
40073
40095
  };
40074
- startDnd(onMouseMove, onMouseUp);
40096
+ this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
40075
40097
  }
40076
40098
  /**
40077
40099
  * Initialize the resize of a figure with mouse movements
@@ -40119,7 +40141,7 @@ class FiguresContainer extends owl.Component {
40119
40141
  this.dnd.horizontalSnap = undefined;
40120
40142
  this.dnd.verticalSnap = undefined;
40121
40143
  };
40122
- startDnd(onMouseMove, onMouseUp);
40144
+ this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
40123
40145
  }
40124
40146
  getOtherFigures(figId) {
40125
40147
  return this.getVisibleFigures().filter((f) => f.id !== figId);
@@ -46727,13 +46749,12 @@ const MIGRATIONS = [
46727
46749
  to: 8,
46728
46750
  applyMigration(data) {
46729
46751
  const namesTaken = [];
46730
- const globalForbiddenInExcel = new RegExp(FORBIDDEN_IN_EXCEL_REGEX, "g");
46731
46752
  for (let sheet of data.sheets || []) {
46732
46753
  if (!sheet.name) {
46733
46754
  continue;
46734
46755
  }
46735
46756
  const oldName = sheet.name;
46736
- const escapedName = oldName.replace(globalForbiddenInExcel, "_");
46757
+ const escapedName = sanitizeSheetName(oldName, "_");
46737
46758
  let i = 1;
46738
46759
  let newName = escapedName;
46739
46760
  while (namesTaken.includes(newName)) {
@@ -48232,7 +48253,7 @@ class CellPlugin extends CorePlugin {
48232
48253
  const before = this.getters.getCell({ sheetId, col, row });
48233
48254
  const hasContent = "content" in after || "formula" in after;
48234
48255
  // Compute the new cell properties
48235
- const afterContent = hasContent ? replaceSpecialSpaces(after?.content) : before?.content || "";
48256
+ const afterContent = hasContent ? replaceNewLines(after?.content) : before?.content || "";
48236
48257
  let style;
48237
48258
  if (after.style !== undefined) {
48238
48259
  style = after.style || undefined;
@@ -51093,6 +51114,9 @@ class SheetPlugin extends CorePlugin {
51093
51114
  };
51094
51115
  }
51095
51116
  getUnboundedZone(sheetId, zone) {
51117
+ if (zone.bottom === undefined || zone.right === undefined) {
51118
+ return zone;
51119
+ }
51096
51120
  const isFullRow = zone.left === 0 && zone.right === this.getNumberCols(sheetId) - 1;
51097
51121
  const isFullCol = zone.top === 0 && zone.bottom === this.getNumberRows(sheetId) - 1;
51098
51122
  return {
@@ -51258,7 +51282,7 @@ class SheetPlugin extends CorePlugin {
51258
51282
  if (orderedSheetIds.find((id) => sheets[id]?.name.toLowerCase() === name && id !== cmd.sheetId)) {
51259
51283
  return "DuplicatedSheetName" /* CommandResult.DuplicatedSheetName */;
51260
51284
  }
51261
- if (FORBIDDEN_IN_EXCEL_REGEX.test(name)) {
51285
+ if (FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX.test(name)) {
51262
51286
  return "ForbiddenCharactersInSheetName" /* CommandResult.ForbiddenCharactersInSheetName */;
51263
51287
  }
51264
51288
  return "Success" /* CommandResult.Success */;
@@ -56047,11 +56071,13 @@ class PivotUIPlugin extends UIPlugin {
56047
56071
  return EMPTY_PIVOT_CELL;
56048
56072
  }
56049
56073
  if (functionName === "PIVOT") {
56050
- const includeTotal = args[2] === false ? false : undefined;
56051
- const includeColumnHeaders = args[3] === false ? false : undefined;
56074
+ const includeTotal = toScalar(args[2]);
56075
+ const shouldIncludeTotal = includeTotal === undefined ? true : toBoolean(includeTotal);
56076
+ const includeColumnHeaders = toScalar(args[3]);
56077
+ const shouldIncludeColumnHeaders = includeColumnHeaders === undefined ? true : toBoolean(includeColumnHeaders);
56052
56078
  const pivotCells = pivot
56053
56079
  .getTableStructure()
56054
- .getPivotCells(includeTotal, includeColumnHeaders);
56080
+ .getPivotCells(shouldIncludeTotal, shouldIncludeColumnHeaders);
56055
56081
  const pivotCol = position.col - mainPosition.col;
56056
56082
  const pivotRow = position.row - mainPosition.row;
56057
56083
  return pivotCells[pivotCol][pivotRow];
@@ -58156,7 +58182,7 @@ class InsertPivotPlugin extends UIPlugin {
58156
58182
  getPivotDuplicateSheetName(pivotName) {
58157
58183
  let i = 1;
58158
58184
  const names = this.getters.getSheetIds().map((id) => this.getters.getSheetName(id));
58159
- const sanitizedName = pivotName.replace(new RegExp(FORBIDDEN_IN_EXCEL_REGEX, "g"), " ");
58185
+ const sanitizedName = sanitizeSheetName(pivotName);
58160
58186
  let name = sanitizedName;
58161
58187
  while (names.includes(name)) {
58162
58188
  name = `${sanitizedName} (${i})`;
@@ -61300,6 +61326,7 @@ class SheetViewPlugin extends UIPlugin {
61300
61326
  break;
61301
61327
  case "DELETE_SHEET":
61302
61328
  this.cleanViewports();
61329
+ this.sheetsWithDirtyViewports.delete(cmd.sheetId);
61303
61330
  break;
61304
61331
  case "ACTIVATE_SHEET":
61305
61332
  this.sheetsWithDirtyViewports.add(cmd.sheetIdTo);
@@ -62197,7 +62224,7 @@ function interactiveRenameSheet(env, sheetId, name, errorCallback) {
62197
62224
  env.raiseError(_t("A sheet with the name %s already exists. Please select another name.", name), errorCallback);
62198
62225
  }
62199
62226
  else if (result.reasons.includes("ForbiddenCharactersInSheetName" /* CommandResult.ForbiddenCharactersInSheetName */)) {
62200
- env.raiseError(_t("Some used characters are not allowed in a sheet name (Forbidden characters are %s).", FORBIDDEN_SHEET_CHARS.join(" ")), errorCallback);
62227
+ env.raiseError(_t("Some used characters are not allowed in a sheet name (Forbidden characters are %s).", FORBIDDEN_SHEETNAME_CHARS.join(" ")), errorCallback);
62201
62228
  }
62202
62229
  }
62203
62230
 
@@ -63456,7 +63483,7 @@ class ActionButton extends owl.Component {
63456
63483
  setup() {
63457
63484
  owl.onWillUpdateProps((nextProps) => {
63458
63485
  if (nextProps.action !== this.props.action) {
63459
- this.actionButton = createAction(this.props.action);
63486
+ this.actionButton = createAction(nextProps.action);
63460
63487
  }
63461
63488
  });
63462
63489
  }
@@ -63723,7 +63750,6 @@ css /* scss */ `
63723
63750
  height: fit-content;
63724
63751
  margin-top: -1px;
63725
63752
  border: 1px solid;
63726
- z-index: ${ComponentsImportance.TopBarComposer};
63727
63753
 
63728
63754
  .o-composer:empty:not(:focus):not(.active)::before {
63729
63755
  content: url("data:image/svg+xml,${encodeURIComponent(FX_SVG)}");
@@ -63765,6 +63791,7 @@ class TopBarComposer extends owl.Component {
63765
63791
  }
63766
63792
  return cssPropertiesToCss({
63767
63793
  "border-color": SELECTION_BORDER_COLOR,
63794
+ "z-index": String(ComponentsImportance.TopBarComposer),
63768
63795
  });
63769
63796
  }
63770
63797
  get delimitation() {
@@ -68589,6 +68616,7 @@ const helpers = {
68589
68616
  createPivotFormula,
68590
68617
  areDomainArgsFieldsValid,
68591
68618
  formatTickValue,
68619
+ sanitizeSheetName,
68592
68620
  };
68593
68621
  const links = {
68594
68622
  isMarkdownLink,
@@ -68719,6 +68747,6 @@ exports.tokenColors = tokenColors;
68719
68747
  exports.tokenize = tokenize;
68720
68748
 
68721
68749
 
68722
- __info__.version = "17.4.14";
68723
- __info__.date = "2024-11-28T09:08:12.462Z";
68724
- __info__.hash = "81bf386";
68750
+ __info__.version = "17.4.16";
68751
+ __info__.date = "2024-12-19T07:50:04.021Z";
68752
+ __info__.hash = "6b827fc";
@@ -5548,6 +5548,8 @@ declare function createCurrencyFormat(currency: Partial<Currency>): Format;
5548
5548
  */
5549
5549
  declare function deepCopy<T>(obj: T): T;
5550
5550
  declare function unquote(string: string, quoteChar?: "'" | '"'): string;
5551
+ /** Replace the excel-excluded characters of a sheetName */
5552
+ declare function sanitizeSheetName(sheetName: string, replacementChar?: string): string;
5551
5553
  declare function isMarkdownLink(str: string): boolean;
5552
5554
  /**
5553
5555
  * Build a markdown link from a label and an url
@@ -8283,6 +8285,7 @@ interface DndState {
8283
8285
  draggedFigure?: Figure;
8284
8286
  horizontalSnap?: Snap<HFigureAxisType>;
8285
8287
  verticalSnap?: Snap<VFigureAxisType>;
8288
+ cancelDnd: (() => void) | undefined;
8286
8289
  }
8287
8290
  /**
8288
8291
  * Each figure ⭐ is positioned inside a container `div` placed and sized
@@ -11531,6 +11534,7 @@ declare const helpers: {
11531
11534
  createPivotFormula: typeof createPivotFormula;
11532
11535
  areDomainArgsFieldsValid: typeof areDomainArgsFieldsValid;
11533
11536
  formatTickValue: typeof formatTickValue;
11537
+ sanitizeSheetName: typeof sanitizeSheetName;
11534
11538
  };
11535
11539
  declare const links: {
11536
11540
  isMarkdownLink: typeof isMarkdownLink;
@@ -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.14
6
- * @date 2024-11-28T09:08:12.462Z
7
- * @hash 81bf386
5
+ * @version 17.4.16
6
+ * @date 2024-12-19T07:50:04.021Z
7
+ * @hash 6b827fc
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -304,8 +304,8 @@ const LINE_FILL_TRANSPARENCY = 0.4;
304
304
  const DEBOUNCE_TIME = 200;
305
305
  const MESSAGE_VERSION = 1;
306
306
  // Sheets
307
- const FORBIDDEN_SHEET_CHARS = ["'", "*", "?", "/", "\\", "[", "]"];
308
- const FORBIDDEN_IN_EXCEL_REGEX = /'|\*|\?|\/|\\|\[|\]/;
307
+ const FORBIDDEN_SHEETNAME_CHARS = ["'", "*", "?", "/", "\\", "[", "]"];
308
+ const FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX = /'|\*|\?|\/|\\|\[|\]/;
309
309
  // Cells
310
310
  const FORMULA_REF_IDENTIFIER = "|";
311
311
  // Components
@@ -351,6 +351,7 @@ const PIVOT_TABLE_CONFIG = {
351
351
  //------------------------------------------------------------------------------
352
352
  // Miscellaneous
353
353
  //------------------------------------------------------------------------------
354
+ const sanitizeSheetNameRegex = new RegExp(FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX, "g");
354
355
  /**
355
356
  * Remove quotes from a quoted string
356
357
  * ```js
@@ -446,6 +447,10 @@ function getCanonicalSheetName(sheetName) {
446
447
  }
447
448
  return sheetName;
448
449
  }
450
+ /** Replace the excel-excluded characters of a sheetName */
451
+ function sanitizeSheetName(sheetName, replacementChar = " ") {
452
+ return sheetName.replace(sanitizeSheetNameRegex, replacementChar);
453
+ }
449
454
  function clip(val, min, max) {
450
455
  return val < min ? min : val > max ? max : val;
451
456
  }
@@ -761,6 +766,7 @@ function removeFalsyAttributes(obj) {
761
766
  * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes
762
767
  */
763
768
  const whiteSpaceSpecialCharacters = [
769
+ " ",
764
770
  "\t",
765
771
  "\f",
766
772
  "\v",
@@ -775,17 +781,15 @@ const whiteSpaceSpecialCharacters = [
775
781
  String.fromCharCode(parseInt("3000", 16)),
776
782
  String.fromCharCode(parseInt("feff", 16)),
777
783
  ];
778
- const whiteSpaceRegexp = new RegExp(whiteSpaceSpecialCharacters.join("|") + "|(\r\n|\r|\n)", "g");
784
+ const whiteSpaceRegexp = new RegExp(whiteSpaceSpecialCharacters.join("|"), "g");
785
+ const newLineRegexp = /(\r\n|\r)/g;
779
786
  /**
780
- * Replace all the special spaces in a string (non-breaking, tabs, ...) by normal spaces, and all the
781
- * different newlines types by \n.
787
+ * Replace all different newlines characters by \n
782
788
  */
783
- function replaceSpecialSpaces(text) {
789
+ function replaceNewLines(text) {
784
790
  if (!text)
785
791
  return "";
786
- if (!whiteSpaceRegexp.test(text))
787
- return text;
788
- return text.replace(whiteSpaceRegexp, (match, newLine) => (newLine ? NEWLINE : " "));
792
+ return text.replace(newLineRegexp, NEWLINE);
789
793
  }
790
794
  /**
791
795
  * Determine if the numbers are consecutive.
@@ -5677,7 +5681,7 @@ class BorderClipboardHandler extends AbstractCellClipboardHandler {
5677
5681
  const POSTFIX_UNARY_OPERATORS = ["%"];
5678
5682
  const OPERATORS = "+,-,*,/,:,=,<>,>=,>,<=,<,^,&".split(",").concat(POSTFIX_UNARY_OPERATORS);
5679
5683
  function tokenize(str, locale = DEFAULT_LOCALE) {
5680
- str = replaceSpecialSpaces(str);
5684
+ str = replaceNewLines(str);
5681
5685
  const chars = new TokenizingChars(str);
5682
5686
  const result = [];
5683
5687
  while (!chars.isOver()) {
@@ -5824,12 +5828,12 @@ function tokenizeSpace(chars) {
5824
5828
  if (length) {
5825
5829
  return { type: "SPACE", value: NEWLINE.repeat(length) };
5826
5830
  }
5827
- while (chars.current === " ") {
5828
- length++;
5829
- chars.shift();
5831
+ let spaces = "";
5832
+ while (chars.current && chars.current.match(whiteSpaceRegexp)) {
5833
+ spaces += chars.shift();
5830
5834
  }
5831
- if (length) {
5832
- return { type: "SPACE", value: " ".repeat(length) };
5835
+ if (spaces) {
5836
+ return { type: "SPACE", value: spaces };
5833
5837
  }
5834
5838
  return null;
5835
5839
  }
@@ -38559,6 +38563,7 @@ css /* scss */ `
38559
38563
  }
38560
38564
  }
38561
38565
  `;
38566
+ const DEFAULT_TABLE_STYLE_COLOR = "#3C78D8";
38562
38567
  class TableStyleEditorPanel extends Component {
38563
38568
  static template = "o-spreadsheet-TableStyleEditorPanel";
38564
38569
  static components = { Section, RoundColorPicker, TableStylePreview };
@@ -38577,7 +38582,7 @@ class TableStyleEditorPanel extends Component {
38577
38582
  : null;
38578
38583
  return {
38579
38584
  pickerOpened: false,
38580
- primaryColor: editedStyle?.primaryColor || "#3C78D8",
38585
+ primaryColor: editedStyle?.primaryColor || DEFAULT_TABLE_STYLE_COLOR,
38581
38586
  selectedTemplateName: editedStyle?.templateName || "lightColoredText",
38582
38587
  styleName: editedStyle?.displayName || this.env.model.getters.getNewCustomTableStyleName(),
38583
38588
  };
@@ -38586,7 +38591,7 @@ class TableStyleEditorPanel extends Component {
38586
38591
  this.state.pickerOpened = !this.state.pickerOpened;
38587
38592
  }
38588
38593
  onColorPicked(color) {
38589
- this.state.primaryColor = color;
38594
+ this.state.primaryColor = isColorValid(color) ? color : DEFAULT_TABLE_STYLE_COLOR;
38590
38595
  this.state.pickerOpened = false;
38591
38596
  }
38592
38597
  onTemplatePicked(templateName) {
@@ -39933,6 +39938,7 @@ class FiguresContainer extends Component {
39933
39938
  draggedFigure: undefined,
39934
39939
  horizontalSnap: undefined,
39935
39940
  verticalSnap: undefined,
39941
+ cancelDnd: undefined,
39936
39942
  });
39937
39943
  setup() {
39938
39944
  onMounted(() => {
@@ -39945,12 +39951,28 @@ class FiguresContainer extends Component {
39945
39951
  // new rendering
39946
39952
  this.render();
39947
39953
  });
39954
+ onWillUpdateProps(() => {
39955
+ const sheetId = this.env.model.getters.getActiveSheetId();
39956
+ const draggedFigureId = this.dnd.draggedFigure?.id;
39957
+ if (draggedFigureId && !this.env.model.getters.getFigure(sheetId, draggedFigureId)) {
39958
+ if (this.dnd.cancelDnd) {
39959
+ this.dnd.cancelDnd();
39960
+ }
39961
+ this.dnd.draggedFigure = undefined;
39962
+ this.dnd.horizontalSnap = undefined;
39963
+ this.dnd.verticalSnap = undefined;
39964
+ this.dnd.cancelDnd = undefined;
39965
+ }
39966
+ });
39948
39967
  }
39949
39968
  getVisibleFigures() {
39950
39969
  const visibleFigures = this.env.model.getters.getVisibleFigures();
39951
39970
  if (this.dnd.draggedFigure &&
39952
39971
  !visibleFigures.some((figure) => figure.id === this.dnd.draggedFigure?.id)) {
39953
- visibleFigures.push(this.env.model.getters.getFigure(this.env.model.getters.getActiveSheetId(), this.dnd.draggedFigure?.id));
39972
+ const draggedFigure = this.env.model.getters.getFigure(this.env.model.getters.getActiveSheetId(), this.dnd.draggedFigure?.id);
39973
+ if (draggedFigure) {
39974
+ visibleFigures.push(draggedFigure);
39975
+ }
39954
39976
  }
39955
39977
  return visibleFigures;
39956
39978
  }
@@ -40069,7 +40091,7 @@ class FiguresContainer extends Component {
40069
40091
  this.dnd.verticalSnap = undefined;
40070
40092
  this.env.model.dispatch("UPDATE_FIGURE", { sheetId, id: figure.id, x, y });
40071
40093
  };
40072
- startDnd(onMouseMove, onMouseUp);
40094
+ this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
40073
40095
  }
40074
40096
  /**
40075
40097
  * Initialize the resize of a figure with mouse movements
@@ -40117,7 +40139,7 @@ class FiguresContainer extends Component {
40117
40139
  this.dnd.horizontalSnap = undefined;
40118
40140
  this.dnd.verticalSnap = undefined;
40119
40141
  };
40120
- startDnd(onMouseMove, onMouseUp);
40142
+ this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
40121
40143
  }
40122
40144
  getOtherFigures(figId) {
40123
40145
  return this.getVisibleFigures().filter((f) => f.id !== figId);
@@ -46725,13 +46747,12 @@ const MIGRATIONS = [
46725
46747
  to: 8,
46726
46748
  applyMigration(data) {
46727
46749
  const namesTaken = [];
46728
- const globalForbiddenInExcel = new RegExp(FORBIDDEN_IN_EXCEL_REGEX, "g");
46729
46750
  for (let sheet of data.sheets || []) {
46730
46751
  if (!sheet.name) {
46731
46752
  continue;
46732
46753
  }
46733
46754
  const oldName = sheet.name;
46734
- const escapedName = oldName.replace(globalForbiddenInExcel, "_");
46755
+ const escapedName = sanitizeSheetName(oldName, "_");
46735
46756
  let i = 1;
46736
46757
  let newName = escapedName;
46737
46758
  while (namesTaken.includes(newName)) {
@@ -48230,7 +48251,7 @@ class CellPlugin extends CorePlugin {
48230
48251
  const before = this.getters.getCell({ sheetId, col, row });
48231
48252
  const hasContent = "content" in after || "formula" in after;
48232
48253
  // Compute the new cell properties
48233
- const afterContent = hasContent ? replaceSpecialSpaces(after?.content) : before?.content || "";
48254
+ const afterContent = hasContent ? replaceNewLines(after?.content) : before?.content || "";
48234
48255
  let style;
48235
48256
  if (after.style !== undefined) {
48236
48257
  style = after.style || undefined;
@@ -51091,6 +51112,9 @@ class SheetPlugin extends CorePlugin {
51091
51112
  };
51092
51113
  }
51093
51114
  getUnboundedZone(sheetId, zone) {
51115
+ if (zone.bottom === undefined || zone.right === undefined) {
51116
+ return zone;
51117
+ }
51094
51118
  const isFullRow = zone.left === 0 && zone.right === this.getNumberCols(sheetId) - 1;
51095
51119
  const isFullCol = zone.top === 0 && zone.bottom === this.getNumberRows(sheetId) - 1;
51096
51120
  return {
@@ -51256,7 +51280,7 @@ class SheetPlugin extends CorePlugin {
51256
51280
  if (orderedSheetIds.find((id) => sheets[id]?.name.toLowerCase() === name && id !== cmd.sheetId)) {
51257
51281
  return "DuplicatedSheetName" /* CommandResult.DuplicatedSheetName */;
51258
51282
  }
51259
- if (FORBIDDEN_IN_EXCEL_REGEX.test(name)) {
51283
+ if (FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX.test(name)) {
51260
51284
  return "ForbiddenCharactersInSheetName" /* CommandResult.ForbiddenCharactersInSheetName */;
51261
51285
  }
51262
51286
  return "Success" /* CommandResult.Success */;
@@ -56045,11 +56069,13 @@ class PivotUIPlugin extends UIPlugin {
56045
56069
  return EMPTY_PIVOT_CELL;
56046
56070
  }
56047
56071
  if (functionName === "PIVOT") {
56048
- const includeTotal = args[2] === false ? false : undefined;
56049
- const includeColumnHeaders = args[3] === false ? false : undefined;
56072
+ const includeTotal = toScalar(args[2]);
56073
+ const shouldIncludeTotal = includeTotal === undefined ? true : toBoolean(includeTotal);
56074
+ const includeColumnHeaders = toScalar(args[3]);
56075
+ const shouldIncludeColumnHeaders = includeColumnHeaders === undefined ? true : toBoolean(includeColumnHeaders);
56050
56076
  const pivotCells = pivot
56051
56077
  .getTableStructure()
56052
- .getPivotCells(includeTotal, includeColumnHeaders);
56078
+ .getPivotCells(shouldIncludeTotal, shouldIncludeColumnHeaders);
56053
56079
  const pivotCol = position.col - mainPosition.col;
56054
56080
  const pivotRow = position.row - mainPosition.row;
56055
56081
  return pivotCells[pivotCol][pivotRow];
@@ -58154,7 +58180,7 @@ class InsertPivotPlugin extends UIPlugin {
58154
58180
  getPivotDuplicateSheetName(pivotName) {
58155
58181
  let i = 1;
58156
58182
  const names = this.getters.getSheetIds().map((id) => this.getters.getSheetName(id));
58157
- const sanitizedName = pivotName.replace(new RegExp(FORBIDDEN_IN_EXCEL_REGEX, "g"), " ");
58183
+ const sanitizedName = sanitizeSheetName(pivotName);
58158
58184
  let name = sanitizedName;
58159
58185
  while (names.includes(name)) {
58160
58186
  name = `${sanitizedName} (${i})`;
@@ -61298,6 +61324,7 @@ class SheetViewPlugin extends UIPlugin {
61298
61324
  break;
61299
61325
  case "DELETE_SHEET":
61300
61326
  this.cleanViewports();
61327
+ this.sheetsWithDirtyViewports.delete(cmd.sheetId);
61301
61328
  break;
61302
61329
  case "ACTIVATE_SHEET":
61303
61330
  this.sheetsWithDirtyViewports.add(cmd.sheetIdTo);
@@ -62195,7 +62222,7 @@ function interactiveRenameSheet(env, sheetId, name, errorCallback) {
62195
62222
  env.raiseError(_t("A sheet with the name %s already exists. Please select another name.", name), errorCallback);
62196
62223
  }
62197
62224
  else if (result.reasons.includes("ForbiddenCharactersInSheetName" /* CommandResult.ForbiddenCharactersInSheetName */)) {
62198
- env.raiseError(_t("Some used characters are not allowed in a sheet name (Forbidden characters are %s).", FORBIDDEN_SHEET_CHARS.join(" ")), errorCallback);
62225
+ env.raiseError(_t("Some used characters are not allowed in a sheet name (Forbidden characters are %s).", FORBIDDEN_SHEETNAME_CHARS.join(" ")), errorCallback);
62199
62226
  }
62200
62227
  }
62201
62228
 
@@ -63454,7 +63481,7 @@ class ActionButton extends Component {
63454
63481
  setup() {
63455
63482
  onWillUpdateProps((nextProps) => {
63456
63483
  if (nextProps.action !== this.props.action) {
63457
- this.actionButton = createAction(this.props.action);
63484
+ this.actionButton = createAction(nextProps.action);
63458
63485
  }
63459
63486
  });
63460
63487
  }
@@ -63721,7 +63748,6 @@ css /* scss */ `
63721
63748
  height: fit-content;
63722
63749
  margin-top: -1px;
63723
63750
  border: 1px solid;
63724
- z-index: ${ComponentsImportance.TopBarComposer};
63725
63751
 
63726
63752
  .o-composer:empty:not(:focus):not(.active)::before {
63727
63753
  content: url("data:image/svg+xml,${encodeURIComponent(FX_SVG)}");
@@ -63763,6 +63789,7 @@ class TopBarComposer extends Component {
63763
63789
  }
63764
63790
  return cssPropertiesToCss({
63765
63791
  "border-color": SELECTION_BORDER_COLOR,
63792
+ "z-index": String(ComponentsImportance.TopBarComposer),
63766
63793
  });
63767
63794
  }
63768
63795
  get delimitation() {
@@ -68587,6 +68614,7 @@ const helpers = {
68587
68614
  createPivotFormula,
68588
68615
  areDomainArgsFieldsValid,
68589
68616
  formatTickValue,
68617
+ sanitizeSheetName,
68590
68618
  };
68591
68619
  const links = {
68592
68620
  isMarkdownLink,
@@ -68674,6 +68702,6 @@ const constants = {
68674
68702
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
68675
68703
 
68676
68704
 
68677
- __info__.version = "17.4.14";
68678
- __info__.date = "2024-11-28T09:08:12.462Z";
68679
- __info__.hash = "81bf386";
68705
+ __info__.version = "17.4.16";
68706
+ __info__.date = "2024-12-19T07:50:04.021Z";
68707
+ __info__.hash = "6b827fc";