@useinsider/guido 3.8.0-beta.910d4af → 3.8.0-beta.bf9ea20

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 (23) hide show
  1. package/dist/components/organisms/email-preview/desktop-preview/DesktopPreview.vue.js +8 -8
  2. package/dist/components/organisms/email-preview/desktop-preview/DesktopPreview.vue2.js +12 -15
  3. package/dist/components/organisms/email-preview/mobile-preview/ContentView.vue.js +5 -5
  4. package/dist/components/organisms/email-preview/mobile-preview/ContentView.vue2.js +15 -16
  5. package/dist/components/organisms/unsubscribe/UnsubscribePageSelection.vue.js +5 -5
  6. package/dist/components/organisms/unsubscribe/UnsubscribePageSelection.vue2.js +37 -42
  7. package/dist/components/organisms/unsubscribe/UnsubscribeTypeSelection.vue.js +3 -3
  8. package/dist/components/organisms/unsubscribe/UnsubscribeTypeSelection.vue2.js +37 -40
  9. package/dist/composables/useSave.js +14 -14
  10. package/dist/composables/validators/useUnsubscribeBlockValidator.js +17 -26
  11. package/dist/extensions/Blocks/Items/block.js +48 -29
  12. package/dist/extensions/Blocks/Items/utils/nodeConfigUtils.js +62 -45
  13. package/dist/extensions/Blocks/Unsubscribe/block.js +37 -40
  14. package/dist/extensions/Blocks/Unsubscribe/control.js +16 -19
  15. package/dist/guido.css +1 -1
  16. package/dist/src/composables/validators/useUnsubscribeBlockValidator.d.ts +0 -1
  17. package/dist/src/extensions/Blocks/Items/block.d.ts +8 -0
  18. package/dist/src/extensions/Blocks/Items/utils/nodeConfigUtils.d.ts +1 -1
  19. package/dist/src/stores/unsubscribe.d.ts +1 -11
  20. package/dist/stores/unsubscribe.js +7 -8
  21. package/package.json +1 -1
  22. package/dist/composables/usePreviewInteractionGuard.js +0 -17
  23. package/dist/src/composables/usePreviewInteractionGuard.d.ts +0 -3
@@ -1,20 +1,20 @@
1
- import { BlockId as g } from "../../../enums/block.js";
1
+ import { BlockId as u } from "../../../enums/block.js";
2
2
  import { useOnboardingStore as p } from "../../../stores/onboarding.js";
3
- import { getMigrationBannerHtml as f } from "../../../utils/migrationBannerHtml.js";
4
- import { Block as u, BlockCompositionType as I, ModificationDescription as o } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
5
- import { SETTINGS_ENUMS as a, DefaultConfigValues as i } from "./enums/settingsEnums.js";
6
- import { getDefaultTemplate as C } from "./template.js";
7
- import { getItemsBlockContainer as y, getItemsBlockConfig as b, getDefaultItemsBlockConfig as h } from "./utils/nodeConfigUtils.js";
8
- const c = g.Items;
9
- class E extends u {
3
+ import { getMigrationBannerHtml as C } from "../../../utils/migrationBannerHtml.js";
4
+ import { Block as I, BlockCompositionType as y, ModificationDescription as s } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
5
+ import { SETTINGS_ENUMS as c, DefaultConfigValues as a } from "./enums/settingsEnums.js";
6
+ import { getDefaultTemplate as h } from "./template.js";
7
+ import { getItemsBlockContainer as l, getItemsBlockConfig as m, getDefaultItemsBlockConfig as b } from "./utils/nodeConfigUtils.js";
8
+ const d = u.Items;
9
+ class E extends I {
10
10
  getId() {
11
- return c;
11
+ return d;
12
12
  }
13
13
  getIcon() {
14
14
  return "items-icon";
15
15
  }
16
16
  getBlockCompositionType() {
17
- return I.CONTAINER;
17
+ return y.CONTAINER;
18
18
  }
19
19
  getName() {
20
20
  return this.api.translate("Items");
@@ -23,41 +23,60 @@ class E extends u {
23
23
  return this.api.translate("Items lets you display personalized products based on user behavior.");
24
24
  }
25
25
  getSettingsPanelTitleHtml() {
26
- return f(
27
- c,
26
+ return C(
27
+ d,
28
28
  this.api.translate("Items"),
29
29
  this.api.translate("This block is switched from the Old Version to the New Version. We recommend you check the Items block and test your message to ensure it works properly.")
30
30
  );
31
31
  }
32
32
  getTemplate() {
33
- return C({
34
- orientation: a.ORIENTATION.VERTICAL,
35
- itemsType: a.ITEMS_TYPE.CART_ITEMS,
33
+ return h({
34
+ orientation: c.ORIENTATION.VERTICAL,
35
+ itemsType: c.ITEMS_TYPE.CART_ITEMS,
36
36
  itemId: "{{Abandoned Cart Item (1) Url}}",
37
- currencySymbol: i.productPriceCurrencySymbolControlValue,
38
- currencyLocation: i.productPriceCurrencyLocationControlValue,
39
- formattedPrice: i.productPriceFormattedControlValue === "1"
37
+ currencySymbol: a.productPriceCurrencySymbolControlValue,
38
+ currencyLocation: a.productPriceCurrencyLocationControlValue,
39
+ formattedPrice: a.productPriceFormattedControlValue === "1"
40
40
  });
41
41
  }
42
42
  allowInnerBlocksDND() {
43
43
  return !1;
44
44
  }
45
- onCreated(n) {
46
- const l = this.api.getDocumentModifier(), r = this.api.getDocumentRootCssNode();
47
- r.querySelector('[product-attr="imageSrc"] img') || l.modifyCss(r).appendRule('[product-attr="imageSrc"] img {object-fit: contain;}');
48
- const e = y(n);
49
- if (!e)
45
+ canBeSavedAsModule() {
46
+ return !0;
47
+ }
48
+ onCreated(i) {
49
+ const n = this.api.getDocumentModifier(), r = this.api.getDocumentRootCssNode();
50
+ r.querySelector('[product-attr="imageSrc"] img') || n.modifyCss(r).appendRule('[product-attr="imageSrc"] img {object-fit: contain;}');
51
+ const t = l(i);
52
+ if (!t)
50
53
  return;
51
- const s = e.getNodeConfig(), m = s && Object.keys(s).length > 0, t = b(n);
52
- if (t != null && t.initialized)
53
- m ? t.blockInstanceId || this.api.getDocumentModifier().modifyHtml(e).setNodeConfig({ ...t, blockInstanceId: String(Date.now()) }).apply(new o("Assign block instance ID to block")) : this.api.getDocumentModifier().modifyHtml(e).setNodeConfig(t).apply(new o("Migrate legacy config to nodeConfig"));
54
+ const e = t.getNodeConfig(), g = e && Object.keys(e).length > 0, o = m(i);
55
+ if (o != null && o.initialized)
56
+ g ? o.blockInstanceId || this.api.getDocumentModifier().modifyHtml(t).setNodeConfig({ ...o, blockInstanceId: String(Date.now()) }).apply(new s("Assign block instance ID to block")) : this.api.getDocumentModifier().modifyHtml(t).setNodeConfig(o).apply(new s("Migrate legacy config to nodeConfig"));
54
57
  else {
55
- const d = h();
56
- this.api.getDocumentModifier().modifyHtml(e).setNodeConfig(d).apply(new o("Initialize Items block with default configuration")), p().startOnboarding("itemsOnboarding");
58
+ const f = b();
59
+ this.api.getDocumentModifier().modifyHtml(t).setNodeConfig(f).apply(new s("Initialize Items block with default configuration")), p().startOnboarding("itemsOnboarding");
57
60
  }
58
61
  }
62
+ /**
63
+ * Re-seeds nodeConfig from the persisted esd-ext-config when a saved module
64
+ * surfaces via document load. Stripo strips esd-ext-config and never restores it
65
+ * into nodeConfig, so without this a reused module would reset to defaults.
66
+ * Guarded to the nodeConfig-empty case so it runs once and never loops.
67
+ */
68
+ onDocumentChanged(i) {
69
+ const n = l(i);
70
+ if (!n)
71
+ return;
72
+ const r = n.getNodeConfig();
73
+ if (r && Object.keys(r).length > 0)
74
+ return;
75
+ const e = m(i);
76
+ e != null && e.initialized && this.api.getDocumentModifier().modifyHtml(n).setNodeConfig(e).apply(new s("Recover Items block config from saved module"));
77
+ }
59
78
  }
60
79
  export {
61
- c as BLOCK_ID,
80
+ d as BLOCK_ID,
62
81
  E as ItemsBlock
63
82
  };
@@ -1,36 +1,36 @@
1
1
  import { ModificationDescription as b } from "../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
2
- import { DefaultConfigValues as o, SETTINGS_ENUMS as n, ItemInCartOptions as g } from "../enums/settingsEnums.js";
2
+ import { DefaultConfigValues as i, SETTINGS_ENUMS as n, ItemInCartOptions as g } from "../enums/settingsEnums.js";
3
3
  function _() {
4
4
  return String(Date.now() + Math.floor(Math.random() * 1e3));
5
5
  }
6
6
  const E = (r) => r.replace(/\$/g, "$$$$");
7
- function S() {
7
+ function y() {
8
8
  return {
9
9
  initialized: !0,
10
10
  blockInstanceId: _(),
11
11
  source: n.ITEMS_TYPE.CART_ITEMS,
12
12
  type: n.ITEMS_TYPE.CART_ITEMS,
13
- itemsSelectValue: o.cartItemsSelectControlValue,
13
+ itemsSelectValue: i.cartItemsSelectControlValue,
14
14
  orientation: n.ORIENTATION.VERTICAL,
15
- nameTrimming: o.productNameTrimmingControlValue === "1",
16
- priceHideDiscount: o.productPriceHideDiscountControlValue === "1",
17
- priceFormatted: o.productPriceFormattedControlValue === "1",
15
+ nameTrimming: i.productNameTrimmingControlValue === "1",
16
+ priceHideDiscount: i.productPriceHideDiscountControlValue === "1",
17
+ priceFormatted: i.productPriceFormattedControlValue === "1",
18
18
  priceSinglePrice: !1,
19
- priceCurrencySymbol: o.productPriceCurrencySymbolControlValue,
20
- priceCurrencyLocation: o.productPriceCurrencyLocationControlValue,
19
+ priceCurrencySymbol: i.productPriceCurrencySymbolControlValue,
20
+ priceCurrencyLocation: i.productPriceCurrencyLocationControlValue,
21
21
  priceOrientation: "horizontal",
22
- quantityControlEnabled: o.productQuantityControlEnabled === "1",
23
- buttonLink: o.productButtonLinkControlValue,
24
- imageLink: o.productImageLinkControlValue,
22
+ quantityControlEnabled: i.productQuantityControlEnabled === "1",
23
+ buttonLink: i.productButtonLinkControlValue,
24
+ imageLink: i.productImageLinkControlValue,
25
25
  buttonLabel: "Buy",
26
26
  buttonFullWidth: !0,
27
27
  // Default to full width (es-fw class)
28
- imageVisible: o.productImageVisible === "1",
29
- nameVisible: o.productNameVisible === "1",
30
- quantityVisible: o.productQuantityVisible === "1",
31
- priceVisible: o.productPriceVisible === "1",
32
- originalPriceVisible: o.productOriginalPriceVisible === "1",
33
- buttonVisible: o.productButtonVisible === "1"
28
+ imageVisible: i.productImageVisible === "1",
29
+ nameVisible: i.productNameVisible === "1",
30
+ quantityVisible: i.productQuantityVisible === "1",
31
+ priceVisible: i.productPriceVisible === "1",
32
+ originalPriceVisible: i.productOriginalPriceVisible === "1",
33
+ buttonVisible: i.productButtonVisible === "1"
34
34
  };
35
35
  }
36
36
  function p(r) {
@@ -50,26 +50,26 @@ function m(r) {
50
50
  PURCHASED_ITEMS: n.ITEMS_TYPE.PURCHASED_ITEMS
51
51
  }[r] || n.ITEMS_TYPE.CART_ITEMS : n.ITEMS_TYPE.CART_ITEMS;
52
52
  }
53
- function I(r, t) {
53
+ function f(r, t) {
54
54
  if (!r)
55
- return o.cartItemsSelectControlValue;
55
+ return i.cartItemsSelectControlValue;
56
56
  if (r.includes("{{"))
57
57
  return r;
58
58
  if (/^\d+$/.test(r)) {
59
- const e = parseInt(r) - 1, i = g[t];
60
- if (i && i[e])
61
- return i[e].value;
59
+ const e = parseInt(r) - 1, o = g[t];
60
+ if (o && o[e])
61
+ return o[e].value;
62
62
  }
63
- return o.cartItemsSelectControlValue;
63
+ return i.cartItemsSelectControlValue;
64
64
  }
65
65
  function C(r) {
66
66
  const t = r.querySelector("esd-config-block");
67
67
  if (!t)
68
68
  return null;
69
- const e = (c, s) => c == null ? s : c === "1" || c === "true", i = (c, s) => c || s, u = t.getAttribute("data-type"), a = m(u), d = t.getAttribute("data-cart_items_select_control_value"), l = I(d, a);
69
+ const e = (u, s) => u == null ? s : u === "1" || u === "true", o = (u, s) => u || s, c = t.getAttribute("data-type"), a = m(c), d = t.getAttribute("data-cart_items_select_control_value"), l = f(d, a);
70
70
  return {
71
71
  initialized: e(t.getAttribute("data-initialized"), !1),
72
- blockInstanceId: i(
72
+ blockInstanceId: o(
73
73
  t.getAttribute("data-block-instance-id"),
74
74
  _()
75
75
  ),
@@ -93,28 +93,28 @@ function C(r) {
93
93
  t.getAttribute("data-product_price_control_single_price"),
94
94
  !1
95
95
  ),
96
- priceCurrencySymbol: i(
96
+ priceCurrencySymbol: o(
97
97
  t.getAttribute("data-product_price_control_currency_symbol"),
98
- o.productPriceCurrencySymbolControlValue
98
+ i.productPriceCurrencySymbolControlValue
99
99
  ),
100
- priceCurrencyLocation: i(
100
+ priceCurrencyLocation: o(
101
101
  t.getAttribute("data-product_price_currency_location"),
102
- o.productPriceCurrencyLocationControlValue
102
+ i.productPriceCurrencyLocationControlValue
103
103
  ),
104
104
  priceOrientation: t.getAttribute("data-product_original_price_control_orientation") || "horizontal",
105
105
  quantityControlEnabled: e(
106
106
  t.getAttribute("data-product_quantity_control_enabled"),
107
107
  !0
108
108
  ),
109
- buttonLink: i(
109
+ buttonLink: o(
110
110
  t.getAttribute("data-product_button_link"),
111
- o.productButtonLinkControlValue
111
+ i.productButtonLinkControlValue
112
112
  ),
113
- imageLink: i(
113
+ imageLink: o(
114
114
  t.getAttribute("data-product_image_link"),
115
- o.productImageLinkControlValue
115
+ i.productImageLinkControlValue
116
116
  ),
117
- buttonLabel: i(
117
+ buttonLabel: o(
118
118
  t.getAttribute("data-product_button_control_label"),
119
119
  "Buy"
120
120
  ),
@@ -149,28 +149,45 @@ function C(r) {
149
149
  )
150
150
  };
151
151
  }
152
- function y(r) {
152
+ function I(r) {
153
+ if (typeof r.getAttribute != "function")
154
+ return null;
155
+ const t = r.getAttribute("esd-ext-config");
156
+ if (!t)
157
+ return null;
158
+ try {
159
+ const e = JSON.parse(t);
160
+ if (e && e.initialized)
161
+ return e;
162
+ } catch {
163
+ }
164
+ return null;
165
+ }
166
+ function A(r) {
153
167
  const t = p(r);
154
168
  if (!t)
155
169
  return null;
156
170
  const e = t.getNodeConfig();
157
171
  if (e && e.initialized)
158
172
  return e;
159
- const i = C(t);
160
- return i || null;
173
+ const o = I(t);
174
+ if (o)
175
+ return o;
176
+ const c = C(t);
177
+ return c || null;
161
178
  }
162
- function A(r, t, e, i) {
163
- const u = p(r);
164
- if (!u)
179
+ function V(r, t, e, o) {
180
+ const c = p(r);
181
+ if (!c)
165
182
  return;
166
- const d = { ...u.getNodeConfig() || {}, ...e }, l = i ?? t.getDocumentModifier();
167
- l.modifyHtml(u).setNodeConfig(d), i || l.apply(new b("Update Items block configuration"));
183
+ const d = { ...c.getNodeConfig() || {}, ...e }, l = o ?? t.getDocumentModifier();
184
+ l.modifyHtml(c).setNodeConfig(d), o || l.apply(new b("Update Items block configuration"));
168
185
  }
169
186
  export {
170
187
  E as escapeReplacement,
171
188
  _ as generateBlockInstanceId,
172
- S as getDefaultItemsBlockConfig,
173
- y as getItemsBlockConfig,
189
+ y as getDefaultItemsBlockConfig,
190
+ A as getItemsBlockConfig,
174
191
  p as getItemsBlockContainer,
175
- A as setItemsBlockConfig
192
+ V as setItemsBlockConfig
176
193
  };
@@ -1,20 +1,19 @@
1
1
  var S = Object.defineProperty;
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";
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
5
  import { ToasterTypeOptions as A } from "../../../enums/toaster.js";
6
6
  import { PAGE_TYPES as h } from "../../../enums/unsubscribe.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";
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";
11
10
  import { UNSUBSCRIBE_BLOCK_SELECTOR as m, DATA_ATTRIBUTES as n, UNSUBSCRIBE_EVENTS as b } from "./utils/constants.js";
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 = {
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 = {
14
13
  [h.GLOBAL_UNSUBSCRIBE]: "{{ins-global-unsubscribe-link}}",
15
14
  [h.SUBSCRIPTION_PREFERENCE_CENTER]: "{{ins-preferences-unsubscribe-link}}"
16
- }, P = 3;
17
- class W extends T {
15
+ }, w = 3;
16
+ class H extends y {
18
17
  constructor() {
19
18
  super();
20
19
  a(this, "selectEventListener", null);
@@ -30,13 +29,13 @@ class W extends T {
30
29
  a(this, "guardAttemptsByBlockId", /* @__PURE__ */ new Map());
31
30
  }
32
31
  getId() {
33
- return N;
32
+ return C;
34
33
  }
35
34
  getIcon() {
36
35
  return "unsubscribe-icon";
37
36
  }
38
37
  getBlockCompositionType() {
39
- return I.BLOCK;
38
+ return T.BLOCK;
40
39
  }
41
40
  getName() {
42
41
  return this.api.translate("Unsubscribe Block");
@@ -45,16 +44,15 @@ class W extends T {
45
44
  return this.api.translate("Unsubscribe Block Description");
46
45
  }
47
46
  getTemplate() {
48
- return C();
47
+ return v();
49
48
  }
50
49
  getContextActionsIds() {
51
- return [B.MOVE, B.REMOVE];
50
+ return [k.MOVE, k.REMOVE];
52
51
  }
53
52
  onSelect(e) {
54
- if (this.currentNode = e, y().isPreviewModeOpen)
55
- return;
53
+ this.currentNode = e;
56
54
  const t = this._getOrAssignBlockId(e);
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());
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());
58
56
  }
59
57
  onCreated(e) {
60
58
  this._ensureLeadingTextGuard(e);
@@ -109,9 +107,9 @@ class W extends T {
109
107
  const g = this._getOrAssignBlockId(e);
110
108
  if (!g)
111
109
  return;
112
- const k = this.guardAttemptsByBlockId.get(g) ?? 0;
113
- if (!(k >= P)) {
114
- this.guardAttemptsByBlockId.set(g, k + 1);
110
+ const _ = this.guardAttemptsByBlockId.get(g) ?? 0;
111
+ if (!(_ >= w)) {
112
+ this.guardAttemptsByBlockId.set(g, _ + 1);
115
113
  try {
116
114
  this.api.getDocumentModifier().modifyHtml(r).prepend(" ").apply(new d("Ensure unsubscribe link text guard"));
117
115
  } catch (p) {
@@ -156,8 +154,8 @@ class W extends T {
156
154
  const t = this.api.getDocumentRoot();
157
155
  t && "querySelectorAll" in t && t.querySelectorAll(m).forEach((r) => {
158
156
  if ("getAttribute" in r) {
159
- const i = r.getAttribute(n.BLOCK_ID), u = i ? parseInt(i) : 0;
160
- u > e && (e = u);
157
+ const i = r.getAttribute(n.BLOCK_ID), l = i ? parseInt(i) : 0;
158
+ l > e && (e = l);
161
159
  }
162
160
  });
163
161
  } catch {
@@ -166,14 +164,14 @@ class W extends T {
166
164
  }
167
165
  _warnLinkRemoved() {
168
166
  try {
169
- const { showToaster: e } = L();
167
+ const { showToaster: e } = f();
170
168
  e({
171
169
  type: A.Warning,
172
- message: this.api.translate(D),
170
+ message: this.api.translate(R),
173
171
  actionButton: {
174
172
  text: this.api.translate("Visit Academy"),
175
173
  onClick: () => {
176
- window.open(R, "_blank", "noopener,noreferrer");
174
+ window.open(U, "_blank", "noopener,noreferrer");
177
175
  }
178
176
  }
179
177
  });
@@ -190,10 +188,9 @@ class W extends T {
190
188
  _removeSelectEventListener() {
191
189
  this.selectEventListener && (document.removeEventListener(b.SELECT, this.selectEventListener), this.selectEventListener = null);
192
190
  }
193
- _setupCancelEventListener(e) {
194
- this._removeCancelEventListener(), this.cancelEventListener = (t) => {
195
- const { detail: s } = t;
196
- ((s == null ? void 0 : s.blockId) ?? null) === e && this._handleCancel();
191
+ _setupCancelEventListener() {
192
+ this._removeCancelEventListener(), this.cancelEventListener = () => {
193
+ this._handleCancel();
197
194
  }, document.addEventListener(b.CANCEL, this.cancelEventListener);
198
195
  }
199
196
  _removeCancelEventListener() {
@@ -203,7 +200,7 @@ class W extends T {
203
200
  try {
204
201
  if (!this.currentNode)
205
202
  return;
206
- this.api.getDocumentModifier().modifyHtml(this.currentNode).replaceWith(`<${v.EMPTY_CONTAINER}/>`).apply(new d("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"));
207
204
  } catch (e) {
208
205
  console.warn("[UnsubscribeBlock] Failed to remove unsubscribe block:", e);
209
206
  }
@@ -221,19 +218,19 @@ class W extends T {
221
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"));
222
219
  }
223
220
  _getMergeTag(e) {
224
- return w[e] ?? U;
221
+ return D[e] ?? N;
225
222
  }
226
223
  _openDrawer() {
227
224
  if (!(this.currentNode && this.currentNode.getAttribute("data-unsubscribe-page-type")))
228
225
  try {
229
- const e = l();
226
+ const e = u();
230
227
  e.typeSelectionDrawerStatus = !0;
231
228
  } catch (e) {
232
229
  console.error("[UnsubscribeBlock] Failed to open drawer:", e);
233
230
  }
234
231
  }
235
232
  _checkExistingBlocks() {
236
- const e = l();
233
+ const e = u();
237
234
  e.isGlobalUnsubscribeDisabled = !1, e.isSubscriptionPreferencesCenterDisabled = !1, this.api.getDocumentRoot().querySelectorAll(m).forEach((s) => {
238
235
  if ("getAttribute" in s) {
239
236
  const r = s.getAttribute(n.PAGE_TYPE);
@@ -250,11 +247,11 @@ class W extends T {
250
247
  const t = e.getAttribute(n.PAGE_TYPE), s = e.getAttribute(n.PAGE_LIST);
251
248
  if (!t || !s)
252
249
  return;
253
- const r = l(), i = Number(t), u = _(s);
254
- await r.fetchTemplates(), r.setCollectionWithoutAutoSelection(i), r.loadSelectedTemplates(u);
250
+ const r = u(), i = Number(t), l = B(s);
251
+ await r.fetchTemplates(), r.setCollectionWithoutAutoSelection(i), r.loadSelectedTemplates(l);
255
252
  }
256
253
  _resetStoreState() {
257
- l().$reset();
254
+ u().$reset();
258
255
  }
259
256
  _removeBlockTemplatesFromStore(e) {
260
257
  if (!("getAttribute" in e))
@@ -262,11 +259,11 @@ class W extends T {
262
259
  const t = e.getAttribute(n.PAGE_LIST);
263
260
  if (!t)
264
261
  return;
265
- const s = l(), r = _(t);
262
+ const s = u(), r = B(t);
266
263
  s.removeUnsubscribePages(r);
267
264
  }
268
265
  }
269
266
  export {
270
- N as UNSUBSCRIBE_BLOCK_ID,
271
- W as UnsubscribeBlock
267
+ C as UNSUBSCRIBE_BLOCK_ID,
268
+ H as UnsubscribeBlock
272
269
  };
@@ -1,19 +1,18 @@
1
1
  var T = Object.defineProperty;
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";
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);
5
4
  import { useUnsubscribeStore as l } from "../../../stores/unsubscribe.js";
6
- import { Control as g, UEAttr as i, UIElementType as n } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
5
+ import { Control as _, UEAttr as i, UIElementType as n } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
7
6
  import { DATA_ATTRIBUTES as d } from "./utils/constants.js";
8
7
  import { parsePageList as h } from "./utils/utils.js";
9
- const v = "ui-elements-unsubscribe", r = {
8
+ const g = "ui-elements-unsubscribe", r = {
10
9
  SELECT_BUTTON: "selectTemplateButton",
11
10
  PREV_BUTTON: "prevButton",
12
11
  NEXT_BUTTON: "nextButton",
13
12
  COUNTER_TEXT: "counterText",
14
13
  PREVIEW_IMAGE: "previewImage"
15
14
  };
16
- class w extends g {
15
+ class B extends _ {
17
16
  constructor() {
18
17
  super(...arguments);
19
18
  c(this, "currentPreviewIndex", 0);
@@ -23,7 +22,7 @@ class w extends g {
23
22
  c(this, "lastParsedAttribute");
24
23
  }
25
24
  getId() {
26
- return v;
25
+ return g;
27
26
  }
28
27
  getTemplate() {
29
28
  return `
@@ -60,12 +59,10 @@ class w extends g {
60
59
  this.api.onValueChanged(r.NEXT_BUTTON, () => this._onNextClick())
61
60
  );
62
61
  }
63
- async _onButtonClick() {
62
+ _onButtonClick() {
64
63
  try {
65
- if (_().isPreviewModeOpen)
66
- return;
67
64
  const e = l();
68
- await e.fetchTemplates(!0), this._reseedSelectionFromBlock(), 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;
69
66
  } catch (e) {
70
67
  console.error("[UnsubscribeControl] Failed to open drawer:", e);
71
68
  }
@@ -74,8 +71,8 @@ class w extends g {
74
71
  const e = l();
75
72
  if (e.$reset(), !this.currentNode || !("getAttribute" in this.currentNode))
76
73
  return;
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)));
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)));
79
76
  }
80
77
  _onPrevClick() {
81
78
  this.currentPreviewIndex > 0 && (this.currentPreviewIndex--, this._updatePreview(), this._updateCounter());
@@ -103,8 +100,8 @@ class w extends g {
103
100
  }
104
101
  }
105
102
  _updateCounter() {
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(
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(
108
105
  r.COUNTER_TEXT,
109
106
  i.LABEL.text,
110
107
  `${this.api.translate("Showing")} ${e} ${this.api.translate("of")} ${t}`
@@ -145,8 +142,8 @@ class w extends g {
145
142
  </${n.LABEL}>
146
143
  `;
147
144
  }
148
- _getIconButton(e, t, o) {
149
- const u = o ? `${i.BUTTON.disabled}="true"` : "";
145
+ _getIconButton(e, t, a) {
146
+ const u = a ? `${i.BUTTON.disabled}="true"` : "";
150
147
  return `
151
148
  <${n.BUTTON}
152
149
  id="${e}"
@@ -175,6 +172,6 @@ class w extends g {
175
172
  }
176
173
  }
177
174
  export {
178
- v as UNSUBSCRIBE_CONTROL_ID,
179
- w as UnsubscribeControl
175
+ g as UNSUBSCRIBE_CONTROL_ID,
176
+ B as UnsubscribeControl
180
177
  };
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-669fe7cf]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-669fe7cf]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-669fe7cf]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-669fe7cf]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-669fe7cf]{object-fit:cover;transform:scale(1)}[data-v-7a305bb2] .guido__verion-history-view-option-selection-desktop svg,[data-v-7a305bb2] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-7a305bb2] .in-segments-wrapper__button_selected,[data-v-7a305bb2] .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}
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-18e1220a] .guido__verion-history-view-option-selection-desktop svg,[data-v-18e1220a] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-18e1220a] .in-segments-wrapper__button_selected,[data-v-18e1220a] .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,4 +1,3 @@
1
1
  export declare const useUnsubscribeBlockValidator: () => {
2
2
  validateUnsubscribeBlockUniqueness: (html: string) => boolean;
3
- validateUnsubscribeBlockHasTemplate: (html: string) => boolean;
4
3
  };
@@ -24,5 +24,13 @@ export declare class ItemsBlock extends Block {
24
24
  getSettingsPanelTitleHtml(): string;
25
25
  getTemplate(): string;
26
26
  allowInnerBlocksDND(): boolean;
27
+ canBeSavedAsModule(): boolean;
27
28
  onCreated(node: ImmutableHtmlNode): void;
29
+ /**
30
+ * Re-seeds nodeConfig from the persisted esd-ext-config when a saved module
31
+ * surfaces via document load. Stripo strips esd-ext-config and never restores it
32
+ * into nodeConfig, so without this a reused module would reset to defaults.
33
+ * Guarded to the nodeConfig-empty case so it runs once and never loops.
34
+ */
35
+ onDocumentChanged(node: ImmutableHtmlNode): void;
28
36
  }
@@ -55,7 +55,7 @@ export declare function getItemsBlockContainer(currentNode: ImmutableHtmlNode |
55
55
  /**
56
56
  * Gets the node configuration from the Items block.
57
57
  * Uses Stripo V2's getNodeConfig() API.
58
- * Falls back to migrating from legacy config block if nodeConfig is empty.
58
+ * Falls back to the persisted esd-ext-config (saved modules), then legacy config block.
59
59
  * @param currentNode - The current node from the control
60
60
  * @returns The ItemsBlockConfig object or null if not found
61
61
  */