@useinsider/guido 3.2.0-beta.c3bc14c → 3.2.0-beta.caa22bf

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 (91) hide show
  1. package/README.md +92 -0
  2. package/dist/@types/config/schemas.js +150 -94
  3. package/dist/components/Guido.vue.js +1 -1
  4. package/dist/components/Guido.vue2.js +88 -87
  5. package/dist/components/organisms/onboarding/AMPOnboarding.vue2.js +51 -31
  6. package/dist/components/organisms/onboarding/GenericOnboarding.vue.js +1 -1
  7. package/dist/components/organisms/onboarding/GenericOnboarding.vue2.js +23 -22
  8. package/dist/components/organisms/onboarding/ItemsOnboarding.vue.js +1 -1
  9. package/dist/components/organisms/onboarding/ItemsOnboarding.vue2.js +37 -39
  10. package/dist/components/organisms/onboarding/TextBlockOnboarding.vue.js +3 -3
  11. package/dist/components/organisms/onboarding/TextBlockOnboarding.vue2.js +30 -41
  12. package/dist/components/organisms/onboarding/VersionHistoryOnboarding.vue2.js +15 -14
  13. package/dist/composables/useRecommendation.js +46 -26
  14. package/dist/composables/useRibbonOffset.js +21 -0
  15. package/dist/composables/useStripo.js +14 -16
  16. package/dist/composables/validators/useCouponBlockValidator.js +6 -6
  17. package/dist/config/compiler/recommendationCompilerRules.js +27 -27
  18. package/dist/config/migrator/index.js +9 -9
  19. package/dist/config/migrator/radioButtonMigrator.js +64 -44
  20. package/dist/config/migrator/recommendation/compositionMapper.js +98 -0
  21. package/dist/config/migrator/recommendation/extractors.js +27 -0
  22. package/dist/config/migrator/recommendation/htmlBuilder.js +496 -0
  23. package/dist/config/migrator/recommendation/parseLegacyConfig.js +33 -0
  24. package/dist/config/migrator/recommendation/settingsMapper.js +70 -0
  25. package/dist/config/migrator/recommendation/themeMapper.js +93 -0
  26. package/dist/config/migrator/recommendationMigrator.js +74 -290
  27. package/dist/enums/extensions/recommendationBlock.js +2 -1
  28. package/dist/enums/onboarding.js +7 -2
  29. package/dist/extensions/Blocks/RadioButton/template.js +1 -1
  30. package/dist/extensions/Blocks/Recommendation/block.js +35 -32
  31. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +5 -5
  32. package/dist/extensions/Blocks/Recommendation/controls/main/algorithm.js +25 -24
  33. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +228 -181
  34. package/dist/extensions/Blocks/Recommendation/services/configService.js +65 -29
  35. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +130 -90
  36. package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +8 -8
  37. package/dist/extensions/Blocks/Recommendation/templates/utils.js +1 -1
  38. package/dist/extensions/Blocks/Recommendation/utils/legacyStrategyMap.js +21 -0
  39. package/dist/extensions/Blocks/Recommendation/utils/preserveTextStyles.js +13 -22
  40. package/dist/guido.css +1 -1
  41. package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js +258 -235
  42. package/dist/node_modules/valibot/dist/index.js +450 -235
  43. package/dist/package.json.js +1 -1
  44. package/dist/services/templateLibraryApi.js +5 -4
  45. package/dist/src/@types/config/defaults.d.ts +5 -1
  46. package/dist/src/@types/config/index.d.ts +3 -3
  47. package/dist/src/@types/config/schemas.d.ts +213 -0
  48. package/dist/src/@types/config/types.d.ts +9 -1
  49. package/dist/src/components/wrappers/WpModal.vue.d.ts +1 -1
  50. package/dist/src/composables/useConfig.d.ts +56 -0
  51. package/dist/src/composables/useRecommendation.d.ts +10 -1
  52. package/dist/src/composables/useRecommendation.test.d.ts +1 -0
  53. package/dist/src/composables/useRibbonOffset.d.ts +4 -0
  54. package/dist/src/config/migrator/index.d.ts +2 -1
  55. package/dist/src/config/migrator/recommendation/compositionMapper.d.ts +2 -0
  56. package/dist/src/config/migrator/recommendation/compositionMapper.test.d.ts +1 -0
  57. package/dist/src/config/migrator/recommendation/extractors.d.ts +7 -0
  58. package/dist/src/config/migrator/recommendation/extractors.test.d.ts +1 -0
  59. package/dist/src/config/migrator/recommendation/htmlBuilder.d.ts +11 -0
  60. package/dist/src/config/migrator/recommendation/parseLegacyConfig.d.ts +15 -0
  61. package/dist/src/config/migrator/recommendation/parseLegacyConfig.test.d.ts +1 -0
  62. package/dist/src/config/migrator/recommendation/settingsMapper.d.ts +7 -0
  63. package/dist/src/config/migrator/recommendation/settingsMapper.test.d.ts +1 -0
  64. package/dist/src/config/migrator/recommendation/themeMapper.d.ts +5 -0
  65. package/dist/src/config/migrator/recommendation/themeMapper.test.d.ts +1 -0
  66. package/dist/src/config/migrator/recommendation/types.d.ts +205 -0
  67. package/dist/src/config/migrator/recommendationMigrator.d.ts +13 -1
  68. package/dist/src/config/migrator/recommendationMigrator.test.d.ts +1 -0
  69. package/dist/src/enums/onboarding.d.ts +6 -0
  70. package/dist/src/extensions/Blocks/RadioButton/template.d.ts +1 -1
  71. package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.test.d.ts +1 -0
  72. package/dist/src/extensions/Blocks/Recommendation/services/configService.d.ts +10 -0
  73. package/dist/src/extensions/Blocks/Recommendation/services/configService.test.d.ts +1 -0
  74. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +34 -0
  75. package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +1 -1
  76. package/dist/src/extensions/Blocks/Recommendation/utils/legacyStrategyMap.d.ts +21 -0
  77. package/dist/src/extensions/Blocks/Recommendation/utils/legacyStrategyMap.test.d.ts +1 -0
  78. package/dist/src/extensions/Blocks/Recommendation/utils/preserveTextStyles.d.ts +0 -3
  79. package/dist/src/library.d.ts +1 -1
  80. package/dist/src/stores/config.d.ts +504 -0
  81. package/dist/src/stores/onboarding.d.ts +4 -0
  82. package/dist/src/utils/htmlEscape.d.ts +5 -0
  83. package/dist/src/utils/htmlEscape.test.d.ts +1 -0
  84. package/dist/stores/onboarding.js +4 -0
  85. package/dist/utils/htmlEscape.js +13 -0
  86. package/dist/utils/pairProductVariables.js +89 -88
  87. package/dist/utils/templatePreparation.js +72 -32
  88. package/package.json +7 -3
  89. package/dist/enums/displayConditions.js +0 -80
  90. package/dist/extensions/Blocks/Recommendation/templates/grid/migration.js +0 -251
  91. package/dist/src/enums/displayConditions.d.ts +0 -2
@@ -0,0 +1,93 @@
1
+ function r(n, t, o) {
2
+ o != null && o !== "" && n.push(`${t}: ${o}`);
3
+ }
4
+ function $(n) {
5
+ if (!n)
6
+ return null;
7
+ const t = n.top ?? n.all ?? 0, o = n.right ?? n.all ?? 0, i = n.bottom ?? n.all ?? 0, l = n.left ?? n.all ?? 0;
8
+ return t === 0 && o === 0 && i === 0 && l === 0 ? null : `${t}px ${o}px ${i}px ${l}px`;
9
+ }
10
+ function j(n) {
11
+ if (!n)
12
+ return null;
13
+ const { top: t, right: o, bottom: i, left: l } = n;
14
+ return t === void 0 ? null : t === o && t === i && t === l ? t : null;
15
+ }
16
+ function S(n, t, o, i) {
17
+ const l = j(o);
18
+ if (l !== null) {
19
+ r(n, `border-${t}`, i(l));
20
+ return;
21
+ }
22
+ o && (r(n, `border-top-${t}`, o.top !== void 0 ? i(o.top) : null), r(n, `border-right-${t}`, o.right !== void 0 ? i(o.right) : null), r(n, `border-bottom-${t}`, o.bottom !== void 0 ? i(o.bottom) : null), r(n, `border-left-${t}`, o.left !== void 0 ? i(o.left) : null));
23
+ }
24
+ function C(n) {
25
+ if (!n)
26
+ return null;
27
+ if (typeof n.radius == "number")
28
+ return `${n.radius}px`;
29
+ if (typeof n.lt == "number" || typeof n.rt == "number" || typeof n.rb == "number" || typeof n.lb == "number") {
30
+ const t = n.lt ?? 0, o = n.rt ?? 0, i = n.rb ?? 0, l = n.lb ?? 0;
31
+ return `${t}px ${o}px ${i}px ${l}px`;
32
+ }
33
+ return null;
34
+ }
35
+ function I(n) {
36
+ var t, o;
37
+ return ((t = n.textLineSpacing) == null ? void 0 : t.lineSpacing) ?? ((o = n.textLineSpacing) == null ? void 0 : o["font-lineSpacing"]);
38
+ }
39
+ function L(n) {
40
+ var f, u, a, g, d, b, p, s;
41
+ const t = [], o = [], i = (f = n == null ? void 0 : n.textAlign) == null ? void 0 : f.align, l = $((u = n == null ? void 0 : n.textPadding) == null ? void 0 : u.desktop), x = (a = n == null ? void 0 : n.textStyle) == null ? void 0 : a["font-weight"], c = (g = n == null ? void 0 : n.textStyle) == null ? void 0 : g["font-style"];
42
+ return r(t, "background-color", (d = n == null ? void 0 : n.textBackgroundColor) == null ? void 0 : d.color), r(t, "padding", l), r(o, "font-family", (b = n == null ? void 0 : n.textStyle) == null ? void 0 : b["font-family"]), r(o, "font-size", (p = n == null ? void 0 : n.textStyle) == null ? void 0 : p["font-size"]), r(o, "font-weight", x), r(o, "font-style", c), r(o, "color", (s = n == null ? void 0 : n.textColor) == null ? void 0 : s.color), r(o, "line-height", I(n ?? {})), r(o, "text-align", i), {
43
+ tdStyle: t.join("; "),
44
+ pStyle: o.join("; "),
45
+ align: i || void 0,
46
+ wrapBold: x === "bold",
47
+ wrapItalic: c === "italic",
48
+ textTrimming: (n == null ? void 0 : n.textTrimming) === !0
49
+ };
50
+ }
51
+ function N(n) {
52
+ var u, a, g, d, b, p, s, k, w, P, B, z;
53
+ const t = [], o = [], i = [];
54
+ r(t, "padding", $((u = n == null ? void 0 : n.buttonExternalPadding) == null ? void 0 : u.desktop)), r(i, "padding", $((a = n == null ? void 0 : n.buttonInternalPadding) == null ? void 0 : a.desktop)), r(i, "font-family", (g = n == null ? void 0 : n.buttonStyle) == null ? void 0 : g["font-family"]), r(i, "font-size", (d = n == null ? void 0 : n.buttonStyle) == null ? void 0 : d["font-size"]), r(i, "font-weight", (b = n == null ? void 0 : n.buttonStyle) == null ? void 0 : b["font-weight"]), r(i, "font-style", (p = n == null ? void 0 : n.buttonStyle) == null ? void 0 : p["font-style"]);
55
+ const l = (s = n == null ? void 0 : n.buttonColor) == null ? void 0 : s.color, x = (k = n == null ? void 0 : n.textButtonColor) == null ? void 0 : k.color;
56
+ r(o, "background", l), r(i, "background", l), r(i, "color", x);
57
+ const c = n == null ? void 0 : n.buttonBorder;
58
+ S(o, "width", c == null ? void 0 : c.width, (y) => `${y}px`), S(o, "style", c == null ? void 0 : c.style, (y) => y), S(o, "color", c == null ? void 0 : c.color, (y) => y);
59
+ const f = C(n == null ? void 0 : n.buttonBorderRadius);
60
+ return f && (r(o, "border-radius", f), r(i, "border-radius", f)), ((w = n == null ? void 0 : n.buttonStretch) == null ? void 0 : w.stretched) === !1 ? (r(o, "display", "inline-block"), r(i, "display", "inline-block")) : ((P = n == null ? void 0 : n.buttonStretch) == null ? void 0 : P.stretched) === !0 && (r(o, "display", "block"), r(i, "display", "block")), {
61
+ tdStyle: t.join("; "),
62
+ align: ((B = n == null ? void 0 : n.buttonAlign) == null ? void 0 : B.align) || void 0,
63
+ spanStyle: o.join("; "),
64
+ aStyle: i.join("; "),
65
+ text: (z = n == null ? void 0 : n.buttonText) == null ? void 0 : z.text
66
+ };
67
+ }
68
+ function T(n) {
69
+ if (typeof n == "number" && Number.isFinite(n) && n >= 0)
70
+ return Math.trunc(n);
71
+ if (typeof n == "string" && /^\d+$/.test(n.trim())) {
72
+ const t = Number(n.trim());
73
+ if (Number.isFinite(t) && t >= 0)
74
+ return t;
75
+ }
76
+ }
77
+ function A(n) {
78
+ var t, o;
79
+ return {
80
+ width: T((t = n == null ? void 0 : n.imageSize) == null ? void 0 : t.width),
81
+ height: T((o = n == null ? void 0 : n.imageSize) == null ? void 0 : o.height)
82
+ };
83
+ }
84
+ function F(n, t) {
85
+ const o = (n ?? "").trim().replace(/;$/, "").trim(), i = (t ?? "").trim().replace(/;$/, "").trim();
86
+ return o ? i ? `${o}; ${i}` : o : i;
87
+ }
88
+ export {
89
+ F as appendStyle,
90
+ N as mapButtonTheme,
91
+ A as mapImageTheme,
92
+ L as mapTextTheme
93
+ };
@@ -1,297 +1,81 @@
1
- var h = Object.defineProperty;
2
- var T = (d, e, t) => e in d ? h(d, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : d[e] = t;
3
- var A = (d, e, t) => T(d, typeof e != "symbol" ? e + "" : e, t);
4
- import { BLOCK_ID as S } from "../../extensions/Blocks/Recommendation/block.js";
5
- import P, { prepareProductRows as q } from "../../extensions/Blocks/Recommendation/templates/grid/migration.js";
6
- import { useTemplateStore as w } from "../../stores/template.js";
7
- import { getDefaultProducts as $ } from "../../extensions/Blocks/Recommendation/templates/utils.js";
8
- class B {
9
- constructor() {
10
- A(this, "parser");
11
- this.parser = new DOMParser();
12
- }
13
- migrate(e) {
14
- try {
15
- const t = this.parser.parseFromString(e, "text/html"), s = t.querySelectorAll(
16
- 'td.ins-recommendation-v3-block-1:not(.recommendation-block-v2), td.product-block[esd-handler-name*="EmailRecommendationV3"]:not(.recommendation-block-v2)'
17
- );
18
- return w().$patch((i) => {
19
- i.migrations = { ...i.migrations, [S]: s.length };
20
- }), s.length === 0 ? e : (s.forEach((i) => {
21
- const r = i.getAttribute("id"), n = this.extractBgColor(i), u = this.extractTitle(i), c = this.extractProductRows(i), l = P.replace("{-{-TITLE-}-}", u).replace("{-{-PRODUCT_ROWS-}-}", c), a = this.parser.parseFromString(
22
- `<table id="tempDoc"><tbody><tr>${l}</tr></tbody></table>`,
23
- "text/html"
24
- ).querySelector(".recommendation-block-v2");
25
- a && i.parentNode && (r && a.setAttribute("id", r), n && a.setAttribute("bgcolor", n), i.parentNode.replaceChild(a, i));
26
- }), t.documentElement.outerHTML);
27
- } catch (t) {
28
- return console.error("RecommendationMigrator failed:", t), e;
29
- }
30
- }
31
- /**
32
- * Extracts background color from old block
33
- * @param block - The old recommendation block element
34
- * @returns The background color value or empty string
35
- */
36
- extractBgColor(e) {
37
- const t = e.getAttribute("bgcolor");
38
- if (t)
39
- return t.trim();
40
- const s = e.getAttribute("style");
41
- if (s) {
42
- const o = s.match(/background-color\s*:\s*([^;]+)/i);
43
- if (o && o[1])
44
- return o[1].trim();
45
- }
46
- return "";
47
- }
48
- /**
49
- * Extracts background color from product card wrapper element
50
- * @param cardElement - The product card TD element
51
- * @returns The background color value or empty string
52
- */
53
- extractCardBgColor(e) {
54
- const t = e.getAttribute("bgcolor");
55
- if (t)
56
- return t.trim();
57
- const s = e.getAttribute("style");
58
- if (s) {
59
- const o = s.match(/background-color\s*:\s*([^;]+)/i);
60
- if (o && o[1])
61
- return o[1].trim();
62
- }
63
- return "";
64
- }
65
- /**
66
- * Extracts title from old block and converts to new structure
67
- * @param block - The old recommendation block element
68
- * @returns HTML string for the title block
69
- */
70
- extractTitle(e) {
71
- var g, a;
72
- const t = e.querySelector(".ext-recommendation-title");
73
- if (!t)
74
- return this.buildTitleBlock({
75
- text: "You May Also Like!",
76
- isBold: !0,
77
- isItalic: !1,
78
- align: "center",
79
- styles: "font-size: 28px; color: #333333;"
80
- });
81
- const s = t.querySelector("p");
82
- if (!s) {
83
- const p = ((g = t.textContent) == null ? void 0 : g.trim()) || "You May Also Like!", b = t.getAttribute("align") || "center";
84
- return this.buildTitleBlock({
85
- text: p,
86
- isBold: !0,
87
- isItalic: !1,
88
- align: b,
89
- styles: "font-size: 28px; color: #333333;"
90
- });
91
- }
92
- const o = ((a = s.textContent) == null ? void 0 : a.trim()) || "You May Also Like!", i = t.getAttribute("align") || s.getAttribute("align") || "center", r = s.getAttribute("style") || "", n = /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"]), l = this.convertInlineToBlock(c);
93
- return this.buildTitleBlock({
94
- text: o,
95
- isBold: n,
96
- isItalic: u,
97
- align: i,
98
- styles: l
1
+ import { BlockId as f } from "../../enums/block.js";
2
+ import { useTemplateStore as u } from "../../stores/template.js";
3
+ import { mapComposition as b } from "./recommendation/compositionMapper.js";
4
+ import { extractTitleText as y, extractCardBgColor as C } from "./recommendation/extractors.js";
5
+ import { buildBlockHtml as v } from "./recommendation/htmlBuilder.js";
6
+ import { parseRecommendationId as w, parseLegacyConfig as R } from "./recommendation/parseLegacyConfig.js";
7
+ import { mapSettings as S } from "./recommendation/settingsMapper.js";
8
+ const h = 'td[esd-dev-product-config][class*="ins-recommendation-v3-block-"]:not(.recommendation-block-v2), td.product-block[esd-handler-name*="EmailRecommendationV3"][esd-dev-product-config]:not(.recommendation-block-v2)';
9
+ function x(i, t, c) {
10
+ var s;
11
+ const o = w(t);
12
+ if (o === null)
13
+ return console.warn(
14
+ "[RecommendationMigrator] Skipping block — missing/invalid `ins-recommendation-v3-campaign-id`"
15
+ ), !1;
16
+ const r = R(t);
17
+ if (!r)
18
+ return console.warn(
19
+ `[RecommendationMigrator] Aborting block id=${o} \`esd-dev-product-config\` missing or unable to be parsed`
20
+ ), !1;
21
+ const n = c[String(o)];
22
+ if (!n)
23
+ return console.warn(
24
+ `[RecommendationMigrator] Aborting block id=${o} — recommendationConfigs entry missing in Guido Config`
25
+ ), !1;
26
+ const a = S(n, r, o), e = b((s = r.composition) == null ? void 0 : s.variables), d = y(t), l = C(t), g = {
27
+ ...a,
28
+ composition: e.composition,
29
+ visibility: e.visibility,
30
+ textTrimming: e.anyTextTrimming
31
+ }, p = `
32
+ <table>
33
+ <tbody>
34
+ <tr>
35
+ <td class="esd-structure" align="left">
36
+ <table width="100%" cellpadding="0" cellspacing="0">
37
+ <tbody>
38
+ <tr>${v({
39
+ nodeConfig: g,
40
+ composition: e,
41
+ cardBg: l,
42
+ titleText: d,
43
+ legacyId: t.getAttribute("id") ?? void 0,
44
+ legacyBgColor: t.getAttribute("bgcolor") ?? void 0
45
+ })}</tr>
46
+ </tbody>
47
+ </table>
48
+ </td>
49
+ </tr>
50
+ </tbody>
51
+ </table>
52
+ `, m = i.parseFromString(p, "text/html").querySelector("td.esd-structure");
53
+ return !m || !t.parentNode ? (console.warn(
54
+ `[RecommendationMigrator] Aborting block id=${o} — failed to construct new HTML element`
55
+ ), !1) : (t.parentNode.replaceChild(m, t), !0);
56
+ }
57
+ function I(i, t = {}) {
58
+ const c = new DOMParser(), o = c.parseFromString(i, "text/html"), r = Array.from(o.querySelectorAll(h));
59
+ try {
60
+ u().$patch((e) => {
61
+ e.migrations = {
62
+ ...e.migrations,
63
+ [f.Recommendation]: r.length
64
+ };
99
65
  });
66
+ } catch {
100
67
  }
101
- /**
102
- * Extracts product configuration from old block and generates new product rows
103
- * @param block - The old recommendation block element
104
- * @returns HTML string for product rows
105
- */
106
- extractProductRows(e) {
107
- const t = this.extractProductConfig(e);
108
- if (!t)
109
- return console.warn("[RecommendationMigrator] No product config found, using defaults"), this.generateProductRows(6, 3, {});
110
- const { totalCount: s, productsPerRow: o } = t, i = this.extractProductStyles(e);
111
- return this.generateProductRows(s, o, i);
112
- }
113
- /**
114
- * Extracts Stripo padding/margin utility classes from a class string
115
- * @param classString - Space-separated class string from element
116
- * @returns Filtered Stripo utility classes as a space-separated string
117
- */
118
- extractStripoClasses(e) {
119
- return e ? e.split(/\s+/).filter((o) => /^es-(p\d+|m[-\d])/.test(o)).join(" ") : "";
120
- }
121
- /**
122
- * Extracts product configuration from old block
123
- * @param block - The old recommendation block element
124
- * @returns Object with totalCount and productsPerRow, or null if parsing fails
125
- */
126
- extractProductConfig(e) {
127
- const t = e.getAttribute("esd-dev-product-config");
128
- if (!t)
129
- return null;
68
+ if (r.length === 0)
69
+ return i;
70
+ let n = 0;
71
+ return r.forEach((a) => {
130
72
  try {
131
- const s = this.unescapeJsonString(t), o = JSON.parse(s);
132
- return {
133
- totalCount: o.totalCount ?? 6,
134
- productsPerRow: o.rowCount ?? 3
135
- };
136
- } catch (s) {
137
- return console.error("[RecommendationMigrator] Failed to parse product config:", s), console.error(
138
- "[RecommendationMigrator] Error details:",
139
- s instanceof Error ? s.message : String(s)
140
- ), null;
141
- }
142
- }
143
- /**
144
- * Decodes HTML entities from JSON string
145
- * @param text - The encoded string
146
- * @returns Decoded string
147
- */
148
- unescapeJsonString(e) {
149
- return e.replace(/&amp;/g, "&").replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&#x27;/g, "'").replace(/&quot;/g, '"').replace(/\\\\"/g, "'");
150
- }
151
- /**
152
- * Generates product rows using prepareProductRows with default product data
153
- * @param totalCount - Total number of products to display
154
- * @param productsPerRow - Number of products in each row
155
- * @param extractedStyles - Styles extracted from old product elements
156
- * @returns HTML string for product rows with applied styles
157
- */
158
- generateProductRows(e, t, s) {
159
- const o = $(), i = [];
160
- for (let n = 0; n < e; n++) {
161
- const u = o[n % o.length];
162
- i.push({ ...u });
163
- }
164
- let r = q(i, t);
165
- return r = this.applyExtractedStyles(r, s), r;
166
- }
167
- /**
168
- * Extracts styles from old product elements
169
- * @param block - The old recommendation block element
170
- * @returns Object with extracted styles for each element type
171
- */
172
- extractProductStyles(e) {
173
- const t = {}, s = e.querySelector(".product-card");
174
- if (!s)
175
- return console.warn("[RecommendationMigrator] No product card found, using default styles"), t;
176
- const o = this.extractCardBgColor(s);
177
- o && (t.cardBgColor = o);
178
- const i = s.querySelector(".ext-product-image");
179
- if (i) {
180
- const l = i.querySelector("img"), g = l == null ? void 0 : l.getAttribute("width"), a = i.getAttribute("style") || "", p = i.getAttribute("align") || "center", b = i.getAttribute("class") || "", m = this.extractStripoClasses(b);
181
- t.imageWidth = g || "120", t.imageAlign = p, t.imageTdStyle = a, t.imageClasses = m;
182
- }
183
- const r = s.querySelector(".ext-product-name");
184
- if (r) {
185
- const l = r.querySelector("p"), g = (l == null ? void 0 : l.getAttribute("style")) || "", a = r.getAttribute("align") || "center", p = r.getAttribute("style") || "", b = r.getAttribute("class") || "", m = this.extractStripoClasses(b);
186
- t.nameStyle = g, t.nameAlign = a, t.nameTdStyle = p, t.nameClasses = m;
187
- }
188
- const n = s.querySelector(".ext-product-price");
189
- if (n) {
190
- const l = n.querySelector("p"), g = (l == null ? void 0 : l.getAttribute("style")) || "", a = n.getAttribute("align") || "center", p = n.getAttribute("style") || "", b = n.getAttribute("class") || "", m = this.extractStripoClasses(b);
191
- t.priceStyle = g, t.priceAlign = a, t.priceTdStyle = p, t.priceClasses = m;
192
- }
193
- const u = s.querySelector(".ext-product-original-price");
194
- if (u) {
195
- const l = u.querySelector("p"), g = (l == null ? void 0 : l.getAttribute("style")) || "", a = u.getAttribute("align") || "center", p = u.getAttribute("style") || "", b = u.getAttribute("class") || "", m = this.extractStripoClasses(b);
196
- t.oldPriceStyle = g, t.oldPriceAlign = a, t.oldPriceTdStyle = p, t.oldPriceClasses = m;
197
- }
198
- const c = s.querySelector(".ext-product-button");
199
- if (c) {
200
- const l = c.querySelector(".es-button-border"), g = c.querySelector("a.es-button"), a = (l == null ? void 0 : l.getAttribute("style")) || "", p = (g == null ? void 0 : g.getAttribute("style")) || "", b = c.getAttribute("align") || "center", m = c.getAttribute("style") || "", f = c.getAttribute("class") || "", C = this.extractStripoClasses(f), y = ((c == null ? void 0 : c.textContent) || "").trim();
201
- t.buttonBorderStyle = a, t.buttonLinkStyle = p, t.buttonAlign = b, t.buttonTdStyle = m, t.buttonClasses = C, t.buttonText = y;
73
+ x(c, a, t) && (n += 1);
74
+ } catch (e) {
75
+ console.error("[RecommendationMigrator] Unexpected error migrating block:", e);
202
76
  }
203
- return t;
204
- }
205
- /**
206
- * Applies extracted styles to the generated HTML
207
- * @param html - The generated HTML from prepareProductRows
208
- * @param extractedStyles - Styles extracted from old product elements
209
- * @returns HTML with applied styles
210
- */
211
- applyExtractedStyles(e, t) {
212
- if (!t || Object.keys(t).length === 0)
213
- return e;
214
- const s = this.parser.parseFromString(`<table>${e}</table>`, "text/html");
215
- t.cardBgColor && s.querySelectorAll(".product-attribute-cell").forEach((r) => {
216
- r.setAttribute("bgcolor", t.cardBgColor);
217
- }), (t.imageWidth || t.imageAlign || t.imageTdStyle || t.imageClasses) && s.querySelectorAll(".product-image").forEach((r) => {
218
- if (t.imageAlign && r.setAttribute("align", t.imageAlign), t.imageTdStyle && r.setAttribute("style", t.imageTdStyle), t.imageClasses) {
219
- const c = `${r.getAttribute("class") || ""} ${t.imageClasses}`.trim();
220
- r.setAttribute("class", c);
221
- }
222
- const n = r.querySelector("img");
223
- n && t.imageWidth && n.setAttribute("width", t.imageWidth);
224
- }), (t.nameStyle || t.nameAlign || t.nameTdStyle || t.nameClasses) && s.querySelectorAll(".product-name").forEach((r) => {
225
- if (t.nameAlign && r.setAttribute("align", t.nameAlign), t.nameTdStyle && r.setAttribute("style", t.nameTdStyle), t.nameClasses) {
226
- const c = `${r.getAttribute("class") || ""} ${t.nameClasses}`.trim();
227
- r.setAttribute("class", c);
228
- }
229
- const n = r.querySelector("p");
230
- n && t.nameStyle && n.setAttribute("style", t.nameStyle);
231
- }), (t.priceStyle || t.priceAlign || t.priceTdStyle || t.priceClasses) && s.querySelectorAll(".product-price").forEach((r) => {
232
- if (t.priceAlign && r.setAttribute("align", t.priceAlign), t.priceTdStyle && r.setAttribute("style", t.priceTdStyle), t.priceClasses) {
233
- const c = `${r.getAttribute("class") || ""} ${t.priceClasses}`.trim();
234
- r.setAttribute("class", c);
235
- }
236
- const n = r.querySelector("p");
237
- n && t.priceStyle && n.setAttribute("style", t.priceStyle);
238
- }), (t.oldPriceStyle || t.oldPriceAlign || t.oldPriceTdStyle || t.oldPriceClasses) && s.querySelectorAll(".product-old-price").forEach((r) => {
239
- if (t.oldPriceAlign && r.setAttribute("align", t.oldPriceAlign), t.oldPriceTdStyle && r.setAttribute("style", t.oldPriceTdStyle), t.oldPriceClasses) {
240
- const c = `${r.getAttribute("class") || ""} ${t.oldPriceClasses}`.trim();
241
- r.setAttribute("class", c);
242
- }
243
- const n = r.querySelector("p");
244
- n && t.oldPriceStyle && n.setAttribute("style", t.oldPriceStyle);
245
- }), (t.buttonBorderStyle || t.buttonLinkStyle || t.buttonAlign || t.buttonTdStyle || t.buttonClasses) && s.querySelectorAll(".product-button").forEach((r) => {
246
- if (t.buttonAlign && r.setAttribute("align", t.buttonAlign), t.buttonTdStyle && r.setAttribute("style", t.buttonTdStyle), t.buttonClasses) {
247
- const l = `${r.getAttribute("class") || ""} ${t.buttonClasses}`.trim();
248
- r.setAttribute("class", l);
249
- }
250
- const n = r.querySelector(".es-button-border");
251
- n && t.buttonBorderStyle && n.setAttribute("style", t.buttonBorderStyle);
252
- const u = r.querySelector("a.es-button");
253
- u && (t.buttonLinkStyle && u.setAttribute("style", t.buttonLinkStyle), t.buttonText && (u.textContent = t.buttonText));
254
- });
255
- const o = s.querySelector("table");
256
- return (o == null ? void 0 : o.innerHTML) || e;
257
- }
258
- /**
259
- * Builds title block with proper structure
260
- */
261
- buildTitleBlock(e) {
262
- let t = e.text;
263
- 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>`);
264
- const s = e.align ? ` align="${e.align}"` : "", o = e.styles ? ` style="${e.styles}"` : "";
265
- return `
266
- <td class="esd-block-text es-p10t es-p10b es-p20l es-p20r"${s}>
267
- <p path="1"${o}>
268
- ${t}
269
- </p>
270
- </td>
271
- `;
272
- }
273
- /**
274
- * Removes specified style properties from a style string
275
- */
276
- removeStyleProperties(e, t) {
277
- return e ? t.reduce((o, i) => {
278
- const r = new RegExp(`${i}\\s*:\\s*[^;]*;?`, "gi");
279
- return o.replace(r, "");
280
- }, e).replace(/;\s*;/g, ";").replace(/^;|;$/g, "").trim() : "";
281
- }
282
- /**
283
- * Converts inline display to block display
284
- */
285
- convertInlineToBlock(e) {
286
- if (!e)
287
- return "";
288
- let t = e.replace(/display\s*:\s*inline/gi, "display: block");
289
- return /display\s*:/i.test(t) || (t = t ? `${t}; display: block` : "display: block"), t.replace(/;\s*;/g, ";").replace(/^;|;$/g, "").replace(/"/g, "'").trim();
290
- }
291
- }
292
- function v(d) {
293
- return new B().migrate(d);
77
+ }), n > 0 && console.info(`[RecommendationMigrator] Migrated ${n} legacy Recommendation block(s)`), o.documentElement.outerHTML;
294
78
  }
295
79
  export {
296
- v as migrateRecommendation
80
+ I as migrateRecommendation
297
81
  };
@@ -18,7 +18,8 @@ const s = {
18
18
  { text: "after the amount", value: "1" }
19
19
  ], d = [
20
20
  { text: "dot(.)", value: "." },
21
- { text: "comma(,)", value: "," }
21
+ { text: "comma(,)", value: "," },
22
+ { text: "space( )", value: " " }
22
23
  ], p = [
23
24
  { text: "0", value: "0" },
24
25
  { text: "1", value: "1" },
@@ -2,10 +2,15 @@ const e = [
2
2
  ".service-element.stacked-panel-item.ng-tns-c1014751574-3.level-bottom-0.ng-star-inserted",
3
3
  ".service-element.stacked-panel-item.ng-tns-c1014751574-3.level-bottom-1.ng-star-inserted",
4
4
  ".service-element.stacked-panel-item.ng-tns-c1014751574-3.level-bottom-2.ng-star-inserted"
5
- ], t = "ui-editor", n = 'button[role="tab"][aria-label="Card Composition"]', s = 'button[role="tab"][aria-label="Settings"]', o = ".in-ribbons-wrapper";
5
+ ], t = "ui-editor", n = 'button[role="tab"][aria-label="Card Composition"]', s = 'button[role="tab"][aria-label="Settings"]', E = ".in-ribbons-wrapper", o = ".guido__amp-toggle-html", a = ".in-segments-wrapper", O = '[data-testid="guido-header"]', _ = 158, i = 10;
6
6
  export {
7
+ o as AMP_TOGGLE_BUTTON_SELECTOR,
8
+ a as AMP_TOGGLE_WRAPPER_SELECTOR,
7
9
  n as CARD_COMPOSITION_TAB_SELECTOR,
8
- o as RIBBON_SELECTOR,
10
+ O as HEADER_SELECTOR,
11
+ _ as POPOVER_LEFT_OFFSET,
12
+ i as POPOVER_TOP_GAP,
13
+ E as RIBBON_SELECTOR,
9
14
  e as SERVICE_HOVER_SELECTORS,
10
15
  s as SETTINGS_TAB_SELECTOR,
11
16
  t as UI_EDITOR_SELECTOR
@@ -119,7 +119,7 @@ const e = {
119
119
  id="radioYes"
120
120
  name="unsubscribe"
121
121
  data-cke-editable="1"
122
- style="margin: 0px; vertical-align: middle;>
122
+ style="margin: 0px; vertical-align: middle;">
123
123
  </td>
124
124
  {-{-YES-}-}
125
125
  </tr>
@@ -1,15 +1,15 @@
1
- var k = Object.defineProperty;
2
- var I = (r, n, t) => n in r ? k(r, n, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[n] = t;
3
- var u = (r, n, t) => I(r, typeof n != "symbol" ? n + "" : n, t);
4
- import { BlockId as B } from "../../../enums/block.js";
5
- import { getMigrationBannerHtml as _ } from "../../../utils/migrationBannerHtml.js";
1
+ var I = Object.defineProperty;
2
+ var k = (r, n, t) => n in r ? I(r, n, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[n] = t;
3
+ var u = (r, n, t) => k(r, typeof n != "symbol" ? n + "" : n, t);
4
+ import { BlockId as _ } from "../../../enums/block.js";
5
+ import { getMigrationBannerHtml as B } from "../../../utils/migrationBannerHtml.js";
6
6
  import { Block as b, BlockCompositionType as R, ModificationDescription as y } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
7
7
  import { regenerateMobileProductRows as C } from "./controls/main/utils.js";
8
8
  import { ensureMobileCssRulesExist as g, setMobileLayoutOptOut as d, hasMobileLayoutOptOut as A } from "./controls/mobileLayout/cssRules.js";
9
9
  import { RecommendationConfigService as c } from "./services/configService.js";
10
10
  import { useRecommendationExtensionStore as p } from "./store/recommendation.js";
11
11
  import { getDefaultTemplate as E } from "./templates/grid/template.js";
12
- const f = B.Recommendation, a = "recommendation-block-v2", l = "recommendation-id";
12
+ const f = _.Recommendation, l = "recommendation-block-v2", m = "recommendation-id";
13
13
  let h = !1;
14
14
  class q extends b {
15
15
  constructor() {
@@ -38,7 +38,7 @@ class q extends b {
38
38
  );
39
39
  }
40
40
  getSettingsPanelTitleHtml() {
41
- return _(
41
+ return B(
42
42
  f,
43
43
  this.api.translate("Recommendation Block"),
44
44
  this.api.translate("This block is switched from the Old Version to the New Version. We recommend you check the Recommendation block and test your message to ensure it works properly.")
@@ -66,15 +66,18 @@ class q extends b {
66
66
  * @param node - The newly created block node
67
67
  */
68
68
  onCreated(t) {
69
- const e = this._pendingBlockId ?? this._generateNextId();
70
- this._pendingBlockId = null, this._assignRecommendationId(t, e);
71
- const o = c.initializeConfig(this.api, t, { recommendationId: e }), i = p();
72
- i.setCurrentBlock(e), g(this.api);
73
- const s = this._getBlockElement(t);
74
- s && (d(this.api, s, !0), C({
69
+ const e = this._getRecommendationId(t);
70
+ if (e !== null && e > 0)
71
+ return;
72
+ const i = this._pendingBlockId ?? this._generateNextId();
73
+ this._pendingBlockId = null, this._assignRecommendationId(t, i);
74
+ const o = c.initializeConfig(this.api, t, { recommendationId: i }), s = p();
75
+ s.setCurrentBlock(i), g(this.api);
76
+ const a = this._getBlockElement(t);
77
+ a && (d(this.api, a, !0), C({
75
78
  currentNode: t,
76
79
  documentModifier: this.api.getDocumentModifier()
77
- })), i.patchCurrentBlockConfig({ language: o.language }, { triggerRefetch: !1 });
80
+ })), s.patchCurrentBlockConfig({ language: o.language }, { triggerRefetch: !1 });
78
81
  }
79
82
  /**
80
83
  * Called when the document changes or template is loaded
@@ -97,10 +100,10 @@ class q extends b {
97
100
  c.needsMigration(t) && this._migrateFromLegacy(t);
98
101
  try {
99
102
  h || (g(this.api), h = !0);
100
- const e = c.getConfig(t), o = this._getBlockElement(t);
101
- if (o) {
102
- const i = !e.mobileLayoutEnabled;
103
- A(o) !== i && d(this.api, o, i);
103
+ const e = c.getConfig(t), i = this._getBlockElement(t);
104
+ if (i) {
105
+ const o = !e.mobileLayoutEnabled;
106
+ A(i) !== o && d(this.api, i, o);
104
107
  }
105
108
  } catch {
106
109
  }
@@ -124,10 +127,10 @@ class q extends b {
124
127
  let t = 0;
125
128
  try {
126
129
  const e = this.api.getDocumentRoot();
127
- e && "querySelectorAll" in e && e.querySelectorAll(`.${a}`).forEach((i) => {
128
- if ("getAttribute" in i) {
129
- const s = i.getAttribute(l), m = s ? parseInt(s) : 0;
130
- m > t && (t = m);
130
+ e && "querySelectorAll" in e && e.querySelectorAll(`.${l}`).forEach((o) => {
131
+ if ("getAttribute" in o) {
132
+ const s = o.getAttribute(m), a = s ? parseInt(s) : 0;
133
+ a > t && (t = a);
131
134
  }
132
135
  });
133
136
  } catch {
@@ -141,11 +144,11 @@ class q extends b {
141
144
  * added classes via setAttribute.
142
145
  */
143
146
  _assignRecommendationId(t, e) {
144
- const o = this._getBlockElement(t);
145
- if (!o)
147
+ const i = this._getBlockElement(t);
148
+ if (!i)
146
149
  return;
147
- const i = this.api.getDocumentModifier();
148
- i.modifyHtml(o).setAttribute(l, e.toString()), i.apply(new y(`Assign recommendation ID ${e}`));
150
+ const o = this.api.getDocumentModifier();
151
+ o.modifyHtml(i).setAttribute(m, e.toString()), o.apply(new y(`Assign recommendation ID ${e}`));
149
152
  }
150
153
  /**
151
154
  * Gets the recommendation-id from a block node
@@ -154,11 +157,11 @@ class q extends b {
154
157
  const e = this._getBlockElement(t);
155
158
  if (!e || !("getAttribute" in e))
156
159
  return null;
157
- const o = e.getAttribute(l);
158
- if (!o)
160
+ const i = e.getAttribute(m);
161
+ if (!i)
159
162
  return null;
160
- const i = parseInt(o);
161
- return Number.isNaN(i) ? null : i;
163
+ const o = parseInt(i);
164
+ return Number.isNaN(o) ? null : o;
162
165
  }
163
166
  /**
164
167
  * Gets the block element (the element with BLOCK_CLASS)
@@ -166,10 +169,10 @@ class q extends b {
166
169
  _getBlockElement(t) {
167
170
  if ("getAttribute" in t) {
168
171
  const e = t.getAttribute("class");
169
- if (e && e.includes(a))
172
+ if (e && e.includes(l))
170
173
  return t;
171
174
  }
172
- return "querySelector" in t ? t.querySelector(`.${a}`) ?? null : null;
175
+ return "querySelector" in t ? t.querySelector(`.${l}`) ?? null : null;
173
176
  }
174
177
  /**
175
178
  * Migrate configuration from legacy format