@odoo/o-spreadsheet 18.4.13 → 18.4.14

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.4.13
6
- * @date 2025-10-07T10:00:55.413Z
7
- * @hash d4df70e
5
+ * @version 18.4.14
6
+ * @date 2025-10-16T06:39:40.249Z
7
+ * @hash bc55c40
8
8
  */
9
9
 
10
10
  'use strict';
@@ -3194,7 +3194,17 @@ function toNumberMatrix(data, argName) {
3194
3194
  return toMatrix(data).map((row) => {
3195
3195
  return row.map((cell) => {
3196
3196
  if (typeof cell.value !== "number") {
3197
- throw new EvaluationError(_t("Function [[FUNCTION_NAME]] expects number values for %s, but got a %s.", argName, typeof cell.value));
3197
+ let message = "";
3198
+ if (typeof cell === "object") {
3199
+ message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got an empty value.", argName);
3200
+ }
3201
+ else if (typeof cell === "string") {
3202
+ message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got a string.", argName);
3203
+ }
3204
+ else if (typeof cell === "boolean") {
3205
+ message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got a boolean.", argName);
3206
+ }
3207
+ throw new EvaluationError(message);
3198
3208
  }
3199
3209
  return cell.value;
3200
3210
  });
@@ -9082,7 +9092,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
9082
9092
  pasteCell(origin, target, clipboardOption) {
9083
9093
  const { sheetId, col, row } = target;
9084
9094
  const targetCell = this.getters.getEvaluatedCell(target);
9085
- const originFormat = origin?.format ?? origin.evaluatedCell.format;
9095
+ const originFormat = origin?.format || origin.evaluatedCell.format;
9086
9096
  if (clipboardOption?.pasteOption === "asValue") {
9087
9097
  this.dispatch("UPDATE_CELL", {
9088
9098
  ...target,
@@ -13179,7 +13189,7 @@ const GROWTH = {
13179
13189
  if (knownDataY.length === 0 || knownDataY[0].length === 0) {
13180
13190
  return new EvaluationError(emptyDataErrorMessage("known_data_y"));
13181
13191
  }
13182
- return expM(predictLinearValues(logM(toNumberMatrix(knownDataY, "the first argument (known_data_y)")), toNumberMatrix(knownDataX, "the second argument (known_data_x)"), toNumberMatrix(newDataX, "the third argument (new_data_y)"), toBoolean(b)));
13192
+ return expM(predictLinearValues(logM(toNumberMatrix(knownDataY, "known_data_y")), toNumberMatrix(knownDataX, "known_data_x"), toNumberMatrix(newDataX, "new_data_y"), toBoolean(b)));
13183
13193
  },
13184
13194
  };
13185
13195
  // -----------------------------------------------------------------------------
@@ -13252,7 +13262,7 @@ const LINEST = {
13252
13262
  if (dataY.length === 0 || dataY[0].length === 0) {
13253
13263
  return new EvaluationError(emptyDataErrorMessage("data_y"));
13254
13264
  }
13255
- return fullLinearRegression(toNumberMatrix(dataX, "the first argument (data_y)"), toNumberMatrix(dataY, "the second argument (data_x)"), toBoolean(calculateB), toBoolean(verbose));
13265
+ return fullLinearRegression(toNumberMatrix(dataX, "data_x"), toNumberMatrix(dataY, "data_y"), toBoolean(calculateB), toBoolean(verbose));
13256
13266
  },
13257
13267
  isExported: true,
13258
13268
  };
@@ -13271,7 +13281,7 @@ const LOGEST = {
13271
13281
  if (dataY.length === 0 || dataY[0].length === 0) {
13272
13282
  return new EvaluationError(emptyDataErrorMessage("data_y"));
13273
13283
  }
13274
- const coeffs = fullLinearRegression(toNumberMatrix(dataX, "the second argument (data_x)"), logM(toNumberMatrix(dataY, "the first argument (data_y)")), toBoolean(calculateB), toBoolean(verbose));
13284
+ const coeffs = fullLinearRegression(toNumberMatrix(dataX, "data_x"), logM(toNumberMatrix(dataY, "data_y")), toBoolean(calculateB), toBoolean(verbose));
13275
13285
  for (let i = 0; i < coeffs.length; i++) {
13276
13286
  coeffs[i][0] = Math.exp(coeffs[i][0]);
13277
13287
  }
@@ -13885,7 +13895,7 @@ const TREND = {
13885
13895
  if (knownDataY.length === 0 || knownDataY[0].length === 0) {
13886
13896
  return new EvaluationError(emptyDataErrorMessage("known_data_y"));
13887
13897
  }
13888
- return predictLinearValues(toNumberMatrix(knownDataY, "the first argument (known_data_y)"), toNumberMatrix(knownDataX, "the second argument (known_data_x)"), toNumberMatrix(newDataX, "the third argument (new_data_y)"), toBoolean(b));
13898
+ return predictLinearValues(toNumberMatrix(knownDataY, "known_data_y"), toNumberMatrix(knownDataX, "known_data_x"), toNumberMatrix(newDataX, "new_data_y"), toBoolean(b));
13889
13899
  },
13890
13900
  };
13891
13901
  // -----------------------------------------------------------------------------
@@ -21879,6 +21889,10 @@ const chartShowValuesPlugin = {
21879
21889
  }
21880
21890
  const ctx = chart.ctx;
21881
21891
  ctx.save();
21892
+ const { left, top, height, width } = chart.chartArea;
21893
+ ctx.beginPath();
21894
+ ctx.rect(left, top, width, height);
21895
+ ctx.clip();
21882
21896
  ctx.textAlign = "center";
21883
21897
  ctx.textBaseline = "middle";
21884
21898
  ctx.miterLimit = 1; // Avoid sharp artifacts on strokeText
@@ -22914,7 +22928,18 @@ class ChartJsComponent extends owl.Component {
22914
22928
  this.chart.update();
22915
22929
  }
22916
22930
  hasChartDataChanged() {
22917
- return !deepEquals(this.currentRuntime.chartJsConfig.data, this.chartRuntime.chartJsConfig.data);
22931
+ return !deepEquals(this.getChartDataInRuntime(this.currentRuntime), this.getChartDataInRuntime(this.chartRuntime));
22932
+ }
22933
+ getChartDataInRuntime(runtime) {
22934
+ const data = runtime.chartJsConfig.data;
22935
+ return {
22936
+ labels: data.labels,
22937
+ dataset: data.datasets.map((dataset) => ({
22938
+ data: dataset.data,
22939
+ label: dataset.label,
22940
+ tree: dataset.tree,
22941
+ })),
22942
+ };
22918
22943
  }
22919
22944
  enableAnimationInChartData(chartData) {
22920
22945
  return {
@@ -24536,6 +24561,7 @@ function getChartTimeOptions(labels, labelFormat, locale) {
24536
24561
  parser: luxonFormat,
24537
24562
  displayFormats,
24538
24563
  unit: timeUnit ?? false,
24564
+ tooltipFormat: luxonFormat,
24539
24565
  };
24540
24566
  }
24541
24567
  /**
@@ -25616,6 +25642,7 @@ function getLineChartScales(definition, args) {
25616
25642
  };
25617
25643
  Object.assign(scales.x, axis);
25618
25644
  scales.x.ticks.maxTicksLimit = 15;
25645
+ delete scales?.x?.ticks?.callback;
25619
25646
  }
25620
25647
  else if (axisType === "linear") {
25621
25648
  scales.x.type = "linear";
@@ -30664,7 +30691,7 @@ class ChartDashboardMenu extends owl.Component {
30664
30691
  }
30665
30692
  openContextMenu(ev) {
30666
30693
  this.menuState.isOpen = true;
30667
- this.menuState.anchorRect = { x: ev.clientX, y: ev.clientY, width: 0, height: 0 };
30694
+ this.menuState.anchorRect = getBoundingRectAsPOJO(ev.currentTarget);
30668
30695
  this.menuState.menuItems = getChartMenuActions(this.props.figureUI.id, () => { }, this.env);
30669
30696
  }
30670
30697
  get fullScreenMenuItem() {
@@ -37466,6 +37493,74 @@ function getPath2D(svgPath) {
37466
37493
  return path2D;
37467
37494
  }
37468
37495
 
37496
+ /**
37497
+ * Get the relative path between two files
37498
+ *
37499
+ * Eg.:
37500
+ * from "folder1/file1.txt" to "folder2/file2.txt" => "../folder2/file2.txt"
37501
+ */
37502
+ function getRelativePath(from, to) {
37503
+ const fromPathParts = from.split("/");
37504
+ const toPathParts = to.split("/");
37505
+ let relPath = "";
37506
+ let startIndex = 0;
37507
+ for (let i = 0; i < fromPathParts.length - 1; i++) {
37508
+ if (fromPathParts[i] === toPathParts[i]) {
37509
+ startIndex++;
37510
+ }
37511
+ else {
37512
+ relPath += "../";
37513
+ }
37514
+ }
37515
+ relPath += toPathParts.slice(startIndex).join("/");
37516
+ return relPath;
37517
+ }
37518
+ /**
37519
+ * Convert an array of element into an object where the objects keys were the elements position in the array.
37520
+ * Can give an offset as argument, and all the array indexes will we shifted by this offset in the returned object.
37521
+ *
37522
+ * eg. : ["a", "b"] => {0:"a", 1:"b"}
37523
+ */
37524
+ function arrayToObject(array, indexOffset = 0) {
37525
+ const obj = {};
37526
+ for (let i = 0; i < array.length; i++) {
37527
+ if (array[i]) {
37528
+ obj[i + indexOffset] = array[i];
37529
+ }
37530
+ }
37531
+ return obj;
37532
+ }
37533
+ /**
37534
+ * In xlsx we can have string with unicode characters with the format _x00fa_.
37535
+ * Replace with characters understandable by JS
37536
+ */
37537
+ function fixXlsxUnicode(str) {
37538
+ return str.replace(/_x([0-9a-zA-Z]{4})_/g, (match, code) => {
37539
+ return String.fromCharCode(parseInt(code, 16));
37540
+ });
37541
+ }
37542
+ /** Get a header in the SheetData. Create the header if it doesn't exist in the SheetData */
37543
+ function getSheetDataHeader(sheetData, dimension, index) {
37544
+ if (dimension === "COL") {
37545
+ if (!sheetData.cols[index]) {
37546
+ sheetData.cols[index] = {};
37547
+ }
37548
+ return sheetData.cols[index];
37549
+ }
37550
+ if (!sheetData.rows[index]) {
37551
+ sheetData.rows[index] = {};
37552
+ }
37553
+ return sheetData.rows[index];
37554
+ }
37555
+ /** Prefix the string by "=" if the string looks like a formula */
37556
+ function prefixFormulaWithEqual(formula) {
37557
+ if (formula[0] === "=") {
37558
+ return formula;
37559
+ }
37560
+ const tokens = tokenize(formula);
37561
+ return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
37562
+ }
37563
+
37469
37564
  /**
37470
37565
  * Map of the different types of conversions warnings and their name in error messages
37471
37566
  */
@@ -37988,66 +38083,6 @@ function hexaToInt(hex) {
37988
38083
  */
37989
38084
  const DEFAULT_SYSTEM_COLOR = "FF000000";
37990
38085
 
37991
- /**
37992
- * Get the relative path between two files
37993
- *
37994
- * Eg.:
37995
- * from "folder1/file1.txt" to "folder2/file2.txt" => "../folder2/file2.txt"
37996
- */
37997
- function getRelativePath(from, to) {
37998
- const fromPathParts = from.split("/");
37999
- const toPathParts = to.split("/");
38000
- let relPath = "";
38001
- let startIndex = 0;
38002
- for (let i = 0; i < fromPathParts.length - 1; i++) {
38003
- if (fromPathParts[i] === toPathParts[i]) {
38004
- startIndex++;
38005
- }
38006
- else {
38007
- relPath += "../";
38008
- }
38009
- }
38010
- relPath += toPathParts.slice(startIndex).join("/");
38011
- return relPath;
38012
- }
38013
- /**
38014
- * Convert an array of element into an object where the objects keys were the elements position in the array.
38015
- * Can give an offset as argument, and all the array indexes will we shifted by this offset in the returned object.
38016
- *
38017
- * eg. : ["a", "b"] => {0:"a", 1:"b"}
38018
- */
38019
- function arrayToObject(array, indexOffset = 0) {
38020
- const obj = {};
38021
- for (let i = 0; i < array.length; i++) {
38022
- if (array[i]) {
38023
- obj[i + indexOffset] = array[i];
38024
- }
38025
- }
38026
- return obj;
38027
- }
38028
- /**
38029
- * In xlsx we can have string with unicode characters with the format _x00fa_.
38030
- * Replace with characters understandable by JS
38031
- */
38032
- function fixXlsxUnicode(str) {
38033
- return str.replace(/_x([0-9a-zA-Z]{4})_/g, (match, code) => {
38034
- return String.fromCharCode(parseInt(code, 16));
38035
- });
38036
- }
38037
- /** Get a header in the SheetData. Create the header if it doesn't exist in the SheetData */
38038
- function getSheetDataHeader(sheetData, dimension, index) {
38039
- if (dimension === "COL") {
38040
- if (!sheetData.cols[index]) {
38041
- sheetData.cols[index] = {};
38042
- }
38043
- return sheetData.cols[index];
38044
- }
38045
- if (!sheetData.rows[index]) {
38046
- sheetData.rows[index] = {};
38047
- }
38048
- return sheetData.rows[index];
38049
- }
38050
-
38051
38086
  const XLSX_DATE_FORMAT_REGEX = /^(yy|yyyy|m{1,5}|d{1,4}|h{1,2}|s{1,2}|am\/pm|a\/m|\s|-|\/|\.|:)+$/i;
38052
38087
  /**
38053
38088
  * Convert excel format to o_spreadsheet format
@@ -38257,9 +38292,9 @@ function convertConditionalFormats(xlsxCfs, dxfs, warningManager) {
38257
38292
  if (!rule.operator || !rule.formula || rule.formula.length === 0)
38258
38293
  continue;
38259
38294
  operator = CF_OPERATOR_TYPE_CONVERSION_MAP[rule.operator];
38260
- values.push(prefixFormula(rule.formula[0]));
38295
+ values.push(prefixFormulaWithEqual(rule.formula[0]));
38261
38296
  if (rule.formula.length === 2) {
38262
- values.push(prefixFormula(rule.formula[1]));
38297
+ values.push(prefixFormulaWithEqual(rule.formula[1]));
38263
38298
  }
38264
38299
  break;
38265
38300
  }
@@ -38417,11 +38452,6 @@ function convertIcons(xlsxIconSet, index) {
38417
38452
  ? ICON_SETS[iconSet].neutral
38418
38453
  : ICON_SETS[iconSet].good;
38419
38454
  }
38420
- /** Prefix the string by "=" if the string looks like a formula */
38421
- function prefixFormula(formula) {
38422
- const tokens = tokenize(formula);
38423
- return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
38424
- }
38425
38455
  // ---------------------------------------------------------------------------
38426
38456
  // Warnings
38427
38457
  // ---------------------------------------------------------------------------
@@ -38893,7 +38923,7 @@ function convertDataValidationRules(xlsxDataValidations, warningManager) {
38893
38923
  dvRules.push(decimalRule);
38894
38924
  break;
38895
38925
  case "list":
38896
- const listRule = convertListrule(dvId++, dv);
38926
+ const listRule = convertListRule(dvId++, dv);
38897
38927
  dvRules.push(listRule);
38898
38928
  break;
38899
38929
  case "date":
@@ -38913,9 +38943,9 @@ function convertDataValidationRules(xlsxDataValidations, warningManager) {
38913
38943
  return dvRules;
38914
38944
  }
38915
38945
  function convertDecimalRule(id, dv) {
38916
- const values = [dv.formula1.toString()];
38946
+ const values = [prefixFormulaWithEqual(dv.formula1.toString())];
38917
38947
  if (dv.formula2) {
38918
- values.push(dv.formula2.toString());
38948
+ values.push(prefixFormulaWithEqual(dv.formula2.toString()));
38919
38949
  }
38920
38950
  return {
38921
38951
  id: id.toString(),
@@ -38927,7 +38957,7 @@ function convertDecimalRule(id, dv) {
38927
38957
  },
38928
38958
  };
38929
38959
  }
38930
- function convertListrule(id, dv) {
38960
+ function convertListRule(id, dv) {
38931
38961
  const formula1 = dv.formula1.toString();
38932
38962
  const isRangeRule = rangeReference.test(formula1);
38933
38963
  return {
@@ -38943,9 +38973,9 @@ function convertListrule(id, dv) {
38943
38973
  }
38944
38974
  function convertDateRule(id, dv) {
38945
38975
  let criterion;
38946
- const values = [dv.formula1.toString()];
38976
+ const values = [prefixFormulaWithEqual(dv.formula1.toString())];
38947
38977
  if (dv.formula2) {
38948
- values.push(dv.formula2.toString());
38978
+ values.push(prefixFormulaWithEqual(dv.formula2.toString()));
38949
38979
  criterion = {
38950
38980
  type: XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[dv.operator],
38951
38981
  values: getDateCriterionFormattedValues(values, DEFAULT_LOCALE),
@@ -38972,7 +39002,7 @@ function convertCustomRule(id, dv) {
38972
39002
  isBlocking: dv.errorStyle !== "warning",
38973
39003
  criterion: {
38974
39004
  type: "customFormula",
38975
- values: [`=${dv.formula1.toString()}`],
39005
+ values: [prefixFormulaWithEqual(dv.formula1.toString())],
38976
39006
  },
38977
39007
  };
38978
39008
  }
@@ -52863,12 +52893,13 @@ class DataValidationEditor extends owl.Component {
52863
52893
  onCloseSidePanel: { type: Function, optional: true },
52864
52894
  };
52865
52895
  state = owl.useState({ rule: this.defaultDataValidationRule, errors: [] });
52896
+ editingSheetId;
52866
52897
  setup() {
52898
+ this.editingSheetId = this.env.model.getters.getActiveSheetId();
52867
52899
  if (this.props.rule) {
52868
- const sheetId = this.env.model.getters.getActiveSheetId();
52869
52900
  this.state.rule = {
52870
52901
  ...this.props.rule,
52871
- ranges: this.props.rule.ranges.map((range) => this.env.model.getters.getRangeString(range, sheetId)),
52902
+ ranges: this.props.rule.ranges.map((range) => this.env.model.getters.getRangeString(range, this.editingSheetId)),
52872
52903
  };
52873
52904
  this.state.rule.criterion.type = this.props.rule.criterion.type;
52874
52905
  }
@@ -52902,7 +52933,6 @@ class DataValidationEditor extends owl.Component {
52902
52933
  const locale = this.env.model.getters.getLocale();
52903
52934
  const criterion = rule.criterion;
52904
52935
  const criterionEvaluator = criterionEvaluatorRegistry.get(criterion.type);
52905
- const sheetId = this.env.model.getters.getActiveSheetId();
52906
52936
  const values = criterion.values
52907
52937
  .slice(0, criterionEvaluator.numberOfValues(criterion))
52908
52938
  .map((value) => value?.trim())
@@ -52910,8 +52940,8 @@ class DataValidationEditor extends owl.Component {
52910
52940
  .map((value) => canonicalizeContent(value, locale));
52911
52941
  rule.criterion = { ...criterion, values };
52912
52942
  return {
52913
- sheetId,
52914
- ranges: this.state.rule.ranges.map((xc) => this.env.model.getters.getRangeDataFromXc(sheetId, xc)),
52943
+ sheetId: this.editingSheetId,
52944
+ ranges: this.state.rule.ranges.map((xc) => this.env.model.getters.getRangeDataFromXc(this.editingSheetId, xc)),
52915
52945
  rule,
52916
52946
  };
52917
52947
  }
@@ -53438,6 +53468,7 @@ css /* scss */ `
53438
53468
  .o-button {
53439
53469
  height: 19px;
53440
53470
  width: 19px;
53471
+ box-sizing: content-box;
53441
53472
  .o-icon {
53442
53473
  height: 14px;
53443
53474
  width: 14px;
@@ -65528,7 +65559,7 @@ class FormulaDependencyGraph {
65528
65559
  * in the correct order they should be evaluated.
65529
65560
  * This is called a topological ordering (excluding cycles)
65530
65561
  */
65531
- getCellsDependingOn(ranges) {
65562
+ getCellsDependingOn(ranges, ignore) {
65532
65563
  const visited = this.createEmptyPositionSet();
65533
65564
  const queue = Array.from(ranges).reverse();
65534
65565
  while (queue.length > 0) {
@@ -65543,7 +65574,7 @@ class FormulaDependencyGraph {
65543
65574
  const impactedPositions = this.rTree.search(range).map((dep) => dep.data);
65544
65575
  const nextInQueue = {};
65545
65576
  for (const position of impactedPositions) {
65546
- if (!visited.has(position)) {
65577
+ if (!visited.has(position) && !ignore.has(position)) {
65547
65578
  if (!nextInQueue[position.sheetId]) {
65548
65579
  nextInQueue[position.sheetId] = [];
65549
65580
  }
@@ -66100,7 +66131,7 @@ class Evaluator {
66100
66131
  }
66101
66132
  invalidatePositionsDependingOnSpread(sheetId, resultZone) {
66102
66133
  // the result matrix is split in 2 zones to exclude the array formula position
66103
- const invalidatedPositions = this.formulaDependencies().getCellsDependingOn(excludeTopLeft(resultZone).map((zone) => ({ sheetId, zone })));
66134
+ const invalidatedPositions = this.formulaDependencies().getCellsDependingOn(excludeTopLeft(resultZone).map((zone) => ({ sheetId, zone })), this.nextPositionsToUpdate);
66104
66135
  invalidatedPositions.delete({ sheetId, col: resultZone.left, row: resultZone.top });
66105
66136
  this.nextPositionsToUpdate.addMany(invalidatedPositions);
66106
66137
  }
@@ -66218,7 +66249,7 @@ class Evaluator {
66218
66249
  for (const sheetId in zonesBySheetIds) {
66219
66250
  ranges.push(...zonesBySheetIds[sheetId].map((zone) => ({ sheetId, zone })));
66220
66251
  }
66221
- return this.formulaDependencies().getCellsDependingOn(ranges);
66252
+ return this.formulaDependencies().getCellsDependingOn(ranges, this.nextPositionsToUpdate);
66222
66253
  }
66223
66254
  }
66224
66255
  function forEachSpreadPositionInMatrix(nbColumns, nbRows, callback) {
@@ -67691,7 +67722,8 @@ class DynamicTablesPlugin extends CoreViewPlugin {
67691
67722
  const topLeft = { col: unionZone.left, row: unionZone.top, sheetId };
67692
67723
  const parentSpreadingCell = this.getters.getArrayFormulaSpreadingOn(topLeft);
67693
67724
  if (!parentSpreadingCell) {
67694
- return false;
67725
+ const evaluatedCell = this.getters.getEvaluatedCell(topLeft);
67726
+ return (evaluatedCell.value === CellErrorType.SpilledBlocked && !evaluatedCell.errorOriginPosition);
67695
67727
  }
67696
67728
  else if (deepEquals(parentSpreadingCell, topLeft) && getZoneArea(unionZone) === 1) {
67697
67729
  return true;
@@ -78592,6 +78624,7 @@ class RibbonMenu extends owl.Component {
78592
78624
  static components = { Menu };
78593
78625
  rootItems = topbarMenuRegistry.getMenuItems();
78594
78626
  menuRef = owl.useRef("menu");
78627
+ containerRef = owl.useRef("container");
78595
78628
  state = owl.useState({
78596
78629
  menuItems: this.rootItems,
78597
78630
  title: _t("Menu Bar"),
@@ -78599,6 +78632,7 @@ class RibbonMenu extends owl.Component {
78599
78632
  });
78600
78633
  setup() {
78601
78634
  owl.useExternalListener(window, "click", this.onExternalClick, { capture: true });
78635
+ owl.onMounted(this.updateShadows);
78602
78636
  }
78603
78637
  onExternalClick(ev) {
78604
78638
  if (!this.menuRef.el?.contains(ev.target)) {
@@ -78611,6 +78645,7 @@ class RibbonMenu extends owl.Component {
78611
78645
  this.state.parentState = { ...this.state };
78612
78646
  this.state.menuItems = children;
78613
78647
  this.state.title = menu.name(this.env);
78648
+ this.containerRef.el?.scrollTo({ top: 0 });
78614
78649
  }
78615
78650
  else {
78616
78651
  this.state.menuItems = this.rootItems;
@@ -78632,6 +78667,19 @@ class RibbonMenu extends owl.Component {
78632
78667
  height: `${this.props.height}px`,
78633
78668
  });
78634
78669
  }
78670
+ updateShadows() {
78671
+ if (!this.containerRef.el) {
78672
+ return;
78673
+ }
78674
+ this.containerRef.el.classList.remove("scroll-top", "scroll-bottom");
78675
+ const maxScroll = this.containerRef.el.scrollHeight - this.containerRef.el.clientHeight || 0;
78676
+ if (this.containerRef.el.scrollTop < maxScroll - 1) {
78677
+ this.containerRef.el.classList.add("scroll-bottom");
78678
+ }
78679
+ if (this.containerRef.el.scrollTop > 0) {
78680
+ this.containerRef.el.classList.add("scroll-top");
78681
+ }
78682
+ }
78635
78683
  onClickBack() {
78636
78684
  if (!this.state.parentState) {
78637
78685
  this.props.onClose();
@@ -78640,6 +78688,7 @@ class RibbonMenu extends owl.Component {
78640
78688
  this.state.menuItems = this.state.parentState.menuItems;
78641
78689
  this.state.title = this.state.parentState.title;
78642
78690
  this.state.parentState = this.state.parentState.parentState;
78691
+ this.containerRef.el?.scrollTo({ top: 0 });
78643
78692
  }
78644
78693
  get backTitle() {
78645
78694
  return this.state.parentState ? _t("Go to previous menu") : _t("Close menu bar");
@@ -78696,7 +78745,9 @@ class SmallBottomBar extends owl.Component {
78696
78745
  : "inactive";
78697
78746
  }
78698
78747
  get showFxIcon() {
78699
- return this.focus === "inactive" && !this.composerStore.currentContent;
78748
+ return (this.focus === "inactive" &&
78749
+ !this.composerStore.currentContent &&
78750
+ !this.composerStore.placeholder);
78700
78751
  }
78701
78752
  get rect() {
78702
78753
  return this.composerRef.el
@@ -78722,6 +78773,7 @@ class SmallBottomBar extends owl.Component {
78722
78773
  "max-height": `130px`,
78723
78774
  }),
78724
78775
  showAssistant: !isIOS(), // Hide assistant on iOS as it breaks visually
78776
+ placeholder: this.composerStore.placeholder,
78725
78777
  };
78726
78778
  }
78727
78779
  get symbols() {
@@ -78784,7 +78836,9 @@ class TopBarComposer extends owl.Component {
78784
78836
  : "inactive";
78785
78837
  }
78786
78838
  get showFxIcon() {
78787
- return this.focus === "inactive" && !this.composerStore.currentContent;
78839
+ return (this.focus === "inactive" &&
78840
+ !this.composerStore.currentContent &&
78841
+ !this.composerStore.placeholder);
78788
78842
  }
78789
78843
  get composerStyle() {
78790
78844
  const style = {
@@ -84851,6 +84905,6 @@ exports.tokenColors = tokenColors;
84851
84905
  exports.tokenize = tokenize;
84852
84906
 
84853
84907
 
84854
- __info__.version = "18.4.13";
84855
- __info__.date = "2025-10-07T10:00:55.413Z";
84856
- __info__.hash = "d4df70e";
84908
+ __info__.version = "18.4.14";
84909
+ __info__.date = "2025-10-16T06:39:40.249Z";
84910
+ __info__.hash = "bc55c40";
@@ -9279,6 +9279,7 @@ declare class ChartJsComponent extends Component<Props$P, SpreadsheetChildEnv> {
9279
9279
  private createChart;
9280
9280
  private updateChartJs;
9281
9281
  private hasChartDataChanged;
9282
+ private getChartDataInRuntime;
9282
9283
  private enableAnimationInChartData;
9283
9284
  get animationFigureId(): string;
9284
9285
  }
@@ -12173,12 +12174,14 @@ declare class RibbonMenu extends Component<RibbonMenuProps, SpreadsheetChildEnv>
12173
12174
  };
12174
12175
  rootItems: Action[];
12175
12176
  private menuRef;
12177
+ private containerRef;
12176
12178
  state: State$1;
12177
12179
  setup(): void;
12178
12180
  onExternalClick(ev: Event): void;
12179
12181
  onClickMenu(menu: Action): void;
12180
12182
  get menuProps(): MenuProps;
12181
12183
  get style(): string;
12184
+ updateShadows(): void;
12182
12185
  onClickBack(): void;
12183
12186
  get backTitle(): string;
12184
12187
  }