@useinsider/guido 3.8.3-beta.96b5eeb → 3.9.0-beta.ba394b1

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 (67) hide show
  1. package/dist/@types/config/schemas.js +70 -66
  2. package/dist/composables/useCustomInterfaceAppearance.js +16 -18
  3. package/dist/composables/usePreviewMode.js +15 -14
  4. package/dist/composables/useRecommendationPreview.js +111 -0
  5. package/dist/composables/useStripo.js +39 -37
  6. package/dist/composables/useStripoNotifications.js +26 -0
  7. package/dist/config/compiler/recommendationCompilerRules.js +1 -1
  8. package/dist/config/compiler/utils/recommendationCompilerUtils.js +88 -80
  9. package/dist/config/migrator/recommendation/htmlBuilder.js +53 -52
  10. package/dist/config/migrator/recommendation/settingsMapper.js +38 -33
  11. package/dist/enums/toaster.js +2 -2
  12. package/dist/extensions/Blocks/Items/block.js +48 -29
  13. package/dist/extensions/Blocks/Items/utils/nodeConfigUtils.js +62 -45
  14. package/dist/extensions/Blocks/Recommendation/block.js +64 -42
  15. package/dist/extensions/Blocks/Recommendation/canvasPreview.css.js +16 -0
  16. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +41 -32
  17. package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +461 -363
  18. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +99 -87
  19. package/dist/extensions/Blocks/Recommendation/controls/main/pricePlacement.js +133 -0
  20. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +162 -160
  21. package/dist/extensions/Blocks/Recommendation/extension.js +30 -29
  22. package/dist/extensions/Blocks/Recommendation/iconsRegistry.js +21 -7
  23. package/dist/extensions/Blocks/Recommendation/recommendation.css.js +64 -4
  24. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +3 -1
  25. package/dist/extensions/Blocks/Recommendation/templates/grid/elementRenderer.js +130 -96
  26. package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +43 -54
  27. package/dist/extensions/Blocks/Recommendation/templates/index.js +17 -14
  28. package/dist/extensions/Blocks/Recommendation/templates/list/elementRenderer.js +86 -80
  29. package/dist/extensions/Blocks/Recommendation/templates/list/template.js +31 -40
  30. package/dist/extensions/Blocks/Recommendation/templates/utils.js +155 -102
  31. package/dist/extensions/Blocks/Recommendation/useRecommendationBlockWarning.js +7 -7
  32. package/dist/extensions/Blocks/controlFactories.js +76 -57
  33. package/dist/services/templateLibraryApi.js +9 -8
  34. package/dist/src/@types/config/schemas.d.ts +16 -0
  35. package/dist/src/composables/useConfig.d.ts +4 -0
  36. package/dist/src/composables/useRecommendationPreview.d.ts +10 -0
  37. package/dist/src/composables/useStripoNotifications.d.ts +10 -0
  38. package/dist/src/config/migrator/recommendation/settingsMapper.d.ts +1 -1
  39. package/dist/src/enums/toaster.d.ts +2 -2
  40. package/dist/src/extensions/Blocks/CouponBlock/controls/index.d.ts +1 -1
  41. package/dist/src/extensions/Blocks/Items/block.d.ts +8 -0
  42. package/dist/src/extensions/Blocks/Items/controls/index.d.ts +3 -3
  43. package/dist/src/extensions/Blocks/Items/utils/nodeConfigUtils.d.ts +1 -1
  44. package/dist/src/extensions/Blocks/Recommendation/block.d.ts +10 -0
  45. package/dist/src/extensions/Blocks/Recommendation/controls/cardComposition/index.d.ts +29 -3
  46. package/dist/src/extensions/Blocks/Recommendation/controls/index.d.ts +1 -1
  47. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +3 -1
  48. package/dist/src/extensions/Blocks/Recommendation/controls/main/pricePlacement.d.ts +59 -0
  49. package/dist/src/extensions/Blocks/Recommendation/controls/name/index.d.ts +1 -1
  50. package/dist/src/extensions/Blocks/Recommendation/controls/oldPrice/index.d.ts +1 -1
  51. package/dist/src/extensions/Blocks/Recommendation/controls/omnibusDiscount/index.d.ts +1 -1
  52. package/dist/src/extensions/Blocks/Recommendation/controls/omnibusPrice/index.d.ts +1 -1
  53. package/dist/src/extensions/Blocks/Recommendation/controls/price/index.d.ts +1 -1
  54. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +2 -0
  55. package/dist/src/extensions/Blocks/Recommendation/templates/grid/elementRenderer.d.ts +13 -1
  56. package/dist/src/extensions/Blocks/Recommendation/templates/grid/template.d.ts +4 -4
  57. package/dist/src/extensions/Blocks/Recommendation/templates/index.d.ts +1 -1
  58. package/dist/src/extensions/Blocks/Recommendation/templates/list/elementRenderer.d.ts +10 -1
  59. package/dist/src/extensions/Blocks/Recommendation/templates/list/template.d.ts +3 -3
  60. package/dist/src/extensions/Blocks/Recommendation/templates/utils.d.ts +51 -1
  61. package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +15 -0
  62. package/dist/src/extensions/Blocks/controlFactories.d.ts +10 -1
  63. package/dist/src/stores/config.d.ts +36 -0
  64. package/dist/src/stores/toaster.d.ts +2 -3
  65. package/dist/stores/toaster.js +10 -10
  66. package/package.json +2 -2
  67. package/dist/static/styles/components/notification.css.js +0 -74
@@ -1,69 +1,69 @@
1
- var J = Object.defineProperty;
2
- var Q = (p, _, t) => _ in p ? J(p, _, { enumerable: !0, configurable: !0, writable: !0, value: t }) : p[_] = t;
3
- var T = (p, _, t) => Q(p, typeof _ != "symbol" ? _ + "" : _, t);
4
- import { UIElementType as f, UEAttr as I, ModificationDescription as A } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
5
- import { CommonControl as Z } from "../../../common-control.js";
6
- import { ATTR_PRODUCT_IMAGE as L, ATTR_PRODUCT_NAME as tt, ATTR_PRODUCT_PRICE as et, ATTR_PRODUCT_OLD_PRICE as rt, ATTR_PRODUCT_OMNIBUS_PRICE as ot, ATTR_PRODUCT_OMNIBUS_DISCOUNT as st, ATTR_PRODUCT_BUTTON as B, ATTR_DATA_CUSTOM_ATTRIBUTES as q, ATTR_CUSTOM_PREFIX as m, BUILT_IN_DEFAULT_ATTRIBUTES as it } from "../../constants/selectors.js";
7
- import { DEFAULT_COMPOSITION as P, DEFAULT_VISIBILITY as F } from "../../constants/defaultConfig.js";
8
- import { RecommendationConfigService as nt } from "../../services/configService.js";
1
+ var tt = Object.defineProperty;
2
+ var et = (g, b, t) => b in g ? tt(g, b, { enumerable: !0, configurable: !0, writable: !0, value: t }) : g[b] = t;
3
+ var v = (g, b, t) => et(g, typeof b != "symbol" ? b + "" : b, t);
4
+ import { UIElementType as f, UEAttr as D, ModificationDescription as T } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
5
+ import { CommonControl as rt } from "../../../common-control.js";
6
+ import { ATTR_PRODUCT_IMAGE as k, ATTR_PRODUCT_NAME as it, ATTR_PRODUCT_PRICE as S, ATTR_PRODUCT_OLD_PRICE as N, ATTR_PRODUCT_OMNIBUS_PRICE as ot, ATTR_PRODUCT_OMNIBUS_DISCOUNT as st, ATTR_PRODUCT_BUTTON as U, ATTR_DATA_CUSTOM_ATTRIBUTES as F, ATTR_CUSTOM_PREFIX as m, BUILT_IN_DEFAULT_ATTRIBUTES as nt } from "../../constants/selectors.js";
7
+ import { DEFAULT_COMPOSITION as x, DEFAULT_VISIBILITY as M } from "../../constants/defaultConfig.js";
8
+ import { RecommendationConfigService as y } from "../../services/configService.js";
9
9
  import { useRecommendationExtensionStore as lt } from "../../store/recommendation.js";
10
- import { ATTRIBUTE_CELL_CLASS as at, gridElementRenderer as ct, DEFAULT_CELL_PADDING as ut, buildFillerCell as dt } from "../../templates/grid/elementRenderer.js";
10
+ import { ATTRIBUTE_CELL_CLASS as at, gridElementRenderer as ct, DEFAULT_CELL_PADDING as dt, buildFillerCell as ut } from "../../templates/grid/elementRenderer.js";
11
11
  import { listElementRenderer as mt } from "../../templates/list/elementRenderer.js";
12
- import { toDisplayName as ht, isDefaultAttribute as pt, toDisplayableAttributeValue as _t, buildElementRenderer as w } from "../../templates/utils.js";
12
+ import { resolveInlinePriceOrder as ht, toDisplayName as pt, isDefaultAttribute as gt, toDisplayableAttributeValue as bt, buildElementRenderer as V } from "../../templates/utils.js";
13
13
  import { getTableDisplayValue as ft } from "../../utils/tagName.js";
14
- import { isPartnerManagedBlock as gt, getCurrentLayout as bt } from "../main/utils.js";
15
- const yt = "ui-elements-recommendation-card-composition", S = ".recommendation-attribute-row", N = ".product-card-wrapper > tbody", M = ".product-info-cell > table > tbody", V = "data-card-composition", y = "data-attribute-type", v = "data-visibility", x = {
14
+ import { isPartnerManagedBlock as _t, regenerateProductRowsWithStyles as yt, getCurrentLayout as Ct } from "../main/utils.js";
15
+ const St = "ui-elements-recommendation-card-composition", $ = ".recommendation-attribute-row", H = ".product-card-wrapper > tbody", j = ".product-info-cell > table > tbody", W = "data-card-composition", C = "data-attribute-type", E = "data-visibility", K = {
16
16
  ADD_ATTRIBUTE: "addAttribute"
17
- }, g = 5, E = "reorderIcon_", h = [
18
- { key: L, label: "Product Image" },
19
- { key: tt, label: "Product Name" },
20
- { key: et, label: "Product Price" },
21
- { key: rt, label: "Product Original Price" },
17
+ }, _ = 5, O = "reorderIcon_", At = '<svg width="14" height="10" viewBox="0 0 14 10" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><circle cx="2" cy="2.5" r="1.2"/><circle cx="7" cy="2.5" r="1.2"/><circle cx="12" cy="2.5" r="1.2"/><circle cx="2" cy="7.5" r="1.2"/><circle cx="7" cy="7.5" r="1.2"/><circle cx="12" cy="7.5" r="1.2"/></svg>', h = [
18
+ { key: k, label: "Product Image" },
19
+ { key: it, label: "Product Name" },
20
+ { key: S, label: "Product Price" },
21
+ { key: N, label: "Product Original Price" },
22
22
  { key: ot, label: "Omnibus Price" },
23
23
  { key: st, label: "Omnibus Discount" },
24
- { key: B, label: "Product Button" }
25
- ], At = new Set(h.map((p) => p.key)), C = "customAttr_", R = "deleteAttr_";
26
- class Ut extends Z {
24
+ { key: U, label: "Product Button" }
25
+ ], Tt = new Set(h.map((g) => g.key)), I = "customAttr_", R = "deleteAttr_";
26
+ class qt extends rt {
27
27
  constructor() {
28
28
  super(...arguments);
29
- T(this, "store", lt());
30
- T(this, "unsubscribeStore", null);
31
- T(this, "eventController", null);
29
+ v(this, "store", lt());
30
+ v(this, "unsubscribeStore", null);
31
+ v(this, "eventController", null);
32
32
  /**
33
33
  * Guard flag: when true, onTemplateNodeUpdated skips _initializeComposition.
34
34
  * Used during _onReorder to prevent multiple intermediate rebuilds.
35
35
  */
36
- T(this, "reorderInProgress", !1);
36
+ v(this, "reorderInProgress", !1);
37
37
  }
38
38
  getId() {
39
- return yt;
39
+ return St;
40
40
  }
41
41
  // ========================================================================
42
42
  // Lifecycle
43
43
  // ========================================================================
44
44
  getTemplate() {
45
- const t = h.map((l) => `
46
- <div data-toggle-key="${l.key}" style="display: none;">
47
- ${this._GuToggle(`visibility_${l.key}`)}
45
+ const t = h.map((a) => `
46
+ <div data-toggle-key="${a.key}" style="display: none;">
47
+ ${this._GuToggle(`visibility_${a.key}`)}
48
48
  </div>
49
- `).join(""), r = Array.from(
50
- { length: g },
51
- (l, u) => `
52
- <div data-custom-select-key="${C}${u}" style="display: none;">
49
+ `).join(""), e = Array.from(
50
+ { length: _ },
51
+ (a, d) => `
52
+ <div data-custom-select-key="${I}${d}" style="display: none;">
53
53
  ${this._GuSelect({
54
- name: `${C}${u}`,
54
+ name: `${I}${d}`,
55
55
  placeholder: this.api.translate("Select Attribute"),
56
56
  options: []
57
57
  })}
58
58
  </div>
59
59
  `
60
- ).join(""), e = h.length + g, o = Array.from(
61
- { length: e },
62
- (l, u) => `
63
- <div data-reorder-icon-key="${E}${u}" style="display: none;">
60
+ ).join(""), r = h.length + _, o = Array.from(
61
+ { length: r },
62
+ (a, d) => `
63
+ <div data-reorder-icon-key="${O}${d}" style="display: none;">
64
64
  <${f.BUTTON}
65
65
  class="drag-handle-btn flat-inline flat-white"
66
- ${I.BUTTON.name}="${E}${u}"
66
+ ${D.BUTTON.name}="${O}${d}"
67
67
  >
68
68
  <${f.ICON}
69
69
  src="reorder"
@@ -72,13 +72,13 @@ class Ut extends Z {
72
72
  </${f.BUTTON}>
73
73
  </div>
74
74
  `
75
- ).join(""), s = Array.from(
76
- { length: g },
77
- (l, u) => `
78
- <div data-custom-delete-key="${R}${u}" style="display: none;">
75
+ ).join(""), i = Array.from(
76
+ { length: _ },
77
+ (a, d) => `
78
+ <div data-custom-delete-key="${R}${d}" style="display: none;">
79
79
  <${f.BUTTON}
80
80
  class="custom-attr-delete flat-inline flat-white"
81
- ${I.BUTTON.name}="${R}${u}"
81
+ ${D.BUTTON.name}="${R}${d}"
82
82
  >
83
83
  <${f.ICON}
84
84
  src="delete"
@@ -87,17 +87,17 @@ class Ut extends Z {
87
87
  </${f.BUTTON}>
88
88
  </div>
89
89
  `
90
- ).join(""), i = "https://academy.insiderone.com/docs/new-editor-email-recommendation-block", n = this.api.translate(
90
+ ).join(""), s = "https://academy.insiderone.com/docs/new-editor-email-recommendation-block", n = this.api.translate(
91
91
  "Drag and drop the card elements to reorder them, adjust their visibility or add new attributes up to 5."
92
- ), a = this.api.translate("For more information, you can"), c = this.api.translate("visit Academy");
92
+ ), c = this.api.translate("For more information, you can"), l = this.api.translate("visit Academy");
93
93
  return `
94
94
  <div class="recommendation-controls-container" data-card-composition-control>
95
95
  <div class="container">
96
96
  <p class="card-composition-description">
97
97
  ${n}
98
- ${a}
98
+ ${c}
99
99
  <!-- cspell:disable-next-line -->
100
- <a href="${i}" target="_blank" rel="noopener noreferrer">${c}</a>.
100
+ <a href="${s}" target="_blank" rel="noopener noreferrer">${l}</a>.
101
101
  </p>
102
102
  </div>
103
103
 
@@ -106,11 +106,11 @@ class Ut extends Z {
106
106
  </div>
107
107
 
108
108
  <div class="custom-select-store" style="display: none;">
109
- ${r}
109
+ ${e}
110
110
  </div>
111
111
 
112
112
  <div class="custom-delete-store" style="display: none;">
113
- ${s}
113
+ ${i}
114
114
  </div>
115
115
 
116
116
  <div class="reorder-icon-store" style="display: none;">
@@ -120,7 +120,7 @@ class Ut extends Z {
120
120
  <div class="orderable-list" data-composition-list></div>
121
121
 
122
122
  ${this._GuButton({
123
- name: x.ADD_ATTRIBUTE,
123
+ name: K.ADD_ATTRIBUTE,
124
124
  label: this.api.translate("Add Attribute"),
125
125
  id: "guido__btn-add-attribute"
126
126
  })}
@@ -137,12 +137,12 @@ class Ut extends Z {
137
137
  * container is rendered inert (greyed + non-interactive) instead.
138
138
  */
139
139
  _syncDisabledState() {
140
- var e;
141
- const t = (e = this.getContainer()) == null ? void 0 : e.querySelector("[data-card-composition-control]");
140
+ var r;
141
+ const t = (r = this.getContainer()) == null ? void 0 : r.querySelector("[data-card-composition-control]");
142
142
  if (!t)
143
143
  return;
144
- const r = gt(this.currentNode);
145
- t.style.pointerEvents = r ? "none" : "", t.style.opacity = r ? "0.5" : "";
144
+ const e = _t(this.currentNode);
145
+ t.style.pointerEvents = e ? "none" : "", t.style.opacity = e ? "0.5" : "";
146
146
  }
147
147
  onTemplateNodeUpdated(t) {
148
148
  super.onTemplateNodeUpdated(t), !this.reorderInProgress && (this._initializeComposition(), this._updateOrderableState(), this._syncDisabledState());
@@ -154,19 +154,19 @@ class Ut extends Z {
154
154
  // Initialization
155
155
  // ========================================================================
156
156
  _initializeComposition() {
157
- const t = this._readCompositionFromNode(), r = this._readCustomAttributesFromNode(), e = this._readVisibilityFromRows(), o = this._renderOrderableItems(t, r), s = this._buildVisibilityValues(e);
158
- this.api.updateValues(s), o && this._initializeCustomSelects(r), this._updateAddButtonState();
157
+ const t = this._readCompositionFromNode(), e = this._readCustomAttributesFromNode(), r = this._readVisibilityFromRows(), o = this._renderOrderableItems(t, e), i = this._buildVisibilityValues(r);
158
+ this.api.updateValues(i), o && this._initializeCustomSelects(e), this._updateAddButtonState();
159
159
  }
160
160
  _registerValueChangeListeners() {
161
161
  h.forEach((t) => {
162
- this.api.onValueChanged(`visibility_${t.key}`, (r) => {
163
- this._applyVisibilityToBlock(t.key, r);
162
+ this.api.onValueChanged(`visibility_${t.key}`, (e) => {
163
+ this._applyVisibilityToBlock(t.key, e);
164
164
  });
165
165
  });
166
- for (let t = 0; t < g; t++) {
167
- const r = `${C}${t}`, e = t;
168
- this.api.onValueChanged(r, (o) => {
169
- this._onCustomAttributeChanged(e, o);
166
+ for (let t = 0; t < _; t++) {
167
+ const e = `${I}${t}`, r = t;
168
+ this.api.onValueChanged(e, (o) => {
169
+ this._onCustomAttributeChanged(r, o);
170
170
  });
171
171
  }
172
172
  }
@@ -175,50 +175,56 @@ class Ut extends Z {
175
175
  // ========================================================================
176
176
  _readCompositionFromNode() {
177
177
  if (!this.currentNode || !("getAttribute" in this.currentNode))
178
- return [...P];
179
- const t = this.currentNode.getAttribute(V);
180
- return t ? t.split(",").filter(Boolean) : [...P];
178
+ return [...x];
179
+ const t = this.currentNode.getAttribute(W);
180
+ if (t)
181
+ return t.split(",").filter(Boolean);
182
+ const { composition: e } = y.getConfig(this.currentNode);
183
+ return e != null && e.length ? [...e] : [...x];
181
184
  }
182
185
  _readCustomAttributesFromNode() {
183
186
  if (!this.currentNode || !("getAttribute" in this.currentNode))
184
187
  return [];
185
- const t = this.currentNode.getAttribute(q);
186
- if (!t)
187
- return [];
188
- try {
189
- return JSON.parse(t);
190
- } catch {
191
- return [];
192
- }
188
+ const t = this.currentNode.getAttribute(F);
189
+ if (t)
190
+ try {
191
+ return JSON.parse(t);
192
+ } catch {
193
+ return [];
194
+ }
195
+ return this._readCompositionFromNode().filter((e) => e.startsWith(m)).map((e) => e.substring(m.length));
193
196
  }
194
197
  _readVisibilityFromRows() {
195
198
  if (!this.currentNode)
196
199
  return this._getDefaultVisibilities();
197
- const t = Array.from(this.currentNode.querySelectorAll(S)), r = this._extractVisibilityFromRows(t);
198
- return this._mergeWithDefaults(r);
200
+ const t = Array.from(this.currentNode.querySelectorAll($)), e = this._extractVisibilityFromRows(t);
201
+ if (Object.keys(e).length > 0)
202
+ return this._mergeWithDefaults(e);
203
+ const r = y.getConfig(this.currentNode).visibility;
204
+ return this._mergeWithDefaults({ ...r });
199
205
  }
200
206
  _getDefaultVisibilities() {
201
- return { ...F };
207
+ return { ...M };
202
208
  }
203
209
  _extractVisibilityFromRows(t) {
204
- const r = {};
205
- return t.forEach((e) => {
206
- if (!("getAttribute" in e))
210
+ const e = {};
211
+ return t.forEach((r) => {
212
+ if (!("getAttribute" in r))
207
213
  return;
208
- const o = e.getAttribute(y), s = e.getAttribute(v);
209
- o && s !== null && (r[o] = this._parseVisibilityValue(s));
210
- }), r;
214
+ const o = r.getAttribute(C), i = r.getAttribute(E);
215
+ o && i !== null && (e[o] = this._parseVisibilityValue(i));
216
+ }), e;
211
217
  }
212
218
  _parseVisibilityValue(t) {
213
219
  return t === "1" || t === "true";
214
220
  }
215
221
  _mergeWithDefaults(t) {
216
- return Object.entries(F).forEach(([r, e]) => {
217
- r in t || (t[r] = e);
222
+ return Object.entries(M).forEach(([e, r]) => {
223
+ e in t || (t[e] = r);
218
224
  }), t;
219
225
  }
220
226
  _buildVisibilityValues(t) {
221
- return h.reduce((r, e) => (r[`visibility_${e.key}`] = t[e.key] ?? !0, r), {});
227
+ return h.reduce((e, r) => (e[`visibility_${r.key}`] = t[r.key] ?? !0, e), {});
222
228
  }
223
229
  // ========================================================================
224
230
  // UI Rendering (Orderable List)
@@ -228,28 +234,34 @@ class Ut extends Z {
228
234
  * Returns `true` if a full DOM rebuild occurred, `false` if existing
229
235
  * elements were reordered in-place (preserving UE-SELECT state).
230
236
  */
231
- _renderOrderableItems(t, r) {
232
- const e = this._getControlContainer();
233
- if (!e)
237
+ _renderOrderableItems(t, e) {
238
+ const r = this._getControlContainer();
239
+ if (!r)
234
240
  return !1;
235
- const o = e.querySelector("[data-composition-list]");
236
- if (!o || this._tryReorderInPlace(o, t))
241
+ const o = r.querySelector("[data-composition-list]");
242
+ if (!o)
237
243
  return !1;
238
- const s = new Set(r);
239
- let i = 0, n = 0;
240
- const a = t.map((c) => {
241
- if (At.has(c)) {
242
- const l = h.find((u) => u.key === c);
243
- return this._createBuiltInItemHtml(l, n++);
244
+ const i = !y.getConfig(this.currentNode).priceMovedToNextLine;
245
+ if (!(o.dataset.inlinePrices !== String(i)) && this._tryReorderInPlace(o, t))
246
+ return !1;
247
+ o.dataset.inlinePrices = String(i);
248
+ const n = new Set(e), c = ht(t);
249
+ let l = 0, a = 0;
250
+ const d = t.map((u) => {
251
+ if (i && (u === S || u === N))
252
+ return u === c.anchor ? this._createPriceGroupItemHtml(a++, c.originalFirst) : "";
253
+ if (Tt.has(u)) {
254
+ const p = h.find((A) => A.key === u);
255
+ return this._createBuiltInItemHtml(p, a++);
244
256
  }
245
- if (c.startsWith(m)) {
246
- const l = c.substring(m.length);
247
- if (s.has(l))
248
- return this._createCustomItemHtml(c, i++, n++);
257
+ if (u.startsWith(m)) {
258
+ const p = u.substring(m.length);
259
+ if (n.has(p))
260
+ return this._createCustomItemHtml(u, l++, a++);
249
261
  }
250
262
  return "";
251
263
  }).join("");
252
- return this._rescueTogglesToStore(e), this._rescueSelectsToStore(e), this._rescueDeleteButtonsToStore(e), this._rescueReorderIconsToStore(e), o.innerHTML = a, this._moveTogglesIntoItems(e), this._moveSelectsIntoItems(e, r.length), this._moveDeleteButtonsIntoItems(e, r.length), this._moveReorderIconsIntoItems(e, n), !0;
264
+ return this._rescueTogglesToStore(r), this._rescueSelectsToStore(r), this._rescueDeleteButtonsToStore(r), this._rescueReorderIconsToStore(r), o.innerHTML = d, this._moveTogglesIntoItems(r), this._moveSelectsIntoItems(r, e.length), this._moveDeleteButtonsIntoItems(r, e.length), this._moveReorderIconsIntoItems(r, a), !0;
253
265
  }
254
266
  /**
255
267
  * Attempts to reorder existing orderable-item elements to match the composition order.
@@ -257,52 +269,79 @@ class Ut extends Z {
257
269
  * performs a lightweight DOM reorder instead of a full innerHTML rebuild.
258
270
  * Returns true if reorder was performed, false if a full rebuild is needed.
259
271
  */
260
- _tryReorderInPlace(t, r) {
261
- const e = Array.from(t.querySelectorAll(".orderable-item"));
262
- if (e.length !== r.length)
272
+ _tryReorderInPlace(t, e) {
273
+ const r = Array.from(t.querySelectorAll(".orderable-item"));
274
+ if (r.length !== e.length)
263
275
  return !1;
264
- const o = e.map((c) => c.dataset.key).filter(Boolean);
265
- if (o.length !== r.length)
276
+ const o = r.map((l) => l.dataset.key).filter(Boolean);
277
+ if (o.length !== e.length)
266
278
  return !1;
267
- const s = [...o].sort().join(","), i = [...r].sort().join(",");
268
- if (s !== i || r.some((c) => c.startsWith(m)))
279
+ const i = [...o].sort().join(","), s = [...e].sort().join(",");
280
+ if (i !== s || e.some((l) => l.startsWith(m)))
269
281
  return !1;
270
282
  const n = /* @__PURE__ */ new Map();
271
- e.forEach((c) => {
272
- const { key: l } = c.dataset;
273
- if (l) {
274
- const u = n.get(l) || [];
275
- u.push(c), n.set(l, u);
283
+ r.forEach((l) => {
284
+ const { key: a } = l.dataset;
285
+ if (a) {
286
+ const d = n.get(a) || [];
287
+ d.push(l), n.set(a, d);
276
288
  }
277
289
  });
278
- const a = /* @__PURE__ */ new Map();
279
- return r.forEach((c) => {
280
- const l = n.get(c);
281
- if (!l)
290
+ const c = /* @__PURE__ */ new Map();
291
+ return e.forEach((l) => {
292
+ const a = n.get(l);
293
+ if (!a)
282
294
  return;
283
- const u = a.get(c) || 0;
284
- a.set(c, u + 1), l[u] && t.appendChild(l[u]);
295
+ const d = c.get(l) || 0;
296
+ c.set(l, d + 1), a[d] && t.appendChild(a[d]);
285
297
  }), !0;
286
298
  }
287
- _createBuiltInItemHtml(t, r) {
299
+ _createBuiltInItemHtml(t, e) {
288
300
  return `
289
301
  <div class="orderable-item" draggable="true" data-key="${t.key}">
290
- <span class="drag-handle" data-reorder-icon-slot="${r}"></span>
302
+ <span class="drag-handle" data-reorder-icon-slot="${e}"></span>
291
303
  <span class="item-label">${this.api.translate(t.label)}</span>
292
304
  <div class="item-action" data-action-for="${t.key}"></div>
293
305
  </div>
294
306
  `;
295
307
  }
296
- _createCustomItemHtml(t, r, e) {
308
+ /**
309
+ * Inline mode: the merged "Product Prices" group item. It moves as a unit in
310
+ * the main list (both keys stay adjacent) and contains a nested 2-item drag
311
+ * to reorder Product Price ↔ Product Original Price — which flips the inline
312
+ * render order via `resolveInlinePriceOrder`. The group keeps a single
313
+ * visibility toggle (`data-action-for="productPrice"`). Nested sub-items use a
314
+ * plain drag handle (no UE button → untouched by the reorder-icon rescue).
315
+ */
316
+ _createPriceGroupItemHtml(t, e) {
317
+ var n, c;
318
+ const r = ((n = h.find((l) => l.key === S)) == null ? void 0 : n.label) ?? "Product Price", o = ((c = h.find((l) => l.key === N)) == null ? void 0 : c.label) ?? "Product Original Price", i = (l, a) => `
319
+ <div class="price-suborderable-item" draggable="true" data-subkey="${l}">
320
+ <span class="sub-drag-handle">${At}</span>
321
+ <span class="item-label">${this.api.translate(a)}</span>
322
+ </div>`, s = e ? i(N, o) + i(S, r) : i(S, r) + i(N, o);
323
+ return `
324
+ <div class="orderable-item price-group-item" draggable="true"
325
+ data-key="${S}" data-group="prices">
326
+ <div class="price-group-header">
327
+ <span class="drag-handle" data-reorder-icon-slot="${t}"></span>
328
+ <span class="item-label">${this.api.translate("Product Prices")}</span>
329
+ <div class="item-action" data-action-for="${S}"></div>
330
+ </div>
331
+ <div class="price-suborderable-list">${s}</div>
332
+ </div>
333
+ `;
334
+ }
335
+ _createCustomItemHtml(t, e, r) {
297
336
  return `
298
337
  <div class="orderable-item" draggable="true"
299
- data-key="${t}" data-custom-index="${r}">
300
- <span class="drag-handle" data-reorder-icon-slot="${e}"></span>
338
+ data-key="${t}" data-custom-index="${e}">
339
+ <span class="drag-handle" data-reorder-icon-slot="${r}"></span>
301
340
  <div class="custom-attr-select-wrap"
302
- data-custom-select-slot="${r}"></div>
341
+ data-custom-select-slot="${e}"></div>
303
342
  <div class="item-action"
304
- data-custom-index="${r}"
305
- data-custom-delete-slot="${r}"></div>
343
+ data-custom-index="${e}"
344
+ data-custom-delete-slot="${e}"></div>
306
345
  </div>
307
346
  `;
308
347
  }
@@ -310,13 +349,13 @@ class Ut extends Z {
310
349
  * Builds select options from the store's filterList.
311
350
  * Falls back to a single option for the currently selected attribute.
312
351
  */
313
- _getSelectOptions(t, r = []) {
314
- const e = this._getAddableFilters();
315
- if (e.length > 0) {
316
- const s = new Set(r);
317
- return s.delete(t), e.filter((i) => !s.has(i.attributeName)).map((i) => ({
318
- text: i.displayName,
319
- value: i.attributeName
352
+ _getSelectOptions(t, e = []) {
353
+ const r = this._getAddableFilters();
354
+ if (r.length > 0) {
355
+ const i = new Set(e);
356
+ return i.delete(t), r.filter((s) => !i.has(s.attributeName)).map((s) => ({
357
+ text: s.displayName,
358
+ value: s.attributeName
320
359
  }));
321
360
  }
322
361
  return [{ text: this._getDisplayNameForAttribute(t), value: t }];
@@ -328,9 +367,9 @@ class Ut extends Z {
328
367
  */
329
368
  _initializeCustomSelects(t) {
330
369
  t.length !== 0 && setTimeout(() => {
331
- t.forEach((r, e) => {
332
- const o = `${C}${e}`, s = this._getSelectOptions(r, t);
333
- this.api.setUIEAttribute(o, I.SELECTPICKER.items, s), this.api.updateValues({ [o]: r });
370
+ t.forEach((e, r) => {
371
+ const o = `${I}${r}`, i = this._getSelectOptions(e, t);
372
+ this.api.setUIEAttribute(o, D.SELECTPICKER.items, i), this.api.updateValues({ [o]: e });
334
373
  });
335
374
  }, 0);
336
375
  }
@@ -339,11 +378,11 @@ class Ut extends Z {
339
378
  * Stripo initializes toggles at template parse time; moving the DOM node preserves bindings.
340
379
  */
341
380
  _moveTogglesIntoItems(t) {
342
- h.forEach((r) => {
343
- const e = t.querySelector(`[data-toggle-key="${r.key}"]`), o = t.querySelector(`[data-action-for="${r.key}"]`);
344
- if (e && o) {
345
- const s = e.querySelector("ue-switcher");
346
- s && o.appendChild(s);
381
+ h.forEach((e) => {
382
+ const r = t.querySelector(`[data-toggle-key="${e.key}"]`), o = t.querySelector(`[data-action-for="${e.key}"]`);
383
+ if (r && o) {
384
+ const i = r.querySelector("ue-switcher");
385
+ i && o.appendChild(i);
347
386
  }
348
387
  });
349
388
  }
@@ -351,12 +390,12 @@ class Ut extends Z {
351
390
  * Moves pre-allocated UE-SELECT elements from the hidden custom-select-store
352
391
  * into orderable item slots. Same pattern as _moveTogglesIntoItems.
353
392
  */
354
- _moveSelectsIntoItems(t, r) {
355
- for (let e = 0; e < r; e++) {
356
- const o = `${C}${e}`, s = t.querySelector(`[data-custom-select-key="${o}"]`), i = t.querySelector(`[data-custom-select-slot="${e}"]`);
357
- if (s && i) {
358
- const n = s.querySelector("ue-select");
359
- n && i.appendChild(n);
393
+ _moveSelectsIntoItems(t, e) {
394
+ for (let r = 0; r < e; r++) {
395
+ const o = `${I}${r}`, i = t.querySelector(`[data-custom-select-key="${o}"]`), s = t.querySelector(`[data-custom-select-slot="${r}"]`);
396
+ if (i && s) {
397
+ const n = i.querySelector("ue-select");
398
+ n && s.appendChild(n);
360
399
  }
361
400
  }
362
401
  }
@@ -367,11 +406,11 @@ class Ut extends Z {
367
406
  * previously-moved toggles, making them permanently lost.
368
407
  */
369
408
  _rescueTogglesToStore(t) {
370
- h.forEach((r) => {
371
- const e = t.querySelector(`[data-toggle-key="${r.key}"]`), o = t.querySelector(`[data-action-for="${r.key}"]`);
409
+ h.forEach((e) => {
410
+ const r = t.querySelector(`[data-toggle-key="${e.key}"]`), o = t.querySelector(`[data-action-for="${e.key}"]`);
372
411
  if (o) {
373
- const s = o.querySelector("ue-switcher");
374
- s && e && e.appendChild(s);
412
+ const i = o.querySelector("ue-switcher");
413
+ i && r && r.appendChild(i);
375
414
  }
376
415
  });
377
416
  }
@@ -380,11 +419,11 @@ class Ut extends Z {
380
419
  * Same rescue pattern as _rescueTogglesToStore — prevents innerHTML from destroying them.
381
420
  */
382
421
  _rescueSelectsToStore(t) {
383
- for (let r = 0; r < g; r++) {
384
- const e = `${C}${r}`, o = t.querySelector(`[data-custom-select-key="${e}"]`), s = t.querySelector(`[data-custom-select-slot="${r}"]`);
385
- if (s) {
386
- const i = s.querySelector("ue-select");
387
- i && o && o.appendChild(i);
422
+ for (let e = 0; e < _; e++) {
423
+ const r = `${I}${e}`, o = t.querySelector(`[data-custom-select-key="${r}"]`), i = t.querySelector(`[data-custom-select-slot="${e}"]`);
424
+ if (i) {
425
+ const s = i.querySelector("ue-select");
426
+ s && o && o.appendChild(s);
388
427
  }
389
428
  }
390
429
  }
@@ -392,12 +431,12 @@ class Ut extends Z {
392
431
  * Moves pre-allocated UE-BUTTON delete elements from the hidden custom-delete-store
393
432
  * into orderable item slots. Same pattern as _moveSelectsIntoItems.
394
433
  */
395
- _moveDeleteButtonsIntoItems(t, r) {
396
- for (let e = 0; e < r; e++) {
397
- const o = `${R}${e}`, s = t.querySelector(`[data-custom-delete-key="${o}"]`), i = t.querySelector(`[data-custom-delete-slot="${e}"]`);
398
- if (s && i) {
399
- const n = s.querySelector("ue-button");
400
- n && i.appendChild(n);
434
+ _moveDeleteButtonsIntoItems(t, e) {
435
+ for (let r = 0; r < e; r++) {
436
+ const o = `${R}${r}`, i = t.querySelector(`[data-custom-delete-key="${o}"]`), s = t.querySelector(`[data-custom-delete-slot="${r}"]`);
437
+ if (i && s) {
438
+ const n = i.querySelector("ue-button");
439
+ n && s.appendChild(n);
401
440
  }
402
441
  }
403
442
  }
@@ -406,11 +445,11 @@ class Ut extends Z {
406
445
  * Same rescue pattern as _rescueSelectsToStore — prevents innerHTML from destroying them.
407
446
  */
408
447
  _rescueDeleteButtonsToStore(t) {
409
- for (let r = 0; r < g; r++) {
410
- const e = `${R}${r}`, o = t.querySelector(`[data-custom-delete-key="${e}"]`), s = t.querySelector(`[data-custom-delete-slot="${r}"]`);
411
- if (s) {
412
- const i = s.querySelector("ue-button");
413
- i && o && o.appendChild(i);
448
+ for (let e = 0; e < _; e++) {
449
+ const r = `${R}${e}`, o = t.querySelector(`[data-custom-delete-key="${r}"]`), i = t.querySelector(`[data-custom-delete-slot="${e}"]`);
450
+ if (i) {
451
+ const s = i.querySelector("ue-button");
452
+ s && o && o.appendChild(s);
414
453
  }
415
454
  }
416
455
  }
@@ -418,12 +457,12 @@ class Ut extends Z {
418
457
  * Moves pre-allocated reorder icon UE-BUTTON elements from the hidden reorder-icon-store
419
458
  * into orderable item drag-handle slots. Same pattern as _moveDeleteButtonsIntoItems.
420
459
  */
421
- _moveReorderIconsIntoItems(t, r) {
422
- for (let e = 0; e < r; e++) {
423
- const o = `${E}${e}`, s = t.querySelector(`[data-reorder-icon-key="${o}"]`), i = t.querySelector(`[data-reorder-icon-slot="${e}"]`);
424
- if (s && i) {
425
- const n = s.querySelector("ue-button");
426
- n && i.appendChild(n);
460
+ _moveReorderIconsIntoItems(t, e) {
461
+ for (let r = 0; r < e; r++) {
462
+ const o = `${O}${r}`, i = t.querySelector(`[data-reorder-icon-key="${o}"]`), s = t.querySelector(`[data-reorder-icon-slot="${r}"]`);
463
+ if (i && s) {
464
+ const n = i.querySelector("ue-button");
465
+ n && s.appendChild(n);
427
466
  }
428
467
  }
429
468
  }
@@ -432,12 +471,12 @@ class Ut extends Z {
432
471
  * Same rescue pattern as _rescueDeleteButtonsToStore — prevents innerHTML from destroying them.
433
472
  */
434
473
  _rescueReorderIconsToStore(t) {
435
- const r = h.length + g;
436
- for (let e = 0; e < r; e++) {
437
- const o = `${E}${e}`, s = t.querySelector(`[data-reorder-icon-key="${o}"]`), i = t.querySelector(`[data-reorder-icon-slot="${e}"]`);
438
- if (i) {
439
- const n = i.querySelector("ue-button");
440
- n && s && s.appendChild(n);
474
+ const e = h.length + _;
475
+ for (let r = 0; r < e; r++) {
476
+ const o = `${O}${r}`, i = t.querySelector(`[data-reorder-icon-key="${o}"]`), s = t.querySelector(`[data-reorder-icon-slot="${r}"]`);
477
+ if (s) {
478
+ const n = s.querySelector("ue-button");
479
+ n && i && i.appendChild(n);
441
480
  }
442
481
  }
443
482
  }
@@ -446,85 +485,132 @@ class Ut extends Z {
446
485
  // ========================================================================
447
486
  _setupEventListeners() {
448
487
  this.eventController && this.eventController.abort(), this.eventController = new AbortController();
449
- const { signal: t } = this.eventController, r = this._getControlContainer();
450
- if (!r)
488
+ const { signal: t } = this.eventController, e = this._getControlContainer();
489
+ if (!e)
451
490
  return;
452
- const e = r.querySelector("[data-composition-list]"), o = r.querySelector("#guido__btn-add-attribute");
453
- e && (this._setupDragAndDrop(e, t), this._setupDeleteHandler(e, t)), o && o.addEventListener("click", () => {
454
- const s = new Set(this._readCustomAttributesFromNode()), i = this._getAddableFilters().find((n) => !s.has(n.attributeName));
455
- i && this._onAddAttribute(i.attributeName, i.displayName);
491
+ const r = e.querySelector("[data-composition-list]"), o = e.querySelector("#guido__btn-add-attribute");
492
+ r && (this._setupDragAndDrop(r, t), this._setupDeleteHandler(r, t)), o && o.addEventListener("click", () => {
493
+ const i = new Set(this._readCustomAttributesFromNode()), s = this._getAddableFilters().find((n) => !i.has(n.attributeName));
494
+ s && this._onAddAttribute(s.attributeName, s.displayName);
456
495
  }, { signal: t });
457
496
  }
458
- _setupDragAndDrop(t, r) {
459
- let e = null, o = null;
460
- t.addEventListener("dragstart", (s) => {
497
+ /**
498
+ * Builds the composition key order from the orderable list, expanding the
499
+ * inline "Product Prices" group into its two sub-keys (in nested DOM order)
500
+ * so both price keys stay adjacent and in the user-chosen order.
501
+ */
502
+ _extractCompositionOrder(t) {
503
+ const e = [];
504
+ return t.querySelectorAll(".orderable-item").forEach((r) => {
505
+ const o = r;
506
+ o.dataset.group === "prices" ? o.querySelectorAll(".price-suborderable-item").forEach((i) => {
507
+ const s = i.dataset.subkey;
508
+ s && e.push(s);
509
+ }) : o.dataset.key && e.push(o.dataset.key);
510
+ }), e;
511
+ }
512
+ _setupDragAndDrop(t, e) {
513
+ this._registerDragHandlers(t, e, {
514
+ itemSelector: ".orderable-item",
515
+ ignoreSelector: ".price-suborderable-item",
516
+ getDropParent: () => t
517
+ }), this._registerDragHandlers(t, e, {
518
+ itemSelector: ".price-suborderable-item",
519
+ getDropParent: (r) => r.parentElement
520
+ });
521
+ }
522
+ /**
523
+ * Wires drag/drop reordering for one item level on the shared list. Both the
524
+ * top-level items and the nested price sub-items use this; they never fight
525
+ * because each only sets its `dragged` ref when its own `itemSelector` matches
526
+ * at dragstart (and the top-level one additionally ignores drags originating
527
+ * inside `ignoreSelector`). Every drop re-reads the full composition via
528
+ * `_extractCompositionOrder`, so both levels commit through `_onReorder`
529
+ * identically.
530
+ */
531
+ _registerDragHandlers(t, e, r) {
532
+ let o = null, i = null;
533
+ const s = (n) => n.target.closest(r.itemSelector);
534
+ t.addEventListener("dragstart", (n) => {
461
535
  var a;
462
- const n = s.target.closest(".orderable-item");
463
- n && (e = n, n.classList.add("dragging"), (a = s.dataTransfer) == null || a.setData("text/plain", n.dataset.key || ""));
464
- }, { signal: r }), t.addEventListener("dragend", () => {
465
- e && e.classList.remove("dragging"), e = null, o == null || o.classList.remove("drag-over"), o = null;
466
- }, { signal: r }), t.addEventListener("dragover", (s) => {
467
- s.preventDefault();
468
- const n = s.target.closest(".orderable-item"), a = n && n !== e ? n : null;
469
- a !== o && (o == null || o.classList.remove("drag-over"), o = a, o == null || o.classList.add("drag-over"));
470
- }, { signal: r }), t.addEventListener("drop", (s) => {
471
- s.preventDefault();
472
- const n = s.target.closest(".orderable-item");
473
- if (!n || !e || n === e)
536
+ const c = n.target;
537
+ if (r.ignoreSelector && c.closest(r.ignoreSelector))
538
+ return;
539
+ const l = s(n);
540
+ l && (o = l, l.classList.add("dragging"), (a = n.dataTransfer) == null || a.setData("text/plain", l.dataset.key ?? l.dataset.subkey ?? ""));
541
+ }, { signal: e }), t.addEventListener("dragend", () => {
542
+ o == null || o.classList.remove("dragging"), i == null || i.classList.remove("drag-over"), o = null, i = null;
543
+ }, { signal: e }), t.addEventListener("dragover", (n) => {
544
+ if (!o)
545
+ return;
546
+ const c = s(n);
547
+ if (!c)
548
+ return;
549
+ n.preventDefault();
550
+ const l = c !== o ? c : null;
551
+ l !== i && (i == null || i.classList.remove("drag-over"), i = l, i == null || i.classList.add("drag-over"));
552
+ }, { signal: e }), t.addEventListener("drop", (n) => {
553
+ var d;
554
+ const c = o && s(n);
555
+ if (!o || !c || c === o)
474
556
  return;
475
- const a = n.getBoundingClientRect(), c = a.top + a.height / 2;
476
- s.clientY < c ? t.insertBefore(e, n) : t.insertBefore(e, n.nextSibling), o == null || o.classList.remove("drag-over"), o = null, e.classList.remove("dragging");
477
- const u = t.querySelectorAll(".orderable-item"), d = Array.from(u).map((b) => b.dataset.key).filter(Boolean);
478
- this._onReorder(d), e = null;
479
- }, { signal: r });
480
- }
481
- _setupDeleteHandler(t, r) {
482
- t.addEventListener("click", (e) => {
483
- const s = e.target.closest(".custom-attr-delete");
484
- if (!s)
557
+ n.preventDefault();
558
+ const l = c.getBoundingClientRect(), a = n.clientY < l.top + l.height / 2;
559
+ (d = r.getDropParent(c)) == null || d.insertBefore(o, a ? c : c.nextSibling), i == null || i.classList.remove("drag-over"), o.classList.remove("dragging"), o = null, i = null, this._onReorder(this._extractCompositionOrder(t));
560
+ }, { signal: e });
561
+ }
562
+ _setupDeleteHandler(t, e) {
563
+ t.addEventListener("click", (r) => {
564
+ const i = r.target.closest(".custom-attr-delete");
565
+ if (!i)
485
566
  return;
486
- const i = s.closest("[data-custom-index]"), n = i == null ? void 0 : i.dataset.customIndex;
567
+ const s = i.closest("[data-custom-index]"), n = s == null ? void 0 : s.dataset.customIndex;
487
568
  n !== void 0 && this._onDeleteCustomAttribute(Number(n));
488
- }, { signal: r });
569
+ }, { signal: e });
489
570
  }
490
571
  // ========================================================================
491
572
  // Actions (Add, Delete, Reorder)
492
573
  // ========================================================================
493
- _onAddAttribute(t, r) {
494
- const e = `${m}${t}`, o = this._readCompositionFromNode();
495
- o.push(e);
496
- const s = [...this._readCustomAttributesFromNode(), t];
497
- this._updateBothAttributes(o, s), this._injectCustomAttributeHtml(t, r, e, o), this._renderOrderableItems(o, s), this._initializeCustomSelects(s), this._updateAddButtonState();
574
+ _onAddAttribute(t, e) {
575
+ const r = `${m}${t}`, o = this._readCompositionFromNode();
576
+ o.push(r);
577
+ const i = [...this._readCustomAttributesFromNode(), t];
578
+ this._updateBothAttributes(o, i), this._injectCustomAttributeHtml(t, e, r, o), this._renderOrderableItems(o, i), this._initializeCustomSelects(i), this._updateAddButtonState();
498
579
  }
499
580
  /**
500
581
  * Removes a single custom attribute by its index in the customAttrs array.
501
582
  * Index-based to correctly handle duplicate attributes.
502
583
  */
503
584
  _onDeleteCustomAttribute(t) {
504
- const r = this._readCustomAttributesFromNode();
505
- if (r[t] === void 0)
585
+ const e = this._readCustomAttributesFromNode();
586
+ if (e[t] === void 0)
506
587
  return;
507
- const o = this._readCompositionFromNode(), s = this._findNthCustomKeyIndex(o, t), i = o.filter((a, c) => c !== s), n = r.filter((a, c) => c !== t);
508
- this._updateBothAttributes(i, n), this._removeCustomAttributeHtml(i), this._renderOrderableItems(i, n), this._initializeCustomSelects(n), this._updateAddButtonState();
588
+ const o = this._readCompositionFromNode(), i = this._findNthCustomKeyIndex(o, t), s = o.filter((c, l) => l !== i), n = e.filter((c, l) => l !== t);
589
+ this._updateBothAttributes(s, n), this._removeCustomAttributeHtml(s), this._renderOrderableItems(s, n), this._initializeCustomSelects(n), this._updateAddButtonState();
509
590
  }
510
591
  /**
511
592
  * Handles changing a custom attribute's selection via its inline _GuSelect.
512
593
  * Uses the customIndex to target only the specific instance, supporting duplicates.
513
594
  */
514
- _onCustomAttributeChanged(t, r) {
515
- const e = this._readCustomAttributesFromNode(), o = e[t];
516
- if (o === void 0 || o === r)
595
+ _onCustomAttributeChanged(t, e) {
596
+ const r = this._readCustomAttributesFromNode(), o = r[t];
597
+ if (o === void 0 || o === e)
517
598
  return;
518
- const s = `${m}${r}`, i = this._readCompositionFromNode(), n = this._findNthCustomKeyIndex(i, t);
519
- n !== -1 && (i[n] = s), e[t] = r;
520
- const a = this._getDisplayNameForAttribute(r);
521
- this._updateBothAttributes(i, e), this._injectCustomAttributeHtml(r, a, s, i), this._renderOrderableItems(i, e), this._initializeCustomSelects(e);
599
+ const i = `${m}${e}`, s = this._readCompositionFromNode(), n = this._findNthCustomKeyIndex(s, t);
600
+ n !== -1 && (s[n] = i), r[t] = e;
601
+ const c = this._getDisplayNameForAttribute(e);
602
+ this._updateBothAttributes(s, r), this._injectCustomAttributeHtml(e, c, i, s), this._renderOrderableItems(s, r), this._initializeCustomSelects(r);
522
603
  }
523
604
  _onReorder(t) {
524
- const r = t.filter((e) => e.startsWith(m)).map((e) => e.substring(m.length));
605
+ const e = t.filter((r) => r.startsWith(m)).map((r) => r.substring(m.length));
525
606
  this.reorderInProgress = !0;
526
607
  try {
527
- this._updateBothAttributes(t, r), this._getCurrentLayout() === "grid" && this._reorderProductAttributes(t);
608
+ this._updateBothAttributes(t, e);
609
+ const r = !y.getConfig(this.currentNode).priceMovedToNextLine;
610
+ this._getCurrentLayout() === "grid" && !r ? this._reorderProductAttributes(t) : this.currentNode && yt({
611
+ currentNode: this.currentNode,
612
+ documentModifier: this.api.getDocumentModifier()
613
+ });
528
614
  } finally {
529
615
  this.reorderInProgress = !1;
530
616
  }
@@ -533,67 +619,67 @@ class Ut extends Z {
533
619
  // ========================================================================
534
620
  // HTML Injection / Removal (Product Card DOM)
535
621
  // ========================================================================
536
- _injectCustomAttributeHtml(t, r, e, o) {
622
+ _injectCustomAttributeHtml(t, e, r, o) {
537
623
  if (!this.currentNode)
538
624
  return;
539
- this._getCurrentLayout() === "grid" ? this._injectGridAttributeRow(t, r, e, o) : this._injectListAttributeRow(t, r, e, o);
625
+ this._getCurrentLayout() === "grid" ? this._injectGridAttributeRow(t, e, r, o) : this._injectListAttributeRow(t, e, r, o);
540
626
  }
541
- _injectGridAttributeRow(t, r, e, o) {
542
- const s = this.currentNode.querySelectorAll(N);
543
- if (!(s != null && s.length))
627
+ _injectGridAttributeRow(t, e, r, o) {
628
+ const i = this.currentNode.querySelectorAll(H);
629
+ if (!(i != null && i.length))
544
630
  return;
545
- const i = nt.getConfig(this.currentNode), a = `0 ${Math.floor(i.columnSpacing / 2)}px`, c = this.api.getDocumentModifier(), l = this.store.recommendationProducts.length;
546
- let u = 0;
547
- s.forEach((d) => {
548
- var k;
549
- const b = d.querySelector(S), $ = ((k = b == null ? void 0 : b.querySelectorAll(`.${at}`)) == null ? void 0 : k.length) || 1, U = (100 / $).toFixed(2), { bgStyle: j, bgAttr: W } = this._extractSegmentBgFromCard(d), O = l > 0 ? Math.min($, l - u) : $, K = o.map((H) => {
550
- if (H === e) {
551
- const z = Array.from(
552
- { length: O },
553
- (St, Y) => {
554
- const X = this._resolveAttributeContent(
631
+ const s = y.getConfig(this.currentNode), c = `0 ${Math.floor(s.columnSpacing / 2)}px`, l = this.api.getDocumentModifier(), a = this.store.recommendationProducts.length;
632
+ let d = 0;
633
+ i.forEach((u) => {
634
+ var w;
635
+ const p = u.querySelector($), A = ((w = p == null ? void 0 : p.querySelectorAll(`.${at}`)) == null ? void 0 : w.length) || 1, q = (100 / A).toFixed(2), { bgStyle: G, bgAttr: z } = this._extractSegmentBgFromCard(u), L = a > 0 ? Math.min(A, a - d) : A, Y = o.map((B) => {
636
+ if (B === r) {
637
+ const X = Array.from(
638
+ { length: L },
639
+ ($t, Q) => {
640
+ const Z = this._resolveAttributeContent(
555
641
  t,
556
- r,
557
- u + Y
642
+ e,
643
+ d + Q
558
644
  );
559
645
  return this._getGridCellHtml(
560
646
  t,
561
- X,
562
- U,
563
- j,
564
- W,
565
- a
647
+ Z,
648
+ q,
649
+ G,
650
+ z,
651
+ c
566
652
  );
567
653
  }
568
- ).join(""), G = dt(U, a).repeat($ - O);
569
- return `<tr class="recommendation-attribute-row" ${y}="${e}" ${v}="1">${z}${G}</tr>`;
654
+ ).join(""), J = ut(q, c).repeat(A - L);
655
+ return `<tr class="recommendation-attribute-row" ${C}="${r}" ${E}="1">${X}${J}</tr>`;
570
656
  }
571
- const D = d.querySelector(
572
- `${S}[${y}="${H}"]`
657
+ const P = u.querySelector(
658
+ `${$}[${C}="${B}"]`
573
659
  );
574
- return D && "getOuterHTML" in D ? D.getOuterHTML() : "";
660
+ return P && "getOuterHTML" in P ? P.getOuterHTML() : "";
575
661
  }).join("");
576
- u += O, l > 0 && u >= l && (u = 0), c.modifyHtml(d).setInnerHtml(K);
577
- }), c.apply(new A(`${this.api.translate("Add custom attribute")}: ${r}`));
662
+ d += L, a > 0 && d >= a && (d = 0), l.modifyHtml(u).setInnerHtml(Y);
663
+ }), l.apply(new T(`${this.api.translate("Add custom attribute")}: ${e}`));
578
664
  }
579
- _injectListAttributeRow(t, r, e, o) {
580
- const s = this.currentNode.querySelectorAll(M);
581
- if (!(s != null && s.length))
665
+ _injectListAttributeRow(t, e, r, o) {
666
+ const i = this.currentNode.querySelectorAll(j);
667
+ if (!(i != null && i.length))
582
668
  return;
583
- const i = o.filter((a) => a !== L && a !== B), n = this.api.getDocumentModifier();
584
- s.forEach((a, c) => {
585
- const l = i.map((u) => {
586
- if (u === e) {
587
- const b = this._resolveAttributeContent(t, r, c);
588
- return this._getListRowHtml(t, b, e);
669
+ const s = o.filter((c) => c !== k && c !== U), n = this.api.getDocumentModifier();
670
+ i.forEach((c, l) => {
671
+ const a = s.map((d) => {
672
+ if (d === r) {
673
+ const p = this._resolveAttributeContent(t, e, l);
674
+ return this._getListRowHtml(t, p, r);
589
675
  }
590
- const d = a.querySelector(
591
- `${S}[${y}="${u}"]`
676
+ const u = c.querySelector(
677
+ `${$}[${C}="${d}"]`
592
678
  );
593
- return d && "getOuterHTML" in d ? d.getOuterHTML() : "";
679
+ return u && "getOuterHTML" in u ? u.getOuterHTML() : "";
594
680
  }).join("");
595
- n.modifyHtml(a).setInnerHtml(l);
596
- }), n.apply(new A(`${this.api.translate("Add custom attribute")}: ${r}`));
681
+ n.modifyHtml(c).setInnerHtml(a);
682
+ }), n.apply(new T(`${this.api.translate("Add custom attribute")}: ${e}`));
597
683
  }
598
684
  /**
599
685
  * Removes a custom attribute by rebuilding product card content without it.
@@ -602,21 +688,21 @@ class Ut extends Z {
602
688
  _removeCustomAttributeHtml(t) {
603
689
  if (!this.currentNode)
604
690
  return;
605
- const r = this._getCurrentLayout(), e = this.api.getDocumentModifier();
606
- if (r === "grid") {
607
- const o = this.currentNode.querySelectorAll(N);
608
- o == null || o.forEach((s) => {
609
- const i = this._buildCompositionHtml(s, t);
610
- e.modifyHtml(s).setInnerHtml(i);
691
+ const e = this._getCurrentLayout(), r = this.api.getDocumentModifier();
692
+ if (e === "grid") {
693
+ const o = this.currentNode.querySelectorAll(H);
694
+ o == null || o.forEach((i) => {
695
+ const s = this._buildCompositionHtml(i, t);
696
+ r.modifyHtml(i).setInnerHtml(s);
611
697
  });
612
698
  } else {
613
- const o = t.filter((i) => i !== L && i !== B), s = this.currentNode.querySelectorAll(M);
614
- s == null || s.forEach((i) => {
615
- const n = this._buildCompositionHtml(i, o);
616
- e.modifyHtml(i).setInnerHtml(n);
699
+ const o = t.filter((s) => s !== k && s !== U), i = this.currentNode.querySelectorAll(j);
700
+ i == null || i.forEach((s) => {
701
+ const n = this._buildCompositionHtml(s, o);
702
+ r.modifyHtml(s).setInnerHtml(n);
617
703
  });
618
704
  }
619
- e.apply(new A(this.api.translate("Remove custom attribute")));
705
+ r.apply(new T(this.api.translate("Remove custom attribute")));
620
706
  }
621
707
  // ========================================================================
622
708
  // DOM Mutation (Block Root Attributes, Reorder)
@@ -628,8 +714,14 @@ class Ut extends Z {
628
714
  * where composition is updated but customAttributes still has the old order,
629
715
  * producing a flicker on the custom attribute dropdowns.
630
716
  */
631
- _updateBothAttributes(t, r) {
632
- this.currentNode && this.api.getDocumentModifier().modifyHtml(this.currentNode).setAttribute(V, t.join(",")).setAttribute(q, JSON.stringify(r)).apply(new A(this.api.translate("Update card composition")));
717
+ _updateBothAttributes(t, e) {
718
+ if (!this.currentNode)
719
+ return;
720
+ const r = {
721
+ ...y.getConfig(this.currentNode),
722
+ composition: t
723
+ };
724
+ this.api.getDocumentModifier().modifyHtml(this.currentNode).setAttribute(W, t.join(",")).setAttribute(F, JSON.stringify(e)).setNodeConfig(r).apply(new T(this.api.translate("Update card composition")));
633
725
  }
634
726
  /**
635
727
  * Reorders attribute rows within each product card based on composition order.
@@ -638,39 +730,44 @@ class Ut extends Z {
638
730
  _reorderProductAttributes(t) {
639
731
  if (!this.currentNode)
640
732
  return;
641
- const r = this.currentNode.querySelectorAll(N);
642
- if (!(r != null && r.length))
733
+ const e = this.currentNode.querySelectorAll(H);
734
+ if (!(e != null && e.length))
643
735
  return;
644
- const e = this.api.getDocumentModifier();
645
- r.forEach((o) => {
646
- const s = this._buildCompositionHtml(o, t);
647
- e.modifyHtml(o).setInnerHtml(s);
648
- }), e.apply(new A(this.api.translate("Reorder product attributes")));
736
+ const r = this.api.getDocumentModifier();
737
+ e.forEach((o) => {
738
+ const i = this._buildCompositionHtml(o, t);
739
+ r.modifyHtml(o).setInnerHtml(i);
740
+ }), r.apply(new T(this.api.translate("Reorder product attributes")));
649
741
  }
650
742
  /**
651
743
  * Builds HTML string with attributes ordered according to composition.
652
744
  * Queries existing rows from the container by data-attribute-type.
653
745
  */
654
- _buildCompositionHtml(t, r) {
655
- return r.reduce((e, o) => {
656
- const s = t.querySelector(`${S}[${y}="${o}"]`);
657
- return s && "getOuterHTML" in s ? e + s.getOuterHTML() : e;
746
+ _buildCompositionHtml(t, e) {
747
+ return e.reduce((r, o) => {
748
+ const i = t.querySelector(`${$}[${C}="${o}"]`);
749
+ return i && "getOuterHTML" in i ? r + i.getOuterHTML() : r;
658
750
  }, "");
659
751
  }
660
752
  // ========================================================================
661
753
  // Visibility
662
754
  // ========================================================================
663
- _applyVisibilityToBlock(t, r) {
755
+ _applyVisibilityToBlock(t, e) {
664
756
  if (!this.currentNode)
665
757
  return;
666
- const e = this.currentNode.querySelectorAll(`${S}[${y}="${t}"]`);
667
- if (!(e != null && e.length))
758
+ const r = this.currentNode.querySelectorAll(`${$}[${C}="${t}"]`);
759
+ if (!(r != null && r.length))
668
760
  return;
669
- const o = r ? "1" : "0", s = r ? this.api.translate("visible") : this.api.translate("hidden"), i = `${this.api.translate("Set visibility")}: ${t} → ${s}`, n = this.api.getDocumentModifier();
670
- e.forEach((a) => {
671
- const c = ft(a), l = r ? c : "none";
672
- n.modifyHtml(a).setStyle("display", l).setAttribute(v, o);
673
- }), n.apply(new A(i));
761
+ const o = e ? "1" : "0", i = e ? this.api.translate("visible") : this.api.translate("hidden"), s = `${this.api.translate("Set visibility")}: ${t} → ${i}`, n = this.api.getDocumentModifier();
762
+ r.forEach((l) => {
763
+ const a = ft(l), d = e ? a : "none";
764
+ n.modifyHtml(l).setStyle("display", d).setAttribute(E, o);
765
+ });
766
+ const c = {
767
+ ...y.getConfig(this.currentNode),
768
+ visibility: { ...this._readVisibilityFromRows(), [t]: e }
769
+ };
770
+ n.modifyHtml(this.currentNode).setNodeConfig(c), n.apply(new T(s));
674
771
  }
675
772
  // ========================================================================
676
773
  // Utilities
@@ -680,18 +777,18 @@ class Ut extends Z {
680
777
  * Scans left-to-right, counting only entries with the custom prefix.
681
778
  * The customIndex maps 1:1 with the customAttrs array order.
682
779
  */
683
- _findNthCustomKeyIndex(t, r) {
684
- let e = 0;
780
+ _findNthCustomKeyIndex(t, e) {
781
+ let r = 0;
685
782
  for (let o = 0; o < t.length; o++)
686
783
  if (t[o].startsWith(m)) {
687
- if (e === r)
784
+ if (r === e)
688
785
  return o;
689
- e++;
786
+ r++;
690
787
  }
691
788
  return -1;
692
789
  }
693
790
  _getCurrentLayout() {
694
- return this.store.recommendationConfigs.orientation || bt(this.currentNode);
791
+ return this.store.recommendationConfigs.orientation || Ct(this.currentNode);
695
792
  }
696
793
  /**
697
794
  * Extracts background color properties from existing card elements.
@@ -701,20 +798,20 @@ class Ut extends Z {
701
798
  */
702
799
  _extractSegmentBgFromCard(t) {
703
800
  var o;
704
- const r = t.querySelector(".product-card-segment");
705
- if (r && "getAttribute" in r) {
706
- const i = (r.getAttribute("style") || "").match(/background-color:\s*([^;]+)/);
707
- if (i) {
708
- const n = r.getAttribute("bgcolor") || "";
709
- return { bgStyle: `background-color: ${i[1].trim()};`, bgAttr: n };
801
+ const e = t.querySelector(".product-card-segment");
802
+ if (e && "getAttribute" in e) {
803
+ const s = (e.getAttribute("style") || "").match(/background-color:\s*([^;]+)/);
804
+ if (s) {
805
+ const n = e.getAttribute("bgcolor") || "";
806
+ return { bgStyle: `background-color: ${s[1].trim()};`, bgAttr: n };
710
807
  }
711
808
  }
712
- const e = (o = this.currentNode) == null ? void 0 : o.querySelector(".product-card-wrapper");
713
- if (e && "getStyle" in e) {
714
- const s = e.getStyle("background-color");
715
- if (s && s !== "transparent") {
716
- const i = "getAttribute" in e && e.getAttribute("bgcolor") || "";
717
- return { bgStyle: `background-color: ${s};`, bgAttr: i };
809
+ const r = (o = this.currentNode) == null ? void 0 : o.querySelector(".product-card-wrapper");
810
+ if (r && "getStyle" in r) {
811
+ const i = r.getStyle("background-color");
812
+ if (i && i !== "transparent") {
813
+ const s = "getAttribute" in r && r.getAttribute("bgcolor") || "";
814
+ return { bgStyle: `background-color: ${i};`, bgAttr: s };
718
815
  }
719
816
  }
720
817
  return { bgStyle: "", bgAttr: "" };
@@ -724,17 +821,18 @@ class Ut extends Z {
724
821
  return t ? t.querySelector("[data-card-composition-control]") : null;
725
822
  }
726
823
  /**
727
- * Adds/removes orderable-disabled class based on layout orientation.
728
- * List layout hides drag handles via CSS and disables draggable attribute
729
- * to prevent native browser drag-and-drop from working without the handle.
824
+ * Ensures composition reorder is enabled. Both grid and list layouts now
825
+ * support reordering top-level items and the nested price sub-items are all
826
+ * draggable. (Items render with `draggable="true"`; this just clears any stale
827
+ * disabled state.)
730
828
  */
731
829
  _updateOrderableState() {
732
- const r = this._getCurrentLayout() === "list", e = this._getControlContainer();
733
- if (!e)
830
+ const t = this._getControlContainer();
831
+ if (!t)
734
832
  return;
735
- const o = e.querySelector("[data-composition-list]");
736
- o && (o.classList.toggle("orderable-disabled", r), o.querySelectorAll(".orderable-item").forEach((s) => {
737
- s.setAttribute("draggable", r ? "false" : "true");
833
+ const e = t.querySelector("[data-composition-list]");
834
+ e && (e.classList.remove("orderable-disabled"), e.querySelectorAll(".orderable-item").forEach((r) => {
835
+ r.setAttribute("draggable", "true");
738
836
  }));
739
837
  }
740
838
  /**
@@ -742,11 +840,11 @@ class Ut extends Z {
742
840
  * or when all available filters have already been added (no unused attributes left).
743
841
  */
744
842
  _updateAddButtonState() {
745
- const t = this._readCustomAttributesFromNode(), r = t.length >= g, e = new Set(t), o = this._getAddableFilters(), s = o.length > 0 && o.every((i) => e.has(i.attributeName));
843
+ const t = this._readCustomAttributesFromNode(), e = t.length >= _, r = new Set(t), o = this._getAddableFilters(), i = o.length > 0 && o.every((s) => r.has(s.attributeName));
746
844
  this.api.setUIEAttribute(
747
- x.ADD_ATTRIBUTE,
748
- I.BUTTON.disabled,
749
- r || s ? "true" : "false"
845
+ K.ADD_ATTRIBUTE,
846
+ D.BUTTON.disabled,
847
+ e || i ? "true" : "false"
750
848
  );
751
849
  }
752
850
  /**
@@ -755,12 +853,12 @@ class Ut extends Z {
755
853
  */
756
854
  _subscribeToStoreChanges() {
757
855
  this.unsubscribeStore && this.unsubscribeStore();
758
- let t = this.store.recommendationConfigs.orientation, r = Object.keys(this.store.filterList).sort().join(",");
856
+ let t = this.store.recommendationConfigs.orientation, e = Object.keys(this.store.filterList).sort().join(",");
759
857
  this.unsubscribeStore = this.store.$subscribe(() => {
760
- const e = this.store.recommendationConfigs.orientation;
761
- e !== t && (t = e, this._updateOrderableState());
858
+ const r = this.store.recommendationConfigs.orientation;
859
+ r !== t && (t = r, this._updateOrderableState());
762
860
  const o = Object.keys(this.store.filterList).sort().join(",");
763
- o !== r && (r = o, this._initializeComposition());
861
+ o !== e && (e = o, this._initializeComposition());
764
862
  });
765
863
  }
766
864
  /**
@@ -768,45 +866,45 @@ class Ut extends Z {
768
866
  * excluding default attributes already covered by built-in toggle items.
769
867
  */
770
868
  _getAddableFilters() {
771
- return Object.values(this.store.filterList).filter((t) => !(t.type === "defaultAttribute" && it.has(t.attributeName)));
869
+ return Object.values(this.store.filterList).filter((t) => !(t.type === "defaultAttribute" && nt.has(t.attributeName)));
772
870
  }
773
871
  /**
774
872
  * Looks up the display name for an attribute from the store's filterList.
775
873
  * Falls back to Title Case conversion of the snake_case attribute name.
776
874
  */
777
875
  _getDisplayNameForAttribute(t) {
778
- const r = Object.values(this.store.filterList).find((e) => e.attributeName === t);
779
- return r ? r.displayName : ht(t);
876
+ const e = Object.values(this.store.filterList).find((r) => r.attributeName === t);
877
+ return e ? e.displayName : pt(t);
780
878
  }
781
879
  /**
782
880
  * Resolves the display content for a custom attribute cell.
783
881
  * Uses the real product value from the store when available, falls back to displayName.
784
882
  */
785
- _resolveAttributeContent(t, r, e) {
883
+ _resolveAttributeContent(t, e, r) {
786
884
  var n;
787
- const s = this.store.recommendationProducts[e], i = pt(t, this.store.filterList) ? s == null ? void 0 : s[t] : (n = s == null ? void 0 : s.product_attributes) == null ? void 0 : n[t];
788
- return _t(i) ?? r;
885
+ const i = this.store.recommendationProducts[r], s = gt(t, this.store.filterList) ? i == null ? void 0 : i[t] : (n = i == null ? void 0 : i.product_attributes) == null ? void 0 : n[t];
886
+ return bt(s) ?? e;
789
887
  }
790
- _getGridCellHtml(t, r, e, o = "", s = "", i = "") {
791
- const n = `${m}${t}`, a = w(ct, [n], this.store.filterList), c = {
792
- [t]: r,
793
- product_attributes: { [t]: r }
888
+ _getGridCellHtml(t, e, r, o = "", i = "", s = "") {
889
+ const n = `${m}${t}`, c = V(ct, [n], this.store.filterList), l = {
890
+ [t]: e,
891
+ product_attributes: { [t]: e }
794
892
  };
795
- let l = a[n](c);
796
- return l = l.replace("<td", `<td width="${e}%"`), i && (l = l.replace(
797
- `padding: ${ut}`,
798
- `padding: ${i}`
799
- )), o && (l = l.replace(/style="table-layout: fixed;"/, `style="table-layout: fixed; ${o}"`)), s && (l = l.replace(/border="0"/, `border="0" bgcolor="${s}"`)), l;
800
- }
801
- _getListRowHtml(t, r, e) {
802
- const o = w(mt, [e], this.store.filterList), s = {
803
- [t]: r,
804
- product_attributes: { [t]: r }
805
- }, n = o[e](s).replace(/<tr>/, "").replace(/<\/tr>/, "");
806
- return `<tr class="recommendation-attribute-row" ${y}="${e}" ${v}="1">${n}</tr>`;
893
+ let a = c[n](l);
894
+ return a = a.replace("<td", `<td width="${r}%"`), s && (a = a.replace(
895
+ `padding: ${dt}`,
896
+ `padding: ${s}`
897
+ )), o && (a = a.replace(/style="table-layout: fixed;"/, `style="table-layout: fixed; ${o}"`)), i && (a = a.replace(/border="0"/, `border="0" bgcolor="${i}"`)), a;
898
+ }
899
+ _getListRowHtml(t, e, r) {
900
+ const o = V(mt, [r], this.store.filterList), i = {
901
+ [t]: e,
902
+ product_attributes: { [t]: e }
903
+ }, n = o[r](i).replace(/<tr>/, "").replace(/<\/tr>/, "");
904
+ return `<tr class="recommendation-attribute-row" ${C}="${r}" ${E}="1">${n}</tr>`;
807
905
  }
808
906
  }
809
907
  export {
810
- yt as COMPOSITION_CONTROL_BLOCK_ID,
811
- Ut as RecommendationCardCompositionControl
908
+ St as COMPOSITION_CONTROL_BLOCK_ID,
909
+ qt as RecommendationCardCompositionControl
812
910
  };