@useinsider/guido 3.18.2-beta.3eec9b0 → 3.18.2-beta.4d2b065

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 (57) hide show
  1. package/README.md +21 -23
  2. package/dist/@types/config/schemas.js +59 -51
  3. package/dist/components/Guido.vue.js +4 -4
  4. package/dist/components/Guido.vue2.js +55 -53
  5. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +7 -7
  6. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +53 -49
  7. package/dist/components/organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue.js +18 -0
  8. package/dist/components/organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue2.js +25 -0
  9. package/dist/components/organisms/extensions/recommendation/RemoveStrategyModal.vue2.js +24 -22
  10. package/dist/components/organisms/onboarding/OnboardingWrapper.vue2.js +28 -24
  11. package/dist/components/organisms/onboarding/RecommendationLegacyStrategyOnboarding.vue.js +21 -0
  12. package/dist/components/organisms/onboarding/RecommendationLegacyStrategyOnboarding.vue2.js +46 -0
  13. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.js +21 -0
  14. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue2.js +46 -0
  15. package/dist/composables/useCustomInterfaceAppearance.js +46 -42
  16. package/dist/composables/useGuidoStateBridge.js +24 -29
  17. package/dist/composables/useLegacyStrategyConversion.js +61 -0
  18. package/dist/composables/useStripo.js +7 -7
  19. package/dist/enums/extensions/recommendationBlock.js +40 -31
  20. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +77 -76
  21. package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +72 -28
  22. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +45 -44
  23. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +110 -46
  24. package/dist/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.js +42 -0
  25. package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +7 -7
  26. package/dist/guido.css +1 -1
  27. package/dist/library.js +13 -15
  28. package/dist/services/recommendationApi.js +46 -37
  29. package/dist/src/@types/config/schemas.d.ts +16 -0
  30. package/dist/src/components/organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue.d.ts +2 -0
  31. package/dist/src/components/organisms/onboarding/RecommendationLegacyStrategyOnboarding.vue.d.ts +2 -0
  32. package/dist/src/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.d.ts +2 -0
  33. package/dist/src/composables/useConfig.d.ts +4 -0
  34. package/dist/src/composables/useGuidoStateBridge.d.ts +7 -11
  35. package/dist/src/composables/useLegacyStrategyConversion.d.ts +3 -0
  36. package/dist/src/enums/extensions/recommendationBlock.d.ts +5 -1
  37. package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +2 -0
  38. package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +4 -0
  39. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +70 -1
  40. package/dist/src/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.d.ts +32 -0
  41. package/dist/src/library.d.ts +0 -2
  42. package/dist/src/public/trackingIds.d.ts +2 -6
  43. package/dist/src/services/recommendationApi.d.ts +2 -1
  44. package/dist/src/stores/config.d.ts +322 -0
  45. package/dist/src/stores/editor.d.ts +0 -25
  46. package/dist/src/stores/guido-email-editor.d.ts +27 -27
  47. package/dist/src/stores/onboarding.d.ts +808 -10
  48. package/dist/static/assets/icons/filled-arrow-rising.svg.js +5 -0
  49. package/dist/static/assets/icons/line-info.svg.js +5 -0
  50. package/dist/static/styles/components/recommendation-strategy.css.js +70 -5
  51. package/dist/stores/config.js +74 -60
  52. package/dist/stores/editor.js +0 -4
  53. package/dist/stores/guido-email-editor.js +4 -0
  54. package/dist/stores/onboarding.js +46 -36
  55. package/package.json +1 -5
  56. package/dist/public/editorState.js +0 -4
  57. package/dist/src/public/editorState.d.ts +0 -14
@@ -1,59 +1,54 @@
1
- import { useActionsApi as v } from "./useActionsApi.js";
2
- import { useEditorLock as C } from "./useEditorLock.js";
1
+ import { useActionsApi as b } from "./useActionsApi.js";
2
+ import { useEditorLock as v } from "./useEditorLock.js";
3
3
  import { useConfigStore as T } from "../stores/config.js";
4
4
  import { useEditorStore as w } from "../stores/editor.js";
5
5
  import { useGuidoEmailEditorStore as y } from "../stores/guido-email-editor.js";
6
- import { watch as c, onUnmounted as z } from "vue";
7
- const B = 500, G = () => {
8
- const i = w(), u = y(), d = T(), { getTemplateData: l } = v(), { runExclusive: m, isEditorBusy: p } = C();
9
- let o = null, n = !1;
10
- const r = () => {
6
+ import { watch as a, onUnmounted as B } from "vue";
7
+ const C = 500, L = () => {
8
+ const i = w(), u = y(), l = T(), { getTemplateData: d } = b(), { runExclusive: m, isEditorBusy: p } = v();
9
+ let o = null, s = !1;
10
+ const n = () => {
11
11
  o && (clearTimeout(o), o = null);
12
- }, a = (t) => {
13
- r(), o = setTimeout(() => {
12
+ }, c = (t) => {
13
+ n(), o = setTimeout(() => {
14
14
  o = null, t();
15
- }, B);
15
+ }, C);
16
16
  }, e = async () => {
17
- var t, s;
18
- if (!(n || !i.isStripoInitialized)) {
17
+ var t, r;
18
+ if (!(s || !i.isStripoInitialized)) {
19
19
  if (p()) {
20
- a(() => void e());
20
+ c(() => void e());
21
21
  return;
22
22
  }
23
23
  try {
24
- const { html: E, css: I } = await m(l), b = ((s = (t = d.config) == null ? void 0 : t.identity) == null ? void 0 : s.templateId) ?? "";
25
- if (n)
24
+ const { html: E, css: g } = await m(d), I = ((r = (t = l.config) == null ? void 0 : t.identity) == null ? void 0 : r.templateId) ?? "";
25
+ if (s)
26
26
  return;
27
27
  u.$patch({
28
28
  html: E ?? "",
29
- css: I ?? "",
30
- templateId: b,
29
+ css: g ?? "",
30
+ templateId: I,
31
31
  lastUpdatedAt: Date.now()
32
32
  });
33
33
  } catch {
34
34
  }
35
35
  }
36
- }, f = () => a(() => void e()), h = c(
36
+ }, f = () => c(() => void e()), h = a(
37
37
  () => i.isStripoInitialized,
38
38
  (t) => {
39
39
  t && e();
40
40
  },
41
41
  { immediate: !0 }
42
- ), S = c(
43
- () => i.changeSeq,
44
- () => {
45
- i.isStripoInitialized && f();
46
- }
47
- ), g = c(
42
+ ), S = a(
48
43
  () => i.hasChanges,
49
- (t, s) => {
50
- !t && s && i.isStripoInitialized && (r(), e());
44
+ (t, r) => {
45
+ i.isStripoInitialized && (t ? f() : r && (n(), e()));
51
46
  }
52
47
  );
53
- z(() => {
54
- n = !0, r(), h(), S(), g();
48
+ B(() => {
49
+ s = !0, n(), h(), S();
55
50
  });
56
51
  };
57
52
  export {
58
- G as useGuidoStateBridge
53
+ L as useGuidoStateBridge
59
54
  };
@@ -0,0 +1,61 @@
1
+ import { useRecommendation as I } from "./useRecommendation.js";
2
+ import { useToaster as C } from "./useToaster.js";
3
+ import { useTranslations as v } from "./useTranslations.js";
4
+ import { ToasterTypeOptions as g } from "../enums/toaster.js";
5
+ import "../extensions/Blocks/Recommendation/constants/selectors.js";
6
+ import { CURRENT_CONFIG_VERSION as L } from "../extensions/Blocks/Recommendation/constants/defaultConfig.js";
7
+ import { useRecommendationExtensionStore as b } from "../extensions/Blocks/Recommendation/store/recommendation.js";
8
+ import { resolveMigrationTarget as R, buildLegacyMigrationPayload as T } from "../extensions/Blocks/Recommendation/utils/legacyStrategyMigration.js";
9
+ import { commitBlockChangeOutsidePanel as h } from "../extensions/Blocks/Recommendation/utils/nodeConfigWriter.js";
10
+ import { useConfigStore as k } from "../stores/config.js";
11
+ const F = () => {
12
+ const e = b(), r = k(), { buildCampaignUrl: m } = I(), { showToaster: i } = C(), c = v();
13
+ return { convertLegacyStrategy: async () => {
14
+ const t = e.currentRecommendationId;
15
+ if (t === null || !e.isLegacyStrategyBlock || e.legacyConversionLoading)
16
+ return "";
17
+ const { strategy: d, productIds: y, size: l, strategyId: p, nodeConfigVersion: u } = e.recommendationConfigs, f = { strategyId: p, size: l, nodeConfigVersion: u }, s = R({
18
+ campaignId: r.campaignId,
19
+ templateLibraryId: r.templateLibraryId
20
+ }), S = T({
21
+ blockId: t,
22
+ url: m(String(t)),
23
+ campaignId: r.campaignId,
24
+ variationId: r.variationId,
25
+ strategy: d,
26
+ productIds: y,
27
+ target: s
28
+ });
29
+ let o;
30
+ try {
31
+ o = await e.convertLegacyStrategy(S, s);
32
+ } catch (n) {
33
+ return console.error("[useLegacyStrategyConversion] migration failed", n), i({
34
+ type: g.Error,
35
+ message: c("email-editor.legacy-strategy-update-failed")
36
+ }), "";
37
+ }
38
+ try {
39
+ await e.fetchStrategyProductsForBlock(t);
40
+ } catch (n) {
41
+ console.error("[useLegacyStrategyConversion] product refetch failed", n);
42
+ }
43
+ const a = e.blockStates[t];
44
+ return a ? h(
45
+ t,
46
+ {
47
+ strategyId: o,
48
+ size: a.recommendationConfigs.size,
49
+ configVersion: L
50
+ },
51
+ a.recommendationProducts,
52
+ "Converted legacy recommendation strategy"
53
+ ) ? (e.currentRecommendationId === t && e.openLegacyStrategyUpdatedModal(), o) : (console.error("[useLegacyStrategyConversion] node write failed", t), e.revertLegacyConversion(t, f), i({
54
+ type: g.Error,
55
+ message: c("email-editor.legacy-strategy-update-failed")
56
+ }), "") : o;
57
+ } };
58
+ };
59
+ export {
60
+ F as useLegacyStrategyConversion
61
+ };
@@ -1,6 +1,6 @@
1
- import { useActionsApi as x } from "./useActionsApi.js";
2
- import { useBlocksConfig as L } from "./useBlocksConfig.js";
3
- import { useConfig as O } from "./useConfig.js";
1
+ import { useActionsApi as L } from "./useActionsApi.js";
2
+ import { useBlocksConfig as O } from "./useBlocksConfig.js";
3
+ import { useConfig as q } from "./useConfig.js";
4
4
  import { useCustomInterfaceAppearance as H } from "./useCustomInterfaceAppearance.js";
5
5
  import { useFullStoryBridge as N } from "./useFullStoryBridge.js";
6
6
  import { useModuleRepair as j } from "./useModuleRepair.js";
@@ -17,7 +17,7 @@ import { buildMergeTagEntries as W, flattenDynamicContentList as Y } from "../ut
17
17
  import Z from "../package.json.js";
18
18
  let n = null;
19
19
  const Ce = () => {
20
- const { features: c, template: u, isFeatureEnabled: m } = O(), { handleError: p, showToaster: k } = G(), { getToken: B, getCustomFonts: M, getSyncModulesStatus: T } = K(), { handleEvent: v } = z(), { handleModuleAdd: F } = j(), { getStripoBlocksConfig: A } = L(), { getStripoNotifications: V } = $(), f = () => n || (n = new Promise((i, s) => {
20
+ const { features: c, template: u, isFeatureEnabled: m } = q(), { handleError: p, showToaster: k } = G(), { getToken: B, getCustomFonts: M, getSyncModulesStatus: T } = K(), { handleEvent: v } = z(), { handleModuleAdd: F } = j(), { getStripoBlocksConfig: A } = O(), { getStripoNotifications: V } = $(), f = () => n || (n = new Promise((i, s) => {
21
21
  var d;
22
22
  if (document.getElementById("UiEditorScript")) {
23
23
  i();
@@ -88,8 +88,8 @@ const Ce = () => {
88
88
  },
89
89
  onTemplateLoaded() {
90
90
  try {
91
- const { importCss: t } = H(), { activateCustomViewStyles: l, updateTimerInClonedTemplate: I } = x(), { injectFullStory: q } = N();
92
- t(), l(), q(), I(), o.onReady(), e.isStripoInitialized = !0, e.loadingStatus = !1, setTimeout(() => {
91
+ const { importCss: t } = H(), { activateCustomViewStyles: l, updateTimerInClonedTemplate: I } = L(), { injectFullStory: x } = N();
92
+ t(), l(), x(), I(), o.onReady(), e.isStripoInitialized = !0, e.loadingStatus = !1, setTimeout(() => {
93
93
  e.hasChanges = !1;
94
94
  }, 1e3);
95
95
  } catch (t) {
@@ -106,7 +106,7 @@ const Ce = () => {
106
106
  e.isVersionHistoryOpen = t;
107
107
  },
108
108
  onDataChanged() {
109
- e.hasChanges = !0, e.changeSeq += 1;
109
+ e.hasChanges = !0;
110
110
  },
111
111
  onEvent: v,
112
112
  onModuleAdd: F,
@@ -1,14 +1,22 @@
1
- import { useTranslations as r } from "../../composables/useTranslations.js";
2
- const l = {
1
+ import { useTranslations as n } from "../../composables/useTranslations.js";
2
+ const a = {
3
3
  RECOMMENDATION_API_URL: "https://recommendationv2.api.useinsider.com",
4
4
  // Relative path → same-origin as the embedding inone dashboard.
5
5
  PRODUCT_ATTRIBUTES_PATH: "/product-attributes/get-attributes",
6
6
  RECOMMENDATION_STRATEGIES_PATH: "/api/recommendation-strategies",
7
- RECOMMENDATION_STRATEGIES_PANEL_PATH: "/discovery/recommendation-strategies"
7
+ RECOMMENDATION_STRATEGIES_PANEL_PATH: "/discovery/recommendation-strategies",
8
+ NEWSLETTER_RECOMMENDATIONS_PATH: "/newsletter/recommendations",
9
+ MIGRATE_STRATEGIES_PATH: "/newsletter/recommendations/migrate-strategies",
10
+ // The template route narrows the recommendations resource before the action: the id
11
+ // travels in the body, not the path.
12
+ TEMPLATE_MIGRATE_STRATEGIES_PATH: "/newsletter/recommendations/template/migrate-strategies"
8
13
  }, c = {
14
+ campaign: a.MIGRATE_STRATEGIES_PATH,
15
+ template: a.TEMPLATE_MIGRATE_STRATEGIES_PATH
16
+ }, d = {
9
17
  CLIENT_ID: "clientId"
10
- }, d = () => {
11
- const e = r();
18
+ }, m = () => {
19
+ const e = n();
12
20
  return [
13
21
  {
14
22
  id: 11,
@@ -71,73 +79,74 @@ const l = {
71
79
  path: "top-sellers"
72
80
  }
73
81
  ];
74
- }, m = ["discount", "omnibus_price", "omnibus_discount", "price", "original_price"], p = [
82
+ }, p = ["discount", "omnibus_price", "omnibus_discount", "price", "original_price"], T = [
75
83
  { text: "before the amount", value: "0" },
76
84
  { text: "after the amount", value: "1" }
77
85
  ], v = [
78
86
  { text: "dot(.)", value: "." },
79
87
  { text: "comma(,)", value: "," },
80
88
  { text: "space( )", value: " " }
81
- ], h = [
89
+ ], A = [
82
90
  { text: "0", value: "0" },
83
91
  { text: "1", value: "1" },
84
92
  { text: "2", value: "2" },
85
93
  { text: "3", value: "3" },
86
94
  { text: "4", value: "4" },
87
95
  { text: "5", value: "5" }
88
- ], a = "||", t = [
96
+ ], r = "||", t = [
89
97
  { text: "is exactly", value: "=" },
90
98
  { text: "contains", value: "~" },
91
99
  { text: "does not contain", value: "!~" },
92
- { text: "any of", value: a }
93
- ], n = [
100
+ { text: "any of", value: r }
101
+ ], o = [
94
102
  { text: "is exactly", value: "=" },
95
103
  { text: "is not exactly", value: "!==" },
96
104
  { text: "contains", value: "~" },
97
105
  { text: "does not contain", value: "!~" },
98
- { text: "any of", value: a }
99
- ], o = [
106
+ { text: "any of", value: r }
107
+ ], s = [
100
108
  { text: "is equal to", value: "=" },
101
109
  { text: "is greater than", value: ">" },
102
110
  { text: "is less than", value: "<" }
103
- ], s = [
111
+ ], i = [
104
112
  { text: "is equal to", value: "=" },
105
113
  { text: "after", value: ">" },
106
114
  { text: "before", value: "<" }
107
- ], i = [
115
+ ], u = [
108
116
  { text: "true", value: "==" },
109
117
  { text: "false", value: "!=" }
110
- ], x = (e) => {
118
+ ], E = (e) => {
111
119
  if (!e)
112
120
  return t;
113
121
  switch (e) {
114
122
  case "Boolean":
115
- return i;
123
+ return u;
116
124
  case "Date":
117
- return s;
125
+ return i;
118
126
  case "Number":
119
- return o;
127
+ return s;
120
128
  case "String":
121
129
  return t;
122
130
  case "Strings":
123
- return n;
131
+ return o;
124
132
  default:
125
133
  return t;
126
134
  }
127
135
  };
128
136
  export {
129
- a as OP_ANY_OF,
130
- m as PriceAttributes,
131
- c as QUERY_PARAMS,
132
- l as URLS,
133
- h as currencyDecimalCounts,
134
- p as currencyLocationMaps,
137
+ c as MIGRATION_PATHS,
138
+ r as OP_ANY_OF,
139
+ p as PriceAttributes,
140
+ d as QUERY_PARAMS,
141
+ a as URLS,
142
+ A as currencyDecimalCounts,
143
+ T as currencyLocationMaps,
135
144
  v as currencyOperators,
136
- x as getOperatorOptions,
137
- d as getRecommendationFeedSourceMaps,
138
- n as operatorOptionsForArrayOfStrings,
139
- i as operatorOptionsForBooleans,
140
- s as operatorOptionsForDates,
141
- o as operatorOptionsForNumbers,
145
+ E as getOperatorOptions,
146
+ m as getRecommendationFeedSourceMaps,
147
+ o as operatorOptionsForArrayOfStrings,
148
+ u as operatorOptionsForBooleans,
149
+ i as operatorOptionsForDates,
150
+ s as operatorOptionsForNumbers,
142
151
  t as operatorOptionsForStrings
143
152
  };
@@ -1,6 +1,6 @@
1
1
  var m = Object.defineProperty;
2
- var C = (h, l, t) => l in h ? m(h, l, { enumerable: !0, configurable: !0, writable: !0, value: t }) : h[l] = t;
3
- var n = (h, l, t) => C(h, typeof l != "symbol" ? l + "" : l, t);
2
+ var C = (g, l, t) => l in g ? m(g, l, { enumerable: !0, configurable: !0, writable: !0, value: t }) : g[l] = t;
3
+ var r = (g, l, t) => C(g, typeof l != "symbol" ? l + "" : l, t);
4
4
  import { useConfig as p } from "../../../../../composables/useConfig.js";
5
5
  import { ModificationDescription as y } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
6
6
  import { CommonControl as N } from "../../../common-control.js";
@@ -12,16 +12,16 @@ import { registerNodeConfigWriter as b } from "../../utils/nodeConfigWriter.js";
12
12
  import { AlgorithmControl as T } from "./algorithm.js";
13
13
  import { ALGORITHM_CONTROL_ID as ut } from "./algorithm.js";
14
14
  import { CurrencyControl as P } from "./currency.js";
15
- import { CURRENCY_CONTROL_ID as ht } from "./currency.js";
15
+ import { CURRENCY_CONTROL_ID as gt } from "./currency.js";
16
16
  import { FiltersControl as S } from "./filters.js";
17
- import { FILTERS_CONTROL_ID as gt } from "./filters.js";
17
+ import { FILTERS_CONTROL_ID as ht } from "./filters.js";
18
18
  import { LayoutOrientationControl as O } from "./layoutOrientation.js";
19
19
  import { LAYOUT_ORIENTATION_CONTROL_ID as Ct } from "./layoutOrientation.js";
20
20
  import { LocaleControl as L } from "./locale.js";
21
21
  import { LOCALE_CONTROL_ID as yt } from "./locale.js";
22
- import { PricePlacementControl as E } from "./pricePlacement.js";
22
+ import { PricePlacementControl as k } from "./pricePlacement.js";
23
23
  import { PRICE_PLACEMENT_CONTROL_ID as _t } from "./pricePlacement.js";
24
- import { ProductCountControl as k } from "./productCount.js";
24
+ import { ProductCountControl as E } from "./productCount.js";
25
25
  import { PRODUCT_COUNT_CONTROL_ID as Rt } from "./productCount.js";
26
26
  import { ProductLayoutControl as F } from "./productLayout.js";
27
27
  import { PRODUCT_LAYOUT_CONTROL_ID as Tt } from "./productLayout.js";
@@ -29,36 +29,36 @@ import { ShuffleControl as D } from "./shuffle.js";
29
29
  import { SHUFFLE_CONTROL_ID as St } from "./shuffle.js";
30
30
  import { StrategyControl as w } from "./strategy.js";
31
31
  import { STRATEGY_CONTROL_ID as Lt } from "./strategy.js";
32
- import { setCurrencyAttributes as A, getBlockElement as v, isPartnerManagedBlock as x, updateProductContentInPlace as B, regenerateProductRowsWithStyles as U } from "./utils.js";
33
- import { adjustProductsToSize as kt, formatProductPrice as Ft, getCardComposition as Dt, getCurrentLayout as wt, getMainContainerTbody as At, regenerateMobileProductRows as vt, updatePricesInPlace as xt, updateSingleProductContent as Bt } from "./utils.js";
32
+ import { setCurrencyAttributes as A, getBlockElement as B, isPartnerManagedBlock as v, updateProductContentInPlace as x, regenerateProductRowsWithStyles as U } from "./utils.js";
33
+ import { adjustProductsToSize as Et, formatProductPrice as Ft, getCardComposition as Dt, getCurrentLayout as wt, getMainContainerTbody as At, regenerateMobileProductRows as Bt, updatePricesInPlace as vt, updateSingleProductContent as xt } from "./utils.js";
34
34
  import { useDebounceFn as f } from "../../../../../node_modules/@vueuse/shared/index.js";
35
35
  const $ = "ui-elements-recommendation-block";
36
36
  class at extends N {
37
37
  constructor() {
38
38
  super(...arguments);
39
- n(this, "store", R());
40
- n(this, "storeUnsubscription", () => {
39
+ r(this, "store", R());
40
+ r(this, "storeUnsubscription", () => {
41
41
  });
42
42
  // A config change waiting to reach the node config. Deferred so it can ride the
43
43
  // re-render's single apply() — one user action must cost one undo press.
44
- n(this, "pendingNodeConfigWrite", null);
45
- n(this, "pendingConfigFlushTimer", null);
44
+ r(this, "pendingNodeConfigWrite", null);
45
+ r(this, "pendingConfigFlushTimer", null);
46
46
  // Sub-control instances for lifecycle management
47
- n(this, "algorithmControl", null);
48
- n(this, "localeControl", null);
49
- n(this, "currencyControl", null);
50
- n(this, "productCountControl", null);
51
- n(this, "productLayoutControl", null);
52
- n(this, "filtersControl", null);
53
- n(this, "shuffleControl", null);
54
- n(this, "pricePlacementControl", null);
55
- n(this, "layoutOrientationControl", null);
56
- n(this, "strategyControl", null);
57
- n(this, "rrsEnabled", !1);
47
+ r(this, "algorithmControl", null);
48
+ r(this, "localeControl", null);
49
+ r(this, "currencyControl", null);
50
+ r(this, "productCountControl", null);
51
+ r(this, "productLayoutControl", null);
52
+ r(this, "filtersControl", null);
53
+ r(this, "shuffleControl", null);
54
+ r(this, "pricePlacementControl", null);
55
+ r(this, "layoutOrientationControl", null);
56
+ r(this, "strategyControl", null);
57
+ r(this, "rrsEnabled", !1);
58
58
  /**
59
59
  * Debounced product fetch to prevent rapid API calls during config changes
60
60
  */
61
- n(this, "_debouncedFetchProducts", f(async () => {
61
+ r(this, "_debouncedFetchProducts", f(async () => {
62
62
  try {
63
63
  await this.store.fetchRecommendationProducts();
64
64
  } finally {
@@ -76,16 +76,16 @@ class at extends N {
76
76
  * count. The store pads products to the configured size, so in-place only
77
77
  * fails when the size actually changed.
78
78
  */
79
- n(this, "_debouncedRegenerateWithProducts", f(() => {
79
+ r(this, "_debouncedRegenerateWithProducts", f(() => {
80
80
  const t = this.store.recommendationProducts;
81
81
  if (!this.currentNode || !this.api)
82
82
  return;
83
83
  const e = this.api.getDocumentModifier(), o = this._stagePendingNodeConfig(e);
84
- if (x(this.currentNode)) {
84
+ if (v(this.currentNode)) {
85
85
  o && (e.apply(new y("Update recommendation configuration")), this.pendingNodeConfigWrite = null, this._clearConfigFlush());
86
86
  return;
87
87
  }
88
- B({
88
+ x({
89
89
  currentNode: this.currentNode,
90
90
  documentModifier: e,
91
91
  products: t
@@ -118,7 +118,7 @@ class at extends N {
118
118
  return this.rrsEnabled = p().isFeatureEnabled("reusableRecommendationStrategy"), this._subControls.forEach((e) => {
119
119
  var o;
120
120
  return (o = e == null ? void 0 : e.onDestroy) == null ? void 0 : o.call(e);
121
- }), this.algorithmControl = new T(), this.localeControl = new L(), this.currencyControl = new P(), this.productCountControl = new k(), this.productLayoutControl = new F(), this.filtersControl = new S(), this.shuffleControl = new D(), this.pricePlacementControl = new E(), this.layoutOrientationControl = new O(), this.strategyControl = this.rrsEnabled ? new w() : null, this._subControls.forEach((e) => {
121
+ }), this.algorithmControl = new T(), this.localeControl = new L(), this.currencyControl = new P(), this.productCountControl = new E(), this.productLayoutControl = new F(), this.filtersControl = new S(), this.shuffleControl = new D(), this.pricePlacementControl = new k(), this.layoutOrientationControl = new O(), this.strategyControl = this.rrsEnabled ? new w() : null, this._subControls.forEach((e) => {
122
122
  e && (e.api = this.api);
123
123
  }), `
124
124
  <div class="recommendation-controls-container">
@@ -140,8 +140,8 @@ class at extends N {
140
140
  const e = (i = this.getContainer()) == null ? void 0 : i.querySelector(".recommendation-controls-container");
141
141
  if (!e)
142
142
  return;
143
- const o = this._getRecommendationIdFromNode(t) === null ? null : c.getConfig(t), r = this.rrsEnabled && !!o && (!!(o != null && o.strategyId) || ((o == null ? void 0 : o.configVersion) ?? 0) >= _);
144
- e.classList.toggle("strategy-block", r);
143
+ const o = this._getRecommendationIdFromNode(t) === null ? null : c.getConfig(t), n = this.rrsEnabled && !!o && (!!(o != null && o.strategyId) || ((o == null ? void 0 : o.configVersion) ?? 0) >= _), s = this.rrsEnabled && !!o && !n;
144
+ e.classList.toggle("strategy-block", n), e.classList.toggle("legacy-strategy-block", s);
145
145
  }
146
146
  async onRender() {
147
147
  var o;
@@ -159,9 +159,9 @@ class at extends N {
159
159
  const e = this._getRecommendationIdFromNode(t);
160
160
  e !== null && e !== this.store.currentRecommendationId && this.store.setCurrentBlock(e), e !== null && this._syncNodeConfigIfChanged(e), this._showControlsForBlock(t), e !== null && !((o = this.store.blockStates[e]) != null && o.isInitialized) && this._fetchBlockData(e).then(() => {
161
161
  this._initializeSubControls();
162
- }), this._subControls.forEach((r) => {
163
- var i;
164
- r != null && r.api && (r.currentNode = t, (i = r.onTemplateNodeUpdated) == null || i.call(r, t));
162
+ }), this._subControls.forEach((n) => {
163
+ var s;
164
+ n != null && n.api && (n.currentNode = t, (s = n.onTemplateNodeUpdated) == null || s.call(n, t));
165
165
  });
166
166
  }
167
167
  onDestroy() {
@@ -209,18 +209,18 @@ class at extends N {
209
209
  const e = this.store.blockStates[t];
210
210
  if (!e)
211
211
  return;
212
- const o = JSON.stringify(c.getConfig(this.currentNode)), r = e.syncedConfigFingerprint;
213
- e.syncedConfigFingerprint = o, r !== o && (this.pendingNodeConfigWrite || this._syncNodeConfigToStore());
212
+ const o = JSON.stringify(c.getConfig(this.currentNode)), n = e.syncedConfigFingerprint;
213
+ e.syncedConfigFingerprint = o, n !== o && (this.pendingNodeConfigWrite || this._syncNodeConfigToStore());
214
214
  }
215
215
  _capturePendingNodeConfigWrite() {
216
216
  const t = this.store.currentRecommendationId;
217
217
  if (!this.currentNode || !this.api || t === null)
218
218
  return;
219
- const { filters: e, strategyId: o, size: r } = this.store.recommendationConfigs;
219
+ const { filters: e, strategyId: o, size: n, nodeConfigVersion: s } = this.store.recommendationConfigs;
220
220
  this.pendingNodeConfigWrite = {
221
221
  blockId: t,
222
222
  node: this.currentNode,
223
- updates: { filters: e, strategyId: o, size: r }
223
+ updates: { filters: e, strategyId: o, size: n, configVersion: s }
224
224
  };
225
225
  }
226
226
  /**
@@ -263,11 +263,12 @@ class at extends N {
263
263
  JSON.stringify(o.filters) === JSON.stringify(t.updates.filters) && o.strategyId === t.updates.strategyId && o.size === t.updates.size || c.updateConfig(this.api, e, t.updates, "Update recommendation filters");
264
264
  }
265
265
  _syncNodeConfigToStore() {
266
- var r;
267
- const t = c.getConfig(this.currentNode), e = this.store.currentRecommendationId, o = e !== null && ((r = this.store.blockStates[e]) == null ? void 0 : r.isInitialized);
266
+ var n;
267
+ const t = c.getConfig(this.currentNode), e = this.store.currentRecommendationId, o = e !== null && ((n = this.store.blockStates[e]) == null ? void 0 : n.isInitialized);
268
268
  this.store.patchCurrentBlockConfig({
269
269
  strategy: t.strategy,
270
270
  strategyId: t.strategyId,
271
+ nodeConfigVersion: t.configVersion,
271
272
  language: t.language,
272
273
  size: t.size,
273
274
  productIds: t.productIds,
@@ -306,8 +307,8 @@ class at extends N {
306
307
  t !== null && this.store.markBlockInitialized(t), (await Promise.allSettled([
307
308
  this.store.fetchRecommendationCreateData(),
308
309
  this.store.fetchRecommendationFilters()
309
- ])).forEach((o, r) => {
310
- o.status === "rejected" && console.warn(`Recommendation block: ${["fetchRecommendationCreateData", "fetchRecommendationFilters"][r]} failed`, o.reason);
310
+ ])).forEach((o, n) => {
311
+ o.status === "rejected" && console.warn(`Recommendation block: ${["fetchRecommendationCreateData", "fetchRecommendationFilters"][n]} failed`, o.reason);
311
312
  }), this._applySmartDefaults();
312
313
  try {
313
314
  await this.store.fetchRecommendationProducts();
@@ -329,30 +330,30 @@ class at extends N {
329
330
  if (!this.currentNode || !this.api)
330
331
  return;
331
332
  const t = c.getConfig(this.currentNode), e = {};
332
- let o = null, r = null, i = null;
333
+ let o = null, n = null, s = null;
333
334
  if (t.currency.code === a.currency.code) {
334
- const { currencyList: s } = this.store;
335
- s.length > 0 && (s.some(
335
+ const { currencyList: i } = this.store;
336
+ i.length > 0 && (i.some(
336
337
  (d) => d.value === `price.${a.currency.code}`
337
- ) || (o = s[0].value.replace("price.", ""), e.currency = {
338
+ ) || (o = i[0].value.replace("price.", ""), e.currency = {
338
339
  ...a.currency,
339
340
  code: o,
340
341
  symbol: o
341
342
  }));
342
343
  }
343
344
  if (t.strategy === a.strategy) {
344
- const s = this.store.getActivePredictiveAlgorithms;
345
- s.length > 0 && (s.some(
345
+ const i = this.store.getActivePredictiveAlgorithms;
346
+ i.length > 0 && (i.some(
346
347
  (d) => d.value === a.strategy
347
- ) || (r = s[0].value, e.strategy = r));
348
+ ) || (n = i[0].value, e.strategy = n));
348
349
  }
349
350
  if (t.language === a.language) {
350
- const s = this.store.getLanguages;
351
- s.length > 0 && (s.some(
351
+ const i = this.store.getLanguages;
352
+ i.length > 0 && (i.some(
352
353
  (d) => d.value === a.language
353
- ) || (i = s[0].value, e.language = i));
354
+ ) || (s = i[0].value, e.language = s));
354
355
  }
355
- !o && !r && !i || (c.updateConfig(
356
+ !o && !n && !s || (c.updateConfig(
356
357
  this.api,
357
358
  this.currentNode,
358
359
  e,
@@ -373,22 +374,22 @@ class at extends N {
373
374
  thousandSeparator: a.currency.thousandSeparator
374
375
  }
375
376
  } : {},
376
- ...r ? { strategy: r } : {},
377
- ...i ? { language: i } : {}
377
+ ...n ? { strategy: n } : {},
378
+ ...s ? { language: s } : {}
378
379
  }, { triggerRefetch: !1 }));
379
380
  }
380
381
  /**
381
382
  * Reads the recommendation-id attribute from the block element within the node
382
383
  */
383
384
  _getRecommendationIdFromNode(t) {
384
- const e = v(t);
385
+ const e = B(t);
385
386
  if (!e || !("getAttribute" in e))
386
387
  return null;
387
388
  const o = e.getAttribute(I);
388
389
  if (!o)
389
390
  return null;
390
- const r = parseInt(o);
391
- return Number.isNaN(r) ? null : r;
391
+ const n = parseInt(o);
392
+ return Number.isNaN(n) ? null : n;
392
393
  }
393
394
  /**
394
395
  * Listen to store changes that require product refresh or regeneration.
@@ -405,17 +406,17 @@ class at extends N {
405
406
  */
406
407
  _listenStateUpdates() {
407
408
  const { store: t } = this;
408
- let e = t.recommendationProducts, o = t.$state.configVersion, r = t.currentRecommendationId;
409
+ let e = t.recommendationProducts, o = t.$state.configVersion, n = t.currentRecommendationId;
409
410
  this.storeUnsubscription = t.$subscribe(() => {
410
- const i = t.currentRecommendationId;
411
- if (i !== r) {
412
- r = i, e = t.recommendationProducts, o = t.$state.configVersion;
411
+ const s = t.currentRecommendationId;
412
+ if (s !== n) {
413
+ n = s, e = t.recommendationProducts, o = t.$state.configVersion;
413
414
  return;
414
415
  }
415
- const s = t.$state.configVersion;
416
- s !== o && (o = s, this._capturePendingNodeConfigWrite(), this._debouncedFetchProducts());
417
- const u = t.recommendationProducts, d = u !== e, g = Array.isArray(u) && u.length > 0;
418
- d && g && (e = u, this._debouncedRegenerateWithProducts());
416
+ const i = t.$state.configVersion;
417
+ i !== o && (o = i, this._capturePendingNodeConfigWrite(), this._debouncedFetchProducts());
418
+ const u = t.recommendationProducts, d = u !== e, h = Array.isArray(u) && u.length > 0;
419
+ d && h && (e = u, this._debouncedRegenerateWithProducts());
419
420
  });
420
421
  }
421
422
  }
@@ -423,9 +424,9 @@ export {
423
424
  ut as ALGORITHM_CONTROL_ID,
424
425
  T as AlgorithmControl,
425
426
  $ as CONTROL_BLOCK_ID,
426
- ht as CURRENCY_CONTROL_ID,
427
+ gt as CURRENCY_CONTROL_ID,
427
428
  P as CurrencyControl,
428
- gt as FILTERS_CONTROL_ID,
429
+ ht as FILTERS_CONTROL_ID,
429
430
  S as FiltersControl,
430
431
  Ct as LAYOUT_ORIENTATION_CONTROL_ID,
431
432
  yt as LOCALE_CONTROL_ID,
@@ -434,25 +435,25 @@ export {
434
435
  _t as PRICE_PLACEMENT_CONTROL_ID,
435
436
  Rt as PRODUCT_COUNT_CONTROL_ID,
436
437
  Tt as PRODUCT_LAYOUT_CONTROL_ID,
437
- E as PricePlacementControl,
438
- k as ProductCountControl,
438
+ k as PricePlacementControl,
439
+ E as ProductCountControl,
439
440
  F as ProductLayoutControl,
440
441
  at as RecommendationBlockControl,
441
442
  St as SHUFFLE_CONTROL_ID,
442
443
  Lt as STRATEGY_CONTROL_ID,
443
444
  D as ShuffleControl,
444
445
  w as StrategyControl,
445
- kt as adjustProductsToSize,
446
+ Et as adjustProductsToSize,
446
447
  Ft as formatProductPrice,
447
- v as getBlockElement,
448
+ B as getBlockElement,
448
449
  Dt as getCardComposition,
449
450
  wt as getCurrentLayout,
450
451
  At as getMainContainerTbody,
451
- x as isPartnerManagedBlock,
452
- vt as regenerateMobileProductRows,
452
+ v as isPartnerManagedBlock,
453
+ Bt as regenerateMobileProductRows,
453
454
  U as regenerateProductRowsWithStyles,
454
455
  A as setCurrencyAttributes,
455
- xt as updatePricesInPlace,
456
- B as updateProductContentInPlace,
457
- Bt as updateSingleProductContent
456
+ vt as updatePricesInPlace,
457
+ x as updateProductContentInPlace,
458
+ xt as updateSingleProductContent
458
459
  };