@useinsider/guido 1.0.3-beta.4f5545f → 1.0.3-beta.4fc0167

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 (95) hide show
  1. package/dist/config/migrator/index.js +7 -6
  2. package/dist/config/migrator/recommendationMigrator.js +293 -0
  3. package/dist/extensions/Blocks/Recommendation/block.js +6 -3
  4. package/dist/extensions/Blocks/Recommendation/cardCompositionControl.js +103 -0
  5. package/dist/extensions/Blocks/Recommendation/constants.js +5 -0
  6. package/dist/extensions/Blocks/Recommendation/control.js +69 -40
  7. package/dist/extensions/Blocks/Recommendation/controls/button/align.js +13 -0
  8. package/dist/extensions/Blocks/Recommendation/controls/button/border.js +13 -0
  9. package/dist/extensions/Blocks/Recommendation/controls/button/borderRadius.js +13 -0
  10. package/dist/extensions/Blocks/Recommendation/controls/button/color.js +13 -0
  11. package/dist/extensions/Blocks/Recommendation/controls/button/fitToContent.js +13 -0
  12. package/dist/extensions/Blocks/Recommendation/controls/button/fontFamily.js +13 -0
  13. package/dist/extensions/Blocks/Recommendation/controls/button/margins.js +13 -0
  14. package/dist/extensions/Blocks/Recommendation/controls/button/paddings.js +13 -0
  15. package/dist/extensions/Blocks/Recommendation/controls/button/text.js +13 -0
  16. package/dist/extensions/Blocks/Recommendation/controls/button/textSize.js +13 -0
  17. package/dist/extensions/Blocks/Recommendation/controls/button/textStyleAndFontColor.js +13 -0
  18. package/dist/extensions/Blocks/Recommendation/controls/image/margins.js +13 -0
  19. package/dist/extensions/Blocks/Recommendation/controls/image/size.js +13 -0
  20. package/dist/extensions/Blocks/Recommendation/controls/name/align.js +13 -0
  21. package/dist/extensions/Blocks/Recommendation/controls/name/background.js +13 -0
  22. package/dist/extensions/Blocks/Recommendation/controls/name/color.js +13 -0
  23. package/dist/extensions/Blocks/Recommendation/controls/name/fontFamily.js +13 -0
  24. package/dist/extensions/Blocks/Recommendation/controls/name/paddings.js +13 -0
  25. package/dist/extensions/Blocks/Recommendation/controls/name/size.js +13 -0
  26. package/dist/extensions/Blocks/Recommendation/controls/name/style.js +13 -0
  27. package/dist/extensions/Blocks/Recommendation/controls/oldPrice/align.js +13 -0
  28. package/dist/extensions/Blocks/Recommendation/controls/oldPrice/background.js +13 -0
  29. package/dist/extensions/Blocks/Recommendation/controls/oldPrice/color.js +13 -0
  30. package/dist/extensions/Blocks/Recommendation/controls/oldPrice/fontFamily.js +13 -0
  31. package/dist/extensions/Blocks/Recommendation/controls/oldPrice/paddings.js +13 -0
  32. package/dist/extensions/Blocks/Recommendation/controls/oldPrice/size.js +13 -0
  33. package/dist/extensions/Blocks/Recommendation/controls/oldPrice/style.js +13 -0
  34. package/dist/extensions/Blocks/Recommendation/controls/price/align.js +13 -0
  35. package/dist/extensions/Blocks/Recommendation/controls/price/background.js +13 -0
  36. package/dist/extensions/Blocks/Recommendation/controls/price/color.js +13 -0
  37. package/dist/extensions/Blocks/Recommendation/controls/price/fontFamily.js +13 -0
  38. package/dist/extensions/Blocks/Recommendation/controls/price/paddings.js +13 -0
  39. package/dist/extensions/Blocks/Recommendation/controls/price/size.js +13 -0
  40. package/dist/extensions/Blocks/Recommendation/controls/price/style.js +13 -0
  41. package/dist/extensions/Blocks/Recommendation/extension.js +42 -7
  42. package/dist/extensions/Blocks/Recommendation/settingsPanel.js +107 -22
  43. package/dist/extensions/Blocks/Recommendation/templates/blockTemplate.js +160 -0
  44. package/dist/extensions/Blocks/Recommendation/templates/migrationTemplate.js +152 -0
  45. package/dist/extensions/Blocks/Recommendation/templates/templateUtils.js +180 -0
  46. package/dist/extensions/Blocks/common-control.js +125 -43
  47. package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js +307 -100
  48. package/dist/package.json.js +1 -1
  49. package/dist/src/config/migrator/recommendationMigrator.d.ts +1 -0
  50. package/dist/src/extensions/Blocks/Recommendation/block.d.ts +1 -0
  51. package/dist/src/extensions/Blocks/Recommendation/cardCompositionControl.d.ts +28 -0
  52. package/dist/src/extensions/Blocks/Recommendation/constants.d.ts +51 -0
  53. package/dist/src/extensions/Blocks/Recommendation/control.d.ts +6 -0
  54. package/dist/src/extensions/Blocks/Recommendation/controls/button/align.d.ts +5 -0
  55. package/dist/src/extensions/Blocks/Recommendation/controls/button/border.d.ts +5 -0
  56. package/dist/src/extensions/Blocks/Recommendation/controls/button/borderRadius.d.ts +5 -0
  57. package/dist/src/extensions/Blocks/Recommendation/controls/button/color.d.ts +5 -0
  58. package/dist/src/extensions/Blocks/Recommendation/controls/button/fitToContent.d.ts +5 -0
  59. package/dist/src/extensions/Blocks/Recommendation/controls/button/fontFamily.d.ts +5 -0
  60. package/dist/src/extensions/Blocks/Recommendation/controls/button/margins.d.ts +5 -0
  61. package/dist/src/extensions/Blocks/Recommendation/controls/button/paddings.d.ts +5 -0
  62. package/dist/src/extensions/Blocks/Recommendation/controls/button/text.d.ts +5 -0
  63. package/dist/src/extensions/Blocks/Recommendation/controls/button/textSize.d.ts +5 -0
  64. package/dist/src/extensions/Blocks/Recommendation/controls/button/textStyleAndFontColor.d.ts +5 -0
  65. package/dist/src/extensions/Blocks/Recommendation/controls/image/margins.d.ts +5 -0
  66. package/dist/src/extensions/Blocks/Recommendation/controls/image/size.d.ts +5 -0
  67. package/dist/src/extensions/Blocks/Recommendation/controls/name/align.d.ts +5 -0
  68. package/dist/src/extensions/Blocks/Recommendation/controls/name/background.d.ts +5 -0
  69. package/dist/src/extensions/Blocks/Recommendation/controls/name/color.d.ts +5 -0
  70. package/dist/src/extensions/Blocks/Recommendation/controls/name/fontFamily.d.ts +5 -0
  71. package/dist/src/extensions/Blocks/Recommendation/controls/name/paddings.d.ts +5 -0
  72. package/dist/src/extensions/Blocks/Recommendation/controls/name/size.d.ts +5 -0
  73. package/dist/src/extensions/Blocks/Recommendation/controls/name/style.d.ts +5 -0
  74. package/dist/src/extensions/Blocks/Recommendation/controls/oldPrice/align.d.ts +5 -0
  75. package/dist/src/extensions/Blocks/Recommendation/controls/oldPrice/background.d.ts +5 -0
  76. package/dist/src/extensions/Blocks/Recommendation/controls/oldPrice/color.d.ts +5 -0
  77. package/dist/src/extensions/Blocks/Recommendation/controls/oldPrice/fontFamily.d.ts +5 -0
  78. package/dist/src/extensions/Blocks/Recommendation/controls/oldPrice/paddings.d.ts +5 -0
  79. package/dist/src/extensions/Blocks/Recommendation/controls/oldPrice/size.d.ts +5 -0
  80. package/dist/src/extensions/Blocks/Recommendation/controls/oldPrice/style.d.ts +5 -0
  81. package/dist/src/extensions/Blocks/Recommendation/controls/price/align.d.ts +5 -0
  82. package/dist/src/extensions/Blocks/Recommendation/controls/price/background.d.ts +5 -0
  83. package/dist/src/extensions/Blocks/Recommendation/controls/price/color.d.ts +5 -0
  84. package/dist/src/extensions/Blocks/Recommendation/controls/price/fontFamily.d.ts +5 -0
  85. package/dist/src/extensions/Blocks/Recommendation/controls/price/paddings.d.ts +5 -0
  86. package/dist/src/extensions/Blocks/Recommendation/controls/price/size.d.ts +5 -0
  87. package/dist/src/extensions/Blocks/Recommendation/controls/price/style.d.ts +5 -0
  88. package/dist/src/extensions/Blocks/Recommendation/templates/blockTemplate.d.ts +16 -0
  89. package/dist/src/extensions/Blocks/Recommendation/templates/migrationTemplate.d.ts +16 -0
  90. package/dist/src/extensions/Blocks/Recommendation/templates/templateUtils.d.ts +44 -0
  91. package/dist/src/extensions/Blocks/common-control.d.ts +21 -0
  92. package/dist/static/styles/customEditorStyle.css.js +5 -0
  93. package/package.json +3 -3
  94. package/dist/extensions/Blocks/Recommendation/template.js +0 -200
  95. package/dist/src/extensions/Blocks/Recommendation/template.d.ts +0 -6
@@ -1,11 +1,12 @@
1
- import { migrateCheckbox as o } from "./checkboxMigrator.js";
2
- import { migrateCouponBlock as m } from "./couponBlockMigrator.js";
1
+ import { migrateCheckbox as m } from "./checkboxMigrator.js";
2
+ import { migrateCouponBlock as o } from "./couponBlockMigrator.js";
3
3
  import { migrateRadioButton as i } from "./radioButtonMigrator.js";
4
- import { migrateUnsubscribe as e } from "./unsubscribeMigrator.js";
5
- const c = async (t) => {
4
+ import { migrateRecommendation as e } from "./recommendationMigrator.js";
5
+ import { migrateUnsubscribe as a } from "./unsubscribeMigrator.js";
6
+ const s = async (t) => {
6
7
  let r = t;
7
- return r = o(r), r = i(r), r = await e(r), r = m(r), r;
8
+ return r = m(r), r = i(r), r = await a(r), r = o(r), r = e(r), r;
8
9
  };
9
10
  export {
10
- c as migrate
11
+ s as migrate
11
12
  };
@@ -0,0 +1,293 @@
1
+ var h = Object.defineProperty;
2
+ var T = (A, e, t) => e in A ? h(A, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : A[e] = t;
3
+ var m = (A, e, t) => T(A, typeof e != "symbol" ? e + "" : e, t);
4
+ import P, { prepareProductRows as S } from "../../extensions/Blocks/Recommendation/templates/migrationTemplate.js";
5
+ import { getDefaultProducts as q } from "../../extensions/Blocks/Recommendation/templates/templateUtils.js";
6
+ class w {
7
+ constructor() {
8
+ m(this, "parser");
9
+ this.parser = new DOMParser();
10
+ }
11
+ migrate(e) {
12
+ try {
13
+ const t = this.parser.parseFromString(e, "text/html"), s = t.querySelectorAll(
14
+ 'td.ins-recommendation-v3-block-1, td.product-block[esd-handler-name*="EmailRecommendationV3"]'
15
+ );
16
+ return s.length === 0 ? e : (s.forEach((o) => {
17
+ const l = o.getAttribute("id"), r = this.extractBgColor(o), i = this.extractTitle(o), u = this.extractProductRows(o), c = P.replace("{-{-TITLE-}-}", i).replace("{-{-PRODUCT_ROWS-}-}", u), a = this.parser.parseFromString(
18
+ `<table id="tempDoc"><tbody><tr>${c}</tr></tbody></table>`,
19
+ "text/html"
20
+ ).querySelector(".ins-recommendation-v3-block-v2");
21
+ a && o.parentNode && (l && a.setAttribute("id", l), r && a.setAttribute("bgcolor", r), o.parentNode.replaceChild(a, o));
22
+ }), t.documentElement.outerHTML);
23
+ } catch (t) {
24
+ return console.error("RecommendationMigrator failed:", t), e;
25
+ }
26
+ }
27
+ /**
28
+ * Extracts background color from old block
29
+ * @param block - The old recommendation block element
30
+ * @returns The background color value or empty string
31
+ */
32
+ extractBgColor(e) {
33
+ const t = e.getAttribute("bgcolor");
34
+ if (t)
35
+ return t.trim();
36
+ const s = e.getAttribute("style");
37
+ if (s) {
38
+ const o = s.match(/background-color\s*:\s*([^;]+)/i);
39
+ if (o && o[1])
40
+ return o[1].trim();
41
+ }
42
+ return "";
43
+ }
44
+ /**
45
+ * Extracts background color from product card wrapper element
46
+ * @param cardElement - The product card TD element
47
+ * @returns The background color value or empty string
48
+ */
49
+ extractCardBgColor(e) {
50
+ const t = e.getAttribute("bgcolor");
51
+ if (t)
52
+ return t.trim();
53
+ const s = e.getAttribute("style");
54
+ if (s) {
55
+ const o = s.match(/background-color\s*:\s*([^;]+)/i);
56
+ if (o && o[1])
57
+ return o[1].trim();
58
+ }
59
+ return "";
60
+ }
61
+ /**
62
+ * Extracts title from old block and converts to new structure
63
+ * @param block - The old recommendation block element
64
+ * @returns HTML string for the title block
65
+ */
66
+ extractTitle(e) {
67
+ var a, g;
68
+ const t = e.querySelector(".ext-recommendation-title");
69
+ if (!t)
70
+ return this.buildTitleBlock({
71
+ text: "You May Also Like!",
72
+ isBold: !0,
73
+ isItalic: !1,
74
+ align: "center",
75
+ styles: "font-size: 28px; color: #333333;"
76
+ });
77
+ const s = t.querySelector("p");
78
+ if (!s) {
79
+ const p = ((a = t.textContent) == null ? void 0 : a.trim()) || "You May Also Like!", b = t.getAttribute("align") || "center";
80
+ return this.buildTitleBlock({
81
+ text: p,
82
+ isBold: !0,
83
+ isItalic: !1,
84
+ align: b,
85
+ styles: "font-size: 28px; color: #333333;"
86
+ });
87
+ }
88
+ const o = ((g = s.textContent) == null ? void 0 : g.trim()) || "You May Also Like!", l = t.getAttribute("align") || s.getAttribute("align") || "center", r = s.getAttribute("style") || "", i = /font-weight\s*:\s*bold/i.test(r) || !!s.querySelector("b, strong"), u = /font-style\s*:\s*italic/i.test(r) || !!s.querySelector("i, em"), c = this.removeStyleProperties(r, ["font-weight", "font-style"]), n = this.convertInlineToBlock(c);
89
+ return this.buildTitleBlock({
90
+ text: o,
91
+ isBold: i,
92
+ isItalic: u,
93
+ align: l,
94
+ styles: n
95
+ });
96
+ }
97
+ /**
98
+ * Extracts product configuration from old block and generates new product rows
99
+ * @param block - The old recommendation block element
100
+ * @returns HTML string for product rows
101
+ */
102
+ extractProductRows(e) {
103
+ const t = this.extractProductConfig(e);
104
+ if (!t)
105
+ return console.warn("[RecommendationMigrator] No product config found, using defaults"), this.generateProductRows(6, 3, {});
106
+ const { totalCount: s, productsPerRow: o } = t, l = this.extractProductStyles(e);
107
+ return this.generateProductRows(s, o, l);
108
+ }
109
+ /**
110
+ * Extracts Stripo padding/margin utility classes from a class string
111
+ * @param classString - Space-separated class string from element
112
+ * @returns Filtered Stripo utility classes as a space-separated string
113
+ */
114
+ extractStripoClasses(e) {
115
+ return e ? e.split(/\s+/).filter((o) => /^es-(p\d+|m[-\d])/.test(o)).join(" ") : "";
116
+ }
117
+ /**
118
+ * Extracts product configuration from old block
119
+ * @param block - The old recommendation block element
120
+ * @returns Object with totalCount and productsPerRow, or null if parsing fails
121
+ */
122
+ extractProductConfig(e) {
123
+ const t = e.getAttribute("esd-dev-product-config");
124
+ if (!t)
125
+ return null;
126
+ try {
127
+ const s = this.unescapeJsonString(t), o = JSON.parse(s);
128
+ return {
129
+ totalCount: o.totalCount ?? 6,
130
+ productsPerRow: o.rowCount ?? 3
131
+ };
132
+ } catch (s) {
133
+ return console.error("[RecommendationMigrator] Failed to parse product config:", s), console.error(
134
+ "[RecommendationMigrator] Error details:",
135
+ s instanceof Error ? s.message : String(s)
136
+ ), null;
137
+ }
138
+ }
139
+ /**
140
+ * Decodes HTML entities from JSON string
141
+ * @param text - The encoded string
142
+ * @returns Decoded string
143
+ */
144
+ unescapeJsonString(e) {
145
+ return e.replace(/&amp;/g, "&").replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&#x27;/g, "'").replace(/&quot;/g, '"').replace(/\\\\"/g, "'");
146
+ }
147
+ /**
148
+ * Generates product rows using prepareProductRows with default product data
149
+ * @param totalCount - Total number of products to display
150
+ * @param productsPerRow - Number of products in each row
151
+ * @param extractedStyles - Styles extracted from old product elements
152
+ * @returns HTML string for product rows with applied styles
153
+ */
154
+ generateProductRows(e, t, s) {
155
+ const o = q(), l = [];
156
+ for (let i = 0; i < e; i++) {
157
+ const u = o[i % o.length];
158
+ l.push({ ...u });
159
+ }
160
+ let r = S(l, t);
161
+ return r = this.applyExtractedStyles(r, s), r;
162
+ }
163
+ /**
164
+ * Extracts styles from old product elements
165
+ * @param block - The old recommendation block element
166
+ * @returns Object with extracted styles for each element type
167
+ */
168
+ extractProductStyles(e) {
169
+ const t = {}, s = e.querySelector(".product-card");
170
+ if (!s)
171
+ return console.warn("[RecommendationMigrator] No product card found, using default styles"), t;
172
+ const o = this.extractCardBgColor(s);
173
+ o && (t.cardBgColor = o);
174
+ const l = s.querySelector(".ext-product-image");
175
+ if (l) {
176
+ const n = l.querySelector("img"), a = n == null ? void 0 : n.getAttribute("width"), g = l.getAttribute("style") || "", p = l.getAttribute("align") || "center", b = l.getAttribute("class") || "", d = this.extractStripoClasses(b);
177
+ t.imageWidth = a || "120", t.imageAlign = p, t.imageTdStyle = g, t.imageClasses = d;
178
+ }
179
+ const r = s.querySelector(".ext-product-name");
180
+ if (r) {
181
+ const n = r.querySelector("p"), a = (n == null ? void 0 : n.getAttribute("style")) || "", g = r.getAttribute("align") || "center", p = r.getAttribute("style") || "", b = r.getAttribute("class") || "", d = this.extractStripoClasses(b);
182
+ t.nameStyle = a, t.nameAlign = g, t.nameTdStyle = p, t.nameClasses = d;
183
+ }
184
+ const i = s.querySelector(".ext-product-price");
185
+ if (i) {
186
+ const n = i.querySelector("p"), a = (n == null ? void 0 : n.getAttribute("style")) || "", g = i.getAttribute("align") || "center", p = i.getAttribute("style") || "", b = i.getAttribute("class") || "", d = this.extractStripoClasses(b);
187
+ t.priceStyle = a, t.priceAlign = g, t.priceTdStyle = p, t.priceClasses = d;
188
+ }
189
+ const u = s.querySelector(".ext-product-original-price");
190
+ if (u) {
191
+ const n = u.querySelector("p"), a = (n == null ? void 0 : n.getAttribute("style")) || "", g = u.getAttribute("align") || "center", p = u.getAttribute("style") || "", b = u.getAttribute("class") || "", d = this.extractStripoClasses(b);
192
+ t.oldPriceStyle = a, t.oldPriceAlign = g, t.oldPriceTdStyle = p, t.oldPriceClasses = d;
193
+ }
194
+ const c = s.querySelector(".ext-product-button");
195
+ if (c) {
196
+ const n = c.querySelector(".es-button-border"), a = c.querySelector("a.es-button"), g = (n == null ? void 0 : n.getAttribute("style")) || "", p = (a == null ? void 0 : a.getAttribute("style")) || "", b = c.getAttribute("align") || "center", d = c.getAttribute("style") || "", f = c.getAttribute("class") || "", C = this.extractStripoClasses(f), y = ((c == null ? void 0 : c.textContent) || "").trim();
197
+ t.buttonBorderStyle = g, t.buttonLinkStyle = p, t.buttonAlign = b, t.buttonTdStyle = d, t.buttonClasses = C, t.buttonText = y;
198
+ }
199
+ return t;
200
+ }
201
+ /**
202
+ * Applies extracted styles to the generated HTML
203
+ * @param html - The generated HTML from prepareProductRows
204
+ * @param extractedStyles - Styles extracted from old product elements
205
+ * @returns HTML with applied styles
206
+ */
207
+ applyExtractedStyles(e, t) {
208
+ if (!t || Object.keys(t).length === 0)
209
+ return e;
210
+ const s = this.parser.parseFromString(`<table>${e}</table>`, "text/html");
211
+ t.cardBgColor && s.querySelectorAll(".product-attribute-cell").forEach((r) => {
212
+ r.setAttribute("bgcolor", t.cardBgColor);
213
+ }), (t.imageWidth || t.imageAlign || t.imageTdStyle || t.imageClasses) && s.querySelectorAll(".product-image").forEach((r) => {
214
+ if (t.imageAlign && r.setAttribute("align", t.imageAlign), t.imageTdStyle && r.setAttribute("style", t.imageTdStyle), t.imageClasses) {
215
+ const c = `${r.getAttribute("class") || ""} ${t.imageClasses}`.trim();
216
+ r.setAttribute("class", c);
217
+ }
218
+ const i = r.querySelector("img");
219
+ i && t.imageWidth && i.setAttribute("width", t.imageWidth);
220
+ }), (t.nameStyle || t.nameAlign || t.nameTdStyle || t.nameClasses) && s.querySelectorAll(".product-name").forEach((r) => {
221
+ if (t.nameAlign && r.setAttribute("align", t.nameAlign), t.nameTdStyle && r.setAttribute("style", t.nameTdStyle), t.nameClasses) {
222
+ const c = `${r.getAttribute("class") || ""} ${t.nameClasses}`.trim();
223
+ r.setAttribute("class", c);
224
+ }
225
+ const i = r.querySelector("p");
226
+ i && t.nameStyle && i.setAttribute("style", t.nameStyle);
227
+ }), (t.priceStyle || t.priceAlign || t.priceTdStyle || t.priceClasses) && s.querySelectorAll(".product-price").forEach((r) => {
228
+ if (t.priceAlign && r.setAttribute("align", t.priceAlign), t.priceTdStyle && r.setAttribute("style", t.priceTdStyle), t.priceClasses) {
229
+ const c = `${r.getAttribute("class") || ""} ${t.priceClasses}`.trim();
230
+ r.setAttribute("class", c);
231
+ }
232
+ const i = r.querySelector("p");
233
+ i && t.priceStyle && i.setAttribute("style", t.priceStyle);
234
+ }), (t.oldPriceStyle || t.oldPriceAlign || t.oldPriceTdStyle || t.oldPriceClasses) && s.querySelectorAll(".product-old-price").forEach((r) => {
235
+ if (t.oldPriceAlign && r.setAttribute("align", t.oldPriceAlign), t.oldPriceTdStyle && r.setAttribute("style", t.oldPriceTdStyle), t.oldPriceClasses) {
236
+ const c = `${r.getAttribute("class") || ""} ${t.oldPriceClasses}`.trim();
237
+ r.setAttribute("class", c);
238
+ }
239
+ const i = r.querySelector("p");
240
+ i && t.oldPriceStyle && i.setAttribute("style", t.oldPriceStyle);
241
+ }), (t.buttonBorderStyle || t.buttonLinkStyle || t.buttonAlign || t.buttonTdStyle || t.buttonClasses) && s.querySelectorAll(".product-button").forEach((r) => {
242
+ if (t.buttonAlign && r.setAttribute("align", t.buttonAlign), t.buttonTdStyle && r.setAttribute("style", t.buttonTdStyle), t.buttonClasses) {
243
+ const n = `${r.getAttribute("class") || ""} ${t.buttonClasses}`.trim();
244
+ r.setAttribute("class", n);
245
+ }
246
+ const i = r.querySelector(".es-button-border");
247
+ i && t.buttonBorderStyle && i.setAttribute("style", t.buttonBorderStyle);
248
+ const u = r.querySelector("a.es-button");
249
+ u && (t.buttonLinkStyle && u.setAttribute("style", t.buttonLinkStyle), t.buttonText && (u.textContent = t.buttonText));
250
+ });
251
+ const o = s.querySelector("table");
252
+ return (o == null ? void 0 : o.innerHTML) || e;
253
+ }
254
+ /**
255
+ * Builds title block with proper structure
256
+ */
257
+ buildTitleBlock(e) {
258
+ let t = e.text;
259
+ e.isBold && e.isItalic ? t = `<strong path="1,0"><em path="1,0,0">${t}</em></strong>` : e.isBold ? t = `<strong path="1,0">${t}</strong>` : e.isItalic && (t = `<em path="1,0">${t}</em>`);
260
+ const s = e.align ? ` align="${e.align}"` : "", o = e.styles ? ` style="${e.styles}"` : "";
261
+ return `
262
+ <td class="esd-block-text es-p10t es-p10b es-p20l es-p20r"${s}>
263
+ <p path="1"${o}>
264
+ ${t}
265
+ </p>
266
+ </td>
267
+ `;
268
+ }
269
+ /**
270
+ * Removes specified style properties from a style string
271
+ */
272
+ removeStyleProperties(e, t) {
273
+ return e ? t.reduce((o, l) => {
274
+ const r = new RegExp(`${l}\\s*:\\s*[^;]*;?`, "gi");
275
+ return o.replace(r, "");
276
+ }, e).replace(/;\s*;/g, ";").replace(/^;|;$/g, "").trim() : "";
277
+ }
278
+ /**
279
+ * Converts inline display to block display
280
+ */
281
+ convertInlineToBlock(e) {
282
+ if (!e)
283
+ return "";
284
+ let t = e.replace(/display\s*:\s*inline/gi, "display: block");
285
+ return /display\s*:/i.test(t) || (t = t ? `${t}; display: block` : "display: block"), t.replace(/;\s*;/g, ";").replace(/^;|;$/g, "").replace(/"/g, "'").trim();
286
+ }
287
+ }
288
+ function k(A) {
289
+ return new w().migrate(A);
290
+ }
291
+ export {
292
+ k as migrateRecommendation
293
+ };
@@ -1,7 +1,10 @@
1
1
  import { Block as e, BlockCompositionType as t } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
2
- import { getDefaultTemplate as o } from "./template.js";
2
+ import { getDefaultTemplate as o } from "./templates/blockTemplate.js";
3
3
  const n = "recommendation-block";
4
- class c extends e {
4
+ class m extends e {
5
+ constructor() {
6
+ super();
7
+ }
5
8
  getId() {
6
9
  return n;
7
10
  }
@@ -23,5 +26,5 @@ class c extends e {
23
26
  }
24
27
  export {
25
28
  n as BLOCK_ID,
26
- c as RecommendationBlock
29
+ m as RecommendationBlock
27
30
  };
@@ -0,0 +1,103 @@
1
+ var m = Object.defineProperty;
2
+ var y = (n, o, i) => o in n ? m(n, o, { enumerable: !0, configurable: !0, writable: !0, value: i }) : n[o] = i;
3
+ var a = (n, o, i) => y(n, typeof o != "symbol" ? o + "" : o, i);
4
+ import { ModificationDescription as u } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
5
+ import { CommonControl as b } from "../common-control.js";
6
+ const h = "ui-elements-recommendation-card-composition", s = [
7
+ { key: "productImage", label: "Product Image", visible: !0 },
8
+ { key: "productName", label: "Product Name", visible: !0 },
9
+ { key: "productPrice", label: "Product Price", visible: !0 },
10
+ { key: "productOriginalPrice", label: "Product Original Price", visible: !0 },
11
+ { key: "productButton", label: "Product Button", visible: !0 }
12
+ ];
13
+ class g extends b {
14
+ constructor() {
15
+ super(...arguments);
16
+ a(this, "currentComposition", []);
17
+ a(this, "currentVisibility", {});
18
+ }
19
+ getId() {
20
+ return h;
21
+ }
22
+ getTemplate() {
23
+ const i = s.map((e) => ({
24
+ key: e.key,
25
+ label: e.label,
26
+ content: `
27
+ <div style="display: flex; align-items: center; justify-content: space-between;
28
+ padding: 8px; gap: 8px;">
29
+ <span style="flex: 1;">${e.label}</span>
30
+ ${this._GuToggle(`visibility_${e.key}`)}
31
+ </div>
32
+ `
33
+ }));
34
+ return `
35
+ <div class="container">
36
+ ${this._GuLabel({ text: "Card Element Order & Visibility" })}
37
+ ${this._GuOrderable("cardComposition", i)}
38
+ </div>
39
+ `;
40
+ }
41
+ onRender() {
42
+ this._initializeComposition(), this.api.onValueChanged("cardComposition", (i) => {
43
+ this.currentComposition = i, this._applyCompositionToBlock(i);
44
+ }), s.forEach((i) => {
45
+ this.api.onValueChanged(`visibility_${i.key}`, (e) => {
46
+ this.currentVisibility[i.key] = e, this._applyVisibilityToBlock();
47
+ });
48
+ });
49
+ }
50
+ onTemplateNodeUpdated(i) {
51
+ super.onTemplateNodeUpdated(i), this._initializeComposition();
52
+ }
53
+ /**
54
+ * Initialize the composition order and visibility from the block or use defaults
55
+ */
56
+ _initializeComposition() {
57
+ var p;
58
+ const i = (p = this.currentNode) == null ? void 0 : p.querySelector(".ins-recommendation-v3-block-v2");
59
+ let e = null, l = null;
60
+ if (i && "getAttribute" in i && (e = i.getAttribute("data-card-composition"), l = i.getAttribute("data-card-visibility")), e) {
61
+ const t = e.split(",").filter(Boolean), r = s.map((c) => c.key);
62
+ t.every((c) => r.includes(c)) && t.length > 0 ? this.currentComposition = t : this.currentComposition = r;
63
+ } else
64
+ this.currentComposition = s.map((t) => t.key);
65
+ if (l)
66
+ try {
67
+ const t = JSON.parse(l);
68
+ this.currentVisibility = t;
69
+ } catch {
70
+ this.currentVisibility = s.reduce((t, r) => (t[r.key] = r.visible, t), {});
71
+ }
72
+ else
73
+ this.currentVisibility = s.reduce((t, r) => (t[r.key] = r.visible, t), {});
74
+ const d = {
75
+ cardComposition: this.currentComposition
76
+ };
77
+ s.forEach((t) => {
78
+ d[`visibility_${t.key}`] = this.currentVisibility[t.key] ?? !0;
79
+ }), this.api.updateValues(d);
80
+ }
81
+ /**
82
+ * Apply the reordered composition to the block's HTML structure
83
+ */
84
+ _applyCompositionToBlock(i) {
85
+ if (!this.currentNode)
86
+ return;
87
+ const e = this.currentNode.querySelector(".ins-recommendation-v3-block-v2");
88
+ e && this.api.getDocumentModifier().modifyHtml(e).setAttribute("data-card-composition", i.join(",")).apply(new u("Stored card composition order"));
89
+ }
90
+ /**
91
+ * Apply visibility changes to the block's HTML structure
92
+ */
93
+ _applyVisibilityToBlock() {
94
+ if (!this.currentNode)
95
+ return;
96
+ const i = this.currentNode.querySelector(".ins-recommendation-v3-block-v2");
97
+ i && this.api.getDocumentModifier().modifyHtml(i).setAttribute("data-card-visibility", JSON.stringify(this.currentVisibility)).apply(new u("Stored card visibility settings"));
98
+ }
99
+ }
100
+ export {
101
+ h as COMPOSITION_CONTROL_BLOCK_ID,
102
+ g as RecommendationCardCompositionControl
103
+ };
@@ -0,0 +1,5 @@
1
+ var o = /* @__PURE__ */ ((c) => (c.BUTTON = "recommendation-block-button", c.NAME = "recommendation-block-name", c.PRICE = "recommendation-block-price", c.OLD_PRICE = "recommendation-block-old-price", c.IMAGE = "recommendation-block-image", c))(o || {}), r = /* @__PURE__ */ ((c) => (c.BUTTON_ALIGN = "recommendation-block-button-align-control", c.BUTTON_BORDER = "recommendation-block-button-border-control", c.BUTTON_BORDER_RADIUS = "recommendation-block-button-border-radius-control", c.BUTTON_COLOR = "recommendation-block-button-color-control", c.BUTTON_FIT_TO_CONTENT = "recommendation-block-button-fit-to-content-control", c.BUTTON_FONT_FAMILY = "recommendation-block-button-font-family-control", c.BUTTON_MARGINS = "recommendation-block-button-margins-control", c.BUTTON_PADDINGS = "recommendation-block-button-paddings-control", c.BUTTON_TEXT = "recommendation-block-button-text-control", c.BUTTON_TEXT_SIZE = "recommendation-block-button-text-size-control", c.BUTTON_TEXT_STYLE_AND_FONT_COLOR = "recommendation-block-button-text-style-and-font-color-control", c.NAME_ALIGN = "recommendation-block-name-align-control", c.NAME_BACKGROUND = "recommendation-block-name-background-control", c.NAME_COLOR = "recommendation-block-name-color-control", c.NAME_FONT_FAMILY = "recommendation-block-name-font-family-control", c.NAME_PADDINGS = "recommendation-block-name-paddings-control", c.NAME_SIZE = "recommendation-block-name-size-control", c.NAME_STYLE = "recommendation-block-name-style-control", c.PRICE_ALIGN = "recommendation-block-price-align-control", c.PRICE_BACKGROUND = "recommendation-block-price-background-control", c.PRICE_COLOR = "recommendation-block-price-color-control", c.PRICE_FONT_FAMILY = "recommendation-block-price-font-family-control", c.PRICE_PADDINGS = "recommendation-block-price-paddings-control", c.PRICE_SIZE = "recommendation-block-price-size-control", c.PRICE_STYLE = "recommendation-block-price-style-control", c.OLD_PRICE_ALIGN = "recommendation-block-old-price-align-control", c.OLD_PRICE_BACKGROUND = "recommendation-block-old-price-background-control", c.OLD_PRICE_COLOR = "recommendation-block-old-price-color-control", c.OLD_PRICE_FONT_FAMILY = "recommendation-block-old-price-font-family-control", c.OLD_PRICE_PADDINGS = "recommendation-block-old-price-paddings-control", c.OLD_PRICE_SIZE = "recommendation-block-old-price-size-control", c.OLD_PRICE_STYLE = "recommendation-block-old-price-style-control", c.IMAGE_SIZE = "recommendation-block-image-size-control", c.IMAGE_MARGINS = "recommendation-block-image-margins-control", c))(r || {});
2
+ export {
3
+ o as RecommendationBlockId,
4
+ r as RecommendationControlId
5
+ };
@@ -1,11 +1,14 @@
1
1
  var _ = Object.defineProperty;
2
- var R = (o, n, e) => n in o ? _(o, n, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[n] = e;
3
- var r = (o, n, e) => R(o, typeof n != "symbol" ? n + "" : n, e);
4
- import { currencyDecimalCounts as c, currencyOperators as a, currencyLocationMaps as l } from "../../../enums/extensions/recommendationBlock.js";
5
- import { UEAttr as d } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
6
- import { CommonControl as m } from "../common-control.js";
7
- import { useRecommendationExtensionStore as S } from "./store/recommendation.js";
8
- const g = "ui-elements-recommendation-block", t = {
2
+ var R = (s, n, e) => n in s ? _(s, n, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[n] = e;
3
+ var r = (s, n, e) => R(s, typeof n != "symbol" ? n + "" : n, e);
4
+ import { currencyDecimalCounts as l, currencyOperators as c, currencyLocationMaps as h } from "../../../enums/extensions/recommendationBlock.js";
5
+ import { UEAttr as m, ModificationDescription as S } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
6
+ import { CommonControl as g } from "../common-control.js";
7
+ import { useRecommendationExtensionStore as O } from "./store/recommendation.js";
8
+ import { prepareProductRows as p } from "./templates/blockTemplate.js";
9
+ import { DEFAULT_CARD_COMPOSITION as C, getDefaultProducts as E } from "./templates/templateUtils.js";
10
+ import { useDebounceFn as U } from "../../../node_modules/@vueuse/shared/index.js";
11
+ const L = "ui-elements-recommendation-block", t = {
9
12
  ALGORITHM: "strategy",
10
13
  PRODUCT_IDS: "productIds",
11
14
  LOCALE: "language",
@@ -21,18 +24,21 @@ const g = "ui-elements-recommendation-block", t = {
21
24
  SHUFFLE_PRODUCTS: "shuffleProducts",
22
25
  RESPONSIVE: "unresponsive"
23
26
  };
24
- class p extends m {
27
+ class b extends g {
25
28
  constructor() {
26
29
  super(...arguments);
27
- r(this, "store", S());
30
+ r(this, "store", O());
28
31
  r(this, "storeUnsubscription", () => {
29
32
  });
30
33
  r(this, "addFilterListener", () => {
31
34
  });
32
35
  r(this, "addFilterButton", null);
36
+ r(this, "_debouncedRegenerateProductRows", U(() => {
37
+ this._regenerateProductRows();
38
+ }, 500));
33
39
  }
34
40
  getId() {
35
- return g;
41
+ return L;
36
42
  }
37
43
  getTemplate() {
38
44
  return `
@@ -78,22 +84,22 @@ class p extends m {
78
84
  });
79
85
  }
80
86
  _initializeSelectItems() {
81
- const { store: e } = this, s = e.getActivePredictiveAlgorithms, i = e.getLanguages, C = {
82
- [t.ALGORITHM]: s,
87
+ const { store: e } = this, o = e.getActivePredictiveAlgorithms, i = e.getLanguages, a = {
88
+ [t.ALGORITHM]: o,
83
89
  [t.LOCALE]: i,
84
90
  [t.CURRENCY]: e.currencyList,
85
- [t.CURRENCY_LOCATION]: l,
91
+ [t.CURRENCY_LOCATION]: h,
86
92
  [t.CURRENCY_SYMBOL]: e.getCurrencySymbolList,
87
- [t.CURRENCY_THOUSAND_SEPARATOR]: a,
88
- [t.CURRENCY_DECIMAL_SEPARATOR]: a,
89
- [t.CURRENCY_DECIMAL_COUNT]: c,
93
+ [t.CURRENCY_THOUSAND_SEPARATOR]: c,
94
+ [t.CURRENCY_DECIMAL_SEPARATOR]: c,
95
+ [t.CURRENCY_DECIMAL_COUNT]: l,
90
96
  [t.PRODUCT_COUNT]: Number(e.recommendationConfigs.size),
91
97
  [t.PRODUCT_IN_ROW]: e.recommendationConfigs.cardsInRow,
92
98
  [t.SHUFFLE_PRODUCTS]: e.recommendationConfigs.shuffleProducts,
93
99
  [t.RESPONSIVE]: !e.recommendationConfigs.unresponsive
94
100
  };
95
- Object.entries(C).forEach(([u, h]) => {
96
- this.api.setUIEAttribute(u, d.SELECTPICKER.items, h);
101
+ Object.entries(a).forEach(([u, d]) => {
102
+ this.api.setUIEAttribute(u, m.SELECTPICKER.items, d);
97
103
  });
98
104
  }
99
105
  _getAlgorithms() {
@@ -139,7 +145,7 @@ class p extends m {
139
145
  this._GuSelect({
140
146
  name: t.CURRENCY_LOCATION,
141
147
  placeholder: "Select Currency Location",
142
- options: l
148
+ options: h
143
149
  }),
144
150
  this._GuLabel({ text: "Currency Symbol" }),
145
151
  this._GuSelect({
@@ -151,19 +157,19 @@ class p extends m {
151
157
  this._GuSelect({
152
158
  name: t.CURRENCY_THOUSAND_SEPARATOR,
153
159
  placeholder: "Select Thousand Separator",
154
- options: a
160
+ options: c
155
161
  }),
156
162
  this._GuLabel({ text: "Decimal Separator" }),
157
163
  this._GuSelect({
158
164
  name: t.CURRENCY_DECIMAL_SEPARATOR,
159
165
  placeholder: "Select Decimal Separator",
160
- options: a
166
+ options: c
161
167
  }),
162
168
  this._GuLabel({ text: "Decimal Count" }),
163
169
  this._GuSelect({
164
170
  name: t.CURRENCY_DECIMAL_COUNT,
165
171
  placeholder: "Select Decimal Count",
166
- options: c
172
+ options: l
167
173
  })
168
174
  ])}
169
175
  `;
@@ -217,39 +223,62 @@ class p extends m {
217
223
  filterSelectionDrawerStatus: !0
218
224
  });
219
225
  }
220
- _onDataChange(e, s) {
221
- this.currentNode && this.store.$patch({
226
+ _onDataChange(e, o) {
227
+ this.currentNode && (this.store.$patch({
222
228
  recommendationConfigs: {
223
- [e]: s
229
+ [e]: o
224
230
  }
225
- });
231
+ }), this._debouncedRegenerateProductRows());
232
+ }
233
+ /**
234
+ * Get the current card composition from block data attribute or use default
235
+ */
236
+ _getCardComposition() {
237
+ if (!this.currentNode)
238
+ return C;
239
+ const e = this.currentNode.querySelector(".ins-recommendation-v3-block-v2");
240
+ if (!e || !("getAttribute" in e))
241
+ return C;
242
+ const o = e.getAttribute("data-card-composition");
243
+ return o ? o.split(",").filter(Boolean) : C;
244
+ }
245
+ _regenerateProductRows() {
246
+ if (!this.currentNode || !("querySelector" in this.currentNode))
247
+ return;
248
+ const e = this.currentNode.querySelector(".ins-recommendation-product-container");
249
+ if (!e) {
250
+ console.error("Could not find container table for product rows");
251
+ return;
252
+ }
253
+ const o = this.store.recommendationProducts.length > 0 ? this.store.recommendationProducts : E(), { cardsInRow: i } = this.store.recommendationConfigs, a = this._getCardComposition(), u = p(o, i, a);
254
+ this.api.getDocumentModifier().modifyHtml(e).setInnerHtml(u).apply(new S("Updated product"));
226
255
  }
227
- _onCurrencyConfigChange(e, s) {
256
+ _onCurrencyConfigChange(e, o) {
228
257
  this.currentNode && this.store.$patch({
229
258
  recommendationConfigs: {
230
259
  currencySettings: {
231
- [e]: s
260
+ [e]: o
232
261
  }
233
262
  }
234
263
  });
235
264
  }
236
265
  _onCurrencyChange(e) {
237
- const [, s] = e.split(".");
266
+ const [, o] = e.split(".");
238
267
  this.store.$patch({
239
268
  recommendationConfigs: {
240
269
  currencySettings: {
241
- name: s,
242
- value: s
270
+ name: o,
271
+ value: o
243
272
  }
244
273
  }
245
274
  });
246
275
  }
247
276
  _setProductIdsVisibility() {
248
- const { recommendationConfigs: e } = this.store, s = e.strategy === "manualMerchandising";
249
- this.api.setVisibility(t.PRODUCT_IDS, s), this.api.setVisibility(`${t.PRODUCT_IDS}_label`, s);
277
+ const { recommendationConfigs: e } = this.store, o = e.strategy === "manualMerchandising";
278
+ this.api.setVisibility(t.PRODUCT_IDS, o), this.api.setVisibility(`${t.PRODUCT_IDS}_label`, o);
250
279
  }
251
280
  _listenToFormUpdates() {
252
- var s;
281
+ var o;
253
282
  this.api.onValueChanged(t.ALGORITHM, (i) => {
254
283
  this._onDataChange(t.ALGORITHM, i), this._setProductIdsVisibility();
255
284
  }), this.api.onValueChanged(t.PRODUCT_IDS, (i) => this._onDataChange(t.PRODUCT_IDS, i.split(",") || [])), this.api.onValueChanged(t.LOCALE, (i) => this._onDataChange(t.LOCALE, i)), this.api.onValueChanged(t.CURRENCY, (i) => this._onCurrencyChange(i)), [
@@ -259,19 +288,19 @@ class p extends m {
259
288
  t.CURRENCY_DECIMAL_SEPARATOR,
260
289
  t.CURRENCY_DECIMAL_COUNT
261
290
  ].forEach((i) => {
262
- this.api.onValueChanged(i, (C) => this._onCurrencyConfigChange(i, C));
263
- }), this.api.onValueChanged(t.PRODUCT_COUNT, (i) => this._onDataChange(t.PRODUCT_COUNT, i.toString())), this.api.onValueChanged(t.PRODUCT_IN_ROW, (i) => this._onDataChange(t.PRODUCT_IN_ROW, i)), this.api.onValueChanged(t.SHUFFLE_PRODUCTS, (i) => this._onDataChange(t.SHUFFLE_PRODUCTS, i)), this.api.onValueChanged(t.RESPONSIVE, (i) => this._onDataChange(t.RESPONSIVE, i)), this.addFilterListener = this._onFilterSelectClick.bind(this), this.addFilterButton = this.getContainer().querySelector("#guido__btn-add-filter"), (s = this.addFilterButton) == null || s.addEventListener("click", this.addFilterListener);
291
+ this.api.onValueChanged(i, (a) => this._onCurrencyConfigChange(i, a));
292
+ }), this.api.onValueChanged(t.PRODUCT_COUNT, (i) => this._onDataChange(t.PRODUCT_COUNT, i.toString())), this.api.onValueChanged(t.PRODUCT_IN_ROW, (i) => this._onDataChange(t.PRODUCT_IN_ROW, i)), this.api.onValueChanged(t.SHUFFLE_PRODUCTS, (i) => this._onDataChange(t.SHUFFLE_PRODUCTS, i)), this.api.onValueChanged(t.RESPONSIVE, (i) => this._onDataChange(t.RESPONSIVE, i)), this.addFilterListener = this._onFilterSelectClick.bind(this), this.addFilterButton = this.getContainer().querySelector("#guido__btn-add-filter"), (o = this.addFilterButton) == null || o.addEventListener("click", this.addFilterListener);
264
293
  }
265
294
  _listenStateUpdates() {
266
295
  this.storeUnsubscription = this.store.$subscribe((e) => {
267
296
  if ("payload" in e) {
268
- const s = e.payload.recommendationConfigs;
269
- s && (this.api.updateValues(s), this.store.fetchRecommendationProducts());
297
+ const o = e.payload.recommendationConfigs;
298
+ o && (this.api.updateValues(o), this.store.fetchRecommendationProducts());
270
299
  }
271
300
  });
272
301
  }
273
302
  }
274
303
  export {
275
- g as CONTROL_BLOCK_ID,
276
- p as RecommendationBlockControl
304
+ L as CONTROL_BLOCK_ID,
305
+ b as RecommendationBlockControl
277
306
  };