@useinsider/guido 2.1.0-beta.7ffef92 → 2.1.0-beta.84a7014

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 (64) hide show
  1. package/README.md +41 -2
  2. package/dist/@types/config/schemas.js +1 -1
  3. package/dist/components/Guido.vue.js +1 -1
  4. package/dist/components/Guido.vue2.js +66 -66
  5. package/dist/components/organisms/extensions/recommendation/FilterItem.vue.js +13 -11
  6. package/dist/components/organisms/extensions/recommendation/FilterItem.vue2.js +24 -55
  7. package/dist/components/organisms/extensions/recommendation/FilterSelectionDrawer.vue.js +3 -3
  8. package/dist/components/organisms/extensions/recommendation/FilterSelectionDrawer.vue2.js +21 -34
  9. package/dist/components/organisms/extensions/recommendation/Filters.vue.js +9 -9
  10. package/dist/components/organisms/extensions/recommendation/Filters.vue2.js +35 -44
  11. package/dist/components/organisms/unsubscribe/UnsubscribePageSelection.vue.js +1 -1
  12. package/dist/components/organisms/unsubscribe/UnsubscribePageSelection.vue2.js +19 -19
  13. package/dist/composables/useSave.js +16 -12
  14. package/dist/composables/useStripo.js +63 -57
  15. package/dist/composables/useStripoEventHandler.js +27 -12
  16. package/dist/composables/useSyncModuleExtractor.js +45 -0
  17. package/dist/composables/useVersionHistoryApi.js +1 -1
  18. package/dist/config/i18n/en/index.js +11 -0
  19. package/dist/config/i18n/en/labels.json.js +7 -0
  20. package/dist/config/i18n/en/toasters.json.js +56 -0
  21. package/dist/config/i18n/en/tooltips.json.js +82 -0
  22. package/dist/config/i18n/index.js +7 -0
  23. package/dist/config/migrator/itemsBlockMigrator.js +65 -64
  24. package/dist/enums/unsubscribe.js +25 -21
  25. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +39 -58
  26. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +57 -93
  27. package/dist/extensions/Blocks/Recommendation/utils/filterUtil.js +8 -8
  28. package/dist/extensions/Blocks/Unsubscribe/block.js +29 -29
  29. package/dist/extensions/Blocks/Unsubscribe/control.js +12 -9
  30. package/dist/extensions/Blocks/Unsubscribe/elements/preview.js +13 -11
  31. package/dist/extensions/Blocks/Unsubscribe/styles.css.js +31 -1
  32. package/dist/guido.css +1 -1
  33. package/dist/services/stripoApi.js +55 -19
  34. package/dist/src/@types/config/schemas.d.ts +1 -1
  35. package/dist/src/@types/events.d.ts +38 -2
  36. package/dist/src/components/Guido.vue.d.ts +2 -2
  37. package/dist/src/components/organisms/extensions/recommendation/FilterItem.vue.d.ts +0 -1
  38. package/dist/src/components/organisms/extensions/recommendation/Filters.vue.d.ts +1 -15
  39. package/dist/src/components/organisms/header/EditorActions.vue.d.ts +1 -1
  40. package/dist/src/components/organisms/header/HeaderWrapper.vue.d.ts +1 -1
  41. package/dist/src/components/organisms/header/RightSlot.vue.d.ts +1 -1
  42. package/dist/src/composables/useGuidoActions.d.ts +1 -1
  43. package/dist/src/composables/useSave.d.ts +2 -2
  44. package/dist/src/composables/useStripo.d.ts +2 -2
  45. package/dist/src/composables/useSyncModuleExtractor.d.ts +4 -0
  46. package/dist/src/config/i18n/en/index.d.ts +1 -0
  47. package/dist/src/config/i18n/index.d.ts +16 -0
  48. package/dist/src/enums/unsubscribe.d.ts +3 -0
  49. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +0 -5
  50. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +2 -18
  51. package/dist/src/extensions/Blocks/Unsubscribe/control.d.ts +1 -0
  52. package/dist/src/mock/api/settings.d.ts +2 -0
  53. package/dist/src/services/stripoApi.d.ts +5 -0
  54. package/dist/src/stores/editor.d.ts +23 -0
  55. package/dist/src/utils/templatePreparation.d.ts +1 -1
  56. package/dist/static/styles/components/notification.css.js +18 -0
  57. package/dist/static/styles/components/tools.css.js +6 -2
  58. package/dist/static/styles/variables.css.js +2 -0
  59. package/dist/stores/editor.js +2 -1
  60. package/dist/stores/unsubscribe.js +37 -34
  61. package/dist/utils/templatePreparation.js +1 -1
  62. package/package.json +1 -1
  63. package/dist/extensions/Blocks/Recommendation/validation/filterSchema.js +0 -29
  64. package/dist/src/extensions/Blocks/Recommendation/validation/filterSchema.d.ts +0 -15
@@ -1,15 +1,14 @@
1
- import { RecommendationFeedSourceMaps as d, getOperatorOptions as S, PriceAttributes as p } from "../../../../enums/extensions/recommendationBlock.js";
2
- import { useRecommendationApi as b } from "../../../../services/recommendationApi.js";
3
- import { useConfigStore as I } from "../../../../stores/config.js";
4
- import { defineStore as R } from "pinia";
5
- import { DEFAULT_CARDS_IN_ROW as k } from "../constants/layout.js";
6
- import { getDefaultProducts as C } from "../templates/utils.js";
1
+ import { RecommendationFeedSourceMaps as d, PriceAttributes as S } from "../../../../enums/extensions/recommendationBlock.js";
2
+ import { useRecommendationApi as p } from "../../../../services/recommendationApi.js";
3
+ import { useConfigStore as b } from "../../../../stores/config.js";
4
+ import { defineStore as I } from "pinia";
5
+ import { DEFAULT_CARDS_IN_ROW as R } from "../constants/layout.js";
6
+ import { getDefaultProducts as k } from "../templates/utils.js";
7
7
  import { generateCompleteFilterQuery as f } from "../utils/filterUtil.js";
8
- import { isFilterValid as y } from "../validation/filterSchema.js";
9
- const m = b();
8
+ const m = p();
10
9
  function h() {
11
10
  return {
12
- cardsInRow: k,
11
+ cardsInRow: R,
13
12
  currencySettings: {
14
13
  name: "USD",
15
14
  value: "USD",
@@ -33,18 +32,17 @@ function h() {
33
32
  size: "6"
34
33
  };
35
34
  }
36
- function G() {
35
+ function C() {
37
36
  return {
38
37
  recommendationConfigs: h(),
39
38
  recommendationProducts: [],
40
39
  filterStatus: !1,
41
40
  filterSelectionDrawerStatus: !1,
42
41
  filterGroup: 1,
43
- isInitialized: !1,
44
- filterSnapshot: null
42
+ isInitialized: !1
45
43
  };
46
44
  }
47
- const F = () => ({
45
+ const y = () => ({
48
46
  recommendationCampaignUrls: {},
49
47
  activePredictiveAlgorithms: [],
50
48
  languages: {},
@@ -53,8 +51,8 @@ const F = () => ({
53
51
  blockStates: {},
54
52
  currentRecommendationId: null,
55
53
  configVersion: 0
56
- }), V = R("guidoRecommendationExtension", {
57
- state: () => F(),
54
+ }), A = I("guidoRecommendationExtension", {
55
+ state: () => y(),
58
56
  getters: {
59
57
  // ====================================================================
60
58
  // Proxy Getters — Backward Compatible Access to Current Block State
@@ -96,17 +94,9 @@ const F = () => ({
96
94
  hasFilters() {
97
95
  return !!this.recommendationConfigs.filters.length;
98
96
  },
99
- hasValidFilters() {
100
- const { filters: t } = this.recommendationConfigs;
101
- return t.length ? t.every((r) => r.isValid) : !1;
102
- },
103
97
  getFilterGroupCount() {
104
98
  const { filters: t } = this.recommendationConfigs;
105
- return t.length ? new Set(t.map((r) => r.filterGroup)).size : 0;
106
- },
107
- getUniqueFilterGroups() {
108
- const { filters: t } = this.recommendationConfigs;
109
- return [...new Set(t.map((r) => r.filterGroup))].sort((r, e) => r - e);
99
+ return t.length && t[t.length - 1].filterGroup || 0;
110
100
  },
111
101
  getActivePredictiveAlgorithms: (t) => {
112
102
  const r = [];
@@ -127,7 +117,7 @@ const F = () => ({
127
117
  })),
128
118
  getFilterList() {
129
119
  return Object.values(this.filterList).map((t) => {
130
- const r = t.type === "defaultAttribute", e = p.includes(t.attributeName);
120
+ const r = t.type === "defaultAttribute", e = S.includes(t.attributeName);
131
121
  let n = r ? t.attributeName : `product_attributes.${t.attributeName}`;
132
122
  return n = e ? `${n}.${this.recommendationConfigs.currencySettings.value}` : n, {
133
123
  text: t.displayName,
@@ -151,7 +141,7 @@ const F = () => ({
151
141
  setCurrentBlock(t) {
152
142
  this.blockStates[t] || (this.blockStates = {
153
143
  ...this.blockStates,
154
- [t]: G()
144
+ [t]: C()
155
145
  }), this.currentRecommendationId = t;
156
146
  },
157
147
  /**
@@ -191,56 +181,33 @@ const F = () => ({
191
181
  const { triggerRefetch: n = !0 } = r;
192
182
  n && this.configVersion++;
193
183
  },
194
- /**
195
- * Creates a filter with the first available attribute and operator pre-selected.
196
- */
197
- createDefaultFilter(t, r) {
198
- const [e] = this.getFilterList, [n] = S(e == null ? void 0 : e.type);
199
- return {
200
- type: "standardFilter",
201
- attribute: (e == null ? void 0 : e.value) ?? "",
202
- operator: (n == null ? void 0 : n.value) ?? "",
203
- innerGroupOperator: "*",
204
- outerGroupOperator: "*",
205
- filterNumber: r,
206
- filterGroup: t,
207
- isValid: !1,
208
- value: ""
209
- };
210
- },
211
184
  /**
212
185
  * Opens the filter selection drawer for the current block.
213
- * Saves a snapshot of current filters for cancel/revert.
214
- * If no filters exist, initializes with a default filter
186
+ * If no filters exist, initializes with a default empty filter
215
187
  * so the user has a starting point for input.
216
188
  */
217
189
  openFilterDrawer() {
218
190
  if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
219
191
  return;
220
192
  const t = this.blockStates[this.currentRecommendationId];
221
- t.filterSnapshot = JSON.parse(
222
- JSON.stringify(t.recommendationConfigs.filters)
223
- ), t.recommendationConfigs.filters.length || (t.recommendationConfigs.filters = [this.createDefaultFilter(1, 1)]), t.filterSelectionDrawerStatus = !0;
193
+ t.recommendationConfigs.filters.length || (t.recommendationConfigs.filters = [{
194
+ type: "standardFilter",
195
+ attribute: "",
196
+ operatorReplace: "",
197
+ operator: "",
198
+ innerGroupOperator: "*",
199
+ outerGroupOperator: "*",
200
+ filterNumber: 1,
201
+ filterGroup: 1,
202
+ isValid: !1,
203
+ value: ""
204
+ }]), t.filterSelectionDrawerStatus = !0;
224
205
  },
225
206
  /**
226
- * Closes the filter selection drawer for the current block.
227
- * Called after successful apply — discards the snapshot.
207
+ * Closes the filter selection drawer for the current block
228
208
  */
229
209
  closeFilterDrawer() {
230
- if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
231
- return;
232
- const t = this.blockStates[this.currentRecommendationId];
233
- t.filterSnapshot = null, t.filterSelectionDrawerStatus = !1;
234
- },
235
- /**
236
- * Cancels the filter selection drawer and reverts filters
237
- * to the snapshot taken when the drawer was opened.
238
- */
239
- cancelFilterDrawer() {
240
- if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
241
- return;
242
- const t = this.blockStates[this.currentRecommendationId];
243
- t.filterSnapshot !== null && (t.recommendationConfigs.filters = t.filterSnapshot, t.filterSnapshot = null), t.filterSelectionDrawerStatus = !1;
210
+ this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].filterSelectionDrawerStatus = !1);
244
211
  },
245
212
  // ====================================================================
246
213
  // Shared Data Fetching (fetched once, used by all blocks)
@@ -267,18 +234,18 @@ const F = () => ({
267
234
  // Per-Block Filter Actions
268
235
  // ====================================================================
269
236
  addFilterGroup(t) {
270
- this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || this.blockStates[this.currentRecommendationId].recommendationConfigs.filters.push(
271
- this.createDefaultFilter(t, 1)
272
- );
273
- },
274
- deleteFilterGroup(t) {
275
- if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
276
- return;
277
- const r = this.blockStates[this.currentRecommendationId], e = r.recommendationConfigs.filters.filter((i) => i.filterGroup !== t), n = [...new Set(e.map((i) => i.filterGroup))].sort((i, o) => i - o), s = new Map(n.map((i, o) => [i, o + 1]));
278
- r.recommendationConfigs.filters = e.map((i) => ({
279
- ...i,
280
- filterGroup: s.get(i.filterGroup) ?? i.filterGroup
281
- }));
237
+ this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || this.blockStates[this.currentRecommendationId].recommendationConfigs.filters.push({
238
+ type: "standardFilter",
239
+ attribute: "",
240
+ operatorReplace: "",
241
+ operator: "",
242
+ innerGroupOperator: "",
243
+ outerGroupOperator: "",
244
+ value: "",
245
+ filterNumber: 1,
246
+ isValid: !0,
247
+ filterGroup: t
248
+ });
282
249
  },
283
250
  updateFilter(t) {
284
251
  if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
@@ -286,10 +253,7 @@ const F = () => ({
286
253
  const r = this.blockStates[this.currentRecommendationId], e = r.recommendationConfigs.filters.findIndex((n) => n.filterNumber === t.filterNumber && n.filterGroup === t.filterGroup);
287
254
  if (e !== -1) {
288
255
  const n = [...r.recommendationConfigs.filters];
289
- n[e] = {
290
- ...t,
291
- isValid: y(t)
292
- }, r.recommendationConfigs.filters = n;
256
+ n[e] = t, t.value.length && t.operator && t.attribute && t.innerGroupOperator && t.outerGroupOperator ? n[e].isValid = !0 : n[e].isValid = !1, r.recommendationConfigs.filters = n;
293
257
  }
294
258
  },
295
259
  deleteFilter(t) {
@@ -304,15 +268,15 @@ const F = () => ({
304
268
  addFilter(t) {
305
269
  if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
306
270
  return;
307
- const r = this.blockStates[this.currentRecommendationId], e = [...r.recommendationConfigs.filters], s = e.filter(
308
- (o) => o.filterGroup === t.filterGroup
309
- ).length + 1, i = e.findLastIndex((o) => o.filterGroup === t.filterGroup);
310
- i !== -1 ? e.splice(i + 1, 0, {
271
+ const r = this.blockStates[this.currentRecommendationId], e = [...r.recommendationConfigs.filters], o = e.filter(
272
+ (i) => i.filterGroup === t.filterGroup
273
+ ).length + 1, s = e.findLastIndex((i) => i.filterGroup === t.filterGroup);
274
+ s !== -1 ? e.splice(s + 1, 0, {
311
275
  ...t,
312
- filterNumber: s
276
+ filterNumber: o
313
277
  }) : e.push({
314
278
  ...t,
315
- filterNumber: s
279
+ filterNumber: o
316
280
  }), r.recommendationConfigs.filters = e;
317
281
  },
318
282
  generateFilterQuery() {
@@ -325,26 +289,26 @@ const F = () => ({
325
289
  var u;
326
290
  if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
327
291
  return;
328
- const t = this.currentRecommendationId, r = this.blockStates[t], { recommendationConfigs: e } = r, n = e.filters.filter((l) => l.isValid), s = f(n), i = ((u = d.find((l) => l.key === e.strategy)) == null ? void 0 : u.path) || "", o = I(), c = {
292
+ const t = this.currentRecommendationId, r = this.blockStates[t], { recommendationConfigs: e } = r, n = e.filters.filter((l) => l.isValid), o = f(n), s = ((u = d.find((l) => l.key === e.strategy)) == null ? void 0 : u.path) || "", i = b(), c = {
329
293
  locale: e.language,
330
294
  currency: e.currencySettings.value,
331
- partnerName: o.partnerName,
295
+ partnerName: i.partnerName,
332
296
  size: e.size,
333
297
  details: !0,
334
- campaignId: o.variationId
298
+ campaignId: i.variationId
335
299
  };
336
- e.strategy === "manualMerchandising" ? c.productId = e.productIds.join(",") : e.strategy === "similarViewed" && (c.productId = "{itemId}"), s && (c.filter = s), e.shuffleProducts && (c.shuffle = !0);
300
+ e.strategy === "manualMerchandising" ? c.productId = e.productIds.join(",") : e.strategy === "similarViewed" && (c.productId = "{itemId}"), o && (c.filter = o), e.shuffleProducts && (c.shuffle = !0);
337
301
  const g = parseInt(e.size) || 6;
338
302
  let a;
339
303
  try {
340
- a = await m.fetchRecommendationProducts(i, c);
304
+ a = await m.fetchRecommendationProducts(s, c);
341
305
  } catch {
342
306
  a = [];
343
307
  }
344
- this.blockStates[t] && (this.blockStates[t].recommendationProducts = a.length > 0 ? a : C(g));
308
+ this.blockStates[t] && (this.blockStates[t].recommendationProducts = a.length > 0 ? a : k(g));
345
309
  }
346
310
  }
347
311
  });
348
312
  export {
349
- V as useRecommendationExtensionStore
313
+ A as useRecommendationExtensionStore
350
314
  };
@@ -1,22 +1,22 @@
1
1
  function l(t) {
2
2
  if (t.length === 0)
3
3
  return "";
4
- const o = t.sort((r, e) => r.filterNumber - e.filterNumber), n = o.map((r) => `[${r.attribute}][${r.operator}][${r.value}]`), [p, ...i] = n;
5
- let u = p;
6
- for (let r = 0; r < i.length; r++) {
7
- const e = o[r].innerGroupOperator;
8
- u += `${e}${i[r]}`;
4
+ const o = t.sort((r, e) => r.filterNumber - e.filterNumber), n = o.map((r) => `[${r.attribute}][${r.operatorReplace}][${r.value}]`), [i, ...p] = n;
5
+ let u = i;
6
+ for (let r = 0; r < p.length; r++) {
7
+ const e = o[r + 1].innerGroupOperator;
8
+ u += `${e}${p[r]}`;
9
9
  }
10
10
  return `(${u})`;
11
11
  }
12
12
  function f(t) {
13
13
  if (!t || t.length === 0)
14
14
  return "";
15
- const o = t.reduce((r, e) => (r[e.filterGroup] || (r[e.filterGroup] = []), r[e.filterGroup].push(e), r), {}), n = Object.keys(o).map(Number).sort((r, e) => r - e), p = n.map((r) => {
15
+ const o = t.reduce((r, e) => (r[e.filterGroup] || (r[e.filterGroup] = []), r[e.filterGroup].push(e), r), {}), n = Object.keys(o).map(Number).sort((r, e) => r - e), i = n.map((r) => {
16
16
  const e = o[r];
17
17
  return l(e);
18
- }), [i, ...u] = p;
19
- let s = i;
18
+ }), [p, ...u] = i;
19
+ let s = p;
20
20
  for (let r = 0; r < u.length; r++) {
21
21
  const e = n[r + 1], c = o[e][0].outerGroupOperator;
22
22
  s += `${c}${u[r]}`;
@@ -1,17 +1,17 @@
1
1
  var d = Object.defineProperty;
2
- var _ = (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) => _(n, typeof i != "symbol" ? i + "" : i, e);
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);
4
4
  import { PAGE_TYPES as E } from "../../../enums/unsubscribe.js";
5
5
  import { useUnsubscribeStore as c } from "../../../stores/unsubscribe.js";
6
- import { Block as h, BlockCompositionType as S, ModificationDescription as b } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
6
+ import { Block as _, BlockCompositionType as S, ModificationDescription as b } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
7
7
  import { getDefaultTemplate as L } from "./template.js";
8
8
  import { UNSUBSCRIBE_EVENTS as a, DATA_ATTRIBUTES as o } from "./utils/constants.js";
9
9
  import { parsePageList as p } from "./utils/utils.js";
10
- const g = "unsubscribe-block", v = 'a[data-unsubscribe-link="true"]', f = ".unsubscribe-block-v2", B = "{{ins-unsubscribe-link}}", T = {
10
+ const v = "unsubscribe-block", g = 'a[data-unsubscribe-link="true"]', f = ".unsubscribe-block-v2", T = "{{ins-unsubscribe-link}}", B = {
11
11
  [E.GLOBAL_UNSUBSCRIBE]: "{{ins-global-unsubscribe-link}}",
12
12
  [E.SUBSCRIPTION_PREFERENCE_CENTER]: "{{ins-preferences-unsubscribe-link}}"
13
13
  };
14
- class R extends h {
14
+ class R extends _ {
15
15
  constructor() {
16
16
  super();
17
17
  u(this, "selectEventListener", null);
@@ -19,7 +19,7 @@ class R extends h {
19
19
  u(this, "currentNode");
20
20
  }
21
21
  getId() {
22
- return g;
22
+ return v;
23
23
  }
24
24
  getIcon() {
25
25
  return "unsubscribe-icon";
@@ -47,8 +47,8 @@ class R extends h {
47
47
  }
48
48
  _setupSelectEventListener() {
49
49
  this._removeSelectEventListener(), this.selectEventListener = (e) => {
50
- const s = e, { collectionType: t, selectedPages: r } = s.detail;
51
- this._updateBlock(t, r.join(","));
50
+ const r = e, { collectionType: s, selectedPages: t } = r.detail;
51
+ this._updateBlock(s, t.join(","));
52
52
  }, document.addEventListener(a.SELECT, this.selectEventListener);
53
53
  }
54
54
  _removeSelectEventListener() {
@@ -74,17 +74,17 @@ class R extends h {
74
74
  _removeEventListeners() {
75
75
  this._removeSelectEventListener(), this._removeCancelEventListener();
76
76
  }
77
- _updateBlock(e, s) {
77
+ _updateBlock(e, r) {
78
78
  if (!this.currentNode || !("querySelector" in this.currentNode))
79
79
  return;
80
- const t = this.currentNode.querySelector(v);
81
- if (!t)
80
+ const s = this.currentNode.querySelector(g);
81
+ if (!s)
82
82
  return;
83
- const r = this._getMergeTag(e);
84
- this.api.getDocumentModifier().modifyHtml(t).setAttribute("href", r).apply(new b(`Updated unsubscribe link to ${r}`)), this.api.getDocumentModifier().modifyHtml(this.currentNode).setAttribute(o.PAGE_TYPE, e.toString()).setAttribute(o.PAGE_LIST, s).apply(new b("Updated unsubscribe block metadata"));
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"));
85
85
  }
86
86
  _getMergeTag(e) {
87
- return T[e] ?? B;
87
+ return B[e] ?? T;
88
88
  }
89
89
  _openDrawer() {
90
90
  if (!(this.currentNode && this.currentNode.getAttribute("data-unsubscribe-page-type")))
@@ -97,24 +97,24 @@ class R extends h {
97
97
  }
98
98
  _checkExistingBlocks() {
99
99
  const e = c();
100
- e.isGlobalUnsubscribeDisabled = !1, e.isSubscriptionPreferencesCenterDisabled = !1, this.api.getDocumentRoot().querySelectorAll(f).forEach((t) => {
101
- if ("getAttribute" in t) {
102
- const r = t.getAttribute(o.PAGE_TYPE);
103
- if (r) {
104
- const l = Number(r);
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
105
  l === E.GLOBAL_UNSUBSCRIBE ? e.isGlobalUnsubscribeDisabled = !0 : l === E.SUBSCRIPTION_PREFERENCE_CENTER && (e.isSubscriptionPreferencesCenterDisabled = !0);
106
106
  }
107
107
  }
108
108
  });
109
109
  }
110
- _loadBlockState(e) {
110
+ async _loadBlockState(e) {
111
111
  if (!("getAttribute" in e))
112
112
  return;
113
- const s = e.getAttribute(o.PAGE_TYPE), t = e.getAttribute(o.PAGE_LIST);
114
- if (!s || !t)
113
+ const r = e.getAttribute(o.PAGE_TYPE), s = e.getAttribute(o.PAGE_LIST);
114
+ if (!r || !s)
115
115
  return;
116
- const r = c(), l = Number(s), m = p(t);
117
- r.setCollectionWithoutAutoSelection(l), r.loadSelectedTemplates(m);
116
+ const t = c(), l = Number(r), m = p(s);
117
+ await t.fetchTemplates(), t.setCollectionWithoutAutoSelection(l), t.loadSelectedTemplates(m);
118
118
  }
119
119
  _resetStoreState() {
120
120
  c().$reset();
@@ -122,14 +122,14 @@ class R extends h {
122
122
  _removeBlockTemplatesFromStore(e) {
123
123
  if (!("getAttribute" in e))
124
124
  return;
125
- const s = e.getAttribute(o.PAGE_LIST);
126
- if (!s)
125
+ const r = e.getAttribute(o.PAGE_LIST);
126
+ if (!r)
127
127
  return;
128
- const t = c(), r = p(s);
129
- t.removeUnsubscribePages(r);
128
+ const s = c(), t = p(r);
129
+ s.removeUnsubscribePages(t);
130
130
  }
131
131
  }
132
132
  export {
133
- g as UNSUBSCRIBE_BLOCK_ID,
133
+ v as UNSUBSCRIBE_BLOCK_ID,
134
134
  R as UnsubscribeBlock
135
135
  };
@@ -1,18 +1,18 @@
1
- var h = Object.defineProperty;
2
- var d = (a, s, e) => s in a ? h(a, s, { enumerable: !0, configurable: !0, writable: !0, value: e }) : a[s] = e;
3
- var u = (a, s, e) => d(a, typeof s != "symbol" ? s + "" : s, e);
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);
4
4
  import { useUnsubscribeStore as l } from "../../../stores/unsubscribe.js";
5
5
  import { Control as T, UEAttr as i, UIElementType as n } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
6
6
  import { DATA_ATTRIBUTES as p } from "./utils/constants.js";
7
7
  import { parsePageList as _ } from "./utils/utils.js";
8
- const g = "ui-elements-unsubscribe", r = {
8
+ const v = "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 N extends T {
15
+ class B extends T {
16
16
  constructor() {
17
17
  super(...arguments);
18
18
  u(this, "currentPreviewIndex", 0);
@@ -22,7 +22,7 @@ class N extends T {
22
22
  u(this, "lastParsedAttribute");
23
23
  }
24
24
  getId() {
25
- return g;
25
+ return v;
26
26
  }
27
27
  getTemplate() {
28
28
  return `
@@ -35,7 +35,7 @@ class N extends T {
35
35
  onTemplateNodeUpdated(e) {
36
36
  if (this.currentNode = e, "getAttribute" in this.currentNode) {
37
37
  const t = this.currentNode.getAttribute(p.PAGE_LIST);
38
- t && (t !== this.lastParsedAttribute && (this.currentPages = _(t), this.lastParsedAttribute = t, this.currentPreviewIndex = 0), this._updatePreview(), this._updateCounter());
38
+ t && (t !== this.lastParsedAttribute && (this.currentPages = _(t), this.lastParsedAttribute = t, this.currentPreviewIndex = 0), this._updateCounter(), this._loadAndUpdatePreview());
39
39
  }
40
40
  }
41
41
  onRender() {
@@ -73,6 +73,9 @@ class N extends T {
73
73
  _onNextClick() {
74
74
  this.currentPreviewIndex < this.totalTemplates - 1 && (this.currentPreviewIndex++, this._updatePreview(), this._updateCounter());
75
75
  }
76
+ async _loadAndUpdatePreview() {
77
+ await l().fetchTemplates(), this._updatePreview(), this._updateCounter();
78
+ }
76
79
  _updatePreview() {
77
80
  var e;
78
81
  if ((e = this.currentPages) != null && e.length)
@@ -162,6 +165,6 @@ class N extends T {
162
165
  }
163
166
  }
164
167
  export {
165
- g as UNSUBSCRIBE_CONTROL_ID,
166
- N as UnsubscribeControl
168
+ v as UNSUBSCRIBE_CONTROL_ID,
169
+ B as UnsubscribeControl
167
170
  };
@@ -1,12 +1,12 @@
1
- var r = Object.defineProperty;
2
- var n = (i, t, e) => t in i ? r(i, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : i[t] = e;
3
- var s = (i, t, e) => n(i, typeof t != "symbol" ? t + "" : t, e);
4
- import { UIElement as m } from "../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
5
- const E = "unsubscribe-preview", l = "img", c = "Unsubscribe page preview";
6
- class o extends m {
1
+ var n = Object.defineProperty;
2
+ var m = (s, i, e) => i in s ? n(s, i, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[i] = e;
3
+ var r = (s, i, e) => m(s, typeof i != "symbol" ? i + "" : i, e);
4
+ import { UIElement as l } from "../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
5
+ const E = "unsubscribe-preview", c = "img", a = "Unsubscribe page preview", g = "is-loaded";
6
+ class d extends l {
7
7
  constructor() {
8
8
  super(...arguments);
9
- s(this, "imgElement");
9
+ r(this, "imgElement");
10
10
  }
11
11
  getId() {
12
12
  return E;
@@ -14,19 +14,21 @@ class o extends m {
14
14
  getTemplate() {
15
15
  return `
16
16
  <div class="unsubscribe-preview-image-container">
17
+ <div class="unsubscribe-preview-loader"></div>
17
18
  <img
18
19
  src=""
19
- alt="${c}"
20
+ alt="${a}"
20
21
  class="unsubscribe-preview-image"
21
22
  />
22
23
  </div>
23
24
  `;
24
25
  }
25
26
  onRender(e) {
26
- this.imgElement = e.querySelector(l);
27
+ this.imgElement = e.querySelector(c);
27
28
  }
28
29
  setValue(e) {
29
- this.imgElement && (this.imgElement.src = e);
30
+ var t;
31
+ this.imgElement && (this.imgElement.src = e, (t = this.imgElement.parentElement) == null || t.classList.add(g));
30
32
  }
31
33
  getValue() {
32
34
  var e;
@@ -38,5 +40,5 @@ class o extends m {
38
40
  }
39
41
  export {
40
42
  E as PREVIEW_UI_ELEMENT_ID,
41
- o as PreviewUIElement
43
+ d as PreviewUIElement
42
44
  };
@@ -29,12 +29,42 @@ const n = `/* Unsubscribe Extension Styles */
29
29
  display: flex;
30
30
  align-items: center;
31
31
  justify-content: center;
32
+ position: relative;
32
33
  }
33
34
 
34
- .unsubscribe-preview-image {
35
+ .unsubscribe-preview-image-container .unsubscribe-preview-image {
35
36
  object-fit: cover;
36
37
  width: 100%;
37
38
  height: auto;
39
+ display: none;
40
+ }
41
+
42
+ .unsubscribe-preview-image-container.is-loaded .unsubscribe-preview-image {
43
+ display: block;
44
+ }
45
+
46
+ .unsubscribe-preview-image-container.is-loaded .unsubscribe-preview-loader {
47
+ display: none;
48
+ }
49
+
50
+ /* Loading shimmer */
51
+ .unsubscribe-preview-loader {
52
+ width: 100%;
53
+ height: 200px;
54
+ border-radius: 4px;
55
+ background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
56
+ background-size: 200% 100%;
57
+ animation: unsubscribe-shimmer 1.5s infinite;
58
+ }
59
+
60
+ @keyframes unsubscribe-shimmer {
61
+ 0% {
62
+ background-position: 200% 0;
63
+ }
64
+
65
+ 100% {
66
+ background-position: -200% 0;
67
+ }
38
68
  }
39
69
  `;
40
70
  export {
package/dist/guido.css CHANGED
@@ -1 +1 @@
1
- .gap-16[data-v-b88d274d],.gap-16[data-v-bd89e39d]{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-913a3417] .in-progress-wrapper__progress p span:last-child{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}.editor-actions[data-v-17dd4d8b]{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-16abb398]{position:relative;width:100%;height:calc(100vh - 128px)}.guido-editor__container[data-v-16abb398]{width:100%;height:calc(100vh - 128px)}.guido-editor__no-header[data-v-16abb398]{height:calc(100vh - 75px)}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-a86fc486]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-a86fc486]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-a86fc486]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-a86fc486]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-a86fc486]{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-d3c52b44] .vueperslides__bullets,[data-v-dd1a237a] .vueperslides__bullets{pointer-events:none!important}[data-v-dd1a237a] .vueperslides__parallax-wrapper{height:110px!important}[data-v-a408dcea] .vueperslides__bullets{pointer-events:none!important}[data-v-a408dcea] .vueperslides__parallax-wrapper{height:110px!important}
1
+ .gap-16[data-v-6562e38c],.gap-16[data-v-1ccb6d4a]{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-913a3417] .in-progress-wrapper__progress p span:last-child{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}.editor-actions[data-v-17dd4d8b]{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-a26d7792]{position:relative;width:100%;height:calc(100vh - 128px)}.guido-editor__container[data-v-a26d7792]{width:100%;height:calc(100vh - 128px)}.guido-editor__no-header[data-v-a26d7792]{height:calc(100vh - 75px)}[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-d3c52b44] .vueperslides__bullets,[data-v-dd1a237a] .vueperslides__bullets{pointer-events:none!important}[data-v-dd1a237a] .vueperslides__parallax-wrapper{height:110px!important}[data-v-a408dcea] .vueperslides__bullets{pointer-events:none!important}[data-v-a408dcea] .vueperslides__parallax-wrapper{height:110px!important}