@useinsider/guido 3.19.0-beta.fcad6e5 → 3.20.0-beta.05ce01c

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 (53) hide show
  1. package/README.md +1 -0
  2. package/dist/@types/config/schemas.js +39 -37
  3. package/dist/components/Guido.vue.js +8 -8
  4. package/dist/components/Guido.vue2.js +70 -67
  5. package/dist/components/organisms/AutoSaveController.vue2.js +10 -8
  6. package/dist/components/organisms/header/EditorActions.vue.js +5 -5
  7. package/dist/components/organisms/header/EditorActions.vue2.js +83 -46
  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 +50 -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/useAutoSave.js +46 -44
  15. package/dist/composables/useHtmlCompiler.js +37 -26
  16. package/dist/composables/useHtmlValidator.js +2 -0
  17. package/dist/composables/useSave.js +93 -45
  18. package/dist/composables/useSaveValidation.js +284 -0
  19. package/dist/composables/useSaveValidationRollout.js +20 -0
  20. package/dist/composables/validators/useCouponBlockValidator.js +24 -21
  21. package/dist/composables/validators/useUnsubscribeBlockValidator.js +34 -27
  22. package/dist/enums/save-validation.js +4 -0
  23. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +203 -246
  24. package/dist/guido.css +1 -1
  25. package/dist/services/settingsApi.js +11 -0
  26. package/dist/src/@types/config/schemas.d.ts +4 -0
  27. package/dist/src/@types/save-validation.d.ts +19 -0
  28. package/dist/src/components/Guido.vue.d.ts +17 -1
  29. package/dist/src/components/organisms/header/EditorActions.vue.d.ts +17 -1
  30. package/dist/src/components/organisms/header/HeaderWrapper.vue.d.ts +17 -1
  31. package/dist/src/components/organisms/header/RightSlot.vue.d.ts +17 -1
  32. package/dist/src/components/organisms/validation/ValidationErrorDrawer.vue.d.ts +2 -0
  33. package/dist/src/components/wrappers/WpDrawer.vue.d.ts +4 -3
  34. package/dist/src/composables/useAutoSave.d.ts +4 -1
  35. package/dist/src/composables/useConfig.d.ts +2 -0
  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 +4 -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/extensions/Blocks/Recommendation/controls/main/index.d.ts +0 -8
  44. package/dist/src/services/settingsApi.d.ts +6 -0
  45. package/dist/src/stores/config.d.ts +32 -0
  46. package/dist/src/stores/save-validation.d.ts +22 -0
  47. package/dist/src/stores/setup-settings.d.ts +4 -0
  48. package/dist/src/utils/templatePreparation.d.ts +30 -0
  49. package/dist/stores/config.js +84 -67
  50. package/dist/stores/save-validation.js +30 -0
  51. package/dist/stores/setup-settings.js +10 -0
  52. package/dist/utils/templatePreparation.js +39 -36
  53. 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,4 +1,4 @@
1
- import { ModuleFolderDefaults as S } from "../../enums/defaults.js";
1
+ import { ModuleFolderDefaults as f } from "../../enums/defaults.js";
2
2
  import { object as a, number as s, optional as e, string as t, picklist as m, pipe as i, minLength as b, custom as k, boolean as o, array as c, transform as y, unknown as r, record as g, fallback as R, literal as u, looseObject as C, variant as I, union as h, lazy as T } from "../../node_modules/valibot/dist/index.js";
3
3
  const p = {
4
4
  /** Promotional/marketing emails */
@@ -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 = a({
41
+ }), E = a({
42
42
  /** Partner/organization name (required) */
43
43
  name: i(
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 = a({
65
+ }), M = a({
66
66
  /** Display text for the dynamic content */
67
67
  text: t(),
68
68
  /** Template variable value (e.g., {{username}}) */
@@ -76,17 +76,17 @@ const p = {
76
76
  value: t()
77
77
  })
78
78
  )
79
- }), f = T(() => C({
79
+ }), S = T(() => C({
80
80
  text: e(t()),
81
81
  // eslint-disable-next-line camelcase -- backend field name
82
82
  tag_text: e(t()),
83
83
  value: e(t()),
84
- children: e(c(f)),
84
+ children: e(c(S)),
85
85
  // eslint-disable-next-line camelcase -- backend field name
86
- select_items: e(c(f))
86
+ select_items: e(c(S))
87
87
  })), N = g(
88
88
  t(),
89
- R(c(f), [])
89
+ R(c(S), [])
90
90
  ), P = C({
91
91
  /** Block ID (matches the dictionary key and the legacy HTML element id) */
92
92
  id: e(s()),
@@ -132,7 +132,7 @@ const p = {
132
132
  isPriceMovedToNextLine: e(o()),
133
133
  /** Legacy "Hide if same as discounted" / delete-price-for-zero-sale toggle */
134
134
  isPriceDeletedForZeroSale: e(o())
135
- }), x = a({
135
+ }), v = a({
136
136
  /**
137
137
  * Legacy recommendation block configs keyed by block ID.
138
138
  * Pass this when loading a template authored with the v1
@@ -143,14 +143,14 @@ const p = {
143
143
  g(t(), P),
144
144
  {}
145
145
  )
146
- }), D = a({
146
+ }), x = a({
147
147
  /** Initial HTML content */
148
148
  html: e(t(), ""),
149
149
  /** Initial CSS content */
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
  /**
@@ -194,13 +194,13 @@ const p = {
194
194
  )
195
195
  ),
196
196
  /** Migration-only inputs (legacy block configs) */
197
- migration: e(x, {})
198
- }), O = a({
197
+ migration: e(v, {})
198
+ }), D = a({
199
199
  /** Sender display name */
200
200
  senderName: e(t(), ""),
201
201
  /** Email subject line */
202
202
  subject: e(t(), "")
203
- }), v = a({
203
+ }), O = a({
204
204
  /** Locale for the editor UI */
205
205
  locale: e(t(), "en"),
206
206
  /** Path to translations object */
@@ -208,11 +208,11 @@ const p = {
208
208
  /** Migration date for template compatibility */
209
209
  migrationDate: e(s(), 1759696858),
210
210
  /** Email header settings */
211
- emailHeader: e(O, { senderName: "", subject: "" }),
211
+ emailHeader: e(D, { senderName: "", subject: "" }),
212
212
  /** Folder name for user-saved modules (used by Stripo plugin panel for path construction) */
213
- savedModulesFolderName: e(t(), S.SAVED_MODULES),
213
+ savedModulesFolderName: e(t(), f.SAVED_MODULES),
214
214
  /** Folder name for default/prebuilt modules (used by Stripo plugin panel for path construction) */
215
- defaultModulesFolderName: e(t(), S.DEFAULT_MODULES)
215
+ defaultModulesFolderName: e(t(), f.DEFAULT_MODULES)
216
216
  }), F = a({
217
217
  /** Whether to show the header bar */
218
218
  showHeader: e(o(), !0),
@@ -241,8 +241,10 @@ const p = {
241
241
  allowlistEnabled: e(o(), !1),
242
242
  /** Enable persistent link tracking-id assignment for the click heatmap (opt-in) */
243
243
  linkTrackingIds: e(o(), !1),
244
+ /** Allow persisting a template that still has validation errors (drawer "Save and Continue" soft-save). Host sets false for transactional + unsubscribe. */
245
+ allowSaveWithErrors: e(o(), !0),
244
246
  reusableRecommendationStrategy: e(o(), !1)
245
- }), B = m([
247
+ }), w = m([
246
248
  "amp-accordion",
247
249
  "amp-carousel",
248
250
  "amp-form-controls",
@@ -256,7 +258,7 @@ const p = {
256
258
  "text-block",
257
259
  "timer-block",
258
260
  "video-block"
259
- ]), w = m([
261
+ ]), B = m([
260
262
  "dynamic-content",
261
263
  "checkbox-block",
262
264
  "radio-button-block",
@@ -267,12 +269,12 @@ const p = {
267
269
  ]), j = a({
268
270
  /** Default blocks to exclude from the editor */
269
271
  excludeDefaults: e(
270
- c(B),
272
+ c(w),
271
273
  []
272
274
  ),
273
275
  /** Custom blocks to include in the editor */
274
276
  includeCustoms: e(
275
- c(w),
277
+ c(B),
276
278
  []
277
279
  )
278
280
  }), d = a({
@@ -323,7 +325,7 @@ const p = {
323
325
  customRules: e(c(V), []),
324
326
  /** Skip default compiler rules */
325
327
  ignoreDefaultRules: e(o(), !1)
326
- }), Z = a({
328
+ }), W = a({
327
329
  /**
328
330
  * External validation handler called before save completes.
329
331
  * Return false to cancel the save operation.
@@ -334,17 +336,17 @@ const p = {
334
336
  "externalValidation must be a function"
335
337
  )
336
338
  )
337
- }), Q = a({
339
+ }), K = a({
338
340
  // Required sections
339
341
  /** Identity configuration (required) */
340
342
  identity: A,
341
343
  /** Partner configuration (required) */
342
- partner: M,
344
+ partner: E,
343
345
  // Optional sections (with defaults)
344
346
  /** Template content and presets */
345
- template: e(D, {}),
347
+ template: e(x, {}),
346
348
  /** Editor settings */
347
- editor: e(v, {}),
349
+ editor: e(O, {}),
348
350
  /** UI configuration */
349
351
  ui: e(F, {}),
350
352
  /** Feature toggles */
@@ -354,33 +356,33 @@ const p = {
354
356
  /** Compiler configuration */
355
357
  compiler: e(z, {}),
356
358
  /** Callbacks and event handlers */
357
- callbacks: e(Z, {})
359
+ callbacks: e(W, {})
358
360
  });
359
361
  export {
360
362
  j as BlocksSchema,
361
- Z as CallbacksSchema,
363
+ W as CallbacksSchema,
362
364
  V as CompilerRuleSchema,
363
365
  z as CompilerSchema,
364
- w as CustomBlockTypeSchema,
366
+ B as CustomBlockTypeSchema,
365
367
  G as CustomRuleSchema,
366
- B as DefaultBlockTypeSchema,
368
+ w as DefaultBlockTypeSchema,
367
369
  N as DynamicContentListSchema,
368
- f as DynamicContentNodeSchema,
369
- E as DynamicContentSchema,
370
- v as EditorSchema,
371
- O as EmailHeaderSchema,
370
+ S as DynamicContentNodeSchema,
371
+ M as DynamicContentSchema,
372
+ O as EditorSchema,
373
+ D as EmailHeaderSchema,
372
374
  L as FallbackFontSchema,
373
375
  U as FeaturesSchema,
374
- Q as GuidoConfigSchema,
376
+ K as GuidoConfigSchema,
375
377
  A as IdentitySchema,
376
378
  P as LegacyRecommendationConfigSchema,
377
379
  p as MessageType,
378
- M as PartnerSchema,
380
+ E as PartnerSchema,
379
381
  l as ProductType,
380
382
  _ as RegexRuleSchema,
381
383
  q as RemoveRuleSchema,
382
384
  H as ReplaceRuleSchema,
383
- x as TemplateMigrationSchema,
384
- D as TemplateSchema,
385
+ v as TemplateMigrationSchema,
386
+ x as TemplateSchema,
385
387
  F as UISchema
386
388
  };
@@ -1,20 +1,20 @@
1
1
  import o from "./Guido.vue2.js";
2
2
  /* empty css */
3
- import t from "../_virtual/_plugin-vue2_normalizer.js";
4
- var i = function() {
3
+ import i from "../_virtual/_plugin-vue2_normalizer.js";
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.AuthErrorModal), 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.AuthErrorModal), 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__ */ t(
9
+ }, s = [], n = /* @__PURE__ */ i(
10
10
  o,
11
- i,
11
+ t,
12
12
  s,
13
13
  !1,
14
14
  null,
15
- "c404d230"
15
+ "d0a8825a"
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,32 +1,35 @@
1
- import { defineComponent as ae, defineAsyncComponent as m, ref as W, computed as p, watch as G, 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 { useStripo as pe } from "../composables/useStripo.js";
8
- import { useTimerClone as fe } from "../composables/useTimerClone.js";
9
- import { migrate as z } from "../config/migrator/index.js";
10
- import { ModuleFolderDefaults as H } from "../enums/defaults.js";
11
- import { RIBBON_SELECTOR as ye } from "../enums/onboarding.js";
1
+ import { defineComponent as ie, defineAsyncComponent as m, ref as G, computed as p, watch as V, onMounted as ce, onUnmounted as de } from "vue";
2
+ import { useCortexBlueprintBridge as me } from "../composables/useCortexBlueprintBridge.js";
3
+ import { useEditorLock as le } from "../composables/useEditorLock.js";
4
+ import { provideGuidoActions as ue } from "../composables/useGuidoActions.js";
5
+ import { useGuidoStateBridge as pe } from "../composables/useGuidoStateBridge.js";
6
+ import { usePartner as fe } from "../composables/usePartner.js";
7
+ import { useSaveValidationRollout as ye } from "../composables/useSaveValidationRollout.js";
8
+ import { useStripo as ge } from "../composables/useStripo.js";
9
+ import { useTimerClone as Se } from "../composables/useTimerClone.js";
10
+ import { migrate as $ } from "../config/migrator/index.js";
11
+ import { ModuleFolderDefaults as z } from "../enums/defaults.js";
12
+ import { RIBBON_SELECTOR as ve } from "../enums/onboarding.js";
12
13
  import { useRecommendationExtensionStore as E } from "../extensions/Blocks/Recommendation/store/recommendation.js";
13
- import ge from "./organisms/AutoSaveController.vue.js";
14
- import Se from "./organisms/base/AuthErrorModal.vue.js";
15
- import ve 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 { useStripoApi as De } from "../services/stripoApi.js";
22
- import { useConfigStore as ke } from "../stores/config.js";
23
- import { useDynamicContentStore as Fe } from "../stores/dynamic-content.js";
14
+ import be from "./organisms/AutoSaveController.vue.js";
15
+ import he from "./organisms/base/AuthErrorModal.vue.js";
16
+ import Ee from "./organisms/base/Toaster.vue.js";
17
+ import we from "./organisms/extensions/recommendation/FilterSelectionDrawer.vue.js";
18
+ import De from "./organisms/header/HeaderWrapper.vue.js";
19
+ import Ce from "./organisms/LoadingWrapper.vue.js";
20
+ import ke from "./organisms/save-as-template/SaveAsTemplateDrawer.vue.js";
21
+ import Re from "./organisms/unsubscribe/UnsubscribeWrapper.vue.js";
22
+ import Fe from "./organisms/validation/ValidationErrorDrawer.vue.js";
23
+ import { useStripoApi as Me } from "../services/stripoApi.js";
24
+ import { useConfigStore as Te } from "../stores/config.js";
25
+ import { useDynamicContentStore as Ie } from "../stores/dynamic-content.js";
24
26
  import { useEditorStore as w } from "../stores/editor.js";
25
- import { usePreviewStore as Me } from "../stores/preview.js";
26
- import { useTemplateStore as Re } from "../stores/template.js";
27
- import { useUnsubscribeStore as Te } from "../stores/unsubscribe.js";
28
- import { readTrackFloor as $ } from "../utils/linkTrackingIds.js";
29
- const rt = /* @__PURE__ */ ae({
27
+ import { usePreviewStore as Le } from "../stores/preview.js";
28
+ import { useSaveValidationStore as Ue } from "../stores/save-validation.js";
29
+ import { useTemplateStore as Ae } from "../stores/template.js";
30
+ import { useUnsubscribeStore as Be } from "../stores/unsubscribe.js";
31
+ import { readTrackFloor as H } from "../utils/linkTrackingIds.js";
32
+ const ut = /* @__PURE__ */ ie({
30
33
  __name: "Guido",
31
34
  props: {
32
35
  config: null,
@@ -34,25 +37,25 @@ const rt = /* @__PURE__ */ ae({
34
37
  },
35
38
  emits: ["dynamic-content:open", "back", "save:start", "save:complete", "on-change", "ready", "onboarding:finished", "test-email:click"],
36
39
  setup(q, { expose: K, emit: r }) {
37
- const s = q, V = m(
40
+ const s = q, j = m(
38
41
  () => import("./organisms/email-preview/PreviewContainer.vue.js")
39
- ), j = m(
40
- () => import("./organisms/onboarding/OnboardingWrapper.vue.js")
41
42
  ), J = m(
42
- () => import("./organisms/extensions/recommendation/AssignStrategyDrawer.vue.js")
43
+ () => import("./organisms/onboarding/OnboardingWrapper.vue.js")
43
44
  ), Q = m(
44
- () => import("./organisms/extensions/recommendation/RemoveStrategyModal.vue.js")
45
+ () => import("./organisms/extensions/recommendation/AssignStrategyDrawer.vue.js")
45
46
  ), X = m(
47
+ () => import("./organisms/extensions/recommendation/RemoveStrategyModal.vue.js")
48
+ ), Y = m(
46
49
  () => import("./organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue.js")
47
- ), C = W(), f = W(), y = Fe(), D = Te(), o = ke();
50
+ ), D = G(), f = G(), y = Ie(), C = Be(), o = Te();
48
51
  s.ready && o.init(s.config);
49
- const c = w(), Y = Me(), l = p(() => c.hasChanges), { isTestPartner: Z } = ue(), k = () => {
52
+ const c = w(), Z = Le(), l = p(() => c.hasChanges), { isTestPartner: ee } = fe(), { isEnabled: te, loadRollout: k } = ye(), R = () => {
50
53
  var t;
51
- return (t = C.value) == null ? void 0 : t.handleSave(!0);
54
+ return (t = D.value) == null ? void 0 : t.handleSave(!0);
52
55
  }, F = (t) => {
53
56
  c.loadingStatus = t;
54
57
  };
55
- ce(), le();
58
+ me(), pe();
56
59
  const g = () => {
57
60
  var t, e;
58
61
  return {
@@ -60,18 +63,18 @@ const rt = /* @__PURE__ */ ae({
60
63
  userId: o.userId,
61
64
  username: o.username,
62
65
  partnerName: o.partnerName,
63
- savedModulesFolderName: ((t = o.editor) == null ? void 0 : t.savedModulesFolderName) || H.SAVED_MODULES,
64
- defaultModulesFolderName: ((e = o.editor) == null ? void 0 : e.defaultModulesFolderName) || H.DEFAULT_MODULES
66
+ savedModulesFolderName: ((t = o.editor) == null ? void 0 : t.savedModulesFolderName) || z.SAVED_MODULES,
67
+ defaultModulesFolderName: ((e = o.editor) == null ? void 0 : e.defaultModulesFolderName) || z.DEFAULT_MODULES
65
68
  };
66
- }, { initPlugin: M, preloadRuntime: R } = pe(), { runExclusive: T, beginMount: I, isCurrentMount: S } = de();
69
+ }, { initPlugin: M, preloadRuntime: T } = ge(), { runExclusive: I, beginMount: L, isCurrentMount: S } = le();
67
70
  let u = 0;
68
- const { getDefaultTemplate: L } = De(), { cloneTimersOnSave: U, hasTimerBlocks: A } = fe(), ee = p(() => {
71
+ const { getDefaultTemplate: U } = Me(), { cloneTimersOnSave: A, hasTimerBlocks: B } = Se(), oe = p(() => {
69
72
  var t;
70
73
  return !((t = o.ui) != null && t.showHeader);
71
- }), te = p(() => o.isFeatureEnabled("reusableRecommendationStrategy")), oe = p(
74
+ }), ne = p(() => o.isFeatureEnabled("reusableRecommendationStrategy")), re = p(
72
75
  () => !!E().recommendationConfigs.strategyId
73
76
  );
74
- me({
77
+ ue({
75
78
  onBack: () => {
76
79
  console.debug("guido:back"), r("back");
77
80
  },
@@ -86,12 +89,12 @@ const rt = /* @__PURE__ */ ae({
86
89
  console.debug("guido:test-email:click"), r("test-email:click");
87
90
  }
88
91
  });
89
- const B = (t) => {
92
+ const N = (t) => {
90
93
  console.debug("dynamic-content:close", t), y.setSelectedDynamicContent(t), document.dispatchEvent(new CustomEvent("dynamic-content:close", { detail: t }));
91
- }, N = () => {
94
+ }, P = () => {
92
95
  console.debug("dynamic-content:close", "Without Data"), document.dispatchEvent(new CustomEvent("dynamic-content:close", { detail: { text: "", value: "" } }));
93
96
  };
94
- G(() => l.value, () => {
97
+ V(() => l.value, () => {
95
98
  r("on-change", l.value);
96
99
  });
97
100
  const v = (t) => {
@@ -101,57 +104,57 @@ const rt = /* @__PURE__ */ ae({
101
104
  let i = null;
102
105
  const b = () => {
103
106
  var e;
104
- const t = document.querySelector(ye);
107
+ const t = document.querySelector(ve);
105
108
  (e = f.value) == null || e.style.setProperty("--ribbon-offset", `${(t == null ? void 0 : t.offsetHeight) ?? 0}px`);
106
109
  }, h = async () => {
107
110
  var t;
108
111
  try {
109
112
  o.initialized || o.init(s.config), c.templateId = o.templateId;
110
- 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) || [];
111
- D.selectedUnsubscribePages = (e == null ? void 0 : e.selectedUnsubscribePages) || [];
112
- const _ = ((t = e == null ? void 0 : e.migration) == null ? void 0 : t.recommendationConfigs) ?? {}, O = o.isFeatureEnabled("linkTrackingIds"), x = {
113
+ const e = o.template, a = (e == null ? void 0 : e.html) || "", d = (e == null ? void 0 : e.css) || "", _ = (e == null ? void 0 : e.preselectedDynamicContent) || [];
114
+ C.selectedUnsubscribePages = (e == null ? void 0 : e.selectedUnsubscribePages) || [];
115
+ const O = ((t = e == null ? void 0 : e.migration) == null ? void 0 : t.recommendationConfigs) ?? {}, x = o.isFeatureEnabled("linkTrackingIds"), W = {
113
116
  partnerName: o.partnerName,
114
117
  campaignUrls: e == null ? void 0 : e.recommendationCampaignUrls,
115
118
  rrsEnabled: o.isFeatureEnabled("reusableRecommendationStrategy")
116
119
  };
117
120
  let n = {
118
- html: a && await z(a, _, x),
121
+ html: a && await $(a, O, W),
119
122
  css: d
120
123
  };
121
- n.html || (n = await L(), n.html = await z(n.html, _, x));
122
- const ne = O ? $(n.html, (e == null ? void 0 : e.trackIdCounter) || 0) : 0;
123
- A(n.html) && (n.html = await U(n.html)), O && (c.trackIdSessionFloor = Math.max(ne, $(n.html)));
124
- const re = {
125
- preselectedDynamicContentList: P,
124
+ n.html || (n = await U(), n.html = await $(n.html, O, W));
125
+ const ae = x ? H(n.html, (e == null ? void 0 : e.trackIdCounter) || 0) : 0;
126
+ B(n.html) && (n.html = await A(n.html)), x && (c.trackIdSessionFloor = Math.max(ae, H(n.html)));
127
+ const se = {
128
+ preselectedDynamicContentList: _,
126
129
  onReady: () => {
127
130
  console.debug("guido:ready"), r("ready");
128
131
  }
129
132
  };
130
- u = I(), await M(n, g(), re), y.selectedDynamicContentList = P;
133
+ u = L(), await M(n, g(), se), y.selectedDynamicContentList = _;
131
134
  } catch (e) {
132
135
  console.error("Failed to initialize Stripo editor:", e);
133
136
  }
134
137
  };
135
- return se(async () => {
138
+ return ce(async () => {
136
139
  var e;
137
- console.debug("Guido says happy coding 🎉"), console.debug("🚗 Ka-Chow"), E().$reset(), w().$reset(), Re().$reset(), b();
140
+ console.debug("Guido says happy coding 🎉"), console.debug("🚗 Ka-Chow"), E().$reset(), w().$reset(), Ae().$reset(), Ue().$reset(), k(), b();
138
141
  const t = (e = f.value) == null ? void 0 : e.parentElement;
139
- if (t && (i = new ResizeObserver(b), i.observe(t)), R(), s.ready)
142
+ if (t && (i = new ResizeObserver(b), i.observe(t)), T(), s.ready)
140
143
  await h();
141
144
  else {
142
- const a = G(() => s.ready, (d) => {
145
+ const a = V(() => s.ready, (d) => {
143
146
  d && (a(), h());
144
147
  });
145
148
  }
146
149
  document.addEventListener("dynamic-content:open", v);
147
- }), ie(() => {
150
+ }), de(() => {
148
151
  if (i == null || i.disconnect(), document.removeEventListener("dynamic-content:open", v), E().disposeStrategyPageReturn(), S(u))
149
152
  try {
150
153
  w().isStripoInitialized = !1;
151
154
  } catch (t) {
152
155
  console.debug("Failed to close the editor readiness gate on unmount", t);
153
156
  }
154
- T(async () => {
157
+ I(async () => {
155
158
  if (S(u))
156
159
  try {
157
160
  window.UIEditor.removeEditor();
@@ -161,15 +164,15 @@ const rt = /* @__PURE__ */ ae({
161
164
  }), o.reset();
162
165
  }), K({
163
166
  dynamicContent: {
164
- insert: B,
165
- close: N
167
+ insert: N,
168
+ close: P
166
169
  },
167
170
  hasChanges: l,
168
- saveSilent: k,
171
+ saveSilent: R,
169
172
  setLoading: F
170
- }), { __sfc: !0, PreviewContainer: V, OnboardingWrapper: j, AssignStrategyDrawer: J, RemoveStrategyModal: Q, LegacyStrategyUpdatedModal: X, headerWrapperRef: C, wrapperRef: f, dynamicContentStore: y, unsubscribeStore: D, props: s, configStore: o, editorStore: c, previewStore: Y, hasChanges: l, isTestPartner: Z, saveSilent: k, setLoading: F, emit: r, buildMetadata: g, initPlugin: M, preloadRuntime: R, runExclusive: T, beginMount: I, isCurrentMount: S, mountGeneration: u, getDefaultTemplate: L, cloneTimersOnSave: U, hasTimerBlocks: A, noHeader: ee, isRrsEnabled: te, hasAssignedStrategy: oe, insertDynamicContent: B, closeDynamicContent: N, handleDynamicContentOpen: v, ribbonObserver: i, updateRibbonOffset: b, startEditor: h, AutoSaveController: ge, AuthErrorModal: Se, Toaster: ve, FilterSelectionDrawer: be, HeaderWrapper: he, LoadingWrapper: Ee, SaveAsTemplateDrawer: we, UnsubscribeWrapper: Ce };
173
+ }), { __sfc: !0, PreviewContainer: j, OnboardingWrapper: J, AssignStrategyDrawer: Q, RemoveStrategyModal: X, LegacyStrategyUpdatedModal: Y, headerWrapperRef: D, wrapperRef: f, dynamicContentStore: y, unsubscribeStore: C, props: s, configStore: o, editorStore: c, previewStore: Z, hasChanges: l, isTestPartner: ee, isSaveValidationEnabled: te, loadRollout: k, saveSilent: R, setLoading: F, emit: r, buildMetadata: g, initPlugin: M, preloadRuntime: T, runExclusive: I, beginMount: L, isCurrentMount: S, mountGeneration: u, getDefaultTemplate: U, cloneTimersOnSave: A, hasTimerBlocks: B, noHeader: oe, isRrsEnabled: ne, hasAssignedStrategy: re, insertDynamicContent: N, closeDynamicContent: P, handleDynamicContentOpen: v, ribbonObserver: i, updateRibbonOffset: b, startEditor: h, AutoSaveController: be, AuthErrorModal: he, Toaster: Ee, FilterSelectionDrawer: we, HeaderWrapper: De, LoadingWrapper: Ce, SaveAsTemplateDrawer: ke, UnsubscribeWrapper: Re, ValidationErrorDrawer: Fe };
171
174
  }
172
175
  });
173
176
  export {
174
- rt as default
177
+ ut as default
175
178
  };
@@ -1,13 +1,15 @@
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 n } from "vue";
2
+ import { useAutoSave as u } from "../../composables/useAutoSave.js";
3
+ import { useSave as i } from "../../composables/useSave.js";
4
+ import { useSaveValidationRollout as l } from "../../composables/useSaveValidationRollout.js";
5
+ import { useConfigStore as m } from "../../stores/config.js";
6
+ const d = /* @__PURE__ */ n({
5
7
  __name: "AutoSaveController",
6
- setup(a) {
7
- const { save: e } = s(), o = () => e(!1, !0);
8
- return r(o), { __sfc: !0, save: e, backgroundSave: o };
8
+ setup(f) {
9
+ const { save: e, saveRawOnly: t } = i(), { isEnabled: r } = l(), a = m(), o = () => r.value && a.allowSaveWithErrors, s = () => o() ? t() : e(!1, !0);
10
+ return u(s, { clearsChanges: () => !o() }), { __sfc: !0, save: e, saveRawOnly: t, isEnabled: r, configStore: a, isRawAutosave: o, backgroundSave: s };
9
11
  }
10
12
  });
11
13
  export {
12
- f as default
14
+ d as default
13
15
  };
@@ -4,20 +4,20 @@ 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);
11
11
  } } })], 1);
12
- }, c = [], p = /* @__PURE__ */ d(
12
+ }, p = [], c = /* @__PURE__ */ d(
13
13
  l,
14
14
  u,
15
- c,
15
+ p,
16
16
  !1,
17
17
  null,
18
- "c61cc8ea"
18
+ "baf7a5dd"
19
19
  );
20
- const v = p.exports;
20
+ const v = c.exports;
21
21
  export {
22
22
  v as default
23
23
  };