@useinsider/guido 3.4.1 → 3.5.0-beta.70f8c74

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 (32) hide show
  1. package/README.md +2 -0
  2. package/dist/components/Guido.vue.js +1 -1
  3. package/dist/components/Guido.vue2.js +50 -48
  4. package/dist/components/organisms/extensions/recommendation/FilterItem.vue.js +2 -2
  5. package/dist/components/organisms/extensions/recommendation/FilterItem.vue2.js +49 -49
  6. package/dist/composables/useActionsApi.js +9 -5
  7. package/dist/composables/useSave.js +13 -14
  8. package/dist/config/migrator/checkboxMigrator.js +20 -69
  9. package/dist/config/migrator/itemsBlockMigrator.js +28 -18
  10. package/dist/config/migrator/radioButtonMigrator.js +36 -91
  11. package/dist/config/migrator/textBlockMigration.js +65 -0
  12. package/dist/extensions/Blocks/Recommendation/block.js +90 -45
  13. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +33 -14
  14. package/dist/extensions/Blocks/Recommendation/utils/filterUtil.js +24 -16
  15. package/dist/extensions/Blocks/Unsubscribe/block.js +133 -49
  16. package/dist/extensions/Blocks/Unsubscribe/template.js +8 -8
  17. package/dist/extensions/Blocks/Unsubscribe/utils/constants.js +2 -1
  18. package/dist/guido.css +1 -1
  19. package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js +145 -144
  20. package/dist/src/composables/useActionsApi.d.ts +1 -1
  21. package/dist/src/config/migrator/textBlockMigration.d.ts +24 -0
  22. package/dist/src/extensions/Blocks/Recommendation/block.d.ts +10 -0
  23. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +5 -0
  24. package/dist/src/extensions/Blocks/Recommendation/utils/filterUtil.d.ts +2 -0
  25. package/dist/src/extensions/Blocks/Unsubscribe/block.d.ts +20 -1
  26. package/dist/src/extensions/Blocks/Unsubscribe/utils/constants.d.ts +1 -0
  27. package/dist/src/stores/config.test.d.ts +1 -0
  28. package/dist/src/vitest.setup.d.ts +0 -0
  29. package/dist/static/styles/components/wide-panel.css.js +5 -0
  30. package/dist/stores/config.js +24 -23
  31. package/dist/utils/templatePreparation.js +51 -43
  32. package/package.json +3 -2
@@ -1,16 +1,16 @@
1
- import { getRecommendationFeedSourceMaps as g, getOperatorOptions as R, PriceAttributes as y } from "../../../../enums/extensions/recommendationBlock.js";
2
- import { useRecommendationApi as C } from "../../../../services/recommendationApi.js";
1
+ import { getRecommendationFeedSourceMaps as g, getOperatorOptions as R, PriceAttributes as C } from "../../../../enums/extensions/recommendationBlock.js";
2
+ import { useRecommendationApi as y } from "../../../../services/recommendationApi.js";
3
3
  import { useConfigStore as G } from "../../../../stores/config.js";
4
4
  import { defineStore as P } from "pinia";
5
5
  import { DEFAULT_CARDS_IN_ROW as F } from "../constants/layout.js";
6
6
  import { EXCLUDED_ALGORITHM_IDS as D } 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
- import { isFilterValid as w } from "../validation/filterSchema.js";
10
- import { isConfigValid as v } from "../validation/requiredFields.js";
11
- const h = C();
9
+ import { isFilterValid as v } from "../validation/filterSchema.js";
10
+ import { isConfigValid as w } from "../validation/requiredFields.js";
11
+ const h = y();
12
12
  let m = null, u = null, d = null;
13
- function k() {
13
+ function I() {
14
14
  return {
15
15
  cardsInRow: F,
16
16
  currencySettings: {
@@ -38,9 +38,9 @@ function k() {
38
38
  customAttributes: []
39
39
  };
40
40
  }
41
- function I() {
41
+ function k() {
42
42
  return {
43
- recommendationConfigs: k(),
43
+ recommendationConfigs: I(),
44
44
  recommendationProducts: [],
45
45
  filterStatus: !1,
46
46
  filterSelectionDrawerStatus: !1,
@@ -69,7 +69,7 @@ const N = () => ({
69
69
  * This allows all existing code that reads `store.recommendationConfigs` to work unchanged.
70
70
  */
71
71
  recommendationConfigs(t) {
72
- return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : k();
72
+ return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : I();
73
73
  },
74
74
  /**
75
75
  * Proxy getter: delegates to blockStates[currentRecommendationId].recommendationProducts
@@ -133,7 +133,7 @@ const N = () => ({
133
133
  getFilterList() {
134
134
  return Object.values(this.filterList).map((t) => {
135
135
  let e;
136
- return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : y.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
136
+ return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : C.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
137
137
  text: t.displayName,
138
138
  value: e,
139
139
  type: t.attributeType
@@ -155,7 +155,7 @@ const N = () => ({
155
155
  setCurrentBlock(t) {
156
156
  this.blockStates[t] || (this.blockStates = {
157
157
  ...this.blockStates,
158
- [t]: I()
158
+ [t]: k()
159
159
  }), this.currentRecommendationId = t;
160
160
  },
161
161
  /**
@@ -174,6 +174,25 @@ const N = () => ({
174
174
  this.currentRecommendationId = n.length > 0 ? n[0] : null;
175
175
  }
176
176
  },
177
+ /**
178
+ * Deep-clones a block's state and mirrors its campaign URL under a new id.
179
+ * Invoked from `onCreated` when a duplicate is detected (SD-142352).
180
+ */
181
+ cloneBlockState(t, e) {
182
+ const r = this.blockStates[t];
183
+ if (r) {
184
+ const o = structuredClone(r);
185
+ o.recommendationConfigs.id = e, this.blockStates = {
186
+ ...this.blockStates,
187
+ [e]: o
188
+ };
189
+ }
190
+ const n = t.toString(), c = e.toString(), i = this.recommendationCampaignUrls[n];
191
+ i && (this.recommendationCampaignUrls = {
192
+ ...this.recommendationCampaignUrls,
193
+ [c]: i
194
+ });
195
+ },
177
196
  /**
178
197
  * Marks a block as initialized (initial API data has been fetched).
179
198
  * Automatically cleaned up when removeBlockState deletes the block entry.
@@ -204,7 +223,7 @@ const N = () => ({
204
223
  decimalCount: String(e.currencyDecimalCount),
205
224
  decimalSeparator: r(e.currencyDecimalSeparator, ","),
206
225
  thousandSeparator: r(e.currencyThousandSeparator, ".")
207
- }, c = !this.blockStates[t], i = c ? I() : this.blockStates[t];
226
+ }, c = !this.blockStates[t], i = c ? k() : this.blockStates[t];
208
227
  i.recommendationConfigs = {
209
228
  ...i.recommendationConfigs,
210
229
  strategy: e.strategy,
@@ -359,7 +378,7 @@ const N = () => ({
359
378
  const n = [...e.recommendationConfigs.filters];
360
379
  n[r] = {
361
380
  ...t,
362
- isValid: w(t)
381
+ isValid: v(t)
363
382
  }, e.recommendationConfigs.filters = n;
364
383
  }
365
384
  },
@@ -405,7 +424,7 @@ const N = () => ({
405
424
  * every block's recommendationConfigs across user edits.
406
425
  */
407
426
  hasInvalidBlock() {
408
- return Object.values(this.blockStates).some((t) => !v(t.recommendationConfigs, this));
427
+ return Object.values(this.blockStates).some((t) => !w(t.recommendationConfigs, this));
409
428
  },
410
429
  // ====================================================================
411
430
  // Per-Block Product Fetching
@@ -9,36 +9,44 @@ function m(t) {
9
9
  function f(t) {
10
10
  return t.split(",").filter(Boolean).map(m);
11
11
  }
12
- function y(t) {
12
+ function G(t) {
13
+ return t.map(encodeURIComponent).join(",");
14
+ }
15
+ function Q(t) {
16
+ return t.trim().length > 0;
17
+ }
18
+ function d(t) {
13
19
  if (t.length === 0)
14
20
  return "";
15
21
  const o = t.sort((r, e) => r.filterNumber - e.filterNumber), u = o.map((r) => {
16
- const e = r.operator === l, a = e ? "=" : r.operator, c = e ? f(r.value).join(l) : r.value;
17
- return `[${r.attribute}][${encodeURIComponent(a)}][${c}]`;
18
- }), [i, ...p] = u;
19
- let n = i;
20
- for (let r = 0; r < p.length; r++) {
22
+ const e = r.operator === l, a = e ? "=" : r.operator, s = e ? f(r.value).join(l) : r.value;
23
+ return `[${r.attribute}][${encodeURIComponent(a)}][${s}]`;
24
+ }), [p, ...i] = u;
25
+ let n = p;
26
+ for (let r = 0; r < i.length; r++) {
21
27
  const e = o[r].innerGroupOperator;
22
- n += `${e}${p[r]}`;
28
+ n += `${e}${i[r]}`;
23
29
  }
24
30
  return `(${n})`;
25
31
  }
26
- function g(t) {
32
+ function F(t) {
27
33
  if (!t || t.length === 0)
28
34
  return "";
29
- const o = t.reduce((r, e) => (r[e.filterGroup] || (r[e.filterGroup] = []), r[e.filterGroup].push(e), r), {}), u = Object.keys(o).map(Number).sort((r, e) => r - e), i = u.map((r) => {
35
+ const o = t.reduce((r, e) => (r[e.filterGroup] || (r[e.filterGroup] = []), r[e.filterGroup].push(e), r), {}), u = Object.keys(o).map(Number).sort((r, e) => r - e), p = u.map((r) => {
30
36
  const e = o[r];
31
- return y(e);
32
- }), [p, ...n] = i;
33
- let s = p;
37
+ return d(e);
38
+ }), [i, ...n] = p;
39
+ let c = i;
34
40
  for (let r = 0; r < n.length; r++) {
35
- const e = u[r + 1], c = o[e][0].outerGroupOperator;
36
- s += `${c}${n[r]}`;
41
+ const e = u[r + 1], s = o[e][0].outerGroupOperator;
42
+ c += `${s}${n[r]}`;
37
43
  }
38
- return s.trim();
44
+ return c.trim();
39
45
  }
40
46
  export {
41
- g as generateCompleteFilterQuery,
47
+ G as encodeTagList,
48
+ F as generateCompleteFilterQuery,
49
+ Q as isValidFilterTag,
42
50
  f as parseTagList,
43
51
  m as safeDecodeURIComponent
44
52
  };
@@ -1,31 +1,39 @@
1
- var d = Object.defineProperty;
2
- var h = (n, i, e) => i in n ? d(n, i, { enumerable: !0, configurable: !0, writable: !0, value: e }) : n[i] = e;
3
- var u = (n, i, e) => h(n, typeof i != "symbol" ? i + "" : i, e);
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";
4
6
  import { PAGE_TYPES as E } from "../../../enums/unsubscribe.js";
5
- import { useUnsubscribeStore as c } from "../../../stores/unsubscribe.js";
6
- import { Block as _, BlockCompositionType as S, BlockType as L, ModificationDescription as b } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
7
- import { getDefaultTemplate as v } from "./template.js";
8
- import { UNSUBSCRIBE_EVENTS as a, DATA_ATTRIBUTES as o } from "./utils/constants.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";
9
11
  import { parsePageList as p } from "./utils/utils.js";
10
- const g = "unsubscribe-block", T = 'a[data-unsubscribe-link="true"]', f = ".unsubscribe-block-v2", B = "{{ins-unsubscribe-link}}", C = {
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 = {
11
13
  [E.GLOBAL_UNSUBSCRIBE]: "{{ins-global-unsubscribe-link}}",
12
14
  [E.SUBSCRIPTION_PREFERENCE_CENTER]: "{{ins-preferences-unsubscribe-link}}"
13
15
  };
14
- class I extends _ {
16
+ class F extends L {
15
17
  constructor() {
16
18
  super();
17
- u(this, "selectEventListener", null);
18
- u(this, "cancelEventListener", null);
19
- u(this, "currentNode");
19
+ l(this, "selectEventListener", null);
20
+ l(this, "cancelEventListener", null);
21
+ l(this, "currentNode");
22
+ // Per-block "did this instance have a link last time we saw it?" tracking.
23
+ // Keyed by the stable `data-unsubscribe-block-id` we assign, because
24
+ // ImmutableHtmlNode instances are recreated on every document mutation and
25
+ // can't be used as Map keys directly. A singleton boolean here would be
26
+ // polluted across blocks since Stripo fires onDocumentChanged per-instance.
27
+ l(this, "linkStateByBlockId", /* @__PURE__ */ new Map());
20
28
  }
21
29
  getId() {
22
- return g;
30
+ return y;
23
31
  }
24
32
  getIcon() {
25
33
  return "unsubscribe-icon";
26
34
  }
27
35
  getBlockCompositionType() {
28
- return S.BLOCK;
36
+ return f.BLOCK;
29
37
  }
30
38
  getName() {
31
39
  return this.api.translate("Unsubscribe Block");
@@ -34,39 +42,115 @@ class I extends _ {
34
42
  return this.api.translate("Unsubscribe Block Description");
35
43
  }
36
44
  getTemplate() {
37
- return v();
45
+ return A();
46
+ }
47
+ getContextActionsIds() {
48
+ return [h.MOVE, h.REMOVE];
38
49
  }
39
50
  onSelect(e) {
40
- this.currentNode = e, !("getAttribute" in e && e.getAttribute("data-migration")) && (this._resetStoreState(), this._loadBlockState(e), this._setupSelectEventListener(), this._setupCancelEventListener(), this._checkExistingBlocks(), this._openDrawer());
51
+ this.currentNode = e;
52
+ const t = this._getOrAssignBlockId(e);
53
+ 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
+ }
55
+ onDocumentChanged(e) {
56
+ const t = this._getOrAssignBlockId(e);
57
+ if (!t)
58
+ return;
59
+ const r = this._hasUnsubscribeLink(e);
60
+ this.linkStateByBlockId.get(t) === !0 && !r && this._warnLinkRemoved(), this.linkStateByBlockId.set(t, r);
41
61
  }
42
62
  onDelete(e) {
43
63
  this._removeEventListeners(), this._removeBlockTemplatesFromStore(e), this._resetStoreState();
64
+ const t = this._readBlockId(e);
65
+ t && this.linkStateByBlockId.delete(t);
44
66
  }
45
67
  onDestroy() {
46
- this._removeEventListeners(), this.currentNode = void 0;
68
+ this._removeEventListeners(), this.currentNode = void 0, this.linkStateByBlockId.clear();
69
+ }
70
+ _hasUnsubscribeLink(e) {
71
+ return "querySelector" in e ? !!e.querySelector(m) : !1;
72
+ }
73
+ _readBlockId(e) {
74
+ return "getAttribute" in e ? e.getAttribute(i.BLOCK_ID) : null;
75
+ }
76
+ /**
77
+ * Returns the block's stable id, assigning one via the document modifier if
78
+ * the node has not been tagged yet. Idempotent: subsequent calls during
79
+ * the same document-change cycle (e.g. reentrant onDocumentChanged after
80
+ * `apply()`) short-circuit on the existing attribute.
81
+ */
82
+ _getOrAssignBlockId(e) {
83
+ const t = this._readBlockId(e);
84
+ if (t)
85
+ return t;
86
+ if (!("getAttribute" in e))
87
+ return null;
88
+ const r = this._generateNextBlockId();
89
+ 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;
93
+ }
94
+ return r;
95
+ }
96
+ /**
97
+ * Generates a unique id by scanning the document for the highest existing
98
+ * `data-unsubscribe-block-id` and returning max+1. Mirrors the strategy
99
+ * used by RecommendationBlock so reloaded templates don't collide.
100
+ */
101
+ _generateNextBlockId() {
102
+ let e = 0;
103
+ try {
104
+ 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);
109
+ }
110
+ });
111
+ } catch {
112
+ }
113
+ return String(e + 1);
114
+ }
115
+ _warnLinkRemoved() {
116
+ try {
117
+ const { showToaster: e } = B();
118
+ e({
119
+ type: S.Warning,
120
+ message: this.api.translate(C),
121
+ actionButton: {
122
+ text: this.api.translate("Visit Academy"),
123
+ onClick: () => {
124
+ window.open(T, "_blank", "noopener,noreferrer");
125
+ }
126
+ }
127
+ });
128
+ } catch (e) {
129
+ console.error("[UnsubscribeBlock] Failed to show warning toaster:", e);
130
+ }
47
131
  }
48
132
  _setupSelectEventListener() {
49
133
  this._removeSelectEventListener(), this.selectEventListener = (e) => {
50
- const r = e, { collectionType: s, selectedPages: t } = r.detail;
51
- this._updateBlock(s, t.join(","));
52
- }, document.addEventListener(a.SELECT, this.selectEventListener);
134
+ const t = e, { collectionType: r, selectedPages: s } = t.detail;
135
+ this._updateBlock(r, s.join(","));
136
+ }, document.addEventListener(d.SELECT, this.selectEventListener);
53
137
  }
54
138
  _removeSelectEventListener() {
55
- this.selectEventListener && (document.removeEventListener(a.SELECT, this.selectEventListener), this.selectEventListener = null);
139
+ this.selectEventListener && (document.removeEventListener(d.SELECT, this.selectEventListener), this.selectEventListener = null);
56
140
  }
57
141
  _setupCancelEventListener() {
58
142
  this._removeCancelEventListener(), this.cancelEventListener = () => {
59
143
  this._handleCancel();
60
- }, document.addEventListener(a.CANCEL, this.cancelEventListener);
144
+ }, document.addEventListener(d.CANCEL, this.cancelEventListener);
61
145
  }
62
146
  _removeCancelEventListener() {
63
- this.cancelEventListener && (document.removeEventListener(a.CANCEL, this.cancelEventListener), this.cancelEventListener = null);
147
+ this.cancelEventListener && (document.removeEventListener(d.CANCEL, this.cancelEventListener), this.cancelEventListener = null);
64
148
  }
65
149
  _handleCancel() {
66
150
  try {
67
151
  if (!this.currentNode)
68
152
  return;
69
- this.api.getDocumentModifier().modifyHtml(this.currentNode).replaceWith(`<${L.EMPTY_CONTAINER}/>`).apply(new b("Removed unsubscribe block due to cancel"));
153
+ this.api.getDocumentModifier().modifyHtml(this.currentNode).replaceWith(`<${v.EMPTY_CONTAINER}/>`).apply(new b("Removed unsubscribe block due to cancel"));
70
154
  } catch (e) {
71
155
  console.warn("[UnsubscribeBlock] Failed to remove unsubscribe block:", e);
72
156
  }
@@ -74,35 +158,35 @@ class I extends _ {
74
158
  _removeEventListeners() {
75
159
  this._removeSelectEventListener(), this._removeCancelEventListener();
76
160
  }
77
- _updateBlock(e, r) {
161
+ _updateBlock(e, t) {
78
162
  if (!this.currentNode || !("querySelector" in this.currentNode))
79
163
  return;
80
- const s = this.currentNode.querySelector(T);
81
- if (!s)
164
+ const r = this.currentNode.querySelector(m);
165
+ if (!r)
82
166
  return;
83
- const t = this._getMergeTag(e);
84
- this.api.getDocumentModifier().modifyHtml(s).setAttribute("href", t).apply(new b(`Updated unsubscribe link to ${t}`)), this.api.getDocumentModifier().modifyHtml(this.currentNode).setAttribute(o.PAGE_TYPE, e.toString()).setAttribute(o.PAGE_LIST, r).apply(new b("Updated unsubscribe block metadata"));
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"));
85
169
  }
86
170
  _getMergeTag(e) {
87
- return C[e] ?? B;
171
+ return N[e] ?? I;
88
172
  }
89
173
  _openDrawer() {
90
174
  if (!(this.currentNode && this.currentNode.getAttribute("data-unsubscribe-page-type")))
91
175
  try {
92
- const e = c();
176
+ const e = a();
93
177
  e.typeSelectionDrawerStatus = !0;
94
178
  } catch (e) {
95
179
  console.error("[UnsubscribeBlock] Failed to open drawer:", e);
96
180
  }
97
181
  }
98
182
  _checkExistingBlocks() {
99
- const e = c();
100
- e.isGlobalUnsubscribeDisabled = !1, e.isSubscriptionPreferencesCenterDisabled = !1, this.api.getDocumentRoot().querySelectorAll(f).forEach((s) => {
101
- if ("getAttribute" in s) {
102
- const t = s.getAttribute(o.PAGE_TYPE);
103
- if (t) {
104
- const l = Number(t);
105
- l === E.GLOBAL_UNSUBSCRIBE ? e.isGlobalUnsubscribeDisabled = !0 : l === E.SUBSCRIPTION_PREFERENCE_CENTER && (e.isSubscriptionPreferencesCenterDisabled = !0);
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);
106
190
  }
107
191
  }
108
192
  });
@@ -110,26 +194,26 @@ class I extends _ {
110
194
  async _loadBlockState(e) {
111
195
  if (!("getAttribute" in e))
112
196
  return;
113
- const r = e.getAttribute(o.PAGE_TYPE), s = e.getAttribute(o.PAGE_LIST);
114
- if (!r || !s)
197
+ const t = e.getAttribute(i.PAGE_TYPE), r = e.getAttribute(i.PAGE_LIST);
198
+ if (!t || !r)
115
199
  return;
116
- const t = c(), l = Number(r), m = p(s);
117
- await t.fetchTemplates(), t.setCollectionWithoutAutoSelection(l), t.loadSelectedTemplates(m);
200
+ const s = a(), o = Number(t), u = p(r);
201
+ await s.fetchTemplates(), s.setCollectionWithoutAutoSelection(o), s.loadSelectedTemplates(u);
118
202
  }
119
203
  _resetStoreState() {
120
- c().$reset();
204
+ a().$reset();
121
205
  }
122
206
  _removeBlockTemplatesFromStore(e) {
123
207
  if (!("getAttribute" in e))
124
208
  return;
125
- const r = e.getAttribute(o.PAGE_LIST);
126
- if (!r)
209
+ const t = e.getAttribute(i.PAGE_LIST);
210
+ if (!t)
127
211
  return;
128
- const s = c(), t = p(r);
129
- s.removeUnsubscribePages(t);
212
+ const r = a(), s = p(t);
213
+ r.removeUnsubscribePages(s);
130
214
  }
131
215
  }
132
216
  export {
133
- g as UNSUBSCRIBE_BLOCK_ID,
134
- I as UnsubscribeBlock
217
+ y as UNSUBSCRIBE_BLOCK_ID,
218
+ F as UnsubscribeBlock
135
219
  };
@@ -1,22 +1,22 @@
1
- import { BlockType as e } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
2
- const s = "unsubscribe", n = "{{ins-unsubscribe-link}}", t = `
3
- <${e.BLOCK_TEXT}
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 = `
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>You can <strong><a
9
+ <p>&nbsp;<strong><a
10
10
  href="${n}"
11
11
  class="unsubscribe-link"
12
12
  target="_blank"
13
13
  data-unsubscribe-link="true"
14
- >${s}</a></strong> from our emails, if you need to.</p>
15
- </${e.BLOCK_TEXT}>
14
+ >${e}</a></strong></p>
15
+ </${s.BLOCK_TEXT}>
16
16
  `;
17
- function r() {
17
+ function u() {
18
18
  return t;
19
19
  }
20
20
  export {
21
- r as getDefaultTemplate
21
+ u as getDefaultTemplate
22
22
  };
@@ -3,7 +3,8 @@ const s = {
3
3
  CANCEL: "unsubscribe:cancel"
4
4
  }, e = {
5
5
  PAGE_TYPE: "data-unsubscribe-page-type",
6
- PAGE_LIST: "data-unsubscribe-page-list"
6
+ PAGE_LIST: "data-unsubscribe-page-list",
7
+ BLOCK_ID: "data-unsubscribe-block-id"
7
8
  };
8
9
  export {
9
10
  e as DATA_ATTRIBUTES,
package/dist/guido.css CHANGED
@@ -1 +1 @@
1
- .gap-16[data-v-8053a037],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-cd76c125] .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-4e2a4adb]{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-cdee3452]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-cdee3452]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-cdee3452]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-df672485]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-df672485]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-df672485]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-df672485]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-df672485]{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-cd76c125] .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-4e2a4adb]{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-b293a2b0]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-b293a2b0]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-b293a2b0]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-df672485]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-df672485]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-df672485]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-df672485]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-df672485]{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}