@useinsider/guido 3.18.2 → 3.19.0

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.
package/README.md CHANGED
@@ -561,6 +561,26 @@ import {
561
561
  import '@useinsider/guido/style';
562
562
  ```
563
563
 
564
+ ### Subpath entries
565
+
566
+ Two surfaces also ship as their own entry points. Importing one pulls in only its
567
+ own dependencies, so a consumer that needs the store or the tracking-id helpers
568
+ never loads the editor:
569
+
570
+ ```typescript
571
+ // Live editor state, published by the editor into the host's shared Pinia instance.
572
+ // Store id `guidoEmailEditor` is the cross-app contract — read it, do not redeclare it.
573
+ import { useGuidoEmailEditorStore } from '@useinsider/guido/editor-state';
574
+ import type { GuidoEmailEditorState } from '@useinsider/guido/editor-state';
575
+
576
+ // Persistent link ids for the click heatmap.
577
+ import { assignTrackingIds, TRACK_ID_ATTRIBUTE } from '@useinsider/guido/tracking-ids';
578
+ import type { TrackingIdResult } from '@useinsider/guido/tracking-ids';
579
+ ```
580
+
581
+ Both are re-exported from the root barrel as well; the subpath is what keeps the
582
+ editor out of the consumer's module graph.
583
+
564
584
  ---
565
585
 
566
586
  ## Constants
@@ -1,64 +1,64 @@
1
- import { defineComponent as A, ref as c, computed as b, toRef as h, nextTick as C } from "vue";
2
- import N from "../../wrappers/WpDrawer.vue.js";
3
- import { useTranslations as O } from "../../../composables/useTranslations.js";
1
+ import { defineComponent as _, ref as c, computed as h, watch as C, toRef as N, nextTick as O } from "vue";
2
+ import b from "../../wrappers/WpDrawer.vue.js";
3
+ import { useTranslations as D } from "../../../composables/useTranslations.js";
4
4
  import { useTemplateNameValidator as x } from "../../../composables/validators/saveAsTemplate.js";
5
5
  import { useTemplateLibraryApi as B } from "../../../services/templateLibraryApi.js";
6
- import { useEditorStore as D } from "../../../stores/editor.js";
7
- import { useSaveAsTemplateStore as k } from "../../../stores/save-as-template.js";
8
- import { InMultiSelect as I, InBasicTextInput as M } from "@useinsider/design-system-vue";
9
- import { useDebounceFn as V } from "../../../node_modules/@vueuse/shared/index.js";
10
- const H = /* @__PURE__ */ A({
6
+ import { useEditorStore as k } from "../../../stores/editor.js";
7
+ import { useSaveAsTemplateStore as I } from "../../../stores/save-as-template.js";
8
+ import { InMultiSelect as M, InBasicTextInput as V } from "@useinsider/design-system-vue";
9
+ import { useDebounceFn as E } from "../../../node_modules/@vueuse/shared/index.js";
10
+ const J = /* @__PURE__ */ _({
11
11
  __name: "SaveAsTemplateDrawer",
12
- setup(E) {
13
- const o = O(), n = D(), t = k(), { createTemplate: m } = B(), a = c(!1), r = c(!1), l = c(""), f = b(() => ({
12
+ setup(R) {
13
+ const s = D(), o = k(), t = I(), { createTemplate: m } = B(), a = c(!1), n = c(!1), r = c(""), f = h(() => ({
14
14
  primaryButton: {
15
15
  styling: "solid",
16
16
  type: "primary",
17
- labelText: o(a.value ? "newsletter.saving" : "products.save"),
17
+ labelText: s(a.value ? "newsletter.saving" : "products.save"),
18
18
  loadingStatus: a.value,
19
19
  disabledStatus: t.skeletonStatus
20
20
  },
21
21
  cancelOrBackButton: {
22
22
  styling: "ghost",
23
23
  type: "secondary",
24
- labelText: o("products.cancel"),
24
+ labelText: s("products.cancel"),
25
25
  disabledStatus: a.value
26
26
  }
27
- })), u = () => {
28
- l.value = "", n.isSaveAsTemplateDrawerOpen = !1;
29
- }, i = async () => {
30
- const e = h(t, "templateName"), { success: s, errorMessage: _ } = await x(e).validate();
31
- return l.value = _, s;
32
- }, v = V(async (e) => {
33
- t.templateName = e, await i();
34
- }, 500), g = async (e) => {
35
- r.value = !0, await t.addCategory(e), r.value = !1;
36
- }, y = (e) => {
27
+ })), p = () => {
28
+ r.value = "", o.isSaveAsTemplateDrawerOpen = !1;
29
+ }, l = async () => {
30
+ const e = N(t, "templateName"), { success: i, errorMessage: A } = await x(e).validate();
31
+ return r.value = A, i;
32
+ }, v = E(async (e) => {
33
+ t.templateName = e, await l();
34
+ }, 500), S = async (e) => {
35
+ n.value = !0, await t.addCategory(e), n.value = !1;
36
+ }, T = (e) => {
37
37
  t.selectedCategories = e;
38
- }, S = (e) => {
38
+ }, g = (e) => {
39
39
  e && (t.selectedCategories = e);
40
- }, T = () => {
40
+ }, y = () => {
41
41
  t.selectedCategories = [];
42
42
  }, w = async () => {
43
- if (a.value = !0, !await i()) {
43
+ if (a.value = !0, !await l()) {
44
44
  a.value = !1;
45
45
  return;
46
46
  }
47
- const s = await m();
48
- a.value = !1, s && u();
49
- }, p = () => {
50
- C(() => {
47
+ const i = await m();
48
+ a.value = !1, i && p();
49
+ }, u = () => {
50
+ O(() => {
51
51
  const e = document.querySelector("input#guido__template-name-input");
52
52
  e == null || e.focus();
53
53
  });
54
54
  }, d = async () => {
55
- t.$reset(), await t.fetchCategories(), t.skeletonStatus = !1, p();
55
+ t.$reset(), await t.fetchCategories(), t.skeletonStatus = !1, u();
56
56
  };
57
- return n.$subscribe((e, { isSaveAsTemplateDrawerOpen: s }) => {
58
- s && d();
59
- }), { __sfc: !0, trans: o, editorStore: n, saveAsTemplateStore: t, createTemplate: m, isSaving: a, isAddingOption: r, templateNameError: l, footerButtonGroupOptions: f, closeModal: u, validateTemplateName: i, handleTemplateName: v, handleAddOption: g, handleCategoryChange: y, handleSelectAllOptions: S, handleResetAllOptions: T, saveTemplate: w, focusToInput: p, initializeDrawer: d, WpDrawer: N, InBasicTextInput: M, InMultiSelect: I };
57
+ return C(() => o.isSaveAsTemplateDrawerOpen, (e) => {
58
+ e && d();
59
+ }), { __sfc: !0, trans: s, editorStore: o, saveAsTemplateStore: t, createTemplate: m, isSaving: a, isAddingOption: n, templateNameError: r, footerButtonGroupOptions: f, closeModal: p, validateTemplateName: l, handleTemplateName: v, handleAddOption: S, handleCategoryChange: T, handleSelectAllOptions: g, handleResetAllOptions: y, saveTemplate: w, focusToInput: u, initializeDrawer: d, WpDrawer: b, InBasicTextInput: V, InMultiSelect: M };
60
60
  }
61
61
  });
62
62
  export {
63
- H as default
63
+ J as default
64
64
  };
@@ -1,54 +1,59 @@
1
- import { useActionsApi as b } from "./useActionsApi.js";
2
- import { useEditorLock as v } from "./useEditorLock.js";
1
+ import { useActionsApi as v } from "./useActionsApi.js";
2
+ import { useEditorLock as C } from "./useEditorLock.js";
3
3
  import { useConfigStore as T } from "../stores/config.js";
4
4
  import { useEditorStore as w } from "../stores/editor.js";
5
5
  import { useGuidoEmailEditorStore as y } from "../stores/guido-email-editor.js";
6
- import { watch as a, onUnmounted as B } from "vue";
7
- const C = 500, L = () => {
8
- const i = w(), u = y(), l = T(), { getTemplateData: d } = b(), { runExclusive: m, isEditorBusy: p } = v();
9
- let o = null, s = !1;
10
- const n = () => {
6
+ import { watch as c, onUnmounted as z } from "vue";
7
+ const B = 500, G = () => {
8
+ const i = w(), u = y(), d = T(), { getTemplateData: l } = v(), { runExclusive: m, isEditorBusy: p } = C();
9
+ let o = null, n = !1;
10
+ const r = () => {
11
11
  o && (clearTimeout(o), o = null);
12
- }, c = (t) => {
13
- n(), o = setTimeout(() => {
12
+ }, a = (t) => {
13
+ r(), o = setTimeout(() => {
14
14
  o = null, t();
15
- }, C);
15
+ }, B);
16
16
  }, e = async () => {
17
- var t, r;
18
- if (!(s || !i.isStripoInitialized)) {
17
+ var t, s;
18
+ if (!(n || !i.isStripoInitialized)) {
19
19
  if (p()) {
20
- c(() => void e());
20
+ a(() => void e());
21
21
  return;
22
22
  }
23
23
  try {
24
- const { html: E, css: g } = await m(d), I = ((r = (t = l.config) == null ? void 0 : t.identity) == null ? void 0 : r.templateId) ?? "";
25
- if (s)
24
+ const { html: E, css: I } = await m(l), b = ((s = (t = d.config) == null ? void 0 : t.identity) == null ? void 0 : s.templateId) ?? "";
25
+ if (n)
26
26
  return;
27
27
  u.$patch({
28
28
  html: E ?? "",
29
- css: g ?? "",
30
- templateId: I,
29
+ css: I ?? "",
30
+ templateId: b,
31
31
  lastUpdatedAt: Date.now()
32
32
  });
33
33
  } catch {
34
34
  }
35
35
  }
36
- }, f = () => c(() => void e()), h = a(
36
+ }, f = () => a(() => void e()), h = c(
37
37
  () => i.isStripoInitialized,
38
38
  (t) => {
39
39
  t && e();
40
40
  },
41
41
  { immediate: !0 }
42
- ), S = a(
42
+ ), S = c(
43
+ () => i.changeSeq,
44
+ () => {
45
+ i.isStripoInitialized && f();
46
+ }
47
+ ), g = c(
43
48
  () => i.hasChanges,
44
- (t, r) => {
45
- i.isStripoInitialized && (t ? f() : r && (n(), e()));
49
+ (t, s) => {
50
+ !t && s && i.isStripoInitialized && (r(), e());
46
51
  }
47
52
  );
48
- B(() => {
49
- s = !0, n(), h(), S();
53
+ z(() => {
54
+ n = !0, r(), h(), S(), g();
50
55
  });
51
56
  };
52
57
  export {
53
- L as useGuidoStateBridge
58
+ G as useGuidoStateBridge
54
59
  };
@@ -1,14 +1,16 @@
1
- import { getCsrfToken as H } from "../utils/genericUtil.js";
2
- import { ref as p, computed as T } from "vue";
3
- const k = (b = {}) => {
4
- const h = p(!1), a = p(null), u = p(null), g = T(() => h.value), y = T(() => a.value !== null), v = {
1
+ import { getCsrfToken as O } from "../utils/genericUtil.js";
2
+ import { ref as m, computed as T } from "vue";
3
+ const X = (b = {}) => {
4
+ const p = m(!1), a = m(null), u = m(null), g = T(() => p.value), y = T(() => a.value !== null), v = {
5
5
  baseURL: "",
6
6
  timeout: 1e4,
7
7
  retry: 0,
8
8
  retryDelay: 1e3,
9
9
  headers: {
10
10
  "Content-Type": "application/json",
11
- "X-CSRF-TOKEN": H()
11
+ "X-CSRF-TOKEN": O(),
12
+ Accept: "application/json",
13
+ "X-Requested-With": "XMLHttpRequest"
12
14
  },
13
15
  ...b
14
16
  }, w = (e, s) => {
@@ -22,22 +24,22 @@ const k = (b = {}) => {
22
24
  }, e);
23
25
  }), x = (e) => new Promise((s) => {
24
26
  setTimeout(s, e);
25
- }), i = async (e, s, t, D = {}) => {
26
- a.value = null, h.value = !0, u.value = new AbortController();
27
- const n = { ...v, ...D }, L = w(s, n.baseURL), c = {
27
+ }), i = async (e, s, t, L = {}) => {
28
+ a.value = null, p.value = !0, u.value = new AbortController();
29
+ const n = { ...v, ...L }, D = w(s, n.baseURL), c = {
28
30
  method: e,
29
31
  headers: { ...n.headers },
30
32
  signal: u.value.signal,
31
33
  ...n
32
34
  };
33
35
  t && ["POST", "PUT", "PATCH"].includes(e) && (t instanceof FormData ? (delete c.headers["Content-Type"], c.body = t) : c.body = JSON.stringify(t));
34
- const E = async (m = 0) => {
36
+ const E = async (h = 0) => {
35
37
  try {
36
- const o = [fetch(L, c)];
38
+ const o = [fetch(D, c)];
37
39
  n.timeout && o.push(P(n.timeout));
38
40
  const r = await Promise.race(o);
39
41
  if (!r.ok) {
40
- const O = `HTTP Error: ${r.status} ${r.statusText}`, d = new Error(O);
42
+ const H = `HTTP Error: ${r.status} ${r.statusText}`, d = new Error(H);
41
43
  throw d.status = r.status, d.statusText = r.statusText, d.response = r, d;
42
44
  }
43
45
  let f;
@@ -50,19 +52,19 @@ const k = (b = {}) => {
50
52
  };
51
53
  } catch (o) {
52
54
  const r = o instanceof Error && o.name === "AbortError";
53
- if (m < (n.retry || 0) && !r)
54
- return await x(n.retryDelay || 1e3), E(m + 1);
55
+ if (h < (n.retry || 0) && !r)
56
+ return await x(n.retryDelay || 1e3), E(h + 1);
55
57
  throw o instanceof Error ? o.name === "AbortError" ? a.value = { message: "Request was cancelled" } : a.value = { message: o.message } : a.value = o, o;
56
58
  }
57
59
  };
58
60
  try {
59
61
  return await E();
60
62
  } finally {
61
- h.value = !1, u.value = null;
63
+ p.value = !1, u.value = null;
62
64
  }
63
- }, C = (e, s) => i("GET", e, void 0, s), $ = (e, s, t) => i("POST", e, s, t), R = (e, s, t) => i("PUT", e, s, t), U = (e, s, t) => i("PATCH", e, s, t), A = (e, s) => i("DELETE", e, void 0, s), W = (e) => {
65
+ }, C = (e, s) => i("GET", e, void 0, s), R = (e, s, t) => i("POST", e, s, t), $ = (e, s, t) => i("PUT", e, s, t), q = (e, s, t) => i("PATCH", e, s, t), A = (e, s) => i("DELETE", e, void 0, s), U = (e) => {
64
66
  u.value && u.value.abort(e);
65
- }, q = () => {
67
+ }, W = () => {
66
68
  a.value = null;
67
69
  };
68
70
  return {
@@ -73,14 +75,14 @@ const k = (b = {}) => {
73
75
  // Methods
74
76
  request: i,
75
77
  get: C,
76
- post: $,
77
- put: R,
78
- patch: U,
78
+ post: R,
79
+ put: $,
80
+ patch: q,
79
81
  delete: A,
80
- cancel: W,
81
- clearError: q
82
+ cancel: U,
83
+ clearError: W
82
84
  };
83
85
  };
84
86
  export {
85
- k as useHttp
87
+ X as useHttp
86
88
  };
@@ -1,6 +1,6 @@
1
- import { useActionsApi as L } from "./useActionsApi.js";
2
- import { useBlocksConfig as O } from "./useBlocksConfig.js";
3
- import { useConfig as q } from "./useConfig.js";
1
+ import { useActionsApi as x } from "./useActionsApi.js";
2
+ import { useBlocksConfig as L } from "./useBlocksConfig.js";
3
+ import { useConfig as O } from "./useConfig.js";
4
4
  import { useCustomInterfaceAppearance as H } from "./useCustomInterfaceAppearance.js";
5
5
  import { useFullStoryBridge as N } from "./useFullStoryBridge.js";
6
6
  import { useModuleRepair as j } from "./useModuleRepair.js";
@@ -17,7 +17,7 @@ import { buildMergeTagEntries as W, flattenDynamicContentList as Y } from "../ut
17
17
  import Z from "../package.json.js";
18
18
  let n = null;
19
19
  const Ce = () => {
20
- const { features: c, template: u, isFeatureEnabled: m } = q(), { handleError: p, showToaster: k } = G(), { getToken: B, getCustomFonts: M, getSyncModulesStatus: T } = K(), { handleEvent: v } = z(), { handleModuleAdd: F } = j(), { getStripoBlocksConfig: A } = O(), { getStripoNotifications: V } = $(), f = () => n || (n = new Promise((i, s) => {
20
+ const { features: c, template: u, isFeatureEnabled: m } = O(), { handleError: p, showToaster: k } = G(), { getToken: B, getCustomFonts: M, getSyncModulesStatus: T } = K(), { handleEvent: v } = z(), { handleModuleAdd: F } = j(), { getStripoBlocksConfig: A } = L(), { getStripoNotifications: V } = $(), f = () => n || (n = new Promise((i, s) => {
21
21
  var d;
22
22
  if (document.getElementById("UiEditorScript")) {
23
23
  i();
@@ -88,8 +88,8 @@ const Ce = () => {
88
88
  },
89
89
  onTemplateLoaded() {
90
90
  try {
91
- const { importCss: t } = H(), { activateCustomViewStyles: l, updateTimerInClonedTemplate: I } = L(), { injectFullStory: x } = N();
92
- t(), l(), x(), I(), o.onReady(), e.isStripoInitialized = !0, e.loadingStatus = !1, setTimeout(() => {
91
+ const { importCss: t } = H(), { activateCustomViewStyles: l, updateTimerInClonedTemplate: I } = x(), { injectFullStory: q } = N();
92
+ t(), l(), q(), I(), o.onReady(), e.isStripoInitialized = !0, e.loadingStatus = !1, setTimeout(() => {
93
93
  e.hasChanges = !1;
94
94
  }, 1e3);
95
95
  } catch (t) {
@@ -106,7 +106,7 @@ const Ce = () => {
106
106
  e.isVersionHistoryOpen = t;
107
107
  },
108
108
  onDataChanged() {
109
- e.hasChanges = !0;
109
+ e.hasChanges = !0, e.changeSeq += 1;
110
110
  },
111
111
  onEvent: v,
112
112
  onModuleAdd: F,
@@ -67,7 +67,7 @@ class se extends ut {
67
67
  (d, c) => `
68
68
  <div data-reorder-icon-key="${P}${c}" style="display: none;">
69
69
  <${_.BUTTON}
70
- class="drag-handle-btn flat-inline flat-white"
70
+ class="guido-drag-handle-btn flat-inline flat-white"
71
71
  ${O.BUTTON.name}="${P}${c}"
72
72
  >
73
73
  <${_.ICON}
@@ -328,7 +328,7 @@ class se extends ut {
328
328
  _createBuiltInItemHtml(t, e) {
329
329
  return `
330
330
  <div class="orderable-item" draggable="true" data-key="${t.key}">
331
- <span class="drag-handle" data-reorder-icon-slot="${e}"></span>
331
+ <span class="guido-drag-handle" data-reorder-icon-slot="${e}"></span>
332
332
  <span class="item-label">${this.api.translate(t.label)}</span>
333
333
  <div class="item-action" data-action-for="${t.key}"></div>
334
334
  </div>
@@ -353,7 +353,7 @@ class se extends ut {
353
353
  <div class="orderable-item price-group-item" draggable="true"
354
354
  data-key="${C}" data-group="prices">
355
355
  <div class="price-group-header">
356
- <span class="drag-handle" data-reorder-icon-slot="${t}"></span>
356
+ <span class="guido-drag-handle" data-reorder-icon-slot="${t}"></span>
357
357
  <span class="item-label">${this.api.translate("Product Prices")}</span>
358
358
  <div class="item-action" data-action-for="${C}"></div>
359
359
  </div>
@@ -365,7 +365,7 @@ class se extends ut {
365
365
  return `
366
366
  <div class="orderable-item" draggable="true"
367
367
  data-key="${t}" data-custom-index="${e}">
368
- <span class="drag-handle" data-reorder-icon-slot="${r}"></span>
368
+ <span class="guido-drag-handle" data-reorder-icon-slot="${r}"></span>
369
369
  <div class="custom-attr-select-wrap"
370
370
  data-custom-select-slot="${e}"></div>
371
371
  <div class="item-action"
@@ -134,7 +134,10 @@ ue-orderable.orderable-disabled .droppable-icon {
134
134
  border-top: 2px solid var(--guido-color-primary-500, #0A2ECC);
135
135
  }
136
136
 
137
- .drag-handle {
137
+ /* Namespaced: Stripo ships a global \`.drag-handle { position: absolute }\` for its
138
+ floating popups, which knocked this handle out of flow (SD-151734). */
139
+ .guido-drag-handle {
140
+ cursor: move;
138
141
  user-select: none;
139
142
  display: flex;
140
143
  align-items: center;
@@ -144,13 +147,13 @@ ue-orderable.orderable-disabled .droppable-icon {
144
147
  flex-shrink: 0;
145
148
  }
146
149
 
147
- .drag-handle .drag-handle-btn .button {
150
+ .guido-drag-handle .guido-drag-handle-btn .button {
148
151
  padding: 0;
149
152
  min-width: auto;
150
153
  cursor: move;
151
154
  }
152
155
 
153
- .drag-handle .drag-handle-btn .button .icon-button {
156
+ .guido-drag-handle .guido-drag-handle-btn .button .icon-button {
154
157
  color: var(--guido-color-gray-600);
155
158
  }
156
159
 
package/dist/library.js CHANGED
@@ -1,18 +1,20 @@
1
- import { default as e } from "./components/Guido.vue.js";
2
- import { MessageType as f, ProductType as s } from "./@types/config/schemas.js";
1
+ import { default as a } from "./components/Guido.vue.js";
2
+ import { MessageType as t, ProductType as d } from "./@types/config/schemas.js";
3
3
  import "./@types/config/defaults.js";
4
- import { getValidationErrors as d, isValidConfig as p, parseConfig as g, parseConfigSafe as n, validateConfig as l } from "./@types/config/validator.js";
5
- import { assignTrackingIds as T, readTrackFloor as c, readTrackSeq as x } from "./utils/linkTrackingIds.js";
4
+ import { getValidationErrors as s, isValidConfig as p, parseConfig as g, parseConfigSafe as m, validateConfig as n } from "./@types/config/validator.js";
5
+ import { assignTrackingIds as u, readTrackFloor as x, readTrackSeq as T } from "./utils/linkTrackingIds.js";
6
+ import { useGuidoEmailEditorStore as C } from "./stores/guido-email-editor.js";
6
7
  export {
7
- e as Guido,
8
- f as MessageType,
9
- s as ProductType,
10
- T as assignTrackingIds,
11
- d as getValidationErrors,
8
+ a as Guido,
9
+ t as MessageType,
10
+ d as ProductType,
11
+ u as assignTrackingIds,
12
+ s as getValidationErrors,
12
13
  p as isValidConfig,
13
14
  g as parseConfig,
14
- n as parseConfigSafe,
15
- c as readTrackFloor,
16
- x as readTrackSeq,
17
- l as validateConfig
15
+ m as parseConfigSafe,
16
+ x as readTrackFloor,
17
+ T as readTrackSeq,
18
+ C as useGuidoEmailEditorStore,
19
+ n as validateConfig
18
20
  };
@@ -1,4 +1,4 @@
1
- const o = { stripo: { version: "2.76.0" } }, s = {
1
+ const o = { stripo: { version: "2.77.0" } }, s = {
2
2
  guido: o
3
3
  };
4
4
  export {
@@ -0,0 +1,4 @@
1
+ import { useGuidoEmailEditorStore as e } from "../stores/guido-email-editor.js";
2
+ export {
3
+ e as useGuidoEmailEditorStore
4
+ };
@@ -4,13 +4,14 @@ import { useToaster as C } from "../composables/useToaster.js";
4
4
  import { useTranslations as h } from "../composables/useTranslations.js";
5
5
  import { useLiquidValidator as S } from "../composables/validators/useLiquidValidator.js";
6
6
  import { EditorType as v } from "../enums/defaults.js";
7
- import { ToasterTypeOptions as N } from "../enums/toaster.js";
8
- import { useRecommendationExtensionStore as x } from "../extensions/Blocks/Recommendation/store/recommendation.js";
9
- import { useSaveAsTemplateStore as E } from "../stores/save-as-template.js";
7
+ import { ToasterTypeOptions as x } from "../enums/toaster.js";
8
+ import { useRecommendationExtensionStore as E } from "../extensions/Blocks/Recommendation/store/recommendation.js";
9
+ import { useSaveAsTemplateStore as N } from "../stores/save-as-template.js";
10
10
  import { base64EncodeWithSpecialChars as r } from "../utils/base64.js";
11
+ import { isPlainObject as P } from "../utils/genericUtil.js";
11
12
  import { useTemplatePreparation as A } from "../utils/templatePreparation.js";
12
- const j = () => {
13
- const { get: n, post: m } = b(), { handleError: o, showToaster: l } = C(), { config: c, isFeatureEnabled: p } = w(), { validateLiquidSyntax: g } = S(), u = h();
13
+ const B = () => {
14
+ const { get: n, post: m } = b(), { handleError: o, showToaster: l } = C(), { config: c, isFeatureEnabled: p } = w(), { validateLiquidSyntax: f } = S(), u = h();
14
15
  return {
15
16
  getCategories: async () => {
16
17
  try {
@@ -40,10 +41,10 @@ const j = () => {
40
41
  createTemplate: async () => {
41
42
  var e, t, d, y;
42
43
  try {
43
- const { prepareTemplateDetails: i } = A(), s = E(), a = await i();
44
- if (p("liquidSyntax") && !await g(a.compiledHtml))
44
+ const { prepareTemplateDetails: i } = A(), s = N(), a = await i();
45
+ if (p("liquidSyntax") && !await f(a.compiledHtml))
45
46
  return !1;
46
- const f = {
47
+ const T = {
47
48
  name: s.getTemplateName,
48
49
  categories: s.getSelectedCategoryIds,
49
50
  productId: ((t = (e = c.value) == null ? void 0 : e.partner) == null ? void 0 : t.productType) || 0,
@@ -54,7 +55,7 @@ const j = () => {
54
55
  unsubscriptionPreferencePageStatus: !1,
55
56
  unsubscriptionPreferencePages: [],
56
57
  recommendationCampaignUrls: r(
57
- x().recommendationCampaignUrls
58
+ E().recommendationCampaignUrls
58
59
  ),
59
60
  recommendationConfigs: r({}),
60
61
  isGuido: !0,
@@ -66,16 +67,18 @@ const j = () => {
66
67
  css: a.css,
67
68
  dynamicContentList: a.dynamicContentList
68
69
  })
69
- }, { data: { type: T } } = await m(
70
+ }, { data: g } = await m(
70
71
  "/newsletter/template-library/create-template",
71
- f
72
+ T
72
73
  );
73
- return T === "alert" ? (l({
74
+ if (!P(g))
75
+ throw new Error("Unexpected create-template response");
76
+ return g.type === "alert" ? (l({
74
77
  message: u(
75
78
  "newsletter.template-library-save-alert",
76
79
  { templateName: s.getTemplateName }
77
80
  ),
78
- type: N.Error
81
+ type: x.Error
79
82
  }), !1) : (l({
80
83
  message: u(
81
84
  "newsletter.template-library-save-success",
@@ -90,5 +93,5 @@ const j = () => {
90
93
  };
91
94
  };
92
95
  export {
93
- j as useTemplateLibraryApi
96
+ B as useTemplateLibraryApi
94
97
  };
@@ -1,22 +1,26 @@
1
1
  /**
2
2
  * Outbound bridge — publishes the current editor's html/css to the shared
3
- * Pinia store `guidoEmailEditor` so cortex-fe can read it at chat-stream
4
- * submit time and forward it as `clientState.editor`. This is what enables
3
+ * Pinia store `guidoEmailEditor`. cortex-fe reads it at chat-stream submit
4
+ * time and forwards it as `clientState.editor`, which is what enables
5
5
  * sub-case 1.3 (refine an already-loaded template via the email-agent).
6
6
  *
7
7
  * The bridge writes on three triggers:
8
8
  *
9
9
  * 1. Stripo finishes initializing — first snapshot.
10
- * 2. Editor `hasChanges` flips to true — debounced 500 ms so a streaming
11
- * Stripo edit doesn't thrash the store.
10
+ * 2. Every document change, via the `changeSeq` counter — debounced 500 ms
11
+ * so a streaming Stripo edit doesn't thrash the store.
12
12
  * 3. Editor `hasChanges` flips back to false (post-save / autosave) —
13
13
  * immediate, since this is the canonical "saved" snapshot.
14
14
  *
15
15
  * `getTemplateData()` is a Stripo iframe call; it must not run before
16
16
  * `isStripoInitialized` is true. The bridge guards against that.
17
17
  *
18
- * If cortex-fe isn't loaded the store still gets written — that's fine;
19
- * the store has zero overhead and any future reader will find consistent
20
- * state. The bridge is a one-way pipe with no consumer dependency.
18
+ * The store is written even with no reader attached — it has zero overhead,
19
+ * and a late reader still finds consistent state.
20
+ *
21
+ * Readers are not optional any more, so treat the publish timing as part of
22
+ * the contract: the store ships as `@useinsider/guido/editor-state`, and
23
+ * email-fe imports it to scan the live html for its Array of Objects lock.
24
+ * Weakening a trigger here silently breaks that lock in the consumer.
21
25
  */
22
26
  export declare const useGuidoStateBridge: () => void;
@@ -2,5 +2,7 @@ export { default as Guido } from './components/Guido.vue';
2
2
  export type { GuidoConfig, GuidoConfigInput, IdentityConfig, PartnerConfig, TemplateConfig, TemplateMigrationConfig, LegacyRecommendationConfig, EditorConfig, UIConfig, FeaturesConfig, BlocksConfig, CompilerConfig, DynamicContent, EmailHeader, DefaultBlockType, CustomBlockType, ValidationResult, ValidationError, } from './@types/config';
3
3
  export { validateConfig, parseConfig, parseConfigSafe, isValidConfig, getValidationErrors, MessageType, ProductType, } from './@types/config';
4
4
  export { assignTrackingIds, readTrackFloor, readTrackSeq } from './public/trackingIds';
5
+ export { useGuidoEmailEditorStore } from './public/editorState';
6
+ export type { GuidoEmailEditorState } from './public/editorState';
5
7
  export type { StripoEventType } from './@types/events';
6
8
  export type { PositionData, DynamicContentEvent, MergeTagClickEvent, MergeTag, BaseDynamicContent, DynamicContentNode, DynamicContentList, TooltipOptions, TextValueObject, L10n, } from './@types/generic';
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Published as `@useinsider/guido/editor-state` — the live editor snapshot Guido
3
+ * writes into the host's shared Pinia singleton.
4
+ *
5
+ * Importing from here pulls in nothing but pinia, so the editor never enters a
6
+ * consumer's module graph. Re-export surface only: this is the contract,
7
+ * `stores/guido-email-editor` is the implementation and stays free to move.
8
+ *
9
+ * Consumers read the store by importing it; the id `guidoEmailEditor` remains
10
+ * part of the contract for cortex-fe, which probes `pinia._s` at runtime instead
11
+ * of taking a build-time dependency on this package.
12
+ */
13
+ export { useGuidoEmailEditorStore } from '../stores/guido-email-editor';
14
+ export type { GuidoEmailEditorState } from '../stores/guido-email-editor';
@@ -4,6 +4,10 @@
4
4
  * Importing from here pulls in nothing else, so the editor never enters a
5
5
  * consumer's module graph. Re-export surface only: this is the contract,
6
6
  * `utils/linkTrackingIds` is the implementation and stays free to move.
7
+ *
8
+ * Relative, not the `@@/Utils/` alias: vue-tsc copies the specifier into the emitted
9
+ * .d.ts verbatim, and a consumer's TypeScript cannot resolve our alias table. A relative
10
+ * path resolves against dist/src/, so the published types actually load.
7
11
  */
8
- export { assignTrackingIds, readTrackFloor, readTrackSeq, TRACK_ID_ATTRIBUTE, TRACK_SEQ_ATTRIBUTE, } from '@@/Utils/linkTrackingIds';
9
- export type { TrackingIdResult } from '@@/Utils/linkTrackingIds';
12
+ export { assignTrackingIds, readTrackFloor, readTrackSeq, TRACK_ID_ATTRIBUTE, TRACK_SEQ_ATTRIBUTE, } from '../utils/linkTrackingIds';
13
+ export type { TrackingIdResult } from '../utils/linkTrackingIds';