@useinsider/guido 3.20.1 → 3.21.0-beta.0df5409

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.
Files changed (90) hide show
  1. package/dist/components/Guido.vue.js +1 -1
  2. package/dist/components/Guido.vue2.js +65 -64
  3. package/dist/components/organisms/AutoSaveController.vue2.js +10 -9
  4. package/dist/components/organisms/header/EditorActions.vue.js +4 -4
  5. package/dist/components/organisms/header/EditorActions.vue2.js +53 -51
  6. package/dist/components/organisms/validation/ValidationErrorDrawer.vue.js +3 -3
  7. package/dist/components/organisms/validation/ValidationErrorDrawer.vue2.js +23 -22
  8. package/dist/composables/useActionsApi.js +80 -63
  9. package/dist/composables/useAutoSave.js +46 -44
  10. package/dist/composables/useGuidoStateBridge.js +3 -3
  11. package/dist/composables/useLegacyStrategyConversion.js +16 -16
  12. package/dist/composables/useSave.js +26 -23
  13. package/dist/composables/useSaveValidation.js +113 -114
  14. package/dist/composables/useSaveValidationRollout.js +17 -6
  15. package/dist/composables/useStripo.js +11 -10
  16. package/dist/extensions/Blocks/Items/block.js +43 -42
  17. package/dist/extensions/Blocks/Recommendation/block.js +33 -29
  18. package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +78 -83
  19. package/dist/extensions/Blocks/Recommendation/controls/customAttribute/textTrim.js +1 -2
  20. package/dist/extensions/Blocks/Recommendation/controls/main/algorithm.js +2 -12
  21. package/dist/extensions/Blocks/Recommendation/controls/main/currency.js +104 -86
  22. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +348 -263
  23. package/dist/extensions/Blocks/Recommendation/controls/main/layoutOrientation.js +48 -50
  24. package/dist/extensions/Blocks/Recommendation/controls/main/locale.js +16 -21
  25. package/dist/extensions/Blocks/Recommendation/controls/main/pricePlacement.js +44 -40
  26. package/dist/extensions/Blocks/Recommendation/controls/main/productCount.js +14 -19
  27. package/dist/extensions/Blocks/Recommendation/controls/main/productLayout.js +104 -102
  28. package/dist/extensions/Blocks/Recommendation/controls/main/shuffle.js +18 -23
  29. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +312 -286
  30. package/dist/extensions/Blocks/Recommendation/controls/mobileLayout/cssRules.js +24 -20
  31. package/dist/extensions/Blocks/Recommendation/controls/name/textTrim.js +6 -7
  32. package/dist/extensions/Blocks/Recommendation/controls/shared/textTrimCssRules.js +8 -8
  33. package/dist/extensions/Blocks/Recommendation/controls/spacing/index.js +113 -151
  34. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +221 -203
  35. package/dist/extensions/Blocks/Recommendation/utils/blockRefresh.js +28 -0
  36. package/dist/extensions/Blocks/Recommendation/utils/captureStyleTemplates.js +1 -1
  37. package/dist/extensions/Blocks/Recommendation/utils/currencySettings.js +25 -0
  38. package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +111 -40
  39. package/dist/extensions/Blocks/Recommendation/utils/strategyCommit.js +31 -35
  40. package/dist/extensions/Blocks/Unsubscribe/block.js +70 -75
  41. package/dist/guido.css +1 -1
  42. package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js +271 -192
  43. package/dist/package.json.js +1 -1
  44. package/dist/services/settingsApi.js +11 -0
  45. package/dist/src/components/Guido.vue.d.ts +1 -1
  46. package/dist/src/components/organisms/header/EditorActions.vue.d.ts +1 -1
  47. package/dist/src/components/organisms/header/HeaderWrapper.vue.d.ts +1 -1
  48. package/dist/src/components/organisms/header/RightSlot.vue.d.ts +1 -1
  49. package/dist/src/composables/useActionsApi.d.ts +5 -1
  50. package/dist/src/composables/useAutoSave.d.ts +4 -1
  51. package/dist/src/composables/useSaveValidationRollout.d.ts +1 -0
  52. package/dist/src/extensions/Blocks/Checkbox/controls/blockBackground/index.d.ts +1 -0
  53. package/dist/src/extensions/Blocks/CouponBlock/controls/index.d.ts +8 -0
  54. package/dist/src/extensions/Blocks/Items/controls/index.d.ts +40 -0
  55. package/dist/src/extensions/Blocks/RadioButton/controls/blockBackground/index.d.ts +1 -0
  56. package/dist/src/extensions/Blocks/Recommendation/block.d.ts +1 -0
  57. package/dist/src/extensions/Blocks/Recommendation/controls/blockBackground/index.d.ts +1 -0
  58. package/dist/src/extensions/Blocks/Recommendation/controls/button/index.d.ts +11 -0
  59. package/dist/src/extensions/Blocks/Recommendation/controls/cardComposition/index.d.ts +3 -6
  60. package/dist/src/extensions/Blocks/Recommendation/controls/customAttribute/index.d.ts +7 -0
  61. package/dist/src/extensions/Blocks/Recommendation/controls/image/index.d.ts +2 -0
  62. package/dist/src/extensions/Blocks/Recommendation/controls/main/currency.d.ts +5 -5
  63. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +21 -12
  64. package/dist/src/extensions/Blocks/Recommendation/controls/main/layoutOrientation.d.ts +6 -3
  65. package/dist/src/extensions/Blocks/Recommendation/controls/main/pricePlacement.d.ts +6 -5
  66. package/dist/src/extensions/Blocks/Recommendation/controls/main/productLayout.d.ts +6 -3
  67. package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +21 -9
  68. package/dist/src/extensions/Blocks/Recommendation/controls/mobileLayout/cssRules.d.ts +19 -13
  69. package/dist/src/extensions/Blocks/Recommendation/controls/name/index.d.ts +7 -0
  70. package/dist/src/extensions/Blocks/Recommendation/controls/oldPrice/index.d.ts +7 -0
  71. package/dist/src/extensions/Blocks/Recommendation/controls/omnibusDiscount/index.d.ts +7 -0
  72. package/dist/src/extensions/Blocks/Recommendation/controls/omnibusPrice/index.d.ts +7 -0
  73. package/dist/src/extensions/Blocks/Recommendation/controls/price/index.d.ts +7 -0
  74. package/dist/src/extensions/Blocks/Recommendation/controls/shared/textTrimCssRules.d.ts +10 -8
  75. package/dist/src/extensions/Blocks/Recommendation/controls/spacing/index.d.ts +9 -5
  76. package/dist/src/extensions/Blocks/Recommendation/controls/title/index.d.ts +7 -0
  77. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +9 -1
  78. package/dist/src/extensions/Blocks/Recommendation/utils/blockRefresh.d.ts +17 -0
  79. package/dist/src/extensions/Blocks/Recommendation/utils/currencySettings.d.ts +6 -0
  80. package/dist/src/extensions/Blocks/Recommendation/utils/nodeConfigWriter.d.ts +18 -11
  81. package/dist/src/extensions/Blocks/Unsubscribe/block.d.ts +1 -6
  82. package/dist/src/extensions/Blocks/_Boilerplate/controls/blockBackground/index.d.ts +1 -0
  83. package/dist/src/extensions/Blocks/controlFactories.d.ts +22 -0
  84. package/dist/src/services/settingsApi.d.ts +6 -0
  85. package/dist/src/stores/editor.d.ts +3 -1
  86. package/dist/src/stores/setup-settings.d.ts +4 -0
  87. package/dist/static/styles/components/button.css.js +5 -0
  88. package/dist/stores/editor.js +5 -0
  89. package/dist/stores/setup-settings.js +10 -0
  90. package/package.json +4 -4
@@ -2,17 +2,17 @@ var at = Object.defineProperty;
2
2
  var ct = (_, g, t) => g in _ ? at(_, g, { enumerable: !0, configurable: !0, writable: !0, value: t }) : _[g] = t;
3
3
  var v = (_, g, t) => ct(_, typeof g != "symbol" ? g + "" : g, t);
4
4
  import { ACADEMY_LINKS as dt } from "../../../../../enums/academy.js";
5
- import { UIElementType as f, UEAttr as O, ModificationDescription as y } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
5
+ import { UIElementType as f, UEAttr as O, ModificationDescription as S } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
6
6
  import { CommonControl as ut } from "../../../common-control.js";
7
7
  import { ATTR_PRODUCT_IMAGE as q, ATTR_PRODUCT_NAME as mt, ATTR_PRODUCT_PRICE as p, ATTR_PRODUCT_OLD_PRICE as I, ATTR_PRODUCT_OMNIBUS_PRICE as ht, ATTR_PRODUCT_OMNIBUS_DISCOUNT as pt, ATTR_PRODUCT_BUTTON as F, ATTR_RECOMMENDATION_TITLE as $, ATTR_DATA_CARD_COMPOSITION as K, ATTR_DATA_CUSTOM_ATTRIBUTES as W, ATTR_CUSTOM_PREFIX as N, SELECTOR_ATTRIBUTE_ROW as E, SELECTOR_TITLE_CELL as z, ATTR_DATA_VISIBILITY as D, ATTR_DATA_ATTRIBUTE_TYPE as R, CSS_CLASS_ATTRIBUTE_ROW as G, CSS_CLASS_SPACER as _t, BUILT_IN_DEFAULT_ATTRIBUTES as gt } from "../../constants/selectors.js";
8
8
  import { DEFAULT_COMPOSITION as Y, DEFAULT_VISIBILITY as X } from "../../constants/defaultConfig.js";
9
- import { RecommendationConfigService as T } from "../../services/configService.js";
9
+ import { RecommendationConfigService as y } from "../../services/configService.js";
10
10
  import { useRecommendationExtensionStore as ft } from "../../store/recommendation.js";
11
11
  import { ATTRIBUTE_CELL_CLASS as bt, gridElementRenderer as yt, DEFAULT_CELL_PADDING as Tt, buildFillerCell as Ct } from "../../templates/grid/elementRenderer.js";
12
12
  import { listElementRenderer as St } from "../../templates/list/elementRenderer.js";
13
13
  import { buildTitleRows as At, DEFAULT_TITLE_PARAGRAPH as It, DEFAULT_TITLE_TEXT as $t } from "../../templates/titleRows.js";
14
14
  import { resolveInlinePriceOrder as vt, toDisplayName as Nt, toDisplayableAttributeValue as Et, buildElementRenderer as J } from "../../templates/utils.js";
15
- import { normalizeCompositionKeys as Rt, normalizeCustomAttrValues as Lt, compositionKeyToProductAttr as k, resolveRowVisibilityKeys as Ot, filterToProductAttrValue as C, findAttributeRow as Dt, rewriteLegacyRowKeyHtml as Q, bareAttributeName as H, isDefaultProductAttr as Ht, productAttrToCompositionKey as M } from "../../utils/compositionKeys.js";
15
+ import { normalizeCompositionKeys as Rt, normalizeCustomAttrValues as Lt, compositionKeyToProductAttr as k, resolveRowVisibilityKeys as Ot, filterToProductAttrValue as T, findAttributeRow as Dt, rewriteLegacyRowKeyHtml as Q, bareAttributeName as H, isDefaultProductAttr as Ht, productAttrToCompositionKey as M } from "../../utils/compositionKeys.js";
16
16
  import { getTableDisplayValue as Pt } from "../../utils/tagName.js";
17
17
  import { isPartnerManagedBlock as wt, regenerateProductRowsWithStyles as Bt, getMainContainerTbody as kt, getCurrentLayout as Mt } from "../main/utils.js";
18
18
  const Ut = "ui-elements-recommendation-card-composition", U = ".product-card-wrapper > tbody", Z = ".product-info-cell > table > tbody", tt = {
@@ -193,7 +193,7 @@ class se extends ut {
193
193
  const t = this.currentNode.getAttribute(K);
194
194
  if (t)
195
195
  return this._normalizeComposition(t.split(",").filter(Boolean));
196
- const { composition: e } = T.getConfig(this.currentNode);
196
+ const { composition: e } = y.getConfig(this.currentNode);
197
197
  return e != null && e.length ? this._normalizeComposition([...e]) : [...Y];
198
198
  }
199
199
  /** Upgrades legacy bare-name custom keys to the canonical form. (SD-147101) */
@@ -222,7 +222,7 @@ class se extends ut {
222
222
  const t = Array.from(this.currentNode.querySelectorAll(E)), e = this._extractVisibilityFromRows(t);
223
223
  if (Object.keys(e).length > 0)
224
224
  return this._withTitlePresence(this._mergeWithDefaults(e));
225
- const r = T.getConfig(this.currentNode).visibility;
225
+ const r = y.getConfig(this.currentNode).visibility;
226
226
  return this._withTitlePresence(this._mergeWithDefaults({ ...r }));
227
227
  }
228
228
  _withTitlePresence(t) {
@@ -282,7 +282,7 @@ class se extends ut {
282
282
  if (s && (u === p || u === I))
283
283
  return u === l.anchor ? this._createPriceGroupItemHtml(d++, l.originalFirst) : "";
284
284
  if (Ft.has(u)) {
285
- const h = m.find((S) => S.key === u);
285
+ const h = m.find((C) => C.key === u);
286
286
  return this._createBuiltInItemHtml(h, d++);
287
287
  }
288
288
  if (u.startsWith(N)) {
@@ -397,13 +397,13 @@ class se extends ut {
397
397
  const i = /* @__PURE__ */ new Map();
398
398
  r.forEach((o) => i.set(o.attributeName, (i.get(o.attributeName) ?? 0) + 1));
399
399
  const s = new Set(e);
400
- return s.delete(t), r.filter((o) => !s.has(C(o))).map((o) => ({
400
+ return s.delete(t), r.filter((o) => !s.has(T(o))).map((o) => ({
401
401
  text: this._toOptionLabel(
402
402
  o.displayName,
403
403
  o.type === "defaultAttribute",
404
404
  (i.get(o.attributeName) ?? 0) > 1
405
405
  ),
406
- value: C(o)
406
+ value: T(o)
407
407
  }));
408
408
  }
409
409
  /**
@@ -536,8 +536,8 @@ class se extends ut {
536
536
  return;
537
537
  const r = e.querySelector("[data-composition-list]"), i = e.querySelector("#guido__btn-add-attribute");
538
538
  r && (this._setupDragAndDrop(r, t), this._setupDeleteHandler(r, t)), i && i.addEventListener("click", () => {
539
- const s = new Set(this._readCustomAttributesFromNode()), o = this._getAddableFilters().find((n) => !s.has(C(n)));
540
- o && this._onAddAttribute(C(o), o.displayName);
539
+ const s = new Set(this._readCustomAttributesFromNode()), o = this._getAddableFilters().find((n) => !s.has(T(n)));
540
+ o && this._onAddAttribute(T(o), o.displayName);
541
541
  }, { signal: t });
542
542
  }
543
543
  /**
@@ -620,8 +620,8 @@ class se extends ut {
620
620
  _onAddAttribute(t, e) {
621
621
  const r = M(t), i = this._readCompositionFromNode();
622
622
  i.push(r);
623
- const s = [...this._readCustomAttributesFromNode(), t];
624
- this._updateBothAttributes(i, s), this._injectCustomAttributeHtml(t, e, r, i), this._renderOrderableItems(i, s), this._initializeCustomSelects(s), this._updateAddButtonState();
623
+ const s = [...this._readCustomAttributesFromNode(), t], o = this.api.getDocumentModifier();
624
+ this._injectCustomAttributeHtml(o, t, e, r, i), this._stageBothAttributes(o, i, s), o.apply(new S(`${this.api.translate("Add custom attribute")}: ${e}`)), this._renderOrderableItems(i, s), this._initializeCustomSelects(s), this._updateAddButtonState();
625
625
  }
626
626
  /**
627
627
  * Removes a single custom attribute by its index in the customAttrs array.
@@ -631,8 +631,8 @@ class se extends ut {
631
631
  const e = this._readCustomAttributesFromNode();
632
632
  if (e[t] === void 0)
633
633
  return;
634
- const i = this._readCompositionFromNode(), s = this._findNthCustomKeyIndex(i, t), o = i.filter((l, a) => a !== s), n = e.filter((l, a) => a !== t);
635
- this._updateBothAttributes(o, n), this._removeCustomAttributeHtml(o), this._renderOrderableItems(o, n), this._initializeCustomSelects(n), this._updateAddButtonState();
634
+ const i = this._readCompositionFromNode(), s = this._findNthCustomKeyIndex(i, t), o = i.filter((a, d) => d !== s), n = e.filter((a, d) => d !== t), l = this.api.getDocumentModifier();
635
+ this._removeCustomAttributeHtml(l, o), this._stageBothAttributes(l, o, n), l.apply(new S(this.api.translate("Remove custom attribute"))), this._renderOrderableItems(o, n), this._initializeCustomSelects(n), this._updateAddButtonState();
636
636
  }
637
637
  /**
638
638
  * Handles changing a custom attribute's selection via its inline _GuSelect.
@@ -644,19 +644,22 @@ class se extends ut {
644
644
  return;
645
645
  const s = M(e), o = this._readCompositionFromNode(), n = this._findNthCustomKeyIndex(o, t);
646
646
  n !== -1 && (o[n] = s), r[t] = e;
647
- const l = this._getDisplayNameForAttribute(e);
648
- this._updateBothAttributes(o, r), this._injectCustomAttributeHtml(e, l, s, o), this._renderOrderableItems(o, r), this._initializeCustomSelects(r);
647
+ const l = this._getDisplayNameForAttribute(e), a = this.api.getDocumentModifier();
648
+ this._injectCustomAttributeHtml(a, e, l, s, o), this._stageBothAttributes(a, o, r), a.apply(new S(this.api.translate("Update card composition"))), this._renderOrderableItems(o, r), this._initializeCustomSelects(r);
649
649
  }
650
650
  _onReorder(t) {
651
+ if (!this.currentNode)
652
+ return;
651
653
  const e = t.filter((r) => r.startsWith(N)).map(k);
652
654
  this.reorderInProgress = !0;
653
655
  try {
654
- this._updateBothAttributes(t, e);
655
- const r = this._isInlinePrices();
656
- this._getCurrentLayout() === "grid" && !r ? this._reorderProductAttributes(t) : this.currentNode && Bt({
656
+ const r = this.api.getDocumentModifier(), i = this._isInlinePrices();
657
+ this._getCurrentLayout() === "grid" && !i ? this._reorderProductAttributes(r, t) : Bt({
657
658
  currentNode: this.currentNode,
658
- documentModifier: this.api.getDocumentModifier()
659
- });
659
+ documentModifier: r,
660
+ composition: t,
661
+ stageOnly: !0
662
+ }), this._stageBothAttributes(r, t, e), r.apply(new S(this.api.translate("Reorder product attributes")));
660
663
  } finally {
661
664
  this.reorderInProgress = !1;
662
665
  }
@@ -679,119 +682,111 @@ class se extends ut {
679
682
  );
680
683
  return i && "getOuterHTML" in i ? Q(i.getOuterHTML(), e) : "";
681
684
  }
682
- _injectCustomAttributeHtml(t, e, r, i) {
685
+ _injectCustomAttributeHtml(t, e, r, i, s) {
683
686
  if (!this.currentNode)
684
687
  return;
685
- this._getCurrentLayout() === "grid" ? this._injectGridAttributeRow(t, e, r, i) : this._injectListAttributeRow(t, e, r, i);
688
+ this._getCurrentLayout() === "grid" ? this._injectGridAttributeRow(t, e, r, i, s) : this._injectListAttributeRow(t, e, r, i, s);
686
689
  }
687
- _injectGridAttributeRow(t, e, r, i) {
688
- const s = this.currentNode.querySelectorAll(U);
689
- if (!(s != null && s.length))
690
+ _injectGridAttributeRow(t, e, r, i, s) {
691
+ const o = this.currentNode.querySelectorAll(U);
692
+ if (!(o != null && o.length))
690
693
  return;
691
- const o = T.getConfig(this.currentNode), l = `0 ${Math.floor(o.columnSpacing / 2)}px`, a = this.api.getDocumentModifier(), d = this.store.recommendationProducts.length;
694
+ const n = y.getConfig(this.currentNode), a = `0 ${Math.floor(n.columnSpacing / 2)}px`, d = this.store.recommendationProducts.length;
692
695
  let c = 0;
693
- s.forEach((u) => {
696
+ o.forEach((u) => {
694
697
  var V;
695
- const h = u.querySelector(E), S = ((V = h == null ? void 0 : h.querySelectorAll(`.${bt}`)) == null ? void 0 : V.length) || 1, x = (100 / S).toFixed(2), { bgStyle: et, bgAttr: rt } = this._extractSegmentBgFromCard(u), B = d > 0 ? Math.min(S, d - c) : S, it = i.map((j) => {
696
- if (j === r) {
698
+ const h = u.querySelector(E), C = ((V = h == null ? void 0 : h.querySelectorAll(`.${bt}`)) == null ? void 0 : V.length) || 1, x = (100 / C).toFixed(2), { bgStyle: et, bgAttr: rt } = this._extractSegmentBgFromCard(u), B = d > 0 ? Math.min(C, d - c) : C, it = s.map((j) => {
699
+ if (j === i) {
697
700
  const st = Array.from(
698
701
  { length: B },
699
702
  (xt, nt) => {
700
703
  const lt = this._resolveAttributeContent(
701
- t,
702
704
  e,
705
+ r,
703
706
  c + nt
704
707
  );
705
708
  return this._getGridCellHtml(
706
- t,
709
+ e,
707
710
  lt,
708
711
  x,
709
712
  et,
710
713
  rt,
711
- l
714
+ a
712
715
  );
713
716
  }
714
- ).join(""), ot = Ct(x, l).repeat(S - B);
715
- return `<tr class="${G}" ${R}="${r}" ${D}="1">${st}${ot}</tr>`;
717
+ ).join(""), ot = Ct(x, a).repeat(C - B);
718
+ return `<tr class="${G}" ${R}="${i}" ${D}="1">${st}${ot}</tr>`;
716
719
  }
717
720
  return this._getExistingRowHtml(u, j);
718
721
  }).join("");
719
- c += B, d > 0 && c >= d && (c = 0), a.modifyHtml(u).setInnerHtml(it);
720
- }), a.apply(new y(`${this.api.translate("Add custom attribute")}: ${e}`));
722
+ c += B, d > 0 && c >= d && (c = 0), t.modifyHtml(u).setInnerHtml(it);
723
+ });
721
724
  }
722
- _injectListAttributeRow(t, e, r, i) {
723
- const s = this.currentNode.querySelectorAll(Z);
724
- if (!(s != null && s.length))
725
+ _injectListAttributeRow(t, e, r, i, s) {
726
+ const o = this.currentNode.querySelectorAll(Z);
727
+ if (!(o != null && o.length))
725
728
  return;
726
- const o = i.filter((l) => l !== q && l !== F), n = this.api.getDocumentModifier();
727
- s.forEach((l, a) => {
728
- const d = o.map((c) => {
729
- if (c === r) {
730
- const u = this._resolveAttributeContent(t, e, a);
731
- return this._getListRowHtml(t, u, r);
729
+ const n = s.filter((l) => l !== q && l !== F);
730
+ o.forEach((l, a) => {
731
+ const d = n.map((c) => {
732
+ if (c === i) {
733
+ const u = this._resolveAttributeContent(e, r, a);
734
+ return this._getListRowHtml(e, u, i);
732
735
  }
733
736
  return this._getExistingRowHtml(l, c);
734
737
  }).join("");
735
- n.modifyHtml(l).setInnerHtml(d);
736
- }), n.apply(new y(`${this.api.translate("Add custom attribute")}: ${e}`));
738
+ t.modifyHtml(l).setInnerHtml(d);
739
+ });
737
740
  }
738
741
  /**
739
742
  * Removes a custom attribute by rebuilding product card content without it.
740
743
  * The composition parameter should already have the deleted key removed.
741
744
  */
742
- _removeCustomAttributeHtml(t) {
745
+ _removeCustomAttributeHtml(t, e) {
743
746
  if (!this.currentNode)
744
747
  return;
745
- const e = this._getCurrentLayout(), r = this.api.getDocumentModifier();
746
- if (e === "grid") {
748
+ if (this._getCurrentLayout() === "grid") {
747
749
  const i = this.currentNode.querySelectorAll(U);
748
750
  i == null || i.forEach((s) => {
749
- const o = this._buildCompositionHtml(s, t);
750
- r.modifyHtml(s).setInnerHtml(o);
751
+ const o = this._buildCompositionHtml(s, e);
752
+ t.modifyHtml(s).setInnerHtml(o);
751
753
  });
752
754
  } else {
753
- const i = t.filter((o) => o !== q && o !== F), s = this.currentNode.querySelectorAll(Z);
755
+ const i = e.filter((o) => o !== q && o !== F), s = this.currentNode.querySelectorAll(Z);
754
756
  s == null || s.forEach((o) => {
755
757
  const n = this._buildCompositionHtml(o, i);
756
- r.modifyHtml(o).setInnerHtml(n);
758
+ t.modifyHtml(o).setInnerHtml(n);
757
759
  });
758
760
  }
759
- r.apply(new y(this.api.translate("Remove custom attribute")));
760
761
  }
761
762
  // ========================================================================
762
763
  // DOM Mutation (Block Root Attributes, Reorder)
763
764
  // ========================================================================
764
765
  /**
765
- * Atomically updates both composition and custom-attributes in a single apply()
766
- * so that onTemplateNodeUpdated fires only once with fully consistent state.
767
- * Two separate apply() calls would cause an intermediate onTemplateNodeUpdated
768
- * where composition is updated but customAttributes still has the old order,
769
- * producing a flicker on the custom attribute dropdowns.
766
+ * Stages composition and custom-attributes into the caller's batch, so one apply()
767
+ * lands both with the card DOM and onTemplateNodeUpdated sees consistent state.
770
768
  */
771
- _updateBothAttributes(t, e) {
769
+ _stageBothAttributes(t, e, r) {
772
770
  if (!this.currentNode)
773
771
  return;
774
- const r = {
775
- ...T.getConfig(this.currentNode),
776
- composition: t
772
+ const i = {
773
+ ...y.getConfig(this.currentNode),
774
+ composition: e
777
775
  };
778
- this.api.getDocumentModifier().modifyHtml(this.currentNode).setAttribute(K, t.join(",")).setAttribute(W, JSON.stringify(e)).setNodeConfig(r).apply(new y(this.api.translate("Update card composition")));
776
+ t.modifyHtml(this.currentNode).setAttribute(K, e.join(",")).setAttribute(W, JSON.stringify(r)).setNodeConfig(i);
779
777
  }
780
778
  /**
781
779
  * Reorders attribute rows within each product card based on composition order.
782
780
  * Only used for grid layout (list layout has fixed 3-column structure).
783
781
  */
784
- _reorderProductAttributes(t) {
782
+ _reorderProductAttributes(t, e) {
785
783
  if (!this.currentNode)
786
784
  return;
787
- const e = this.currentNode.querySelectorAll(U);
788
- if (!(e != null && e.length))
789
- return;
790
- const r = this.api.getDocumentModifier();
791
- e.forEach((i) => {
792
- const s = this._buildCompositionHtml(i, t);
793
- r.modifyHtml(i).setInnerHtml(s);
794
- }), r.apply(new y(this.api.translate("Reorder product attributes")));
785
+ const r = this.currentNode.querySelectorAll(U);
786
+ r != null && r.length && r.forEach((i) => {
787
+ const s = this._buildCompositionHtml(i, e);
788
+ t.modifyHtml(i).setInnerHtml(s);
789
+ });
795
790
  }
796
791
  /**
797
792
  * Builds HTML string with attributes ordered according to composition.
@@ -819,23 +814,23 @@ class se extends ut {
819
814
  a.modifyHtml(c).setStyle("display", h).setAttribute(D, o);
820
815
  });
821
816
  const d = {
822
- ...T.getConfig(this.currentNode),
817
+ ...y.getConfig(this.currentNode),
823
818
  visibility: {
824
819
  ...this._readVisibilityFromRows(),
825
820
  ...Object.fromEntries(r.map((c) => [c, e]))
826
821
  }
827
822
  };
828
- a.modifyHtml(this.currentNode).setNodeConfig(d), a.apply(new y(l));
823
+ a.modifyHtml(this.currentNode).setNodeConfig(d), a.apply(new S(l));
829
824
  }
830
825
  /** Inline "Product Prices" group row is tagged with whichever price comes first, so it drives both keys. */
831
826
  _resolveVisibilityKeys(t) {
832
827
  return this._isInlinePrices() && t === p ? [p, I] : [t];
833
828
  }
834
829
  _isInlinePrices() {
835
- return !T.getConfig(this.currentNode).priceMovedToNextLine;
830
+ return !y.getConfig(this.currentNode).priceMovedToNextLine;
836
831
  }
837
832
  _applyTitleVisibilityToBlock(t) {
838
- const e = T.getConfig(this.currentNode), r = t ? this._resolveTitleInjection(e) : null, i = t ? [] : this._findTitleRows(), s = t ? this._hasTitle() || !r : i.length === 0;
833
+ const e = y.getConfig(this.currentNode), r = t ? this._resolveTitleInjection(e) : null, i = t ? [] : this._findTitleRows(), s = t ? this._hasTitle() || !r : i.length === 0;
839
834
  if (!this.currentNode || s)
840
835
  return;
841
836
  const o = this.api.getDocumentModifier();
@@ -845,7 +840,7 @@ class se extends ut {
845
840
  visibility: { ...this._readVisibilityFromRows(), [$]: t }
846
841
  });
847
842
  const n = t ? this.api.translate("visible") : this.api.translate("hidden");
848
- o.apply(new y(
843
+ o.apply(new S(
849
844
  `${this.api.translate("Set visibility")}: ${$} → ${n}`
850
845
  ));
851
846
  }
@@ -956,7 +951,7 @@ class se extends ut {
956
951
  * or when all available filters have already been added (no unused attributes left).
957
952
  */
958
953
  _updateAddButtonState() {
959
- const t = this._readCustomAttributesFromNode(), e = t.length >= b, r = new Set(t), i = this._getAddableFilters(), s = i.length > 0 && i.every((o) => r.has(C(o)));
954
+ const t = this._readCustomAttributesFromNode(), e = t.length >= b, r = new Set(t), i = this._getAddableFilters(), s = i.length > 0 && i.every((o) => r.has(T(o)));
960
955
  this.api.setUIEAttribute(
961
956
  tt.ADD_ATTRIBUTE,
962
957
  O.BUTTON.disabled,
@@ -989,7 +984,7 @@ class se extends ut {
989
984
  _getAddableFilters() {
990
985
  const t = /* @__PURE__ */ new Set();
991
986
  return Object.values(this.store.filterList).filter((e) => !(e.type === "defaultAttribute" && gt.has(e.attributeName))).filter((e) => {
992
- const r = C(e);
987
+ const r = T(e);
993
988
  return t.has(r) ? !1 : (t.add(r), !0);
994
989
  });
995
990
  }
@@ -999,7 +994,7 @@ class se extends ut {
999
994
  * resolve to their own entry. Falls back to Title Case of the bare name.
1000
995
  */
1001
996
  _getDisplayNameForAttribute(t) {
1002
- const e = Object.values(this.store.filterList).find((r) => C(r) === t);
997
+ const e = Object.values(this.store.filterList).find((r) => T(r) === t);
1003
998
  return e ? e.displayName : Nt(H(t));
1004
999
  }
1005
1000
  /**
@@ -78,11 +78,10 @@ class g extends m {
78
78
  const e = this._getTargetElements();
79
79
  if (!e.length)
80
80
  return;
81
- t && c(this.api);
82
81
  const r = this.api.getDocumentModifier();
83
82
  e.forEach((s) => {
84
83
  t ? r.modifyHtml(s).setClass(o) : r.modifyHtml(s).removeClass(o);
85
- }), r.apply(
84
+ }), t && c(this.api, r), r.apply(
86
85
  new T(
87
86
  t ? "Enable custom attribute text trimming" : "Disable custom attribute text trimming"
88
87
  )
@@ -77,12 +77,7 @@ class R extends g {
77
77
  this.store.recommendationConfigs.strategy !== t && this.store.patchCurrentBlockConfig({ strategy: e.strategy, filters: e.filters });
78
78
  return;
79
79
  }
80
- n.updateConfig(
81
- this.api,
82
- this.currentNode,
83
- { strategy: t },
84
- `Changed algorithm to ${t}`
85
- ), this.store.patchCurrentBlockConfig({ strategy: t }), this._setProductIdsVisibility(t);
80
+ this.store.recommendationConfigs.strategy !== t && this.store.patchCurrentBlockConfig({ strategy: t }), this._setProductIdsVisibility(t);
86
81
  }
87
82
  _onProductIdsChange(t) {
88
83
  if (!this.currentNode)
@@ -93,12 +88,7 @@ class R extends g {
93
88
  return;
94
89
  }
95
90
  const o = t === "" ? [] : t.split(",");
96
- n.updateConfig(
97
- this.api,
98
- this.currentNode,
99
- { productIds: o },
100
- "Updated product IDs"
101
- ), this.store.patchCurrentBlockConfig({ productIds: o });
91
+ this.store.recommendationConfigs.productIds.join(",") !== t && this.store.patchCurrentBlockConfig({ productIds: o });
102
92
  }
103
93
  _listenToFormUpdates() {
104
94
  this.api.onValueChanged(i.ALGORITHM, (t) => {