@odoo/o-spreadsheet 18.4.3 → 18.4.5

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.3
6
- * @date 2025-07-28T13:39:06.036Z
7
- * @hash 4b596d7
5
+ * @version 18.4.5
6
+ * @date 2025-08-04T06:54:49.107Z
7
+ * @hash 358931f
8
8
  */
9
9
 
10
10
  'use strict';
@@ -1058,16 +1058,21 @@ const colors = [
1058
1058
  "#001f3f",
1059
1059
  ];
1060
1060
  /*
1061
- * transform a color number (R * 256^2 + G * 256 + B) into classic hex6 value
1061
+ * transform a color number (R * 256^2 + G * 256 + B) into classic hex (+alpha) value
1062
1062
  * */
1063
- function colorNumberString(color) {
1064
- return toHex(color.toString(16).padStart(6, "0"));
1063
+ function colorNumberToHex(color, alpha = 1) {
1064
+ const alphaHex = alpha !== 1
1065
+ ? Math.round(alpha * 255)
1066
+ .toString(16)
1067
+ .padStart(2, "0")
1068
+ : "";
1069
+ return toHex(color.toString(16).padStart(6, "0")) + alphaHex;
1065
1070
  }
1066
1071
  function colorToNumber(color) {
1067
1072
  if (typeof color === "number") {
1068
1073
  return color;
1069
1074
  }
1070
- return Number.parseInt(toHex(color).slice(1), 16);
1075
+ return Number.parseInt(toHex(color).slice(1, 7), 16);
1071
1076
  }
1072
1077
  /**
1073
1078
  * Converts any CSS color value to a standardized hex6 value.
@@ -1326,6 +1331,12 @@ function hslaToHex(hsla) {
1326
1331
  function hexToHSLA(hex) {
1327
1332
  return rgbaToHSLA(colorToRGBA(hex));
1328
1333
  }
1334
+ function colorOrNumberToRGBA(color) {
1335
+ if (typeof color === "number") {
1336
+ return colorToRGBA(colorNumberToHex(color));
1337
+ }
1338
+ return colorToRGBA(color);
1339
+ }
1329
1340
  /**
1330
1341
  * Will compare two color strings
1331
1342
  * A tolerance can be provided to account for small differences that could
@@ -1607,6 +1618,8 @@ function getColorScale(colorScalePoints) {
1607
1618
  const sortedColorScalePoints = [...colorScalePoints.sort((a, b) => a.value - b.value)];
1608
1619
  const thresholds = [];
1609
1620
  for (let i = 1; i < sortedColorScalePoints.length; i++) {
1621
+ const minColorAlpha = colorOrNumberToRGBA(sortedColorScalePoints[i - 1].color).a;
1622
+ const maxColorAlpha = colorOrNumberToRGBA(sortedColorScalePoints[i].color).a;
1610
1623
  const minColor = colorToNumber(sortedColorScalePoints[i - 1].color);
1611
1624
  const maxColor = colorToNumber(sortedColorScalePoints[i].color);
1612
1625
  thresholds.push({
@@ -1614,19 +1627,21 @@ function getColorScale(colorScalePoints) {
1614
1627
  max: sortedColorScalePoints[i].value,
1615
1628
  minColor,
1616
1629
  maxColor,
1630
+ minColorAlpha: minColorAlpha,
1631
+ maxColorAlpha: maxColorAlpha,
1617
1632
  colorDiff: computeColorDiffUnits(sortedColorScalePoints[i - 1].value, sortedColorScalePoints[i].value, minColor, maxColor),
1618
1633
  });
1619
1634
  }
1620
1635
  return (value) => {
1621
1636
  if (value < thresholds[0].min) {
1622
- return colorNumberString(thresholds[0].minColor);
1637
+ return colorNumberToHex(thresholds[0].minColor, thresholds[0].minColorAlpha);
1623
1638
  }
1624
1639
  for (const threshold of thresholds) {
1625
1640
  if (value >= threshold.min && value <= threshold.max) {
1626
- return colorNumberString(colorCell(value, threshold.min, threshold.minColor, threshold.colorDiff));
1641
+ return colorNumberToHex(colorCell(value, threshold.min, threshold.minColor, threshold.colorDiff), threshold.maxColorAlpha);
1627
1642
  }
1628
1643
  }
1629
- return colorNumberString(thresholds[thresholds.length - 1].maxColor);
1644
+ return colorNumberToHex(thresholds[thresholds.length - 1].maxColor, thresholds[thresholds.length - 1].maxColorAlpha);
1630
1645
  };
1631
1646
  }
1632
1647
  function computeColorDiffUnits(minValue, maxValue, minColor, maxColor) {
@@ -8626,12 +8641,12 @@ const AGGREGATOR_NAMES = {
8626
8641
  avg: _t("Average"),
8627
8642
  sum: _t("Sum"),
8628
8643
  };
8629
- const NUMBER_CHAR_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
8644
+ const DEFAULT_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
8630
8645
  const AGGREGATORS_BY_FIELD_TYPE = {
8631
- integer: NUMBER_CHAR_AGGREGATORS,
8632
- char: NUMBER_CHAR_AGGREGATORS,
8646
+ integer: DEFAULT_AGGREGATORS,
8647
+ char: DEFAULT_AGGREGATORS,
8648
+ datetime: DEFAULT_AGGREGATORS,
8633
8649
  boolean: ["count_distinct", "count", "bool_and", "bool_or"],
8634
- datetime: ["max", "min", "count_distinct", "count"],
8635
8650
  };
8636
8651
  const AGGREGATORS = {};
8637
8652
  for (const type in AGGREGATORS_BY_FIELD_TYPE) {
@@ -22762,6 +22777,7 @@ class ChartJsComponent extends owl.Component {
22762
22777
  this.animationStore = useStore(ChartAnimationStore);
22763
22778
  }
22764
22779
  owl.onMounted(() => {
22780
+ registerChartJSExtensions();
22765
22781
  const runtime = this.chartRuntime;
22766
22782
  this.currentRuntime = runtime;
22767
22783
  // Note: chartJS modify the runtime in place, so it's important to give it a copy
@@ -31709,7 +31725,7 @@ criterionEvaluatorRegistry.add("isValueInRange", {
31709
31725
  }
31710
31726
  const criterionValues = getters.getDataValidationRangeValues(sheetId, criterion);
31711
31727
  return criterionValues
31712
- .map((value) => value.toLowerCase())
31728
+ .map((value) => value.value.toLowerCase())
31713
31729
  .includes(value.toString().toLowerCase());
31714
31730
  },
31715
31731
  getErrorString: (criterion) => _t("The value must be a value in the range %s", String(criterion.values[0])),
@@ -51845,16 +51861,16 @@ class ConditionalFormatPreview extends owl.Component {
51845
51861
  return cssPropertiesToCss(cellStyleToCss(rule.style));
51846
51862
  }
51847
51863
  else if (rule.type === "ColorScaleRule") {
51848
- const minColor = colorNumberString(rule.minimum.color);
51849
- const midColor = rule.midpoint ? colorNumberString(rule.midpoint.color) : null;
51850
- const maxColor = colorNumberString(rule.maximum.color);
51864
+ const minColor = colorNumberToHex(rule.minimum.color);
51865
+ const midColor = rule.midpoint ? colorNumberToHex(rule.midpoint.color) : null;
51866
+ const maxColor = colorNumberToHex(rule.maximum.color);
51851
51867
  const baseString = "background-image: linear-gradient(to right, ";
51852
51868
  return midColor
51853
51869
  ? baseString + minColor + ", " + midColor + ", " + maxColor + ")"
51854
51870
  : baseString + minColor + ", " + maxColor + ")";
51855
51871
  }
51856
51872
  else if (rule.type === "DataBarRule") {
51857
- const color = colorNumberString(rule.color);
51873
+ const color = colorNumberToHex(rule.color);
51858
51874
  return `background-image: linear-gradient(to right, ${color} 50%, white 50%)`;
51859
51875
  }
51860
51876
  return "";
@@ -52044,7 +52060,8 @@ class ConditionalFormattingEditor extends owl.Component {
52044
52060
  static props = {
52045
52061
  editedCf: Object,
52046
52062
  onCancel: Function,
52047
- onSave: Function,
52063
+ onExit: Function,
52064
+ isNewCf: Boolean,
52048
52065
  };
52049
52066
  static components = {
52050
52067
  SelectionInput,
@@ -52061,7 +52078,7 @@ class ConditionalFormattingEditor extends owl.Component {
52061
52078
  icons = ICONS;
52062
52079
  iconSets = ICON_SETS;
52063
52080
  getTextDecoration = getTextDecoration;
52064
- colorNumberString = colorNumberString;
52081
+ colorNumberToHex = colorNumberToHex;
52065
52082
  state;
52066
52083
  setup() {
52067
52084
  this.state = owl.useState({
@@ -52069,6 +52086,7 @@ class ConditionalFormattingEditor extends owl.Component {
52069
52086
  currentCFType: this.props.editedCf.rule.type,
52070
52087
  ranges: this.props.editedCf.ranges,
52071
52088
  rules: this.getDefaultRules(),
52089
+ hasEditedCf: this.props.isNewCf,
52072
52090
  });
52073
52091
  switch (this.props.editedCf.rule.type) {
52074
52092
  case "CellIsRule":
@@ -52120,6 +52138,9 @@ class ConditionalFormattingEditor extends owl.Component {
52120
52138
  ranges: ranges.map((xc) => this.env.model.getters.getRangeDataFromXc(sheetId, xc)),
52121
52139
  sheetId,
52122
52140
  });
52141
+ if (result.isSuccessful) {
52142
+ this.state.hasEditedCf = true;
52143
+ }
52123
52144
  const reasons = result.reasons.filter((r) => r !== "NoChanges" /* CommandResult.NoChanges */);
52124
52145
  if (!newCf.suppressErrors) {
52125
52146
  this.state.errors = reasons;
@@ -52141,7 +52162,15 @@ class ConditionalFormattingEditor extends owl.Component {
52141
52162
  onSave() {
52142
52163
  const result = this.updateConditionalFormat({});
52143
52164
  if (result.length === 0) {
52144
- this.props.onSave();
52165
+ this.props.onExit();
52166
+ }
52167
+ }
52168
+ onCancel() {
52169
+ if (this.state.hasEditedCf) {
52170
+ this.props.onCancel();
52171
+ }
52172
+ else {
52173
+ this.props.onExit();
52145
52174
  }
52146
52175
  }
52147
52176
  getDefaultRules() {
@@ -52300,9 +52329,9 @@ class ConditionalFormattingEditor extends owl.Component {
52300
52329
  }
52301
52330
  getPreviewGradient() {
52302
52331
  const rule = this.state.rules.colorScale;
52303
- const minColor = colorNumberString(rule.minimum.color);
52304
- const midColor = colorNumberString(rule.midpoint?.color || DEFAULT_COLOR_SCALE_MIDPOINT_COLOR);
52305
- const maxColor = colorNumberString(rule.maximum.color);
52332
+ const minColor = colorNumberToHex(rule.minimum.color);
52333
+ const midColor = colorNumberToHex(rule.midpoint?.color || DEFAULT_COLOR_SCALE_MIDPOINT_COLOR);
52334
+ const maxColor = colorNumberToHex(rule.maximum.color);
52306
52335
  const baseString = "background-image: linear-gradient(to right, ";
52307
52336
  return rule.midpoint === undefined
52308
52337
  ? baseString + minColor + ", " + maxColor + ")"
@@ -52310,8 +52339,8 @@ class ConditionalFormattingEditor extends owl.Component {
52310
52339
  }
52311
52340
  getThresholdColor(threshold) {
52312
52341
  return threshold
52313
- ? colorNumberString(threshold.color)
52314
- : colorNumberString(DEFAULT_COLOR_SCALE_MIDPOINT_COLOR);
52342
+ ? colorNumberToHex(threshold.color)
52343
+ : colorNumberToHex(DEFAULT_COLOR_SCALE_MIDPOINT_COLOR);
52315
52344
  }
52316
52345
  onMidpointChange(ev) {
52317
52346
  const type = ev.target.value;
@@ -66534,9 +66563,9 @@ class CustomColorsPlugin extends CoreViewPlugin {
66534
66563
  formatColors.push(rule.style.fillColor);
66535
66564
  }
66536
66565
  else if (rule.type === "ColorScaleRule") {
66537
- formatColors.push(colorNumberString(rule.minimum.color));
66538
- formatColors.push(rule.midpoint ? colorNumberString(rule.midpoint.color) : undefined);
66539
- formatColors.push(colorNumberString(rule.maximum.color));
66566
+ formatColors.push(colorNumberToHex(rule.minimum.color));
66567
+ formatColors.push(rule.midpoint ? colorNumberToHex(rule.midpoint.color) : undefined);
66568
+ formatColors.push(colorNumberToHex(rule.maximum.color));
66540
66569
  }
66541
66570
  }
66542
66571
  return formatColors.filter(isDefined);
@@ -66907,7 +66936,7 @@ class EvaluationConditionalFormatPlugin extends CoreViewPlugin {
66907
66936
  if (!computedDataBars[col])
66908
66937
  computedDataBars[col] = [];
66909
66938
  computedDataBars[col][row] = {
66910
- color: colorNumberString(color),
66939
+ color: colorNumberToHex(color),
66911
66940
  percentage: (cell.value * 100) / max,
66912
66941
  };
66913
66942
  }
@@ -67036,8 +67065,16 @@ class EvaluationDataValidationPlugin extends CoreViewPlugin {
67036
67065
  }
67037
67066
  getDataValidationRangeValues(sheetId, criterion) {
67038
67067
  const range = this.getters.getRangeFromSheetXC(sheetId, String(criterion.values[0]));
67039
- const criterionValues = this.getters.getRangeValues(range);
67040
- return criterionValues.map((value) => value?.toString()).filter(isDefined);
67068
+ const values = [];
67069
+ const labelsSet = new Set();
67070
+ for (const p of positions(range.zone)) {
67071
+ const cell = this.getters.getEvaluatedCell({ ...p, sheetId: range.sheetId });
67072
+ if (cell.formattedValue && !labelsSet.has(cell.formattedValue)) {
67073
+ labelsSet.add(cell.formattedValue);
67074
+ values.push({ label: cell.formattedValue, value: cell.value?.toString() || "" });
67075
+ }
67076
+ }
67077
+ return values;
67041
67078
  }
67042
67079
  isCellValidCheckbox(cellPosition) {
67043
67080
  if (!this.getters.isMainCellPosition(cellPosition)) {
@@ -75652,25 +75689,30 @@ autoCompleteProviders.add("dataValidation", {
75652
75689
  }
75653
75690
  const sheetId = this.composer.currentEditedCell.sheetId;
75654
75691
  const values = rule.criterion.type === "isValueInRange"
75655
- ? Array.from(new Set(this.getters.getDataValidationRangeValues(sheetId, rule.criterion)))
75656
- : rule.criterion.values;
75692
+ ? this.getters.getDataValidationRangeValues(sheetId, rule.criterion)
75693
+ : rule.criterion.values.map((value) => ({ label: value, value }));
75657
75694
  const isChip = rule.criterion.displayStyle === "chip";
75658
75695
  if (!isChip) {
75659
- return values.map((value) => ({ text: value }));
75696
+ return values.map((value) => ({
75697
+ text: value.value,
75698
+ fuzzySearchKey: value.label,
75699
+ htmlContent: [{ value: value.label }],
75700
+ }));
75660
75701
  }
75661
75702
  const colors = rule.criterion.colors;
75662
75703
  return values.map((value) => {
75663
- const color = colors?.[value];
75704
+ const color = colors?.[value.value];
75664
75705
  return {
75665
- text: value,
75706
+ text: value.value,
75666
75707
  htmlContent: [
75667
75708
  {
75668
- value,
75709
+ value: value.label,
75669
75710
  color: color ? chipTextColor(color) : undefined,
75670
75711
  backgroundColor: color || GRAY_200,
75671
75712
  classes: ["badge rounded-pill fs-6 fw-normal w-100 mt-1 text-start"],
75672
75713
  },
75673
75714
  ],
75715
+ fuzzySearchKey: value.label,
75674
75716
  };
75675
75717
  });
75676
75718
  },
@@ -79911,7 +79953,6 @@ css /* scss */ `
79911
79953
  }
79912
79954
  }
79913
79955
 
79914
- .o-spreadsheet-topbar-wrapper,
79915
79956
  .o-spreadsheet-bottombar-wrapper {
79916
79957
  z-index: ${ComponentsImportance.ScrollBar + 1};
79917
79958
  }
@@ -80026,7 +80067,6 @@ class Spreadsheet extends owl.Component {
80026
80067
  this.checkViewportSize();
80027
80068
  stores.on("store-updated", this, render);
80028
80069
  resizeObserver.observe(this.spreadsheetRef.el);
80029
- registerChartJSExtensions();
80030
80070
  });
80031
80071
  owl.onWillUnmount(() => {
80032
80072
  this.unbindModelEvents();
@@ -82559,7 +82599,7 @@ function addDataBarRule(cf, rule) {
82559
82599
  <dataBar>
82560
82600
  <cfvo type="min" val="0"/>
82561
82601
  <cfvo type="max" val="100"/>
82562
- <color rgb="${toXlsxHexColor(colorNumberString(rule.color))}"/>
82602
+ <color rgb="${toXlsxHexColor(colorNumberToHex(rule.color))}"/>
82563
82603
  </dataBar>
82564
82604
  </cfRule>
82565
82605
  </conditionalFormatting>
@@ -82587,7 +82627,7 @@ function addColorScaleRule(cf, rule) {
82587
82627
  continue;
82588
82628
  }
82589
82629
  cfValueObject.push(thresholdAttributes(threshold, position));
82590
- colors.push([["rgb", toXlsxHexColor(colorNumberString(threshold.color))]]);
82630
+ colors.push([["rgb", toXlsxHexColor(colorNumberToHex(threshold.color))]]);
82591
82631
  }
82592
82632
  if (!canExport) {
82593
82633
  console.warn("Conditional formats with formula rules are not supported at the moment. The rule is therefore skipped.");
@@ -84646,6 +84686,6 @@ exports.tokenColors = tokenColors;
84646
84686
  exports.tokenize = tokenize;
84647
84687
 
84648
84688
 
84649
- __info__.version = "18.4.3";
84650
- __info__.date = "2025-07-28T13:39:06.036Z";
84651
- __info__.hash = "4b596d7";
84689
+ __info__.version = "18.4.5";
84690
+ __info__.date = "2025-08-04T06:54:49.107Z";
84691
+ __info__.hash = "358931f";
@@ -5557,7 +5557,10 @@ declare class EvaluationDataValidationPlugin extends CoreViewPlugin {
5557
5557
  * The value must be canonicalized.
5558
5558
  */
5559
5559
  getDataValidationInvalidCriterionValueMessage(criterionType: DataValidationCriterionType, value: string): string | undefined;
5560
- getDataValidationRangeValues(sheetId: UID, criterion: EvaluatedCriterion): string[];
5560
+ getDataValidationRangeValues(sheetId: UID, criterion: EvaluatedCriterion): {
5561
+ value: string;
5562
+ label: string;
5563
+ }[];
5561
5564
  isCellValidCheckbox(cellPosition: CellPosition): boolean;
5562
5565
  /** Get the validation result if the cell on the given position had the given value */
5563
5566
  getValidationResultForCellValue(cellValue: CellValue, cellPosition: CellPosition): ValidationResult;