@useinsider/guido 3.17.0-beta.ea65303 → 3.17.0-beta.ec8eabb

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 (52) hide show
  1. package/README.md +0 -1
  2. package/dist/@types/config/schemas.js +27 -29
  3. package/dist/components/Guido.vue.js +8 -8
  4. package/dist/components/Guido.vue2.js +59 -60
  5. package/dist/components/organisms/AutoSaveController.vue2.js +8 -9
  6. package/dist/components/organisms/header/EditorActions.vue.js +2 -2
  7. package/dist/components/organisms/header/EditorActions.vue2.js +51 -74
  8. package/dist/components/organisms/header/LeftSlot.vue.js +5 -5
  9. package/dist/components/organisms/header/LeftSlot.vue2.js +12 -16
  10. package/dist/components/wrappers/WpDrawer.vue.js +7 -9
  11. package/dist/components/wrappers/WpDrawer.vue2.js +1 -1
  12. package/dist/composables/useActionsApi.js +82 -67
  13. package/dist/composables/useAutoSave.js +31 -26
  14. package/dist/composables/useEditorLock.js +18 -0
  15. package/dist/composables/useGuidoStateBridge.js +31 -30
  16. package/dist/composables/useHtmlCompiler.js +26 -37
  17. package/dist/composables/useHtmlValidator.js +0 -2
  18. package/dist/composables/useSave.js +47 -86
  19. package/dist/composables/validators/useCouponBlockValidator.js +21 -24
  20. package/dist/composables/validators/useUnsubscribeBlockValidator.js +27 -34
  21. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +26 -33
  22. package/dist/guido.css +1 -1
  23. package/dist/src/@types/config/schemas.d.ts +0 -4
  24. package/dist/src/components/Guido.vue.d.ts +1 -17
  25. package/dist/src/components/organisms/header/EditorActions.vue.d.ts +1 -17
  26. package/dist/src/components/organisms/header/HeaderWrapper.vue.d.ts +1 -17
  27. package/dist/src/components/organisms/header/RightSlot.vue.d.ts +1 -17
  28. package/dist/src/components/wrappers/WpDrawer.vue.d.ts +3 -4
  29. package/dist/src/composables/useConfig.d.ts +0 -2
  30. package/dist/src/composables/useEditorLock.d.ts +11 -0
  31. package/dist/src/composables/useHtmlValidator.d.ts +0 -21
  32. package/dist/src/composables/useSave.d.ts +1 -6
  33. package/dist/src/composables/validators/useCouponBlockValidator.d.ts +0 -3
  34. package/dist/src/composables/validators/useUnsubscribeBlockValidator.d.ts +0 -10
  35. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +0 -5
  36. package/dist/src/stores/config.d.ts +0 -30
  37. package/dist/src/utils/templatePreparation.d.ts +0 -30
  38. package/dist/stores/config.js +22 -39
  39. package/dist/utils/templatePreparation.js +25 -28
  40. package/package.json +1 -1
  41. package/dist/components/organisms/validation/ValidationErrorDrawer.vue.js +0 -20
  42. package/dist/components/organisms/validation/ValidationErrorDrawer.vue2.js +0 -48
  43. package/dist/composables/useSaveValidation.js +0 -279
  44. package/dist/composables/useSaveValidationRollout.js +0 -9
  45. package/dist/enums/save-validation.js +0 -4
  46. package/dist/src/@types/save-validation.d.ts +0 -19
  47. package/dist/src/components/organisms/validation/ValidationErrorDrawer.vue.d.ts +0 -2
  48. package/dist/src/composables/useSaveValidation.d.ts +0 -6
  49. package/dist/src/composables/useSaveValidationRollout.d.ts +0 -3
  50. package/dist/src/enums/save-validation.d.ts +0 -27
  51. package/dist/src/stores/save-validation.d.ts +0 -22
  52. package/dist/stores/save-validation.js +0 -30
@@ -1,94 +1,55 @@
1
- import { useActionsApi as U } from "./useActionsApi.js";
2
- import { useConfig as L } from "./useConfig.js";
3
- import { useSaveStart as A, useSaveComplete as q } from "./useGuidoActions.js";
4
- import { useSaveValidation as M } from "./useSaveValidation.js";
5
- import { useSaveValidationRollout as R } from "./useSaveValidationRollout.js";
6
- import { useSyncModuleExtractor as W } from "./useSyncModuleExtractor.js";
7
- import { ToasterTypeOptions as O } from "../enums/toaster.js";
8
- import { useStripoApi as D } from "../services/stripoApi.js";
9
- import { useConfigStore as F } from "../stores/config.js";
10
- import { useDynamicContentStore as j } from "../stores/dynamic-content.js";
11
- import { useSaveValidationStore as z } from "../stores/save-validation.js";
12
- import { useTemplatePreparation as G, getHtmlReferencedUnsubscribePages as I } from "../utils/templatePreparation.js";
13
- import { useAllowlist as J } from "./useAllowlist.js";
14
- import { useHtmlValidator as K } from "./useHtmlValidator.js";
15
- import { useToaster as N } from "./useToaster.js";
16
- import { useCouponBlockValidator as Q } from "./validators/useCouponBlockValidator.js";
17
- import { useLiquidValidator as X } from "./validators/useLiquidValidator.js";
18
- import { useUnsubscribeBlockValidator as Y } from "./validators/useUnsubscribeBlockValidator.js";
19
- const wt = () => {
20
- const r = A(), u = q(), { validateHtml: d } = K(), { validateLiquidSyntax: f } = X(), { validateCouponBlockTags: p } = Q(), { validateUnsubscribeBlockUniqueness: v, validateUnsubscribeBlockHasTemplate: S } = Y(), { callbacks: a, isFeatureEnabled: c } = L(), { extractSyncModuleData: y } = W(), { setSyncModuleUnsubscriptionPages: w } = D(), { editorSave: b, getTemplateData: g } = U(), { showToaster: H } = N(), { getBlockedDomains: V, resolveToast: E } = J(), { prepareTemplateDetails: m } = G(), { collectSaveValidationErrors: C } = M(), { isEnabled: x } = R(), k = z(), B = j(), T = F(), n = async (t, e, o) => {
21
- if (!c("allowlistEnabled"))
22
- return !1;
23
- const i = await V(t, e);
24
- if (!i.length)
25
- return !1;
26
- if (!o) {
27
- const s = await E(i);
28
- s != null && s.message && H({
29
- type: O.Warning,
30
- message: s.message,
31
- actionButton: s.actionButton
32
- });
33
- }
34
- return !0;
35
- }, P = async (t) => !p(t.compiledHtml) || !v(t.compiledHtml) || !S(t.compiledHtml) ? !1 : c("liquidSyntax") ? f(t.compiledHtml) : d(t.compiledHtml, t.dynamicContentList, !0), l = async (t, e) => {
36
- if (!await b())
1
+ import { useActionsApi as T } from "./useActionsApi.js";
2
+ import { useConfig as B } from "./useConfig.js";
3
+ import { useEditorLock as q } from "./useEditorLock.js";
4
+ import { useSaveStart as C, useSaveComplete as L } from "./useGuidoActions.js";
5
+ import { useSyncModuleExtractor as D } from "./useSyncModuleExtractor.js";
6
+ import { ToasterTypeOptions as P } from "../enums/toaster.js";
7
+ import { useStripoApi as U } from "../services/stripoApi.js";
8
+ import { useTemplatePreparation as A } from "../utils/templatePreparation.js";
9
+ import { useAllowlist as M } from "./useAllowlist.js";
10
+ import { useHtmlValidator as h } from "./useHtmlValidator.js";
11
+ import { useToaster as F } from "./useToaster.js";
12
+ import { useCouponBlockValidator as O } from "./validators/useCouponBlockValidator.js";
13
+ import { useLiquidValidator as W } from "./validators/useLiquidValidator.js";
14
+ import { useUnsubscribeBlockValidator as j } from "./validators/useUnsubscribeBlockValidator.js";
15
+ const et = () => {
16
+ const l = C(), c = L(), { validateHtml: m } = h(), { validateLiquidSyntax: d } = W(), { validateCouponBlockTags: u } = O(), { validateUnsubscribeBlockUniqueness: p, validateUnsubscribeBlockHasTemplate: f } = j(), { callbacks: s, isFeatureEnabled: r } = B(), { extractSyncModuleData: v } = D(), { setSyncModuleUnsubscriptionPages: S } = U(), { editorSave: b } = T(), { showToaster: w } = F(), { getBlockedDomains: V, resolveToast: x } = M(), { runExclusive: y } = q(), E = async (a, e) => {
17
+ var n;
18
+ l();
19
+ const { prepareTemplateDetails: H } = A(), t = await H();
20
+ if (!u(t.compiledHtml) || !p(t.compiledHtml) || !f(t.compiledHtml))
37
21
  return;
38
- const { unsubscribePayload: i, stripoModules: s } = y(t.rawHtml);
39
- if (await w(i), t.modules = s, !e.suppress) {
40
- const h = e.blankCompiled ? { compiledHtml: "", ampHtml: "" } : {};
41
- u({ ...t, ...h, silent: e.silent });
42
- }
43
- return t;
44
- };
45
- return { save: async (t = !1, e = !1) => {
46
- var i;
47
- r();
48
- const o = await m();
49
- if (x.value && !e) {
50
- const s = await C(
51
- o.compiledHtml,
52
- o.dynamicContentList
53
- );
54
- if (s.length) {
55
- k.open(s, "save");
22
+ if (r("liquidSyntax")) {
23
+ if (!await d(t.compiledHtml))
56
24
  return;
57
- }
58
- } else if (!await P(o))
59
- return;
60
- if (!((i = a.value) != null && i.externalValidation && !await a.value.externalValidation(o)) && !await n(o.compiledHtml, o.css, e))
61
- return l(o, { silent: e, suppress: t });
62
- }, saveWithErrors: async () => {
63
- var e;
64
- if (!T.allowSaveWithErrors)
25
+ } else if (!await m(t.compiledHtml, t.dynamicContentList, !0))
65
26
  return;
66
- r();
67
- const t = await m();
68
- if (!((e = a.value) != null && e.externalValidation && !await a.value.externalValidation(t)) && !await n(t.compiledHtml, t.css, !1))
69
- return l(t, { silent: !1, blankCompiled: !0 });
70
- }, saveRawOnly: async () => {
71
- r();
72
- const { html: t, css: e } = await g();
73
- if (await n(t, e, !0))
27
+ if ((n = s.value) != null && n.externalValidation && !await s.value.externalValidation(t))
74
28
  return;
75
- const o = I(t), i = {
76
- dynamicContentList: B.getSelectedDynamicContentList,
77
- compiledHtml: "",
78
- rawHtml: t,
79
- css: e,
80
- ampHtml: "",
81
- ampErrors: [],
82
- modules: [],
83
- recommendation: { campaignUrls: {}, configs: {} },
84
- unsubscribe: {
85
- status: o.length > 0,
86
- config: o
29
+ if (r("allowlistEnabled")) {
30
+ const o = await V(t.compiledHtml, t.css);
31
+ if (o.length) {
32
+ if (!e) {
33
+ const i = await x(o);
34
+ i != null && i.message && w({
35
+ type: P.Warning,
36
+ message: i.message,
37
+ actionButton: i.actionButton
38
+ });
39
+ }
40
+ return;
87
41
  }
88
- };
89
- return l(i, { silent: !0 });
90
- } };
42
+ }
43
+ if (!await b())
44
+ return;
45
+ const { unsubscribePayload: g, stripoModules: k } = v(t.rawHtml);
46
+ return await S(g), t.modules = k, a || c({ ...t, silent: e }), t;
47
+ };
48
+ return { save: (a = !1, e = !1) => y(
49
+ // Serialized so no other editor read/export runs while Stripo is exporting for this save.
50
+ () => E(a, e)
51
+ ) };
91
52
  };
92
53
  export {
93
- wt as useSave
54
+ et as useSave
94
55
  };
@@ -1,27 +1,24 @@
1
- import { ToasterTypeOptions as n } from "../../enums/toaster.js";
2
- import { COUPON_PLACEHOLDER_DEFAULT as s, COUPON_PLACEHOLDER_LIQUID as a } from "../../extensions/Blocks/CouponBlock/template.js";
3
- import { useToaster as i } from "../useToaster.js";
4
- import { useTranslations as l } from "../useTranslations.js";
5
- const c = /* @__PURE__ */ new Set([
6
- s,
7
- a
8
- ]), p = "newsletter.coupon-tag-modified";
9
- function u(r) {
10
- const e = new DOMParser().parseFromString(r, "text/html");
11
- return Array.from(e.querySelectorAll(".coupon-block")).map((o) => {
12
- var t;
13
- return ((t = o.textContent) == null ? void 0 : t.trim()) ?? "";
14
- }).filter((o) => !c.has(o));
15
- }
16
- const T = () => {
17
- const { showToaster: r } = i(), e = l();
18
- return { validateCouponBlockTags: (t) => u(t).length > 0 ? (r({
19
- type: n.Warning,
20
- message: e(p)
21
- }), !1) : !0 };
1
+ import { ToasterTypeOptions as c } from "../../enums/toaster.js";
2
+ import { COUPON_PLACEHOLDER_DEFAULT as i, COUPON_PLACEHOLDER_LIQUID as l } from "../../extensions/Blocks/CouponBlock/template.js";
3
+ import { useToaster as m } from "../useToaster.js";
4
+ import { useTranslations as p } from "../useTranslations.js";
5
+ const u = /* @__PURE__ */ new Set([
6
+ i,
7
+ l
8
+ ]), A = () => {
9
+ const { showToaster: t } = m(), r = p();
10
+ return { validateCouponBlockTags: (e) => {
11
+ const n = new DOMParser().parseFromString(e, "text/html");
12
+ return Array.from(n.querySelectorAll(".coupon-block")).find((s) => {
13
+ var o;
14
+ const a = ((o = s.textContent) == null ? void 0 : o.trim()) ?? "";
15
+ return !u.has(a);
16
+ }) ? (t({
17
+ type: c.Warning,
18
+ message: r("newsletter.coupon-tag-modified")
19
+ }), !1) : !0;
20
+ } };
22
21
  };
23
22
  export {
24
- p as COUPON_TAG_MODIFIED_KEY,
25
- u as findInvalidCouponBlocks,
26
- T as useCouponBlockValidator
23
+ A as useCouponBlockValidator
27
24
  };
@@ -1,8 +1,8 @@
1
- import { ToasterTypeOptions as c } from "../../enums/toaster.js";
1
+ import { ToasterTypeOptions as i } from "../../enums/toaster.js";
2
2
  import { PAGE_TYPES as u } from "../../enums/unsubscribe.js";
3
- import { UNSUBSCRIBE_BLOCK_SELECTOR as i, DATA_ATTRIBUTES as a } from "../../extensions/Blocks/Unsubscribe/utils/constants.js";
4
- import { useToaster as p } from "../useToaster.js";
5
- import { useTranslations as l } from "../useTranslations.js";
3
+ import { UNSUBSCRIBE_BLOCK_SELECTOR as l, DATA_ATTRIBUTES as a } from "../../extensions/Blocks/Unsubscribe/utils/constants.js";
4
+ import { useToaster as E } from "../useToaster.js";
5
+ import { useTranslations as m } from "../useTranslations.js";
6
6
  const T = [
7
7
  {
8
8
  pageType: u.GLOBAL_UNSUBSCRIBE,
@@ -12,37 +12,30 @@ const T = [
12
12
  pageType: u.SUBSCRIPTION_PREFERENCE_CENTER,
13
13
  messageKey: "unsubscription-preference.duplicate-pref-center"
14
14
  }
15
- ], g = "unsubscription-preference.duplicate-both", E = "unsubscription-preference.select-page-to-continue";
16
- function m(r) {
17
- const s = new DOMParser().parseFromString(r, "text/html"), t = /* @__PURE__ */ new Map();
18
- return s.querySelectorAll(i).forEach((n) => {
19
- const e = Number(n.getAttribute(a.PAGE_TYPE));
20
- t.set(e, (t.get(e) ?? 0) + 1);
21
- }), T.filter((n) => (t.get(n.pageType) ?? 0) > 1);
22
- }
23
- function b(r) {
24
- const s = new DOMParser().parseFromString(r, "text/html");
25
- return Array.from(s.querySelectorAll(i)).filter((t) => {
26
- const n = t.getAttribute(a.PAGE_TYPE), e = t.getAttribute(a.PAGE_LIST);
27
- return !n || !e;
28
- }).length;
29
- }
30
- const y = () => {
31
- const { showToaster: r } = p(), s = l();
32
- return { validateUnsubscribeBlockUniqueness: (e) => {
33
- const o = m(e);
34
- return o.length ? (r({
35
- type: c.Error,
36
- message: s(o.length > 1 ? g : o[0].messageKey)
15
+ ], g = "unsubscription-preference.duplicate-both", b = "unsubscription-preference.select-page-to-continue", P = () => {
16
+ const { showToaster: c } = E(), p = m();
17
+ return { validateUnsubscribeBlockUniqueness: (n) => {
18
+ const o = new DOMParser().parseFromString(n, "text/html"), r = /* @__PURE__ */ new Map();
19
+ o.querySelectorAll(l).forEach((e) => {
20
+ const s = Number(e.getAttribute(a.PAGE_TYPE));
21
+ r.set(s, (r.get(s) ?? 0) + 1);
22
+ });
23
+ const t = T.filter((e) => (r.get(e.pageType) ?? 0) > 1).map((e) => e.messageKey);
24
+ return t.length ? (c({
25
+ type: i.Error,
26
+ message: p(t.length > 1 ? g : t[0])
37
27
  }), !1) : !0;
38
- }, validateUnsubscribeBlockHasTemplate: (e) => b(e) === 0 ? !0 : (r({
39
- type: c.Warning,
40
- message: s(E)
41
- }), !1) };
28
+ }, validateUnsubscribeBlockHasTemplate: (n) => {
29
+ const o = new DOMParser().parseFromString(n, "text/html");
30
+ return Array.from(o.querySelectorAll(l)).some((t) => {
31
+ const e = t.getAttribute(a.PAGE_TYPE), s = t.getAttribute(a.PAGE_LIST);
32
+ return !e || !s;
33
+ }) ? (c({
34
+ type: i.Warning,
35
+ message: p(b)
36
+ }), !1) : !0;
37
+ } };
42
38
  };
43
39
  export {
44
- E as EMPTY_BLOCK_KEY,
45
- b as countUnsubBlocksWithoutPage,
46
- m as findDuplicateUnsubPageTypes,
47
- y as useUnsubscribeBlockValidator
40
+ P as useUnsubscribeBlockValidator
48
41
  };
@@ -1,21 +1,21 @@
1
- import { getRecommendationFeedSourceMaps as g, getOperatorOptions as C, PriceAttributes as y } from "../../../../enums/extensions/recommendationBlock.js";
2
- import { useRecommendationApi as G } from "../../../../services/recommendationApi.js";
3
- import { useConfigStore as P } from "../../../../stores/config.js";
4
- import { defineStore as F } from "pinia";
1
+ import { getRecommendationFeedSourceMaps as g, getOperatorOptions as R, PriceAttributes as C } from "../../../../enums/extensions/recommendationBlock.js";
2
+ import { useRecommendationApi as y } from "../../../../services/recommendationApi.js";
3
+ import { useConfigStore as G } from "../../../../stores/config.js";
4
+ import { defineStore as P } from "pinia";
5
5
  import "../constants/selectors.js";
6
- import { DEFAULT_MOBILE_CARDS_IN_ROW as D, DEFAULT_CARDS_IN_ROW as v } from "../constants/layout.js";
6
+ import { DEFAULT_MOBILE_CARDS_IN_ROW as F, DEFAULT_CARDS_IN_ROW as D } from "../constants/layout.js";
7
7
  import { EXCLUDED_ALGORITHM_IDS as w } from "../constants/defaultConfig.js";
8
8
  import { getDefaultProducts as S } from "../templates/utils.js";
9
9
  import { generateCompleteFilterQuery as b } from "../utils/filterUtil.js";
10
- import { getPartnerRecommendationParams as N } from "../utils/partnerCustomizations.js";
11
- import { sanitizeProductIds as x } from "../utils/productIds.js";
12
- import { isFilterValid as L } from "../validation/filterSchema.js";
13
- import { isConfigValid as I } from "../validation/requiredFields.js";
14
- const h = G();
10
+ import { getPartnerRecommendationParams as v } from "../utils/partnerCustomizations.js";
11
+ import { sanitizeProductIds as N } from "../utils/productIds.js";
12
+ import { isFilterValid as x } from "../validation/filterSchema.js";
13
+ import { isConfigValid as L } from "../validation/requiredFields.js";
14
+ const h = y();
15
15
  let m = null, u = null, d = null;
16
- function R() {
16
+ function k() {
17
17
  return {
18
- cardsInRow: v,
18
+ cardsInRow: D,
19
19
  currencySettings: {
20
20
  name: "USD",
21
21
  value: "USD",
@@ -29,7 +29,7 @@ function R() {
29
29
  productIds: [],
30
30
  id: 1,
31
31
  language: "en_US",
32
- mobileCardsInRow: D,
32
+ mobileCardsInRow: F,
33
33
  mobileLayoutEnabled: !1,
34
34
  orientation: "grid",
35
35
  recommendedProducts: [],
@@ -44,9 +44,9 @@ function R() {
44
44
  priceHideIfSameAsDiscounted: !1
45
45
  };
46
46
  }
47
- function k() {
47
+ function I() {
48
48
  return {
49
- recommendationConfigs: R(),
49
+ recommendationConfigs: k(),
50
50
  recommendationProducts: [],
51
51
  filterStatus: !1,
52
52
  filterSelectionDrawerStatus: !1,
@@ -64,7 +64,7 @@ const U = () => ({
64
64
  blockStates: {},
65
65
  currentRecommendationId: null,
66
66
  configVersion: 0
67
- }), H = F("guidoRecommendationExtension", {
67
+ }), H = P("guidoRecommendationExtension", {
68
68
  state: () => U(),
69
69
  getters: {
70
70
  // ====================================================================
@@ -75,7 +75,7 @@ const U = () => ({
75
75
  * This allows all existing code that reads `store.recommendationConfigs` to work unchanged.
76
76
  */
77
77
  recommendationConfigs(t) {
78
- return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : R();
78
+ return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : k();
79
79
  },
80
80
  /**
81
81
  * Proxy getter: delegates to blockStates[currentRecommendationId].recommendationProducts
@@ -139,7 +139,7 @@ const U = () => ({
139
139
  getFilterList() {
140
140
  return Object.values(this.filterList).filter((t) => t.isFilterable !== 0 && t.isFilterable !== !1).map((t) => {
141
141
  let e;
142
- return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : y.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
142
+ return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : C.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
143
143
  text: t.displayName,
144
144
  value: e,
145
145
  type: t.attributeType
@@ -161,7 +161,7 @@ const U = () => ({
161
161
  setCurrentBlock(t) {
162
162
  this.blockStates[t] || (this.blockStates = {
163
163
  ...this.blockStates,
164
- [t]: k()
164
+ [t]: I()
165
165
  }), this.currentRecommendationId = t;
166
166
  },
167
167
  /**
@@ -229,7 +229,7 @@ const U = () => ({
229
229
  decimalCount: String(e.currencyDecimalCount),
230
230
  decimalSeparator: r(e.currencyDecimalSeparator, ","),
231
231
  thousandSeparator: r(e.currencyThousandSeparator, ".")
232
- }, c = !this.blockStates[t], i = c ? k() : this.blockStates[t];
232
+ }, c = !this.blockStates[t], i = c ? I() : this.blockStates[t];
233
233
  i.recommendationConfigs = {
234
234
  ...i.recommendationConfigs,
235
235
  strategy: e.strategy,
@@ -267,7 +267,7 @@ const U = () => ({
267
267
  * Creates a filter with the first available attribute and operator pre-selected.
268
268
  */
269
269
  createDefaultFilter(t, e) {
270
- const [r] = this.getFilterList, [n] = C(r == null ? void 0 : r.type);
270
+ const [r] = this.getFilterList, [n] = R(r == null ? void 0 : r.type);
271
271
  return {
272
272
  type: "standardFilter",
273
273
  attribute: (r == null ? void 0 : r.value) ?? "",
@@ -384,7 +384,7 @@ const U = () => ({
384
384
  const n = [...e.recommendationConfigs.filters];
385
385
  n[r] = {
386
386
  ...t,
387
- isValid: L(t)
387
+ isValid: x(t)
388
388
  }, e.recommendationConfigs.filters = n;
389
389
  }
390
390
  },
@@ -430,14 +430,7 @@ const U = () => ({
430
430
  * every block's recommendationConfigs across user edits.
431
431
  */
432
432
  hasInvalidBlock() {
433
- return Object.values(this.blockStates).some((t) => !I(t.recommendationConfigs, this));
434
- },
435
- /**
436
- * Per-instance counterpart to `hasInvalidBlock`: the ids of every block
437
- * that fails required-field validation, one drawer row each (SD-147430).
438
- */
439
- invalidBlockIds() {
440
- return Object.entries(this.blockStates).filter(([, t]) => !I(t.recommendationConfigs, this)).map(([t]) => t);
433
+ return Object.values(this.blockStates).some((t) => !L(t.recommendationConfigs, this));
441
434
  },
442
435
  // ====================================================================
443
436
  // Per-Block Product Fetching
@@ -458,7 +451,7 @@ const U = () => ({
458
451
  },
459
452
  async _doFetchProducts() {
460
453
  var p;
461
- const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = r.filters.filter((l) => l.isValid), c = b(n), i = ((p = g().find((l) => l.key === r.strategy)) == null ? void 0 : p.path) || "", o = P(), s = parseInt(r.size) || 6, a = {
454
+ const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = r.filters.filter((l) => l.isValid), c = b(n), i = ((p = g().find((l) => l.key === r.strategy)) == null ? void 0 : p.path) || "", o = G(), s = parseInt(r.size) || 6, a = {
462
455
  locale: r.language,
463
456
  currency: r.currencySettings.value,
464
457
  partnerName: o.partnerName,
@@ -466,9 +459,9 @@ const U = () => ({
466
459
  details: !0,
467
460
  campaignId: o.variationId
468
461
  };
469
- r.strategy === "manualMerchandising" ? a.productId = x(r.productIds) : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), c && (a.filter = c), r.shuffleProducts && (a.shuffle = !0), Object.assign(
462
+ r.strategy === "manualMerchandising" ? a.productId = N(r.productIds) : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), c && (a.filter = c), r.shuffleProducts && (a.shuffle = !0), Object.assign(
470
463
  a,
471
- N(o.partnerName, r.strategy)
464
+ v(o.partnerName, r.strategy)
472
465
  );
473
466
  let f;
474
467
  try {
package/dist/guido.css CHANGED
@@ -1 +1 @@
1
- .gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-b8f24f34] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-eedf7416]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.validation-error-list[data-v-30d2e1f9]{gap:16px}.validation-error-row[data-v-30d2e1f9]{gap:8px;padding:24px;border:1px solid #E1E1E1;border-radius:8px}.validation-error-row__icon[data-v-30d2e1f9]{flex-shrink:0;font-size:24px;line-height:0}.validation-error-row__text[data-v-30d2e1f9]{font-size:13px;line-height:16px;color:#292929;word-break:break-word}.guido-editor__wrapper[data-v-f02fdde0]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-f02fdde0]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-f02fdde0]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}
1
+ .gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-fa75f9c3]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-915d61d5]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-915d61d5]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-915d61d5]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}
@@ -395,8 +395,6 @@ export declare const FeaturesSchema: v.ObjectSchema<{
395
395
  readonly allowlistEnabled: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
396
396
  /** Enable persistent link tracking-id assignment for the click heatmap (opt-in) */
397
397
  readonly linkTrackingIds: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
398
- /** Allow persisting a template that still has validation errors (drawer "Save and Continue" soft-save). Host sets false for transactional + unsubscribe. */
399
- readonly allowSaveWithErrors: v.OptionalSchema<v.BooleanSchema<undefined>, true>;
400
398
  }, undefined>;
401
399
  /**
402
400
  * Default block types available in Stripo
@@ -796,8 +794,6 @@ export declare const GuidoConfigSchema: v.ObjectSchema<{
796
794
  readonly allowlistEnabled: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
797
795
  /** Enable persistent link tracking-id assignment for the click heatmap (opt-in) */
798
796
  readonly linkTrackingIds: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
799
- /** Allow persisting a template that still has validation errors (drawer "Save and Continue" soft-save). Host sets false for transactional + unsubscribe. */
800
- readonly allowSaveWithErrors: v.OptionalSchema<v.BooleanSchema<undefined>, true>;
801
797
  }, undefined>, {}>;
802
798
  /** Block configuration */
803
799
  readonly blocks: v.OptionalSchema<v.ObjectSchema<{
@@ -15,23 +15,7 @@ declare const _default: import("vue").DefineComponent<__VLS_WithDefaults<__VLS_T
15
15
  close: () => void;
16
16
  };
17
17
  hasChanges: import("vue").ComputedRef<boolean>;
18
- saveSilent: () => Promise<{
19
- dynamicContentList: import("@@/Types/generic").DynamicContent[];
20
- compiledHtml: string;
21
- rawHtml: string;
22
- css: string;
23
- ampHtml: string;
24
- ampErrors: string[];
25
- modules: number[];
26
- recommendation: {
27
- campaignUrls: Record<string, string>;
28
- configs: Record<string, string>;
29
- };
30
- unsubscribe: {
31
- status: boolean;
32
- config: number[];
33
- };
34
- } | undefined> | undefined;
18
+ saveSilent: () => Promise<Omit<SavedTemplateDetails, "metadata" | "silent"> | undefined> | undefined;
35
19
  setLoading: (value: boolean) => void;
36
20
  }, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {
37
21
  "dynamic-content:open": (detail: {
@@ -1,20 +1,4 @@
1
1
  declare const _default: import("vue").DefineComponent<{}, {
2
- handleSave: (isSilent: boolean) => Promise<{
3
- dynamicContentList: import("../../../@types/generic.js").DynamicContent[];
4
- compiledHtml: string;
5
- rawHtml: string;
6
- css: string;
7
- ampHtml: string;
8
- ampErrors: string[];
9
- modules: number[];
10
- recommendation: {
11
- campaignUrls: Record<string, string>;
12
- configs: Record<string, string>;
13
- };
14
- unsubscribe: {
15
- status: boolean;
16
- config: number[];
17
- };
18
- } | undefined> | undefined;
2
+ handleSave: (isSilent: boolean) => Promise<Omit<import("../../../@types/stripo.js").SavedTemplateDetails, "metadata" | "silent"> | undefined> | undefined;
19
3
  }, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
20
4
  export default _default;
@@ -1,20 +1,4 @@
1
1
  declare const _default: import("vue").DefineComponent<{}, {
2
- handleSave: (isSilent: boolean) => Promise<{
3
- dynamicContentList: import("../../../@types/generic.js").DynamicContent[];
4
- compiledHtml: string;
5
- rawHtml: string;
6
- css: string;
7
- ampHtml: string;
8
- ampErrors: string[];
9
- modules: number[];
10
- recommendation: {
11
- campaignUrls: Record<string, string>;
12
- configs: Record<string, string>;
13
- };
14
- unsubscribe: {
15
- status: boolean;
16
- config: number[];
17
- };
18
- } | undefined> | undefined;
2
+ handleSave: (isSilent: boolean) => Promise<Omit<import("../../../@types/stripo.js").SavedTemplateDetails, "metadata" | "silent"> | undefined> | undefined;
19
3
  }, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
20
4
  export default _default;
@@ -1,20 +1,4 @@
1
1
  declare const _default: import("vue").DefineComponent<{}, {
2
- handleSave: (isSilent: boolean) => Promise<{
3
- dynamicContentList: import("../../../@types/generic.js").DynamicContent[];
4
- compiledHtml: string;
5
- rawHtml: string;
6
- css: string;
7
- ampHtml: string;
8
- ampErrors: string[];
9
- modules: number[];
10
- recommendation: {
11
- campaignUrls: Record<string, string>;
12
- configs: Record<string, string>;
13
- };
14
- unsubscribe: {
15
- status: boolean;
16
- config: number[];
17
- };
18
- } | undefined> | undefined;
2
+ handleSave: (isSilent: boolean) => Promise<Omit<import("../../../@types/stripo.js").SavedTemplateDetails, "metadata" | "silent"> | undefined> | undefined;
19
3
  }, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
20
4
  export default _default;
@@ -10,11 +10,11 @@ interface Props {
10
10
  status: boolean;
11
11
  titleText: string;
12
12
  }
13
- declare var __VLS_13: {}, __VLS_15: {};
13
+ declare var __VLS_12: {}, __VLS_14: {};
14
14
  type __VLS_Slots = {} & {
15
- headerBottomSlot?: (props: typeof __VLS_13) => any;
15
+ headerBottomSlot?: (props: typeof __VLS_12) => any;
16
16
  } & {
17
- default?: (props: typeof __VLS_15) => any;
17
+ default?: (props: typeof __VLS_14) => any;
18
18
  };
19
19
  declare const __VLS_component: import("vue").DefineComponent<__VLS_WithDefaults<__VLS_TypePropsToOption<Props>, {
20
20
  className: string;
@@ -26,7 +26,6 @@ declare const __VLS_component: import("vue").DefineComponent<__VLS_WithDefaults<
26
26
  cancelOrBackButtonEvent: () => void;
27
27
  onCloseEvent: () => void;
28
28
  primaryButtonEvent: () => void;
29
- secondaryButtonEvent: () => void;
30
29
  }, string, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<Props>, {
31
30
  className: string;
32
31
  size: string;
@@ -99,7 +99,6 @@ export declare const useConfig: () => {
99
99
  autosave: boolean;
100
100
  allowlistEnabled: boolean;
101
101
  linkTrackingIds: boolean;
102
- allowSaveWithErrors: boolean;
103
102
  };
104
103
  blocks: {
105
104
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -234,7 +233,6 @@ export declare const useConfig: () => {
234
233
  autosave: boolean;
235
234
  allowlistEnabled: boolean;
236
235
  linkTrackingIds: boolean;
237
- allowSaveWithErrors: boolean;
238
236
  } | null>;
239
237
  blocks: import("vue").ComputedRef<{
240
238
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -0,0 +1,11 @@
1
+ export declare const isEditorBusy: () => boolean;
2
+ /**
3
+ * Runs `task` once every previously queued task has settled — no two editor
4
+ * read/export/save operations ever overlap. A rejected task propagates to its
5
+ * caller but never wedges the queue.
6
+ */
7
+ export declare const runExclusive: <T>(task: () => Promise<T>) => Promise<T>;
8
+ export declare const useEditorLock: () => {
9
+ runExclusive: <T>(task: () => Promise<T>) => Promise<T>;
10
+ isEditorBusy: () => boolean;
11
+ };