@useinsider/guido 3.7.1-beta.4622f87 → 3.7.1-beta.794b3fc

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 (33) hide show
  1. package/dist/components/organisms/unsubscribe/UnsubscribePageSelection.vue.js +2 -2
  2. package/dist/components/organisms/unsubscribe/UnsubscribePageSelection.vue2.js +24 -22
  3. package/dist/composables/useHtmlValidator.js +79 -73
  4. package/dist/enums/extensions/recommendationBlock.js +3 -1
  5. package/dist/enums/html-validator.js +13 -5
  6. package/dist/enums/toaster.js +1 -1
  7. package/dist/extensions/Blocks/Recommendation/block.js +35 -16
  8. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +35 -30
  9. package/dist/extensions/Blocks/Recommendation/controls/main/productLayout.js +62 -50
  10. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +208 -193
  11. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +21 -20
  12. package/dist/extensions/Blocks/Recommendation/useRecommendationBlockWarning.js +16 -0
  13. package/dist/extensions/Blocks/Recommendation/utils/recommendationBlockCount.js +9 -0
  14. package/dist/extensions/Blocks/Unsubscribe/block.js +122 -72
  15. package/dist/extensions/Blocks/Unsubscribe/control.js +33 -26
  16. package/dist/extensions/Blocks/Unsubscribe/template.js +4 -4
  17. package/dist/guido.css +1 -1
  18. package/dist/services/recommendationApi.js +31 -19
  19. package/dist/src/enums/extensions/recommendationBlock.d.ts +1 -0
  20. package/dist/src/enums/html-validator.d.ts +4 -0
  21. package/dist/src/enums/toaster.d.ts +2 -1
  22. package/dist/src/extensions/Blocks/Recommendation/block.d.ts +13 -0
  23. package/dist/src/extensions/Blocks/Recommendation/block.test.d.ts +1 -0
  24. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +1 -0
  25. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +1 -0
  26. package/dist/src/extensions/Blocks/Recommendation/useRecommendationBlockWarning.d.ts +12 -0
  27. package/dist/src/extensions/Blocks/Recommendation/utils/recommendationBlockCount.d.ts +28 -0
  28. package/dist/src/extensions/Blocks/Recommendation/utils/recommendationBlockCount.test.d.ts +1 -0
  29. package/dist/src/extensions/Blocks/Unsubscribe/block.d.ts +9 -0
  30. package/dist/src/extensions/Blocks/Unsubscribe/control.d.ts +1 -0
  31. package/dist/static/styles/components/base-input.css.js +5 -0
  32. package/dist/stores/autosave.js +6 -6
  33. package/package.json +1 -1
@@ -1,19 +1,19 @@
1
1
  import { getRecommendationFeedSourceMaps as g, getOperatorOptions as R, PriceAttributes as C } from "../../../../enums/extensions/recommendationBlock.js";
2
2
  import { useRecommendationApi as y } from "../../../../services/recommendationApi.js";
3
3
  import { useConfigStore as G } from "../../../../stores/config.js";
4
- import { defineStore as P } from "pinia";
5
- import { DEFAULT_CARDS_IN_ROW as F } from "../constants/layout.js";
6
- import { EXCLUDED_ALGORITHM_IDS as D } from "../constants/defaultConfig.js";
4
+ import { defineStore as F } from "pinia";
5
+ import { DEFAULT_MOBILE_CARDS_IN_ROW as P, DEFAULT_CARDS_IN_ROW as D } from "../constants/layout.js";
6
+ import { EXCLUDED_ALGORITHM_IDS as w } from "../constants/defaultConfig.js";
7
7
  import { getDefaultProducts as S } from "../templates/utils.js";
8
8
  import { generateCompleteFilterQuery as b } from "../utils/filterUtil.js";
9
9
  import { getPartnerRecommendationParams as v } from "../utils/partnerCustomizations.js";
10
- import { isFilterValid as w } from "../validation/filterSchema.js";
11
- import { isConfigValid as N } from "../validation/requiredFields.js";
10
+ import { isFilterValid as N } from "../validation/filterSchema.js";
11
+ import { isConfigValid as x } from "../validation/requiredFields.js";
12
12
  const h = y();
13
13
  let m = null, u = null, d = null;
14
- function I() {
14
+ function k() {
15
15
  return {
16
- cardsInRow: F,
16
+ cardsInRow: D,
17
17
  currencySettings: {
18
18
  name: "USD",
19
19
  value: "USD",
@@ -27,6 +27,7 @@ function I() {
27
27
  productIds: [],
28
28
  id: 1,
29
29
  language: "en_US",
30
+ mobileCardsInRow: P,
30
31
  mobileLayoutEnabled: !1,
31
32
  orientation: "grid",
32
33
  recommendedProducts: [],
@@ -39,9 +40,9 @@ function I() {
39
40
  customAttributes: []
40
41
  };
41
42
  }
42
- function k() {
43
+ function I() {
43
44
  return {
44
- recommendationConfigs: I(),
45
+ recommendationConfigs: k(),
45
46
  recommendationProducts: [],
46
47
  filterStatus: !1,
47
48
  filterSelectionDrawerStatus: !1,
@@ -50,7 +51,7 @@ function k() {
50
51
  filterSnapshot: null
51
52
  };
52
53
  }
53
- const x = () => ({
54
+ const L = () => ({
54
55
  recommendationCampaignUrls: {},
55
56
  activePredictiveAlgorithms: [],
56
57
  languages: {},
@@ -59,8 +60,8 @@ const x = () => ({
59
60
  blockStates: {},
60
61
  currentRecommendationId: null,
61
62
  configVersion: 0
62
- }), T = P("guidoRecommendationExtension", {
63
- state: () => x(),
63
+ }), K = F("guidoRecommendationExtension", {
64
+ state: () => L(),
64
65
  getters: {
65
66
  // ====================================================================
66
67
  // Proxy Getters — Backward Compatible Access to Current Block State
@@ -70,7 +71,7 @@ const x = () => ({
70
71
  * This allows all existing code that reads `store.recommendationConfigs` to work unchanged.
71
72
  */
72
73
  recommendationConfigs(t) {
73
- return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : I();
74
+ return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : k();
74
75
  },
75
76
  /**
76
77
  * Proxy getter: delegates to blockStates[currentRecommendationId].recommendationProducts
@@ -116,7 +117,7 @@ const x = () => ({
116
117
  },
117
118
  getActivePredictiveAlgorithms: (t) => {
118
119
  const e = g(), r = [];
119
- return t.activePredictiveAlgorithms.filter((n) => !D.includes(n)).forEach((n) => {
120
+ return t.activePredictiveAlgorithms.filter((n) => !w.includes(n)).forEach((n) => {
120
121
  r.push(...e.filter((c) => c.id === n));
121
122
  }), r.map((n) => ({
122
123
  text: n.name,
@@ -132,7 +133,7 @@ const x = () => ({
132
133
  value: e.text
133
134
  })),
134
135
  getFilterList() {
135
- return Object.values(this.filterList).map((t) => {
136
+ return Object.values(this.filterList).filter((t) => t.isFilterable !== 0 && t.isFilterable !== !1).map((t) => {
136
137
  let e;
137
138
  return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : C.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
138
139
  text: t.displayName,
@@ -156,7 +157,7 @@ const x = () => ({
156
157
  setCurrentBlock(t) {
157
158
  this.blockStates[t] || (this.blockStates = {
158
159
  ...this.blockStates,
159
- [t]: k()
160
+ [t]: I()
160
161
  }), this.currentRecommendationId = t;
161
162
  },
162
163
  /**
@@ -224,7 +225,7 @@ const x = () => ({
224
225
  decimalCount: String(e.currencyDecimalCount),
225
226
  decimalSeparator: r(e.currencyDecimalSeparator, ","),
226
227
  thousandSeparator: r(e.currencyThousandSeparator, ".")
227
- }, c = !this.blockStates[t], i = c ? k() : this.blockStates[t];
228
+ }, c = !this.blockStates[t], i = c ? I() : this.blockStates[t];
228
229
  i.recommendationConfigs = {
229
230
  ...i.recommendationConfigs,
230
231
  strategy: e.strategy,
@@ -379,7 +380,7 @@ const x = () => ({
379
380
  const n = [...e.recommendationConfigs.filters];
380
381
  n[r] = {
381
382
  ...t,
382
- isValid: w(t)
383
+ isValid: N(t)
383
384
  }, e.recommendationConfigs.filters = n;
384
385
  }
385
386
  },
@@ -425,7 +426,7 @@ const x = () => ({
425
426
  * every block's recommendationConfigs across user edits.
426
427
  */
427
428
  hasInvalidBlock() {
428
- return Object.values(this.blockStates).some((t) => !N(t.recommendationConfigs, this));
429
+ return Object.values(this.blockStates).some((t) => !x(t.recommendationConfigs, this));
429
430
  },
430
431
  // ====================================================================
431
432
  // Per-Block Product Fetching
@@ -475,5 +476,5 @@ const x = () => ({
475
476
  }
476
477
  });
477
478
  export {
478
- T as useRecommendationExtensionStore
479
+ K as useRecommendationExtensionStore
479
480
  };
@@ -0,0 +1,16 @@
1
+ import { useToaster as r } from "../../../composables/useToaster.js";
2
+ import { useTranslations as s } from "../../../composables/useTranslations.js";
3
+ import { ToasterTypeOptions as n } from "../../../enums/toaster.js";
4
+ import { countLiveRecommendationBlocks as i } from "./utils/recommendationBlockCount.js";
5
+ const a = "newsletter.multiple-reco-blocks-warning", f = () => {
6
+ const { showToaster: o } = r(), t = s();
7
+ return { warnIfMultipleBlocks: (e) => {
8
+ i(e) > 1 && o({
9
+ type: n.Dark,
10
+ message: t(a)
11
+ });
12
+ } };
13
+ };
14
+ export {
15
+ f as useRecommendationBlockWarning
16
+ };
@@ -0,0 +1,9 @@
1
+ const r = ".recommendation-block-v2", t = ".recommendation-product-row";
2
+ function n(o) {
3
+ return Array.from(o.querySelectorAll(r)).filter((e) => e.querySelector(t)).length;
4
+ }
5
+ export {
6
+ r as RECOMMENDATION_BLOCK_SELECTOR,
7
+ t as RECOMMENDATION_PRODUCT_ROW_SELECTOR,
8
+ n as countLiveRecommendationBlocks
9
+ };
@@ -1,39 +1,41 @@
1
- var g = Object.defineProperty;
2
- var k = (c, n, e) => n in c ? g(c, n, { enumerable: !0, configurable: !0, writable: !0, value: e }) : c[n] = e;
3
- var l = (c, n, e) => k(c, typeof n != "symbol" ? n + "" : n, e);
4
- import { useToaster as B } from "../../../composables/useToaster.js";
5
- import { ToasterTypeOptions as S } from "../../../enums/toaster.js";
6
- import { PAGE_TYPES as E } from "../../../enums/unsubscribe.js";
7
- import { useUnsubscribeStore as a } from "../../../stores/unsubscribe.js";
8
- import { Block as L, BlockCompositionType as f, ContextActionType as h, ModificationDescription as b, BlockType as v } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
9
- import { getDefaultTemplate as A } from "./template.js";
10
- import { DATA_ATTRIBUTES as i, UNSUBSCRIBE_EVENTS as d } from "./utils/constants.js";
11
- import { parsePageList as p } from "./utils/utils.js";
12
- const y = "unsubscribe-block", m = 'a[data-unsubscribe-link="true"]', _ = ".unsubscribe-block-v2", I = "{{ins-unsubscribe-link}}", T = "https://academy.insiderone.com/docs/adding-unsubscribe-pages-into-emails", C = "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.", N = {
13
- [E.GLOBAL_UNSUBSCRIBE]: "{{ins-global-unsubscribe-link}}",
14
- [E.SUBSCRIPTION_PREFERENCE_CENTER]: "{{ins-preferences-unsubscribe-link}}"
15
- };
16
- class F extends L {
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";
5
+ import { ToasterTypeOptions as A } from "../../../enums/toaster.js";
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";
10
+ import { DATA_ATTRIBUTES as n, UNSUBSCRIBE_EVENTS as p } from "./utils/constants.js";
11
+ import { parsePageList as B } from "./utils/utils.js";
12
+ const C = "unsubscribe-block", m = 'a[data-unsubscribe-link="true"]', E = ".unsubscribe-block-v2", 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 = {
13
+ [h.GLOBAL_UNSUBSCRIBE]: "{{ins-global-unsubscribe-link}}",
14
+ [h.SUBSCRIPTION_PREFERENCE_CENTER]: "{{ins-preferences-unsubscribe-link}}"
15
+ }, w = 3;
16
+ class H extends y {
17
17
  constructor() {
18
18
  super();
19
- l(this, "selectEventListener", null);
20
- l(this, "cancelEventListener", null);
21
- l(this, "currentNode");
19
+ a(this, "selectEventListener", null);
20
+ a(this, "cancelEventListener", null);
21
+ a(this, "currentNode");
22
22
  // Per-block "did this instance have a link last time we saw it?" tracking.
23
23
  // Keyed by the stable `data-unsubscribe-block-id` we assign, because
24
24
  // ImmutableHtmlNode instances are recreated on every document mutation and
25
25
  // can't be used as Map keys directly. A singleton boolean here would be
26
26
  // polluted across blocks since Stripo fires onDocumentChanged per-instance.
27
- l(this, "linkStateByBlockId", /* @__PURE__ */ new Map());
27
+ a(this, "linkStateByBlockId", /* @__PURE__ */ new Map());
28
+ // Per-block prepend retry counter for the leading text guard (SD-143097).
29
+ a(this, "guardAttemptsByBlockId", /* @__PURE__ */ new Map());
28
30
  }
29
31
  getId() {
30
- return y;
32
+ return C;
31
33
  }
32
34
  getIcon() {
33
35
  return "unsubscribe-icon";
34
36
  }
35
37
  getBlockCompositionType() {
36
- return f.BLOCK;
38
+ return T.BLOCK;
37
39
  }
38
40
  getName() {
39
41
  return this.api.translate("Unsubscribe Block");
@@ -42,36 +44,84 @@ class F extends L {
42
44
  return this.api.translate("Unsubscribe Block Description");
43
45
  }
44
46
  getTemplate() {
45
- return A();
47
+ return v();
46
48
  }
47
49
  getContextActionsIds() {
48
- return [h.MOVE, h.REMOVE];
50
+ return [k.MOVE, k.REMOVE];
49
51
  }
50
52
  onSelect(e) {
51
53
  this.currentNode = e;
52
54
  const t = this._getOrAssignBlockId(e);
53
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());
54
56
  }
57
+ onCreated(e) {
58
+ this._ensureLeadingTextGuard(e);
59
+ }
60
+ onDocumentInit() {
61
+ try {
62
+ const e = this.api.getDocumentRoot();
63
+ e && "querySelectorAll" in e && e.querySelectorAll(E).forEach((t) => {
64
+ this._ensureLeadingTextGuard(t);
65
+ });
66
+ } catch {
67
+ }
68
+ }
55
69
  onDocumentChanged(e) {
70
+ this._ensureLeadingTextGuard(e);
56
71
  const t = this._getOrAssignBlockId(e);
57
72
  if (!t)
58
73
  return;
59
- const r = this._hasUnsubscribeLink(e);
60
- this.linkStateByBlockId.get(t) === !0 && !r && this._warnLinkRemoved(), this.linkStateByBlockId.set(t, r);
74
+ const s = this._hasUnsubscribeLink(e);
75
+ this.linkStateByBlockId.get(t) === !0 && !s && this._warnLinkRemoved(), this.linkStateByBlockId.set(t, s);
61
76
  }
62
77
  onDelete(e) {
63
78
  this._removeEventListeners(), this._removeBlockTemplatesFromStore(e), this._resetStoreState();
64
79
  const t = this._readBlockId(e);
65
- t && this.linkStateByBlockId.delete(t);
80
+ t && (this.linkStateByBlockId.delete(t), this.guardAttemptsByBlockId.delete(t));
66
81
  }
67
82
  onDestroy() {
68
- this._removeEventListeners(), this.currentNode = void 0, this.linkStateByBlockId.clear();
83
+ this._removeEventListeners(), this.currentNode = void 0, this.linkStateByBlockId.clear(), this.guardAttemptsByBlockId.clear();
84
+ }
85
+ /**
86
+ * Guarantees a plain-text node before the link's wrapper inside the <p>.
87
+ * Without it the only caret position left of the link is inside the anchor,
88
+ * so anything typed there becomes part of the link (SD-143097).
89
+ */
90
+ _ensureLeadingTextGuard(e) {
91
+ if (!("querySelector" in e))
92
+ return;
93
+ const t = e.querySelector(m);
94
+ if (!t)
95
+ return;
96
+ let s = t, r = s.parent();
97
+ for (; r && "getTagName" in r && r.getTagName().toLowerCase() !== "p"; )
98
+ s = r, r = r.parent();
99
+ if (!r || !("getTagName" in r) || r.getTagName().toLowerCase() !== "p")
100
+ return;
101
+ const i = s.previousSibling();
102
+ if (!!(i && i.getType() === "text" && i.getTextContent())) {
103
+ const b = this._readBlockId(e);
104
+ b && this.guardAttemptsByBlockId.delete(b);
105
+ return;
106
+ }
107
+ const g = this._getOrAssignBlockId(e);
108
+ if (!g)
109
+ return;
110
+ const _ = this.guardAttemptsByBlockId.get(g) ?? 0;
111
+ if (!(_ >= w)) {
112
+ this.guardAttemptsByBlockId.set(g, _ + 1);
113
+ try {
114
+ this.api.getDocumentModifier().modifyHtml(r).prepend("&nbsp;").apply(new d("Ensure unsubscribe link text guard"));
115
+ } catch (b) {
116
+ console.warn("[UnsubscribeBlock] Failed to ensure link text guard:", b);
117
+ }
118
+ }
69
119
  }
70
120
  _hasUnsubscribeLink(e) {
71
121
  return "querySelector" in e ? !!e.querySelector(m) : !1;
72
122
  }
73
123
  _readBlockId(e) {
74
- return "getAttribute" in e ? e.getAttribute(i.BLOCK_ID) : null;
124
+ return "getAttribute" in e ? e.getAttribute(n.BLOCK_ID) : null;
75
125
  }
76
126
  /**
77
127
  * Returns the block's stable id, assigning one via the document modifier if
@@ -85,13 +135,13 @@ class F extends L {
85
135
  return t;
86
136
  if (!("getAttribute" in e))
87
137
  return null;
88
- const r = this._generateNextBlockId();
138
+ const s = this._generateNextBlockId();
89
139
  try {
90
- this.api.getDocumentModifier().modifyHtml(e).setAttribute(i.BLOCK_ID, r).apply(new b(`Assign unsubscribe block id ${r}`));
91
- } catch (s) {
92
- return console.warn("[UnsubscribeBlock] Failed to assign block id:", s), null;
140
+ this.api.getDocumentModifier().modifyHtml(e).setAttribute(n.BLOCK_ID, s).apply(new d(`Assign unsubscribe block id ${s}`));
141
+ } catch (r) {
142
+ return console.warn("[UnsubscribeBlock] Failed to assign block id:", r), null;
93
143
  }
94
- return r;
144
+ return s;
95
145
  }
96
146
  /**
97
147
  * Generates a unique id by scanning the document for the highest existing
@@ -102,10 +152,10 @@ class F extends L {
102
152
  let e = 0;
103
153
  try {
104
154
  const t = this.api.getDocumentRoot();
105
- t && "querySelectorAll" in t && t.querySelectorAll(_).forEach((s) => {
106
- if ("getAttribute" in s) {
107
- const o = s.getAttribute(i.BLOCK_ID), u = o ? parseInt(o) : 0;
108
- u > e && (e = u);
155
+ t && "querySelectorAll" in t && t.querySelectorAll(E).forEach((r) => {
156
+ if ("getAttribute" in r) {
157
+ const i = r.getAttribute(n.BLOCK_ID), l = i ? parseInt(i) : 0;
158
+ l > e && (e = l);
109
159
  }
110
160
  });
111
161
  } catch {
@@ -114,14 +164,14 @@ class F extends L {
114
164
  }
115
165
  _warnLinkRemoved() {
116
166
  try {
117
- const { showToaster: e } = B();
167
+ const { showToaster: e } = f();
118
168
  e({
119
- type: S.Warning,
120
- message: this.api.translate(C),
169
+ type: A.Warning,
170
+ message: this.api.translate(R),
121
171
  actionButton: {
122
172
  text: this.api.translate("Visit Academy"),
123
173
  onClick: () => {
124
- window.open(T, "_blank", "noopener,noreferrer");
174
+ window.open(U, "_blank", "noopener,noreferrer");
125
175
  }
126
176
  }
127
177
  });
@@ -131,26 +181,26 @@ class F extends L {
131
181
  }
132
182
  _setupSelectEventListener() {
133
183
  this._removeSelectEventListener(), this.selectEventListener = (e) => {
134
- const t = e, { collectionType: r, selectedPages: s } = t.detail;
135
- this._updateBlock(r, s.join(","));
136
- }, document.addEventListener(d.SELECT, this.selectEventListener);
184
+ const t = e, { collectionType: s, selectedPages: r } = t.detail;
185
+ this._updateBlock(s, r.join(","));
186
+ }, document.addEventListener(p.SELECT, this.selectEventListener);
137
187
  }
138
188
  _removeSelectEventListener() {
139
- this.selectEventListener && (document.removeEventListener(d.SELECT, this.selectEventListener), this.selectEventListener = null);
189
+ this.selectEventListener && (document.removeEventListener(p.SELECT, this.selectEventListener), this.selectEventListener = null);
140
190
  }
141
191
  _setupCancelEventListener() {
142
192
  this._removeCancelEventListener(), this.cancelEventListener = () => {
143
193
  this._handleCancel();
144
- }, document.addEventListener(d.CANCEL, this.cancelEventListener);
194
+ }, document.addEventListener(p.CANCEL, this.cancelEventListener);
145
195
  }
146
196
  _removeCancelEventListener() {
147
- this.cancelEventListener && (document.removeEventListener(d.CANCEL, this.cancelEventListener), this.cancelEventListener = null);
197
+ this.cancelEventListener && (document.removeEventListener(p.CANCEL, this.cancelEventListener), this.cancelEventListener = null);
148
198
  }
149
199
  _handleCancel() {
150
200
  try {
151
201
  if (!this.currentNode)
152
202
  return;
153
- this.api.getDocumentModifier().modifyHtml(this.currentNode).replaceWith(`<${v.EMPTY_CONTAINER}/>`).apply(new b("Removed unsubscribe block due to cancel"));
203
+ this.api.getDocumentModifier().modifyHtml(this.currentNode).replaceWith(`<${I.EMPTY_CONTAINER}/>`).apply(new d("Removed unsubscribe block due to cancel"));
154
204
  } catch (e) {
155
205
  console.warn("[UnsubscribeBlock] Failed to remove unsubscribe block:", e);
156
206
  }
@@ -161,32 +211,32 @@ class F extends L {
161
211
  _updateBlock(e, t) {
162
212
  if (!this.currentNode || !("querySelector" in this.currentNode))
163
213
  return;
164
- const r = this.currentNode.querySelector(m);
165
- if (!r)
214
+ const s = this.currentNode.querySelector(m);
215
+ if (!s)
166
216
  return;
167
- const s = this._getMergeTag(e);
168
- this.api.getDocumentModifier().modifyHtml(r).setAttribute("href", s).apply(new b(`Updated unsubscribe link to ${s}`)), this.api.getDocumentModifier().modifyHtml(this.currentNode).setAttribute(i.PAGE_TYPE, e.toString()).setAttribute(i.PAGE_LIST, t).apply(new b("Updated unsubscribe block metadata"));
217
+ const r = this._getMergeTag(e);
218
+ 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"));
169
219
  }
170
220
  _getMergeTag(e) {
171
- return N[e] ?? I;
221
+ return D[e] ?? N;
172
222
  }
173
223
  _openDrawer() {
174
224
  if (!(this.currentNode && this.currentNode.getAttribute("data-unsubscribe-page-type")))
175
225
  try {
176
- const e = a();
226
+ const e = u();
177
227
  e.typeSelectionDrawerStatus = !0;
178
228
  } catch (e) {
179
229
  console.error("[UnsubscribeBlock] Failed to open drawer:", e);
180
230
  }
181
231
  }
182
232
  _checkExistingBlocks() {
183
- const e = a();
184
- e.isGlobalUnsubscribeDisabled = !1, e.isSubscriptionPreferencesCenterDisabled = !1, this.api.getDocumentRoot().querySelectorAll(_).forEach((r) => {
185
- if ("getAttribute" in r) {
186
- const s = r.getAttribute(i.PAGE_TYPE);
187
- if (s) {
188
- const o = Number(s);
189
- o === E.GLOBAL_UNSUBSCRIBE ? e.isGlobalUnsubscribeDisabled = !0 : o === E.SUBSCRIPTION_PREFERENCE_CENTER && (e.isSubscriptionPreferencesCenterDisabled = !0);
233
+ const e = u();
234
+ e.isGlobalUnsubscribeDisabled = !1, e.isSubscriptionPreferencesCenterDisabled = !1, this.api.getDocumentRoot().querySelectorAll(E).forEach((s) => {
235
+ if ("getAttribute" in s) {
236
+ const r = s.getAttribute(n.PAGE_TYPE);
237
+ if (r) {
238
+ const i = Number(r);
239
+ i === h.GLOBAL_UNSUBSCRIBE ? e.isGlobalUnsubscribeDisabled = !0 : i === h.SUBSCRIPTION_PREFERENCE_CENTER && (e.isSubscriptionPreferencesCenterDisabled = !0);
190
240
  }
191
241
  }
192
242
  });
@@ -194,26 +244,26 @@ class F extends L {
194
244
  async _loadBlockState(e) {
195
245
  if (!("getAttribute" in e))
196
246
  return;
197
- const t = e.getAttribute(i.PAGE_TYPE), r = e.getAttribute(i.PAGE_LIST);
198
- if (!t || !r)
247
+ const t = e.getAttribute(n.PAGE_TYPE), s = e.getAttribute(n.PAGE_LIST);
248
+ if (!t || !s)
199
249
  return;
200
- const s = a(), o = Number(t), u = p(r);
201
- await s.fetchTemplates(), s.setCollectionWithoutAutoSelection(o), s.loadSelectedTemplates(u);
250
+ const r = u(), i = Number(t), l = B(s);
251
+ await r.fetchTemplates(), r.setCollectionWithoutAutoSelection(i), r.loadSelectedTemplates(l);
202
252
  }
203
253
  _resetStoreState() {
204
- a().$reset();
254
+ u().$reset();
205
255
  }
206
256
  _removeBlockTemplatesFromStore(e) {
207
257
  if (!("getAttribute" in e))
208
258
  return;
209
- const t = e.getAttribute(i.PAGE_LIST);
259
+ const t = e.getAttribute(n.PAGE_LIST);
210
260
  if (!t)
211
261
  return;
212
- const r = a(), s = p(t);
213
- r.removeUnsubscribePages(s);
262
+ const s = u(), r = B(t);
263
+ s.removeUnsubscribePages(r);
214
264
  }
215
265
  }
216
266
  export {
217
- y as UNSUBSCRIBE_BLOCK_ID,
218
- F as UnsubscribeBlock
267
+ C as UNSUBSCRIBE_BLOCK_ID,
268
+ H as UnsubscribeBlock
219
269
  };
@@ -1,28 +1,28 @@
1
- var d = Object.defineProperty;
2
- var h = (a, s, e) => s in a ? d(a, s, { enumerable: !0, configurable: !0, writable: !0, value: e }) : a[s] = e;
3
- var u = (a, s, e) => h(a, typeof s != "symbol" ? s + "" : s, e);
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);
4
4
  import { useUnsubscribeStore as l } from "../../../stores/unsubscribe.js";
5
- import { Control as T, UEAttr as i, UIElementType as n } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
6
- import { DATA_ATTRIBUTES as p } from "./utils/constants.js";
7
- import { parsePageList as _ } from "./utils/utils.js";
8
- const v = "ui-elements-unsubscribe", r = {
5
+ import { Control as _, UEAttr as i, UIElementType as n } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
6
+ import { DATA_ATTRIBUTES as d } from "./utils/constants.js";
7
+ import { parsePageList as h } from "./utils/utils.js";
8
+ const g = "ui-elements-unsubscribe", r = {
9
9
  SELECT_BUTTON: "selectTemplateButton",
10
10
  PREV_BUTTON: "prevButton",
11
11
  NEXT_BUTTON: "nextButton",
12
12
  COUNTER_TEXT: "counterText",
13
13
  PREVIEW_IMAGE: "previewImage"
14
14
  };
15
- class B extends T {
15
+ class B extends _ {
16
16
  constructor() {
17
17
  super(...arguments);
18
- u(this, "currentPreviewIndex", 0);
19
- u(this, "currentNode");
20
- u(this, "currentPages");
21
- u(this, "valueChangeHandlers", []);
22
- u(this, "lastParsedAttribute");
18
+ c(this, "currentPreviewIndex", 0);
19
+ c(this, "currentNode");
20
+ c(this, "currentPages");
21
+ c(this, "valueChangeHandlers", []);
22
+ c(this, "lastParsedAttribute");
23
23
  }
24
24
  getId() {
25
- return v;
25
+ return g;
26
26
  }
27
27
  getTemplate() {
28
28
  return `
@@ -34,8 +34,8 @@ class B extends T {
34
34
  }
35
35
  onTemplateNodeUpdated(e) {
36
36
  if (this.currentNode = e, "getAttribute" in this.currentNode) {
37
- const t = this.currentNode.getAttribute(p.PAGE_LIST);
38
- t && (t !== this.lastParsedAttribute && (this.currentPages = _(t), this.lastParsedAttribute = t, this.currentPreviewIndex = 0), this._updateCounter(), this._loadAndUpdatePreview());
37
+ const t = this.currentNode.getAttribute(d.PAGE_LIST);
38
+ t && (t !== this.lastParsedAttribute && (this.currentPages = h(t), this.lastParsedAttribute = t, this.currentPreviewIndex = 0), this._updateCounter(), this._loadAndUpdatePreview());
39
39
  }
40
40
  }
41
41
  onRender() {
@@ -62,11 +62,18 @@ class B extends T {
62
62
  _onButtonClick() {
63
63
  try {
64
64
  const e = l();
65
- e.activeType = e.getSelectedCollection[this.currentPreviewIndex], e.pageSelectionUpdateStatus = !0, e.pageSelectionDrawerStatus = !0;
65
+ this._reseedSelectionFromBlock(), e.activeType = e.getSelectedCollection[this.currentPreviewIndex], e.pageSelectionUpdateStatus = !0, e.pageSelectionDrawerStatus = !0;
66
66
  } catch (e) {
67
67
  console.error("[UnsubscribeControl] Failed to open drawer:", e);
68
68
  }
69
69
  }
70
+ _reseedSelectionFromBlock() {
71
+ const e = l();
72
+ if (e.$reset(), !this.currentNode || !("getAttribute" in this.currentNode))
73
+ 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)));
76
+ }
70
77
  _onPrevClick() {
71
78
  this.currentPreviewIndex > 0 && (this.currentPreviewIndex--, this._updatePreview(), this._updateCounter());
72
79
  }
@@ -80,21 +87,21 @@ class B extends T {
80
87
  var e;
81
88
  if ((e = this.currentPages) != null && e.length)
82
89
  try {
83
- const t = this.currentPages[this.currentPreviewIndex], o = l().getThumbnailByTemplateId(t);
84
- if (!o) {
90
+ const t = this.currentPages[this.currentPreviewIndex], u = l().getThumbnailByTemplateId(t);
91
+ if (!u) {
85
92
  console.warn("[UnsubscribeControl] No thumbnail found for page:", t);
86
93
  return;
87
94
  }
88
95
  this.api.updateValues({
89
- [r.PREVIEW_IMAGE]: o
96
+ [r.PREVIEW_IMAGE]: u
90
97
  });
91
98
  } catch (t) {
92
99
  console.error("[UnsubscribeControl] Failed to update preview:", t);
93
100
  }
94
101
  }
95
102
  _updateCounter() {
96
- const e = this.currentPreviewIndex + 1, t = this.totalTemplates, c = this.currentPreviewIndex === 0, o = this.currentPreviewIndex >= t - 1;
97
- this.api.setUIEAttribute(r.PREV_BUTTON, i.BUTTON.disabled, c), this.api.setUIEAttribute(r.NEXT_BUTTON, i.BUTTON.disabled, o), this.api.setUIEAttribute(
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(
98
105
  r.COUNTER_TEXT,
99
106
  i.LABEL.text,
100
107
  `${this.api.translate("Showing")} ${e} ${this.api.translate("of")} ${t}`
@@ -135,14 +142,14 @@ class B extends T {
135
142
  </${n.LABEL}>
136
143
  `;
137
144
  }
138
- _getIconButton(e, t, c) {
139
- const o = c ? `${i.BUTTON.disabled}="true"` : "";
145
+ _getIconButton(e, t, a) {
146
+ const u = a ? `${i.BUTTON.disabled}="true"` : "";
140
147
  return `
141
148
  <${n.BUTTON}
142
149
  id="${e}"
143
150
  class="flat-inline flat-white"
144
151
  ${i.BUTTON.name}="${e}"
145
- ${o}
152
+ ${u}
146
153
  >
147
154
  <${n.ICON}
148
155
  src="${t}"
@@ -165,6 +172,6 @@ class B extends T {
165
172
  }
166
173
  }
167
174
  export {
168
- v as UNSUBSCRIBE_CONTROL_ID,
175
+ g as UNSUBSCRIBE_CONTROL_ID,
169
176
  B as UnsubscribeControl
170
177
  };
@@ -1,21 +1,21 @@
1
1
  import { BlockType as s } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
2
- const e = "unsubscribe", n = "{{ins-unsubscribe-link}}", t = `
2
+ const e = "unsubscribe", n = "{{ins-unsubscribe-link}}", b = `
3
3
  <${s.BLOCK_TEXT}
4
4
  class="unsubscribe-block-v2 esd-block-unsubscribe es-p0"
5
5
  align="center"
6
6
  data-unsubscribe-page-type=""
7
7
  data-unsubscribe-page-list=""
8
8
  >
9
- <p>&nbsp;<strong><a
9
+ <p>&nbsp;<a
10
10
  href="${n}"
11
11
  class="unsubscribe-link"
12
12
  target="_blank"
13
13
  data-unsubscribe-link="true"
14
- >${e}</a></strong></p>
14
+ >${e}</a></p>
15
15
  </${s.BLOCK_TEXT}>
16
16
  `;
17
17
  function u() {
18
- return t;
18
+ return b;
19
19
  }
20
20
  export {
21
21
  u as getDefaultTemplate