@useinsider/guido 2.0.0-beta.3f24769 → 2.0.0-beta.4178f89

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 (33) hide show
  1. package/dist/@types/config/schemas.js +53 -39
  2. package/dist/components/organisms/email-preview/amp/AmpToggle.vue.js +2 -2
  3. package/dist/components/organisms/header/RightSlot.vue2.js +10 -10
  4. package/dist/composables/useConfig.js +29 -27
  5. package/dist/composables/useSave.js +13 -11
  6. package/dist/extensions/Blocks/Recommendation/constants/layout.js +7 -0
  7. package/dist/extensions/Blocks/Recommendation/controls/cardBackground/index.js +21 -41
  8. package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +48 -53
  9. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +78 -50
  10. package/dist/extensions/Blocks/Recommendation/controls/main/productLayout.js +16 -15
  11. package/dist/extensions/Blocks/Recommendation/controls/spacing/index.js +31 -39
  12. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +17 -14
  13. package/dist/extensions/Blocks/Recommendation/templates/index.js +8 -8
  14. package/dist/extensions/Blocks/Recommendation/templates/vertical/template.js +17 -16
  15. package/dist/extensions/Blocks/Recommendation/utils/filterUtil.js +9 -9
  16. package/dist/extensions/Blocks/Recommendation/utils/preserveTextStyles.js +27 -16
  17. package/dist/extensions/Blocks/Unsubscribe/extension.js +9 -9
  18. package/dist/extensions/Blocks/common-control.js +6 -7
  19. package/dist/guido.css +1 -1
  20. package/dist/src/@types/config/index.d.ts +2 -2
  21. package/dist/src/@types/config/schemas.d.ts +26 -0
  22. package/dist/src/@types/config/types.d.ts +7 -1
  23. package/dist/src/composables/useConfig.d.ts +6 -0
  24. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +1 -0
  25. package/dist/src/extensions/Blocks/Recommendation/constants/layout.d.ts +17 -0
  26. package/dist/src/extensions/Blocks/Recommendation/controls/cardBackground/index.d.ts +0 -10
  27. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +6 -17
  28. package/dist/src/extensions/Blocks/Recommendation/controls/spacing/index.d.ts +0 -5
  29. package/dist/src/extensions/Blocks/common-control.d.ts +1 -1
  30. package/dist/src/stores/config.d.ts +147 -1
  31. package/dist/static/styles/components/button.css.js +1 -1
  32. package/dist/stores/config.js +7 -0
  33. package/package.json +1 -1
@@ -1,13 +1,14 @@
1
1
  import { RecommendationFeedSourceMaps as u, PriceAttributes as c } from "../../../../enums/extensions/recommendationBlock.js";
2
2
  import { useRecommendationApi as p } from "../../../../services/recommendationApi.js";
3
3
  import { useConfigStore as m } from "../../../../stores/config.js";
4
- import { defineStore as d } from "pinia";
4
+ import { defineStore as f } from "pinia";
5
+ import { DEFAULT_CARDS_IN_ROW as d } from "../constants/layout.js";
5
6
  import { generateCompleteFilterQuery as l } from "../utils/filterUtil.js";
6
- const n = p(), f = () => ({
7
+ const s = p(), g = () => ({
7
8
  recommendationCampaignUrls: {},
8
9
  recommendationProducts: [],
9
10
  recommendationConfigs: {
10
- cardsInRow: 3,
11
+ cardsInRow: d,
11
12
  currencySettings: {
12
13
  name: "USD",
13
14
  value: "USD",
@@ -134,8 +135,8 @@ const n = p(), f = () => ({
134
135
  filterSelectionDrawerStatus: !1,
135
136
  filterList: {},
136
137
  filterGroup: 1
137
- }), C = d("guidoRecommendationExtension", {
138
- state: () => f(),
138
+ }), S = f("guidoRecommendationExtension", {
139
+ state: () => g(),
139
140
  getters: {
140
141
  hasFilters: (e) => !!e.recommendationConfigs.filters.length,
141
142
  getFilterGroupCount: (e) => {
@@ -178,13 +179,13 @@ const n = p(), f = () => ({
178
179
  activePredictiveAlgorithms: e,
179
180
  languages: t,
180
181
  currencies: r
181
- } = await n.fetchRecommendationCreateData();
182
+ } = await s.fetchRecommendationCreateData();
182
183
  this.activePredictiveAlgorithms = e, this.languages = t;
183
184
  const [i] = r;
184
185
  this.recommendationConfigs.currencySettings.name = i.text, this.recommendationConfigs.currencySettings.value = i.value, this.currencyList = r, this.filterStatus = !!this.recommendationConfigs.filters.length;
185
186
  },
186
187
  async fetchRecommendationFilters() {
187
- const e = await n.fetchRecommendationFilters();
188
+ const e = await s.fetchRecommendationFilters();
188
189
  this.filterList = e;
189
190
  },
190
191
  addFilterGroup(e) {
@@ -224,13 +225,15 @@ const n = p(), f = () => ({
224
225
  }
225
226
  },
226
227
  addFilter(e) {
227
- const t = [...this.recommendationConfigs.filters], r = t.findLastIndex((i) => i.filterGroup === e.filterGroup);
228
- r !== -1 ? t.splice(r + 1, 0, {
228
+ const t = [...this.recommendationConfigs.filters], i = t.filter(
229
+ (a) => a.filterGroup === e.filterGroup
230
+ ).length + 1, o = t.findLastIndex((a) => a.filterGroup === e.filterGroup);
231
+ o !== -1 ? t.splice(o + 1, 0, {
229
232
  ...e,
230
- filterNumber: r + 2
233
+ filterNumber: i
231
234
  }) : t.push({
232
235
  ...e,
233
- filterNumber: 1
236
+ filterNumber: i
234
237
  }), this.$patch({
235
238
  recommendationConfigs: {
236
239
  filters: t
@@ -241,8 +244,8 @@ const n = p(), f = () => ({
241
244
  return l(this.recommendationConfigs.filters);
242
245
  },
243
246
  async fetchRecommendationProducts() {
244
- var s;
245
- const e = this.recommendationConfigs.filters.filter((a) => a.isValid), t = l(e), r = ((s = u.find((a) => a.key === this.recommendationConfigs.strategy)) == null ? void 0 : s.path) || "", i = m(), o = await n.fetchRecommendationProducts(
247
+ var a;
248
+ const e = this.recommendationConfigs.filters.filter((n) => n.isValid), t = l(e), r = ((a = u.find((n) => n.key === this.recommendationConfigs.strategy)) == null ? void 0 : a.path) || "", i = m(), o = await s.fetchRecommendationProducts(
246
249
  r,
247
250
  {
248
251
  // TODO: Here will be optimized and filled carefully
@@ -263,5 +266,5 @@ const n = p(), f = () => ({
263
266
  }
264
267
  });
265
268
  export {
266
- C as useRecommendationExtensionStore
269
+ S as useRecommendationExtensionStore
267
270
  };
@@ -1,12 +1,12 @@
1
- import { prepareProductRows as s } from "./horizontal/template.js";
2
- import { prepareProductRows as c } from "./vertical/template.js";
3
- const R = 3;
4
- function u(r, o, t = {}) {
1
+ import { DEFAULT_PRODUCTS_PER_ROW as s } from "../constants/layout.js";
2
+ import { prepareProductRows as R } from "./horizontal/template.js";
3
+ import { prepareProductRows as a } from "./vertical/template.js";
4
+ function P(r, o, p = {}) {
5
5
  if (o === "horizontal")
6
- return s(r);
7
- const { productsPerRow: e = R, composition: p } = t;
8
- return c(r, e, p);
6
+ return R(r);
7
+ const { productsPerRow: t = s, composition: e } = p;
8
+ return a(r, t, e);
9
9
  }
10
10
  export {
11
- u as prepareProductRows
11
+ P as prepareProductRows
12
12
  };
@@ -1,6 +1,7 @@
1
- import { DEFAULT_CARD_COMPOSITION as u, spacer as d, createBlockTemplate as R, DEFAULTS as m, getDefaultProducts as I, DEFAULT_CARD_VISIBILITY as L } from "../utils.js";
2
- import { verticalElementRenderer as w } from "./elementRenderer.js";
3
- const E = `
1
+ import { DEFAULT_PRODUCTS_PER_ROW as u } from "../../constants/layout.js";
2
+ import { DEFAULT_CARD_COMPOSITION as d, spacer as m, createBlockTemplate as R, DEFAULTS as I, getDefaultProducts as L, DEFAULT_CARD_VISIBILITY as w } from "../utils.js";
3
+ import { verticalElementRenderer as E } from "./elementRenderer.js";
4
+ const S = `
4
5
  <tr class="recommendation-product-row">
5
6
  <td>
6
7
  <table width="100%" height="100%" cellpadding="0" cellspacing="0" border="0" class="product-card-wrapper">
@@ -10,7 +11,7 @@ const E = `
10
11
  </table>
11
12
  </td>
12
13
  </tr>
13
- `, S = `
14
+ `, b = `
14
15
  <tr
15
16
  class="recommendation-attribute-row"
16
17
  data-attribute-type="{-{-ATTR_TYPE-}-}"
@@ -18,15 +19,15 @@ const E = `
18
19
  {-{-DISPLAY_STYLE-}-}>
19
20
  {-{-CELLS-}-}
20
21
  </tr>
21
- `, b = 3;
22
- function _(r, e, o, n = u) {
22
+ `;
23
+ function _(r, e, o, n = d) {
23
24
  const c = (100 / e).toFixed(2);
24
25
  return n.filter((t) => o[t]).map((t) => {
25
- const l = L[t] ?? !0, i = l ? "" : 'style="display: none;"', a = r.map((p) => {
26
+ const l = w[t] ?? !0, i = l ? "" : 'style="display: none;"', a = r.map((p) => {
26
27
  const T = o[t];
27
28
  return T(p).replace("<td", `<td width="${c}%"`);
28
29
  }).join("");
29
- return S.replace("{-{-ATTR_TYPE-}-}", t).replace("{-{-VISIBILITY-}-}", l ? "1" : "0").replace("{-{-DISPLAY_STYLE-}-}", i).replace("{-{-CELLS-}-}", a);
30
+ return b.replace("{-{-ATTR_TYPE-}-}", t).replace("{-{-VISIBILITY-}-}", l ? "1" : "0").replace("{-{-DISPLAY_STYLE-}-}", i).replace("{-{-CELLS-}-}", a);
30
31
  }).join("");
31
32
  }
32
33
  function A(r, e, o, n) {
@@ -39,22 +40,22 @@ function A(r, e, o, n) {
39
40
  e,
40
41
  o,
41
42
  n
42
- ), a = E.replace("{-{-ATTRIBUTE_ROWS-}-}", i);
43
- return l > 0 ? d + a : a;
43
+ ), a = S.replace("{-{-ATTRIBUTE_ROWS-}-}", i);
44
+ return l > 0 ? m + a : a;
44
45
  }).join("");
45
46
  }
46
47
  function D(r, e, o) {
47
- return A(r, e, w, o);
48
+ return A(r, e, E, o);
48
49
  }
49
- function Y() {
50
+ function U() {
50
51
  const r = R("vertical"), e = D(
51
- I(),
52
- b
52
+ L(),
53
+ u
53
54
  );
54
- return r.replace("{-{-TITLE-}-}", m.TITLE).replace("{-{-PRODUCT_ROWS-}-}", e);
55
+ return r.replace("{-{-TITLE-}-}", I.TITLE).replace("{-{-PRODUCT_ROWS-}-}", e);
55
56
  }
56
57
  export {
57
- Y as getDefaultTemplate,
58
+ U as getDefaultTemplate,
58
59
  D as prepareProductRows,
59
60
  _ as prepareVerticalAttributeRows,
60
61
  A as prepareVerticalProductRows
@@ -1,28 +1,28 @@
1
1
  function l(t) {
2
2
  if (t.length === 0)
3
3
  return "";
4
- const o = t.sort((r, e) => r.filterNumber - e.filterNumber), n = o.map((r) => `[${r.attribute}][${r.operatorReplace}][${r.value}]`), [s, ...p] = n;
5
- let u = s;
4
+ const o = t.sort((r, e) => r.filterNumber - e.filterNumber), n = o.map((r) => `[${r.attribute}][${r.operatorReplace}][${r.value}]`), [i, ...p] = n;
5
+ let u = i;
6
6
  for (let r = 0; r < p.length; r++) {
7
7
  const e = o[r + 1].innerGroupOperator;
8
8
  u += `${e}${p[r]}`;
9
9
  }
10
10
  return `(${u})`;
11
11
  }
12
- function m(t) {
12
+ function f(t) {
13
13
  if (!t || t.length === 0)
14
14
  return "";
15
- const o = t.reduce((r, e) => (r[e.filterGroup] || (r[e.filterGroup] = []), r[e.filterGroup].push(e), r), {}), n = Object.keys(o).map(Number).sort((r, e) => r - e), s = n.map((r) => {
15
+ const o = t.reduce((r, e) => (r[e.filterGroup] || (r[e.filterGroup] = []), r[e.filterGroup].push(e), r), {}), n = Object.keys(o).map(Number).sort((r, e) => r - e), i = n.map((r) => {
16
16
  const e = o[r];
17
17
  return l(e);
18
- }), [p, ...u] = s;
19
- let i = p;
18
+ }), [p, ...u] = i;
19
+ let s = p;
20
20
  for (let r = 0; r < u.length; r++) {
21
21
  const e = n[r + 1], c = o[e][0].outerGroupOperator;
22
- i += `${c}${u[r]}`;
22
+ s += `${c}${u[r]}`;
23
23
  }
24
- return console.debug("🎉 Complete query generated:", i), i.trim();
24
+ return s.trim();
25
25
  }
26
26
  export {
27
- m as generateCompleteFilterQuery
27
+ f as generateCompleteFilterQuery
28
28
  };
@@ -1,25 +1,36 @@
1
- function a(n) {
2
- return "getInnerHTML" in n && typeof n.getInnerHTML == "function" ? n.getInnerHTML() : "innerHTML" in n ? n.innerHTML : "";
1
+ function p(t) {
2
+ const r = {
3
+ "&": "&amp;",
4
+ "<": "&lt;",
5
+ ">": "&gt;",
6
+ '"': "&quot;",
7
+ "'": "&#39;"
8
+ };
9
+ return t.replace(/[&<>"']/g, (n) => r[n]);
3
10
  }
4
- function H(n, t) {
5
- if (!n)
6
- return t;
7
- const r = a(n);
8
- if (!r || r.trim() === "" || !/<(strong|em|u|s|b|i)\b/i.test(r))
9
- return t;
10
- const i = [], s = [];
11
- let o = r.trim();
11
+ function m(t) {
12
+ return "getInnerHTML" in t && typeof t.getInnerHTML == "function" ? t.getInnerHTML() : "innerHTML" in t ? t.innerHTML : "";
13
+ }
14
+ function T(t, r) {
15
+ const n = p(r);
16
+ if (!t)
17
+ return n;
18
+ const e = m(t);
19
+ if (!e || e.trim() === "" || !/<(strong|em|u|s|b|i)\b/i.test(e))
20
+ return n;
21
+ const i = [], o = [];
22
+ let c = e.trim();
12
23
  for (; ; ) {
13
- const u = o.match(/^<(strong|em|u|s|b|i)(\s[^>]*)?>(.*)$/is);
24
+ const u = c.match(/^<(strong|em|u|s|b|i)(\s[^>]*)?>(.*)$/is);
14
25
  if (!u)
15
26
  break;
16
- const [, e, f = "", g] = u, c = new RegExp(`</${e}>$`, "i");
17
- if (!c.test(g))
27
+ const [, s, f = "", g] = u, a = new RegExp(`</${s}>$`, "i");
28
+ if (!a.test(g))
18
29
  break;
19
- i.push(`<${e}${f}>`), s.unshift(`</${e}>`), o = g.replace(c, "").trim();
30
+ i.push(`<${s}${f}>`), o.unshift(`</${s}>`), c = g.replace(a, "").trim();
20
31
  }
21
- return i.length > 0 ? i.join("") + t + s.join("") : t;
32
+ return i.length > 0 ? i.join("") + n + o.join("") : n;
22
33
  }
23
34
  export {
24
- H as preserveTextStyles
35
+ T as preserveTextStyles
25
36
  };
@@ -1,21 +1,21 @@
1
1
  import { ExtensionBuilder as e } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
2
2
  import { UnsubscribeBlock as i } from "./block.js";
3
3
  import { UnsubscribeControl as t } from "./control.js";
4
- import { PreviewUIElement as o } from "./elements/preview.js";
5
- import { UnsubscribeIconsRegistry as r } from "./iconsRegistry.js";
6
- import { SettingsPanel as s } from "./settingsPanel.js";
4
+ import { PreviewUIElement as s } from "./elements/preview.js";
5
+ import { UnsubscribeIconsRegistry as o } from "./iconsRegistry.js";
6
+ import { SettingsPanel as r } from "./settingsPanel.js";
7
7
  import n from "./styles.css.js";
8
- import { UnsubscribeTagRegistry as l } from "./tagRegistry.js";
9
- const f = new e().addBlock(i).withSettingsPanelRegistry(s).addControl(t).addUiElement(o).addStyles(n).withLocalization({
8
+ import { UnsubscribeTagRegistry as c } from "./tagRegistry.js";
9
+ const g = new e().addBlock(i).withSettingsPanelRegistry(r).addControl(t).addUiElement(s).addStyles(n).withLocalization({
10
10
  en: {
11
- "Unsubscribe Block": "Unsubscribe Block",
12
- "Unsubscribe Block Description": "Add an unsubscribe link to your email",
11
+ "Unsubscribe Block": "Unsubscribe",
12
+ "Unsubscribe Block Description": "Unsubscribe lets you add an Unsubscribe Link to direct users to opt out of receiving your messages.",
13
13
  "Select Template": "Select Template",
14
14
  "Unsubscribe Template": "Unsubscribe Template",
15
15
  Showing: "Showing",
16
16
  of: "of"
17
17
  }
18
- }).withUiElementTagRegistry(l).withIconsRegistry(r).build();
18
+ }).withUiElementTagRegistry(c).withIconsRegistry(o).build();
19
19
  export {
20
- f as default
20
+ g as default
21
21
  };
@@ -1,12 +1,12 @@
1
1
  var c = Object.defineProperty;
2
2
  var I = (a, r, e) => r in a ? c(a, r, { enumerable: !0, configurable: !0, writable: !0, value: e }) : a[r] = e;
3
- var l = (a, r, e) => I(a, typeof r != "symbol" ? r + "" : r, e);
3
+ var u = (a, r, e) => I(a, typeof r != "symbol" ? r + "" : r, e);
4
4
  import { Control as O, UIElementType as t, UEAttr as $ } from "../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
5
5
  class _ extends O {
6
6
  constructor() {
7
7
  super(...arguments);
8
- l(this, "currentNode");
9
- l(this, "lastBlockInstanceId", null);
8
+ u(this, "currentNode");
9
+ u(this, "lastBlockInstanceId", null);
10
10
  }
11
11
  getContainer() {
12
12
  var e;
@@ -52,10 +52,9 @@ class _ extends O {
52
52
  const T = o !== this.lastBlockInstanceId;
53
53
  return T ? (this.currentNode && e(this.currentNode), n(), this.lastBlockInstanceId = o) : n(), T;
54
54
  }
55
- _GuLabel({ text: e, name: n = "", position: E = "top" }) {
55
+ _GuLabel({ text: e, name: n = "" }) {
56
56
  return `
57
57
  <${t.LABEL}
58
- style="${E === "top" ? "margin-bottom: 8px;" : ""}"
59
58
  ${$.LABEL.text}="${e}"
60
59
  ${$.LABEL.name}="${n || `${e} Label`}">
61
60
  </${t.LABEL}>
@@ -170,9 +169,9 @@ class _ extends O {
170
169
  _GuOrderable(e, n) {
171
170
  let E = "";
172
171
  n.forEach((T) => {
173
- const u = $.ORDERABLE_ITEM && "name" in $.ORDERABLE_ITEM ? $.ORDERABLE_ITEM.name : "name";
172
+ const l = $.ORDERABLE_ITEM && "name" in $.ORDERABLE_ITEM ? $.ORDERABLE_ITEM.name : "name";
174
173
  E += `
175
- <${t.ORDERABLE_ITEM} ${u}="${T.key}">
174
+ <${t.ORDERABLE_ITEM} ${l}="${T.key}">
176
175
  ${T.content}
177
176
  </${t.ORDERABLE_ITEM}>
178
177
  `;
package/dist/guido.css CHANGED
@@ -1 +1 @@
1
- .gap-16[data-v-6562e38c],.gap-16[data-v-1ccb6d4a]{gap:16px}[data-v-06e6f7a7] .in-button-v2__wrapper{line-height:0}[data-v-b5997368] .in-segments-wrapper .in-tooltip-wrapper__box{text-align:left}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history-wrapper[data-v-52a77eec]{gap:8px}.view-options-wrapper[data-v-d405ca59]{position:relative;display:inline-block}.new-tag[data-v-d405ca59]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-d405ca59] .guido__verion-history-view-option-selection-desktop svg,[data-v-d405ca59] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-d405ca59] .in-segments-wrapper__button_selected,[data-v-d405ca59] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-d405ca59] .in-tooltip-wrapper__icon{cursor:pointer}.view-options-wrapper[data-v-195ab6d4]{position:relative;display:inline-block}.new-tag[data-v-195ab6d4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-195ab6d4] .guido__view-option-selection-desktop svg,[data-v-195ab6d4] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-195ab6d4] .in-segments-wrapper__button_selected,[data-v-195ab6d4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-195ab6d4] .in-tooltip-wrapper__icon{cursor:pointer}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-890b5336]{position:relative;width:100%;height:calc(100vh - 128px)}.guido-editor__container[data-v-890b5336]{width:100%;height:calc(100vh - 128px)}.guido-editor__no-header[data-v-890b5336]{height:calc(100vh - 75px)}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-a86fc486]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-a86fc486]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-a86fc486]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-a86fc486]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-a86fc486]{object-fit:cover;transform:scale(1)}[data-v-bb3bb07c] .guido__verion-history-view-option-selection-desktop svg,[data-v-bb3bb07c] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-bb3bb07c] .in-segments-wrapper__button_selected,[data-v-bb3bb07c] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-7a09985c]{gap:16px}[data-v-c2adc57d] .in-progress-wrapper__progress p span:last-child{display:none!important}.desktop-preview-container[data-v-2dd60b0c],[data-v-2dd60b0c] .desktop-preview-container .in-container{min-height:720px!important;height:100%}.cropped-text[data-v-4b876c1b]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}[data-v-d3c52b44] .vueperslides__bullets,[data-v-dd1a237a] .vueperslides__bullets{pointer-events:none!important}[data-v-dd1a237a] .vueperslides__parallax-wrapper{height:110px!important}[data-v-a408dcea] .vueperslides__bullets{pointer-events:none!important}[data-v-a408dcea] .vueperslides__parallax-wrapper{height:110px!important}
1
+ .gap-16[data-v-6562e38c],.gap-16[data-v-1ccb6d4a]{gap:16px}[data-v-06e6f7a7] .in-button-v2__wrapper{line-height:0}[data-v-5196584c] .in-segments-wrapper .in-tooltip-wrapper__box{text-align:left}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history-wrapper[data-v-52a77eec]{gap:8px}.view-options-wrapper[data-v-d405ca59]{position:relative;display:inline-block}.new-tag[data-v-d405ca59]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-d405ca59] .guido__verion-history-view-option-selection-desktop svg,[data-v-d405ca59] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-d405ca59] .in-segments-wrapper__button_selected,[data-v-d405ca59] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-d405ca59] .in-tooltip-wrapper__icon{cursor:pointer}.view-options-wrapper[data-v-195ab6d4]{position:relative;display:inline-block}.new-tag[data-v-195ab6d4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-195ab6d4] .guido__view-option-selection-desktop svg,[data-v-195ab6d4] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-195ab6d4] .in-segments-wrapper__button_selected,[data-v-195ab6d4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-195ab6d4] .in-tooltip-wrapper__icon{cursor:pointer}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-890b5336]{position:relative;width:100%;height:calc(100vh - 128px)}.guido-editor__container[data-v-890b5336]{width:100%;height:calc(100vh - 128px)}.guido-editor__no-header[data-v-890b5336]{height:calc(100vh - 75px)}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-a86fc486]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-a86fc486]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-a86fc486]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-a86fc486]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-a86fc486]{object-fit:cover;transform:scale(1)}[data-v-bb3bb07c] .guido__verion-history-view-option-selection-desktop svg,[data-v-bb3bb07c] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-bb3bb07c] .in-segments-wrapper__button_selected,[data-v-bb3bb07c] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-7a09985c]{gap:16px}[data-v-c2adc57d] .in-progress-wrapper__progress p span:last-child{display:none!important}.desktop-preview-container[data-v-2dd60b0c],[data-v-2dd60b0c] .desktop-preview-container .in-container{min-height:720px!important;height:100%}.cropped-text[data-v-4b876c1b]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}[data-v-d3c52b44] .vueperslides__bullets,[data-v-dd1a237a] .vueperslides__bullets{pointer-events:none!important}[data-v-dd1a237a] .vueperslides__parallax-wrapper{height:110px!important}[data-v-a408dcea] .vueperslides__bullets{pointer-events:none!important}[data-v-a408dcea] .vueperslides__parallax-wrapper{height:110px!important}
@@ -7,8 +7,8 @@
7
7
  * - Default values for optional configuration
8
8
  * - Validation utilities
9
9
  */
10
- export { MessageType, ProductType, GuidoConfigSchema, IdentitySchema, PartnerSchema, TemplateSchema, EditorSchema, UISchema, FeaturesSchema, BlocksSchema, CompilerSchema, DynamicContentSchema, EmailHeaderSchema, DefaultBlockTypeSchema, CustomBlockTypeSchema, CompilerRuleSchema, CompilerRuleTypeSchema, ReplaceRuleSchema, RegexRuleSchema, RemoveRuleSchema, CustomRuleSchema, } from './schemas';
11
- export type { GuidoConfig, GuidoConfigInput, IdentityConfig, IdentityConfigInput, PartnerConfig, PartnerConfigInput, TemplateConfig, TemplateConfigInput, EditorConfig, EditorConfigInput, UIConfig, UIConfigInput, FeaturesConfig, FeaturesConfigInput, BlocksConfig, BlocksConfigInput, CompilerConfig, CompilerConfigInput, EmailHeader, DynamicContent, DefaultBlockType, CustomBlockType, BlockType, FeatureName, CompilerRule, ReplaceRule, RegexRule, RemoveRule, CustomRule, DeepPartial, ConfigOverrides, } from './types';
10
+ export { MessageType, ProductType, GuidoConfigSchema, IdentitySchema, PartnerSchema, TemplateSchema, EditorSchema, UISchema, FeaturesSchema, BlocksSchema, CompilerSchema, CallbacksSchema, DynamicContentSchema, EmailHeaderSchema, DefaultBlockTypeSchema, CustomBlockTypeSchema, CompilerRuleSchema, CompilerRuleTypeSchema, ReplaceRuleSchema, RegexRuleSchema, RemoveRuleSchema, CustomRuleSchema, } from './schemas';
11
+ export type { GuidoConfig, GuidoConfigInput, IdentityConfig, IdentityConfigInput, PartnerConfig, PartnerConfigInput, TemplateConfig, TemplateConfigInput, EditorConfig, EditorConfigInput, UIConfig, UIConfigInput, FeaturesConfig, FeaturesConfigInput, BlocksConfig, BlocksConfigInput, CompilerConfig, CompilerConfigInput, CallbacksConfig, CallbacksConfigInput, ExternalValidationHandler, EmailHeader, DynamicContent, DefaultBlockType, CustomBlockType, BlockType, FeatureName, CompilerRule, ReplaceRule, RegexRule, RemoveRule, CustomRule, DeepPartial, ConfigOverrides, } from './types';
12
12
  export { DEFAULT_EMAIL_HEADER, DEFAULT_TEMPLATE, DEFAULT_EDITOR, DEFAULT_UI, DEFAULT_FEATURES, DEFAULT_BLOCKS, DEFAULT_COMPILER, DEFAULT_PRODUCT_TYPE, DEFAULT_MESSAGE_TYPE, DEFAULT_USERNAME, EDITOR_TYPE, TEST_PARTNERS, isTestPartner, } from './defaults';
13
13
  export { validateConfig, parseConfig, parseConfigSafe, getValidationErrors, isValidConfig, validateIdentity, validatePartner, } from './validator';
14
14
  export type { ValidationResult, ValidationError, } from './validator';
@@ -5,7 +5,14 @@
5
5
  * All types are inferred from these schemas to ensure single source of truth.
6
6
  * @module @types/config/schemas
7
7
  */
8
+ import type { SavedTemplateDetails } from '../stripo';
8
9
  import * as v from 'valibot';
10
+ /**
11
+ * Handler function for external validation before save
12
+ * @param data - The template details to validate
13
+ * @returns Promise<boolean> - true if valid, false to cancel save
14
+ */
15
+ export type ExternalValidationHandler = (data: SavedTemplateDetails) => Promise<boolean>;
9
16
  /**
10
17
  * Message type constants for email templates
11
18
  */
@@ -346,6 +353,16 @@ export declare const CompilerSchema: v.ObjectSchema<{
346
353
  /** Skip default compiler rules */
347
354
  readonly ignoreDefaultRules: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
348
355
  }, undefined>;
356
+ /**
357
+ * Callbacks configuration - event handlers and hooks
358
+ */
359
+ export declare const CallbacksSchema: v.ObjectSchema<{
360
+ /**
361
+ * External validation handler called before save completes.
362
+ * Return false to cancel the save operation.
363
+ */
364
+ readonly externalValidation: v.OptionalSchema<v.CustomSchema<ExternalValidationHandler, v.ErrorMessage<v.CustomIssue> | undefined>, undefined>;
365
+ }, undefined>;
349
366
  /**
350
367
  * Complete Guido configuration schema
351
368
  *
@@ -358,6 +375,7 @@ export declare const CompilerSchema: v.ObjectSchema<{
358
375
  * - features: Feature toggles
359
376
  * - blocks: Block configuration
360
377
  * - compiler: HTML compilation
378
+ * - callbacks: Event handlers and hooks
361
379
  */
362
380
  export declare const GuidoConfigSchema: v.ObjectSchema<{
363
381
  /** Identity configuration (required) */
@@ -510,4 +528,12 @@ export declare const GuidoConfigSchema: v.ObjectSchema<{
510
528
  /** Skip default compiler rules */
511
529
  readonly ignoreDefaultRules: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
512
530
  }, undefined>, {}>;
531
+ /** Callbacks and event handlers */
532
+ readonly callbacks: v.OptionalSchema<v.ObjectSchema<{
533
+ /**
534
+ * External validation handler called before save completes.
535
+ * Return false to cancel the save operation.
536
+ */
537
+ readonly externalValidation: v.OptionalSchema<v.CustomSchema<ExternalValidationHandler, v.ErrorMessage<v.CustomIssue> | undefined>, undefined>;
538
+ }, undefined>, {}>;
513
539
  }, undefined>;
@@ -5,7 +5,7 @@
5
5
  * This ensures type definitions are always in sync with validation.
6
6
  * @module @types/config/types
7
7
  */
8
- import type { GuidoConfigSchema, IdentitySchema, PartnerSchema, TemplateSchema, EditorSchema, UISchema, FeaturesSchema, BlocksSchema, CompilerSchema, DynamicContentSchema, EmailHeaderSchema, CompilerRuleSchema, ReplaceRuleSchema, RegexRuleSchema, RemoveRuleSchema, CustomRuleSchema, DefaultBlockTypeSchema, CustomBlockTypeSchema } from './schemas';
8
+ import type { GuidoConfigSchema, IdentitySchema, PartnerSchema, TemplateSchema, EditorSchema, UISchema, FeaturesSchema, BlocksSchema, CompilerSchema, CallbacksSchema, DynamicContentSchema, EmailHeaderSchema, CompilerRuleSchema, ReplaceRuleSchema, RegexRuleSchema, RemoveRuleSchema, CustomRuleSchema, DefaultBlockTypeSchema, CustomBlockTypeSchema, ExternalValidationHandler } from './schemas';
9
9
  import type * as v from 'valibot';
10
10
  /**
11
11
  * Complete validated Guido configuration.
@@ -41,6 +41,10 @@ export type FeaturesConfig = v.InferOutput<typeof FeaturesSchema>;
41
41
  export type BlocksConfig = v.InferOutput<typeof BlocksSchema>;
42
42
  /** Compiler configuration (custom rules, ignore defaults) */
43
43
  export type CompilerConfig = v.InferOutput<typeof CompilerSchema>;
44
+ /** Callbacks configuration (event handlers and hooks) */
45
+ export type CallbacksConfig = v.InferOutput<typeof CallbacksSchema>;
46
+ /** Re-export ExternalValidationHandler for convenience */
47
+ export type { ExternalValidationHandler };
44
48
  /** Email header configuration (senderName, subject) */
45
49
  export type EmailHeader = v.InferOutput<typeof EmailHeaderSchema>;
46
50
  /** Dynamic content item */
@@ -85,6 +89,8 @@ export type FeaturesConfigInput = v.InferInput<typeof FeaturesSchema>;
85
89
  export type BlocksConfigInput = v.InferInput<typeof BlocksSchema>;
86
90
  /** Input type for compiler configuration */
87
91
  export type CompilerConfigInput = v.InferInput<typeof CompilerSchema>;
92
+ /** Input type for callbacks configuration */
93
+ export type CallbacksConfigInput = v.InferInput<typeof CallbacksSchema>;
88
94
  /** Default Stripo block types */
89
95
  export type DefaultBlockType = v.InferOutput<typeof DefaultBlockTypeSchema>;
90
96
  /** Custom Guido block types */
@@ -91,6 +91,9 @@ export declare const useConfig: () => {
91
91
  })[];
92
92
  ignoreDefaultRules: boolean;
93
93
  };
94
+ callbacks: {
95
+ externalValidation?: import("@@/Types/config").ExternalValidationHandler | undefined;
96
+ };
94
97
  } | null>;
95
98
  initialized: import("vue").Ref<boolean>;
96
99
  identity: import("vue").ComputedRef<{
@@ -177,6 +180,9 @@ export declare const useConfig: () => {
177
180
  })[];
178
181
  ignoreDefaultRules: boolean;
179
182
  } | null>;
183
+ callbacks: import("vue").ComputedRef<{
184
+ externalValidation?: import("@@/Types/config").ExternalValidationHandler | undefined;
185
+ } | null>;
180
186
  templateId: import("vue").ComputedRef<string>;
181
187
  userId: import("vue").ComputedRef<string>;
182
188
  variationId: import("vue").ComputedRef<string>;
@@ -9,3 +9,4 @@
9
9
  export { RecommendationBlockId } from './blockIds';
10
10
  export { RecommendationControlId } from './controlIds';
11
11
  export { CONTAINER_SELECTOR, ATTR_PRODUCT_IMAGE, ATTR_PRODUCT_NAME, ATTR_PRODUCT_PRICE, ATTR_PRODUCT_OLD_PRICE, ATTR_PRODUCT_OMNIBUS_PRICE, ATTR_PRODUCT_OMNIBUS_DISCOUNT, ATTR_PRODUCT_BUTTON, } from './selectors';
12
+ export { DEFAULT_PRODUCTS_PER_ROW, DEFAULT_CARDS_IN_ROW, MAX_PRODUCT_COUNT, MIN_PRODUCT_COUNT, MAX_PRODUCTS_PER_ROW, MIN_PRODUCTS_PER_ROW, } from './layout';
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Layout-related constants for Recommendation block
3
+ *
4
+ * Centralizes magic numbers for product grid/layout configuration
5
+ */
6
+ /** Default number of products displayed per row in vertical layout */
7
+ export declare const DEFAULT_PRODUCTS_PER_ROW = 3;
8
+ /** Default number of cards in a row (used in store initialization) */
9
+ export declare const DEFAULT_CARDS_IN_ROW = 3;
10
+ /** Maximum number of products that can be displayed */
11
+ export declare const MAX_PRODUCT_COUNT = 9;
12
+ /** Minimum number of products that can be displayed */
13
+ export declare const MIN_PRODUCT_COUNT = 1;
14
+ /** Maximum number of products per row in vertical layout */
15
+ export declare const MAX_PRODUCTS_PER_ROW = 4;
16
+ /** Minimum number of products per row in vertical layout */
17
+ export declare const MIN_PRODUCTS_PER_ROW = 1;
@@ -1,4 +1,3 @@
1
- import type { Orientation } from '@@/Types/recommendation';
2
1
  import { ImmutableHtmlNode } from '@stripoinc/ui-editor-extensions';
3
2
  import { CommonControl } from '../../../common-control';
4
3
  export declare const CARD_BACKGROUND_COLOR_CONTROL_ID = "recommendation-card-background-color-control";
@@ -12,15 +11,6 @@ export declare class CardBackgroundColorControl extends CommonControl {
12
11
  onRender(): void;
13
12
  onTemplateNodeUpdated(node: ImmutableHtmlNode): void;
14
13
  _setFormValues(): void;
15
- /**
16
- * Gets the block element - either currentNode itself or as a descendant
17
- * The currentNode could BE the block element or contain it
18
- */
19
- _getBlockElement(): ImmutableHtmlNode | null;
20
- /**
21
- * Gets the current layout orientation from the block's data attribute
22
- */
23
- _getCurrentLayout(): Orientation;
24
14
  /**
25
15
  * Gets the appropriate selector based on layout
26
16
  * Vertical: .product-card-segment (inner table per product cell)
@@ -1,20 +1,3 @@
1
- /**
2
- * Main Recommendation Block Control
3
- *
4
- * This is a coordinator control that composes all recommendation configuration
5
- * sub-controls into a single settings panel. It handles:
6
- * - Initial API data fetching
7
- * - Store subscriptions for product refresh
8
- * - Coordinating lifecycle of sub-controls
9
- *
10
- * Sub-controls are also exported individually for flexibility:
11
- * - AlgorithmControl: Strategy and product IDs
12
- * - LocaleControl: Language selection
13
- * - CurrencyControl: Currency formatting settings
14
- * - ProductLayoutControl: Product count and grid layout
15
- * - FiltersControl: Filter selection
16
- * - ShuffleControl: Product shuffle toggle
17
- */
18
1
  import { CommonControl } from '../../../common-control';
19
2
  import { AlgorithmControl, ALGORITHM_CONTROL_ID } from './algorithm';
20
3
  import { CurrencyControl, CURRENCY_CONTROL_ID } from './currency';
@@ -47,8 +30,14 @@ export declare class RecommendationBlockControl extends CommonControl {
47
30
  * Each sub-control manages its own form values and event listeners
48
31
  */
49
32
  _initializeSubControls(): void;
33
+ /**
34
+ * Debounced product fetch to prevent rapid API calls during config changes
35
+ */
36
+ private _debouncedFetchProducts;
50
37
  /**
51
38
  * Listen to store changes that require product refresh
39
+ * Only triggers for meaningful config changes (size, strategy, filters, etc.)
40
+ * Uses debounce to prevent rapid API calls
52
41
  */
53
42
  _listenStateUpdates(): void;
54
43
  }
@@ -1,4 +1,3 @@
1
- import type { Orientation } from '@@/Types/recommendation';
2
1
  import { ImmutableHtmlNode } from '@stripoinc/ui-editor-extensions';
3
2
  import { CommonControl } from '../../../common-control';
4
3
  export declare const SPACING_CONTROL_ID = "recommendation-spacing-control";
@@ -14,10 +13,6 @@ export declare class SpacingControl extends CommonControl {
14
13
  getTemplate(): string;
15
14
  onRender(): void;
16
15
  onTemplateNodeUpdated(node: ImmutableHtmlNode): void;
17
- /**
18
- * Gets the current layout orientation from the block's data attribute
19
- */
20
- _getCurrentLayout(): Orientation;
21
16
  /**
22
17
  * Updates column spacing visibility based on layout orientation
23
18
  * Column spacing is hidden for horizontal layout (products are stacked vertically)
@@ -75,7 +75,7 @@ export declare abstract class CommonControl extends Control {
75
75
  * @returns true if block instance changed, false otherwise
76
76
  */
77
77
  protected handleBlockInstanceChange(syncFunction: (node: ImmutableHtmlNode) => void, updateUI: () => void, blockInstanceIdAttribute?: string): boolean;
78
- _GuLabel({ text, name, position }: LabelProps): string;
78
+ _GuLabel({ text, name }: LabelProps): string;
79
79
  _GuToggle(name: string): string;
80
80
  _GuSelectItem({ text, value }: {
81
81
  text: string;