@useinsider/guido 3.19.0-beta.8776c42 → 3.19.0-beta.892c3ca

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +1 -0
  2. package/dist/@types/config/schemas.js +33 -31
  3. package/dist/components/Guido.vue.js +8 -8
  4. package/dist/components/Guido.vue2.js +87 -90
  5. package/dist/components/organisms/AutoSaveController.vue2.js +9 -8
  6. package/dist/components/organisms/header/EditorActions.vue.js +2 -2
  7. package/dist/components/organisms/header/EditorActions.vue2.js +90 -55
  8. package/dist/components/organisms/header/LeftSlot.vue.js +5 -5
  9. package/dist/components/organisms/header/LeftSlot.vue2.js +16 -12
  10. package/dist/components/organisms/validation/ValidationErrorDrawer.vue.js +20 -0
  11. package/dist/components/organisms/validation/ValidationErrorDrawer.vue2.js +49 -0
  12. package/dist/components/wrappers/WpDrawer.vue.js +9 -7
  13. package/dist/components/wrappers/WpDrawer.vue2.js +1 -1
  14. package/dist/composables/useCortexBlueprintBridge.js +54 -122
  15. package/dist/composables/useEmailTemplateApplier.js +50 -106
  16. package/dist/composables/useHtmlCompiler.js +37 -26
  17. package/dist/composables/useHtmlValidator.js +2 -0
  18. package/dist/composables/useSave.js +90 -45
  19. package/dist/composables/useSaveValidation.js +282 -0
  20. package/dist/composables/useSaveValidationRollout.js +9 -0
  21. package/dist/composables/validators/useCouponBlockValidator.js +24 -21
  22. package/dist/composables/validators/useUnsubscribeBlockValidator.js +34 -27
  23. package/dist/enums/save-validation.js +4 -0
  24. package/dist/guido.css +1 -1
  25. package/dist/src/@types/config/schemas.d.ts +4 -0
  26. package/dist/src/@types/save-validation.d.ts +19 -0
  27. package/dist/src/components/Guido.vue.d.ts +17 -1
  28. package/dist/src/components/organisms/header/EditorActions.vue.d.ts +17 -1
  29. package/dist/src/components/organisms/header/HeaderWrapper.vue.d.ts +17 -1
  30. package/dist/src/components/organisms/header/RightSlot.vue.d.ts +17 -1
  31. package/dist/src/components/organisms/validation/ValidationErrorDrawer.vue.d.ts +2 -0
  32. package/dist/src/components/wrappers/WpDrawer.vue.d.ts +4 -3
  33. package/dist/src/composables/useConfig.d.ts +2 -0
  34. package/dist/src/composables/useCortexBlueprintBridge.d.ts +3 -2
  35. package/dist/src/composables/useEmailTemplateApplier.d.ts +5 -18
  36. package/dist/src/composables/useHtmlValidator.d.ts +21 -0
  37. package/dist/src/composables/useSave.d.ts +6 -1
  38. package/dist/src/composables/useSaveValidation.d.ts +6 -0
  39. package/dist/src/composables/useSaveValidationRollout.d.ts +3 -0
  40. package/dist/src/composables/validators/useCouponBlockValidator.d.ts +3 -0
  41. package/dist/src/composables/validators/useUnsubscribeBlockValidator.d.ts +10 -0
  42. package/dist/src/enums/save-validation.d.ts +27 -0
  43. package/dist/src/stores/config.d.ts +32 -0
  44. package/dist/src/stores/guido-email-editor.d.ts +10 -20
  45. package/dist/src/stores/save-validation.d.ts +22 -0
  46. package/dist/src/utils/templatePreparation.d.ts +30 -0
  47. package/dist/stores/config.js +84 -67
  48. package/dist/stores/guido-email-editor.js +1 -3
  49. package/dist/stores/save-validation.js +30 -0
  50. package/dist/utils/templatePreparation.js +39 -36
  51. package/package.json +1 -1
package/README.md CHANGED
@@ -164,6 +164,7 @@ const config: GuidoConfigInput = {
164
164
  liquidSyntax?: boolean, // Default: false - Enable Liquid template syntax
165
165
  autosave?: boolean, // Default: false - Show the Auto Save toggle in the header. See wiki/AUTOSAVE.md.
166
166
  allowlistEnabled?: boolean, // Default: false - Pre-save domain-allowlist check (opt-in). Guido self-serves the block toaster (role lookup, deep-link, copy from window.trans).
167
+ allowSaveWithErrors?: boolean, // Default: true - Allow the validation drawer's "Save and Continue" soft-save. Set false to hard-block invalid saves (transactional + unsubscribe pages).
167
168
  reusableRecommendationStrategy?: boolean, // Default: false - Assign an RRS strategy to recommendation blocks instead of per-block algorithm/filters/shuffle/product-count settings.
168
169
  },
169
170
 
@@ -1,5 +1,5 @@
1
1
  import { ModuleFolderDefaults as f } from "../../enums/defaults.js";
2
- import { object as o, number as n, optional as e, string as t, picklist as i, pipe as m, minLength as b, custom as h, boolean as a, array as c, transform as C, record as k, fallback as R, literal as u, looseObject as g, variant as I, union as y, unknown as r, lazy as T } from "../../node_modules/valibot/dist/index.js";
2
+ import { object as o, number as n, optional as e, string as t, picklist as i, pipe as m, minLength as b, custom as y, boolean as a, array as c, transform as C, record as k, fallback as R, literal as u, looseObject as g, variant as I, union as h, unknown as r, lazy as T } from "../../node_modules/valibot/dist/index.js";
3
3
  const p = {
4
4
  /** Promotional/marketing emails */
5
5
  PROMOTIONAL: 1,
@@ -38,7 +38,7 @@ const p = {
38
38
  name: t(),
39
39
  /** Fallback font family (e.g., "serif" or "sans-serif") */
40
40
  family: t()
41
- }), M = o({
41
+ }), E = o({
42
42
  /** Partner/organization name (required) */
43
43
  name: m(
44
44
  t(),
@@ -62,7 +62,7 @@ const p = {
62
62
  username: e(t(), "Guido User"),
63
63
  /** Fallback font settings from partner settings — used to match backend size calculation */
64
64
  fallbackFont: e(L)
65
- }), E = o({
65
+ }), M = o({
66
66
  /** Display text for the dynamic content */
67
67
  text: t(),
68
68
  /** Template variable value (e.g., {{username}}) */
@@ -84,14 +84,14 @@ const p = {
84
84
  children: e(c(S)),
85
85
  // eslint-disable-next-line camelcase -- backend field name
86
86
  select_items: e(c(S))
87
- })), N = k(
87
+ })), v = k(
88
88
  t(),
89
89
  R(c(S), [])
90
- ), P = g({
90
+ ), N = g({
91
91
  /** Block ID (matches the dictionary key and the legacy HTML element id) */
92
92
  id: e(n()),
93
93
  /** Decimal places for price display (legacy data may use string or number) */
94
- decimalCount: e(y([t(), n()])),
94
+ decimalCount: e(h([t(), n()])),
95
95
  /** Pinned product IDs (empty array when filter-driven) */
96
96
  productIds: e(c(r())),
97
97
  /** Whether the block requested live products at send time */
@@ -125,14 +125,14 @@ const p = {
125
125
  /** Block type marker used by some legacy variants */
126
126
  blockType: e(t()),
127
127
  /** Size variant marker (legacy data may use string or number) */
128
- size: e(y([t(), n()])),
128
+ size: e(h([t(), n()])),
129
129
  /** Vertical responsiveness flag (legacy size=1 variants) */
130
130
  verticalResponsiveness: e(a()),
131
131
  /** Legacy "Move to next line" price placement toggle (cardPricePlacement.js) */
132
132
  isPriceMovedToNextLine: e(a()),
133
133
  /** Legacy "Hide if same as discounted" / delete-price-for-zero-sale toggle */
134
134
  isPriceDeletedForZeroSale: e(a())
135
- }), v = o({
135
+ }), P = o({
136
136
  /**
137
137
  * Legacy recommendation block configs keyed by block ID.
138
138
  * Pass this when loading a template authored with the v1
@@ -140,7 +140,7 @@ const p = {
140
140
  * strategy, currency, locale, and layout data.
141
141
  */
142
142
  recommendationConfigs: e(
143
- k(t(), P),
143
+ k(t(), N),
144
144
  {}
145
145
  )
146
146
  }), x = o({
@@ -150,7 +150,7 @@ const p = {
150
150
  css: e(t(), ""),
151
151
  /** Preselected dynamic content items */
152
152
  preselectedDynamicContent: e(
153
- c(E),
153
+ c(M),
154
154
  []
155
155
  ),
156
156
  /**
@@ -159,7 +159,7 @@ const p = {
159
159
  * (first) partner's leaf attributes into the label→token map that repairs
160
160
  * label-form placeholders (`{{ Phone Number }}`) in dropped saved modules.
161
161
  */
162
- dynamicContentList: e(N, {}),
162
+ dynamicContentList: e(v, {}),
163
163
  /** Valid custom field attribute names from the partner's categorized fields */
164
164
  customFieldAttributes: e(c(t()), []),
165
165
  /** Selected unsubscribe page IDs */
@@ -181,7 +181,7 @@ const p = {
181
181
  0
182
182
  ),
183
183
  /** Migration-only inputs (legacy block configs) */
184
- migration: e(v, {})
184
+ migration: e(P, {})
185
185
  }), D = o({
186
186
  /** Sender display name */
187
187
  senderName: e(t(), ""),
@@ -228,8 +228,10 @@ const p = {
228
228
  allowlistEnabled: e(a(), !1),
229
229
  /** Enable persistent link tracking-id assignment for the click heatmap (opt-in) */
230
230
  linkTrackingIds: e(a(), !1),
231
+ /** Allow persisting a template that still has validation errors (drawer "Save and Continue" soft-save). Host sets false for transactional + unsubscribe. */
232
+ allowSaveWithErrors: e(a(), !0),
231
233
  reusableRecommendationStrategy: e(a(), !1)
232
- }), B = i([
234
+ }), w = i([
233
235
  "amp-accordion",
234
236
  "amp-carousel",
235
237
  "amp-form-controls",
@@ -243,7 +245,7 @@ const p = {
243
245
  "text-block",
244
246
  "timer-block",
245
247
  "video-block"
246
- ]), w = i([
248
+ ]), B = i([
247
249
  "dynamic-content",
248
250
  "checkbox-block",
249
251
  "radio-button-block",
@@ -254,12 +256,12 @@ const p = {
254
256
  ]), H = o({
255
257
  /** Default blocks to exclude from the editor */
256
258
  excludeDefaults: e(
257
- c(B),
259
+ c(w),
258
260
  []
259
261
  ),
260
262
  /** Custom blocks to include in the editor */
261
263
  includeCustoms: e(
262
- c(w),
264
+ c(B),
263
265
  []
264
266
  )
265
267
  }), d = o({
@@ -296,7 +298,7 @@ const p = {
296
298
  ...d.entries,
297
299
  type: u("custom"),
298
300
  /** Custom processor function */
299
- processor: h(
301
+ processor: y(
300
302
  (s) => typeof s == "function",
301
303
  "processor must be a function"
302
304
  )
@@ -310,23 +312,23 @@ const p = {
310
312
  customRules: e(c(V), []),
311
313
  /** Skip default compiler rules */
312
314
  ignoreDefaultRules: e(a(), !1)
313
- }), Z = o({
315
+ }), W = o({
314
316
  /**
315
317
  * External validation handler called before save completes.
316
318
  * Return false to cancel the save operation.
317
319
  */
318
320
  externalValidation: e(
319
- h(
321
+ y(
320
322
  (s) => typeof s == "function",
321
323
  "externalValidation must be a function"
322
324
  )
323
325
  )
324
- }), Q = o({
326
+ }), K = o({
325
327
  // Required sections
326
328
  /** Identity configuration (required) */
327
329
  identity: A,
328
330
  /** Partner configuration (required) */
329
- partner: M,
331
+ partner: E,
330
332
  // Optional sections (with defaults)
331
333
  /** Template content and presets */
332
334
  template: e(x, {}),
@@ -341,33 +343,33 @@ const p = {
341
343
  /** Compiler configuration */
342
344
  compiler: e(z, {}),
343
345
  /** Callbacks and event handlers */
344
- callbacks: e(Z, {})
346
+ callbacks: e(W, {})
345
347
  });
346
348
  export {
347
349
  H as BlocksSchema,
348
- Z as CallbacksSchema,
350
+ W as CallbacksSchema,
349
351
  V as CompilerRuleSchema,
350
352
  z as CompilerSchema,
351
- w as CustomBlockTypeSchema,
353
+ B as CustomBlockTypeSchema,
352
354
  G as CustomRuleSchema,
353
- B as DefaultBlockTypeSchema,
354
- N as DynamicContentListSchema,
355
+ w as DefaultBlockTypeSchema,
356
+ v as DynamicContentListSchema,
355
357
  S as DynamicContentNodeSchema,
356
- E as DynamicContentSchema,
358
+ M as DynamicContentSchema,
357
359
  O as EditorSchema,
358
360
  D as EmailHeaderSchema,
359
361
  L as FallbackFontSchema,
360
362
  U as FeaturesSchema,
361
- Q as GuidoConfigSchema,
363
+ K as GuidoConfigSchema,
362
364
  A as IdentitySchema,
363
- P as LegacyRecommendationConfigSchema,
365
+ N as LegacyRecommendationConfigSchema,
364
366
  p as MessageType,
365
- M as PartnerSchema,
367
+ E as PartnerSchema,
366
368
  l as ProductType,
367
369
  j as RegexRuleSchema,
368
370
  q as RemoveRuleSchema,
369
371
  _ as ReplaceRuleSchema,
370
- v as TemplateMigrationSchema,
372
+ P as TemplateMigrationSchema,
371
373
  x as TemplateSchema,
372
374
  F as UISchema
373
375
  };
@@ -1,20 +1,20 @@
1
- import o from "./Guido.vue2.js";
1
+ import i from "./Guido.vue2.js";
2
2
  /* empty css */
3
- import i from "../_virtual/_plugin-vue2_normalizer.js";
3
+ import o from "../_virtual/_plugin-vue2_normalizer.js";
4
4
  var t = function() {
5
5
  var a = this, r = a._self._c, e = a._self._setupProxy;
6
- return r("div", { ref: "wrapperRef", staticClass: "guido-editor__wrapper", class: { "guido-editor__no-header": e.noHeader } }, [r(e.HeaderWrapper, { ref: "headerWrapperRef" }), r(e.AutoSaveController), e.editorStore.isPreviewModeOpen ? r(e.PreviewContainer) : a._e(), r("div", { directives: [{ name: "show", rawName: "v-show", value: !e.previewStore.isLoaded, expression: "!previewStore.isLoaded" }], staticClass: "guido-editor__container", class: { "guido-editor__no-header": e.noHeader }, attrs: { id: "guido-editor" } }), r(e.Toaster), r(e.FilterSelectionDrawer), e.isRrsEnabled || e.hasAssignedStrategy ? r(e.AssignStrategyDrawer) : a._e(), e.isRrsEnabled || e.hasAssignedStrategy ? r(e.RemoveStrategyModal) : a._e(), e.isRrsEnabled ? r(e.LegacyStrategyUpdatedModal) : a._e(), r(e.SaveAsTemplateDrawer), e.isTestPartner() ? a._e() : r(e.OnboardingWrapper, { on: { "onboarding-finished": function(_) {
6
+ return r("div", { ref: "wrapperRef", staticClass: "guido-editor__wrapper", class: { "guido-editor__no-header": e.noHeader } }, [r(e.HeaderWrapper, { ref: "headerWrapperRef" }), r(e.AutoSaveController), e.editorStore.isPreviewModeOpen ? r(e.PreviewContainer) : a._e(), r("div", { directives: [{ name: "show", rawName: "v-show", value: !e.previewStore.isLoaded, expression: "!previewStore.isLoaded" }], staticClass: "guido-editor__container", class: { "guido-editor__no-header": e.noHeader }, attrs: { id: "guido-editor" } }), r(e.Toaster), r(e.FilterSelectionDrawer), e.isRrsEnabled || e.hasAssignedStrategy ? r(e.AssignStrategyDrawer) : a._e(), e.isRrsEnabled || e.hasAssignedStrategy ? r(e.RemoveStrategyModal) : a._e(), e.isRrsEnabled ? r(e.LegacyStrategyUpdatedModal) : a._e(), r(e.SaveAsTemplateDrawer), e.isSaveValidationEnabled ? r(e.ValidationErrorDrawer) : a._e(), e.isTestPartner() ? a._e() : r(e.OnboardingWrapper, { on: { "onboarding-finished": function(_) {
7
7
  return e.emit("onboarding:finished");
8
8
  } } }), r(e.UnsubscribeWrapper), r(e.LoadingWrapper)], 1);
9
- }, s = [], n = /* @__PURE__ */ i(
10
- o,
9
+ }, s = [], n = /* @__PURE__ */ o(
10
+ i,
11
11
  t,
12
12
  s,
13
13
  !1,
14
14
  null,
15
- "59690055"
15
+ "aaa8fe47"
16
16
  );
17
- const g = n.exports;
17
+ const v = n.exports;
18
18
  export {
19
- g as default
19
+ v as default
20
20
  };
@@ -1,41 +1,44 @@
1
- import { defineComponent as re, defineAsyncComponent as m, ref as x, computed as p, watch as W, onMounted as se, onUnmounted as ae } from "vue";
2
- import { useCortexBlueprintBridge as ie } from "../composables/useCortexBlueprintBridge.js";
3
- import { useEditorLock as ce } from "../composables/useEditorLock.js";
4
- import { provideGuidoActions as de } from "../composables/useGuidoActions.js";
5
- import { useGuidoStateBridge as me } from "../composables/useGuidoStateBridge.js";
6
- import { usePartner as le } from "../composables/usePartner.js";
7
- import { useStripo as ue } from "../composables/useStripo.js";
8
- import { useTimerClone as pe } from "../composables/useTimerClone.js";
9
- import { migrate as G } from "../config/migrator/index.js";
10
- import { ModuleFolderDefaults as z } from "../enums/defaults.js";
11
- import { RIBBON_SELECTOR as fe } from "../enums/onboarding.js";
12
- import { useRecommendationExtensionStore as E } from "../extensions/Blocks/Recommendation/store/recommendation.js";
13
- import ye from "./organisms/AutoSaveController.vue.js";
14
- import ge from "./organisms/base/Toaster.vue.js";
15
- import ve from "./organisms/extensions/recommendation/FilterSelectionDrawer.vue.js";
16
- import Se from "./organisms/header/HeaderWrapper.vue.js";
17
- import he from "./organisms/LoadingWrapper.vue.js";
18
- import be from "./organisms/save-as-template/SaveAsTemplateDrawer.vue.js";
19
- import Ee from "./organisms/unsubscribe/UnsubscribeWrapper.vue.js";
20
- import { useStripoApi as we } from "../services/stripoApi.js";
21
- import { useConfigStore as Ce } from "../stores/config.js";
22
- import { useDynamicContentStore as De } from "../stores/dynamic-content.js";
23
- import { useEditorStore as w } from "../stores/editor.js";
24
- import { usePreviewStore as ke } from "../stores/preview.js";
25
- import { useTemplateStore as Fe } from "../stores/template.js";
26
- import { useUnsubscribeStore as Te } from "../stores/unsubscribe.js";
27
- import { readTrackFloor as H } from "../utils/linkTrackingIds.js";
28
- const tt = /* @__PURE__ */ re({
1
+ import { defineComponent as ae, defineAsyncComponent as m, ref as O, computed as u, watch as x, onMounted as se, onUnmounted as ie } from "vue";
2
+ import { useCortexBlueprintBridge as ce } from "../composables/useCortexBlueprintBridge.js";
3
+ import { useEditorLock as de } from "../composables/useEditorLock.js";
4
+ import { provideGuidoActions as me } from "../composables/useGuidoActions.js";
5
+ import { useGuidoStateBridge as le } from "../composables/useGuidoStateBridge.js";
6
+ import { usePartner as ue } from "../composables/usePartner.js";
7
+ import { useSaveValidationRollout as pe } from "../composables/useSaveValidationRollout.js";
8
+ import { useStripo as fe } from "../composables/useStripo.js";
9
+ import { useTimerClone as ye } from "../composables/useTimerClone.js";
10
+ import { migrate as W } from "../config/migrator/index.js";
11
+ import { ModuleFolderDefaults as G } from "../enums/defaults.js";
12
+ import { RIBBON_SELECTOR as ge } from "../enums/onboarding.js";
13
+ import { useRecommendationExtensionStore as h } from "../extensions/Blocks/Recommendation/store/recommendation.js";
14
+ import ve from "./organisms/AutoSaveController.vue.js";
15
+ import Se from "./organisms/base/Toaster.vue.js";
16
+ import be from "./organisms/extensions/recommendation/FilterSelectionDrawer.vue.js";
17
+ import he from "./organisms/header/HeaderWrapper.vue.js";
18
+ import Ee from "./organisms/LoadingWrapper.vue.js";
19
+ import we from "./organisms/save-as-template/SaveAsTemplateDrawer.vue.js";
20
+ import Ce from "./organisms/unsubscribe/UnsubscribeWrapper.vue.js";
21
+ import De from "./organisms/validation/ValidationErrorDrawer.vue.js";
22
+ import { useStripoApi as ke } from "../services/stripoApi.js";
23
+ import { useConfigStore as Re } from "../stores/config.js";
24
+ import { useDynamicContentStore as Te } from "../stores/dynamic-content.js";
25
+ import { useEditorStore as V } from "../stores/editor.js";
26
+ import { usePreviewStore as Fe } from "../stores/preview.js";
27
+ import { useSaveValidationStore as Me } from "../stores/save-validation.js";
28
+ import { useTemplateStore as Ie } from "../stores/template.js";
29
+ import { useUnsubscribeStore as Le } from "../stores/unsubscribe.js";
30
+ import { readTrackFloor as $ } from "../utils/linkTrackingIds.js";
31
+ const ct = /* @__PURE__ */ ae({
29
32
  __name: "Guido",
30
33
  props: {
31
34
  config: null,
32
35
  ready: { type: Boolean, default: !0 }
33
36
  },
34
37
  emits: ["dynamic-content:open", "back", "save:start", "save:complete", "on-change", "ready", "onboarding:finished", "test-email:click"],
35
- setup($, { expose: q, emit: r }) {
36
- const a = $, K = m(
38
+ setup(H, { expose: z, emit: r }) {
39
+ const s = H, q = m(
37
40
  () => import("./organisms/email-preview/PreviewContainer.vue.js")
38
- ), V = m(
41
+ ), K = m(
39
42
  () => import("./organisms/onboarding/OnboardingWrapper.vue.js")
40
43
  ), j = m(
41
44
  () => import("./organisms/extensions/recommendation/AssignStrategyDrawer.vue.js")
@@ -43,34 +46,34 @@ const tt = /* @__PURE__ */ re({
43
46
  () => import("./organisms/extensions/recommendation/RemoveStrategyModal.vue.js")
44
47
  ), Q = m(
45
48
  () => import("./organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue.js")
46
- ), C = x(), f = x(), y = De(), D = Te(), o = Ce();
47
- a.ready && o.init(a.config);
48
- const c = w(), X = ke(), l = p(() => c.hasChanges), { isTestPartner: Y } = le(), k = () => {
49
+ ), E = O(), p = O(), f = Te(), w = Le(), o = Re();
50
+ s.ready && o.init(s.config);
51
+ const c = V(), X = Fe(), l = u(() => c.hasChanges), { isTestPartner: Y } = ue(), { isEnabled: Z } = pe(), C = () => {
49
52
  var t;
50
- return (t = C.value) == null ? void 0 : t.handleSave(!0);
51
- }, F = (t) => {
53
+ return (t = E.value) == null ? void 0 : t.handleSave(!0);
54
+ }, D = (t) => {
52
55
  c.loadingStatus = t;
53
56
  };
54
- ie(), me();
55
- const g = () => {
57
+ ce(), le();
58
+ const y = () => {
56
59
  var t, e;
57
60
  return {
58
61
  emailId: o.templateId,
59
62
  userId: o.userId,
60
63
  username: o.username,
61
64
  partnerName: o.partnerName,
62
- savedModulesFolderName: ((t = o.editor) == null ? void 0 : t.savedModulesFolderName) || z.SAVED_MODULES,
63
- defaultModulesFolderName: ((e = o.editor) == null ? void 0 : e.defaultModulesFolderName) || z.DEFAULT_MODULES
65
+ savedModulesFolderName: ((t = o.editor) == null ? void 0 : t.savedModulesFolderName) || G.SAVED_MODULES,
66
+ defaultModulesFolderName: ((e = o.editor) == null ? void 0 : e.defaultModulesFolderName) || G.DEFAULT_MODULES
64
67
  };
65
- }, { initPlugin: T, preloadRuntime: I } = ue(), { runExclusive: M, beginMount: R, isCurrentMount: v } = ce();
66
- let u = 0;
67
- const { getDefaultTemplate: L } = we(), { cloneTimersOnSave: B, hasTimerBlocks: U } = pe(), Z = p(() => {
68
+ }, { initPlugin: k, preloadRuntime: R } = fe(), { runExclusive: T, beginMount: F, isCurrentMount: M } = de();
69
+ let g = 0;
70
+ const { getDefaultTemplate: I } = ke(), { cloneTimersOnSave: L, hasTimerBlocks: B } = ye(), ee = u(() => {
68
71
  var t;
69
72
  return !((t = o.ui) != null && t.showHeader);
70
- }), ee = p(() => o.isFeatureEnabled("reusableRecommendationStrategy")), te = p(
71
- () => !!E().recommendationConfigs.strategyId
73
+ }), te = u(() => o.isFeatureEnabled("reusableRecommendationStrategy")), oe = u(
74
+ () => !!h().recommendationConfigs.strategyId
72
75
  );
73
- de({
76
+ me({
74
77
  onBack: () => {
75
78
  console.debug("guido:back"), r("back");
76
79
  },
@@ -78,93 +81,87 @@ const tt = /* @__PURE__ */ re({
78
81
  console.debug("guido:save:start"), r("save:start");
79
82
  },
80
83
  onSaveComplete: (t) => {
81
- const e = { ...t, metadata: g() };
84
+ const e = { ...t, metadata: y() };
82
85
  console.debug("guido:save:complete", e), r("save:complete", e);
83
86
  },
84
87
  onTestEmailClick: () => {
85
88
  console.debug("guido:test-email:click"), r("test-email:click");
86
89
  }
87
90
  });
88
- const A = (t) => {
89
- console.debug("dynamic-content:close", t), y.setSelectedDynamicContent(t), document.dispatchEvent(new CustomEvent("dynamic-content:close", { detail: t }));
90
- }, P = () => {
91
+ const U = (t) => {
92
+ console.debug("dynamic-content:close", t), f.setSelectedDynamicContent(t), document.dispatchEvent(new CustomEvent("dynamic-content:close", { detail: t }));
93
+ }, A = () => {
91
94
  console.debug("dynamic-content:close", "Without Data"), document.dispatchEvent(new CustomEvent("dynamic-content:close", { detail: { text: "", value: "" } }));
92
95
  };
93
- W(() => l.value, () => {
96
+ x(() => l.value, () => {
94
97
  r("on-change", l.value);
95
98
  });
96
- const S = (t) => {
97
- const e = t, { attribute: s, position: d } = e.detail;
98
- console.debug("dynamic-content:open", e.detail), r("dynamic-content:open", s, d);
99
+ const v = (t) => {
100
+ const e = t, { attribute: a, position: d } = e.detail;
101
+ console.debug("dynamic-content:open", e.detail), r("dynamic-content:open", a, d);
99
102
  };
100
103
  let i = null;
101
- const h = () => {
104
+ const S = () => {
102
105
  var e;
103
- const t = document.querySelector(fe);
104
- (e = f.value) == null || e.style.setProperty("--ribbon-offset", `${(t == null ? void 0 : t.offsetHeight) ?? 0}px`);
106
+ const t = document.querySelector(ge);
107
+ (e = p.value) == null || e.style.setProperty("--ribbon-offset", `${(t == null ? void 0 : t.offsetHeight) ?? 0}px`);
105
108
  }, b = async () => {
106
109
  var t;
107
110
  try {
108
- o.initialized || o.init(a.config), c.templateId = o.templateId;
109
- const e = o.template, s = (e == null ? void 0 : e.html) || "", d = (e == null ? void 0 : e.css) || "", _ = (e == null ? void 0 : e.preselectedDynamicContent) || [];
110
- D.selectedUnsubscribePages = (e == null ? void 0 : e.selectedUnsubscribePages) || [];
111
- const N = ((t = e == null ? void 0 : e.migration) == null ? void 0 : t.recommendationConfigs) ?? {}, O = o.isFeatureEnabled("linkTrackingIds");
111
+ o.initialized || o.init(s.config), c.templateId = o.templateId;
112
+ const e = o.template, a = (e == null ? void 0 : e.html) || "", d = (e == null ? void 0 : e.css) || "", P = (e == null ? void 0 : e.preselectedDynamicContent) || [];
113
+ w.selectedUnsubscribePages = (e == null ? void 0 : e.selectedUnsubscribePages) || [];
114
+ const _ = ((t = e == null ? void 0 : e.migration) == null ? void 0 : t.recommendationConfigs) ?? {}, N = o.isFeatureEnabled("linkTrackingIds");
112
115
  let n = {
113
- html: s && await G(s, N),
116
+ html: a && await W(a, _),
114
117
  css: d
115
118
  };
116
- n.html || (n = await L(), n.html = await G(n.html, N));
117
- const oe = O ? H(n.html, (e == null ? void 0 : e.trackIdCounter) || 0) : 0;
118
- U(n.html) && (n.html = await B(n.html)), O && (c.trackIdSessionFloor = Math.max(oe, H(n.html)));
119
- const ne = {
120
- preselectedDynamicContentList: _,
119
+ n.html || (n = await I(), n.html = await W(n.html, _));
120
+ const ne = N ? $(n.html, (e == null ? void 0 : e.trackIdCounter) || 0) : 0;
121
+ B(n.html) && (n.html = await L(n.html)), N && (c.trackIdSessionFloor = Math.max(ne, $(n.html)));
122
+ const re = {
123
+ preselectedDynamicContentList: P,
121
124
  onReady: () => {
122
125
  console.debug("guido:ready"), r("ready");
123
126
  }
124
127
  };
125
- u = R(), await T(n, g(), ne), y.selectedDynamicContentList = _;
128
+ g = F(), await k(n, y(), re), f.selectedDynamicContentList = P;
126
129
  } catch (e) {
127
130
  console.error("Failed to initialize Stripo editor:", e);
128
131
  }
129
132
  };
130
133
  return se(async () => {
131
134
  var e;
132
- console.debug("Guido says happy coding 🎉"), console.debug("🚗 Ka-Chow"), E().$reset(), w().$reset(), Fe().$reset(), h();
133
- const t = (e = f.value) == null ? void 0 : e.parentElement;
134
- if (t && (i = new ResizeObserver(h), i.observe(t)), I(), a.ready)
135
+ console.debug("Guido says happy coding 🎉"), console.debug("🚗 Ka-Chow"), h().$reset(), V().$reset(), Ie().$reset(), Me().$reset(), S();
136
+ const t = (e = p.value) == null ? void 0 : e.parentElement;
137
+ if (t && (i = new ResizeObserver(S), i.observe(t)), R(), s.ready)
135
138
  await b();
136
139
  else {
137
- const s = W(() => a.ready, (d) => {
138
- d && (s(), b());
140
+ const a = x(() => s.ready, (d) => {
141
+ d && (a(), b());
139
142
  });
140
143
  }
141
- document.addEventListener("dynamic-content:open", S);
142
- }), ae(() => {
143
- if (i == null || i.disconnect(), document.removeEventListener("dynamic-content:open", S), E().disposeStrategyPageReturn(), v(u))
144
- try {
145
- w().isStripoInitialized = !1;
146
- } catch (t) {
147
- console.debug("Failed to close the editor readiness gate on unmount", t);
148
- }
149
- M(async () => {
150
- if (v(u))
144
+ document.addEventListener("dynamic-content:open", v);
145
+ }), ie(() => {
146
+ i == null || i.disconnect(), document.removeEventListener("dynamic-content:open", v), h().disposeStrategyPageReturn(), T(async () => {
147
+ if (M(g))
151
148
  try {
152
149
  window.UIEditor.removeEditor();
153
150
  } catch {
154
151
  console.debug("Failed to remove Stripo editor: No editor found");
155
152
  }
156
153
  }), o.reset();
157
- }), q({
154
+ }), z({
158
155
  dynamicContent: {
159
- insert: A,
160
- close: P
156
+ insert: U,
157
+ close: A
161
158
  },
162
159
  hasChanges: l,
163
- saveSilent: k,
164
- setLoading: F
165
- }), { __sfc: !0, PreviewContainer: K, OnboardingWrapper: V, AssignStrategyDrawer: j, RemoveStrategyModal: J, LegacyStrategyUpdatedModal: Q, headerWrapperRef: C, wrapperRef: f, dynamicContentStore: y, unsubscribeStore: D, props: a, configStore: o, editorStore: c, previewStore: X, hasChanges: l, isTestPartner: Y, saveSilent: k, setLoading: F, emit: r, buildMetadata: g, initPlugin: T, preloadRuntime: I, runExclusive: M, beginMount: R, isCurrentMount: v, mountGeneration: u, getDefaultTemplate: L, cloneTimersOnSave: B, hasTimerBlocks: U, noHeader: Z, isRrsEnabled: ee, hasAssignedStrategy: te, insertDynamicContent: A, closeDynamicContent: P, handleDynamicContentOpen: S, ribbonObserver: i, updateRibbonOffset: h, startEditor: b, AutoSaveController: ye, Toaster: ge, FilterSelectionDrawer: ve, HeaderWrapper: Se, LoadingWrapper: he, SaveAsTemplateDrawer: be, UnsubscribeWrapper: Ee };
160
+ saveSilent: C,
161
+ setLoading: D
162
+ }), { __sfc: !0, PreviewContainer: q, OnboardingWrapper: K, AssignStrategyDrawer: j, RemoveStrategyModal: J, LegacyStrategyUpdatedModal: Q, headerWrapperRef: E, wrapperRef: p, dynamicContentStore: f, unsubscribeStore: w, props: s, configStore: o, editorStore: c, previewStore: X, hasChanges: l, isTestPartner: Y, isSaveValidationEnabled: Z, saveSilent: C, setLoading: D, emit: r, buildMetadata: y, initPlugin: k, preloadRuntime: R, runExclusive: T, beginMount: F, isCurrentMount: M, mountGeneration: g, getDefaultTemplate: I, cloneTimersOnSave: L, hasTimerBlocks: B, noHeader: ee, isRrsEnabled: te, hasAssignedStrategy: oe, insertDynamicContent: U, closeDynamicContent: A, handleDynamicContentOpen: v, ribbonObserver: i, updateRibbonOffset: S, startEditor: b, AutoSaveController: ve, Toaster: Se, FilterSelectionDrawer: be, HeaderWrapper: he, LoadingWrapper: Ee, SaveAsTemplateDrawer: we, UnsubscribeWrapper: Ce, ValidationErrorDrawer: De };
166
163
  }
167
164
  });
168
165
  export {
169
- tt as default
166
+ ct as default
170
167
  };
@@ -1,13 +1,14 @@
1
- import { defineComponent as t } from "vue";
2
- import { useAutoSave as r } from "../../composables/useAutoSave.js";
3
- import { useSave as s } from "../../composables/useSave.js";
4
- const f = /* @__PURE__ */ t({
1
+ import { defineComponent as r } from "vue";
2
+ import { useAutoSave as s } from "../../composables/useAutoSave.js";
3
+ import { useSave as n } from "../../composables/useSave.js";
4
+ import { useSaveValidationRollout as u } from "../../composables/useSaveValidationRollout.js";
5
+ const v = /* @__PURE__ */ r({
5
6
  __name: "AutoSaveController",
6
- setup(a) {
7
- const { save: e } = s(), o = () => e(!1, !0);
8
- return r(o), { __sfc: !0, save: e, backgroundSave: o };
7
+ setup(m) {
8
+ const { save: e, saveRawOnly: o } = n(), { isEnabled: t } = u(), a = () => t.value ? o() : e(!1, !0);
9
+ return s(a), { __sfc: !0, save: e, saveRawOnly: o, isEnabled: t, backgroundSave: a };
9
10
  }
10
11
  });
11
12
  export {
12
- f as default
13
+ v as default
13
14
  };
@@ -4,7 +4,7 @@ import d from "../../../_virtual/_plugin-vue2_normalizer.js";
4
4
  var u = function() {
5
5
  var s, i, n, a;
6
6
  var o = this, e = o._self._c, t = o._self._setupProxy;
7
- return e("div", { staticClass: "d-f editor-actions" }, [t.isVersionHistoryButtonVisible ? e(t.InButtonV2, { attrs: { id: "guido__history-button", "left-icon": "line-architect-version-history", styling: "ghost", type: "secondary", "disabled-status": t.editorStore.isVersionHistoryButtonDisabled, "label-text-status": !1, "selected-status": t.editorStore.isVersionHistoryOpen, "tooltip-options": t.getTooltipOptions("guido__history-button"), "tooltip-text": t.versionHistoryTooltipText }, on: { click: t.handleVersionHistory } }) : o._e(), e(t.InButtonV2, { attrs: { id: "guido__export-button", "left-icon": "line-export", styling: "ghost", type: "secondary", "disabled-status": t.editorStore.isExportButtonDisabled, "label-text-status": !1, "loading-status": t.isExporting, "tooltip-options": t.getTooltipOptions("guido__export-button"), "tooltip-text": t.trans("newsletter.export") }, on: { click: t.handleExport } }), (i = (s = t.config) == null ? void 0 : s.features) != null && i.saveAsTemplate ? e(t.InButtonV2, { attrs: { id: "guido__save-as-button", "left-icon": "line-newsletter-save-as-template", styling: "ghost", type: "secondary", "disabled-status": t.editorStore.isSaveAsButtonDisabled, "label-text-status": !1, "tooltip-options": t.getTooltipOptions("guido__save-as-button"), "tooltip-text": t.trans("newsletter.save-templates") }, on: { click: t.handleSaveAs } }) : o._e(), (a = (n = t.config) == null ? void 0 : n.features) != null && a.testMessage ? e(t.InButtonV2, { attrs: { id: "guido__test-button", "left-icon": "line-architect-test-journey", styling: "ghost", type: "secondary", "disabled-status": t.editorStore.isTestButtonDisabled, "label-text-status": !1, "tooltip-options": t.getTooltipOptions("guido__test-button", { staticPosition: "bottom right" }), "tooltip-text": t.trans("newsletter.test-email") }, on: { click: t.handleTestEmail } }) : o._e(), t.editorStore.isPreviewModeOpen ? o._e() : e(t.InButtonV2, { staticClass: "ml-3", attrs: { id: "guido__save-button", "label-text": "Save", "disabled-status": !t.isSaving && t.editorStore.isSaveButtonDisabled, "loading-status": t.isSaving }, on: { click: function(r) {
7
+ return e("div", { staticClass: "d-f editor-actions" }, [t.isVersionHistoryButtonVisible ? e(t.InButtonV2, { attrs: { id: "guido__history-button", "left-icon": "line-architect-version-history", styling: "ghost", type: "secondary", "disabled-status": t.editorStore.isVersionHistoryButtonDisabled, "label-text-status": !1, "selected-status": t.editorStore.isVersionHistoryOpen, "tooltip-options": t.getTooltipOptions("guido__history-button"), "tooltip-text": t.versionHistoryTooltipText }, on: { click: t.handleVersionHistory } }) : o._e(), e(t.InButtonV2, { attrs: { id: "guido__export-button", "left-icon": "line-export", styling: "ghost", type: "secondary", "disabled-status": t.editorStore.isExportButtonDisabled, "label-text-status": !1, "loading-status": t.isExporting, "tooltip-options": t.getTooltipOptions("guido__export-button"), "tooltip-text": t.trans("newsletter.export") }, on: { click: t.handleExport } }), (i = (s = t.config) == null ? void 0 : s.features) != null && i.saveAsTemplate ? e(t.InButtonV2, { attrs: { id: "guido__save-as-button", "left-icon": "line-newsletter-save-as-template", styling: "ghost", type: "secondary", "disabled-status": t.editorStore.isSaveAsButtonDisabled, "label-text-status": !1, "tooltip-options": t.getTooltipOptions("guido__save-as-button"), "tooltip-text": t.trans("newsletter.save-templates") }, on: { click: t.handleSaveAs } }) : o._e(), (a = (n = t.config) == null ? void 0 : n.features) != null && a.testMessage ? e(t.InButtonV2, { attrs: { id: "guido__test-button", "left-icon": "line-architect-test-journey", styling: "ghost", type: "secondary", "disabled-status": t.editorStore.isTestButtonDisabled, "label-text-status": !1, "tooltip-options": t.getTooltipOptions("guido__test-button", { staticPosition: "bottom right" }), "tooltip-text": t.trans("newsletter.test-email") }, on: { click: t.handleTestEmail } }) : o._e(), t.editorStore.isPreviewModeOpen ? o._e() : e(t.InButtonV2, { staticClass: "ml-3", attrs: { id: "guido__save-button", "disabled-status": !t.isSaving && t.editorStore.isSaveButtonDisabled, "label-text": t.saveLabel, "loading-status": t.isSaving }, on: { click: function(r) {
8
8
  return t.handleSave(!1);
9
9
  } } }), e(t.MigrationConfirmModal, { ref: "migrationModalRef", on: { confirm: function(r) {
10
10
  return t.executeSave(!1);
@@ -15,7 +15,7 @@ var u = function() {
15
15
  c,
16
16
  !1,
17
17
  null,
18
- "c61cc8ea"
18
+ "2cccbd44"
19
19
  );
20
20
  const v = p.exports;
21
21
  export {