@useinsider/guido 3.10.0-beta.37c2e49 → 3.10.0-beta.511e745
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.
- package/dist/config/compiler/recommendationCompilerRules.js +55 -38
- package/dist/config/compiler/utils/recommendationCompilerUtils.js +88 -77
- package/dist/config/i18n/en/labels.json.js +4 -1
- package/dist/enums/unsubscribe.js +41 -36
- package/dist/extensions/Blocks/Checkbox/block.js +5 -3
- package/dist/extensions/Blocks/Checkbox/control.js +42 -28
- package/dist/extensions/Blocks/RadioButton/block.js +9 -7
- package/dist/extensions/Blocks/RadioButton/control.js +64 -50
- package/dist/extensions/Blocks/Recommendation/utils/legacyStrategyMap.js +2 -0
- package/dist/src/enums/unsubscribe.d.ts +2 -0
- package/dist/src/extensions/Blocks/Recommendation/utils/legacyStrategyMap.d.ts +1 -0
- package/dist/static/styles/components/dropdown-menu.css.js +12 -0
- package/dist/utils/templatePreparation.js +20 -16
- package/package.json +1 -1
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { useRecommendation as N } from "../../composables/useRecommendation.js";
|
|
2
|
-
import { DUMMY_IMAGE_MAPPINGS as
|
|
2
|
+
import { DUMMY_IMAGE_MAPPINGS as h, REGEX as d, VerticalOrientation as $, CSS as n, ATTRIBUTES as p, CONDITIONS as A, HTML as g } from "../../enums/recommendation.js";
|
|
3
3
|
import { prepareRecommendationBlocks as O } from "./utils/recommendationCompilerUtils.js";
|
|
4
|
-
const
|
|
4
|
+
const H = [
|
|
5
5
|
{
|
|
6
6
|
id: "replace-images-with-variable-names",
|
|
7
7
|
description: "Replacing dummy images with variable names in recommendation module",
|
|
8
8
|
type: "custom",
|
|
9
|
-
processor: (
|
|
10
|
-
let e =
|
|
11
|
-
return Object.entries(
|
|
12
|
-
Object.entries(r).forEach(([
|
|
13
|
-
e = e.replaceAll(i, `{{${
|
|
9
|
+
processor: (t) => {
|
|
10
|
+
let e = t;
|
|
11
|
+
return Object.entries(h).forEach(([, r]) => {
|
|
12
|
+
Object.entries(r).forEach(([o, i]) => {
|
|
13
|
+
e = e.replaceAll(i, `{{${o}}}`);
|
|
14
14
|
});
|
|
15
15
|
}), e;
|
|
16
16
|
},
|
|
@@ -41,10 +41,10 @@ const U = [
|
|
|
41
41
|
id: "add-recommendation-unresponsive-css",
|
|
42
42
|
description: "Adding recommendation unresponsive css",
|
|
43
43
|
type: "custom",
|
|
44
|
-
processor: (
|
|
44
|
+
processor: (t) => {
|
|
45
45
|
const { calculateCardWidth: e, getRecommendationCampaignData: r } = N();
|
|
46
|
-
let
|
|
47
|
-
const i =
|
|
46
|
+
let o = t;
|
|
47
|
+
const i = o.match(d.ID);
|
|
48
48
|
if (i) {
|
|
49
49
|
const s = [];
|
|
50
50
|
if (i.forEach((c) => {
|
|
@@ -52,10 +52,10 @@ const U = [
|
|
|
52
52
|
u.textTrimming && u.orientation === $ && s.push(e(u));
|
|
53
53
|
}), s.length) {
|
|
54
54
|
const c = `width:${Math.min(...s)}px!important;`;
|
|
55
|
-
|
|
55
|
+
o = o.replace(n.REGULAR_NAME_HEIGHT, `${n.TRIMMED_NAME_HEIGHT} ${c} ${n.ELLIPSIS}`).replace(n.REGULAR_NAME_CONTAINER_HEIGHT, n.TRIMMED_NAME_CONTAINER_CSS).replace(n.RESPONSIVE_NAME_SIZE, `${n.RESPONSIVE_NAME_HEIGHT} ${c} ${n.ELLIPSIS}`).replace(n.RESPONSIVE_NAME_CONTAINER_HEIGHT, n.TRIMMED_RESPONSIVE_NAME_CONTAINER_CSS);
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
-
return
|
|
58
|
+
return o;
|
|
59
59
|
},
|
|
60
60
|
priority: 52
|
|
61
61
|
},
|
|
@@ -63,16 +63,16 @@ const U = [
|
|
|
63
63
|
id: "prepare-recommendations",
|
|
64
64
|
description: "Replacing product data with template variables in recommendation blocks",
|
|
65
65
|
type: "custom",
|
|
66
|
-
processor: (
|
|
66
|
+
processor: (t) => O(t),
|
|
67
67
|
priority: 48
|
|
68
68
|
},
|
|
69
69
|
{
|
|
70
70
|
id: "add-discount-conditions",
|
|
71
71
|
description: "Adding discount conditions to the recommendation block",
|
|
72
72
|
type: "custom",
|
|
73
|
-
processor: (
|
|
74
|
-
let e =
|
|
75
|
-
const r = e.match(d.ATTRIBUTE_PARAGRAPH), { getRecommendationCampaignData:
|
|
73
|
+
processor: (t) => {
|
|
74
|
+
let e = t;
|
|
75
|
+
const r = e.match(d.ATTRIBUTE_PARAGRAPH), { getRecommendationCampaignData: o } = N();
|
|
76
76
|
return r !== null && r.forEach((i) => {
|
|
77
77
|
const s = i.match(d.CUSTOM_FIELD);
|
|
78
78
|
if (!s)
|
|
@@ -80,17 +80,17 @@ const U = [
|
|
|
80
80
|
const [c] = s, m = c.match(d.CUSTOM_FIELD_INDEXES_PART), E = c.match(d.CUSTOM_FIELD_NAME_PART), u = i.match(d.ATTRIBUTE_PARAGRAPH_START_TAG);
|
|
81
81
|
if (!m || !E || !u)
|
|
82
82
|
return;
|
|
83
|
-
const [
|
|
83
|
+
const [T] = m, [I] = E, [_] = u, b = I.substring(1, I.length - 2), S = _.match(d.COMPOSITION) !== null;
|
|
84
84
|
let a = c;
|
|
85
85
|
if (S) {
|
|
86
|
-
const
|
|
86
|
+
const y = T.substring(2, T.length - 3), l = o(y);
|
|
87
87
|
b === p.OMNIBUS_PRICE && (l.priceBeforeTextValue && (a = `${l.priceBeforeTextValue}${a}`), l.priceAfterTextValue && (a = `${a}${l.priceAfterTextValue}`)), b === p.OMNIBUS_DISCOUNT && (l.discountBeforeTextValue && (a = `${l.discountBeforeTextValue}${a}`), l.discountAfterTextValue && (a = `${a}${l.discountAfterTextValue}`));
|
|
88
88
|
}
|
|
89
|
-
const
|
|
90
|
-
let
|
|
91
|
-
b in
|
|
92
|
-
const
|
|
93
|
-
e = e.replace(i,
|
|
89
|
+
const R = T.substring(2);
|
|
90
|
+
let f = "";
|
|
91
|
+
b in A.IF && (f = A.IF[b].replaceAll(`{${p.DISCOUNT}}`, `${R}${p.DISCOUNT}`).replaceAll(`{${p.OMNIBUS_DISCOUNT}}`, `${R}${p.OMNIBUS_DISCOUNT}`).replaceAll(`{${p.OMNIBUS_PRICE}}`, `${R}${p.OMNIBUS_PRICE}`));
|
|
92
|
+
const M = `${_}${a}${g.PARAGRAPH_END_TAG}`, C = `${f}${S ? M : i}${A.ELSE}${_}${g.PARAGRAPH_END_TAG}${A.END_IF}`;
|
|
93
|
+
e = e.replace(i, C);
|
|
94
94
|
}), e;
|
|
95
95
|
},
|
|
96
96
|
priority: 53
|
|
@@ -110,11 +110,11 @@ const U = [
|
|
|
110
110
|
type: "custom",
|
|
111
111
|
// Scoped to REC_START/REC_END markers so it cannot strip `product-attr`
|
|
112
112
|
// from Items block elements, which the items compiler rule depends on.
|
|
113
|
-
processor: (
|
|
113
|
+
processor: (t) => {
|
|
114
114
|
const e = /\s+(?:esd-extension-block-id|data-attribute-type|data-visibility|data-text-before|data-text-after|data-same-price|product-attr|composition)="[^"]*"/g;
|
|
115
|
-
return
|
|
115
|
+
return t.replace(
|
|
116
116
|
/<!--REC_START-->([\s\S]*?)<!--REC_END-->/g,
|
|
117
|
-
(r,
|
|
117
|
+
(r, o) => `<!--REC_START-->${o.replace(e, "")}<!--REC_END-->`
|
|
118
118
|
);
|
|
119
119
|
},
|
|
120
120
|
priority: 55
|
|
@@ -123,8 +123,8 @@ const U = [
|
|
|
123
123
|
id: "strip-unused-recommendation-classes",
|
|
124
124
|
description: "Remove CSS classes not referenced by any style rule from recommendation elements",
|
|
125
125
|
type: "custom",
|
|
126
|
-
processor: (
|
|
127
|
-
let e =
|
|
126
|
+
processor: (t) => {
|
|
127
|
+
let e = t.replace(
|
|
128
128
|
/ class="(?:product-card-segment|attribute-cell|recommendation-attribute-row|product-image|product-name|product-price|product-old-price|product-omnibus-price|product-omnibus-discount|product-button|recommendation-product-row|product-card-wrapper)"/g,
|
|
129
129
|
""
|
|
130
130
|
);
|
|
@@ -136,8 +136,8 @@ const U = [
|
|
|
136
136
|
id: "remove-empty-mobile-layout-artifacts",
|
|
137
137
|
description: "Remove empty mobile container rows and unused mobile layout CSS",
|
|
138
138
|
type: "custom",
|
|
139
|
-
processor: (
|
|
140
|
-
let e =
|
|
139
|
+
processor: (t) => {
|
|
140
|
+
let e = t;
|
|
141
141
|
return e = e.replace(
|
|
142
142
|
/<tr[^>]*class="ins-recommendation-mobile-row"[^>]*><\/tr>/g,
|
|
143
143
|
""
|
|
@@ -146,8 +146,8 @@ const U = [
|
|
|
146
146
|
""
|
|
147
147
|
), e = e.replace(
|
|
148
148
|
/@media[^{]*max-width\s*:\s*480px[^{]*\{((?:[^{}]*\{[^{}]*\})*[^{}]*)\}/g,
|
|
149
|
-
(r,
|
|
150
|
-
const i =
|
|
149
|
+
(r, o) => {
|
|
150
|
+
const i = o.match(/[^{}]+\{[^{}]*\}/g) || [], s = /ins-recommendation|product-image-cell|button-cell|product-info-cell/;
|
|
151
151
|
return i.every((m) => s.test(m)) ? "" : r;
|
|
152
152
|
}
|
|
153
153
|
)), e;
|
|
@@ -163,11 +163,11 @@ const U = [
|
|
|
163
163
|
// (SD-142395: split out of the removed deduplicate-inline-styles rule.)
|
|
164
164
|
description: "Force !important on es-button link color to defeat Gmail link-color override",
|
|
165
165
|
type: "custom",
|
|
166
|
-
processor: (
|
|
166
|
+
processor: (t) => t.replace(
|
|
167
167
|
/<a\b[^>]*\bes-button\b[^>]*>/g,
|
|
168
168
|
(e) => e.replace(
|
|
169
169
|
/([;"]color:)([^;"]+)/g,
|
|
170
|
-
(r,
|
|
170
|
+
(r, o, i) => i.includes("!important") ? r : `${o}${i} !important`
|
|
171
171
|
)
|
|
172
172
|
),
|
|
173
173
|
priority: 58
|
|
@@ -183,13 +183,30 @@ const U = [
|
|
|
183
183
|
// rather than classed, so they survive Gmail clipping.
|
|
184
184
|
description: "Collapse whitespace inside recommendation blocks and strip boundary markers",
|
|
185
185
|
type: "custom",
|
|
186
|
-
processor: (
|
|
187
|
-
const e = (r) => r.replace(/>\s+</g, "><").replace(/<[^>]+>/g, (
|
|
188
|
-
return
|
|
186
|
+
processor: (t) => {
|
|
187
|
+
const e = (r) => r.replace(/>\s+</g, "><").replace(/<[^>]+>/g, (o) => o.replace(/\s+/g, " "));
|
|
188
|
+
return t.replace(/<!--REC_START-->([\s\S]*?)<!--REC_END-->/g, (r, o) => e(o)).replaceAll("<!--REC_START-->", "").replaceAll("<!--REC_END-->", "");
|
|
189
189
|
},
|
|
190
190
|
priority: 99
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
id: "wrap-mobile-row-mso-conditional",
|
|
194
|
+
// SD-145666: OLD Outlook (Word engine) ignores @media and honors display:none
|
|
195
|
+
// on <tr>/<table> unreliably, so it renders BOTH the desktop AND the populated
|
|
196
|
+
// mobile recommendation container — products duplicate (1,2,1,2). prepare-
|
|
197
|
+
// recommendations (P48) tags each POPULATED mobile <tr> with safe placeholder
|
|
198
|
+
// comments; swap them here — AFTER minify (P99) has collapsed whitespace and
|
|
199
|
+
// stripped the REC markers — into a downlevel-revealed conditional comment so
|
|
200
|
+
// Outlook skips the row while every other client still renders it. Injecting the
|
|
201
|
+
// delicate `<!-- -->` ghost token LAST keeps it out of every whitespace/comment-
|
|
202
|
+
// mangling pass. email-service preserves this exact pattern (proven around
|
|
203
|
+
// es-button spans in delivered emails).
|
|
204
|
+
description: "Wrap populated recommendation mobile row in [if !mso] conditional comment for Outlook",
|
|
205
|
+
type: "custom",
|
|
206
|
+
processor: (t) => t.replaceAll("<!--MSO_MOBILE_HIDE_START-->", "<!--[if !mso]><!-- -->").replaceAll("<!--MSO_MOBILE_HIDE_END-->", "<!--<![endif]-->"),
|
|
207
|
+
priority: 100
|
|
191
208
|
}
|
|
192
209
|
];
|
|
193
210
|
export {
|
|
194
|
-
|
|
211
|
+
H as recommendationCompilerRules
|
|
195
212
|
};
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import { useConfig as
|
|
2
|
-
import { useRecommendation as
|
|
3
|
-
import {
|
|
4
|
-
import { useRecommendationExtensionStore as
|
|
5
|
-
import { isIgnoredRecommendationBlock as
|
|
6
|
-
function
|
|
7
|
-
const i = `{{${
|
|
1
|
+
import { useConfig as g } from "../../../composables/useConfig.js";
|
|
2
|
+
import { useRecommendation as O } from "../../../composables/useRecommendation.js";
|
|
3
|
+
import { MOBILE_ROW_SELECTOR as q, MOBILE_CONTAINER_SELECTOR as M, CSS_CLASS_RECO_BUTTON as B } from "../../../extensions/Blocks/Recommendation/constants/selectors.js";
|
|
4
|
+
import { useRecommendationExtensionStore as N } from "../../../extensions/Blocks/Recommendation/store/recommendation.js";
|
|
5
|
+
import { isIgnoredRecommendationBlock as T } from "./recommendationIgnoreUtils.js";
|
|
6
|
+
function L(t, r, e, o, c = "") {
|
|
7
|
+
const i = `{{${c}${t}_${r}_${e}}}`, n = `{{${c}${t}_${r}_currency}}`;
|
|
8
8
|
return o === "before" ? `${n} ${i}` : `${i} ${n}`;
|
|
9
9
|
}
|
|
10
|
-
function
|
|
10
|
+
function _(t) {
|
|
11
11
|
let r = t;
|
|
12
12
|
for (; r.children.length === 1; )
|
|
13
13
|
[r] = r.children;
|
|
14
14
|
return r;
|
|
15
15
|
}
|
|
16
|
-
function A(t, r, e, o,
|
|
16
|
+
function A(t, r, e, o, c, i) {
|
|
17
17
|
switch (r) {
|
|
18
18
|
case "productImage": {
|
|
19
19
|
const n = t.querySelector("img");
|
|
20
20
|
n && (n.setAttribute("src", `{{${i}${e}_${o}_image_url}}`), n.setAttribute("alt", `{{${i}${e}_${o}_name}}`));
|
|
21
|
-
const
|
|
22
|
-
|
|
21
|
+
const s = t.querySelector("a");
|
|
22
|
+
s && (s.setAttribute("href", `{{${i}${e}_${o}_url}}`), s.classList.add(B));
|
|
23
23
|
break;
|
|
24
24
|
}
|
|
25
25
|
case "productName": {
|
|
26
26
|
const n = t.querySelector("p");
|
|
27
|
-
n && (
|
|
27
|
+
n && (_(n).textContent = `{{${i}${e}_${o}_name}}`);
|
|
28
28
|
break;
|
|
29
29
|
}
|
|
30
30
|
// Inline mode ("Move to next line" OFF) merges BOTH prices into one row
|
|
@@ -33,15 +33,15 @@ function A(t, r, e, o, s, i) {
|
|
|
33
33
|
case "productPrice":
|
|
34
34
|
case "productOldPrice": {
|
|
35
35
|
const n = (l, d) => {
|
|
36
|
-
l && (
|
|
36
|
+
l && (_(l).textContent = L(
|
|
37
37
|
e,
|
|
38
38
|
o,
|
|
39
39
|
d,
|
|
40
|
-
|
|
40
|
+
c,
|
|
41
41
|
i
|
|
42
42
|
));
|
|
43
|
-
},
|
|
44
|
-
n(
|
|
43
|
+
}, s = t.querySelector(".product-price p"), a = t.querySelector(".product-old-price p"), u = !s && !a ? t.querySelector("p") : null;
|
|
44
|
+
n(s ?? (r === "productPrice" ? u : null), "price"), n(a ?? (r === "productOldPrice" ? u : null), "original_price");
|
|
45
45
|
break;
|
|
46
46
|
}
|
|
47
47
|
case "productButton": {
|
|
@@ -53,8 +53,8 @@ function A(t, r, e, o, s, i) {
|
|
|
53
53
|
const n = t.querySelector(".omnibus-price-value");
|
|
54
54
|
if (n) {
|
|
55
55
|
n.textContent = `{{${i}${e}_${o}_omnibus_price}}`;
|
|
56
|
-
const
|
|
57
|
-
|
|
56
|
+
const s = n.closest("p");
|
|
57
|
+
s && (s.setAttribute("product-attr", "omnibus_price"), s.setAttribute("composition", "true"));
|
|
58
58
|
}
|
|
59
59
|
break;
|
|
60
60
|
}
|
|
@@ -62,112 +62,112 @@ function A(t, r, e, o, s, i) {
|
|
|
62
62
|
const n = t.querySelector(".omnibus-discount-value");
|
|
63
63
|
if (n) {
|
|
64
64
|
n.textContent = `{{${i}${e}_${o}_omnibus_discount}}`;
|
|
65
|
-
const
|
|
66
|
-
|
|
65
|
+
const s = n.closest("p");
|
|
66
|
+
s && (s.setAttribute("product-attr", "omnibus_discount"), s.setAttribute("composition", "true"));
|
|
67
67
|
}
|
|
68
68
|
break;
|
|
69
69
|
}
|
|
70
70
|
default: {
|
|
71
71
|
const n = t.getAttribute("product-attr") ? t : t.querySelector("[product-attr]");
|
|
72
72
|
if (n) {
|
|
73
|
-
const
|
|
74
|
-
a && (
|
|
73
|
+
const s = n.getAttribute("product-attr"), a = n.querySelector("p");
|
|
74
|
+
a && (_(a).textContent = `{{${i}${e}_${o}_${s}}}`);
|
|
75
75
|
}
|
|
76
76
|
break;
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
|
-
const
|
|
81
|
-
function
|
|
82
|
-
const
|
|
80
|
+
const P = "name";
|
|
81
|
+
function b(t, r, e, o) {
|
|
82
|
+
const c = `${o}${r}_${e}_${P}`;
|
|
83
83
|
return {
|
|
84
|
-
open: t.createComment(`{% if ${
|
|
84
|
+
open: t.createComment(`{% if ${c} and ${c} != "" %}`),
|
|
85
85
|
close: t.createComment("{% endif %}")
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
|
-
function
|
|
89
|
-
return
|
|
88
|
+
function R(t, r, e) {
|
|
89
|
+
return b(t, r, 0, e);
|
|
90
90
|
}
|
|
91
|
-
function
|
|
91
|
+
function D(t, r, e, o) {
|
|
92
92
|
if (!t.innerHTML.includes("{{"))
|
|
93
93
|
return;
|
|
94
|
-
const { open:
|
|
95
|
-
t.insertBefore(
|
|
94
|
+
const { open: c, close: i } = b(t.ownerDocument, r, e, o);
|
|
95
|
+
t.insertBefore(c, t.firstChild), t.appendChild(i);
|
|
96
96
|
}
|
|
97
|
-
function
|
|
98
|
-
var n,
|
|
97
|
+
function w(t, r, e, o) {
|
|
98
|
+
var n, s;
|
|
99
99
|
if (!t.innerHTML.includes("{{"))
|
|
100
100
|
return;
|
|
101
|
-
const { open:
|
|
102
|
-
(n = t.parentNode) == null || n.insertBefore(
|
|
101
|
+
const { open: c, close: i } = b(t.ownerDocument, r, e, o);
|
|
102
|
+
(n = t.parentNode) == null || n.insertBefore(c, t), (s = t.parentNode) == null || s.insertBefore(i, t.nextSibling);
|
|
103
103
|
}
|
|
104
|
-
function
|
|
104
|
+
function W(t, r, e, o) {
|
|
105
105
|
t.querySelectorAll(".recommendation-product-row").forEach((i, n) => {
|
|
106
106
|
i.querySelectorAll("[data-attribute-type]").forEach((a) => {
|
|
107
107
|
const u = a.getAttribute("data-attribute-type") || "", l = a.querySelectorAll(".attribute-cell");
|
|
108
108
|
l.length > 0 ? l.forEach((d) => {
|
|
109
109
|
A(d, u, r, n, e, o);
|
|
110
110
|
}) : A(a, u, r, n, e, o);
|
|
111
|
-
}),
|
|
111
|
+
}), w(i, r, n, o);
|
|
112
112
|
});
|
|
113
113
|
}
|
|
114
|
-
function
|
|
115
|
-
const
|
|
116
|
-
if (!
|
|
114
|
+
function v(t, r, e, o) {
|
|
115
|
+
const c = t.querySelectorAll(".recommendation-product-row");
|
|
116
|
+
if (!c.length)
|
|
117
117
|
return;
|
|
118
|
-
const [i] =
|
|
119
|
-
|
|
118
|
+
const [i] = c, n = i.querySelector("[data-attribute-type]"), s = n ? n.querySelectorAll(".attribute-cell").length : 1;
|
|
119
|
+
c.forEach((a, u) => {
|
|
120
120
|
a.querySelectorAll("[data-attribute-type]").forEach((d) => {
|
|
121
121
|
const p = d.getAttribute("data-attribute-type") || "";
|
|
122
|
-
d.querySelectorAll(".attribute-cell").forEach((
|
|
123
|
-
const h = u *
|
|
124
|
-
A(
|
|
122
|
+
d.querySelectorAll(".attribute-cell").forEach((f, m) => {
|
|
123
|
+
const h = u * s + m;
|
|
124
|
+
A(f, p, r, h, e, o), D(f, r, h, o);
|
|
125
125
|
});
|
|
126
126
|
});
|
|
127
127
|
});
|
|
128
128
|
}
|
|
129
|
-
function
|
|
129
|
+
function H(t, r, e, o) {
|
|
130
130
|
t.querySelectorAll(".ins-recommendation-product-container").forEach((i) => {
|
|
131
|
-
|
|
131
|
+
v(i, r, e, o);
|
|
132
132
|
});
|
|
133
133
|
}
|
|
134
|
-
function
|
|
135
|
-
const o = t.getAttribute("data-layout") || "grid",
|
|
136
|
-
o === "list" ?
|
|
134
|
+
function F(t, r, e) {
|
|
135
|
+
const o = t.getAttribute("data-layout") || "grid", c = t.getAttribute("currency-alignment") || "after";
|
|
136
|
+
o === "list" ? W(t, r, c, e) : H(t, r, c, e);
|
|
137
137
|
}
|
|
138
|
-
function
|
|
139
|
-
const o = new RegExp(`${r}\\s*:\\s*(\\d+)\\s*px`, "i"),
|
|
140
|
-
return
|
|
138
|
+
function y(t, r, e) {
|
|
139
|
+
const o = new RegExp(`${r}\\s*:\\s*(\\d+)\\s*px`, "i"), c = t.match(o);
|
|
140
|
+
return c ? parseInt(c[1]) : e;
|
|
141
141
|
}
|
|
142
|
-
function
|
|
142
|
+
function $(t) {
|
|
143
143
|
const r = t.trim();
|
|
144
144
|
return r.endsWith("%") ? parseFloat(r) < 100 : /^\d+(?:\.\d+)?(?:px)?$/.test(r) && parseInt(r) > 0;
|
|
145
145
|
}
|
|
146
|
-
function
|
|
146
|
+
function C(t) {
|
|
147
147
|
const r = t.getAttribute("width");
|
|
148
|
-
if (r &&
|
|
148
|
+
if (r && $(r))
|
|
149
149
|
return r.trim();
|
|
150
150
|
const e = (t.getAttribute("style") || "").match(/(?:^|[;\s])width\s*:\s*(\d+(?:\.\d+)?(?:px|%))/i);
|
|
151
|
-
return e &&
|
|
151
|
+
return e && $(e[1]) ? e[1] : null;
|
|
152
152
|
}
|
|
153
|
-
function
|
|
153
|
+
function G(t, r) {
|
|
154
154
|
let e = t.parentElement;
|
|
155
155
|
for (; e && e !== r; ) {
|
|
156
|
-
if (e.tagName === "TD" &&
|
|
156
|
+
if (e.tagName === "TD" && C(e))
|
|
157
157
|
return e;
|
|
158
158
|
e = e.parentElement;
|
|
159
159
|
}
|
|
160
160
|
return null;
|
|
161
161
|
}
|
|
162
|
-
function
|
|
163
|
-
const r = t.getAttribute("style") || "", e =
|
|
164
|
-
|
|
162
|
+
function V(t) {
|
|
163
|
+
const r = t.getAttribute("style") || "", e = y(r, "width", 600), o = y(r, "padding", 0) * 2, c = Math.max(0, e - o);
|
|
164
|
+
c !== 0 && t.querySelectorAll("img.adapt-img").forEach((i) => {
|
|
165
165
|
if (i.hasAttribute("width"))
|
|
166
166
|
return;
|
|
167
|
-
const n =
|
|
167
|
+
const n = G(i, t);
|
|
168
168
|
if (!n)
|
|
169
169
|
return;
|
|
170
|
-
const
|
|
170
|
+
const s = C(n), a = y(n.getAttribute("style") || "", "padding", 0) * 2, u = s.endsWith("%") ? Math.floor(c * parseFloat(s) / 100) : parseInt(s), l = Math.max(1, u - a);
|
|
171
171
|
i.setAttribute("width", String(l));
|
|
172
172
|
const d = i.getAttribute("style") || "";
|
|
173
173
|
if (!/\bwidth\s*:\s*\d/i.test(d)) {
|
|
@@ -176,32 +176,43 @@ function G(t) {
|
|
|
176
176
|
}
|
|
177
177
|
});
|
|
178
178
|
}
|
|
179
|
-
|
|
179
|
+
const E = "MSO_MOBILE_HIDE_START", U = "MSO_MOBILE_HIDE_END";
|
|
180
|
+
function X(t, r) {
|
|
181
|
+
t.querySelectorAll(q).forEach((e) => {
|
|
182
|
+
var i, n;
|
|
183
|
+
const o = e.querySelector(M);
|
|
184
|
+
if (!o || o.children.length === 0)
|
|
185
|
+
return;
|
|
186
|
+
const c = e.previousSibling;
|
|
187
|
+
(c == null ? void 0 : c.nodeType) === Node.COMMENT_NODE && c.data === E || ((i = e.parentNode) == null || i.insertBefore(r.createComment(E), e), (n = e.parentNode) == null || n.insertBefore(r.createComment(U), e.nextSibling));
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
function j(t, r) {
|
|
180
191
|
const e = t.match(/<!DOCTYPE[^>]*>/i);
|
|
181
192
|
return (e ? `${e[0]}
|
|
182
193
|
` : "") + r.documentElement.outerHTML;
|
|
183
194
|
}
|
|
184
|
-
function
|
|
195
|
+
function Q(t) {
|
|
185
196
|
const r = t.replaceAll("{%", "<!--{%").replaceAll("%}", "%}-->"), e = new DOMParser().parseFromString(r, "text/html"), o = e.querySelectorAll(".recommendation-block-v2");
|
|
186
197
|
if (!o.length)
|
|
187
198
|
return t;
|
|
188
|
-
const { buildCampaignUrl:
|
|
199
|
+
const { buildCampaignUrl: c } = O(), i = N();
|
|
189
200
|
i.recommendationCampaignUrls = {};
|
|
190
|
-
const { isFeatureEnabled: n } =
|
|
201
|
+
const { isFeatureEnabled: n } = g(), s = n("liquidSyntax") ? "reco_" : "";
|
|
191
202
|
return o.forEach((u) => {
|
|
192
|
-
var d, p,
|
|
203
|
+
var d, p, S, f;
|
|
193
204
|
const l = u.getAttribute("recommendation-id");
|
|
194
205
|
if (l) {
|
|
195
|
-
if ((d = u.parentNode) == null || d.insertBefore(e.createComment("REC_START"), u), (p = u.parentNode) == null || p.insertBefore(e.createComment("REC_END"), u.nextSibling), u.querySelectorAll('[data-visibility="0"]').forEach((
|
|
196
|
-
|
|
197
|
-
const { open:
|
|
198
|
-
(
|
|
206
|
+
if ((d = u.parentNode) == null || d.insertBefore(e.createComment("REC_START"), u), (p = u.parentNode) == null || p.insertBefore(e.createComment("REC_END"), u.nextSibling), u.querySelectorAll('[data-visibility="0"]').forEach((m) => m.remove()), c(l), X(u, e), !T(u)) {
|
|
207
|
+
F(u, l, s);
|
|
208
|
+
const { open: m, close: h } = R(e, l, s);
|
|
209
|
+
(S = u.parentNode) == null || S.insertBefore(m, u), (f = u.parentNode) == null || f.insertBefore(h, u.nextSibling);
|
|
199
210
|
}
|
|
200
|
-
|
|
211
|
+
V(u);
|
|
201
212
|
}
|
|
202
|
-
}),
|
|
213
|
+
}), j(r, e).replaceAll("<!--{%", "{%").replaceAll("%}-->", "%}").replaceAll("<!--{%", "{%").replaceAll("%}-->", "%}");
|
|
203
214
|
}
|
|
204
215
|
export {
|
|
205
|
-
|
|
206
|
-
|
|
216
|
+
L as formatPriceVariable,
|
|
217
|
+
Q as prepareRecommendationBlocks
|
|
207
218
|
};
|
|
@@ -4,7 +4,10 @@ const e = "Items", o = {
|
|
|
4
4
|
"Recommendation Block": "Recommendation",
|
|
5
5
|
Items: e,
|
|
6
6
|
"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.": "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.",
|
|
7
|
-
"This block is switched from the Old Version to the New Version. We recommend you check the Items block and test your message to ensure it works properly.": "This block is switched from the Old Version to the New Version. We recommend you check the Items block and test your message to ensure it works properly."
|
|
7
|
+
"This block is switched from the Old Version to the New Version. We recommend you check the Items block and test your message to ensure it works properly.": "This block is switched from the Old Version to the New Version. We recommend you check the Items block and test your message to ensure it works properly.",
|
|
8
|
+
"Pixel Tracking Opt-in": "Pixel Tracking Opt-in",
|
|
9
|
+
"OPT-IN SELECTION": "OPT-IN SELECTION",
|
|
10
|
+
"UNSUBSCRIBE GROUPS": "UNSUBSCRIBE GROUPS"
|
|
8
11
|
};
|
|
9
12
|
export {
|
|
10
13
|
e as Items,
|
|
@@ -1,35 +1,38 @@
|
|
|
1
1
|
import { useTranslations as R } from "../composables/useTranslations.js";
|
|
2
|
-
import { ProductType as
|
|
2
|
+
import { ProductType as s } from "../@types/config/schemas.js";
|
|
3
3
|
import "../@types/config/defaults.js";
|
|
4
|
-
import { getEnvironmentPrefix as
|
|
5
|
-
const
|
|
4
|
+
import { getEnvironmentPrefix as _ } from "../utils/environmentUtil.js";
|
|
5
|
+
const B = {
|
|
6
6
|
UNSUBSCRIBE_LINK_TYPE: 1,
|
|
7
7
|
PREFERENCES_LINK_TYPE: 3
|
|
8
|
-
},
|
|
8
|
+
}, C = {
|
|
9
9
|
UNSUBSCRIBE_LINK_REGEX: /{{ins-unsubscribe-link}}/g,
|
|
10
10
|
DATA_OGSB_BUTTON_CSS_REGEX: "\\[data-ogsb\\]\\s*\\.es-button\\.es-button-[0-9]+\\s*\\{(?:[^\\}]*)\\}",
|
|
11
11
|
GLOBAL_UNSUBSCRIBE_LINK_REGEX: /{{ins-global-unsubscribe-link}}/g,
|
|
12
12
|
PREFERENCES_UNSUBSCRIBE_LINK_REGEX: /{{ins-preferences-unsubscribe-link}}/g
|
|
13
|
-
},
|
|
14
|
-
UNSUBSCRIBE_URL: `https://mail.${
|
|
15
|
-
PREFERENCES_URL: `https://mail.${
|
|
16
|
-
},
|
|
17
|
-
[
|
|
18
|
-
[
|
|
19
|
-
[
|
|
20
|
-
},
|
|
13
|
+
}, e = _(), U = {
|
|
14
|
+
UNSUBSCRIBE_URL: `https://mail.${e}.com/user/v1/unsub`,
|
|
15
|
+
PREFERENCES_URL: `https://mail.${e}.com/user/v1/prefs`
|
|
16
|
+
}, o = {
|
|
17
|
+
[s.EMAIL]: "email",
|
|
18
|
+
[s.ARCHITECT]: "journey",
|
|
19
|
+
[s.UNSUBSCRIBE_PAGES]: "email"
|
|
20
|
+
}, c = "iid", S = "G", N = "P", u = [
|
|
21
|
+
S,
|
|
22
|
+
N
|
|
23
|
+
], T = () => ({
|
|
21
24
|
name: R()("onboarding-center.email-subscribers-global-unsub-card-title"),
|
|
22
|
-
sendGridId:
|
|
23
|
-
}),
|
|
25
|
+
sendGridId: S
|
|
26
|
+
}), b = "/email/unsubscribe-pages", E = {
|
|
24
27
|
GLOBAL_UNSUBSCRIBE: 1,
|
|
25
28
|
GLOBAL_UNSUBSCRIBE_CONFIRMATION_PAGE: 2,
|
|
26
29
|
SUBSCRIPTION_PREFERENCE_CENTER: 3,
|
|
27
30
|
SUBSCRIPTION_PREFERENCE_CONFIRMATION: 4,
|
|
28
31
|
RESUBSCRIBE: 5
|
|
29
|
-
},
|
|
32
|
+
}, P = {
|
|
30
33
|
[E.GLOBAL_UNSUBSCRIBE]: "custom-unsubscribe",
|
|
31
34
|
[E.SUBSCRIPTION_PREFERENCE_CENTER]: "custom-preferences"
|
|
32
|
-
},
|
|
35
|
+
}, L = {
|
|
33
36
|
[E.GLOBAL_UNSUBSCRIBE]: [
|
|
34
37
|
E.GLOBAL_UNSUBSCRIBE,
|
|
35
38
|
E.GLOBAL_UNSUBSCRIBE_CONFIRMATION_PAGE,
|
|
@@ -39,32 +42,34 @@ const i = {
|
|
|
39
42
|
E.SUBSCRIPTION_PREFERENCE_CENTER,
|
|
40
43
|
E.SUBSCRIPTION_PREFERENCE_CONFIRMATION
|
|
41
44
|
]
|
|
42
|
-
},
|
|
43
|
-
const
|
|
45
|
+
}, O = () => {
|
|
46
|
+
const n = R();
|
|
44
47
|
return {
|
|
45
|
-
[E.GLOBAL_UNSUBSCRIBE]:
|
|
46
|
-
[E.GLOBAL_UNSUBSCRIBE_CONFIRMATION_PAGE]:
|
|
47
|
-
[E.RESUBSCRIBE]:
|
|
48
|
-
[E.SUBSCRIPTION_PREFERENCE_CENTER]:
|
|
49
|
-
[E.SUBSCRIPTION_PREFERENCE_CONFIRMATION]:
|
|
48
|
+
[E.GLOBAL_UNSUBSCRIBE]: n("unsubscription-preference.type-global-unsubscribe"),
|
|
49
|
+
[E.GLOBAL_UNSUBSCRIBE_CONFIRMATION_PAGE]: n("unsubscription-preference.type-global-unsubscription-confirmation"),
|
|
50
|
+
[E.RESUBSCRIBE]: n("unsubscription-preference.type-resubscribe"),
|
|
51
|
+
[E.SUBSCRIPTION_PREFERENCE_CENTER]: n("unsubscription-preference.type-subscription-preferences-center"),
|
|
52
|
+
[E.SUBSCRIPTION_PREFERENCE_CONFIRMATION]: n("unsubscription-preference.type-subscription-preferences-confirmation")
|
|
50
53
|
};
|
|
51
|
-
},
|
|
54
|
+
}, p = {
|
|
52
55
|
default: "{{ins-unsubscribe-link}}",
|
|
53
56
|
[E.GLOBAL_UNSUBSCRIBE]: "{{ins-global-unsubscribe-link}}",
|
|
54
57
|
[E.SUBSCRIPTION_PREFERENCE_CENTER]: "{{ins-preferences-unsubscribe-link}}"
|
|
55
58
|
};
|
|
56
59
|
export {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
S as DEFAULT_UNSUBSCRIBE_GROUP_SEND_GRID_ID,
|
|
61
|
+
c as INSIDER_ID,
|
|
62
|
+
C as LINK_REGEXES,
|
|
63
|
+
B as LINK_TYPES,
|
|
64
|
+
p as MERGE_TAGS,
|
|
62
65
|
E as PAGE_TYPES,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
b as
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
N as PIXEL_TRACKING_SEND_GRID_ID,
|
|
67
|
+
o as PRODUCT_TYPE_URL_SEGMENTS,
|
|
68
|
+
L as TYPE_COLLECTIONS,
|
|
69
|
+
b as UNSUBSCRIBE_PAGES_LINK,
|
|
70
|
+
u as UNSUBSCRIBE_SENTINEL_SEND_GRID_IDS,
|
|
71
|
+
P as UNSUBSCRIBE_SYNC_MODULE_TYPES,
|
|
72
|
+
U as URLS,
|
|
73
|
+
T as getDefaultUnsubscribeGroup,
|
|
74
|
+
O as getTypeTranslations
|
|
70
75
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Block as e, BlockCompositionType as t } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
|
|
2
2
|
import { getDefaultTemplate as o } from "./template.js";
|
|
3
3
|
const r = "checkbox-block";
|
|
4
|
-
class
|
|
4
|
+
class l extends e {
|
|
5
5
|
constructor() {
|
|
6
6
|
super();
|
|
7
7
|
}
|
|
@@ -18,7 +18,9 @@ class s extends e {
|
|
|
18
18
|
return this.api.translate("Checkbox Block");
|
|
19
19
|
}
|
|
20
20
|
getDescription() {
|
|
21
|
-
return this.api.translate(
|
|
21
|
+
return this.api.translate(
|
|
22
|
+
"Checkbox lets you select Unsubscribe and Preference Type for users to manage their opt-in or opt-out preferences."
|
|
23
|
+
);
|
|
22
24
|
}
|
|
23
25
|
getTemplate() {
|
|
24
26
|
return o();
|
|
@@ -29,5 +31,5 @@ class s extends e {
|
|
|
29
31
|
}
|
|
30
32
|
export {
|
|
31
33
|
r as CHECKBOX_BLOCK_ID,
|
|
32
|
-
|
|
34
|
+
l as CheckboxBlock
|
|
33
35
|
};
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import { useHttp as
|
|
5
|
-
import { getDefaultUnsubscribeGroup as
|
|
6
|
-
import { Control as
|
|
7
|
-
const b = "ui-elements-checkbox",
|
|
8
|
-
class
|
|
1
|
+
var p = Object.defineProperty;
|
|
2
|
+
var L = (i, n, e) => n in i ? p(i, n, { enumerable: !0, configurable: !0, writable: !0, value: e }) : i[n] = e;
|
|
3
|
+
var a = (i, n, e) => L(i, typeof n != "symbol" ? n + "" : n, e);
|
|
4
|
+
import { useHttp as h } from "../../../composables/useHttp.js";
|
|
5
|
+
import { getDefaultUnsubscribeGroup as T, PIXEL_TRACKING_SEND_GRID_ID as C, UNSUBSCRIBE_SENTINEL_SEND_GRID_IDS as I } from "../../../enums/unsubscribe.js";
|
|
6
|
+
import { Control as m, UIElementType as r, UEAttr as t, ModificationDescription as S } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
|
|
7
|
+
const b = "ui-elements-checkbox", E = "select", { get: _ } = h();
|
|
8
|
+
class G extends m {
|
|
9
9
|
constructor() {
|
|
10
10
|
super(...arguments);
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
a(this, "currentNode");
|
|
12
|
+
a(this, "selectedUnsubGroup");
|
|
13
|
+
a(this, "unsubList", []);
|
|
14
14
|
}
|
|
15
15
|
getId() {
|
|
16
16
|
return b;
|
|
@@ -19,12 +19,12 @@ class I extends p {
|
|
|
19
19
|
if (this.selectedUnsubGroup = "", this.currentNode && "getAttribute" in this.currentNode) {
|
|
20
20
|
const e = this.currentNode.getAttribute("id");
|
|
21
21
|
if (e) {
|
|
22
|
-
const s = e
|
|
22
|
+
const s = I.includes(e) ? e : Number(e);
|
|
23
23
|
s && (this.selectedUnsubGroup = s);
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
this.api.updateValues({
|
|
27
|
-
[
|
|
27
|
+
[E]: this.selectedUnsubGroup
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
30
|
_getLabel(e, s = `${Math.random()}`) {
|
|
@@ -46,17 +46,19 @@ class I extends p {
|
|
|
46
46
|
return this.unsubList.map((e) => this._getSelectItem(e.name, e.sendGridId)).join("");
|
|
47
47
|
}
|
|
48
48
|
getTemplate() {
|
|
49
|
+
const e = this.api.translate("Unsubscribe & Preference Center Type"), s = this.api.translate("Select Unsubscribe and Preference Type");
|
|
49
50
|
return `
|
|
50
51
|
<div class="checkbox-controls-container">
|
|
51
|
-
<div class="checkbox-select-container container
|
|
52
|
+
<div class="checkbox-select-container container one-column stretch">
|
|
52
53
|
<${r.LABEL}
|
|
53
|
-
${t.LABEL.text}="${
|
|
54
|
+
${t.LABEL.text}="${e}"
|
|
54
55
|
${t.LABEL.name}="${Math.random()}">
|
|
55
56
|
</${r.LABEL}>
|
|
56
57
|
|
|
57
58
|
<${r.SELECTPICKER}
|
|
58
|
-
${t.SELECTPICKER.name}="${
|
|
59
|
-
${t.SELECTPICKER.
|
|
59
|
+
${t.SELECTPICKER.name}="${E}"
|
|
60
|
+
${t.SELECTPICKER.searchable}="true"
|
|
61
|
+
${t.SELECTPICKER.placeholder}="${s}">
|
|
60
62
|
${this._getSelect()}
|
|
61
63
|
</${r.SELECTPICKER}>
|
|
62
64
|
</div>
|
|
@@ -64,30 +66,42 @@ class I extends p {
|
|
|
64
66
|
`;
|
|
65
67
|
}
|
|
66
68
|
_onSelectChange(e) {
|
|
67
|
-
this.currentNode && this.api.getDocumentModifier().modifyHtml(this.currentNode).setAttribute("id", e.toString()).apply(new
|
|
69
|
+
this.currentNode && this.api.getDocumentModifier().modifyHtml(this.currentNode).setAttribute("id", e.toString()).apply(new S(`Updated text to ${e}`));
|
|
68
70
|
}
|
|
69
71
|
_listenToFormUpdates() {
|
|
70
|
-
this.api.onValueChanged(
|
|
72
|
+
this.api.onValueChanged(E, (e) => this._onSelectChange(e));
|
|
71
73
|
}
|
|
72
74
|
onTemplateNodeUpdated(e) {
|
|
73
75
|
this.currentNode = e, this._setFormValues();
|
|
74
76
|
}
|
|
75
77
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
76
78
|
async onRender() {
|
|
77
|
-
const e = await
|
|
79
|
+
const e = await _(
|
|
78
80
|
"/unsubscribe-groups/unsubscribe-list"
|
|
79
|
-
), s =
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}))
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
), s = {
|
|
82
|
+
name: this.api.translate("Pixel Tracking Opt-in"),
|
|
83
|
+
sendGridId: C
|
|
84
|
+
}, c = [T(), ...e.data], u = (o) => ({
|
|
85
|
+
[t.SELECT_ITEM.text]: o.name,
|
|
86
|
+
[t.SELECT_ITEM.value]: o.sendGridId
|
|
87
|
+
}), l = (o) => ({
|
|
88
|
+
[t.SELECT_ITEM.text]: o,
|
|
89
|
+
[t.SELECT_ITEM.value]: `header:${o}`,
|
|
90
|
+
[t.SELECT_ITEM.disabled]: !0
|
|
91
|
+
}), d = [
|
|
92
|
+
l(this.api.translate("OPT-IN SELECTION")),
|
|
93
|
+
u(s),
|
|
94
|
+
l(this.api.translate("UNSUBSCRIBE GROUPS")),
|
|
95
|
+
...c.map(u)
|
|
96
|
+
];
|
|
97
|
+
this.unsubList = [s, ...c], this.api.setUIEAttribute(
|
|
98
|
+
E,
|
|
85
99
|
t.SELECTPICKER.items,
|
|
86
|
-
|
|
100
|
+
d
|
|
87
101
|
), this._setFormValues(), this._listenToFormUpdates();
|
|
88
102
|
}
|
|
89
103
|
}
|
|
90
104
|
export {
|
|
91
105
|
b as CHECKBOX_CONTROL_BLOCK_ID,
|
|
92
|
-
|
|
106
|
+
G as CheckboxControl
|
|
93
107
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Block as t, BlockCompositionType as
|
|
2
|
-
import { getDefaultTemplate as
|
|
1
|
+
import { Block as t, BlockCompositionType as e } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
|
|
2
|
+
import { getDefaultTemplate as o } from "./template.js";
|
|
3
3
|
const r = "radio-button-block";
|
|
4
|
-
class
|
|
4
|
+
class i extends t {
|
|
5
5
|
constructor() {
|
|
6
6
|
super();
|
|
7
7
|
}
|
|
@@ -12,16 +12,18 @@ class l extends t {
|
|
|
12
12
|
return "radio-button-icon";
|
|
13
13
|
}
|
|
14
14
|
getBlockCompositionType() {
|
|
15
|
-
return
|
|
15
|
+
return e.CONTAINER;
|
|
16
16
|
}
|
|
17
17
|
getName() {
|
|
18
18
|
return this.api.translate("Radio Button Block");
|
|
19
19
|
}
|
|
20
20
|
getDescription() {
|
|
21
|
-
return this.api.translate(
|
|
21
|
+
return this.api.translate(
|
|
22
|
+
"Radio button lets you select Unsubscribe and Preference Type for users to manage their opt-in or opt-out preferences."
|
|
23
|
+
);
|
|
22
24
|
}
|
|
23
25
|
getTemplate() {
|
|
24
|
-
return
|
|
26
|
+
return o();
|
|
25
27
|
}
|
|
26
28
|
allowInnerBlocksDND() {
|
|
27
29
|
return !1;
|
|
@@ -29,5 +31,5 @@ class l extends t {
|
|
|
29
31
|
}
|
|
30
32
|
export {
|
|
31
33
|
r as BLOCK_ID,
|
|
32
|
-
|
|
34
|
+
i as RadioButtonCustomBlock
|
|
33
35
|
};
|
|
@@ -1,93 +1,107 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import { useHttp as
|
|
5
|
-
import { getDefaultUnsubscribeGroup as
|
|
6
|
-
import { Control as
|
|
7
|
-
const b = "ui-elements-radio-button",
|
|
8
|
-
class
|
|
1
|
+
var p = Object.defineProperty;
|
|
2
|
+
var L = (i, n, e) => n in i ? p(i, n, { enumerable: !0, configurable: !0, writable: !0, value: e }) : i[n] = e;
|
|
3
|
+
var a = (i, n, e) => L(i, typeof n != "symbol" ? n + "" : n, e);
|
|
4
|
+
import { useHttp as T } from "../../../composables/useHttp.js";
|
|
5
|
+
import { getDefaultUnsubscribeGroup as h, PIXEL_TRACKING_SEND_GRID_ID as I, UNSUBSCRIBE_SENTINEL_SEND_GRID_IDS as m } from "../../../enums/unsubscribe.js";
|
|
6
|
+
import { Control as C, UIElementType as r, UEAttr as t, ModificationDescription as S } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
|
|
7
|
+
const b = "ui-elements-radio-button", E = "select", { get: _ } = T();
|
|
8
|
+
class G extends C {
|
|
9
9
|
constructor() {
|
|
10
10
|
super(...arguments);
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
a(this, "currentNode");
|
|
12
|
+
a(this, "selectedUnsubGroup");
|
|
13
|
+
a(this, "unsubList", []);
|
|
14
14
|
}
|
|
15
15
|
getId() {
|
|
16
16
|
return b;
|
|
17
17
|
}
|
|
18
18
|
_setFormValues() {
|
|
19
19
|
if (this.selectedUnsubGroup = "", this.currentNode && "getAttribute" in this.currentNode) {
|
|
20
|
-
const
|
|
21
|
-
if (
|
|
22
|
-
const s =
|
|
20
|
+
const e = this.currentNode.getAttribute("id");
|
|
21
|
+
if (e) {
|
|
22
|
+
const s = m.includes(e) ? e : Number(e);
|
|
23
23
|
s && (this.selectedUnsubGroup = s);
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
this.api.updateValues({
|
|
27
|
-
[
|
|
27
|
+
[E]: this.selectedUnsubGroup
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
|
-
_getLabel(
|
|
30
|
+
_getLabel(e, s = `${Math.random()}`) {
|
|
31
31
|
return `
|
|
32
|
-
<${
|
|
33
|
-
${
|
|
34
|
-
${
|
|
35
|
-
</${
|
|
32
|
+
<${r.LABEL}
|
|
33
|
+
${t.LABEL.text}="${e}"
|
|
34
|
+
${t.LABEL.name}="${s}">
|
|
35
|
+
</${r.LABEL}>
|
|
36
36
|
`;
|
|
37
37
|
}
|
|
38
|
-
_getSelectItem(
|
|
38
|
+
_getSelectItem(e, s) {
|
|
39
39
|
return `
|
|
40
|
-
<${
|
|
41
|
-
${
|
|
42
|
-
${
|
|
43
|
-
</${
|
|
40
|
+
<${r.SELECT_ITEM}
|
|
41
|
+
${t.SELECT_ITEM.text}="${e}"
|
|
42
|
+
${t.SELECT_ITEM.value}="${s}">
|
|
43
|
+
</${r.SELECT_ITEM}>`;
|
|
44
44
|
}
|
|
45
45
|
_getSelect() {
|
|
46
|
-
return this.unsubList.map((
|
|
46
|
+
return this.unsubList.map((e) => this._getSelectItem(e.name, e.sendGridId)).join("");
|
|
47
47
|
}
|
|
48
48
|
getTemplate() {
|
|
49
|
+
const e = this.api.translate("Unsubscribe & Preference Center Type"), s = this.api.translate("Select Unsubscribe and Preference Type");
|
|
49
50
|
return `
|
|
50
51
|
<div class="checkbox-controls-container">
|
|
51
|
-
<div class="checkbox-select-container container
|
|
52
|
-
<${
|
|
53
|
-
${
|
|
54
|
-
${
|
|
55
|
-
</${
|
|
52
|
+
<div class="checkbox-select-container container one-column stretch">
|
|
53
|
+
<${r.LABEL}
|
|
54
|
+
${t.LABEL.text}="${e}"
|
|
55
|
+
${t.LABEL.name}="${Math.random()}">
|
|
56
|
+
</${r.LABEL}>
|
|
56
57
|
|
|
57
|
-
<${
|
|
58
|
-
${
|
|
59
|
-
${
|
|
58
|
+
<${r.SELECTPICKER}
|
|
59
|
+
${t.SELECTPICKER.name}="${E}"
|
|
60
|
+
${t.SELECTPICKER.searchable}="true"
|
|
61
|
+
${t.SELECTPICKER.placeholder}="${s}">
|
|
60
62
|
${this._getSelect()}
|
|
61
|
-
</${
|
|
63
|
+
</${r.SELECTPICKER}>
|
|
62
64
|
</div>
|
|
63
65
|
</div>
|
|
64
66
|
`;
|
|
65
67
|
}
|
|
66
|
-
_onSelectChange(
|
|
67
|
-
this.currentNode && this.api.getDocumentModifier().modifyHtml(this.currentNode).setAttribute("id",
|
|
68
|
+
_onSelectChange(e) {
|
|
69
|
+
this.currentNode && this.api.getDocumentModifier().modifyHtml(this.currentNode).setAttribute("id", e.toString()).apply(new S(`Updated text to ${e}`));
|
|
68
70
|
}
|
|
69
71
|
_listenToFormUpdates() {
|
|
70
|
-
this.api.onValueChanged(
|
|
72
|
+
this.api.onValueChanged(E, (e) => this._onSelectChange(e));
|
|
71
73
|
}
|
|
72
|
-
onTemplateNodeUpdated(
|
|
73
|
-
this.currentNode =
|
|
74
|
+
onTemplateNodeUpdated(e) {
|
|
75
|
+
this.currentNode = e, this._setFormValues();
|
|
74
76
|
}
|
|
75
77
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
76
78
|
async onRender() {
|
|
77
|
-
const
|
|
79
|
+
const e = await _(
|
|
78
80
|
"/unsubscribe-groups/unsubscribe-list"
|
|
79
|
-
), s =
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}))
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
81
|
+
), s = {
|
|
82
|
+
name: this.api.translate("Pixel Tracking Opt-in"),
|
|
83
|
+
sendGridId: I
|
|
84
|
+
}, u = [h(), ...e.data], c = (o) => ({
|
|
85
|
+
[t.SELECT_ITEM.text]: o.name,
|
|
86
|
+
[t.SELECT_ITEM.value]: o.sendGridId
|
|
87
|
+
}), d = (o) => ({
|
|
88
|
+
[t.SELECT_ITEM.text]: o,
|
|
89
|
+
[t.SELECT_ITEM.value]: `header:${o}`,
|
|
90
|
+
[t.SELECT_ITEM.disabled]: !0
|
|
91
|
+
}), l = [
|
|
92
|
+
d(this.api.translate("OPT-IN SELECTION")),
|
|
93
|
+
c(s),
|
|
94
|
+
d(this.api.translate("UNSUBSCRIBE GROUPS")),
|
|
95
|
+
...u.map(c)
|
|
96
|
+
];
|
|
97
|
+
this.unsubList = [s, ...u], this.api.setUIEAttribute(
|
|
98
|
+
E,
|
|
99
|
+
t.SELECTPICKER.items,
|
|
100
|
+
l
|
|
87
101
|
), this._setFormValues(), this._listenToFormUpdates();
|
|
88
102
|
}
|
|
89
103
|
}
|
|
90
104
|
export {
|
|
91
105
|
b as CONTROL_BLOCK_ID,
|
|
92
|
-
|
|
106
|
+
G as RadioButtonControl
|
|
93
107
|
};
|
|
@@ -19,6 +19,8 @@ export declare const PRODUCT_TYPE_URL_SEGMENTS: {
|
|
|
19
19
|
};
|
|
20
20
|
export declare const INSIDER_ID = "iid";
|
|
21
21
|
export declare const DEFAULT_UNSUBSCRIBE_GROUP_SEND_GRID_ID = "G";
|
|
22
|
+
export declare const PIXEL_TRACKING_SEND_GRID_ID = "P";
|
|
23
|
+
export declare const UNSUBSCRIBE_SENTINEL_SEND_GRID_IDS: string[];
|
|
22
24
|
/**
|
|
23
25
|
* Get the default unsubscribe group lazily so the translated name resolves at access time.
|
|
24
26
|
* Must be called within a Vue component context or after Pinia is initialized.
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* - `trending` → `trendingProducts` (id 40, path `trending`)
|
|
9
9
|
* - `mostValuable` → `mostValuableOfPartner` (id 46, path `most-valuable`)
|
|
10
10
|
* - `topSellers` → `mostPurchased` (id 62, path `top-sellers`)
|
|
11
|
+
* - `mostViewed` → `mostPopular` (id 61, path `most-popular`)
|
|
11
12
|
*
|
|
12
13
|
* Used at two boundaries:
|
|
13
14
|
* 1. The migrator (`settingsMapper`), so freshly migrated node configs carry
|
|
@@ -39,6 +39,18 @@ ue-dropdown .service-element.padding-t-3 {
|
|
|
39
39
|
color: var(--guido-color-primary-500);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/*
|
|
43
|
+
* SD-145233: the pixel-tracking preference dropdown has no native option groups,
|
|
44
|
+
* so its section titles are rendered as disabled items. Present them as
|
|
45
|
+
* non-interactive group headers instead of options: no hover/cursor affordance
|
|
46
|
+
* and a little extra vertical spacing.
|
|
47
|
+
*/
|
|
48
|
+
.dropdown__menu .dropdown__item.disabled {
|
|
49
|
+
padding-top: 14px;
|
|
50
|
+
padding-bottom: 8px;
|
|
51
|
+
pointer-events: none;
|
|
52
|
+
}
|
|
53
|
+
|
|
42
54
|
.menu {
|
|
43
55
|
padding: 8px 0px;
|
|
44
56
|
}
|
|
@@ -2,15 +2,16 @@ import { useActionsApi as P } from "../composables/useActionsApi.js";
|
|
|
2
2
|
import { useHtmlCompiler as w } from "../composables/useHtmlCompiler.js";
|
|
3
3
|
import { DEFAULT_CURRENCY as l, DEFAULT_NODE_CONFIG as i } from "../extensions/Blocks/Recommendation/constants/defaultConfig.js";
|
|
4
4
|
import { useRecommendationExtensionStore as b } from "../extensions/Blocks/Recommendation/store/recommendation.js";
|
|
5
|
+
import { mapLegacyStrategy as E } from "../extensions/Blocks/Recommendation/utils/legacyStrategyMap.js";
|
|
5
6
|
import { DATA_ATTRIBUTES as h } from "../extensions/Blocks/Unsubscribe/utils/constants.js";
|
|
6
|
-
import { parsePageList as
|
|
7
|
-
import { useDynamicContentStore as
|
|
8
|
-
import { useUnsubscribeStore as
|
|
9
|
-
function
|
|
7
|
+
import { parsePageList as H } from "../extensions/Blocks/Unsubscribe/utils/utils.js";
|
|
8
|
+
import { useDynamicContentStore as U } from "../stores/dynamic-content.js";
|
|
9
|
+
import { useUnsubscribeStore as F } from "../stores/unsubscribe.js";
|
|
10
|
+
function L(s) {
|
|
10
11
|
const o = new DOMParser().parseFromString(s, "text/html").querySelectorAll(`[${h.PAGE_LIST}]`), t = [];
|
|
11
|
-
return o.forEach((
|
|
12
|
-
const
|
|
13
|
-
|
|
12
|
+
return o.forEach((a) => {
|
|
13
|
+
const n = a.getAttribute(h.PAGE_LIST);
|
|
14
|
+
n && t.push(...H(n));
|
|
14
15
|
}), [...new Set(t)];
|
|
15
16
|
}
|
|
16
17
|
async function R(s) {
|
|
@@ -20,8 +21,8 @@ async function R(s) {
|
|
|
20
21
|
const o = b();
|
|
21
22
|
m.forEach((t) => {
|
|
22
23
|
var c, p, g, f, r;
|
|
23
|
-
const
|
|
24
|
-
if (!Number.isFinite(
|
|
24
|
+
const a = t.getAttribute("recommendation-id"), n = a ? Number(a) : NaN;
|
|
25
|
+
if (!Number.isFinite(n))
|
|
25
26
|
return;
|
|
26
27
|
const d = t.getAttribute("esd-ext-config");
|
|
27
28
|
if (!d)
|
|
@@ -35,7 +36,10 @@ async function R(s) {
|
|
|
35
36
|
if (!e || typeof e != "object" || Array.isArray(e))
|
|
36
37
|
return;
|
|
37
38
|
const y = {
|
|
38
|
-
strategy
|
|
39
|
+
// Normalize legacy strategy keys (e.g. `mostViewed` → `mostPopular`) so
|
|
40
|
+
// already-saved blocks that never re-run the migrator don't emit a
|
|
41
|
+
// strategy-less campaign URL. `||` also catches '' / undefined (SD-144882).
|
|
42
|
+
strategy: E(e.strategy) || i.strategy,
|
|
39
43
|
language: e.language ?? i.language,
|
|
40
44
|
size: e.size ?? i.size,
|
|
41
45
|
// Spread the default arrays so each block gets a fresh reference
|
|
@@ -49,7 +53,7 @@ async function R(s) {
|
|
|
49
53
|
currencyDecimalSeparator: ((f = e.currency) == null ? void 0 : f.decimalSeparator) ?? l.decimalSeparator,
|
|
50
54
|
currencyThousandSeparator: ((r = e.currency) == null ? void 0 : r.thousandSeparator) ?? l.thousandSeparator
|
|
51
55
|
};
|
|
52
|
-
o.seedBlockUrlConfig(
|
|
56
|
+
o.seedBlockUrlConfig(n, y);
|
|
53
57
|
});
|
|
54
58
|
try {
|
|
55
59
|
await o.fetchRecommendationCreateData();
|
|
@@ -60,8 +64,8 @@ async function R(s) {
|
|
|
60
64
|
);
|
|
61
65
|
}
|
|
62
66
|
}
|
|
63
|
-
const
|
|
64
|
-
const s =
|
|
67
|
+
const G = () => {
|
|
68
|
+
const s = U(), u = F(), { getCompiledEmail: m, getTemplateData: o } = P(), { compileHtml: t, compileAmpHtml: a } = w();
|
|
65
69
|
return {
|
|
66
70
|
prepareTemplateDetails: async () => {
|
|
67
71
|
const { html: d, ampHtml: e = "", ampErrors: y = [] } = await m({
|
|
@@ -69,7 +73,7 @@ const v = () => {
|
|
|
69
73
|
resetDataSavedFlag: !1
|
|
70
74
|
}), { html: c, css: p, syncModulesIds: g = [] } = await o();
|
|
71
75
|
u.selectedUnsubscribePages.length && await u.fetchTemplates(), await R(c);
|
|
72
|
-
const { compiledHtml: f, stats: r, appliedRules: A } = t(d), C = e &&
|
|
76
|
+
const { compiledHtml: f, stats: r, appliedRules: A } = t(d), C = e && a(e).compiledHtml, T = s.getSelectedDynamicContentList, D = b(), S = L(c);
|
|
73
77
|
return console.debug("HTML Compilation Stats:", {
|
|
74
78
|
originalSize: r.originalSize,
|
|
75
79
|
compiledSize: r.compiledSize,
|
|
@@ -97,6 +101,6 @@ const v = () => {
|
|
|
97
101
|
};
|
|
98
102
|
};
|
|
99
103
|
export {
|
|
100
|
-
|
|
101
|
-
|
|
104
|
+
L as getHtmlReferencedUnsubscribePages,
|
|
105
|
+
G as useTemplatePreparation
|
|
102
106
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@useinsider/guido",
|
|
3
|
-
"version": "3.10.0-beta.
|
|
3
|
+
"version": "3.10.0-beta.511e745",
|
|
4
4
|
"description": "Guido is a Vue + TypeScript wrapper for Email Plugin. Easily embed the email editor in your Vue applications.",
|
|
5
5
|
"main": "./dist/guido.umd.cjs",
|
|
6
6
|
"module": "./dist/library.js",
|