@useinsider/guido 3.15.0-beta.f5247a0 → 3.15.0-beta.fcabbea

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 (58) hide show
  1. package/dist/@types/config/schemas.js +108 -92
  2. package/dist/components/Guido.vue.js +1 -1
  3. package/dist/components/Guido.vue2.js +78 -75
  4. package/dist/composables/useActionsApi.js +30 -22
  5. package/dist/composables/useEmailTemplateApplier.js +25 -23
  6. package/dist/composables/useHtmlValidator.js +50 -50
  7. package/dist/composables/useRecommendation.js +20 -19
  8. package/dist/composables/useTimerClone.js +21 -19
  9. package/dist/config/i18n/en/labels.json.js +7 -3
  10. package/dist/config/migrator/recommendation/compositionMapper.js +26 -23
  11. package/dist/config/migrator/recommendation/htmlBuilder.js +156 -155
  12. package/dist/extensions/Blocks/Items/block.js +44 -42
  13. package/dist/extensions/Blocks/Items/template.js +86 -86
  14. package/dist/extensions/Blocks/Recommendation/constants/selectors.js +18 -15
  15. package/dist/extensions/Blocks/Recommendation/controls/cardBackground/index.js +9 -5
  16. package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +363 -322
  17. package/dist/extensions/Blocks/Recommendation/controls/main/algorithm.js +37 -26
  18. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +21 -21
  19. package/dist/extensions/Blocks/Recommendation/controls/main/layoutOrientation.js +8 -8
  20. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +271 -231
  21. package/dist/extensions/Blocks/Recommendation/controls/spacing/index.js +113 -98
  22. package/dist/extensions/Blocks/Recommendation/recommendation.css.js +0 -21
  23. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +13 -12
  24. package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +16 -16
  25. package/dist/extensions/Blocks/Recommendation/templates/list/template.js +16 -16
  26. package/dist/extensions/Blocks/Recommendation/templates/utils.js +120 -120
  27. package/dist/extensions/Blocks/Recommendation/utils/captureStyleTemplates.js +55 -54
  28. package/dist/extensions/Blocks/Recommendation/utils/compositionKeys.js +89 -0
  29. package/dist/extensions/Blocks/Recommendation/utils/productIds.js +6 -0
  30. package/dist/extensions/Blocks/common-control.js +42 -35
  31. package/dist/guido.css +1 -1
  32. package/dist/library.js +11 -7
  33. package/dist/node_modules/valibot/dist/index.js +230 -216
  34. package/dist/public/trackingIds.js +8 -0
  35. package/dist/src/@types/config/schemas.d.ts +20 -0
  36. package/dist/src/composables/useActionsApi.d.ts +1 -1
  37. package/dist/src/composables/useConfig.d.ts +4 -0
  38. package/dist/src/composables/useHtmlValidator.d.ts +3 -2
  39. package/dist/src/config/migrator/recommendation/types.d.ts +1 -0
  40. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +1 -1
  41. package/dist/src/extensions/Blocks/Recommendation/constants/selectors.d.ts +6 -0
  42. package/dist/src/extensions/Blocks/Recommendation/controls/cardComposition/index.d.ts +27 -5
  43. package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +4 -2
  44. package/dist/src/extensions/Blocks/Recommendation/controls/spacing/index.d.ts +0 -5
  45. package/dist/src/extensions/Blocks/Recommendation/templates/utils.d.ts +12 -11
  46. package/dist/src/extensions/Blocks/Recommendation/utils/compositionKeys.d.ts +47 -0
  47. package/dist/src/extensions/Blocks/Recommendation/utils/productIds.d.ts +6 -0
  48. package/dist/src/extensions/Blocks/common-control.d.ts +3 -1
  49. package/dist/src/library.d.ts +1 -0
  50. package/dist/src/public/trackingIds.d.ts +9 -0
  51. package/dist/src/stores/config.d.ts +36 -0
  52. package/dist/src/stores/editor.d.ts +25 -0
  53. package/dist/src/utils/linkTrackingIds.d.ts +30 -0
  54. package/dist/stores/editor.js +4 -1
  55. package/dist/utils/linkTrackingIds.js +56 -0
  56. package/dist/utils/pairProductVariables.js +105 -99
  57. package/dist/utils/templatePreparation.js +72 -61
  58. package/package.json +5 -1
@@ -1,16 +1,16 @@
1
- var y = Object.defineProperty;
2
- var M = (u, s, t) => s in u ? y(u, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : u[s] = t;
3
- var g = (u, s, t) => M(u, typeof s != "symbol" ? s + "" : s, t);
4
- import { ModificationDescription as S } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
5
- import { CommonControl as E } from "../../../common-control.js";
6
- import { DESKTOP_CONTAINER_SELECTOR as m, MOBILE_CONTAINER_SELECTOR as L } from "../../constants/selectors.js";
7
- import { SPACING_STEP as P, MAX_SPACING as G, MIN_SPACING as R, DEFAULT_COLUMN_SPACING as C, DEFAULT_ROW_SPACING as I } from "../../constants/layout.js";
1
+ var G = Object.defineProperty;
2
+ var P = (u, s, t) => s in u ? G(u, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : u[s] = t;
3
+ var C = (u, s, t) => P(u, typeof s != "symbol" ? s + "" : s, t);
4
+ import { ModificationDescription as m } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
5
+ import { CommonControl as R } from "../../../common-control.js";
6
+ import { DESKTOP_CONTAINER_SELECTOR as S, MOBILE_CONTAINER_SELECTOR as M } from "../../constants/selectors.js";
7
+ import { SPACING_STEP as _, MAX_SPACING as N, MIN_SPACING as b, DEFAULT_COLUMN_SPACING as g, DEFAULT_ROW_SPACING as E } from "../../constants/layout.js";
8
8
  import { RecommendationConfigService as p } from "../../services/configService.js";
9
9
  import { useRecommendationExtensionStore as w } from "../../store/recommendation.js";
10
- import { safeGetStyle as f, safeGetParent as B } from "../../utils/tagName.js";
11
- import { getCurrentLayout as _, getBlockElement as U } from "../main/utils.js";
12
- import { useDebounceFn as N } from "../../../../../node_modules/@vueuse/shared/index.js";
13
- const V = "recommendation-spacing-control", o = {
10
+ import { safeGetStyle as L, safeGetParent as V } from "../../utils/tagName.js";
11
+ import { getCurrentLayout as f, getBlockElement as B } from "../main/utils.js";
12
+ import { useDebounceFn as O } from "../../../../../node_modules/@vueuse/shared/index.js";
13
+ const U = "recommendation-spacing-control", n = {
14
14
  COLUMN_SPACING: "columnSpacing",
15
15
  COLUMN_SPACING_LABEL: "columnSpacingLabel",
16
16
  ROW_SPACING: "rowSpacing",
@@ -19,67 +19,97 @@ const V = "recommendation-spacing-control", o = {
19
19
  MOBILE_COLUMN_SPACING_LABEL: "mobileColumnSpacingLabel",
20
20
  MOBILE_ROW_SPACING: "mobileRowSpacing",
21
21
  MOBILE_ROW_SPACING_LABEL: "mobileRowSpacingLabel"
22
- }, b = {
22
+ }, A = {
23
23
  COLUMN_SPACING: "data-column-spacing",
24
24
  ROW_SPACING: "data-row-spacing",
25
25
  MOBILE_COLUMN_SPACING: "data-mobile-column-spacing",
26
26
  MOBILE_ROW_SPACING: "data-mobile-row-spacing"
27
27
  };
28
- function O(u, s) {
28
+ function I(u, s) {
29
29
  if (!u)
30
30
  return s;
31
31
  const t = parseFloat(u);
32
32
  return Number.isNaN(t) ? s : t;
33
33
  }
34
- class j extends E {
34
+ class j extends R {
35
35
  constructor() {
36
36
  super(...arguments);
37
- g(this, "store", w());
38
- g(this, "unsubscribeOrientation", null);
37
+ C(this, "store", w());
38
+ C(this, "unsubscribeOrientation", null);
39
39
  /**
40
40
  * Debounced version of _onColumnSpacingChange
41
41
  * Prevents excessive DOM updates when user rapidly adjusts the counter
42
42
  */
43
- g(this, "_debouncedOnColumnSpacingChange", N((t) => {
43
+ C(this, "_debouncedOnColumnSpacingChange", O((t) => {
44
44
  this._onColumnSpacingChange(t);
45
45
  }, 300));
46
46
  /**
47
47
  * Debounced version of _onRowSpacingChange
48
48
  */
49
- g(this, "_debouncedOnRowSpacingChange", N((t) => {
49
+ C(this, "_debouncedOnRowSpacingChange", O((t) => {
50
50
  this._onRowSpacingChange(t);
51
51
  }, 300));
52
52
  /**
53
53
  * Debounced version of _onMobileColumnSpacingChange
54
54
  */
55
- g(this, "_debouncedOnMobileColumnSpacingChange", N((t) => {
55
+ C(this, "_debouncedOnMobileColumnSpacingChange", O((t) => {
56
56
  this._onMobileColumnSpacingChange(t);
57
57
  }, 300));
58
58
  /**
59
59
  * Debounced version of _onMobileRowSpacingChange
60
60
  */
61
- g(this, "_debouncedOnMobileRowSpacingChange", N((t) => {
61
+ C(this, "_debouncedOnMobileRowSpacingChange", O((t) => {
62
62
  this._onMobileRowSpacingChange(t);
63
63
  }, 300));
64
64
  }
65
65
  getId() {
66
- return V;
66
+ return U;
67
67
  }
68
68
  getTemplate() {
69
69
  return `
70
70
  <div class="spacing-control-container">
71
- ${this._spacingRow("Column Spacing (px)", o.COLUMN_SPACING_LABEL, o.COLUMN_SPACING)}
72
- ${this._spacingRow("Row Spacing (px)", o.ROW_SPACING_LABEL, o.ROW_SPACING)}
73
- ${this._spacingRow(
74
- "Column Spacing on Mobile (px)",
75
- o.MOBILE_COLUMN_SPACING_LABEL,
76
- o.MOBILE_COLUMN_SPACING
77
- )}
78
- ${this._spacingRow(
79
- "Row Spacing on Mobile (px)",
80
- o.MOBILE_ROW_SPACING_LABEL,
81
- o.MOBILE_ROW_SPACING
82
- )}
71
+ ${this._GuTwoColumns([
72
+ this._GuLabel({
73
+ text: this.api.translate("Column Spacing (px)"),
74
+ name: n.COLUMN_SPACING_LABEL
75
+ }),
76
+ this._GuCounter({
77
+ name: n.COLUMN_SPACING,
78
+ minValue: b,
79
+ maxValue: N,
80
+ step: _
81
+ }),
82
+ this._GuLabel({
83
+ text: this.api.translate("Row Spacing (px)"),
84
+ name: n.ROW_SPACING_LABEL
85
+ }),
86
+ this._GuCounter({
87
+ name: n.ROW_SPACING,
88
+ minValue: b,
89
+ maxValue: N,
90
+ step: _
91
+ }),
92
+ this._GuLabel({
93
+ text: this.api.translate("Column Spacing on Mobile (px)"),
94
+ name: n.MOBILE_COLUMN_SPACING_LABEL
95
+ }),
96
+ this._GuCounter({
97
+ name: n.MOBILE_COLUMN_SPACING,
98
+ minValue: b,
99
+ maxValue: N,
100
+ step: _
101
+ }),
102
+ this._GuLabel({
103
+ text: this.api.translate("Row Spacing on Mobile (px)"),
104
+ name: n.MOBILE_ROW_SPACING_LABEL
105
+ }),
106
+ this._GuCounter({
107
+ name: n.MOBILE_ROW_SPACING,
108
+ minValue: b,
109
+ maxValue: N,
110
+ step: _
111
+ })
112
+ ])}
83
113
  </div>
84
114
  `;
85
115
  }
@@ -92,21 +122,6 @@ class j extends E {
92
122
  onDestroy() {
93
123
  this.unsubscribeOrientation && (this.unsubscribeOrientation(), this.unsubscribeOrientation = null);
94
124
  }
95
- /**
96
- * One label + counter per two-column row, so every spacing field gets the same
97
- * 16px-padded row the color controls already render instead of sharing one grid.
98
- */
99
- _spacingRow(t, e, n) {
100
- return this._GuTwoColumns([
101
- this._GuLabel({ text: this.api.translate(t), name: e }),
102
- this._GuCounter({
103
- name: n,
104
- minValue: R,
105
- maxValue: G,
106
- step: P
107
- })
108
- ]);
109
- }
110
125
  /**
111
126
  * Updates spacing control visibility based on layout orientation and mobileLayoutEnabled.
112
127
  * - List layout: hide column spacing (products are full-width), hide ALL mobile
@@ -117,14 +132,14 @@ class j extends E {
117
132
  _updateSpacingVisibility() {
118
133
  if (!this.api)
119
134
  return;
120
- const t = p.getConfig(this.currentNode), e = this.store.recommendationConfigs.orientation, i = (t.layout || e || _(this.currentNode)) === "grid", { mobileLayoutEnabled: a } = t, r = t.cardsInRow > 1, c = t.mobileCardsInRow > 1;
121
- this.api.setVisibility(o.COLUMN_SPACING, i && r), this.api.setVisibility(o.COLUMN_SPACING_LABEL, i && r), this.api.setVisibility(o.ROW_SPACING, !0), this.api.setVisibility(o.ROW_SPACING_LABEL, !0), this.api.setVisibility(
122
- o.MOBILE_COLUMN_SPACING,
135
+ const t = p.getConfig(this.currentNode), e = this.store.recommendationConfigs.orientation, i = (t.layout || e || f(this.currentNode)) === "grid", { mobileLayoutEnabled: a } = t, r = t.cardsInRow > 1, c = t.mobileCardsInRow > 1;
136
+ this.api.setVisibility(n.COLUMN_SPACING, i && r), this.api.setVisibility(n.COLUMN_SPACING_LABEL, i && r), this.api.setVisibility(n.ROW_SPACING, !0), this.api.setVisibility(n.ROW_SPACING_LABEL, !0), this.api.setVisibility(
137
+ n.MOBILE_COLUMN_SPACING,
123
138
  i && a && c
124
139
  ), this.api.setVisibility(
125
- o.MOBILE_COLUMN_SPACING_LABEL,
140
+ n.MOBILE_COLUMN_SPACING_LABEL,
126
141
  i && a && c
127
- ), this.api.setVisibility(o.MOBILE_ROW_SPACING, i && a), this.api.setVisibility(o.MOBILE_ROW_SPACING_LABEL, i && a);
142
+ ), this.api.setVisibility(n.MOBILE_ROW_SPACING, i && a), this.api.setVisibility(n.MOBILE_ROW_SPACING_LABEL, i && a);
128
143
  }
129
144
  /**
130
145
  * Reads spacing values from node config first, falls back to DOM styles.
@@ -133,12 +148,12 @@ class j extends E {
133
148
  _setFormValues() {
134
149
  if (!this.api)
135
150
  return;
136
- const t = p.hasConfig(this.currentNode), e = p.getConfig(this.currentNode), n = t ? e.columnSpacing : this._getStoredColumnSpacing(), i = t ? e.rowSpacing : this._getStoredRowSpacing();
151
+ const t = p.hasConfig(this.currentNode), e = p.getConfig(this.currentNode), o = t ? e.columnSpacing : this._getStoredColumnSpacing(), i = t ? e.rowSpacing : this._getStoredRowSpacing();
137
152
  this.api.updateValues({
138
- [o.COLUMN_SPACING]: n,
139
- [o.ROW_SPACING]: i,
140
- [o.MOBILE_COLUMN_SPACING]: e.mobileColumnSpacing,
141
- [o.MOBILE_ROW_SPACING]: e.mobileRowSpacing
153
+ [n.COLUMN_SPACING]: o,
154
+ [n.ROW_SPACING]: i,
155
+ [n.MOBILE_COLUMN_SPACING]: e.mobileColumnSpacing,
156
+ [n.MOBILE_ROW_SPACING]: e.mobileRowSpacing
142
157
  });
143
158
  }
144
159
  /**
@@ -150,20 +165,20 @@ class j extends E {
150
165
  */
151
166
  _getStoredColumnSpacing() {
152
167
  if (!this.currentNode)
153
- return C;
154
- const t = this.currentNode.querySelector(m) ?? this.currentNode;
155
- if (_(this.currentNode) === "grid") {
156
- const h = t.querySelector(".recommendation-attribute-row"), l = (h == null ? void 0 : h.querySelector("td")) ?? null, d = f(l, "padding");
168
+ return g;
169
+ const t = this.currentNode.querySelector(S) ?? this.currentNode;
170
+ if (f(this.currentNode) === "grid") {
171
+ const h = t.querySelector(".recommendation-attribute-row"), l = (h == null ? void 0 : h.querySelector("td")) ?? null, d = L(l, "padding");
157
172
  if (!d)
158
- return C;
159
- const A = d.trim().split(/\s+/);
160
- return A.length < 2 ? C : O(A[1], C / 2) * 2;
173
+ return g;
174
+ const y = d.trim().split(/\s+/);
175
+ return y.length < 2 ? g : I(y[1], g / 2) * 2;
161
176
  }
162
- const n = t.querySelector(".product-card-wrapper") ?? null, i = B(n), a = f(i, "padding");
177
+ const o = t.querySelector(".product-card-wrapper") ?? null, i = V(o), a = L(i, "padding");
163
178
  if (!a)
164
- return C;
179
+ return g;
165
180
  const r = a.trim().split(/\s+/);
166
- return r.length < 2 ? C : O(r[1], C / 2) * 2;
181
+ return r.length < 2 ? g : I(r[1], g / 2) * 2;
167
182
  }
168
183
  /**
169
184
  * Gets stored row spacing from the first spacer element's height style
@@ -171,9 +186,9 @@ class j extends E {
171
186
  */
172
187
  _getStoredRowSpacing() {
173
188
  if (!this.currentNode)
174
- return I;
175
- const e = (this.currentNode.querySelector(m) ?? this.currentNode).querySelector(".spacer") ?? null, n = f(e, "height");
176
- return O(n, I);
189
+ return E;
190
+ const e = (this.currentNode.querySelector(S) ?? this.currentNode).querySelector(".spacer") ?? null, o = L(e, "height");
191
+ return I(o, E);
177
192
  }
178
193
  // ========================================================================
179
194
  // Desktop Spacing Handlers
@@ -190,9 +205,9 @@ class j extends E {
190
205
  this.currentNode,
191
206
  { columnSpacing: t },
192
207
  `Changed column spacing to ${t}px`
193
- ), this._storeDataAttribute(b.COLUMN_SPACING, t);
194
- const n = p.getConfig(this.currentNode).layout || _(this.currentNode), i = this.api.getDocumentModifier(), r = `0 ${t / 2}px`, c = this.currentNode.querySelector(m);
195
- c && (n === "grid" ? Array.from(
208
+ ), this._storeDataAttribute(A.COLUMN_SPACING, t);
209
+ const o = p.getConfig(this.currentNode).layout || f(this.currentNode), i = this.api.getDocumentModifier(), r = `0 ${t / 2}px`, c = this.currentNode.querySelector(S);
210
+ c && (o === "grid" ? Array.from(
196
211
  c.querySelectorAll(".attribute-cell")
197
212
  ).forEach((l) => {
198
213
  i.modifyHtml(l).setStyle("padding", r);
@@ -201,7 +216,7 @@ class j extends E {
201
216
  ).forEach((l) => {
202
217
  const d = "parent" in l ? l.parent() : void 0;
203
218
  d && i.modifyHtml(d).setStyle("padding", r);
204
- }), i.apply(new S(`Update column spacing to ${t}px`)));
219
+ }), i.apply(new m(`Update column spacing to ${t}px`)));
205
220
  }
206
221
  /**
207
222
  * Handles row spacing changes for desktop.
@@ -215,19 +230,19 @@ class j extends E {
215
230
  this.currentNode,
216
231
  { rowSpacing: t },
217
232
  `Changed row spacing to ${t}px`
218
- ), this._storeDataAttribute(b.ROW_SPACING, t);
219
- const e = this.currentNode.querySelector(m);
233
+ ), this._storeDataAttribute(A.ROW_SPACING, t);
234
+ const e = this.currentNode.querySelector(S);
220
235
  if (!e)
221
236
  return;
222
- const n = Array.from(
237
+ const o = Array.from(
223
238
  e.querySelectorAll(".spacer")
224
239
  );
225
- if (!n.length)
240
+ if (!o.length)
226
241
  return;
227
242
  const i = this.api.getDocumentModifier(), a = `${t}px`;
228
- n.forEach((r) => {
243
+ o.forEach((r) => {
229
244
  i.modifyHtml(r).setStyle("height", a);
230
- }), i.apply(new S(`Update row spacing to ${t}px`));
245
+ }), i.apply(new m(`Update row spacing to ${t}px`));
231
246
  }
232
247
  // ========================================================================
233
248
  // Mobile Spacing Handlers
@@ -244,9 +259,9 @@ class j extends E {
244
259
  this.currentNode,
245
260
  { mobileColumnSpacing: t },
246
261
  `Changed mobile column spacing to ${t}px`
247
- ), this._storeDataAttribute(b.MOBILE_COLUMN_SPACING, t);
248
- const n = p.getConfig(this.currentNode).layout || _(this.currentNode), i = this.api.getDocumentModifier(), r = `0 ${t / 2}px`, c = this.currentNode.querySelector(L);
249
- c && (n === "grid" ? Array.from(
262
+ ), this._storeDataAttribute(A.MOBILE_COLUMN_SPACING, t);
263
+ const o = p.getConfig(this.currentNode).layout || f(this.currentNode), i = this.api.getDocumentModifier(), r = `0 ${t / 2}px`, c = this.currentNode.querySelector(M);
264
+ c && (o === "grid" ? Array.from(
250
265
  c.querySelectorAll(".attribute-cell")
251
266
  ).forEach((l) => {
252
267
  i.modifyHtml(l).setStyle("padding", r);
@@ -255,7 +270,7 @@ class j extends E {
255
270
  ).forEach((l) => {
256
271
  const d = "parent" in l ? l.parent() : void 0;
257
272
  d && i.modifyHtml(d).setStyle("padding", r);
258
- }), i.apply(new S(`Update mobile column spacing to ${t}px`)));
273
+ }), i.apply(new m(`Update mobile column spacing to ${t}px`)));
259
274
  }
260
275
  /**
261
276
  * Handles row spacing changes for mobile.
@@ -269,19 +284,19 @@ class j extends E {
269
284
  this.currentNode,
270
285
  { mobileRowSpacing: t },
271
286
  `Changed mobile row spacing to ${t}px`
272
- ), this._storeDataAttribute(b.MOBILE_ROW_SPACING, t);
273
- const e = this.currentNode.querySelector(L);
287
+ ), this._storeDataAttribute(A.MOBILE_ROW_SPACING, t);
288
+ const e = this.currentNode.querySelector(M);
274
289
  if (!e)
275
290
  return;
276
- const n = Array.from(
291
+ const o = Array.from(
277
292
  e.querySelectorAll(".spacer")
278
293
  );
279
- if (!n.length)
294
+ if (!o.length)
280
295
  return;
281
296
  const i = this.api.getDocumentModifier(), a = `${t}px`;
282
- n.forEach((r) => {
297
+ o.forEach((r) => {
283
298
  i.modifyHtml(r).setStyle("height", a);
284
- }), i.apply(new S(`Update mobile row spacing to ${t}px`));
299
+ }), i.apply(new m(`Update mobile row spacing to ${t}px`));
285
300
  }
286
301
  // ========================================================================
287
302
  // Data Attribute Storage
@@ -290,23 +305,23 @@ class j extends E {
290
305
  * Stores a spacing value as a data attribute on the block root element
291
306
  */
292
307
  _storeDataAttribute(t, e) {
293
- const n = U(this.currentNode);
294
- n && this.api.getDocumentModifier().modifyHtml(n).setAttribute(t, e.toString()).apply(new S(`Store ${t}`));
308
+ const o = B(this.currentNode);
309
+ o && this.api.getDocumentModifier().modifyHtml(o).setAttribute(t, e.toString()).apply(new m(`Store ${t}`));
295
310
  }
296
311
  // ========================================================================
297
312
  // Event Listeners
298
313
  // ========================================================================
299
314
  _listenToFormUpdates() {
300
- this.api.onValueChanged(o.COLUMN_SPACING, (t) => {
315
+ this.api.onValueChanged(n.COLUMN_SPACING, (t) => {
301
316
  const e = parseInt(t);
302
317
  Number.isNaN(e) || this._debouncedOnColumnSpacingChange(e);
303
- }), this.api.onValueChanged(o.ROW_SPACING, (t) => {
318
+ }), this.api.onValueChanged(n.ROW_SPACING, (t) => {
304
319
  const e = parseInt(t);
305
320
  Number.isNaN(e) || this._debouncedOnRowSpacingChange(e);
306
- }), this.api.onValueChanged(o.MOBILE_COLUMN_SPACING, (t) => {
321
+ }), this.api.onValueChanged(n.MOBILE_COLUMN_SPACING, (t) => {
307
322
  const e = parseInt(t);
308
323
  Number.isNaN(e) || this._debouncedOnMobileColumnSpacingChange(e);
309
- }), this.api.onValueChanged(o.MOBILE_ROW_SPACING, (t) => {
324
+ }), this.api.onValueChanged(n.MOBILE_ROW_SPACING, (t) => {
310
325
  const e = parseInt(t);
311
326
  Number.isNaN(e) || this._debouncedOnMobileRowSpacingChange(e);
312
327
  });
@@ -322,6 +337,6 @@ class j extends E {
322
337
  }
323
338
  }
324
339
  export {
325
- V as SPACING_CONTROL_ID,
340
+ U as SPACING_CONTROL_ID,
326
341
  j as SpacingControl
327
342
  };
@@ -25,27 +25,6 @@ const n = `/* Utils */
25
25
  border-top: none;
26
26
  }
27
27
 
28
- /* The editor's row-separator rule only reaches \`.container\`s that are direct
29
- children of \`.container-wrapper\`; the spacing rows sit one level deeper, so the
30
- first one loses its line. Restore it with the editor's own border token. */
31
- .spacing-control-container > .container {
32
- border-top: var(--ue-border-width-1, 1px) solid var(--ue-panels-border-color, rgba(0, 0, 0, 0.07));
33
- }
34
-
35
- /* A spacing field that doesn't apply (mobile rows, column spacing in list layout) is
36
- removed from its row and leaves the wrapper behind — collapse it so it can't
37
- render as an empty separator-topped strip. */
38
- .spacing-control-container > .container:not(:has(ue-counter)) {
39
- display: none;
40
- }
41
-
42
- /* The block background row stacks the editor's "inherits background color" banner
43
- above its field, separated by the editor's default 10px gap — match the tab's 16px.
44
- Scoped via the spacing control so other blocks keep the default. */
45
- .ue-scrollable-content:has(.spacing-control-container) .e2e-block-bg-color {
46
- row-gap: 16px;
47
- }
48
-
49
28
  /* Right-align the mobile layout toggle within the two-column grid */
50
29
  .product-layout-control-container ue-switcher {
51
30
  justify-self: end;
@@ -1,15 +1,16 @@
1
1
  import { getRecommendationFeedSourceMaps as g, getOperatorOptions as R, PriceAttributes as C } from "../../../../enums/extensions/recommendationBlock.js";
2
2
  import { useRecommendationApi as y } from "../../../../services/recommendationApi.js";
3
3
  import { useConfigStore as G } from "../../../../stores/config.js";
4
- import { defineStore as F } from "pinia";
4
+ import { defineStore as P } from "pinia";
5
5
  import "../constants/selectors.js";
6
- import { DEFAULT_MOBILE_CARDS_IN_ROW as P, DEFAULT_CARDS_IN_ROW as D } from "../constants/layout.js";
6
+ import { DEFAULT_MOBILE_CARDS_IN_ROW as F, DEFAULT_CARDS_IN_ROW as D } from "../constants/layout.js";
7
7
  import { EXCLUDED_ALGORITHM_IDS as w } from "../constants/defaultConfig.js";
8
8
  import { getDefaultProducts as S } from "../templates/utils.js";
9
9
  import { generateCompleteFilterQuery as b } from "../utils/filterUtil.js";
10
10
  import { getPartnerRecommendationParams as v } from "../utils/partnerCustomizations.js";
11
- import { isFilterValid as N } from "../validation/filterSchema.js";
12
- import { isConfigValid as x } from "../validation/requiredFields.js";
11
+ import { sanitizeProductIds as N } from "../utils/productIds.js";
12
+ import { isFilterValid as x } from "../validation/filterSchema.js";
13
+ import { isConfigValid as L } from "../validation/requiredFields.js";
13
14
  const h = y();
14
15
  let m = null, u = null, d = null;
15
16
  function k() {
@@ -28,7 +29,7 @@ function k() {
28
29
  productIds: [],
29
30
  id: 1,
30
31
  language: "en_US",
31
- mobileCardsInRow: P,
32
+ mobileCardsInRow: F,
32
33
  mobileLayoutEnabled: !1,
33
34
  orientation: "grid",
34
35
  recommendedProducts: [],
@@ -54,7 +55,7 @@ function I() {
54
55
  filterSnapshot: null
55
56
  };
56
57
  }
57
- const L = () => ({
58
+ const U = () => ({
58
59
  recommendationCampaignUrls: {},
59
60
  activePredictiveAlgorithms: [],
60
61
  languages: {},
@@ -63,8 +64,8 @@ const L = () => ({
63
64
  blockStates: {},
64
65
  currentRecommendationId: null,
65
66
  configVersion: 0
66
- }), $ = F("guidoRecommendationExtension", {
67
- state: () => L(),
67
+ }), H = P("guidoRecommendationExtension", {
68
+ state: () => U(),
68
69
  getters: {
69
70
  // ====================================================================
70
71
  // Proxy Getters — Backward Compatible Access to Current Block State
@@ -383,7 +384,7 @@ const L = () => ({
383
384
  const n = [...e.recommendationConfigs.filters];
384
385
  n[r] = {
385
386
  ...t,
386
- isValid: N(t)
387
+ isValid: x(t)
387
388
  }, e.recommendationConfigs.filters = n;
388
389
  }
389
390
  },
@@ -429,7 +430,7 @@ const L = () => ({
429
430
  * every block's recommendationConfigs across user edits.
430
431
  */
431
432
  hasInvalidBlock() {
432
- return Object.values(this.blockStates).some((t) => !x(t.recommendationConfigs, this));
433
+ return Object.values(this.blockStates).some((t) => !L(t.recommendationConfigs, this));
433
434
  },
434
435
  // ====================================================================
435
436
  // Per-Block Product Fetching
@@ -458,7 +459,7 @@ const L = () => ({
458
459
  details: !0,
459
460
  campaignId: o.variationId
460
461
  };
461
- r.strategy === "manualMerchandising" ? a.productId = r.productIds.join(",") : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), c && (a.filter = c), r.shuffleProducts && (a.shuffle = !0), Object.assign(
462
+ r.strategy === "manualMerchandising" ? a.productId = N(r.productIds) : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), c && (a.filter = c), r.shuffleProducts && (a.shuffle = !0), Object.assign(
462
463
  a,
463
464
  v(o.partnerName, r.strategy)
464
465
  );
@@ -479,5 +480,5 @@ const L = () => ({
479
480
  }
480
481
  });
481
482
  export {
482
- $ as useRecommendationExtensionStore
483
+ H as useRecommendationExtensionStore
483
484
  };
@@ -28,10 +28,10 @@ const G = `
28
28
  {-{-CELLS-}-}
29
29
  </tr>
30
30
  `;
31
- function j(e, t, n, r = Y, c = {}, i = {}) {
32
- const { cellPadding: s = k, cardBackgroundColor: u, visibility: a, priceInline: o = !1 } = i, d = (100 / t).toFixed(2), p = t - e.length, T = p > 0 ? x(d, s).repeat(p) : "", m = B(n, r, c), R = F(r), L = o ? r.filter((l) => l !== R.skip) : r, C = I(f, i), P = I(O, i);
31
+ function j(t, r, o, e = Y, c = {}, i = {}) {
32
+ const { cellPadding: s = k, cardBackgroundColor: u, visibility: a, priceInline: n = !1 } = i, d = (100 / r).toFixed(2), p = r - t.length, T = p > 0 ? x(d, s).repeat(p) : "", m = B(o, e, c), R = F(e), L = n ? e.filter((l) => l !== R.skip) : e, C = I(f, i), P = I(O, i);
33
33
  return L.filter((l) => m[l]).map((l) => {
34
- const _ = (a == null ? void 0 : a[l]) ?? W[l] ?? !0, b = _ ? "" : 'style="display: none;"', S = I(l, i), D = e.map((E) => (o && l === R.anchor ? H(
34
+ const _ = (a == null ? void 0 : a[l]) ?? W[l] ?? !0, b = _ ? "" : 'style="display: none;"', S = I(l, i, e), D = t.map((E) => (n && l === R.anchor ? H(
35
35
  E,
36
36
  R.originalFirst,
37
37
  C,
@@ -41,36 +41,36 @@ function j(e, t, n, r = Y, c = {}, i = {}) {
41
41
  return V.replace("{-{-ATTR_TYPE-}-}", l).replace("{-{-VISIBILITY-}-}", _ ? "1" : "0").replace("{-{-DISPLAY_STYLE-}-}", b).replace("{-{-CELLS-}-}", D + T);
42
42
  }).join("");
43
43
  }
44
- function v(e, t, n, r, c = {}, i = {}) {
44
+ function v(t, r, o, e, c = {}, i = {}) {
45
45
  const s = [];
46
- for (let o = 0; o < e.length; o += t)
47
- s.push(e.slice(o, o + t));
46
+ for (let n = 0; n < t.length; n += r)
47
+ s.push(t.slice(n, n + r));
48
48
  const u = h(i.rowSpacingPx);
49
- return s.map((o, d) => {
49
+ return s.map((n, d) => {
50
50
  const p = j(
51
- o,
52
- t,
53
51
  n,
54
52
  r,
53
+ o,
54
+ e,
55
55
  c,
56
56
  i
57
57
  ), T = G.replace("{-{-ATTRIBUTE_ROWS-}-}", p);
58
58
  return d > 0 ? u + T : T;
59
59
  }).join("");
60
60
  }
61
- function M(e, t, n, r = {}, c = {}) {
61
+ function M(t, r, o, e = {}, c = {}) {
62
62
  return v(
63
- e,
64
63
  t,
65
- y,
66
- n,
67
64
  r,
65
+ y,
66
+ o,
67
+ e,
68
68
  c
69
69
  );
70
70
  }
71
- function Q(e) {
72
- const t = e ? `ins-recommendation-v3-block-${e}` : void 0, n = U("grid", t), r = A(), c = M(r, w);
73
- return n.replace("{-{-TITLE-}-}", g.TITLE).replace("{-{-PRODUCT_ROWS-}-}", c).replace("{-{-MOBILE_PRODUCT_ROWS-}-}", "");
71
+ function Q(t) {
72
+ const r = t ? `ins-recommendation-v3-block-${t}` : void 0, o = U("grid", r), e = A(), c = M(e, w);
73
+ return o.replace("{-{-TITLE-}-}", g.TITLE).replace("{-{-PRODUCT_ROWS-}-}", c).replace("{-{-MOBILE_PRODUCT_ROWS-}-}", "");
74
74
  }
75
75
  export {
76
76
  Q as getDefaultTemplate,
@@ -1,13 +1,13 @@
1
- import { ATTR_PRODUCT_IMAGE as p, ATTR_PRODUCT_BUTTON as C, ATTR_PRODUCT_OLD_PRICE as A, ATTR_PRODUCT_PRICE as m } from "../../constants/selectors.js";
2
- import { buildSpacer as I, DEFAULT_CARD_COMPOSITION as g, buildElementRenderer as E, buildCellOptions as i, resolveInlinePriceOrder as w, DEFAULT_CARD_VISIBILITY as y } from "../utils.js";
1
+ import { ATTR_PRODUCT_IMAGE as p, ATTR_PRODUCT_BUTTON as C, ATTR_PRODUCT_OLD_PRICE as A, ATTR_PRODUCT_PRICE as I } from "../../constants/selectors.js";
2
+ import { buildSpacer as m, DEFAULT_CARD_COMPOSITION as g, buildElementRenderer as E, buildCellOptions as i, resolveInlinePriceOrder as w, DEFAULT_CARD_VISIBILITY as y } from "../utils.js";
3
3
  import { listElementRenderer as L, renderInlineListPriceRow as O } from "./elementRenderer.js";
4
4
  const S = "0 5px";
5
5
  function U(l, r, n) {
6
- const e = n ? "" : ' style="display: none;"', o = l.replace(/<tr>/, "").replace(/<\/tr>/, "");
6
+ const t = n ? "" : ' style="display: none;"', o = l.replace(/<tr>/, "").replace(/<\/tr>/, "");
7
7
  return `<tr
8
8
  class="recommendation-attribute-row"
9
9
  data-attribute-type="${r}"
10
- data-visibility="${n ? "1" : "0"}"${e}>${o}</tr>`;
10
+ data-visibility="${n ? "1" : "0"}"${t}>${o}</tr>`;
11
11
  }
12
12
  const N = `
13
13
  <tr class="recommendation-product-row">
@@ -27,36 +27,36 @@ const N = `
27
27
  </td>
28
28
  </tr>
29
29
  `;
30
- function x(l, r = g, n = {}, e = {}) {
30
+ function x(l, r = g, n = {}, t = {}) {
31
31
  const {
32
32
  cellPadding: o = S,
33
33
  cardBackgroundColor: d,
34
34
  visibility: c,
35
35
  priceInline: a = !1
36
- } = e, u = d ? ` style="table-layout: fixed; background-color: ${d};"` : ' style="table-layout: fixed;"', s = E(L, r, n), P = s[p](l, i(p, e)), R = w(r), T = `
36
+ } = t, u = d ? ` style="table-layout: fixed; background-color: ${d};"` : ' style="table-layout: fixed;"', s = E(L, r, n), P = s[p](l, i(p, t)), R = w(r), T = `
37
37
  <td class="product-info-cell" valign="middle" style="padding: 15px;">
38
38
  <table cellpadding="0" cellspacing="0" role="presentation" width="100%" style="table-layout: fixed;">
39
39
  <tbody>
40
- ${r.filter((t) => t !== p && t !== C).filter((t) => !(a && t === R.skip)).filter((t) => s[t]).map((t) => {
41
- const b = (c == null ? void 0 : c[t]) ?? y[t] ?? !0, f = a && t === R.anchor ? O(
40
+ ${r.filter((e) => e !== p && e !== C).filter((e) => !(a && e === R.skip)).filter((e) => s[e]).map((e) => {
41
+ const b = (c == null ? void 0 : c[e]) ?? y[e] ?? !0, f = a && e === R.anchor ? O(
42
42
  l,
43
43
  R.originalFirst,
44
- i(m, e),
45
- i(A, e)
46
- ) : s[t](l, i(t, e));
47
- return U(f, t, b);
44
+ i(I, t),
45
+ i(A, t)
46
+ ) : s[e](l, i(e, t, r));
47
+ return U(f, e, b);
48
48
  }).join(`
49
49
  `)}
50
50
  </tbody>
51
51
  </table>
52
52
  </td>
53
- `, _ = s[C](l, i(C, e)), D = P + T + _;
53
+ `, _ = s[C](l, i(C, t)), D = P + T + _;
54
54
  return N.replace("{-{-CARD_PADDING-}-}", o).replace("{-{-WRAPPER_STYLE-}-}", u).replace("{-{-PRODUCT_CONTENT-}-}", D);
55
55
  }
56
- function W(l, r, n = {}, e = {}) {
57
- const o = I(e.rowSpacingPx);
56
+ function W(l, r, n = {}, t = {}) {
57
+ const o = m(t.rowSpacingPx);
58
58
  return l.map((d, c) => {
59
- const a = x(d, r, n, e);
59
+ const a = x(d, r, n, t);
60
60
  return c > 0 ? o + a : a;
61
61
  }).join("");
62
62
  }