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