@odoo/o-spreadsheet 18.0.8 → 18.0.9

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 18.0.8
6
- * @date 2024-12-19T07:50:36.150Z
7
- * @hash 7cf34a6
5
+ * @version 18.0.9
6
+ * @date 2025-01-14T11:33:47.429Z
7
+ * @hash 0c5220e
8
8
  */
9
9
 
10
10
  'use strict';
@@ -3542,6 +3542,7 @@ exports.CommandResult = void 0;
3542
3542
  CommandResult["SheetIsHidden"] = "SheetIsHidden";
3543
3543
  CommandResult["InvalidTableResize"] = "InvalidTableResize";
3544
3544
  CommandResult["PivotIdNotFound"] = "PivotIdNotFound";
3545
+ CommandResult["PivotInError"] = "PivotInError";
3545
3546
  CommandResult["EmptyName"] = "EmptyName";
3546
3547
  CommandResult["ValueCellIsInvalidFormula"] = "ValueCellIsInvalidFormula";
3547
3548
  CommandResult["InvalidDefinition"] = "InvalidDefinition";
@@ -9388,9 +9389,9 @@ function getTrendDatasetForBarChart(config, dataset) {
9388
9389
  if (!newValues.length) {
9389
9390
  return;
9390
9391
  }
9391
- return getFullTrendingLineDataSet(dataset, config, newValues);
9392
+ return getFullTrendingLineDataSet(dataset, config, newValues, newLabels);
9392
9393
  }
9393
- function getFullTrendingLineDataSet(dataset, config, data) {
9394
+ function getFullTrendingLineDataSet(dataset, config, data, labels) {
9394
9395
  const defaultBorderColor = colorToRGBA(dataset.backgroundColor);
9395
9396
  defaultBorderColor.a = 1;
9396
9397
  const borderColor = config.color || lightenColor(rgbaToHex(defaultBorderColor), 0.5);
@@ -9399,7 +9400,7 @@ function getFullTrendingLineDataSet(dataset, config, data) {
9399
9400
  xAxisID: TREND_LINE_XAXIS_ID,
9400
9401
  yAxisID: dataset.yAxisID,
9401
9402
  label: dataset.label ? _t("Trend line for %s", dataset.label) : "",
9402
- data,
9403
+ data: data.map((v, i) => ({ x: labels[i], y: v })),
9403
9404
  order: -1,
9404
9405
  showLine: true,
9405
9406
  pointRadius: 0,
@@ -19570,6 +19571,17 @@ const TEXT = {
19570
19571
  },
19571
19572
  isExported: true,
19572
19573
  };
19574
+ // -----------------------------------------------------------------------------
19575
+ // VALUE
19576
+ // -----------------------------------------------------------------------------
19577
+ const VALUE = {
19578
+ description: _t("Converts a string to a numeric value."),
19579
+ args: [arg("value (number)", _t("the string to be converted"))],
19580
+ compute: function (value) {
19581
+ return toNumber(value, this.locale);
19582
+ },
19583
+ isExported: true,
19584
+ };
19573
19585
 
19574
19586
  var text = /*#__PURE__*/Object.freeze({
19575
19587
  __proto__: null,
@@ -19592,7 +19604,8 @@ var text = /*#__PURE__*/Object.freeze({
19592
19604
  TEXT: TEXT,
19593
19605
  TEXTJOIN: TEXTJOIN,
19594
19606
  TRIM: TRIM,
19595
- UPPER: UPPER
19607
+ UPPER: UPPER,
19608
+ VALUE: VALUE
19596
19609
  });
19597
19610
 
19598
19611
  // -----------------------------------------------------------------------------
@@ -19856,14 +19869,11 @@ autoCompleteProviders.add("functions", {
19856
19869
  });
19857
19870
 
19858
19871
  class DOMFocusableElementStore {
19859
- mutators = ["setFocusableElement", "focus"];
19872
+ mutators = ["setFocusableElement"];
19860
19873
  focusableElement = undefined;
19861
19874
  setFocusableElement(element) {
19862
19875
  this.focusableElement = element;
19863
19876
  }
19864
- focus() {
19865
- this.focusableElement?.focus();
19866
- }
19867
19877
  }
19868
19878
 
19869
19879
  /**
@@ -20828,7 +20838,7 @@ class Composer extends owl.Component {
20828
20838
  if (document.activeElement === this.contentHelper.el &&
20829
20839
  this.props.composerStore.editionMode === "inactive" &&
20830
20840
  !this.props.isDefaultFocus) {
20831
- this.DOMFocusableElementStore.focus();
20841
+ this.DOMFocusableElementStore.focusableElement?.focus();
20832
20842
  }
20833
20843
  });
20834
20844
  owl.useEffect(() => {
@@ -24412,7 +24422,7 @@ function extractStyle(cell, data) {
24412
24422
  vertical: style.verticalAlign
24413
24423
  ? V_ALIGNMENT_EXPORT_CONVERSION_MAP[style.verticalAlign]
24414
24424
  : undefined,
24415
- wrapText: style.wrapping === "wrap" || undefined,
24425
+ wrapText: style.wrapping === "wrap" || cell.content?.includes(NEWLINE) ? true : undefined,
24416
24426
  },
24417
24427
  };
24418
24428
  styles.font["strike"] = !!style?.strikethrough || undefined;
@@ -24635,7 +24645,7 @@ function convertFigure(figure, id, sheetData) {
24635
24645
  return undefined;
24636
24646
  }
24637
24647
  function isChartData(data) {
24638
- return "dataSets" in data;
24648
+ return "dataSets" in data && data.dataSets.length > 0;
24639
24649
  }
24640
24650
  function isImageData(data) {
24641
24651
  return "imageSrc" in data;
@@ -24874,9 +24884,8 @@ function convertRows(sheet, numberOfRows, headerGroups) {
24874
24884
  }
24875
24885
  return rows;
24876
24886
  }
24877
- /** Remove newlines (\n) in shared strings, We do not support them */
24878
24887
  function convertSharedStrings(xlsxSharedStrings) {
24879
- return xlsxSharedStrings.map((str) => str.replace(/\n/g, ""));
24888
+ return xlsxSharedStrings.map(replaceNewLines);
24880
24889
  }
24881
24890
  function convertCells(sheet, data, sheetDims, warningManager) {
24882
24891
  const cells = {};
@@ -25977,15 +25986,10 @@ class XlsxMiscExtractor extends XlsxBaseExtractor {
25977
25986
  getSharedStrings() {
25978
25987
  return this.mapOnElements({ parent: this.rootFile.file.xml, query: "si" }, (ssElement) => {
25979
25988
  // Shared string can either be a simple text, or a rich text (text with formatting, possibly in multiple parts)
25980
- if (ssElement.children[0].tagName === "t") {
25981
- return this.extractTextContent(ssElement) || "";
25982
- }
25983
25989
  // We don't support rich text formatting, we'll only extract the text
25984
- else {
25985
- return this.mapOnElements({ parent: ssElement, query: "t" }, (textElement) => {
25986
- return this.extractTextContent(textElement) || "";
25987
- }).join("");
25988
- }
25990
+ return this.mapOnElements({ parent: ssElement, query: "t" }, (textElement) => {
25991
+ return this.extractTextContent(textElement) || "";
25992
+ }).join("");
25989
25993
  });
25990
25994
  }
25991
25995
  }
@@ -28338,7 +28342,7 @@ function getChartDatasetValues(getters, dataSets) {
28338
28342
  // then using the classical aggregation method to sum the values.
28339
28343
  data.fill(1);
28340
28344
  }
28341
- else if (data.every((cell) => cell === undefined || cell === null || !isNumber(cell.toString(), getters.getLocale()))) {
28345
+ else if (data.every((cell) => cell === undefined || cell === null || !isNumber(cell.toString(), DEFAULT_LOCALE))) {
28342
28346
  continue;
28343
28347
  }
28344
28348
  datasetValues.push({ data, label });
@@ -28914,12 +28918,12 @@ function getTrendDatasetForLineChart(config, dataset, axisType, locale) {
28914
28918
  }
28915
28919
  const numberOfStep = 5 * labels.length;
28916
28920
  const step = (xmax - xmin) / numberOfStep;
28917
- const newLabels = range(xmin, xmax + step / 2, step);
28918
- const newValues = interpolateData(config, filteredValues, filteredLabels, newLabels);
28919
- if (!newValues.length) {
28921
+ const trendLabels = range(xmin, xmax + step / 2, step);
28922
+ const trendValues = interpolateData(config, filteredValues, filteredLabels, trendLabels);
28923
+ if (!trendValues.length) {
28920
28924
  return;
28921
28925
  }
28922
- return getFullTrendingLineDataSet(dataset, config, newValues);
28926
+ return getFullTrendingLineDataSet(dataset, config, trendValues, trendLabels);
28923
28927
  }
28924
28928
  function createLineOrScatterChartRuntime(chart, getters) {
28925
28929
  const axisType = getChartAxisType(chart, getters);
@@ -29036,8 +29040,16 @@ function createLineOrScatterChartRuntime(chart, getters) {
29036
29040
  config.options.scales.x.type = "linear";
29037
29041
  config.options.scales.x.ticks.callback = (value) => formatValue(value, { format: labelFormat, locale });
29038
29042
  config.options.plugins.tooltip.callbacks.label = (tooltipItem) => {
29039
- const dataSetPoint = dataSetsValues[tooltipItem.datasetIndex].data[tooltipItem.dataIndex];
29040
- let label = tooltipItem.label || labelValues.values[tooltipItem.dataIndex];
29043
+ let dataSetPoint;
29044
+ let label;
29045
+ if (tooltipItem.dataset.xAxisID === TREND_LINE_XAXIS_ID) {
29046
+ dataSetPoint = dataSetsValues[tooltipItem.datasetIndex].data[tooltipItem.dataIndex].y;
29047
+ label = "";
29048
+ }
29049
+ else {
29050
+ dataSetPoint = dataSetsValues[tooltipItem.datasetIndex].data[tooltipItem.dataIndex];
29051
+ label = labelValues.values[tooltipItem.dataIndex];
29052
+ }
29041
29053
  if (isNumber(label, locale)) {
29042
29054
  label = toNumber(label, locale);
29043
29055
  }
@@ -29108,16 +29120,18 @@ function createLineOrScatterChartRuntime(chart, getters) {
29108
29120
  }
29109
29121
  }
29110
29122
  if (trendDatasets.length) {
29111
- /* We add a second x axis here to draw the trend lines, with the labels length being
29112
- * set so that the second axis points match the classical x axis
29113
- */
29114
29123
  config.options.scales[TREND_LINE_XAXIS_ID] = {
29115
29124
  ...xAxis,
29116
- type: "category",
29117
- labels: range(0, maxLength).map((x) => x.toString()),
29118
- offset: false,
29119
29125
  display: false,
29120
29126
  };
29127
+ if (axisType === "category" || axisType === "time") {
29128
+ /* We add a second x axis here to draw the trend lines, with the labels length being
29129
+ * set so that the second axis points match the classical x axis
29130
+ */
29131
+ config.options.scales[TREND_LINE_XAXIS_ID]["type"] = "category";
29132
+ config.options.scales[TREND_LINE_XAXIS_ID]["labels"] = range(0, maxLength).map((x) => x.toString());
29133
+ config.options.scales[TREND_LINE_XAXIS_ID]["offset"] = false;
29134
+ }
29121
29135
  /* These datasets must be inserted after the original datasets to ensure the way we
29122
29136
  * distinguish the originals and trendLine datasets after
29123
29137
  */
@@ -29608,7 +29622,11 @@ function createGaugeChartRuntime(chart, getters) {
29608
29622
  colors.push(chartColors.upperColor);
29609
29623
  return {
29610
29624
  background: getters.getStyleOfSingleCellChart(chart.background, dataRange).background,
29611
- title: chart.title ?? { text: "" },
29625
+ title: {
29626
+ ...chart.title,
29627
+ // chart titles are extracted from .json files and they are translated at runtime here
29628
+ text: _t(chart.title.text ?? ""),
29629
+ },
29612
29630
  minValue: {
29613
29631
  value: minValue,
29614
29632
  label: formatValue(minValue, { locale, format }),
@@ -34289,12 +34307,20 @@ function fontSizeMenuBuilder() {
34289
34307
  });
34290
34308
  }
34291
34309
  function isAutomaticFormatSelected(env) {
34292
- const activeCell = env.model.getters.getCell(env.model.getters.getActivePosition());
34293
- return !activeCell || !activeCell.format;
34310
+ const activePosition = env.model.getters.getActivePosition();
34311
+ const pivotCell = env.model.getters.getPivotCellFromPosition(activePosition);
34312
+ if (pivotCell.type === "VALUE") {
34313
+ return !env.model.getters.getEvaluatedCell(activePosition).format;
34314
+ }
34315
+ return !env.model.getters.getCell(activePosition)?.format;
34294
34316
  }
34295
34317
  function isFormatSelected(env, format) {
34296
- const activeCell = env.model.getters.getCell(env.model.getters.getActivePosition());
34297
- return activeCell?.format === format;
34318
+ const activePosition = env.model.getters.getActivePosition();
34319
+ const pivotCell = env.model.getters.getPivotCellFromPosition(activePosition);
34320
+ if (pivotCell.type === "VALUE") {
34321
+ return env.model.getters.getEvaluatedCell(activePosition).format === format;
34322
+ }
34323
+ return env.model.getters.getCell(activePosition)?.format === format;
34298
34324
  }
34299
34325
  function isFontSizeSelected(env, fontSize) {
34300
34326
  const currentFontSize = env.model.getters.getCurrentStyle().fontSize || DEFAULT_FONT_SIZE;
@@ -39977,6 +40003,10 @@ css /* scss */ `
39977
40003
  border: 1px solid #d8dadd;
39978
40004
  color: #374151;
39979
40005
  }
40006
+
40007
+ table {
40008
+ table-layout: fixed;
40009
+ }
39980
40010
  }
39981
40011
  `;
39982
40012
  class CustomCurrencyPanel extends owl.Component {
@@ -42212,16 +42242,21 @@ class TextInput extends owl.Component {
42212
42242
  }
42213
42243
  this.inputRef.el?.blur();
42214
42244
  }
42215
- focusInputAndSelectContent() {
42216
- const inputEl = this.inputRef.el;
42217
- if (!inputEl)
42218
- return;
42219
- // The onFocus event selects all text in the input.
42220
- // The subsequent mouseup event can deselect this text,
42221
- // so t-on-mouseup.prevent.stop is used to prevent this
42222
- // default behavior and preserve the selection.
42223
- inputEl.focus();
42224
- inputEl.select();
42245
+ onMouseDown(ev) {
42246
+ // Stop the event if the input is not focused, we handle everything in onMouseUp
42247
+ if (ev.target !== document.activeElement) {
42248
+ ev.preventDefault();
42249
+ ev.stopPropagation();
42250
+ }
42251
+ }
42252
+ onMouseUp(ev) {
42253
+ const target = ev.target;
42254
+ if (target !== document.activeElement) {
42255
+ target.focus();
42256
+ target.select();
42257
+ ev.preventDefault();
42258
+ ev.stopPropagation();
42259
+ }
42225
42260
  }
42226
42261
  }
42227
42262
 
@@ -42699,7 +42734,16 @@ class PivotTitleSection extends owl.Component {
42699
42734
  newPivotId,
42700
42735
  newSheetId,
42701
42736
  });
42702
- const text = result.isSuccessful ? _t("Pivot duplicated.") : _t("Pivot duplication failed");
42737
+ let text;
42738
+ if (result.isSuccessful) {
42739
+ text = _t("Pivot duplicated.");
42740
+ }
42741
+ else if (result.isCancelledBecause("PivotInError" /* CommandResult.PivotInError */)) {
42742
+ text = _t("Cannot duplicate a pivot in error.");
42743
+ }
42744
+ else {
42745
+ text = _t("Pivot duplication failed.");
42746
+ }
42703
42747
  const type = result.isSuccessful ? "success" : "danger";
42704
42748
  this.env.notifyUser({
42705
42749
  text,
@@ -43997,7 +44041,9 @@ class PivotSidePanelStore extends SpreadsheetStore {
43997
44041
  pivot: this.draft,
43998
44042
  });
43999
44043
  this.draft = null;
44000
- if (!this.alreadyNotified && !this.isDynamicPivotInViewport()) {
44044
+ if (!this.alreadyNotified &&
44045
+ !this.isDynamicPivotInViewport() &&
44046
+ this.isStaticPivotInViewport()) {
44001
44047
  const formulaId = this.getters.getPivotFormulaId(this.pivotId);
44002
44048
  const pivotExample = `=PIVOT(${formulaId})`;
44003
44049
  this.alreadyNotified = true;
@@ -44064,6 +44110,18 @@ class PivotSidePanelStore extends SpreadsheetStore {
44064
44110
  }
44065
44111
  return false;
44066
44112
  }
44113
+ isStaticPivotInViewport() {
44114
+ for (const position of this.getters.getVisibleCellPositions()) {
44115
+ const cell = this.getters.getCell(position);
44116
+ if (cell?.isFormula) {
44117
+ const pivotFunction = getFirstPivotFunction(cell.compiledFormula.tokens);
44118
+ if (pivotFunction && pivotFunction.functionName !== "PIVOT") {
44119
+ return true;
44120
+ }
44121
+ }
44122
+ }
44123
+ return false;
44124
+ }
44067
44125
  addDefaultDateTimeGranularity(fields, definition) {
44068
44126
  const { columns, rows } = definition;
44069
44127
  const columnsWithGranularity = deepCopy(columns);
@@ -49450,7 +49508,7 @@ class Grid extends owl.Component {
49450
49508
  this.cellPopovers = useStore(CellPopoverStore);
49451
49509
  owl.useEffect(() => {
49452
49510
  if (!this.sidePanel.isOpen) {
49453
- this.DOMFocusableElementStore.focus();
49511
+ this.DOMFocusableElementStore.focusableElement?.focus();
49454
49512
  }
49455
49513
  }, () => [this.sidePanel.isOpen]);
49456
49514
  }
@@ -49654,7 +49712,7 @@ class Grid extends owl.Component {
49654
49712
  focusDefaultElement() {
49655
49713
  if (!this.env.model.getters.getSelectedFigureId() &&
49656
49714
  this.composerFocusStore.activeComposer.editionMode === "inactive") {
49657
- this.DOMFocusableElementStore.focus();
49715
+ this.DOMFocusableElementStore.focusableElement?.focus();
49658
49716
  }
49659
49717
  }
49660
49718
  get gridEl() {
@@ -50218,10 +50276,34 @@ class BordersPlugin extends CorePlugin {
50218
50276
  const elements = [...cmd.elements].sort((a, b) => b - a);
50219
50277
  for (const group of groupConsecutive(elements)) {
50220
50278
  if (cmd.dimension === "COL") {
50221
- this.shiftBordersHorizontally(cmd.sheetId, group[group.length - 1] + 1, -group.length);
50279
+ if (group[0] >= this.getters.getNumberCols(cmd.sheetId)) {
50280
+ for (let row = 0; row < this.getters.getNumberRows(cmd.sheetId); row++) {
50281
+ this.history.update("borders", cmd.sheetId, group[0] + 1, row, "vertical", undefined);
50282
+ }
50283
+ }
50284
+ if (group[group.length - 1] === 0) {
50285
+ for (let row = 0; row < this.getters.getNumberRows(cmd.sheetId); row++) {
50286
+ this.history.update("borders", cmd.sheetId, 0, row, "vertical", undefined);
50287
+ }
50288
+ }
50289
+ const zone = this.getters.getColsZone(cmd.sheetId, group[group.length - 1] + 1, group[0]);
50290
+ this.clearInsideBorders(cmd.sheetId, [zone]);
50291
+ this.shiftBordersHorizontally(cmd.sheetId, group[0] + 1, -group.length);
50222
50292
  }
50223
50293
  else {
50224
- this.shiftBordersVertically(cmd.sheetId, group[group.length - 1] + 1, -group.length);
50294
+ if (group[0] >= this.getters.getNumberRows(cmd.sheetId)) {
50295
+ for (let col = 0; col < this.getters.getNumberCols(cmd.sheetId); col++) {
50296
+ this.history.update("borders", cmd.sheetId, col, group[0] + 1, "horizontal", undefined);
50297
+ }
50298
+ }
50299
+ if (group[group.length - 1] === 0) {
50300
+ for (let col = 0; col < this.getters.getNumberCols(cmd.sheetId); col++) {
50301
+ this.history.update("borders", cmd.sheetId, col, 0, "horizontal", undefined);
50302
+ }
50303
+ }
50304
+ const zone = this.getters.getRowsZone(cmd.sheetId, group[group.length - 1] + 1, group[0]);
50305
+ this.clearInsideBorders(cmd.sheetId, [zone]);
50306
+ this.shiftBordersVertically(cmd.sheetId, group[0] + 1, -group.length);
50225
50307
  }
50226
50308
  }
50227
50309
  break;
@@ -50528,6 +50610,18 @@ class BordersPlugin extends CorePlugin {
50528
50610
  }
50529
50611
  }
50530
50612
  }
50613
+ /**
50614
+ * Remove the borders inside of a zone
50615
+ */
50616
+ clearInsideBorders(sheetId, zones) {
50617
+ for (let zone of zones) {
50618
+ for (let row = zone.top; row <= zone.bottom; row++) {
50619
+ for (let col = zone.left; col <= zone.right; col++) {
50620
+ this.history.update("borders", sheetId, col, row, undefined);
50621
+ }
50622
+ }
50623
+ }
50624
+ }
50531
50625
  /**
50532
50626
  * Add a border to the existing one to a cell
50533
50627
  */
@@ -61155,6 +61249,9 @@ class Session extends EventBus {
61155
61249
  }
61156
61250
  }
61157
61251
  this.acknowledge(message);
61252
+ if (message.type === "REMOTE_REVISION" && message.clientId === this.clientId) {
61253
+ return;
61254
+ }
61158
61255
  this.trigger("collaborative-event-received");
61159
61256
  }
61160
61257
  onClientMoved(message) {
@@ -61769,6 +61866,19 @@ class HeaderVisibilityUIPlugin extends UIPlugin {
61769
61866
 
61770
61867
  class InsertPivotPlugin extends UIPlugin {
61771
61868
  static getters = [];
61869
+ allowDispatch(cmd) {
61870
+ switch (cmd.type) {
61871
+ case "DUPLICATE_PIVOT_IN_NEW_SHEET":
61872
+ if (!this.getters.isExistingPivot(cmd.pivotId)) {
61873
+ return "PivotIdNotFound" /* CommandResult.PivotIdNotFound */;
61874
+ }
61875
+ if (!this.getters.getPivot(cmd.pivotId).isValid()) {
61876
+ return "PivotInError" /* CommandResult.PivotInError */;
61877
+ }
61878
+ break;
61879
+ }
61880
+ return "Success" /* CommandResult.Success */;
61881
+ }
61772
61882
  handle(cmd) {
61773
61883
  switch (cmd.type) {
61774
61884
  case "INSERT_NEW_PIVOT":
@@ -65997,11 +66107,6 @@ class BottomBarSheet extends owl.Component {
65997
66107
  editionState = "initializing";
65998
66108
  DOMFocusableElementStore;
65999
66109
  setup() {
66000
- owl.onMounted(() => {
66001
- if (this.isSheetActive) {
66002
- this.scrollToSheet();
66003
- }
66004
- });
66005
66110
  owl.onPatched(() => {
66006
66111
  if (this.sheetNameRef.el && this.state.isEditing && this.editionState === "initializing") {
66007
66112
  this.editionState = "editing";
@@ -66010,6 +66115,11 @@ class BottomBarSheet extends owl.Component {
66010
66115
  });
66011
66116
  this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
66012
66117
  owl.useExternalListener(window, "click", () => (this.state.pickerOpened = false));
66118
+ owl.useEffect((sheetId) => {
66119
+ if (this.props.sheetId === sheetId) {
66120
+ this.scrollToSheet();
66121
+ }
66122
+ }, () => [this.env.model.getters.getActiveSheetId()]);
66013
66123
  }
66014
66124
  focusInputAndSelectContent() {
66015
66125
  if (!this.state.isEditing || !this.sheetNameRef.el)
@@ -66021,7 +66131,10 @@ class BottomBarSheet extends owl.Component {
66021
66131
  }
66022
66132
  }
66023
66133
  scrollToSheet() {
66024
- this.sheetDivRef.el?.scrollIntoView?.();
66134
+ this.sheetDivRef.el?.scrollIntoView?.({
66135
+ behavior: "smooth",
66136
+ inline: "nearest",
66137
+ });
66025
66138
  }
66026
66139
  onFocusOut() {
66027
66140
  if (this.state.isEditing && this.editionState !== "initializing") {
@@ -66051,11 +66164,11 @@ class BottomBarSheet extends owl.Component {
66051
66164
  if (ev.key === "Enter") {
66052
66165
  ev.preventDefault();
66053
66166
  this.stopEdition();
66054
- this.DOMFocusableElementStore.focus();
66167
+ this.DOMFocusableElementStore.focusableElement?.focus();
66055
66168
  }
66056
66169
  if (ev.key === "Escape") {
66057
66170
  this.cancelEdition();
66058
- this.DOMFocusableElementStore.focus();
66171
+ this.DOMFocusableElementStore.focusableElement?.focus();
66059
66172
  }
66060
66173
  }
66061
66174
  onMouseEventSheetName(ev) {
@@ -71679,7 +71792,12 @@ function createSharedStrings(strings) {
71679
71792
  ["count", strings.length],
71680
71793
  ["uniqueCount", strings.length],
71681
71794
  ];
71682
- const stringNodes = strings.map((string) => escapeXml /*xml*/ `<si><t>${string}</t></si>`);
71795
+ const stringNodes = strings.map((string) => {
71796
+ if (string.trim() !== string) {
71797
+ return escapeXml /*xml*/ `<si><t xml:space="preserve">${string}</t></si>`;
71798
+ }
71799
+ return escapeXml /*xml*/ `<si><t>${string}</t></si>`;
71800
+ });
71683
71801
  const xml = escapeXml /*xml*/ `
71684
71802
  <sst ${formatAttributes(namespaces)}>
71685
71803
  ${joinXmlNodes(stringNodes)}
@@ -71924,7 +72042,7 @@ class Model extends EventBus {
71924
72042
  // events
71925
72043
  this.setupSessionEvents();
71926
72044
  this.joinSession();
71927
- if (config.snapshotRequested) {
72045
+ if (config.snapshotRequested || (data["[Content_Types].xml"] && !this.getters.isReadonly())) {
71928
72046
  const startSnapshot = performance.now();
71929
72047
  console.debug("Snapshot requested");
71930
72048
  this.session.snapshot(this.exportData());
@@ -72422,6 +72540,8 @@ const helpers = {
72422
72540
  splitReference,
72423
72541
  formatTickValue,
72424
72542
  sanitizeSheetName,
72543
+ isNumber,
72544
+ isDateTime,
72425
72545
  };
72426
72546
  const links = {
72427
72547
  isMarkdownLink,
@@ -72557,6 +72677,6 @@ exports.tokenColors = tokenColors;
72557
72677
  exports.tokenize = tokenize;
72558
72678
 
72559
72679
 
72560
- __info__.version = "18.0.8";
72561
- __info__.date = "2024-12-19T07:50:36.150Z";
72562
- __info__.hash = "7cf34a6";
72680
+ __info__.version = "18.0.9";
72681
+ __info__.date = "2025-01-14T11:33:47.429Z";
72682
+ __info__.hash = "0c5220e";
@@ -2666,6 +2666,7 @@ declare const enum CommandResult {
2666
2666
  SheetIsHidden = "SheetIsHidden",
2667
2667
  InvalidTableResize = "InvalidTableResize",
2668
2668
  PivotIdNotFound = "PivotIdNotFound",
2669
+ PivotInError = "PivotInError",
2669
2670
  EmptyName = "EmptyName",
2670
2671
  ValueCellIsInvalidFormula = "ValueCellIsInvalidFormula",
2671
2672
  InvalidDefinition = "InvalidDefinition",
@@ -3664,6 +3665,10 @@ declare class BordersPlugin extends CorePlugin<BordersPluginState> implements Bo
3664
3665
  * Remove the borders of a zone
3665
3666
  */
3666
3667
  private clearBorders;
3668
+ /**
3669
+ * Remove the borders inside of a zone
3670
+ */
3671
+ private clearInsideBorders;
3667
3672
  /**
3668
3673
  * Add a border to the existing one to a cell
3669
3674
  */
@@ -5685,6 +5690,7 @@ declare class DateTime {
5685
5690
  setMinutes(minutes: number): number;
5686
5691
  setSeconds(seconds: number): number;
5687
5692
  }
5693
+ declare function isDateTime(str: string, locale: Locale): boolean;
5688
5694
 
5689
5695
  interface FormatWidth {
5690
5696
  availableWidth: number;
@@ -5730,6 +5736,13 @@ declare function lazy<T>(fn: (() => T) | T): Lazy<T>;
5730
5736
  */
5731
5737
  declare function deepEquals(o1: any, o2: any): boolean;
5732
5738
 
5739
+ /**
5740
+ * Return true if the argument is a "number string".
5741
+ *
5742
+ * Note that "" (empty string) does not count as a number string
5743
+ */
5744
+ declare function isNumber(value: string | undefined, locale: Locale): boolean;
5745
+
5733
5746
  interface ConstructorArgs {
5734
5747
  readonly zone: Readonly<Zone | UnboundedZone>;
5735
5748
  readonly parts: readonly RangePart[];
@@ -9560,7 +9573,8 @@ declare class TextInput extends Component<Props$j, SpreadsheetChildEnv> {
9560
9573
  setup(): void;
9561
9574
  onKeyDown(ev: KeyboardEvent): void;
9562
9575
  save(): void;
9563
- focusInputAndSelectContent(): void;
9576
+ onMouseDown(ev: MouseEvent): void;
9577
+ onMouseUp(ev: MouseEvent): void;
9564
9578
  }
9565
9579
 
9566
9580
  interface Props$i {
@@ -9831,6 +9845,7 @@ declare class PivotSidePanelStore extends SpreadsheetStore {
9831
9845
  discardPendingUpdate(): void;
9832
9846
  update(definitionUpdate: Partial<PivotCoreDefinition>): void;
9833
9847
  private isDynamicPivotInViewport;
9848
+ private isStaticPivotInViewport;
9834
9849
  private addDefaultDateTimeGranularity;
9835
9850
  private getUnusedGranularities;
9836
9851
  }
@@ -9899,7 +9914,10 @@ declare function getTrendDatasetForBarChart(config: TrendConfiguration, dataset:
9899
9914
  xAxisID: string;
9900
9915
  yAxisID: string | undefined;
9901
9916
  label: string;
9902
- data: number[];
9917
+ data: {
9918
+ x: number;
9919
+ y: number;
9920
+ }[];
9903
9921
  order: number;
9904
9922
  showLine: boolean;
9905
9923
  pointRadius: number;
@@ -12088,6 +12106,8 @@ declare const helpers: {
12088
12106
  splitReference: typeof splitReference;
12089
12107
  formatTickValue: typeof formatTickValue;
12090
12108
  sanitizeSheetName: typeof sanitizeSheetName;
12109
+ isNumber: typeof isNumber;
12110
+ isDateTime: typeof isDateTime;
12091
12111
  };
12092
12112
  declare const links: {
12093
12113
  isMarkdownLink: typeof isMarkdownLink;