@useinsider/guido 3.18.1-beta.4bd98d6 → 3.18.1-beta.4fbee43

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.
@@ -12,9 +12,9 @@ var t = function() {
12
12
  s,
13
13
  !1,
14
14
  null,
15
- "7de301b5"
15
+ "050dfa52"
16
16
  );
17
- const v = n.exports;
17
+ const f = n.exports;
18
18
  export {
19
- v as default
19
+ f as default
20
20
  };
@@ -1,4 +1,4 @@
1
- import { defineComponent as ne, defineAsyncComponent as u, ref as P, computed as p, watch as x, onMounted as re, onUnmounted as se } from "vue";
1
+ import { defineComponent as ne, defineAsyncComponent as l, ref as O, computed as u, watch as P, onMounted as re, onUnmounted as se } from "vue";
2
2
  import { useCortexBlueprintBridge as ae } from "../composables/useCortexBlueprintBridge.js";
3
3
  import { useEditorLock as ie } from "../composables/useEditorLock.js";
4
4
  import { provideGuidoActions as ce } from "../composables/useGuidoActions.js";
@@ -6,25 +6,25 @@ import { useGuidoStateBridge as de } from "../composables/useGuidoStateBridge.js
6
6
  import { usePartner as me } from "../composables/usePartner.js";
7
7
  import { useStripo as le } from "../composables/useStripo.js";
8
8
  import { useTimerClone as ue } from "../composables/useTimerClone.js";
9
- import { migrate as W } from "../config/migrator/index.js";
10
- import { ModuleFolderDefaults as G } from "../enums/defaults.js";
9
+ import { migrate as x } from "../config/migrator/index.js";
10
+ import { ModuleFolderDefaults as W } from "../enums/defaults.js";
11
11
  import { RIBBON_SELECTOR as pe } from "../enums/onboarding.js";
12
- import { useRecommendationExtensionStore as $ } from "../extensions/Blocks/Recommendation/store/recommendation.js";
12
+ import { useRecommendationExtensionStore as G } from "../extensions/Blocks/Recommendation/store/recommendation.js";
13
13
  import fe from "./organisms/AutoSaveController.vue.js";
14
14
  import ye from "./organisms/base/Toaster.vue.js";
15
15
  import ge from "./organisms/extensions/recommendation/FilterSelectionDrawer.vue.js";
16
16
  import ve from "./organisms/header/HeaderWrapper.vue.js";
17
17
  import Se from "./organisms/LoadingWrapper.vue.js";
18
- import he from "./organisms/save-as-template/SaveAsTemplateDrawer.vue.js";
19
- import be from "./organisms/unsubscribe/UnsubscribeWrapper.vue.js";
18
+ import be from "./organisms/save-as-template/SaveAsTemplateDrawer.vue.js";
19
+ import he from "./organisms/unsubscribe/UnsubscribeWrapper.vue.js";
20
20
  import { useStripoApi as Ee } from "../services/stripoApi.js";
21
21
  import { useConfigStore as we } from "../stores/config.js";
22
22
  import { useDynamicContentStore as Ce } from "../stores/dynamic-content.js";
23
- import { useEditorStore as E } from "../stores/editor.js";
23
+ import { useEditorStore as H } from "../stores/editor.js";
24
24
  import { usePreviewStore as De } from "../stores/preview.js";
25
25
  import { useTemplateStore as ke } from "../stores/template.js";
26
- import { useUnsubscribeStore as Fe } from "../stores/unsubscribe.js";
27
- import { readTrackFloor as H } from "../utils/linkTrackingIds.js";
26
+ import { useUnsubscribeStore as Te } from "../stores/unsubscribe.js";
27
+ import { readTrackFloor as $ } from "../utils/linkTrackingIds.js";
28
28
  const et = /* @__PURE__ */ ne({
29
29
  __name: "Guido",
30
30
  props: {
@@ -33,40 +33,40 @@ const et = /* @__PURE__ */ ne({
33
33
  },
34
34
  emits: ["dynamic-content:open", "back", "save:start", "save:complete", "on-change", "ready", "onboarding:finished", "test-email:click"],
35
35
  setup(z, { expose: q, emit: r }) {
36
- const a = z, K = u(
36
+ const a = z, K = l(
37
37
  () => import("./organisms/email-preview/PreviewContainer.vue.js")
38
- ), V = u(
38
+ ), V = l(
39
39
  () => import("./organisms/onboarding/OnboardingWrapper.vue.js")
40
- ), j = u(
40
+ ), j = l(
41
41
  () => import("./organisms/extensions/recommendation/AssignStrategyDrawer.vue.js")
42
- ), J = u(
42
+ ), J = l(
43
43
  () => import("./organisms/extensions/recommendation/RemoveStrategyModal.vue.js")
44
- ), w = P(), f = P(), y = Ce(), C = Fe(), o = we();
44
+ ), h = O(), p = O(), f = Ce(), E = Te(), o = we();
45
45
  a.ready && o.init(a.config);
46
- const c = E(), Q = De(), m = p(() => c.hasChanges), { isTestPartner: X } = me(), D = () => {
46
+ const c = H(), Q = De(), m = u(() => c.hasChanges), { isTestPartner: X } = me(), w = () => {
47
47
  var t;
48
- return (t = w.value) == null ? void 0 : t.handleSave(!0);
49
- }, k = (t) => {
48
+ return (t = h.value) == null ? void 0 : t.handleSave(!0);
49
+ }, C = (t) => {
50
50
  c.loadingStatus = t;
51
51
  };
52
52
  ae(), de();
53
- const g = () => {
53
+ const y = () => {
54
54
  var t, e;
55
55
  return {
56
56
  emailId: o.templateId,
57
57
  userId: o.userId,
58
58
  username: o.username,
59
59
  partnerName: o.partnerName,
60
- savedModulesFolderName: ((t = o.editor) == null ? void 0 : t.savedModulesFolderName) || G.SAVED_MODULES,
61
- defaultModulesFolderName: ((e = o.editor) == null ? void 0 : e.defaultModulesFolderName) || G.DEFAULT_MODULES
60
+ savedModulesFolderName: ((t = o.editor) == null ? void 0 : t.savedModulesFolderName) || W.SAVED_MODULES,
61
+ defaultModulesFolderName: ((e = o.editor) == null ? void 0 : e.defaultModulesFolderName) || W.DEFAULT_MODULES
62
62
  };
63
- }, { initPlugin: F, preloadRuntime: T } = le(), { runExclusive: I, beginMount: M, isCurrentMount: v } = ie();
64
- let l = 0;
65
- const { getDefaultTemplate: R } = Ee(), { cloneTimersOnSave: L, hasTimerBlocks: B } = ue(), Y = p(() => {
63
+ }, { initPlugin: D, preloadRuntime: k } = le(), { runExclusive: T, beginMount: F, isCurrentMount: I } = ie();
64
+ let g = 0;
65
+ const { getDefaultTemplate: M } = Ee(), { cloneTimersOnSave: R, hasTimerBlocks: L } = ue(), Y = u(() => {
66
66
  var t;
67
67
  return !((t = o.ui) != null && t.showHeader);
68
- }), Z = p(() => o.isFeatureEnabled("reusableRecommendationStrategy")), ee = p(
69
- () => !!$().recommendationConfigs.strategyId
68
+ }), Z = u(() => o.isFeatureEnabled("reusableRecommendationStrategy")), ee = u(
69
+ () => !!G().recommendationConfigs.strategyId
70
70
  );
71
71
  ce({
72
72
  onBack: () => {
@@ -76,76 +76,70 @@ const et = /* @__PURE__ */ ne({
76
76
  console.debug("guido:save:start"), r("save:start");
77
77
  },
78
78
  onSaveComplete: (t) => {
79
- const e = { ...t, metadata: g() };
79
+ const e = { ...t, metadata: y() };
80
80
  console.debug("guido:save:complete", e), r("save:complete", e);
81
81
  },
82
82
  onTestEmailClick: () => {
83
83
  console.debug("guido:test-email:click"), r("test-email:click");
84
84
  }
85
85
  });
86
- const A = (t) => {
87
- console.debug("dynamic-content:close", t), y.setSelectedDynamicContent(t), document.dispatchEvent(new CustomEvent("dynamic-content:close", { detail: t }));
88
- }, U = () => {
86
+ const B = (t) => {
87
+ console.debug("dynamic-content:close", t), f.setSelectedDynamicContent(t), document.dispatchEvent(new CustomEvent("dynamic-content:close", { detail: t }));
88
+ }, A = () => {
89
89
  console.debug("dynamic-content:close", "Without Data"), document.dispatchEvent(new CustomEvent("dynamic-content:close", { detail: { text: "", value: "" } }));
90
90
  };
91
- x(() => m.value, () => {
91
+ P(() => m.value, () => {
92
92
  r("on-change", m.value);
93
93
  });
94
- const S = (t) => {
94
+ const v = (t) => {
95
95
  const e = t, { attribute: s, position: d } = e.detail;
96
96
  console.debug("dynamic-content:open", e.detail), r("dynamic-content:open", s, d);
97
97
  };
98
98
  let i = null;
99
- const h = () => {
99
+ const S = () => {
100
100
  var e;
101
101
  const t = document.querySelector(pe);
102
- (e = f.value) == null || e.style.setProperty("--ribbon-offset", `${(t == null ? void 0 : t.offsetHeight) ?? 0}px`);
102
+ (e = p.value) == null || e.style.setProperty("--ribbon-offset", `${(t == null ? void 0 : t.offsetHeight) ?? 0}px`);
103
103
  }, b = async () => {
104
104
  var t;
105
105
  try {
106
106
  o.initialized || o.init(a.config), c.templateId = o.templateId;
107
- const e = o.template, s = (e == null ? void 0 : e.html) || "", d = (e == null ? void 0 : e.css) || "", _ = (e == null ? void 0 : e.preselectedDynamicContent) || [];
108
- C.selectedUnsubscribePages = (e == null ? void 0 : e.selectedUnsubscribePages) || [];
109
- const N = ((t = e == null ? void 0 : e.migration) == null ? void 0 : t.recommendationConfigs) ?? {}, O = o.isFeatureEnabled("linkTrackingIds");
107
+ const e = o.template, s = (e == null ? void 0 : e.html) || "", d = (e == null ? void 0 : e.css) || "", U = (e == null ? void 0 : e.preselectedDynamicContent) || [];
108
+ E.selectedUnsubscribePages = (e == null ? void 0 : e.selectedUnsubscribePages) || [];
109
+ const _ = ((t = e == null ? void 0 : e.migration) == null ? void 0 : t.recommendationConfigs) ?? {}, N = o.isFeatureEnabled("linkTrackingIds");
110
110
  let n = {
111
- html: s && await W(s, N),
111
+ html: s && await x(s, _),
112
112
  css: d
113
113
  };
114
- n.html || (n = await R(), n.html = await W(n.html, N));
115
- const te = O ? H(n.html, (e == null ? void 0 : e.trackIdCounter) || 0) : 0;
116
- B(n.html) && (n.html = await L(n.html)), O && (c.trackIdSessionFloor = Math.max(te, H(n.html)));
114
+ n.html || (n = await M(), n.html = await x(n.html, _));
115
+ const te = N ? $(n.html, (e == null ? void 0 : e.trackIdCounter) || 0) : 0;
116
+ L(n.html) && (n.html = await R(n.html)), N && (c.trackIdSessionFloor = Math.max(te, $(n.html)));
117
117
  const oe = {
118
- preselectedDynamicContentList: _,
118
+ preselectedDynamicContentList: U,
119
119
  onReady: () => {
120
120
  console.debug("guido:ready"), r("ready");
121
121
  }
122
122
  };
123
- l = M(), await F(n, g(), oe), y.selectedDynamicContentList = _;
123
+ g = F(), await D(n, y(), oe), f.selectedDynamicContentList = U;
124
124
  } catch (e) {
125
125
  console.error("Failed to initialize Stripo editor:", e);
126
126
  }
127
127
  };
128
128
  return re(async () => {
129
129
  var e;
130
- console.debug("Guido says happy coding 🎉"), console.debug("🚗 Ka-Chow"), $().$reset(), E().$reset(), ke().$reset(), h();
131
- const t = (e = f.value) == null ? void 0 : e.parentElement;
132
- if (t && (i = new ResizeObserver(h), i.observe(t)), T(), a.ready)
130
+ console.debug("Guido says happy coding 🎉"), console.debug("🚗 Ka-Chow"), G().$reset(), H().$reset(), ke().$reset(), S();
131
+ const t = (e = p.value) == null ? void 0 : e.parentElement;
132
+ if (t && (i = new ResizeObserver(S), i.observe(t)), k(), a.ready)
133
133
  await b();
134
134
  else {
135
- const s = x(() => a.ready, (d) => {
135
+ const s = P(() => a.ready, (d) => {
136
136
  d && (s(), b());
137
137
  });
138
138
  }
139
- document.addEventListener("dynamic-content:open", S);
139
+ document.addEventListener("dynamic-content:open", v);
140
140
  }), se(() => {
141
- if (i == null || i.disconnect(), document.removeEventListener("dynamic-content:open", S), v(l))
142
- try {
143
- E().$reset();
144
- } catch (t) {
145
- console.debug("Failed to reset the editor store on unmount", t);
146
- }
147
- I(async () => {
148
- if (v(l))
141
+ i == null || i.disconnect(), document.removeEventListener("dynamic-content:open", v), T(async () => {
142
+ if (I(g))
149
143
  try {
150
144
  window.UIEditor.removeEditor();
151
145
  } catch {
@@ -154,13 +148,13 @@ const et = /* @__PURE__ */ ne({
154
148
  }), o.reset();
155
149
  }), q({
156
150
  dynamicContent: {
157
- insert: A,
158
- close: U
151
+ insert: B,
152
+ close: A
159
153
  },
160
154
  hasChanges: m,
161
- saveSilent: D,
162
- setLoading: k
163
- }), { __sfc: !0, PreviewContainer: K, OnboardingWrapper: V, AssignStrategyDrawer: j, RemoveStrategyModal: J, headerWrapperRef: w, wrapperRef: f, dynamicContentStore: y, unsubscribeStore: C, props: a, configStore: o, editorStore: c, previewStore: Q, hasChanges: m, isTestPartner: X, saveSilent: D, setLoading: k, emit: r, buildMetadata: g, initPlugin: F, preloadRuntime: T, runExclusive: I, beginMount: M, isCurrentMount: v, mountGeneration: l, getDefaultTemplate: R, cloneTimersOnSave: L, hasTimerBlocks: B, noHeader: Y, isRrsEnabled: Z, hasAssignedStrategy: ee, insertDynamicContent: A, closeDynamicContent: U, handleDynamicContentOpen: S, ribbonObserver: i, updateRibbonOffset: h, startEditor: b, AutoSaveController: fe, Toaster: ye, FilterSelectionDrawer: ge, HeaderWrapper: ve, LoadingWrapper: Se, SaveAsTemplateDrawer: he, UnsubscribeWrapper: be };
155
+ saveSilent: w,
156
+ setLoading: C
157
+ }), { __sfc: !0, PreviewContainer: K, OnboardingWrapper: V, AssignStrategyDrawer: j, RemoveStrategyModal: J, headerWrapperRef: h, wrapperRef: p, dynamicContentStore: f, unsubscribeStore: E, props: a, configStore: o, editorStore: c, previewStore: Q, hasChanges: m, isTestPartner: X, saveSilent: w, setLoading: C, emit: r, buildMetadata: y, initPlugin: D, preloadRuntime: k, runExclusive: T, beginMount: F, isCurrentMount: I, mountGeneration: g, getDefaultTemplate: M, cloneTimersOnSave: R, hasTimerBlocks: L, noHeader: Y, isRrsEnabled: Z, hasAssignedStrategy: ee, insertDynamicContent: B, closeDynamicContent: A, handleDynamicContentOpen: v, ribbonObserver: i, updateRibbonOffset: S, startEditor: b, AutoSaveController: fe, Toaster: ye, FilterSelectionDrawer: ge, HeaderWrapper: ve, LoadingWrapper: Se, SaveAsTemplateDrawer: be, UnsubscribeWrapper: he };
164
158
  }
165
159
  });
166
160
  export {
@@ -1,21 +1,17 @@
1
1
  import { filterAmpErrors as v } from "../utils/ampErrorFilter.js";
2
2
  import { useToaster as y } from "./useToaster.js";
3
- const D = 1e4, T = 3e4, p = (n, l, w) => new Promise((A, s) => {
4
- const c = setTimeout(
5
- () => s(new Error(`${n} did not report completion within ${l}ms`)),
3
+ const D = 1e4, d = 3e4, s = (n, l, u) => new Promise((T, m) => {
4
+ const w = setTimeout(
5
+ () => m(new Error(`${n} did not report completion within ${l}ms`)),
6
6
  l
7
- ), d = (r) => (t) => {
8
- clearTimeout(c), r(t);
7
+ ), p = (A) => (t) => {
8
+ clearTimeout(w), A(t);
9
9
  };
10
- try {
11
- w(d(A), d(s));
12
- } catch (r) {
13
- clearTimeout(c), s(r instanceof Error ? r : new Error(String(r)));
14
- }
10
+ u(p(T), p(m));
15
11
  }), I = () => {
16
- const { handleError: n } = y(), l = (t = {}) => p(
12
+ const { handleError: n } = y(), l = (t = {}) => s(
17
13
  "compileEmail",
18
- T,
14
+ d,
19
15
  (e, a) => {
20
16
  const o = { ...{
21
17
  minimize: !0,
@@ -36,9 +32,9 @@ const D = 1e4, T = 3e4, p = (n, l, w) => new Promise((A, s) => {
36
32
  forceAmp: !1,
37
33
  resetDataSavedFlag: !1,
38
34
  disableLineHeightsReplace: !0
39
- }, ...t }, u = {
40
- callback: (m, C, f, S, g) => {
41
- m ? a(m) : e({
35
+ }, ...t }, c = {
36
+ callback: (r, C, f, S, g) => {
37
+ r ? a(r) : e({
42
38
  html: C,
43
39
  ampHtml: f,
44
40
  ampErrors: v(S ?? []),
@@ -47,22 +43,22 @@ const D = 1e4, T = 3e4, p = (n, l, w) => new Promise((A, s) => {
47
43
  },
48
44
  ...o
49
45
  };
50
- window.StripoEditorApi.actionsApi.compileEmail(u);
46
+ window.StripoEditorApi.actionsApi.compileEmail(c);
51
47
  }
52
48
  );
53
49
  return {
54
50
  getCompiledEmail: l,
55
- getTemplateData: () => p(
51
+ getTemplateData: () => s(
56
52
  "getTemplateData",
57
- T,
53
+ d,
58
54
  (t) => {
59
- const e = ({ html: a, css: i, width: o, height: E, utmParams: u, syncModulesIds: m }) => t({
55
+ const e = ({ html: a, css: i, width: o, height: E, utmParams: c, syncModulesIds: r }) => t({
60
56
  html: a,
61
57
  css: i,
62
58
  width: o,
63
59
  height: E,
64
- utmParams: u,
65
- syncModulesIds: m
60
+ utmParams: c,
61
+ syncModulesIds: r
66
62
  });
67
63
  window.StripoEditorApi.actionsApi.getTemplateData(e);
68
64
  }
@@ -109,13 +105,13 @@ const D = 1e4, T = 3e4, p = (n, l, w) => new Promise((A, s) => {
109
105
  }),
110
106
  updateHtmlAndCss: (t, e) => {
111
107
  const { actionsApi: a } = window.StripoEditorApi;
112
- return p("updateHtmlAndCss", D, (i) => {
108
+ return s("updateHtmlAndCss", D, (i) => {
113
109
  a.updateHtmlAndCss(t, e, () => i());
114
110
  });
115
111
  },
116
- editorSave: () => p(
112
+ editorSave: () => s(
117
113
  "save",
118
- T,
114
+ d,
119
115
  (t) => {
120
116
  window.StripoEditorApi.actionsApi.save((e) => {
121
117
  if (e) {
@@ -1,129 +1,70 @@
1
- import { useEmailTemplateApplier as Y, resetEmailTemplateApplier as N } from "./useEmailTemplateApplier.js";
2
- import { useToaster as X } from "./useToaster.js";
3
- import { useTranslationWithFallback as j } from "./useTranslations.js";
4
- import { ToasterTypeOptions as z } from "../enums/toaster.js";
5
- import { useGuidoEmailEditorStore as J } from "../stores/guido-email-editor.js";
6
- import { getActivePinia as Q } from "pinia";
7
- import { onUnmounted as V, watch as W } from "vue";
8
- const Z = "email_template", tt = "chat", et = "guido:debug:ai", rt = 2, nt = 500, ot = (A, p) => `${A}:${p ?? 1}`;
9
- let S = null;
10
- const it = () => {
1
+ import { useEmailTemplateApplier as w, resetEmailTemplateApplier as _ } from "./useEmailTemplateApplier.js";
2
+ import { useToaster as I } from "./useToaster.js";
3
+ import { useTranslations as P } from "./useTranslations.js";
4
+ import { ToasterTypeOptions as S } from "../enums/toaster.js";
5
+ import { getActivePinia as v } from "pinia";
6
+ import { watch as B, onUnmounted as D } from "vue";
7
+ const x = "email_template", L = "chat", M = "guido:debug:ai", R = () => {
11
8
  if (typeof window > "u")
12
9
  return !1;
13
10
  try {
14
- return window.localStorage.getItem(et) === "1";
11
+ return window.localStorage.getItem(M) === "1";
15
12
  } catch {
16
13
  return !1;
17
14
  }
18
- }, ft = () => {
19
- const A = Q();
20
- if (!A)
15
+ }, H = () => {
16
+ const c = v();
17
+ if (!c)
21
18
  return;
22
- const p = J(), _ = Symbol("cortexBlueprintBridge");
23
- S = _, p.$patch((t) => {
24
- t.bridgeActive = !0;
25
- });
26
- const { markPending: R, applyTemplate: q, applyTemplateDebounced: x } = Y(), { showToaster: C } = X(), H = j(), h = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), E = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Set(), M = it();
27
- let T = null, b = null, f;
28
- const O = (t, e) => {
29
- M && console.debug(`[guido:cortex] msg=${t ?? "?"} type=${(e == null ? void 0 : e.type) ?? "?"}`, e);
30
- }, G = () => new Set((f == null ? void 0 : f.appliedBlueprintKeys) ?? []), K = (t) => t instanceof Error ? t.message : String(t), g = (t, e, o, r) => {
31
- const n = p.applyAcks[t], l = Math.max(Date.now(), ((n == null ? void 0 : n.ackAt) ?? 0) + 1), a = { status: e, requestedAt: o, ackAt: l };
32
- r !== void 0 && (a.error = K(r)), p.$patch((c) => {
33
- c.applyAcks = { ...c.applyAcks, [t]: a };
34
- });
35
- }, D = (t) => (d.get(t) ?? 0) > 0, m = async (t, e, o, r) => {
36
- var c, i, L;
37
- const n = ((c = o.blueprintData) == null ? void 0 : c.html) ?? "", l = ((i = o.blueprintData) == null ? void 0 : i.css) ?? "", a = o.applyRequestedAt ?? 0;
38
- d.set(t, (d.get(t) ?? 0) + 1);
39
- try {
40
- const s = r === "debounced" ? await x(e, { html: n, css: l }) : await q(e, { html: n, css: l });
41
- if (s.status === "superseded")
42
- return;
43
- if (s.status === "applied") {
44
- h.set(e, n), u.delete(t), g(t, "applied", a);
45
- return;
46
- }
47
- const w = u.get(t);
48
- u.set(t, { html: n, count: (w == null ? void 0 : w.html) === n ? w.count + 1 : 1 }), g(t, "failed", a, s.error);
49
- } finally {
50
- d.set(t, (d.get(t) ?? 1) - 1);
51
- const s = E.get(t);
52
- s && !D(t) && (E.delete(t), (((L = s.blueprintData) == null ? void 0 : L.html) ?? "") !== n && m(t, e, s, r));
53
- }
54
- }, U = (t) => {
55
- var c;
56
- if (t.blueprintType !== Z)
57
- return;
58
- const { blueprintId: e } = t, o = (c = t.blueprintData) == null ? void 0 : c.html;
59
- if (!e || !o)
19
+ const l = c._s, p = l == null ? void 0 : l.get(L);
20
+ if (!p)
21
+ return;
22
+ const { markPending: d, applyTemplate: f, applyTemplateDebounced: T } = w(), { showToaster: E } = I(), h = P(), y = (r, t) => {
23
+ const e = h(r);
24
+ return e === r ? t : e;
25
+ }, i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set(), u = R(), A = (r, t) => {
26
+ u && console.debug(`[guido:cortex] msg=${r ?? "?"} type=${(t == null ? void 0 : t.type) ?? "?"}`, t);
27
+ }, b = (r) => {
28
+ if (r.blueprintType !== x)
60
29
  return;
61
- if (!t.applyRequested) {
62
- R(e);
30
+ const t = r.blueprintId, e = r.blueprintData;
31
+ if (!t || !(e != null && e.html))
63
32
  return;
64
- }
65
- const r = ot(e, t.version), n = t.applyRequestedAt ?? 0, l = v.get(r);
66
- if (l === void 0 || n > l) {
67
- const i = l === void 0;
68
- if (v.set(r, n), u.delete(r), i && G().has(r)) {
69
- h.set(e, o);
70
- return;
71
- }
72
- m(r, e, t, "immediate");
33
+ if (!r.applyRequested) {
34
+ d(t);
73
35
  return;
74
36
  }
75
- const a = h.get(e);
76
- if (a !== o) {
77
- if (a === void 0) {
78
- if (D(r)) {
79
- E.set(r, t);
80
- return;
81
- }
82
- const i = u.get(r);
83
- if ((i == null ? void 0 : i.html) === o && i.count >= rt)
84
- return;
85
- m(r, e, t, "immediate");
86
- return;
87
- }
88
- m(r, e, t, "debounced");
89
- }
90
- }, B = (t) => t === void 0 || y.has(t) ? !1 : (y.add(t), C({
91
- type: z.Error,
92
- message: H("newsletter.ai-template-failed", "AI couldn't generate the template. Please try again.")
93
- }), !0), k = (t) => {
94
- Array.isArray(t) && t.forEach((e) => {
95
- const o = e == null ? void 0 : e.id;
96
- (e == null ? void 0 : e.isError) === !0 && B(o) && M && console.debug(`[guido:cortex] message-level error id=${o}`, e);
97
- const r = e == null ? void 0 : e.segments;
98
- Array.isArray(r) && r.forEach((n) => {
99
- if (n)
100
- switch (O(o, n), n.type) {
101
- case "blueprint":
102
- U(n);
103
- break;
104
- case "error":
105
- B(o);
106
- break;
107
- }
37
+ const o = i.get(t);
38
+ o === void 0 ? (i.set(t, e.html), f(t, e)) : o !== e.html && (i.set(t, e.html), T(t, e));
39
+ }, s = (r) => r === void 0 || a.has(r) ? !1 : (a.add(r), E({
40
+ type: S.Error,
41
+ message: y("newsletter.ai-template-failed", "AI couldn't generate the template. Please try again.")
42
+ }), !0), m = B(
43
+ () => p.messages,
44
+ (r) => {
45
+ Array.isArray(r) && r.forEach((t) => {
46
+ const e = t == null ? void 0 : t.id;
47
+ (t == null ? void 0 : t.isError) === !0 && s(e) && u && console.debug(`[guido:cortex] message-level error id=${e}`, t);
48
+ const o = t == null ? void 0 : t.segments;
49
+ Array.isArray(o) && o.forEach((n) => {
50
+ if (n)
51
+ switch (A(e, n), n.type) {
52
+ case "blueprint":
53
+ b(n);
54
+ break;
55
+ case "error":
56
+ s(e);
57
+ break;
58
+ }
59
+ });
108
60
  });
109
- });
110
- }, P = () => {
111
- T !== null && (clearInterval(T), T = null);
112
- }, $ = () => {
113
- var t;
114
- return (t = A._s) == null ? void 0 : t.get(tt);
115
- }, F = (t) => {
116
- f = t, b = W(() => t.messages, k, { deep: !0, immediate: !0 });
117
- }, I = $();
118
- I ? F(I) : T = setInterval(() => {
119
- const t = $();
120
- t && (P(), F(t));
121
- }, nt), V(() => {
122
- P(), b == null || b(), f = void 0, h.clear(), v.clear(), u.clear(), d.clear(), E.clear(), y.clear(), S === _ && (S = null, p.$patch((t) => {
123
- t.bridgeActive = !1, t.applyAcks = {};
124
- }), N());
61
+ },
62
+ { deep: !0, immediate: !0 }
63
+ );
64
+ D(() => {
65
+ m(), i.clear(), a.clear(), _();
125
66
  });
126
67
  };
127
68
  export {
128
- ft as useCortexBlueprintBridge
69
+ H as useCortexBlueprintBridge
129
70
  };
@@ -1,102 +1,59 @@
1
- import { useActionsApi as Q } from "./useActionsApi.js";
2
- import { useConfig as x } from "./useConfig.js";
3
- import { useEditorLock as z } from "./useEditorLock.js";
4
- import { useToaster as F } from "./useToaster.js";
5
- import { useTranslationWithFallback as N } from "./useTranslations.js";
6
- import { ToasterTypeOptions as h } from "../enums/toaster.js";
7
- import { useDynamicContentStore as q } from "../stores/dynamic-content.js";
8
- import { useEditorStore as R } from "../stores/editor.js";
9
- import { flattenDynamicContentList as G } from "../utils/genericUtil.js";
10
- import { extractUsedDynamicContent as W } from "../utils/registerUsedDynamicContent.js";
11
- import { ref as $, watch as j } from "vue";
12
- const J = 250, D = 12e4, c = { status: "superseded" }, S = { status: "failed", error: new Error("Blueprint has no html to apply") }, i = $({}), v = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), ie = () => {
13
- const { updateHtmlAndCss: a } = Q(), { runExclusive: M } = z(), { showToaster: d } = F(), y = N(), { template: U } = x(), A = q(), T = R(), E = (e, t) => {
14
- u.get(e) !== t && (u.set(e, t), d({
15
- type: h.Error,
16
- message: y("newsletter.ai-template-failed-apply", "Failed to apply template")
17
- }));
18
- }, O = () => {
19
- var e, t;
20
- return T.isStripoInitialized && typeof ((t = (e = window.StripoEditorApi) == null ? void 0 : e.actionsApi) == null ? void 0 : t.updateHtmlAndCss) == "function";
21
- }, P = (e) => {
22
- i.value[e] === void 0 && (i.value = { ...i.value, [e]: "pending" });
23
- }, m = (e, t) => {
24
- i.value = { ...i.value, [e]: t };
25
- }, _ = (e) => {
26
- var t;
1
+ import { useActionsApi as C } from "./useActionsApi.js";
2
+ import { useConfig as h } from "./useConfig.js";
3
+ import { useToaster as D } from "./useToaster.js";
4
+ import { useTranslations as E } from "./useTranslations.js";
5
+ import { ToasterTypeOptions as f } from "../enums/toaster.js";
6
+ import { useDynamicContentStore as A } from "../stores/dynamic-content.js";
7
+ import { flattenDynamicContentList as w } from "../utils/genericUtil.js";
8
+ import { extractUsedDynamicContent as S } from "../utils/registerUsedDynamicContent.js";
9
+ import { ref as O } from "vue";
10
+ const U = 250, o = O({}), s = {}, u = /* @__PURE__ */ new Map(), z = () => {
11
+ const { updateHtmlAndCss: r } = C(), { showToaster: m } = D(), y = E(), { template: T } = h(), d = A(), g = (e, t) => {
12
+ const a = y(e);
13
+ return a === e ? t : a;
14
+ }, v = (e) => {
15
+ o.value[e] === void 0 && (o.value = { ...o.value, [e]: "pending" });
16
+ }, l = (e, t, a) => {
17
+ var c;
18
+ o.value = { ...o.value, [e]: "applying" };
27
19
  try {
28
- const o = G((t = U.value) == null ? void 0 : t.dynamicContentList), s = W(e, o);
29
- s.length > 0 && A.registerDynamicContent(s);
30
- } catch {
31
- }
32
- }, k = (e, t) => {
33
- u.delete(e), v.get(e) !== t && (v.set(e, t), d({
34
- type: h.Success,
35
- message: y("newsletter.ai-template-applied", "Template applied to the editor")
36
- }));
37
- }, g = async (e, t, o) => {
38
- const s = (l.get(e) ?? 0) + 1;
39
- l.set(e, s), m(e, "applying");
40
- try {
41
- await M(() => a(t, o));
20
+ r(t, a).catch((n) => {
21
+ console.warn("Editor did not acknowledge the template apply.", n);
22
+ }), o.value = { ...o.value, [e]: "applied" };
23
+ try {
24
+ const n = w((c = T.value) == null ? void 0 : c.dynamicContentList), i = S(t, n);
25
+ i.length > 0 && d.registerDynamicContent(i);
26
+ } catch {
27
+ }
28
+ u.get(e) !== t && (u.set(e, t), m({
29
+ type: f.Success,
30
+ message: g("newsletter.ai-template-applied", "Template applied to the editor")
31
+ }));
42
32
  } catch (n) {
43
- return l.get(e) !== s ? c : (console.error("[guido:apply] editor did not acknowledge the template apply", n), m(e, "failed"), E(e, t), { status: "failed", error: n });
44
- }
45
- return l.get(e) !== s ? c : (m(e, "applied"), _(t), k(e, t), { status: "applied" });
46
- }, H = (e) => {
47
- const t = r.get(e);
48
- t && (clearTimeout(t.timer), r.delete(e), t.settle(c));
49
- }, w = (e) => {
50
- const t = p.get(e);
51
- t && (clearTimeout(t.timer), p.delete(e), t.settle(c));
52
- }, B = (e, t, o) => new Promise((s) => {
53
- H(e);
54
- const n = setTimeout(() => {
55
- r.delete(e), m(e, "failed"), E(e, t), s({
56
- status: "failed",
57
- error: new Error(`Editor did not become ready within ${D}ms`)
33
+ o.value = { ...o.value, [e]: "failed" }, m({
34
+ type: f.Error,
35
+ message: n instanceof Error ? n.message : "Failed to apply template"
58
36
  });
59
- }, D);
60
- r.set(e, { html: t, css: o, timer: n, settle: s }), m(e, "applying");
61
- }), C = (e, t, o) => O() ? g(e, t, o) : B(e, t, o), L = async () => {
62
- if (r.size === 0)
63
- return;
64
- const e = [...r.entries()];
65
- r.clear(), e.forEach(([, n]) => clearTimeout(n.timer));
66
- const t = e.pop();
67
- if (e.forEach(([n, f]) => {
68
- m(n, "pending"), f.settle(c);
69
- }), !t)
70
- return;
71
- const [o, s] = t;
72
- s.settle(await g(o, s.html, s.css));
37
+ }
38
+ }, p = (e) => {
39
+ const t = s[e];
40
+ t && (clearTimeout(t), delete s[e]);
73
41
  };
74
- return j(() => T.isStripoInitialized, (e) => {
75
- e && L();
76
- }, { immediate: !0 }), { applyStatus: i, markPending: P, applyTemplate: (e, t) => {
77
- const { html: o } = t;
78
- return o ? (w(e), C(e, o, t.css ?? "")) : Promise.resolve(S);
42
+ return { applyStatus: o, markPending: v, applyTemplate: (e, t) => {
43
+ t.html && (p(e), l(e, t.html, t.css ?? ""));
79
44
  }, applyTemplateDebounced: (e, t) => {
80
- const { html: o } = t;
81
- if (!o)
82
- return Promise.resolve(S);
83
- const s = t.css ?? "";
84
- return new Promise((n) => {
85
- w(e);
86
- const f = setTimeout(() => {
87
- p.delete(e), C(e, o, s).then(n);
88
- }, J);
89
- p.set(e, { timer: f, settle: n });
90
- });
45
+ if (!t.html)
46
+ return;
47
+ p(e);
48
+ const { html: a } = t, c = t.css ?? "";
49
+ s[e] = setTimeout(() => {
50
+ delete s[e], l(e, a, c);
51
+ }, U);
91
52
  } };
92
- }, ce = () => {
93
- p.forEach((a) => {
94
- clearTimeout(a.timer), a.settle(c);
95
- }), p.clear(), r.forEach((a) => {
96
- clearTimeout(a.timer), a.settle(c);
97
- }), r.clear(), l.clear(), u.clear(), i.value = {};
53
+ }, G = () => {
54
+ Object.values(s).forEach(clearTimeout), Object.keys(s).forEach((r) => delete s[r]), o.value = {};
98
55
  };
99
56
  export {
100
- ce as resetEmailTemplateApplier,
101
- ie as useEmailTemplateApplier
57
+ G as resetEmailTemplateApplier,
58
+ z as useEmailTemplateApplier
102
59
  };
@@ -4,26 +4,19 @@ import memoize from "../node_modules/lodash-es/memoize.js";
4
4
  import { ref } from "vue";
5
5
  import { useConfig } from "./useConfig.js";
6
6
  const useTranslations = () => {
7
- var o, r;
8
- const { config } = useConfig(), translationsPath = ((r = (o = config.value) == null ? void 0 : o.editor) == null ? void 0 : r.translationsPath) || DEFAULT_EDITOR.translationsPath, translations = ref(eval(translationsPath)), trans = (n, t) => {
9
- const s = translations.value[n];
10
- return s ? t ? Object.entries(t).reduce(
11
- (e, [a, i]) => e.replace(new RegExp(`{${a}}`, "g"), String(i)),
12
- s
13
- ) : s : (console.warn(`Translation key not found: ${n}`), n);
7
+ var o, e;
8
+ const { config } = useConfig(), translationsPath = ((e = (o = config.value) == null ? void 0 : o.editor) == null ? void 0 : e.translationsPath) || DEFAULT_EDITOR.translationsPath, translations = ref(eval(translationsPath)), trans = (t, n) => {
9
+ const r = translations.value[t];
10
+ return r ? n ? Object.entries(n).reduce(
11
+ (s, [i, a]) => s.replace(new RegExp(`{${i}}`, "g"), String(a)),
12
+ r
13
+ ) : r : (console.warn(`Translation key not found: ${t}`), t);
14
14
  };
15
15
  return memoize(
16
16
  trans,
17
- (n, t) => !t || Object.keys(t).length === 0 ? n : JSON.stringify({ key: n, params: t })
17
+ (t, n) => !n || Object.keys(n).length === 0 ? t : JSON.stringify({ key: t, params: n })
18
18
  );
19
- }, useTranslationWithFallback = () => {
20
- const o = useTranslations();
21
- return (r, n) => {
22
- const t = o(r);
23
- return t === r ? n : t;
24
- };
25
19
  };
26
20
  export {
27
- useTranslationWithFallback,
28
21
  useTranslations
29
22
  };
@@ -23,14 +23,14 @@ import { PricePlacementControl as E } from "./pricePlacement.js";
23
23
  import { PRICE_PLACEMENT_CONTROL_ID as _t } from "./pricePlacement.js";
24
24
  import { ProductCountControl as k } from "./productCount.js";
25
25
  import { PRODUCT_COUNT_CONTROL_ID as Rt } from "./productCount.js";
26
- import { ProductLayoutControl as D } from "./productLayout.js";
26
+ import { ProductLayoutControl as F } from "./productLayout.js";
27
27
  import { PRODUCT_LAYOUT_CONTROL_ID as Tt } from "./productLayout.js";
28
- import { ShuffleControl as F } from "./shuffle.js";
28
+ import { ShuffleControl as D } from "./shuffle.js";
29
29
  import { SHUFFLE_CONTROL_ID as St } from "./shuffle.js";
30
30
  import { StrategyControl as w } from "./strategy.js";
31
31
  import { STRATEGY_CONTROL_ID as Lt } from "./strategy.js";
32
32
  import { setCurrencyAttributes as A, getBlockElement as v, isPartnerManagedBlock as x, updateProductContentInPlace as B, regenerateProductRowsWithStyles as U } from "./utils.js";
33
- import { adjustProductsToSize as kt, formatProductPrice as Dt, getCardComposition as Ft, getCurrentLayout as wt, getMainContainerTbody as At, regenerateMobileProductRows as vt, updatePricesInPlace as xt, updateSingleProductContent as Bt } from "./utils.js";
33
+ import { adjustProductsToSize as kt, formatProductPrice as Ft, getCardComposition as Dt, getCurrentLayout as wt, getMainContainerTbody as At, regenerateMobileProductRows as vt, updatePricesInPlace as xt, updateSingleProductContent as Bt } from "./utils.js";
34
34
  import { useDebounceFn as f } from "../../../../../node_modules/@vueuse/shared/index.js";
35
35
  const $ = "ui-elements-recommendation-block";
36
36
  class at extends N {
@@ -39,8 +39,6 @@ class at extends N {
39
39
  n(this, "store", R());
40
40
  n(this, "storeUnsubscription", () => {
41
41
  });
42
- // blockId -> fingerprint of the node config as it looked at the last sync.
43
- n(this, "syncedConfigs", /* @__PURE__ */ new Map());
44
42
  // A config change waiting to reach the node config. Deferred so it can ride the
45
43
  // re-render's single apply() — one user action must cost one undo press.
46
44
  n(this, "pendingNodeConfigWrite", null);
@@ -120,7 +118,7 @@ class at extends N {
120
118
  return this.rrsEnabled = p().isFeatureEnabled("reusableRecommendationStrategy"), this._subControls.forEach((e) => {
121
119
  var o;
122
120
  return (o = e == null ? void 0 : e.onDestroy) == null ? void 0 : o.call(e);
123
- }), this.algorithmControl = new T(), this.localeControl = new L(), this.currencyControl = new P(), this.productCountControl = new k(), this.productLayoutControl = new D(), this.filtersControl = new S(), this.shuffleControl = new F(), this.pricePlacementControl = new E(), this.layoutOrientationControl = new O(), this.strategyControl = this.rrsEnabled ? new w() : null, this._subControls.forEach((e) => {
121
+ }), this.algorithmControl = new T(), this.localeControl = new L(), this.currencyControl = new P(), this.productCountControl = new k(), this.productLayoutControl = new F(), this.filtersControl = new S(), this.shuffleControl = new D(), this.pricePlacementControl = new E(), this.layoutOrientationControl = new O(), this.strategyControl = this.rrsEnabled ? new w() : null, this._subControls.forEach((e) => {
124
122
  e && (e.api = this.api);
125
123
  }), `
126
124
  <div class="recommendation-controls-container">
@@ -200,11 +198,19 @@ class at extends N {
200
198
  * fingerprint diff on this hook is the only way to notice (SD-149105).
201
199
  * An unchanged fingerprint means the move came from us, so runtime store
202
200
  * edits are never clobbered (SD-141049).
201
+ *
202
+ * The fingerprint is kept on the block's own store state so deleting the
203
+ * block drops it with the state it describes. A control-owned memo outlived
204
+ * that state and made a re-dropped saved module keep the defaults its wiped
205
+ * state was rebuilt with (SD-150347).
203
206
  */
204
207
  _syncNodeConfigIfChanged(t) {
205
208
  this.pendingNodeConfigWrite && this.pendingNodeConfigWrite.blockId !== t && this._flushPendingNodeConfig();
206
- const e = JSON.stringify(c.getConfig(this.currentNode)), o = this.syncedConfigs.get(t);
207
- this.syncedConfigs.set(t, e), o !== e && (this.pendingNodeConfigWrite || this._syncNodeConfigToStore());
209
+ const e = this.store.blockStates[t];
210
+ if (!e)
211
+ return;
212
+ const o = JSON.stringify(c.getConfig(this.currentNode)), r = e.syncedConfigFingerprint;
213
+ e.syncedConfigFingerprint = o, r !== o && (this.pendingNodeConfigWrite || this._syncNodeConfigToStore());
208
214
  }
209
215
  _capturePendingNodeConfigWrite() {
210
216
  const t = this.store.currentRecommendationId;
@@ -430,16 +436,16 @@ export {
430
436
  Tt as PRODUCT_LAYOUT_CONTROL_ID,
431
437
  E as PricePlacementControl,
432
438
  k as ProductCountControl,
433
- D as ProductLayoutControl,
439
+ F as ProductLayoutControl,
434
440
  at as RecommendationBlockControl,
435
441
  St as SHUFFLE_CONTROL_ID,
436
442
  Lt as STRATEGY_CONTROL_ID,
437
- F as ShuffleControl,
443
+ D as ShuffleControl,
438
444
  w as StrategyControl,
439
445
  kt as adjustProductsToSize,
440
- Dt as formatProductPrice,
446
+ Ft as formatProductPrice,
441
447
  v as getBlockElement,
442
- Ft as getCardComposition,
448
+ Dt as getCardComposition,
443
449
  wt as getCurrentLayout,
444
450
  At as getMainContainerTbody,
445
451
  x as isPartnerManagedBlock,
@@ -1,7 +1,7 @@
1
1
  import { getRecommendationFeedSourceMaps as b, getOperatorOptions as G, PriceAttributes as v } from "../../../../enums/extensions/recommendationBlock.js";
2
2
  import { useRecommendationApi as D } from "../../../../services/recommendationApi.js";
3
- import { useConfigStore as P } from "../../../../stores/config.js";
4
- import { defineStore as F } from "pinia";
3
+ import { useConfigStore as F } from "../../../../stores/config.js";
4
+ import { defineStore as P } from "pinia";
5
5
  import "../constants/selectors.js";
6
6
  import { DEFAULT_MOBILE_CARDS_IN_ROW as _, DEFAULT_CARDS_IN_ROW as U } from "../constants/layout.js";
7
7
  import { DEFAULT_NODE_CONFIG as N, EXCLUDED_ALGORITHM_IDS as L } from "../constants/defaultConfig.js";
@@ -12,7 +12,7 @@ import { sanitizeProductIds as A } from "../utils/productIds.js";
12
12
  import { isFilterValid as B } from "../validation/filterSchema.js";
13
13
  import { isConfigValid as M } from "../validation/requiredFields.js";
14
14
  const u = D();
15
- let f = null, h = null, g = null, S = null;
15
+ let f = null, g = null, h = null, S = null;
16
16
  const p = /* @__PURE__ */ new Map();
17
17
  function w() {
18
18
  return {
@@ -56,7 +56,8 @@ function C() {
56
56
  removeStrategyModalStatus: !1,
57
57
  filterGroup: 1,
58
58
  isInitialized: !1,
59
- filterSnapshot: null
59
+ filterSnapshot: null,
60
+ syncedConfigFingerprint: null
60
61
  };
61
62
  }
62
63
  const z = () => ({
@@ -71,7 +72,7 @@ const z = () => ({
71
72
  blockStates: {},
72
73
  currentRecommendationId: null,
73
74
  configVersion: 0
74
- }), Y = F("guidoRecommendationExtension", {
75
+ }), Y = P("guidoRecommendationExtension", {
75
76
  state: () => z(),
76
77
  getters: {
77
78
  // ====================================================================
@@ -241,7 +242,7 @@ const z = () => ({
241
242
  const r = (o, c) => o === "." || o === "," || o === " " ? o : c, n = {
242
243
  name: e.currencyCode,
243
244
  value: e.currencyCode,
244
- symbol: e.currencyCode,
245
+ symbol: e.currencySymbol,
245
246
  alignment: e.currencyAlignment === "before" ? "0" : "1",
246
247
  decimalCount: String(e.currencyDecimalCount),
247
248
  decimalSeparator: r(e.currencyDecimalSeparator, ","),
@@ -412,18 +413,18 @@ const z = () => ({
412
413
  },
413
414
  async fetchRecommendationFilters() {
414
415
  if (!Object.keys(this.filterList).length) {
415
- if (h) {
416
- await h;
416
+ if (g) {
417
+ await g;
417
418
  return;
418
419
  }
419
- h = (async () => {
420
+ g = (async () => {
420
421
  const t = await u.fetchRecommendationFilters();
421
422
  this.filterList = t;
422
423
  })();
423
424
  try {
424
- await h;
425
+ await g;
425
426
  } finally {
426
- h = null;
427
+ g = null;
427
428
  }
428
429
  }
429
430
  },
@@ -505,21 +506,21 @@ const z = () => ({
505
506
  // ====================================================================
506
507
  async fetchRecommendationProducts() {
507
508
  if (!(this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])) {
508
- if (g) {
509
- await g;
509
+ if (h) {
510
+ await h;
510
511
  return;
511
512
  }
512
- g = this._doFetchProducts();
513
+ h = this._doFetchProducts();
513
514
  try {
514
- await g;
515
+ await h;
515
516
  } finally {
516
- g = null;
517
+ h = null;
517
518
  }
518
519
  }
519
520
  },
520
521
  async _doFetchProducts() {
521
522
  var d;
522
- const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = P();
523
+ const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = F();
523
524
  if (r.strategyId && n.isFeatureEnabled("reusableRecommendationStrategy")) {
524
525
  await this._doFetchStrategyProducts(t);
525
526
  return;
package/dist/guido.css CHANGED
@@ -1 +1 @@
1
- @charset "UTF-8";.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-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__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-1ca6baf0]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-7de301b5]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-7de301b5]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-7de301b5]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .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-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{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-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-2580a7d9]{width:100%;max-width:none}.assign-strategy-drawer-content .assign-strategy-select[data-v-2580a7d9] .in-dropdown-box__container{width:413px}.assign-strategy-drawer .spaced-dot-sep{background-image:linear-gradient(90deg,#91949f 20%,#fff0 0);background-position:center bottom;background-repeat:repeat-x;background-size:5px 1px}.assign-strategy-drawer .spaced-dot-sep--top{background-position:center top}.assign-strategy-drawer .spaced-dot-sep--fc-n:first-child{background:none}
1
+ @charset "UTF-8";.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-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__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-1ca6baf0]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-050dfa52]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-050dfa52]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-050dfa52]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .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-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{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-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-2580a7d9]{width:100%;max-width:none}.assign-strategy-drawer-content .assign-strategy-select[data-v-2580a7d9] .in-dropdown-box__container{width:413px}.assign-strategy-drawer .spaced-dot-sep{background-image:linear-gradient(90deg,#91949f 20%,#fff0 0);background-position:center bottom;background-repeat:repeat-x;background-size:5px 1px}.assign-strategy-drawer .spaced-dot-sep--top{background-position:center top}.assign-strategy-drawer .spaced-dot-sep--fc-n:first-child{background:none}
@@ -17,13 +17,12 @@
17
17
  * - `error` segments (and message-level `isError` / `isCancelled`) trigger
18
18
  * a localized toaster.
19
19
  *
20
- * Every apply settles into a terminal `applyAcks` entry on the public store, so
21
- * cortex can move its Apply button on the truth of the editor write rather than
22
- * on the click.
23
- *
24
20
  * In dev (`import.meta.env.DEV`) every observed segment + message-level flag
25
21
  * change is also `console.debug`-logged with the prefix `[guido:cortex]` so a
26
22
  * developer can watch the agent stream in real time. In production this is
27
23
  * gated behind `localStorage.guido:debug:ai === '1'`.
24
+ *
25
+ * If cortex-fe isn't loaded the chat store is undefined and the bridge is a
26
+ * no-op (intentional — Guido must still work standalone).
28
27
  */
29
28
  export declare const useCortexBlueprintBridge: () => void;
@@ -1,20 +1,4 @@
1
1
  type ApplyStatus = 'pending' | 'applying' | 'applied' | 'failed';
2
- /**
3
- * Terminal outcome of an apply. Every promise this composable hands out settles
4
- * with exactly one of these — callers (the cortex bridge) ack on it, so a
5
- * never-settling promise would strand cortex's Apply button forever.
6
- *
7
- * `superseded` means a newer payload for the same blueprint replaced this one:
8
- * not a success, not a failure, and deliberately never acked.
9
- */
10
- export type ApplyOutcome = {
11
- status: 'applied';
12
- } | {
13
- status: 'failed';
14
- error: unknown;
15
- } | {
16
- status: 'superseded';
17
- };
18
2
  /**
19
3
  * Applies email_template blueprints from the chat agent to the Stripo editor.
20
4
  *
@@ -25,10 +9,6 @@ export type ApplyOutcome = {
25
9
  * - manual Apply click (first apply): immediate.
26
10
  * - blueprint_update after the user has applied once: debounced 250 ms trailing
27
11
  * so rapid mid-stream updates don't thrash updateHtmlAndCss.
28
- *
29
- * A click that lands before Stripo finished initializing is queued rather than
30
- * dropped, and flushed when `isStripoInitialized` flips — the user does not
31
- * have to click again.
32
12
  */
33
13
  export declare const useEmailTemplateApplier: () => {
34
14
  applyStatus: import("vue").Ref<Record<string, ApplyStatus>>;
@@ -36,11 +16,11 @@ export declare const useEmailTemplateApplier: () => {
36
16
  applyTemplate: (blueprintId: string, data: {
37
17
  html?: string;
38
18
  css?: string;
39
- }) => Promise<ApplyOutcome>;
19
+ }) => void;
40
20
  applyTemplateDebounced: (blueprintId: string, data: {
41
21
  html?: string;
42
22
  css?: string;
43
- }) => Promise<ApplyOutcome>;
23
+ }) => void;
44
24
  };
45
25
  export declare const resetEmailTemplateApplier: () => void;
46
26
  export {};
@@ -2,9 +2,4 @@ interface TranslationValues {
2
2
  [key: string]: string | number | boolean;
3
3
  }
4
4
  export declare const useTranslations: () => ((key: string, params?: TranslationValues) => string) & import("lodash").MemoizedFunction;
5
- /**
6
- * `trans()` echoes the key back when the host catalog has no entry, so a caller
7
- * shipping ahead of its i18n rows can substitute an English default.
8
- */
9
- export declare const useTranslationWithFallback: () => (key: string, fallback: string) => string;
10
5
  export {};
@@ -20,7 +20,6 @@ export * from './utils';
20
20
  export declare class RecommendationBlockControl extends CommonControl {
21
21
  private store;
22
22
  private storeUnsubscription;
23
- private syncedConfigs;
24
23
  private pendingNodeConfigWrite;
25
24
  private pendingConfigFlushTimer;
26
25
  private algorithmControl;
@@ -64,6 +63,11 @@ export declare class RecommendationBlockControl extends CommonControl {
64
63
  * fingerprint diff on this hook is the only way to notice (SD-149105).
65
64
  * An unchanged fingerprint means the move came from us, so runtime store
66
65
  * edits are never clobbered (SD-141049).
66
+ *
67
+ * The fingerprint is kept on the block's own store state so deleting the
68
+ * block drops it with the state it describes. A control-owned memo outlived
69
+ * that state and made a re-dropped saved module keep the defaults its wiped
70
+ * state was rebuilt with (SD-150347).
67
71
  */
68
72
  private _syncNodeConfigIfChanged;
69
73
  private _capturePendingNodeConfigWrite;
@@ -41,6 +41,16 @@ interface PerBlockState {
41
41
  isInitialized: boolean;
42
42
  /** Snapshot of filters taken when the drawer opens, used to revert on cancel */
43
43
  filterSnapshot: Filter[] | null;
44
+ /**
45
+ * Fingerprint of the node config as this block's state last adopted it.
46
+ *
47
+ * Lives here, not on the control, because it is a claim ABOUT this state —
48
+ * "the store already holds that node config". Held on the control it
49
+ * outlived the state it described: `removeBlockState` tore the state down
50
+ * while the fingerprint survived, so re-dropping a saved module under the
51
+ * same id skipped the re-sync and kept the defaults (SD-150347).
52
+ */
53
+ syncedConfigFingerprint: string | null;
44
54
  }
45
55
  /**
46
56
  * Persisted-config subset used by `seedBlockUrlConfig` to reconstruct
@@ -57,6 +67,8 @@ export interface PerBlockUrlConfig {
57
67
  filters: Filter[];
58
68
  shuffleProducts: boolean;
59
69
  currencyCode: string;
70
+ /** The displayed symbol, which is not the code — a TRY block shows `₺`. */
71
+ currencySymbol: string;
60
72
  currencyAlignment: 'before' | 'after';
61
73
  currencyDecimalCount: number;
62
74
  currencyDecimalSeparator: string;
@@ -1,28 +1,16 @@
1
- /** Terminal outcome of an editor write, keyed by `${blueprintId}:${version}`. */
2
- export interface ApplyAck {
3
- status: 'applied' | 'failed';
4
- /** The `applyRequestedAt` of the click this ack answers — lets cortex drop stale acks. */
5
- requestedAt: number;
6
- /** Strictly increasing per key, so two acks in the same millisecond still order. */
7
- ackAt: number;
8
- /** Stringified — cortex JSON-clones store-derived payloads, an Error would not survive. */
9
- error?: string;
10
- }
11
1
  /**
12
2
  * Outbound contract Guido publishes to the host's shared Pinia singleton so
13
3
  * cortex-fe can pick up the current editor state and forward it as
14
4
  * `clientState.editor` on the next chat-stream POST.
15
5
  *
16
- * This store is **state-only, by contract**. It declares no actions and no
17
- * non-trivial getters, so `pinia.state.value['guidoEmailEditor']` is a complete
18
- * view of it. cortex-fe reads it through that public path; adding an action or
19
- * a getter that cortex needs would silently break that read. Keep it
20
- * state-only. (`hasSnapshot` stays — cortex does not read it.)
6
+ * State + getters only — `useGuidoStateBridge` writes via `$patch`, no actions
7
+ * live here (architecture invariant).
21
8
  *
22
- * Store id `guidoEmailEditor` is cross-MFE. The internal Guido editor store
23
- * keeps id `guidoEditor` — these are intentionally separate. The internal store
24
- * carries UI state that cortex-fe should not see; this public store carries the
25
- * contract Guido is willing to share.
9
+ * Store id `guidoEmailEditor` is cross-MFE: cortex-fe reads it via
10
+ * `pinia._s.get('guidoEmailEditor')` at runtime. The internal Guido editor
11
+ * store keeps id `guidoEditor` — these are intentionally separate. The
12
+ * internal store carries UI state that cortex-fe should not see; this public
13
+ * store carries the contract Guido is willing to share.
26
14
  */
27
15
  export declare const useGuidoEmailEditorStore: import("pinia").StoreDefinition<"guidoEmailEditor", {
28
16
  /** Current Stripo HTML — stripe tables only, no DOCTYPE/wrapper. */
@@ -33,10 +21,6 @@ export declare const useGuidoEmailEditorStore: import("pinia").StoreDefinition<"
33
21
  lastUpdatedAt: number;
34
22
  /** Template id from the editor config, for cortex-fe to scope per-template. */
35
23
  templateId: string;
36
- /** True while a mounted Guido bridge is consuming the chat store. Gates cortex's Apply button. */
37
- bridgeActive: boolean;
38
- /** `${blueprintId}:${version}` → terminal outcome of the editor write, written only after it settles. */
39
- applyAcks: Record<string, ApplyAck>;
40
24
  }, {
41
25
  /** True once the bridge has published at least one snapshot. */
42
26
  hasSnapshot: (state: {
@@ -44,8 +28,6 @@ export declare const useGuidoEmailEditorStore: import("pinia").StoreDefinition<"
44
28
  css: string;
45
29
  lastUpdatedAt: number;
46
30
  templateId: string;
47
- bridgeActive: boolean;
48
- applyAcks: Record<string, ApplyAck>;
49
31
  } & import("pinia").PiniaCustomStateProperties<{
50
32
  /** Current Stripo HTML — stripe tables only, no DOCTYPE/wrapper. */
51
33
  html: string;
@@ -55,9 +37,5 @@ export declare const useGuidoEmailEditorStore: import("pinia").StoreDefinition<"
55
37
  lastUpdatedAt: number;
56
38
  /** Template id from the editor config, for cortex-fe to scope per-template. */
57
39
  templateId: string;
58
- /** True while a mounted Guido bridge is consuming the chat store. Gates cortex's Apply button. */
59
- bridgeActive: boolean;
60
- /** `${blueprintId}:${version}` → terminal outcome of the editor write, written only after it settles. */
61
- applyAcks: Record<string, ApplyAck>;
62
40
  }>) => boolean;
63
41
  }, {}>;
@@ -8,11 +8,7 @@ const d = e("guidoEmailEditor", {
8
8
  /** Wall-clock ms when html/css were last written by the bridge. */
9
9
  lastUpdatedAt: 0,
10
10
  /** Template id from the editor config, for cortex-fe to scope per-template. */
11
- templateId: "",
12
- /** True while a mounted Guido bridge is consuming the chat store. Gates cortex's Apply button. */
13
- bridgeActive: !1,
14
- /** `${blueprintId}:${version}` → terminal outcome of the editor write, written only after it settles. */
15
- applyAcks: {}
11
+ templateId: ""
16
12
  }),
17
13
  getters: {
18
14
  /** True once the bridge has published at least one snapshot. */
@@ -1,30 +1,30 @@
1
1
  import { useActionsApi as k } from "../composables/useActionsApi.js";
2
2
  import { useConfig as U } from "../composables/useConfig.js";
3
3
  import { useHtmlCompiler as x } from "../composables/useHtmlCompiler.js";
4
- import { DEFAULT_CURRENCY as d, DEFAULT_NODE_CONFIG as a } from "../extensions/Blocks/Recommendation/constants/defaultConfig.js";
5
- import { useRecommendationExtensionStore as C } from "../extensions/Blocks/Recommendation/store/recommendation.js";
4
+ import { DEFAULT_CURRENCY as m, DEFAULT_NODE_CONFIG as a } from "../extensions/Blocks/Recommendation/constants/defaultConfig.js";
5
+ import { useRecommendationExtensionStore as T } from "../extensions/Blocks/Recommendation/store/recommendation.js";
6
6
  import { mapLegacyStrategy as L } from "../extensions/Blocks/Recommendation/utils/legacyStrategyMap.js";
7
- import { DATA_ATTRIBUTES as A } from "../extensions/Blocks/Unsubscribe/utils/constants.js";
7
+ import { DATA_ATTRIBUTES as C } from "../extensions/Blocks/Unsubscribe/utils/constants.js";
8
8
  import { parsePageList as R } from "../extensions/Blocks/Unsubscribe/utils/utils.js";
9
9
  import { useDynamicContentStore as N } from "../stores/dynamic-content.js";
10
10
  import { useEditorStore as z } from "../stores/editor.js";
11
11
  import { useUnsubscribeStore as _ } from "../stores/unsubscribe.js";
12
12
  import { assignTrackingIds as v } from "./linkTrackingIds.js";
13
- function O(m) {
14
- const i = new DOMParser().parseFromString(m, "text/html").querySelectorAll(`[${A.PAGE_LIST}]`), t = [];
15
- return i.forEach((s) => {
16
- const o = s.getAttribute(A.PAGE_LIST);
13
+ function O(l) {
14
+ const c = new DOMParser().parseFromString(l, "text/html").querySelectorAll(`[${C.PAGE_LIST}]`), t = [];
15
+ return c.forEach((i) => {
16
+ const o = i.getAttribute(C.PAGE_LIST);
17
17
  o && t.push(...R(o));
18
18
  }), [...new Set(t)];
19
19
  }
20
- async function M(m) {
21
- const n = new DOMParser().parseFromString(m, "text/html").querySelectorAll(".recommendation-block-v2");
20
+ async function M(l) {
21
+ const n = new DOMParser().parseFromString(l, "text/html").querySelectorAll(".recommendation-block-v2");
22
22
  if (n.length === 0)
23
23
  return;
24
- const i = C();
24
+ const c = T();
25
25
  n.forEach((t) => {
26
- var r, l, g, f, c;
27
- const s = t.getAttribute("recommendation-id"), o = s ? Number(s) : NaN;
26
+ var r, d, g, f, s, y;
27
+ const i = t.getAttribute("recommendation-id"), o = i ? Number(i) : NaN;
28
28
  if (!Number.isFinite(o))
29
29
  return;
30
30
  const p = t.getAttribute("esd-ext-config");
@@ -38,7 +38,7 @@ async function M(m) {
38
38
  }
39
39
  if (!e || typeof e != "object" || Array.isArray(e))
40
40
  return;
41
- const h = {
41
+ const b = {
42
42
  // Normalize legacy strategy keys (e.g. `mostViewed` → `mostPopular`) so
43
43
  // already-saved blocks that never re-run the migrator don't emit a
44
44
  // strategy-less campaign URL. `||` also catches '' / undefined (SD-144882).
@@ -51,16 +51,17 @@ async function M(m) {
51
51
  productIds: e.productIds ?? [...a.productIds],
52
52
  filters: e.filters ?? [...a.filters],
53
53
  shuffleProducts: e.shuffleProducts ?? a.shuffleProducts,
54
- currencyCode: ((r = e.currency) == null ? void 0 : r.code) ?? d.code,
55
- currencyAlignment: ((l = e.currency) == null ? void 0 : l.alignment) ?? d.alignment,
56
- currencyDecimalCount: ((g = e.currency) == null ? void 0 : g.decimalCount) ?? d.decimalCount,
57
- currencyDecimalSeparator: ((f = e.currency) == null ? void 0 : f.decimalSeparator) ?? d.decimalSeparator,
58
- currencyThousandSeparator: ((c = e.currency) == null ? void 0 : c.thousandSeparator) ?? d.thousandSeparator
54
+ currencyCode: ((r = e.currency) == null ? void 0 : r.code) ?? m.code,
55
+ currencySymbol: ((d = e.currency) == null ? void 0 : d.symbol) ?? m.symbol,
56
+ currencyAlignment: ((g = e.currency) == null ? void 0 : g.alignment) ?? m.alignment,
57
+ currencyDecimalCount: ((f = e.currency) == null ? void 0 : f.decimalCount) ?? m.decimalCount,
58
+ currencyDecimalSeparator: ((s = e.currency) == null ? void 0 : s.decimalSeparator) ?? m.decimalSeparator,
59
+ currencyThousandSeparator: ((y = e.currency) == null ? void 0 : y.thousandSeparator) ?? m.thousandSeparator
59
60
  };
60
- i.seedBlockUrlConfig(o, h);
61
+ c.seedBlockUrlConfig(o, b);
61
62
  });
62
63
  try {
63
- await i.fetchRecommendationCreateData();
64
+ await c.fetchRecommendationCreateData();
64
65
  } catch (t) {
65
66
  console.warn(
66
67
  "Recommendation reference data pre-load failed; validator will skip the availability check.",
@@ -69,44 +70,44 @@ async function M(m) {
69
70
  }
70
71
  }
71
72
  const Z = () => {
72
- const m = N(), u = z(), n = _(), { getCompiledEmail: i, getTemplateData: t, updateHtmlAndCss: s } = k(), { compileHtml: o, compileAmpHtml: p } = x(), { isFeatureEnabled: e } = U();
73
+ const l = N(), u = z(), n = _(), { getCompiledEmail: c, getTemplateData: t, updateHtmlAndCss: i } = k(), { compileHtml: o, compileAmpHtml: p } = x(), { isFeatureEnabled: e } = U();
73
74
  return {
74
75
  prepareTemplateDetails: async () => {
75
- let { html: r, css: l, syncModulesIds: g = [] } = await t();
76
+ let { html: r, css: d, syncModulesIds: g = [] } = await t();
76
77
  if (e("linkTrackingIds"))
77
78
  try {
78
- const { html: S, changed: F, nextSeq: H } = v(r, u.trackIdSessionFloor);
79
- u.trackIdSessionFloor = H, F && (r = S, await s(S, l));
80
- } catch (S) {
81
- console.error("Tracking-id step failed, saving anyway:", S);
79
+ const { html: h, changed: F, nextSeq: H } = v(r, u.trackIdSessionFloor);
80
+ u.trackIdSessionFloor = H, F && (r = h, await i(h, d));
81
+ } catch (h) {
82
+ console.error("Tracking-id step failed, saving anyway:", h);
82
83
  }
83
- const { html: f, ampHtml: c = "", ampErrors: T = [] } = await i({
84
+ const { html: f, ampHtml: s = "", ampErrors: y = [] } = await c({
84
85
  minimize: !0,
85
86
  resetDataSavedFlag: !1
86
87
  });
87
88
  n.selectedUnsubscribePages.length && await n.fetchTemplates(), await M(r);
88
- const { compiledHtml: I, stats: y, appliedRules: w } = o(f), D = c && p(c).compiledHtml, E = m.getSelectedDynamicContentList, P = C(), b = O(r);
89
+ const { compiledHtml: I, stats: S, appliedRules: w } = o(f), D = s && p(s).compiledHtml, E = l.getSelectedDynamicContentList, P = T(), A = O(r);
89
90
  return console.debug("HTML Compilation Stats:", {
90
- originalSize: y.originalSize,
91
- compiledSize: y.compiledSize,
92
- reduction: `${y.reductionPercentage.toFixed(2)}%`,
91
+ originalSize: S.originalSize,
92
+ compiledSize: S.compiledSize,
93
+ reduction: `${S.reductionPercentage.toFixed(2)}%`,
93
94
  appliedRules: w,
94
- executionTime: `${y.executionTime.toFixed(2)}ms`
95
+ executionTime: `${S.executionTime.toFixed(2)}ms`
95
96
  }), {
96
97
  dynamicContentList: E,
97
98
  compiledHtml: I,
98
99
  rawHtml: r,
99
- css: l,
100
+ css: d,
100
101
  ampHtml: D,
101
- ampErrors: T,
102
+ ampErrors: y,
102
103
  modules: g.map(Number),
103
104
  recommendation: {
104
105
  campaignUrls: P.recommendationCampaignUrls,
105
106
  configs: {}
106
107
  },
107
108
  unsubscribe: {
108
- status: b.length > 0,
109
- config: b
109
+ status: A.length > 0,
110
+ config: A
110
111
  }
111
112
  };
112
113
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useinsider/guido",
3
- "version": "3.18.1-beta.4bd98d6",
3
+ "version": "3.18.1-beta.4fbee43",
4
4
  "description": "Guido is a Vue + TypeScript wrapper for Email Plugin. Easily embed the email editor in your Vue applications.",
5
5
  "main": "./dist/guido.umd.cjs",
6
6
  "module": "./dist/library.js",