@odoo/o-spreadsheet 17.2.29 → 17.2.31

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.
@@ -3,9 +3,9 @@
3
3
  /**
4
4
  * This file is generated by o-spreadsheet build tools. Do not edit it.
5
5
  * @see https://github.com/odoo/o-spreadsheet
6
- * @version 17.2.29
7
- * @date 2024-12-05T10:39:14.167Z
8
- * @hash 7b4b898
6
+ * @version 17.2.31
7
+ * @date 2025-01-14T11:31:09.035Z
8
+ * @hash 306dbf7
9
9
  */
10
10
 
11
11
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw } from '@odoo/owl';
@@ -624,6 +624,7 @@ function removeFalsyAttributes(obj) {
624
624
  * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes
625
625
  */
626
626
  const whiteSpaceSpecialCharacters = [
627
+ " ",
627
628
  "\t",
628
629
  "\f",
629
630
  "\v",
@@ -638,17 +639,15 @@ const whiteSpaceSpecialCharacters = [
638
639
  String.fromCharCode(parseInt("3000", 16)),
639
640
  String.fromCharCode(parseInt("feff", 16)),
640
641
  ];
641
- const whiteSpaceRegexp = new RegExp(whiteSpaceSpecialCharacters.join("|") + "|(\r\n|\r|\n)", "g");
642
+ const whiteSpaceRegexp = new RegExp(whiteSpaceSpecialCharacters.join("|"), "g");
643
+ const newLineRegexp = /(\r\n|\r)/g;
642
644
  /**
643
- * Replace all the special spaces in a string (non-breaking, tabs, ...) by normal spaces, and all the
644
- * different newlines types by \n.
645
+ * Replace all different newlines characters by \n
645
646
  */
646
- function replaceSpecialSpaces(text) {
647
+ function replaceNewLines(text) {
647
648
  if (!text)
648
649
  return "";
649
- if (!whiteSpaceRegexp.test(text))
650
- return text;
651
- return text.replace(whiteSpaceRegexp, (match, newLine) => (newLine ? NEWLINE : " "));
650
+ return text.replace(newLineRegexp, NEWLINE);
652
651
  }
653
652
  /**
654
653
  * Determine if the numbers are consecutive.
@@ -5161,7 +5160,7 @@ class BorderClipboardHandler extends AbstractCellClipboardHandler {
5161
5160
  const POSTFIX_UNARY_OPERATORS = ["%"];
5162
5161
  const OPERATORS = "+,-,*,/,:,=,<>,>=,>,<=,<,^,&".split(",").concat(POSTFIX_UNARY_OPERATORS);
5163
5162
  function tokenize(str, locale = DEFAULT_LOCALE) {
5164
- str = replaceSpecialSpaces(str);
5163
+ str = replaceNewLines(str);
5165
5164
  const chars = new TokenizingChars(str);
5166
5165
  const result = [];
5167
5166
  while (!chars.isOver()) {
@@ -5308,12 +5307,12 @@ function tokenizeSpace(chars) {
5308
5307
  if (length) {
5309
5308
  return { type: "SPACE", value: NEWLINE.repeat(length) };
5310
5309
  }
5311
- while (chars.current === " ") {
5312
- length++;
5313
- chars.shift();
5310
+ let spaces = "";
5311
+ while (chars.current && chars.current.match(whiteSpaceRegexp)) {
5312
+ spaces += chars.shift();
5314
5313
  }
5315
- if (length) {
5316
- return { type: "SPACE", value: " ".repeat(length) };
5314
+ if (spaces) {
5315
+ return { type: "SPACE", value: spaces };
5317
5316
  }
5318
5317
  return null;
5319
5318
  }
@@ -20244,7 +20243,7 @@ function createGaugeChartRuntime(chart, getters) {
20244
20243
  colors.push(chartColors.upperColor);
20245
20244
  return {
20246
20245
  background: getters.getStyleOfSingleCellChart(chart.background, dataRange).background,
20247
- title: chart.title,
20246
+ title: _t(chart.title),
20248
20247
  minValue: {
20249
20248
  value: minValue,
20250
20249
  label: formatValue(minValue, { locale, format }),
@@ -31581,14 +31580,11 @@ unGroupHeadersMenuRegistry
31581
31580
  });
31582
31581
 
31583
31582
  class DOMFocusableElementStore {
31584
- mutators = ["setFocusableElement", "focus"];
31583
+ mutators = ["setFocusableElement"];
31585
31584
  focusableElement = undefined;
31586
31585
  setFocusableElement(element) {
31587
31586
  this.focusableElement = element;
31588
31587
  }
31589
- focus() {
31590
- this.focusableElement?.focus();
31591
- }
31592
31588
  }
31593
31589
 
31594
31590
  // -----------------------------------------------------------------------------
@@ -32928,7 +32924,7 @@ class GridComposer extends Component {
32928
32924
  this.isEditing = isEditing;
32929
32925
  if (!isEditing) {
32930
32926
  this.rect = this.defaultRect;
32931
- this.DOMFocusableElementStore.focus();
32927
+ this.DOMFocusableElementStore.focusableElement?.focus();
32932
32928
  return;
32933
32929
  }
32934
32930
  const position = this.env.model.getters.getActivePosition();
@@ -33526,6 +33522,7 @@ class FiguresContainer extends Component {
33526
33522
  draggedFigure: undefined,
33527
33523
  horizontalSnap: undefined,
33528
33524
  verticalSnap: undefined,
33525
+ cancelDnd: undefined,
33529
33526
  });
33530
33527
  setup() {
33531
33528
  onMounted(() => {
@@ -33538,12 +33535,28 @@ class FiguresContainer extends Component {
33538
33535
  // new rendering
33539
33536
  this.render();
33540
33537
  });
33538
+ onWillUpdateProps(() => {
33539
+ const sheetId = this.env.model.getters.getActiveSheetId();
33540
+ const draggedFigureId = this.dnd.draggedFigure?.id;
33541
+ if (draggedFigureId && !this.env.model.getters.getFigure(sheetId, draggedFigureId)) {
33542
+ if (this.dnd.cancelDnd) {
33543
+ this.dnd.cancelDnd();
33544
+ }
33545
+ this.dnd.draggedFigure = undefined;
33546
+ this.dnd.horizontalSnap = undefined;
33547
+ this.dnd.verticalSnap = undefined;
33548
+ this.dnd.cancelDnd = undefined;
33549
+ }
33550
+ });
33541
33551
  }
33542
33552
  getVisibleFigures() {
33543
33553
  const visibleFigures = this.env.model.getters.getVisibleFigures();
33544
33554
  if (this.dnd.draggedFigure &&
33545
33555
  !visibleFigures.some((figure) => figure.id === this.dnd.draggedFigure?.id)) {
33546
- visibleFigures.push(this.env.model.getters.getFigure(this.env.model.getters.getActiveSheetId(), this.dnd.draggedFigure?.id));
33556
+ const draggedFigure = this.env.model.getters.getFigure(this.env.model.getters.getActiveSheetId(), this.dnd.draggedFigure?.id);
33557
+ if (draggedFigure) {
33558
+ visibleFigures.push(draggedFigure);
33559
+ }
33547
33560
  }
33548
33561
  return visibleFigures;
33549
33562
  }
@@ -33662,7 +33675,7 @@ class FiguresContainer extends Component {
33662
33675
  this.dnd.verticalSnap = undefined;
33663
33676
  this.env.model.dispatch("UPDATE_FIGURE", { sheetId, id: figure.id, x, y });
33664
33677
  };
33665
- startDnd(onMouseMove, onMouseUp);
33678
+ this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
33666
33679
  }
33667
33680
  /**
33668
33681
  * Initialize the resize of a figure with mouse movements
@@ -33710,7 +33723,7 @@ class FiguresContainer extends Component {
33710
33723
  this.dnd.horizontalSnap = undefined;
33711
33724
  this.dnd.verticalSnap = undefined;
33712
33725
  };
33713
- startDnd(onMouseMove, onMouseUp);
33726
+ this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
33714
33727
  }
33715
33728
  getOtherFigures(figId) {
33716
33729
  return this.getVisibleFigures().filter((f) => f.id !== figId);
@@ -35847,7 +35860,7 @@ class Grid extends Component {
35847
35860
  this.cellPopovers = useStore(CellPopoverStore);
35848
35861
  useEffect(() => {
35849
35862
  if (!this.sidePanel.isOpen) {
35850
- this.DOMFocusableElementStore.focus();
35863
+ this.DOMFocusableElementStore.focusableElement?.focus();
35851
35864
  }
35852
35865
  }, () => [this.sidePanel.isOpen]);
35853
35866
  }
@@ -36051,7 +36064,7 @@ class Grid extends Component {
36051
36064
  focusDefaultElement() {
36052
36065
  if (!this.env.model.getters.getSelectedFigureId() &&
36053
36066
  this.composerStore.editionMode === "inactive") {
36054
- this.DOMFocusableElementStore.focus();
36067
+ this.DOMFocusableElementStore.focusableElement?.focus();
36055
36068
  }
36056
36069
  }
36057
36070
  get gridEl() {
@@ -37670,7 +37683,7 @@ function extractStyle(cell, data) {
37670
37683
  vertical: style.verticalAlign
37671
37684
  ? V_ALIGNMENT_EXPORT_CONVERSION_MAP[style.verticalAlign]
37672
37685
  : undefined,
37673
- wrapText: style.wrapping === "wrap",
37686
+ wrapText: style.wrapping === "wrap" || cell.content?.includes(NEWLINE) ? true : undefined,
37674
37687
  },
37675
37688
  };
37676
37689
  styles.font["strike"] = !!style?.strikethrough || undefined;
@@ -37893,7 +37906,7 @@ function convertFigure(figure, id, sheetData) {
37893
37906
  return undefined;
37894
37907
  }
37895
37908
  function isChartData(data) {
37896
- return "dataSets" in data;
37909
+ return "dataSets" in data && data.dataSets.length > 0;
37897
37910
  }
37898
37911
  function isImageData(data) {
37899
37912
  return "imageSrc" in data;
@@ -38122,9 +38135,8 @@ function convertRows(sheet, numberOfRows, headerGroups) {
38122
38135
  }
38123
38136
  return rows;
38124
38137
  }
38125
- /** Remove newlines (\n) in shared strings, We do not support them */
38126
38138
  function convertSharedStrings(xlsxSharedStrings) {
38127
- return xlsxSharedStrings.map((str) => str.replace(/\n/g, ""));
38139
+ return xlsxSharedStrings.map(replaceNewLines);
38128
38140
  }
38129
38141
  function convertCells(sheet, data, sheetDims, warningManager) {
38130
38142
  const cells = {};
@@ -38966,15 +38978,10 @@ class XlsxMiscExtractor extends XlsxBaseExtractor {
38966
38978
  getSharedStrings() {
38967
38979
  return this.mapOnElements({ parent: this.rootFile.file.xml, query: "si" }, (ssElement) => {
38968
38980
  // Shared string can either be a simple text, or a rich text (text with formatting, possibly in multiple parts)
38969
- if (ssElement.children[0].tagName === "t") {
38970
- return this.extractTextContent(ssElement) || "";
38971
- }
38972
38981
  // We don't support rich text formatting, we'll only extract the text
38973
- else {
38974
- return this.mapOnElements({ parent: ssElement, query: "t" }, (textElement) => {
38975
- return this.extractTextContent(textElement) || "";
38976
- }).join("");
38977
- }
38982
+ return this.mapOnElements({ parent: ssElement, query: "t" }, (textElement) => {
38983
+ return this.extractTextContent(textElement) || "";
38984
+ }).join("");
38978
38985
  });
38979
38986
  }
38980
38987
  }
@@ -40696,10 +40703,34 @@ class BordersPlugin extends CorePlugin {
40696
40703
  const elements = [...cmd.elements].sort((a, b) => b - a);
40697
40704
  for (const group of groupConsecutive(elements)) {
40698
40705
  if (cmd.dimension === "COL") {
40699
- this.shiftBordersHorizontally(cmd.sheetId, group[group.length - 1] + 1, -group.length);
40706
+ if (group[0] >= this.getters.getNumberCols(cmd.sheetId)) {
40707
+ for (let row = 0; row < this.getters.getNumberRows(cmd.sheetId); row++) {
40708
+ this.history.update("borders", cmd.sheetId, group[0] + 1, row, "vertical", undefined);
40709
+ }
40710
+ }
40711
+ if (group[group.length - 1] === 0) {
40712
+ for (let row = 0; row < this.getters.getNumberRows(cmd.sheetId); row++) {
40713
+ this.history.update("borders", cmd.sheetId, 0, row, "vertical", undefined);
40714
+ }
40715
+ }
40716
+ const zone = this.getters.getColsZone(cmd.sheetId, group[group.length - 1] + 1, group[0]);
40717
+ this.clearInsideBorders(cmd.sheetId, [zone]);
40718
+ this.shiftBordersHorizontally(cmd.sheetId, group[0] + 1, -group.length);
40700
40719
  }
40701
40720
  else {
40702
- this.shiftBordersVertically(cmd.sheetId, group[group.length - 1] + 1, -group.length);
40721
+ if (group[0] >= this.getters.getNumberRows(cmd.sheetId)) {
40722
+ for (let col = 0; col < this.getters.getNumberCols(cmd.sheetId); col++) {
40723
+ this.history.update("borders", cmd.sheetId, col, group[0] + 1, "horizontal", undefined);
40724
+ }
40725
+ }
40726
+ if (group[group.length - 1] === 0) {
40727
+ for (let col = 0; col < this.getters.getNumberCols(cmd.sheetId); col++) {
40728
+ this.history.update("borders", cmd.sheetId, col, 0, "horizontal", undefined);
40729
+ }
40730
+ }
40731
+ const zone = this.getters.getRowsZone(cmd.sheetId, group[group.length - 1] + 1, group[0]);
40732
+ this.clearInsideBorders(cmd.sheetId, [zone]);
40733
+ this.shiftBordersVertically(cmd.sheetId, group[0] + 1, -group.length);
40703
40734
  }
40704
40735
  }
40705
40736
  break;
@@ -41006,6 +41037,18 @@ class BordersPlugin extends CorePlugin {
41006
41037
  }
41007
41038
  }
41008
41039
  }
41040
+ /**
41041
+ * Remove the borders inside of a zone
41042
+ */
41043
+ clearInsideBorders(sheetId, zones) {
41044
+ for (let zone of zones) {
41045
+ for (let row = zone.top; row <= zone.bottom; row++) {
41046
+ for (let col = zone.left; col <= zone.right; col++) {
41047
+ this.history.update("borders", sheetId, col, row, undefined);
41048
+ }
41049
+ }
41050
+ }
41051
+ }
41009
41052
  /**
41010
41053
  * Add a border to the existing one to a cell
41011
41054
  */
@@ -41868,7 +41911,7 @@ class CellPlugin extends CorePlugin {
41868
41911
  const before = this.getters.getCell({ sheetId, col, row });
41869
41912
  const hasContent = "content" in after || "formula" in after;
41870
41913
  // Compute the new cell properties
41871
- const afterContent = hasContent ? replaceSpecialSpaces(after?.content) : before?.content || "";
41914
+ const afterContent = hasContent ? replaceNewLines(after?.content) : before?.content || "";
41872
41915
  let style;
41873
41916
  if (after.style !== undefined) {
41874
41917
  style = after.style || undefined;
@@ -50587,6 +50630,9 @@ class Session extends EventBus {
50587
50630
  }
50588
50631
  }
50589
50632
  this.acknowledge(message);
50633
+ if (message.type === "REMOTE_REVISION" && message.clientId === this.clientId) {
50634
+ return;
50635
+ }
50590
50636
  this.trigger("collaborative-event-received");
50591
50637
  }
50592
50638
  onClientMoved(message) {
@@ -54190,6 +54236,7 @@ class SheetViewPlugin extends UIPlugin {
54190
54236
  break;
54191
54237
  case "DELETE_SHEET":
54192
54238
  this.cleanViewports();
54239
+ this.sheetsWithDirtyViewports.delete(cmd.sheetId);
54193
54240
  break;
54194
54241
  case "ACTIVATE_SHEET":
54195
54242
  this.sheetsWithDirtyViewports.add(cmd.sheetIdTo);
@@ -55137,11 +55184,6 @@ class BottomBarSheet extends Component {
55137
55184
  editionState = "initializing";
55138
55185
  DOMFocusableElementStore;
55139
55186
  setup() {
55140
- onMounted(() => {
55141
- if (this.isSheetActive) {
55142
- this.scrollToSheet();
55143
- }
55144
- });
55145
55187
  onPatched(() => {
55146
55188
  if (this.sheetNameRef.el && this.state.isEditing && this.editionState === "initializing") {
55147
55189
  this.editionState = "editing";
@@ -55149,6 +55191,11 @@ class BottomBarSheet extends Component {
55149
55191
  }
55150
55192
  });
55151
55193
  this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
55194
+ useEffect((sheetId) => {
55195
+ if (this.props.sheetId === sheetId) {
55196
+ this.scrollToSheet();
55197
+ }
55198
+ }, () => [this.env.model.getters.getActiveSheetId()]);
55152
55199
  }
55153
55200
  focusInputAndSelectContent() {
55154
55201
  if (!this.state.isEditing || !this.sheetNameRef.el)
@@ -55160,7 +55207,10 @@ class BottomBarSheet extends Component {
55160
55207
  }
55161
55208
  }
55162
55209
  scrollToSheet() {
55163
- this.sheetDivRef.el?.scrollIntoView?.();
55210
+ this.sheetDivRef.el?.scrollIntoView?.({
55211
+ behavior: "smooth",
55212
+ inline: "nearest",
55213
+ });
55164
55214
  }
55165
55215
  onFocusOut() {
55166
55216
  if (this.state.isEditing && this.editionState !== "initializing") {
@@ -55190,11 +55240,11 @@ class BottomBarSheet extends Component {
55190
55240
  if (ev.key === "Enter") {
55191
55241
  ev.preventDefault();
55192
55242
  this.stopEdition();
55193
- this.DOMFocusableElementStore.focus();
55243
+ this.DOMFocusableElementStore.focusableElement?.focus();
55194
55244
  }
55195
55245
  if (ev.key === "Escape") {
55196
55246
  this.cancelEdition();
55197
- this.DOMFocusableElementStore.focus();
55247
+ this.DOMFocusableElementStore.focusableElement?.focus();
55198
55248
  }
55199
55249
  }
55200
55250
  onMouseEventSheetName(ev) {
@@ -56427,7 +56477,6 @@ css /* scss */ `
56427
56477
  height: fit-content;
56428
56478
  margin-top: -1px;
56429
56479
  border: 1px solid;
56430
- z-index: ${ComponentsImportance.TopBarComposer};
56431
56480
 
56432
56481
  .o-composer:empty:not(:focus):not(.active)::before {
56433
56482
  content: url("data:image/svg+xml,${encodeURIComponent(FX_SVG)}");
@@ -56469,6 +56518,7 @@ class TopBarComposer extends Component {
56469
56518
  }
56470
56519
  return cssPropertiesToCss({
56471
56520
  "border-color": SELECTION_BORDER_COLOR,
56521
+ "z-index": String(ComponentsImportance.TopBarComposer),
56472
56522
  });
56473
56523
  }
56474
56524
  get delimitation() {
@@ -60252,7 +60302,12 @@ function createSharedStrings(strings) {
60252
60302
  ["count", strings.length],
60253
60303
  ["uniqueCount", strings.length],
60254
60304
  ];
60255
- const stringNodes = strings.map((string) => escapeXml /*xml*/ `<si><t>${string}</t></si>`);
60305
+ const stringNodes = strings.map((string) => {
60306
+ if (string.trim() !== string) {
60307
+ return escapeXml /*xml*/ `<si><t xml:space="preserve">${string}</t></si>`;
60308
+ }
60309
+ return escapeXml /*xml*/ `<si><t>${string}</t></si>`;
60310
+ });
60256
60311
  const xml = escapeXml /*xml*/ `
60257
60312
  <sst ${formatAttributes(namespaces)}>
60258
60313
  ${joinXmlNodes(stringNodes)}
@@ -60903,6 +60958,8 @@ const helpers = {
60903
60958
  expandZoneOnInsertion,
60904
60959
  reduceZoneOnDeletion,
60905
60960
  unquote,
60961
+ isNumber,
60962
+ isDateTime,
60906
60963
  };
60907
60964
  const links = {
60908
60965
  isMarkdownLink,
@@ -60976,6 +61033,6 @@ const constants = {
60976
61033
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, 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 };
60977
61034
 
60978
61035
 
60979
- __info__.version = "17.2.29";
60980
- __info__.date = "2024-12-05T10:39:14.167Z";
60981
- __info__.hash = "7b4b898";
61036
+ __info__.version = "17.2.31";
61037
+ __info__.date = "2025-01-14T11:31:09.035Z";
61038
+ __info__.hash = "306dbf7";