@odoo/o-spreadsheet 17.0.43 → 17.0.45

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.0.43
6
- * @date 2024-12-05T10:36:19.412Z
7
- * @hash 8344531
5
+ * @version 17.0.45
6
+ * @date 2025-01-14T11:30:44.730Z
7
+ * @hash 94f8ef9
8
8
  */
9
9
 
10
10
  'use strict';
@@ -706,6 +706,7 @@ function removeFalsyAttributes(obj) {
706
706
  * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes
707
707
  */
708
708
  const whiteSpaceSpecialCharacters = [
709
+ " ",
709
710
  "\t",
710
711
  "\f",
711
712
  "\v",
@@ -720,17 +721,15 @@ const whiteSpaceSpecialCharacters = [
720
721
  String.fromCharCode(parseInt("3000", 16)),
721
722
  String.fromCharCode(parseInt("feff", 16)),
722
723
  ];
723
- const whiteSpaceRegexp = new RegExp(whiteSpaceSpecialCharacters.join("|") + "|(\r\n|\r|\n)", "g");
724
+ const whiteSpaceRegexp = new RegExp(whiteSpaceSpecialCharacters.join("|"), "g");
725
+ const newLineRegexp = /(\r\n|\r)/g;
724
726
  /**
725
- * Replace all the special spaces in a string (non-breaking, tabs, ...) by normal spaces, and all the
726
- * different newlines types by \n.
727
+ * Replace all different newlines characters by \n
727
728
  */
728
- function replaceSpecialSpaces(text) {
729
+ function replaceNewLines(text) {
729
730
  if (!text)
730
731
  return "";
731
- if (!whiteSpaceRegexp.test(text))
732
- return text;
733
- return text.replace(whiteSpaceRegexp, (match, newLine) => (newLine ? NEWLINE : " "));
732
+ return text.replace(newLineRegexp, NEWLINE);
734
733
  }
735
734
  /**
736
735
  * Determine if the numbers are consecutive.
@@ -7473,7 +7472,7 @@ LinkDisplay.props = {
7473
7472
  const POSTFIX_UNARY_OPERATORS = ["%"];
7474
7473
  const OPERATORS = "+,-,*,/,:,=,<>,>=,>,<=,<,^,&".split(",").concat(POSTFIX_UNARY_OPERATORS);
7475
7474
  function tokenize(str, locale = DEFAULT_LOCALE) {
7476
- str = replaceSpecialSpaces(str);
7475
+ str = replaceNewLines(str);
7477
7476
  const chars = new TokenizingChars(str);
7478
7477
  const result = [];
7479
7478
  while (!chars.isOver()) {
@@ -7620,12 +7619,12 @@ function tokenizeSpace(chars) {
7620
7619
  if (length) {
7621
7620
  return { type: "SPACE", value: NEWLINE.repeat(length) };
7622
7621
  }
7623
- while (chars.current === " ") {
7624
- length++;
7625
- chars.shift();
7622
+ let spaces = "";
7623
+ while (chars.current && chars.current.match(whiteSpaceRegexp)) {
7624
+ spaces += chars.shift();
7626
7625
  }
7627
- if (length) {
7628
- return { type: "SPACE", value: " ".repeat(length) };
7626
+ if (spaces) {
7627
+ return { type: "SPACE", value: spaces };
7629
7628
  }
7630
7629
  return null;
7631
7630
  }
@@ -21820,15 +21819,23 @@ class BarConfigPanel extends LineBarPieConfigPanel {
21820
21819
  }
21821
21820
  }
21822
21821
 
21822
+ /**
21823
+ * Start listening to pointer events and apply the given callbacks.
21824
+ *
21825
+ * @returns A function to remove the listeners.
21826
+ */
21823
21827
  function startDnd(onMouseMove, onMouseUp, onMouseDown = () => { }) {
21824
- const _onMouseUp = (ev) => {
21825
- onMouseUp(ev);
21828
+ const removeListeners = () => {
21826
21829
  window.removeEventListener("mousedown", onMouseDown);
21827
21830
  window.removeEventListener("mouseup", _onMouseUp);
21828
21831
  window.removeEventListener("dragstart", _onDragStart);
21829
21832
  window.removeEventListener("mousemove", onMouseMove);
21830
21833
  window.removeEventListener("wheel", onMouseMove);
21831
21834
  };
21835
+ const _onMouseUp = (ev) => {
21836
+ onMouseUp(ev);
21837
+ removeListeners();
21838
+ };
21832
21839
  function _onDragStart(ev) {
21833
21840
  ev.preventDefault();
21834
21841
  }
@@ -21840,6 +21847,7 @@ function startDnd(onMouseMove, onMouseUp, onMouseDown = () => { }) {
21840
21847
  // preventDefault() is not allowed in passive event handler.
21841
21848
  // https://chromestatus.com/feature/6662647093133312
21842
21849
  window.addEventListener("wheel", onMouseMove, { passive: false });
21850
+ return removeListeners;
21843
21851
  }
21844
21852
  /**
21845
21853
  * Function to be used during a mousedown event, this function allows to
@@ -28013,6 +28021,7 @@ class FiguresContainer extends owl.Component {
28013
28021
  draggedFigure: undefined,
28014
28022
  horizontalSnap: undefined,
28015
28023
  verticalSnap: undefined,
28024
+ cancelDnd: undefined,
28016
28025
  });
28017
28026
  setup() {
28018
28027
  owl.onMounted(() => {
@@ -28025,12 +28034,28 @@ class FiguresContainer extends owl.Component {
28025
28034
  // new rendering
28026
28035
  this.render();
28027
28036
  });
28037
+ owl.onWillUpdateProps(() => {
28038
+ const sheetId = this.env.model.getters.getActiveSheetId();
28039
+ const draggedFigureId = this.dnd.draggedFigure?.id;
28040
+ if (draggedFigureId && !this.env.model.getters.getFigure(sheetId, draggedFigureId)) {
28041
+ if (this.dnd.cancelDnd) {
28042
+ this.dnd.cancelDnd();
28043
+ }
28044
+ this.dnd.draggedFigure = undefined;
28045
+ this.dnd.horizontalSnap = undefined;
28046
+ this.dnd.verticalSnap = undefined;
28047
+ this.dnd.cancelDnd = undefined;
28048
+ }
28049
+ });
28028
28050
  }
28029
28051
  getVisibleFigures() {
28030
28052
  const visibleFigures = this.env.model.getters.getVisibleFigures();
28031
28053
  if (this.dnd.draggedFigure &&
28032
28054
  !visibleFigures.some((figure) => figure.id === this.dnd.draggedFigure?.id)) {
28033
- visibleFigures.push(this.env.model.getters.getFigure(this.env.model.getters.getActiveSheetId(), this.dnd.draggedFigure?.id));
28055
+ const draggedFigure = this.env.model.getters.getFigure(this.env.model.getters.getActiveSheetId(), this.dnd.draggedFigure?.id);
28056
+ if (draggedFigure) {
28057
+ visibleFigures.push(draggedFigure);
28058
+ }
28034
28059
  }
28035
28060
  return visibleFigures;
28036
28061
  }
@@ -28149,7 +28174,7 @@ class FiguresContainer extends owl.Component {
28149
28174
  this.dnd.verticalSnap = undefined;
28150
28175
  this.env.model.dispatch("UPDATE_FIGURE", { sheetId, id: figure.id, x, y });
28151
28176
  };
28152
- startDnd(onMouseMove, onMouseUp);
28177
+ this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
28153
28178
  }
28154
28179
  /**
28155
28180
  * Initialize the resize of a figure with mouse movements
@@ -28197,7 +28222,7 @@ class FiguresContainer extends owl.Component {
28197
28222
  this.dnd.horizontalSnap = undefined;
28198
28223
  this.dnd.verticalSnap = undefined;
28199
28224
  };
28200
- startDnd(onMouseMove, onMouseUp);
28225
+ this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
28201
28226
  }
28202
28227
  getOtherFigures(figId) {
28203
28228
  return this.getVisibleFigures().filter((f) => f.id !== figId);
@@ -31493,7 +31518,7 @@ function extractStyle(cell, data) {
31493
31518
  vertical: style.verticalAlign
31494
31519
  ? V_ALIGNMENT_EXPORT_CONVERSION_MAP[style.verticalAlign]
31495
31520
  : undefined,
31496
- wrapText: style.wrapping === "wrap",
31521
+ wrapText: style.wrapping === "wrap" || cell.content?.includes(NEWLINE) ? true : undefined,
31497
31522
  },
31498
31523
  };
31499
31524
  styles.font["strike"] = !!style?.strikethrough || undefined;
@@ -31710,7 +31735,7 @@ function convertFigure(figure, id, sheetData) {
31710
31735
  return undefined;
31711
31736
  }
31712
31737
  function isChartData(data) {
31713
- return "dataSets" in data;
31738
+ return "dataSets" in data && data.dataSets.length > 0;
31714
31739
  }
31715
31740
  function isImageData(data) {
31716
31741
  return "imageSrc" in data;
@@ -31922,9 +31947,8 @@ function convertRows(sheet, numberOfRows) {
31922
31947
  }
31923
31948
  return rows;
31924
31949
  }
31925
- /** Remove newlines (\n) in shared strings, We do not support them */
31926
31950
  function convertSharedStrings(xlsxSharedStrings) {
31927
- return xlsxSharedStrings.map((str) => str.replace(/\n/g, ""));
31951
+ return xlsxSharedStrings.map(replaceNewLines);
31928
31952
  }
31929
31953
  function convertCells(sheet, data, sheetDims, warningManager) {
31930
31954
  const cells = {};
@@ -32715,15 +32739,10 @@ class XlsxMiscExtractor extends XlsxBaseExtractor {
32715
32739
  getSharedStrings() {
32716
32740
  return this.mapOnElements({ parent: this.rootFile.file.xml, query: "si" }, (ssElement) => {
32717
32741
  // Shared string can either be a simple text, or a rich text (text with formatting, possibly in multiple parts)
32718
- if (ssElement.children[0].tagName === "t") {
32719
- return this.extractTextContent(ssElement) || "";
32720
- }
32721
32742
  // We don't support rich text formatting, we'll only extract the text
32722
- else {
32723
- return this.mapOnElements({ parent: ssElement, query: "t" }, (textElement) => {
32724
- return this.extractTextContent(textElement) || "";
32725
- }).join("");
32726
- }
32743
+ return this.mapOnElements({ parent: ssElement, query: "t" }, (textElement) => {
32744
+ return this.extractTextContent(textElement) || "";
32745
+ }).join("");
32727
32746
  });
32728
32747
  }
32729
32748
  }
@@ -34530,10 +34549,34 @@ class BordersPlugin extends CorePlugin {
34530
34549
  const elements = [...cmd.elements].sort((a, b) => b - a);
34531
34550
  for (const group of groupConsecutive(elements)) {
34532
34551
  if (cmd.dimension === "COL") {
34533
- this.shiftBordersHorizontally(cmd.sheetId, group[group.length - 1] + 1, -group.length);
34552
+ if (group[0] >= this.getters.getNumberCols(cmd.sheetId)) {
34553
+ for (let row = 0; row < this.getters.getNumberRows(cmd.sheetId); row++) {
34554
+ this.history.update("borders", cmd.sheetId, group[0] + 1, row, "vertical", undefined);
34555
+ }
34556
+ }
34557
+ if (group[group.length - 1] === 0) {
34558
+ for (let row = 0; row < this.getters.getNumberRows(cmd.sheetId); row++) {
34559
+ this.history.update("borders", cmd.sheetId, 0, row, "vertical", undefined);
34560
+ }
34561
+ }
34562
+ const zone = this.getters.getColsZone(cmd.sheetId, group[group.length - 1] + 1, group[0]);
34563
+ this.clearInsideBorders(cmd.sheetId, [zone]);
34564
+ this.shiftBordersHorizontally(cmd.sheetId, group[0] + 1, -group.length);
34534
34565
  }
34535
34566
  else {
34536
- this.shiftBordersVertically(cmd.sheetId, group[group.length - 1] + 1, -group.length);
34567
+ if (group[0] >= this.getters.getNumberRows(cmd.sheetId)) {
34568
+ for (let col = 0; col < this.getters.getNumberCols(cmd.sheetId); col++) {
34569
+ this.history.update("borders", cmd.sheetId, col, group[0] + 1, "horizontal", undefined);
34570
+ }
34571
+ }
34572
+ if (group[group.length - 1] === 0) {
34573
+ for (let col = 0; col < this.getters.getNumberCols(cmd.sheetId); col++) {
34574
+ this.history.update("borders", cmd.sheetId, col, 0, "horizontal", undefined);
34575
+ }
34576
+ }
34577
+ const zone = this.getters.getRowsZone(cmd.sheetId, group[group.length - 1] + 1, group[0]);
34578
+ this.clearInsideBorders(cmd.sheetId, [zone]);
34579
+ this.shiftBordersVertically(cmd.sheetId, group[0] + 1, -group.length);
34537
34580
  }
34538
34581
  }
34539
34582
  break;
@@ -34840,6 +34883,18 @@ class BordersPlugin extends CorePlugin {
34840
34883
  }
34841
34884
  }
34842
34885
  }
34886
+ /**
34887
+ * Remove the borders inside of a zone
34888
+ */
34889
+ clearInsideBorders(sheetId, zones) {
34890
+ for (let zone of zones) {
34891
+ for (let row = zone.top; row <= zone.bottom; row++) {
34892
+ for (let col = zone.left; col <= zone.right; col++) {
34893
+ this.history.update("borders", sheetId, col, row, undefined);
34894
+ }
34895
+ }
34896
+ }
34897
+ }
34843
34898
  /**
34844
34899
  * Add a border to the existing one to a cell
34845
34900
  */
@@ -36096,7 +36151,7 @@ class CellPlugin extends CorePlugin {
36096
36151
  const before = this.getters.getCell({ sheetId, col, row });
36097
36152
  const hasContent = "content" in after || "formula" in after;
36098
36153
  // Compute the new cell properties
36099
- const afterContent = hasContent ? replaceSpecialSpaces(after?.content) : before?.content || "";
36154
+ const afterContent = hasContent ? replaceNewLines(after?.content) : before?.content || "";
36100
36155
  let style;
36101
36156
  if (after.style !== undefined) {
36102
36157
  style = after.style || undefined;
@@ -50916,6 +50971,7 @@ class SheetViewPlugin extends UIPlugin {
50916
50971
  break;
50917
50972
  case "DELETE_SHEET":
50918
50973
  this.cleanViewports();
50974
+ this.sheetsWithDirtyViewports.delete(cmd.sheetId);
50919
50975
  break;
50920
50976
  case "ACTIVATE_SHEET":
50921
50977
  this.sheetsWithDirtyViewports.add(cmd.sheetIdTo);
@@ -51838,17 +51894,17 @@ class BottomBarSheet extends owl.Component {
51838
51894
  sheetNameRef = owl.useRef("sheetNameSpan");
51839
51895
  editionState = "initializing";
51840
51896
  setup() {
51841
- owl.onMounted(() => {
51842
- if (this.isSheetActive) {
51843
- this.scrollToSheet();
51844
- }
51845
- });
51846
51897
  owl.onPatched(() => {
51847
51898
  if (this.sheetNameRef.el && this.state.isEditing && this.editionState === "initializing") {
51848
51899
  this.editionState = "editing";
51849
51900
  this.focusInputAndSelectContent();
51850
51901
  }
51851
51902
  });
51903
+ owl.useEffect((sheetId) => {
51904
+ if (this.props.sheetId === sheetId) {
51905
+ this.scrollToSheet();
51906
+ }
51907
+ }, () => [this.env.model.getters.getActiveSheetId()]);
51852
51908
  }
51853
51909
  focusInputAndSelectContent() {
51854
51910
  if (!this.state.isEditing || !this.sheetNameRef.el)
@@ -51860,7 +51916,10 @@ class BottomBarSheet extends owl.Component {
51860
51916
  }
51861
51917
  }
51862
51918
  scrollToSheet() {
51863
- this.sheetDivRef.el?.scrollIntoView?.();
51919
+ this.sheetDivRef.el?.scrollIntoView?.({
51920
+ behavior: "smooth",
51921
+ inline: "nearest",
51922
+ });
51864
51923
  }
51865
51924
  onFocusOut() {
51866
51925
  if (this.state.isEditing && this.editionState !== "initializing") {
@@ -53137,7 +53196,6 @@ css /* scss */ `
53137
53196
  height: fit-content;
53138
53197
  margin-top: -1px;
53139
53198
  border: 1px solid;
53140
- z-index: ${ComponentsImportance.TopBarComposer};
53141
53199
 
53142
53200
  .o-composer:empty:not(:focus):not(.active)::before {
53143
53201
  content: url("data:image/svg+xml,${encodeURIComponent(FX_SVG)}");
@@ -53171,6 +53229,7 @@ class TopBarComposer extends owl.Component {
53171
53229
  }
53172
53230
  return cssPropertiesToCss({
53173
53231
  "border-color": SELECTION_BORDER_COLOR,
53232
+ "z-index": String(ComponentsImportance.TopBarComposer),
53174
53233
  });
53175
53234
  }
53176
53235
  }
@@ -56973,7 +57032,12 @@ function createSharedStrings(strings) {
56973
57032
  ["count", strings.length],
56974
57033
  ["uniqueCount", strings.length],
56975
57034
  ];
56976
- const stringNodes = strings.map((string) => escapeXml /*xml*/ `<si><t>${string}</t></si>`);
57035
+ const stringNodes = strings.map((string) => {
57036
+ if (string.trim() !== string) {
57037
+ return escapeXml /*xml*/ `<si><t xml:space="preserve">${string}</t></si>`;
57038
+ }
57039
+ return escapeXml /*xml*/ `<si><t>${string}</t></si>`;
57040
+ });
56977
57041
  const xml = escapeXml /*xml*/ `
56978
57042
  <sst ${formatAttributes(namespaces)}>
56979
57043
  ${joinXmlNodes(stringNodes)}
@@ -57606,6 +57670,8 @@ const helpers = {
57606
57670
  createActions,
57607
57671
  transformRangeData,
57608
57672
  deepEquals,
57673
+ isNumber,
57674
+ isDateTime,
57609
57675
  };
57610
57676
  const links = {
57611
57677
  isMarkdownLink,
@@ -57684,6 +57750,6 @@ exports.setTranslationMethod = setTranslationMethod;
57684
57750
  exports.tokenize = tokenize;
57685
57751
 
57686
57752
 
57687
- __info__.version = "17.0.43";
57688
- __info__.date = "2024-12-05T10:36:19.412Z";
57689
- __info__.hash = "8344531";
57753
+ __info__.version = "17.0.45";
57754
+ __info__.date = "2025-01-14T11:30:44.730Z";
57755
+ __info__.hash = "94f8ef9";
@@ -968,6 +968,7 @@ declare class DateTime {
968
968
  setMinutes(minutes: number): number;
969
969
  setSeconds(seconds: number): number;
970
970
  }
971
+ declare function isDateTime(str: string, locale: Locale): boolean;
971
972
 
972
973
  /**
973
974
  * Formats a cell value with its format.
@@ -998,6 +999,13 @@ declare function lazy<T>(fn: (() => T) | T): Lazy<T>;
998
999
  */
999
1000
  declare function deepEquals(o1: any, o2: any): boolean;
1000
1001
 
1002
+ /**
1003
+ * Return true if the argument is a "number string".
1004
+ *
1005
+ * Note that "" (empty string) does not count as a number string
1006
+ */
1007
+ declare function isNumber(value: string | undefined, locale: Locale): boolean;
1008
+
1001
1009
  interface ConstructorArgs {
1002
1010
  readonly zone: Readonly<Zone | UnboundedZone>;
1003
1011
  readonly parts: readonly RangePart[];
@@ -3375,6 +3383,10 @@ declare class BordersPlugin extends CorePlugin<BordersPluginState> implements Bo
3375
3383
  * Remove the borders of a zone
3376
3384
  */
3377
3385
  private clearBorders;
3386
+ /**
3387
+ * Remove the borders inside of a zone
3388
+ */
3389
+ private clearInsideBorders;
3378
3390
  /**
3379
3391
  * Add a border to the existing one to a cell
3380
3392
  */
@@ -6386,6 +6398,7 @@ interface DndState {
6386
6398
  draggedFigure?: Figure;
6387
6399
  horizontalSnap?: Snap<HFigureAxisType>;
6388
6400
  verticalSnap?: Snap<VFigureAxisType>;
6401
+ cancelDnd: (() => void) | undefined;
6389
6402
  }
6390
6403
  /**
6391
6404
  * Each figure ⭐ is positioned inside a container `div` placed and sized
@@ -7955,6 +7968,8 @@ declare const helpers: {
7955
7968
  createActions: typeof createActions;
7956
7969
  transformRangeData: typeof transformRangeData;
7957
7970
  deepEquals: typeof deepEquals;
7971
+ isNumber: typeof isNumber;
7972
+ isDateTime: typeof isDateTime;
7958
7973
  };
7959
7974
  declare const links: {
7960
7975
  isMarkdownLink: typeof isMarkdownLink;