@odoo/o-spreadsheet 16.0.64 → 16.0.66

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.
@@ -7386,7 +7386,8 @@ function getChartLabelValues(getters, dataSets, labelRange) {
7386
7386
  }
7387
7387
  }
7388
7388
  else if (dataSets.length === 1) {
7389
- for (let i = 0; i < getData(getters, dataSets[0]).length; i++) {
7389
+ const dataLength = getData(getters, dataSets[0]).length;
7390
+ for (let i = 0; i < dataLength; i++) {
7390
7391
  labels.formattedValues.push("");
7391
7392
  labels.values.push("");
7392
7393
  }
@@ -19591,8 +19592,8 @@ class EditionPlugin extends UIPlugin {
19591
19592
  break;
19592
19593
  case "STOP_EDITION":
19593
19594
  if (cmd.cancel) {
19594
- this.cancelEditionAndActivateSheet();
19595
19595
  this.resetContent();
19596
+ this.cancelEditionAndActivateSheet();
19596
19597
  }
19597
19598
  else {
19598
19599
  this.stopEdition();
@@ -19607,8 +19608,8 @@ class EditionPlugin extends UIPlugin {
19607
19608
  this.replaceSelection(cmd.text);
19608
19609
  break;
19609
19610
  case "SELECT_FIGURE":
19610
- this.cancelEditionAndActivateSheet();
19611
19611
  this.resetContent();
19612
+ this.cancelEditionAndActivateSheet();
19612
19613
  break;
19613
19614
  case "ADD_COLUMNS_ROWS":
19614
19615
  this.onAddElements(cmd);
@@ -19667,8 +19668,8 @@ class EditionPlugin extends UIPlugin {
19667
19668
  const sheetIdExists = !!this.getters.tryGetSheet(this.sheetId);
19668
19669
  if (!sheetIdExists && this.mode !== "inactive") {
19669
19670
  this.sheetId = this.getters.getActiveSheetId();
19670
- this.cancelEditionAndActivateSheet();
19671
19671
  this.resetContent();
19672
+ this.cancelEditionAndActivateSheet();
19672
19673
  this.ui.notifyUI({
19673
19674
  type: "ERROR",
19674
19675
  text: CELL_DELETED_MESSAGE,
@@ -23731,9 +23732,9 @@ const XLSX_CHART_TYPES = [
23731
23732
  /** In XLSX color format (no #) */
23732
23733
  const AUTO_COLOR = "000000";
23733
23734
  const XLSX_ICONSET_MAP = {
23734
- arrow: "3Arrows",
23735
+ arrows: "3Arrows",
23735
23736
  smiley: "3Symbols",
23736
- dot: "3TrafficLights1",
23737
+ dots: "3TrafficLights1",
23737
23738
  };
23738
23739
  const NAMESPACE = {
23739
23740
  styleSheet: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
@@ -24122,6 +24123,7 @@ const ICON_SET_CONVERSION_MAP = {
24122
24123
  };
24123
24124
  /** Map between legend position in XLSX file and human readable position */
24124
24125
  const DRAWING_LEGEND_POSITION_CONVERSION_MAP = {
24126
+ none: "none",
24125
24127
  b: "bottom",
24126
24128
  t: "top",
24127
24129
  l: "left",
@@ -26299,7 +26301,7 @@ class XlsxChartExtractor extends XlsxBaseExtractor {
26299
26301
  ? "right"
26300
26302
  : "left",
26301
26303
  legendPosition: DRAWING_LEGEND_POSITION_CONVERSION_MAP[this.extractChildAttr(rootChartElement, "c:legendPos", "val", {
26302
- default: "b",
26304
+ default: "none",
26303
26305
  }).asString()],
26304
26306
  stacked: barChartGrouping === "stacked",
26305
26307
  fontColor: "000000",
@@ -32449,12 +32451,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
32449
32451
  for (let c = 0; c < width; c++) {
32450
32452
  const origin = rowCells[c];
32451
32453
  const position = { col: col + c, row: row + r, sheetId: sheetId };
32452
- // TODO: refactor this part. the "Paste merge" action is also executed with
32453
- // MOVE_RANGES in pasteFromCut. Adding a condition on the operation type here
32454
- // is not appropriate
32455
- if (this.operation !== "CUT") {
32456
- this.pasteMergeIfExist(origin.position, position);
32457
- }
32454
+ this.pasteMergeIfExist(origin.position, position, this.operation);
32458
32455
  this.pasteCell(origin, position, this.operation, clipboardOptions);
32459
32456
  if (shouldPasteCF) {
32460
32457
  this.dispatch("PASTE_CONDITIONAL_FORMAT", {
@@ -32533,7 +32530,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
32533
32530
  * If the origin position given is the top left of a merge, merge the target
32534
32531
  * position.
32535
32532
  */
32536
- pasteMergeIfExist(origin, target) {
32533
+ pasteMergeIfExist(origin, target, operation) {
32537
32534
  let { sheetId, col, row } = origin;
32538
32535
  const { col: mainCellColOrigin, row: mainCellRowOrigin } = this.getters.getMainCellPosition(sheetId, col, row);
32539
32536
  if (mainCellColOrigin === col && mainCellRowOrigin === row) {
@@ -32541,6 +32538,9 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
32541
32538
  if (!merge) {
32542
32539
  return;
32543
32540
  }
32541
+ if (operation === "CUT") {
32542
+ this.dispatch("REMOVE_MERGE", { sheetId, target: [merge] });
32543
+ }
32544
32544
  ({ sheetId, col, row } = target);
32545
32545
  this.dispatch("ADD_MERGE", {
32546
32546
  sheetId,
@@ -42466,10 +42466,14 @@ function addIconSetRule(cf, rule) {
42466
42466
  continue;
42467
42467
  }
42468
42468
  const cfValueObjectNodes = cfValueObject.map((attrs) => escapeXml /*xml*/ `<cfvo ${formatAttributes(attrs)} />`);
42469
+ const iconSetAttrs = [["iconSet", getIconSet(rule.icons)]];
42470
+ if (isIconSetReversed(rule.icons)) {
42471
+ iconSetAttrs.push(["reverse", "1"]);
42472
+ }
42469
42473
  conditionalFormats.push(escapeXml /*xml*/ `
42470
42474
  <conditionalFormatting sqref="${range}">
42471
42475
  <cfRule ${formatAttributes(ruleAttributes)}>
42472
- <iconSet iconSet="${getIconSet(rule.icons)}">
42476
+ <iconSet ${formatAttributes(iconSetAttrs)}>
42473
42477
  ${joinXmlNodes(cfValueObjectNodes)}
42474
42478
  </iconSet>
42475
42479
  </cfRule>
@@ -42487,9 +42491,21 @@ function commonCfAttributes(cf) {
42487
42491
  ["stopIfTrue", cf.stopIfTrue ? 1 : 0],
42488
42492
  ];
42489
42493
  }
42494
+ function isIconSetReversed(iconSet) {
42495
+ const defaultIconSet = ICON_SETS[detectIconsType(iconSet)];
42496
+ return iconSet.upper === defaultIconSet.bad && iconSet.lower === defaultIconSet.good;
42497
+ }
42490
42498
  function getIconSet(iconSet) {
42491
- return XLSX_ICONSET_MAP[Object.keys(XLSX_ICONSET_MAP).find((key) => iconSet.upper.toLowerCase().startsWith(key)) ||
42492
- "dots"];
42499
+ return XLSX_ICONSET_MAP[detectIconsType(iconSet)];
42500
+ }
42501
+ /**
42502
+ * Partial detection based on "upper" point only.
42503
+ * We support any arbitrary icon in the set, while excel doesn't allow
42504
+ * mixing icons from different types.
42505
+ */
42506
+ function detectIconsType(iconSet) {
42507
+ const type = Object.keys(ICON_SETS).find((type) => Object.values(ICON_SETS[type]).includes(iconSet.upper)) || "dots";
42508
+ return type;
42493
42509
  }
42494
42510
  function thresholdAttributes(threshold, position) {
42495
42511
  const type = getExcelThresholdType(threshold.type, position);
@@ -43762,6 +43778,6 @@ exports.setTranslationMethod = setTranslationMethod;
43762
43778
  exports.tokenize = tokenize;
43763
43779
 
43764
43780
 
43765
- __info__.version = '16.0.64';
43766
- __info__.date = '2025-03-07T10:29:50.957Z';
43767
- __info__.hash = '20def15';
43781
+ __info__.version = '16.0.66';
43782
+ __info__.date = '2025-03-26T12:44:10.381Z';
43783
+ __info__.hash = 'e2c1da2';
@@ -7382,7 +7382,8 @@ function getChartLabelValues(getters, dataSets, labelRange) {
7382
7382
  }
7383
7383
  }
7384
7384
  else if (dataSets.length === 1) {
7385
- for (let i = 0; i < getData(getters, dataSets[0]).length; i++) {
7385
+ const dataLength = getData(getters, dataSets[0]).length;
7386
+ for (let i = 0; i < dataLength; i++) {
7386
7387
  labels.formattedValues.push("");
7387
7388
  labels.values.push("");
7388
7389
  }
@@ -19587,8 +19588,8 @@ class EditionPlugin extends UIPlugin {
19587
19588
  break;
19588
19589
  case "STOP_EDITION":
19589
19590
  if (cmd.cancel) {
19590
- this.cancelEditionAndActivateSheet();
19591
19591
  this.resetContent();
19592
+ this.cancelEditionAndActivateSheet();
19592
19593
  }
19593
19594
  else {
19594
19595
  this.stopEdition();
@@ -19603,8 +19604,8 @@ class EditionPlugin extends UIPlugin {
19603
19604
  this.replaceSelection(cmd.text);
19604
19605
  break;
19605
19606
  case "SELECT_FIGURE":
19606
- this.cancelEditionAndActivateSheet();
19607
19607
  this.resetContent();
19608
+ this.cancelEditionAndActivateSheet();
19608
19609
  break;
19609
19610
  case "ADD_COLUMNS_ROWS":
19610
19611
  this.onAddElements(cmd);
@@ -19663,8 +19664,8 @@ class EditionPlugin extends UIPlugin {
19663
19664
  const sheetIdExists = !!this.getters.tryGetSheet(this.sheetId);
19664
19665
  if (!sheetIdExists && this.mode !== "inactive") {
19665
19666
  this.sheetId = this.getters.getActiveSheetId();
19666
- this.cancelEditionAndActivateSheet();
19667
19667
  this.resetContent();
19668
+ this.cancelEditionAndActivateSheet();
19668
19669
  this.ui.notifyUI({
19669
19670
  type: "ERROR",
19670
19671
  text: CELL_DELETED_MESSAGE,
@@ -23727,9 +23728,9 @@ const XLSX_CHART_TYPES = [
23727
23728
  /** In XLSX color format (no #) */
23728
23729
  const AUTO_COLOR = "000000";
23729
23730
  const XLSX_ICONSET_MAP = {
23730
- arrow: "3Arrows",
23731
+ arrows: "3Arrows",
23731
23732
  smiley: "3Symbols",
23732
- dot: "3TrafficLights1",
23733
+ dots: "3TrafficLights1",
23733
23734
  };
23734
23735
  const NAMESPACE = {
23735
23736
  styleSheet: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
@@ -24118,6 +24119,7 @@ const ICON_SET_CONVERSION_MAP = {
24118
24119
  };
24119
24120
  /** Map between legend position in XLSX file and human readable position */
24120
24121
  const DRAWING_LEGEND_POSITION_CONVERSION_MAP = {
24122
+ none: "none",
24121
24123
  b: "bottom",
24122
24124
  t: "top",
24123
24125
  l: "left",
@@ -26295,7 +26297,7 @@ class XlsxChartExtractor extends XlsxBaseExtractor {
26295
26297
  ? "right"
26296
26298
  : "left",
26297
26299
  legendPosition: DRAWING_LEGEND_POSITION_CONVERSION_MAP[this.extractChildAttr(rootChartElement, "c:legendPos", "val", {
26298
- default: "b",
26300
+ default: "none",
26299
26301
  }).asString()],
26300
26302
  stacked: barChartGrouping === "stacked",
26301
26303
  fontColor: "000000",
@@ -32445,12 +32447,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
32445
32447
  for (let c = 0; c < width; c++) {
32446
32448
  const origin = rowCells[c];
32447
32449
  const position = { col: col + c, row: row + r, sheetId: sheetId };
32448
- // TODO: refactor this part. the "Paste merge" action is also executed with
32449
- // MOVE_RANGES in pasteFromCut. Adding a condition on the operation type here
32450
- // is not appropriate
32451
- if (this.operation !== "CUT") {
32452
- this.pasteMergeIfExist(origin.position, position);
32453
- }
32450
+ this.pasteMergeIfExist(origin.position, position, this.operation);
32454
32451
  this.pasteCell(origin, position, this.operation, clipboardOptions);
32455
32452
  if (shouldPasteCF) {
32456
32453
  this.dispatch("PASTE_CONDITIONAL_FORMAT", {
@@ -32529,7 +32526,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
32529
32526
  * If the origin position given is the top left of a merge, merge the target
32530
32527
  * position.
32531
32528
  */
32532
- pasteMergeIfExist(origin, target) {
32529
+ pasteMergeIfExist(origin, target, operation) {
32533
32530
  let { sheetId, col, row } = origin;
32534
32531
  const { col: mainCellColOrigin, row: mainCellRowOrigin } = this.getters.getMainCellPosition(sheetId, col, row);
32535
32532
  if (mainCellColOrigin === col && mainCellRowOrigin === row) {
@@ -32537,6 +32534,9 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
32537
32534
  if (!merge) {
32538
32535
  return;
32539
32536
  }
32537
+ if (operation === "CUT") {
32538
+ this.dispatch("REMOVE_MERGE", { sheetId, target: [merge] });
32539
+ }
32540
32540
  ({ sheetId, col, row } = target);
32541
32541
  this.dispatch("ADD_MERGE", {
32542
32542
  sheetId,
@@ -42462,10 +42462,14 @@ function addIconSetRule(cf, rule) {
42462
42462
  continue;
42463
42463
  }
42464
42464
  const cfValueObjectNodes = cfValueObject.map((attrs) => escapeXml /*xml*/ `<cfvo ${formatAttributes(attrs)} />`);
42465
+ const iconSetAttrs = [["iconSet", getIconSet(rule.icons)]];
42466
+ if (isIconSetReversed(rule.icons)) {
42467
+ iconSetAttrs.push(["reverse", "1"]);
42468
+ }
42465
42469
  conditionalFormats.push(escapeXml /*xml*/ `
42466
42470
  <conditionalFormatting sqref="${range}">
42467
42471
  <cfRule ${formatAttributes(ruleAttributes)}>
42468
- <iconSet iconSet="${getIconSet(rule.icons)}">
42472
+ <iconSet ${formatAttributes(iconSetAttrs)}>
42469
42473
  ${joinXmlNodes(cfValueObjectNodes)}
42470
42474
  </iconSet>
42471
42475
  </cfRule>
@@ -42483,9 +42487,21 @@ function commonCfAttributes(cf) {
42483
42487
  ["stopIfTrue", cf.stopIfTrue ? 1 : 0],
42484
42488
  ];
42485
42489
  }
42490
+ function isIconSetReversed(iconSet) {
42491
+ const defaultIconSet = ICON_SETS[detectIconsType(iconSet)];
42492
+ return iconSet.upper === defaultIconSet.bad && iconSet.lower === defaultIconSet.good;
42493
+ }
42486
42494
  function getIconSet(iconSet) {
42487
- return XLSX_ICONSET_MAP[Object.keys(XLSX_ICONSET_MAP).find((key) => iconSet.upper.toLowerCase().startsWith(key)) ||
42488
- "dots"];
42495
+ return XLSX_ICONSET_MAP[detectIconsType(iconSet)];
42496
+ }
42497
+ /**
42498
+ * Partial detection based on "upper" point only.
42499
+ * We support any arbitrary icon in the set, while excel doesn't allow
42500
+ * mixing icons from different types.
42501
+ */
42502
+ function detectIconsType(iconSet) {
42503
+ const type = Object.keys(ICON_SETS).find((type) => Object.values(ICON_SETS[type]).includes(iconSet.upper)) || "dots";
42504
+ return type;
42489
42505
  }
42490
42506
  function thresholdAttributes(threshold, position) {
42491
42507
  const type = getExcelThresholdType(threshold.type, position);
@@ -43730,6 +43746,6 @@ function addFunction(functionName, functionDescription) {
43730
43746
  export { AbstractChart, CommandResult, CorePlugin, DATETIME_FORMAT, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, cellTypes, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, load, parse, readonlyAllowedCommands, registries, setTranslationMethod, tokenize };
43731
43747
 
43732
43748
 
43733
- __info__.version = '16.0.64';
43734
- __info__.date = '2025-03-07T10:29:50.957Z';
43735
- __info__.hash = '20def15';
43749
+ __info__.version = '16.0.66';
43750
+ __info__.date = '2025-03-26T12:44:10.381Z';
43751
+ __info__.hash = 'e2c1da2';
@@ -7383,7 +7383,8 @@
7383
7383
  }
7384
7384
  }
7385
7385
  else if (dataSets.length === 1) {
7386
- for (let i = 0; i < getData(getters, dataSets[0]).length; i++) {
7386
+ const dataLength = getData(getters, dataSets[0]).length;
7387
+ for (let i = 0; i < dataLength; i++) {
7387
7388
  labels.formattedValues.push("");
7388
7389
  labels.values.push("");
7389
7390
  }
@@ -19588,8 +19589,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
19588
19589
  break;
19589
19590
  case "STOP_EDITION":
19590
19591
  if (cmd.cancel) {
19591
- this.cancelEditionAndActivateSheet();
19592
19592
  this.resetContent();
19593
+ this.cancelEditionAndActivateSheet();
19593
19594
  }
19594
19595
  else {
19595
19596
  this.stopEdition();
@@ -19604,8 +19605,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
19604
19605
  this.replaceSelection(cmd.text);
19605
19606
  break;
19606
19607
  case "SELECT_FIGURE":
19607
- this.cancelEditionAndActivateSheet();
19608
19608
  this.resetContent();
19609
+ this.cancelEditionAndActivateSheet();
19609
19610
  break;
19610
19611
  case "ADD_COLUMNS_ROWS":
19611
19612
  this.onAddElements(cmd);
@@ -19664,8 +19665,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
19664
19665
  const sheetIdExists = !!this.getters.tryGetSheet(this.sheetId);
19665
19666
  if (!sheetIdExists && this.mode !== "inactive") {
19666
19667
  this.sheetId = this.getters.getActiveSheetId();
19667
- this.cancelEditionAndActivateSheet();
19668
19668
  this.resetContent();
19669
+ this.cancelEditionAndActivateSheet();
19669
19670
  this.ui.notifyUI({
19670
19671
  type: "ERROR",
19671
19672
  text: CELL_DELETED_MESSAGE,
@@ -23728,9 +23729,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
23728
23729
  /** In XLSX color format (no #) */
23729
23730
  const AUTO_COLOR = "000000";
23730
23731
  const XLSX_ICONSET_MAP = {
23731
- arrow: "3Arrows",
23732
+ arrows: "3Arrows",
23732
23733
  smiley: "3Symbols",
23733
- dot: "3TrafficLights1",
23734
+ dots: "3TrafficLights1",
23734
23735
  };
23735
23736
  const NAMESPACE = {
23736
23737
  styleSheet: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
@@ -24119,6 +24120,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
24119
24120
  };
24120
24121
  /** Map between legend position in XLSX file and human readable position */
24121
24122
  const DRAWING_LEGEND_POSITION_CONVERSION_MAP = {
24123
+ none: "none",
24122
24124
  b: "bottom",
24123
24125
  t: "top",
24124
24126
  l: "left",
@@ -26296,7 +26298,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
26296
26298
  ? "right"
26297
26299
  : "left",
26298
26300
  legendPosition: DRAWING_LEGEND_POSITION_CONVERSION_MAP[this.extractChildAttr(rootChartElement, "c:legendPos", "val", {
26299
- default: "b",
26301
+ default: "none",
26300
26302
  }).asString()],
26301
26303
  stacked: barChartGrouping === "stacked",
26302
26304
  fontColor: "000000",
@@ -32446,12 +32448,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
32446
32448
  for (let c = 0; c < width; c++) {
32447
32449
  const origin = rowCells[c];
32448
32450
  const position = { col: col + c, row: row + r, sheetId: sheetId };
32449
- // TODO: refactor this part. the "Paste merge" action is also executed with
32450
- // MOVE_RANGES in pasteFromCut. Adding a condition on the operation type here
32451
- // is not appropriate
32452
- if (this.operation !== "CUT") {
32453
- this.pasteMergeIfExist(origin.position, position);
32454
- }
32451
+ this.pasteMergeIfExist(origin.position, position, this.operation);
32455
32452
  this.pasteCell(origin, position, this.operation, clipboardOptions);
32456
32453
  if (shouldPasteCF) {
32457
32454
  this.dispatch("PASTE_CONDITIONAL_FORMAT", {
@@ -32530,7 +32527,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
32530
32527
  * If the origin position given is the top left of a merge, merge the target
32531
32528
  * position.
32532
32529
  */
32533
- pasteMergeIfExist(origin, target) {
32530
+ pasteMergeIfExist(origin, target, operation) {
32534
32531
  let { sheetId, col, row } = origin;
32535
32532
  const { col: mainCellColOrigin, row: mainCellRowOrigin } = this.getters.getMainCellPosition(sheetId, col, row);
32536
32533
  if (mainCellColOrigin === col && mainCellRowOrigin === row) {
@@ -32538,6 +32535,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
32538
32535
  if (!merge) {
32539
32536
  return;
32540
32537
  }
32538
+ if (operation === "CUT") {
32539
+ this.dispatch("REMOVE_MERGE", { sheetId, target: [merge] });
32540
+ }
32541
32541
  ({ sheetId, col, row } = target);
32542
32542
  this.dispatch("ADD_MERGE", {
32543
32543
  sheetId,
@@ -42463,10 +42463,14 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42463
42463
  continue;
42464
42464
  }
42465
42465
  const cfValueObjectNodes = cfValueObject.map((attrs) => escapeXml /*xml*/ `<cfvo ${formatAttributes(attrs)} />`);
42466
+ const iconSetAttrs = [["iconSet", getIconSet(rule.icons)]];
42467
+ if (isIconSetReversed(rule.icons)) {
42468
+ iconSetAttrs.push(["reverse", "1"]);
42469
+ }
42466
42470
  conditionalFormats.push(escapeXml /*xml*/ `
42467
42471
  <conditionalFormatting sqref="${range}">
42468
42472
  <cfRule ${formatAttributes(ruleAttributes)}>
42469
- <iconSet iconSet="${getIconSet(rule.icons)}">
42473
+ <iconSet ${formatAttributes(iconSetAttrs)}>
42470
42474
  ${joinXmlNodes(cfValueObjectNodes)}
42471
42475
  </iconSet>
42472
42476
  </cfRule>
@@ -42484,9 +42488,21 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42484
42488
  ["stopIfTrue", cf.stopIfTrue ? 1 : 0],
42485
42489
  ];
42486
42490
  }
42491
+ function isIconSetReversed(iconSet) {
42492
+ const defaultIconSet = ICON_SETS[detectIconsType(iconSet)];
42493
+ return iconSet.upper === defaultIconSet.bad && iconSet.lower === defaultIconSet.good;
42494
+ }
42487
42495
  function getIconSet(iconSet) {
42488
- return XLSX_ICONSET_MAP[Object.keys(XLSX_ICONSET_MAP).find((key) => iconSet.upper.toLowerCase().startsWith(key)) ||
42489
- "dots"];
42496
+ return XLSX_ICONSET_MAP[detectIconsType(iconSet)];
42497
+ }
42498
+ /**
42499
+ * Partial detection based on "upper" point only.
42500
+ * We support any arbitrary icon in the set, while excel doesn't allow
42501
+ * mixing icons from different types.
42502
+ */
42503
+ function detectIconsType(iconSet) {
42504
+ const type = Object.keys(ICON_SETS).find((type) => Object.values(ICON_SETS[type]).includes(iconSet.upper)) || "dots";
42505
+ return type;
42490
42506
  }
42491
42507
  function thresholdAttributes(threshold, position) {
42492
42508
  const type = getExcelThresholdType(threshold.type, position);
@@ -43761,9 +43777,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
43761
43777
  Object.defineProperty(exports, '__esModule', { value: true });
43762
43778
 
43763
43779
 
43764
- __info__.version = '16.0.64';
43765
- __info__.date = '2025-03-07T10:29:50.957Z';
43766
- __info__.hash = '20def15';
43780
+ __info__.version = '16.0.66';
43781
+ __info__.date = '2025-03-26T12:44:10.381Z';
43782
+ __info__.hash = 'e2c1da2';
43767
43783
 
43768
43784
 
43769
43785
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);