@useinsider/guido 3.7.2-beta.7b4f9d0 → 3.7.2-beta.a787136

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.
@@ -1,16 +1,16 @@
1
- import { useRecommendation as N } from "../../composables/useRecommendation.js";
2
- import { DUMMY_IMAGE_MAPPINGS as M, REGEX as d, VerticalOrientation as $, CSS as n, ATTRIBUTES as p, CONDITIONS as T, HTML as g } from "../../enums/recommendation.js";
3
- import { prepareRecommendationBlocks as O } from "./utils/recommendationCompilerUtils.js";
4
- const U = [
1
+ import { useRecommendation as h } from "../../composables/useRecommendation.js";
2
+ import { DUMMY_IMAGE_MAPPINGS as N, REGEX as T, VerticalOrientation as M, CSS as E, ATTRIBUTES as A, CONDITIONS as y, HTML as C } from "../../enums/recommendation.js";
3
+ import { prepareRecommendationBlocks as x } from "./utils/recommendationCompilerUtils.js";
4
+ const w = [
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: (o) => {
10
- let e = o;
11
- return Object.entries(M).forEach(([, r]) => {
12
- Object.entries(r).forEach(([t, i]) => {
13
- e = e.replaceAll(i, `{{${t}}}`);
9
+ processor: (c) => {
10
+ let e = c;
11
+ return Object.entries(N).forEach(([, l]) => {
12
+ Object.entries(l).forEach(([n, s]) => {
13
+ e = e.replaceAll(s, `{{${n}}}`);
14
14
  });
15
15
  }), e;
16
16
  },
@@ -41,21 +41,21 @@ const U = [
41
41
  id: "add-recommendation-unresponsive-css",
42
42
  description: "Adding recommendation unresponsive css",
43
43
  type: "custom",
44
- processor: (o) => {
45
- const { calculateCardWidth: e, getRecommendationCampaignData: r } = N();
46
- let t = o;
47
- const i = t.match(d.ID);
48
- if (i) {
49
- const s = [];
50
- if (i.forEach((c) => {
51
- const m = /recommendation-id="(.*?)"/i.exec(c), E = m ? m[1].trim() : "", u = r(E);
52
- u.textTrimming && u.orientation === $ && s.push(e(u));
53
- }), s.length) {
54
- const c = `width:${Math.min(...s)}px!important;`;
55
- t = t.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);
44
+ processor: (c) => {
45
+ const { calculateCardWidth: e, getRecommendationCampaignData: l } = h();
46
+ let n = c;
47
+ const s = n.match(T.ID);
48
+ if (s) {
49
+ const a = [];
50
+ if (s.forEach((i) => {
51
+ const u = /recommendation-id="(.*?)"/i.exec(i), _ = u ? u[1].trim() : "", R = l(_);
52
+ R.textTrimming && R.orientation === M && a.push(e(R));
53
+ }), a.length) {
54
+ const i = `width:${Math.min(...a)}px!important;`;
55
+ n = n.replace(E.REGULAR_NAME_HEIGHT, `${E.TRIMMED_NAME_HEIGHT} ${i} ${E.ELLIPSIS}`).replace(E.REGULAR_NAME_CONTAINER_HEIGHT, E.TRIMMED_NAME_CONTAINER_CSS).replace(E.RESPONSIVE_NAME_SIZE, `${E.RESPONSIVE_NAME_HEIGHT} ${i} ${E.ELLIPSIS}`).replace(E.RESPONSIVE_NAME_CONTAINER_HEIGHT, E.TRIMMED_RESPONSIVE_NAME_CONTAINER_CSS);
56
56
  }
57
57
  }
58
- return t;
58
+ return n;
59
59
  },
60
60
  priority: 52
61
61
  },
@@ -63,34 +63,34 @@ 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: (o) => O(o),
66
+ processor: (c) => x(c),
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: (o) => {
74
- let e = o;
75
- const r = e.match(d.ATTRIBUTE_PARAGRAPH), { getRecommendationCampaignData: t } = N();
76
- return r !== null && r.forEach((i) => {
77
- const s = i.match(d.CUSTOM_FIELD);
78
- if (!s)
73
+ processor: (c) => {
74
+ let e = c;
75
+ const l = e.match(T.ATTRIBUTE_PARAGRAPH), { getRecommendationCampaignData: n } = h();
76
+ return l !== null && l.forEach((s) => {
77
+ const a = s.match(T.CUSTOM_FIELD);
78
+ if (!a)
79
79
  return;
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
- if (!m || !E || !u)
80
+ const [i] = a, u = i.match(T.CUSTOM_FIELD_INDEXES_PART), _ = i.match(T.CUSTOM_FIELD_NAME_PART), R = s.match(T.ATTRIBUTE_PARAGRAPH_START_TAG);
81
+ if (!u || !_ || !R)
82
82
  return;
83
- const [A] = m, [I] = E, [R] = u, b = I.substring(1, I.length - 2), S = R.match(d.COMPOSITION) !== null;
84
- let a = c;
85
- if (S) {
86
- const f = A.substring(2, A.length - 3), l = t(f);
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}`));
83
+ const [b] = u, [I] = _, [d] = R, o = I.substring(1, I.length - 2), r = d.match(T.COMPOSITION) !== null;
84
+ let t = i;
85
+ if (r) {
86
+ const S = b.substring(2, b.length - 3), m = n(S);
87
+ o === A.OMNIBUS_PRICE && (m.priceBeforeTextValue && (t = `${m.priceBeforeTextValue}${t}`), m.priceAfterTextValue && (t = `${t}${m.priceAfterTextValue}`)), o === A.OMNIBUS_DISCOUNT && (m.discountBeforeTextValue && (t = `${m.discountBeforeTextValue}${t}`), m.discountAfterTextValue && (t = `${t}${m.discountAfterTextValue}`));
88
88
  }
89
- const _ = A.substring(2);
90
- let y = "";
91
- b in T.IF && (y = T.IF[b].replaceAll(`{${p.DISCOUNT}}`, `${_}${p.DISCOUNT}`).replaceAll(`{${p.OMNIBUS_DISCOUNT}}`, `${_}${p.OMNIBUS_DISCOUNT}`).replaceAll(`{${p.OMNIBUS_PRICE}}`, `${_}${p.OMNIBUS_PRICE}`));
92
- const C = `${R}${a}${g.PARAGRAPH_END_TAG}`, h = `${y}${S ? C : i}${T.ELSE}${R}${g.PARAGRAPH_END_TAG}${T.END_IF}`;
93
- e = e.replace(i, h);
89
+ const p = b.substring(2);
90
+ let f = "";
91
+ o in y.IF && (f = y.IF[o].replaceAll(`{${A.DISCOUNT}}`, `${p}${A.DISCOUNT}`).replaceAll(`{${A.OMNIBUS_DISCOUNT}}`, `${p}${A.OMNIBUS_DISCOUNT}`).replaceAll(`{${A.OMNIBUS_PRICE}}`, `${p}${A.OMNIBUS_PRICE}`));
92
+ const g = `${d}${t}${C.PARAGRAPH_END_TAG}`, $ = `${f}${r ? g : s}${y.ELSE}${d}${C.PARAGRAPH_END_TAG}${y.END_IF}`;
93
+ e = e.replace(s, $);
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: (o) => {
113
+ processor: (c) => {
114
114
  const e = /\s+(?:esd-extension-block-id|data-attribute-type|data-visibility|data-text-before|data-text-after|product-attr|composition)="[^"]*"/g;
115
- return o.replace(
115
+ return c.replace(
116
116
  /<!--REC_START-->([\s\S]*?)<!--REC_END-->/g,
117
- (r, t) => `<!--REC_START-->${t.replace(e, "")}<!--REC_END-->`
117
+ (l, n) => `<!--REC_START-->${n.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: (o) => {
127
- let e = o.replace(
126
+ processor: (c) => {
127
+ let e = c.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: (o) => {
140
- let e = o;
139
+ processor: (c) => {
140
+ let e = c;
141
141
  return e = e.replace(
142
142
  /<tr[^>]*class="ins-recommendation-mobile-row"[^>]*><\/tr>/g,
143
143
  ""
@@ -146,50 +146,75 @@ const U = [
146
146
  ""
147
147
  ), e = e.replace(
148
148
  /@media[^{]*max-width\s*:\s*480px[^{]*\{((?:[^{}]*\{[^{}]*\})*[^{}]*)\}/g,
149
- (r, t) => {
150
- const i = t.match(/[^{}]+\{[^{}]*\}/g) || [], s = /ins-recommendation|product-image-cell|button-cell|product-info-cell/;
151
- return i.every((m) => s.test(m)) ? "" : r;
149
+ (l, n) => {
150
+ const s = n.match(/[^{}]+\{[^{}]*\}/g) || [], a = /ins-recommendation|product-image-cell|button-cell|product-info-cell/;
151
+ return s.every((u) => a.test(u)) ? "" : l;
152
152
  }
153
153
  )), e;
154
154
  },
155
155
  priority: 57
156
156
  },
157
157
  {
158
- id: "protect-gmail-button-link-color",
159
- // Gmail overrides link colors with `.ii a[href] { color: #15c }`. Force
160
- // `!important` on es-button anchor colors so the intended button text color
161
- // wins. Kept INLINE (never moved into a <style> class) so it survives Gmail's
162
- // clipping — "view entire message" strips <style> blocks but keeps inline styles.
163
- // (SD-142395: split out of the removed deduplicate-inline-styles rule.)
164
- description: "Force !important on es-button link color to defeat Gmail link-color override",
158
+ id: "deduplicate-inline-styles",
159
+ description: "Replace repeated inline styles with CSS class references within recommendation blocks",
165
160
  type: "custom",
166
- processor: (o) => o.replace(
167
- /<a\b[^>]*\bes-button\b[^>]*>/g,
168
- (e) => e.replace(
169
- /([;"]color:)([^;"]+)/g,
170
- (r, t, i) => i.includes("!important") ? r : `${t}${i} !important`
171
- )
172
- ),
173
- priority: 58
174
- },
175
- {
176
- id: "minify-recommendation-whitespace",
177
- // SD-142395: shrink the compiled recommendation block to keep emails under
178
- // Gmail's ~102KB clip threshold. The editor templates emit deeply-indented
179
- // markup that the P48 DOMParser round-trip preserves, and nothing else in the
180
- // pipeline minifies it. Scoped to REC_START/REC_END so it only touches
181
- // recommendation markup, and strips those markers last (relocated here from the
182
- // removed deduplicate-inline-styles rule). Render-critical styles are left inline
183
- // rather than classed, so they survive Gmail clipping.
184
- description: "Collapse whitespace inside recommendation blocks and strip boundary markers",
185
- type: "custom",
186
- processor: (o) => {
187
- const e = (r) => r.replace(/>\s+</g, "><").replace(/<[^>]+>/g, (t) => t.replace(/\s+/g, " "));
188
- return o.replace(/<!--REC_START-->([\s\S]*?)<!--REC_END-->/g, (r, t) => e(t)).replaceAll("<!--REC_START-->", "").replaceAll("<!--REC_END-->", "");
161
+ processor: (c) => {
162
+ const e = c.replace(
163
+ /<a\b[^>]*\bes-button\b[^>]*>/g,
164
+ (o) => o.replace(
165
+ /([;"]color:)([^;"]+)/g,
166
+ (r, t, p) => p.includes("!important") ? r : `${t}${p} !important`
167
+ )
168
+ ), l = /<!--REC_START-->([\s\S]*?)<!--REC_END-->/g, n = / style="([^"]*)"/g, s = /* @__PURE__ */ new Map();
169
+ let a = l.exec(e);
170
+ for (; a !== null; ) {
171
+ let o = n.exec(a[1]);
172
+ for (; o !== null; ) {
173
+ const [, r] = o;
174
+ s.set(r, (s.get(r) || 0) + 1), o = n.exec(a[1]);
175
+ }
176
+ n.lastIndex = 0, a = l.exec(e);
177
+ }
178
+ const i = /* @__PURE__ */ new Map(), u = [];
179
+ let _ = 0;
180
+ if (s.forEach((o, r) => {
181
+ if (!r.includes("v-text-anchor") && o >= 6) {
182
+ const t = `rc${_++}`, p = r.endsWith(";") ? r : `${r};`;
183
+ i.set(r, t), u.push(`.${t}{${p}}`);
184
+ }
185
+ }), i.size === 0) {
186
+ let o = e;
187
+ return o = o.replaceAll("<!--REC_START-->", ""), o = o.replaceAll("<!--REC_END-->", ""), o;
188
+ }
189
+ const R = (o) => o.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), b = (o, r) => `${o.slice(0, -1)} ${r}"`, I = /* @__PURE__ */ new Map();
190
+ i.forEach((o, r) => {
191
+ const t = R(r);
192
+ I.set(r, {
193
+ caseA: new RegExp(`(class="[^"]*")((?:[^>]*?)) style="${t}"`, "g"),
194
+ caseB: new RegExp(` style="${t}"((?:[^>]*?))(class="[^"]*")`, "g")
195
+ });
196
+ });
197
+ let d = e.replace("</style>", `${u.join("")}</style>`);
198
+ return d = d.replace(
199
+ /<!--REC_START-->([\s\S]*?)<!--REC_END-->/g,
200
+ (o, r) => {
201
+ let t = r;
202
+ return i.forEach((p, f) => {
203
+ const g = I.get(f);
204
+ t = t.replace(
205
+ g.caseA,
206
+ ($, S, m) => b(S, p) + m
207
+ ), t = t.replace(
208
+ g.caseB,
209
+ ($, S, m) => S + b(m, p)
210
+ ), t = t.replaceAll(` style="${f}"`, ` class="${p}"`);
211
+ }), t;
212
+ }
213
+ ), d = d.replaceAll("<!--REC_START-->", ""), d = d.replaceAll("<!--REC_END-->", ""), d;
189
214
  },
190
- priority: 99
215
+ priority: 58
191
216
  }
192
217
  ];
193
218
  export {
194
- U as recommendationCompilerRules
219
+ w as recommendationCompilerRules
195
220
  };
@@ -1,19 +1,20 @@
1
1
  var S = Object.defineProperty;
2
- var L = (c, o, e) => o in c ? S(c, o, { enumerable: !0, configurable: !0, writable: !0, value: e }) : c[o] = e;
3
- var a = (c, o, e) => L(c, typeof o != "symbol" ? o + "" : o, e);
4
- import { useToaster as f } from "../../../composables/useToaster.js";
2
+ var f = (c, o, e) => o in c ? S(c, o, { enumerable: !0, configurable: !0, writable: !0, value: e }) : c[o] = e;
3
+ var a = (c, o, e) => f(c, typeof o != "symbol" ? o + "" : o, e);
4
+ import { useToaster as L } from "../../../composables/useToaster.js";
5
5
  import { ToasterTypeOptions as A } from "../../../enums/toaster.js";
6
6
  import { PAGE_TYPES as h } from "../../../enums/unsubscribe.js";
7
- import { useUnsubscribeStore as u } from "../../../stores/unsubscribe.js";
8
- import { Block as y, BlockCompositionType as T, ContextActionType as k, ModificationDescription as d, BlockType as I } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
9
- import { getDefaultTemplate as v } from "./template.js";
7
+ import { useEditorStore as y } from "../../../stores/editor.js";
8
+ import { useUnsubscribeStore as l } from "../../../stores/unsubscribe.js";
9
+ import { Block as T, BlockCompositionType as I, ContextActionType as B, ModificationDescription as d, BlockType as v } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
10
+ import { getDefaultTemplate as C } from "./template.js";
10
11
  import { UNSUBSCRIBE_BLOCK_SELECTOR as m, DATA_ATTRIBUTES as n, UNSUBSCRIBE_EVENTS as b } from "./utils/constants.js";
11
- import { parsePageList as B } from "./utils/utils.js";
12
- const C = "unsubscribe-block", E = 'a[data-unsubscribe-link="true"]', N = "{{ins-unsubscribe-link}}", U = "https://academy.insiderone.com/docs/adding-unsubscribe-pages-into-emails", R = "Removing the unsubscribe text leaves an empty block, but an active unsubscribe link is required. Undo your last action to restore the text, or delete the unsubscribe block entirely.", D = {
12
+ import { parsePageList as _ } from "./utils/utils.js";
13
+ const N = "unsubscribe-block", E = 'a[data-unsubscribe-link="true"]', U = "{{ins-unsubscribe-link}}", R = "https://academy.insiderone.com/docs/adding-unsubscribe-pages-into-emails", D = "Removing the unsubscribe text leaves an empty block, but an active unsubscribe link is required. Undo your last action to restore the text, or delete the unsubscribe block entirely.", w = {
13
14
  [h.GLOBAL_UNSUBSCRIBE]: "{{ins-global-unsubscribe-link}}",
14
15
  [h.SUBSCRIPTION_PREFERENCE_CENTER]: "{{ins-preferences-unsubscribe-link}}"
15
- }, w = 3;
16
- class H extends y {
16
+ }, P = 3;
17
+ class W extends T {
17
18
  constructor() {
18
19
  super();
19
20
  a(this, "selectEventListener", null);
@@ -29,13 +30,13 @@ class H extends y {
29
30
  a(this, "guardAttemptsByBlockId", /* @__PURE__ */ new Map());
30
31
  }
31
32
  getId() {
32
- return C;
33
+ return N;
33
34
  }
34
35
  getIcon() {
35
36
  return "unsubscribe-icon";
36
37
  }
37
38
  getBlockCompositionType() {
38
- return T.BLOCK;
39
+ return I.BLOCK;
39
40
  }
40
41
  getName() {
41
42
  return this.api.translate("Unsubscribe Block");
@@ -44,15 +45,16 @@ class H extends y {
44
45
  return this.api.translate("Unsubscribe Block Description");
45
46
  }
46
47
  getTemplate() {
47
- return v();
48
+ return C();
48
49
  }
49
50
  getContextActionsIds() {
50
- return [k.MOVE, k.REMOVE];
51
+ return [B.MOVE, B.REMOVE];
51
52
  }
52
53
  onSelect(e) {
53
- this.currentNode = e;
54
+ if (this.currentNode = e, y().isPreviewModeOpen)
55
+ return;
54
56
  const t = this._getOrAssignBlockId(e);
55
- t && this.linkStateByBlockId.set(t, this._hasUnsubscribeLink(e)), !("getAttribute" in e && e.getAttribute("data-migration")) && (this._resetStoreState(), this._loadBlockState(e), this._setupSelectEventListener(), this._setupCancelEventListener(), this._checkExistingBlocks(), this._openDrawer());
57
+ t && this.linkStateByBlockId.set(t, this._hasUnsubscribeLink(e)), !("getAttribute" in e && e.getAttribute("data-migration")) && (this._resetStoreState(), t && (l().pendingBlockId = t), this._loadBlockState(e), this._setupSelectEventListener(), this._setupCancelEventListener(t), this._checkExistingBlocks(), this._openDrawer());
56
58
  }
57
59
  onCreated(e) {
58
60
  this._ensureLeadingTextGuard(e);
@@ -107,9 +109,9 @@ class H extends y {
107
109
  const g = this._getOrAssignBlockId(e);
108
110
  if (!g)
109
111
  return;
110
- const _ = this.guardAttemptsByBlockId.get(g) ?? 0;
111
- if (!(_ >= w)) {
112
- this.guardAttemptsByBlockId.set(g, _ + 1);
112
+ const k = this.guardAttemptsByBlockId.get(g) ?? 0;
113
+ if (!(k >= P)) {
114
+ this.guardAttemptsByBlockId.set(g, k + 1);
113
115
  try {
114
116
  this.api.getDocumentModifier().modifyHtml(r).prepend("&nbsp;").apply(new d("Ensure unsubscribe link text guard"));
115
117
  } catch (p) {
@@ -154,8 +156,8 @@ class H extends y {
154
156
  const t = this.api.getDocumentRoot();
155
157
  t && "querySelectorAll" in t && t.querySelectorAll(m).forEach((r) => {
156
158
  if ("getAttribute" in r) {
157
- const i = r.getAttribute(n.BLOCK_ID), l = i ? parseInt(i) : 0;
158
- l > e && (e = l);
159
+ const i = r.getAttribute(n.BLOCK_ID), u = i ? parseInt(i) : 0;
160
+ u > e && (e = u);
159
161
  }
160
162
  });
161
163
  } catch {
@@ -164,14 +166,14 @@ class H extends y {
164
166
  }
165
167
  _warnLinkRemoved() {
166
168
  try {
167
- const { showToaster: e } = f();
169
+ const { showToaster: e } = L();
168
170
  e({
169
171
  type: A.Warning,
170
- message: this.api.translate(R),
172
+ message: this.api.translate(D),
171
173
  actionButton: {
172
174
  text: this.api.translate("Visit Academy"),
173
175
  onClick: () => {
174
- window.open(U, "_blank", "noopener,noreferrer");
176
+ window.open(R, "_blank", "noopener,noreferrer");
175
177
  }
176
178
  }
177
179
  });
@@ -188,9 +190,10 @@ class H extends y {
188
190
  _removeSelectEventListener() {
189
191
  this.selectEventListener && (document.removeEventListener(b.SELECT, this.selectEventListener), this.selectEventListener = null);
190
192
  }
191
- _setupCancelEventListener() {
192
- this._removeCancelEventListener(), this.cancelEventListener = () => {
193
- this._handleCancel();
193
+ _setupCancelEventListener(e) {
194
+ this._removeCancelEventListener(), this.cancelEventListener = (t) => {
195
+ const { detail: s } = t, r = (s == null ? void 0 : s.blockId) ?? null;
196
+ r !== null && r !== e || this._handleCancel();
194
197
  }, document.addEventListener(b.CANCEL, this.cancelEventListener);
195
198
  }
196
199
  _removeCancelEventListener() {
@@ -200,7 +203,7 @@ class H extends y {
200
203
  try {
201
204
  if (!this.currentNode)
202
205
  return;
203
- this.api.getDocumentModifier().modifyHtml(this.currentNode).replaceWith(`<${I.EMPTY_CONTAINER}/>`).apply(new d("Removed unsubscribe block due to cancel"));
206
+ this.api.getDocumentModifier().modifyHtml(this.currentNode).replaceWith(`<${v.EMPTY_CONTAINER}/>`).apply(new d("Removed unsubscribe block due to cancel"));
204
207
  } catch (e) {
205
208
  console.warn("[UnsubscribeBlock] Failed to remove unsubscribe block:", e);
206
209
  }
@@ -218,19 +221,19 @@ class H extends y {
218
221
  this.api.getDocumentModifier().modifyHtml(s).setAttribute("href", r).apply(new d(`Updated unsubscribe link to ${r}`)), this.api.getDocumentModifier().modifyHtml(this.currentNode).setAttribute(n.PAGE_TYPE, e.toString()).setAttribute(n.PAGE_LIST, t).apply(new d("Updated unsubscribe block metadata"));
219
222
  }
220
223
  _getMergeTag(e) {
221
- return D[e] ?? N;
224
+ return w[e] ?? U;
222
225
  }
223
226
  _openDrawer() {
224
227
  if (!(this.currentNode && this.currentNode.getAttribute("data-unsubscribe-page-type")))
225
228
  try {
226
- const e = u();
229
+ const e = l();
227
230
  e.typeSelectionDrawerStatus = !0;
228
231
  } catch (e) {
229
232
  console.error("[UnsubscribeBlock] Failed to open drawer:", e);
230
233
  }
231
234
  }
232
235
  _checkExistingBlocks() {
233
- const e = u();
236
+ const e = l();
234
237
  e.isGlobalUnsubscribeDisabled = !1, e.isSubscriptionPreferencesCenterDisabled = !1, this.api.getDocumentRoot().querySelectorAll(m).forEach((s) => {
235
238
  if ("getAttribute" in s) {
236
239
  const r = s.getAttribute(n.PAGE_TYPE);
@@ -247,11 +250,11 @@ class H extends y {
247
250
  const t = e.getAttribute(n.PAGE_TYPE), s = e.getAttribute(n.PAGE_LIST);
248
251
  if (!t || !s)
249
252
  return;
250
- const r = u(), i = Number(t), l = B(s);
251
- await r.fetchTemplates(), r.setCollectionWithoutAutoSelection(i), r.loadSelectedTemplates(l);
253
+ const r = l(), i = Number(t), u = _(s);
254
+ await r.fetchTemplates(), r.setCollectionWithoutAutoSelection(i), r.loadSelectedTemplates(u);
252
255
  }
253
256
  _resetStoreState() {
254
- u().$reset();
257
+ l().$reset();
255
258
  }
256
259
  _removeBlockTemplatesFromStore(e) {
257
260
  if (!("getAttribute" in e))
@@ -259,11 +262,11 @@ class H extends y {
259
262
  const t = e.getAttribute(n.PAGE_LIST);
260
263
  if (!t)
261
264
  return;
262
- const s = u(), r = B(t);
265
+ const s = l(), r = _(t);
263
266
  s.removeUnsubscribePages(r);
264
267
  }
265
268
  }
266
269
  export {
267
- C as UNSUBSCRIBE_BLOCK_ID,
268
- H as UnsubscribeBlock
270
+ N as UNSUBSCRIBE_BLOCK_ID,
271
+ W as UnsubscribeBlock
269
272
  };
@@ -1,18 +1,19 @@
1
1
  var T = Object.defineProperty;
2
- var p = (o, s, e) => s in o ? T(o, s, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[s] = e;
3
- var c = (o, s, e) => p(o, typeof s != "symbol" ? s + "" : s, e);
2
+ var p = (a, s, e) => s in a ? T(a, s, { enumerable: !0, configurable: !0, writable: !0, value: e }) : a[s] = e;
3
+ var c = (a, s, e) => p(a, typeof s != "symbol" ? s + "" : s, e);
4
+ import { useEditorStore as _ } from "../../../stores/editor.js";
4
5
  import { useUnsubscribeStore as l } from "../../../stores/unsubscribe.js";
5
- import { Control as _, UEAttr as i, UIElementType as n } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
6
+ import { Control as g, UEAttr as i, UIElementType as n } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
6
7
  import { DATA_ATTRIBUTES as d } from "./utils/constants.js";
7
8
  import { parsePageList as h } from "./utils/utils.js";
8
- const g = "ui-elements-unsubscribe", r = {
9
+ const v = "ui-elements-unsubscribe", r = {
9
10
  SELECT_BUTTON: "selectTemplateButton",
10
11
  PREV_BUTTON: "prevButton",
11
12
  NEXT_BUTTON: "nextButton",
12
13
  COUNTER_TEXT: "counterText",
13
14
  PREVIEW_IMAGE: "previewImage"
14
15
  };
15
- class B extends _ {
16
+ class w extends g {
16
17
  constructor() {
17
18
  super(...arguments);
18
19
  c(this, "currentPreviewIndex", 0);
@@ -22,7 +23,7 @@ class B extends _ {
22
23
  c(this, "lastParsedAttribute");
23
24
  }
24
25
  getId() {
25
- return g;
26
+ return v;
26
27
  }
27
28
  getTemplate() {
28
29
  return `
@@ -59,10 +60,12 @@ class B extends _ {
59
60
  this.api.onValueChanged(r.NEXT_BUTTON, () => this._onNextClick())
60
61
  );
61
62
  }
62
- _onButtonClick() {
63
+ async _onButtonClick() {
63
64
  try {
65
+ if (_().isPreviewModeOpen)
66
+ return;
64
67
  const e = l();
65
- this._reseedSelectionFromBlock(), e.activeType = e.getSelectedCollection[this.currentPreviewIndex], e.pageSelectionUpdateStatus = !0, e.pageSelectionDrawerStatus = !0;
68
+ await e.fetchTemplates(!0), this._reseedSelectionFromBlock(), e.activeType = e.getSelectedCollection[this.currentPreviewIndex], e.pageSelectionUpdateStatus = !0, e.pageSelectionDrawerStatus = !0;
66
69
  } catch (e) {
67
70
  console.error("[UnsubscribeControl] Failed to open drawer:", e);
68
71
  }
@@ -71,8 +74,8 @@ class B extends _ {
71
74
  const e = l();
72
75
  if (e.$reset(), !this.currentNode || !("getAttribute" in this.currentNode))
73
76
  return;
74
- const t = this.currentNode.getAttribute(d.PAGE_TYPE), a = this.currentNode.getAttribute(d.PAGE_LIST);
75
- !t || !a || (e.setCollectionWithoutAutoSelection(Number(t)), e.loadSelectedTemplates(h(a)));
77
+ const t = this.currentNode.getAttribute(d.PAGE_TYPE), o = this.currentNode.getAttribute(d.PAGE_LIST);
78
+ !t || !o || (e.setCollectionWithoutAutoSelection(Number(t)), e.loadSelectedTemplates(h(o)));
76
79
  }
77
80
  _onPrevClick() {
78
81
  this.currentPreviewIndex > 0 && (this.currentPreviewIndex--, this._updatePreview(), this._updateCounter());
@@ -100,8 +103,8 @@ class B extends _ {
100
103
  }
101
104
  }
102
105
  _updateCounter() {
103
- const e = this.currentPreviewIndex + 1, t = this.totalTemplates, a = this.currentPreviewIndex === 0, u = this.currentPreviewIndex >= t - 1;
104
- this.api.setUIEAttribute(r.PREV_BUTTON, i.BUTTON.disabled, a), this.api.setUIEAttribute(r.NEXT_BUTTON, i.BUTTON.disabled, u), this.api.setUIEAttribute(
106
+ const e = this.currentPreviewIndex + 1, t = this.totalTemplates, o = this.currentPreviewIndex === 0, u = this.currentPreviewIndex >= t - 1;
107
+ this.api.setUIEAttribute(r.PREV_BUTTON, i.BUTTON.disabled, o), this.api.setUIEAttribute(r.NEXT_BUTTON, i.BUTTON.disabled, u), this.api.setUIEAttribute(
105
108
  r.COUNTER_TEXT,
106
109
  i.LABEL.text,
107
110
  `${this.api.translate("Showing")} ${e} ${this.api.translate("of")} ${t}`
@@ -142,8 +145,8 @@ class B extends _ {
142
145
  </${n.LABEL}>
143
146
  `;
144
147
  }
145
- _getIconButton(e, t, a) {
146
- const u = a ? `${i.BUTTON.disabled}="true"` : "";
148
+ _getIconButton(e, t, o) {
149
+ const u = o ? `${i.BUTTON.disabled}="true"` : "";
147
150
  return `
148
151
  <${n.BUTTON}
149
152
  id="${e}"
@@ -172,6 +175,6 @@ class B extends _ {
172
175
  }
173
176
  }
174
177
  export {
175
- g as UNSUBSCRIBE_CONTROL_ID,
176
- B as UnsubscribeControl
178
+ v as UNSUBSCRIBE_CONTROL_ID,
179
+ w as UnsubscribeControl
177
180
  };
package/dist/guido.css CHANGED
@@ -1 +1 @@
1
- .gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-195ab6d4]{position:relative;display:inline-block}.new-tag[data-v-195ab6d4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-195ab6d4] .guido__view-option-selection-desktop svg,[data-v-195ab6d4] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-195ab6d4] .in-segments-wrapper__button_selected,[data-v-195ab6d4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-195ab6d4] .in-tooltip-wrapper__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-64c52560]{gap:8px}.version-history__toolbar[data-v-64c52560]{gap:4px}.view-options-wrapper[data-v-d405ca59]{position:relative;display:inline-block}.new-tag[data-v-d405ca59]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-d405ca59] .guido__verion-history-view-option-selection-desktop svg,[data-v-d405ca59] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-d405ca59] .in-segments-wrapper__button_selected,[data-v-d405ca59] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-d405ca59] .in-tooltip-wrapper__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-82128f7d]{gap:4px}.header-wrapper[data-v-5c02dcc7]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-50dac6de]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-50dac6de]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-50dac6de]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-f6a8cb4c]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-f6a8cb4c]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-f6a8cb4c]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-f6a8cb4c]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-f6a8cb4c]{object-fit:cover;transform:scale(1)}[data-v-43c617a7] .guido__verion-history-view-option-selection-desktop svg,[data-v-43c617a7] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-43c617a7] .in-segments-wrapper__button_selected,[data-v-43c617a7] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-988f8da6]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-988f8da6]{min-height:504px}.iframe-wrapper[data-v-e0424e99]{width:258px}.iframe-scaled[data-v-e0424e99]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-7419ae06] .vueperslides__bullets,[data-v-796d193b] .vueperslides__bullets{pointer-events:none!important}[data-v-796d193b] .vueperslides__parallax-wrapper{height:110px!important}[data-v-cadfc82d] .vueperslides__bullets{pointer-events:none!important}[data-v-cadfc82d] .vueperslides__parallax-wrapper{height:110px!important}
1
+ .gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-195ab6d4]{position:relative;display:inline-block}.new-tag[data-v-195ab6d4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-195ab6d4] .guido__view-option-selection-desktop svg,[data-v-195ab6d4] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-195ab6d4] .in-segments-wrapper__button_selected,[data-v-195ab6d4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-195ab6d4] .in-tooltip-wrapper__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-64c52560]{gap:8px}.version-history__toolbar[data-v-64c52560]{gap:4px}.view-options-wrapper[data-v-d405ca59]{position:relative;display:inline-block}.new-tag[data-v-d405ca59]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-d405ca59] .guido__verion-history-view-option-selection-desktop svg,[data-v-d405ca59] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-d405ca59] .in-segments-wrapper__button_selected,[data-v-d405ca59] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-d405ca59] .in-tooltip-wrapper__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-82128f7d]{gap:4px}.header-wrapper[data-v-5c02dcc7]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-50dac6de]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-50dac6de]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-50dac6de]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-ec5c2ac6]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-ec5c2ac6]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-ec5c2ac6]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-ec5c2ac6]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-ec5c2ac6]{object-fit:cover;transform:scale(1)}[data-v-811cff80] .guido__verion-history-view-option-selection-desktop svg,[data-v-811cff80] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-811cff80] .in-segments-wrapper__button_selected,[data-v-811cff80] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-06afaecb]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-06afaecb]{min-height:504px}.iframe-wrapper[data-v-cbafc185]{width:258px}.iframe-scaled[data-v-cbafc185]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-7419ae06] .vueperslides__bullets,[data-v-796d193b] .vueperslides__bullets{pointer-events:none!important}[data-v-796d193b] .vueperslides__parallax-wrapper{height:110px!important}[data-v-cadfc82d] .vueperslides__bullets{pointer-events:none!important}[data-v-cadfc82d] .vueperslides__parallax-wrapper{height:110px!important}
@@ -0,0 +1,3 @@
1
+ export declare const usePreviewInteractionGuard: () => {
2
+ blockPreviewInteractions: (iframe: HTMLIFrameElement) => void;
3
+ };
@@ -1,3 +1,4 @@
1
1
  export declare const useUnsubscribeBlockValidator: () => {
2
2
  validateUnsubscribeBlockUniqueness: (html: string) => boolean;
3
+ validateUnsubscribeBlockHasTemplate: (html: string) => boolean;
3
4
  };