@useinsider/guido 3.17.0 → 3.18.0-beta.0ece468

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 (116) hide show
  1. package/README.md +6 -5
  2. package/dist/@types/config/schemas.js +7 -6
  3. package/dist/components/Guido.vue.js +10 -10
  4. package/dist/components/Guido.vue2.js +84 -78
  5. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +23 -0
  6. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +122 -0
  7. package/dist/components/organisms/extensions/recommendation/RemoveStrategyModal.vue.js +17 -0
  8. package/dist/components/organisms/extensions/recommendation/RemoveStrategyModal.vue2.js +57 -0
  9. package/dist/components/organisms/extensions/recommendation/StrategyInfoBoxContent.vue.js +19 -0
  10. package/dist/components/organisms/extensions/recommendation/StrategyInfoBoxContent.vue2.js +63 -0
  11. package/dist/components/organisms/onboarding/OnboardingWrapper.vue2.js +20 -18
  12. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.js +21 -0
  13. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue2.js +46 -0
  14. package/dist/composables/useCustomInterfaceAppearance.js +52 -38
  15. package/dist/composables/useModuleRepair.js +33 -0
  16. package/dist/composables/useRecommendation.js +41 -34
  17. package/dist/composables/useSave.js +30 -29
  18. package/dist/composables/useStripo.js +15 -15
  19. package/dist/composables/useSyncModuleExtractor.js +15 -13
  20. package/dist/composables/validators/useSyncModuleBlockValidator.js +24 -0
  21. package/dist/config/i18n/en/labels.json.js +1 -1
  22. package/dist/config/migrator/index.js +9 -8
  23. package/dist/config/migrator/recommendation/compositionMapper.js +20 -20
  24. package/dist/config/migrator/recommendation/extractors.js +29 -24
  25. package/dist/config/migrator/recommendation/htmlBuilder.js +116 -130
  26. package/dist/config/migrator/recommendation/settingsMapper.js +17 -17
  27. package/dist/config/migrator/recommendationMigrator.js +31 -25
  28. package/dist/config/migrator/recommendationTitleMigrator.js +119 -0
  29. package/dist/enums/academy.js +2 -1
  30. package/dist/enums/date.js +5 -3
  31. package/dist/enums/extensions/recommendationBlock.js +40 -31
  32. package/dist/extensions/Blocks/Items/block.js +118 -49
  33. package/dist/extensions/Blocks/Items/constants/currency.js +25 -0
  34. package/dist/extensions/Blocks/Items/controls/price/currencyLocation.js +25 -24
  35. package/dist/extensions/Blocks/Items/controls/price/currencySymbol.js +12 -11
  36. package/dist/extensions/Blocks/Items/template.js +153 -152
  37. package/dist/extensions/Blocks/Items/utils/constants.js +4 -0
  38. package/dist/extensions/Blocks/Recommendation/block.js +35 -29
  39. package/dist/extensions/Blocks/Recommendation/constants/blockIds.js +1 -1
  40. package/dist/extensions/Blocks/Recommendation/constants/controlIds.js +1 -1
  41. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +29 -27
  42. package/dist/extensions/Blocks/Recommendation/constants/selectors.js +35 -28
  43. package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +309 -236
  44. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +241 -180
  45. package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +128 -0
  46. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +1 -0
  47. package/dist/extensions/Blocks/Recommendation/controls/title/index.js +44 -0
  48. package/dist/extensions/Blocks/Recommendation/extension.js +31 -29
  49. package/dist/extensions/Blocks/Recommendation/services/configService.js +54 -36
  50. package/dist/extensions/Blocks/Recommendation/settingsPanel.js +23 -4
  51. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +236 -79
  52. package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +3 -3
  53. package/dist/extensions/Blocks/Recommendation/templates/titleRows.js +33 -0
  54. package/dist/extensions/Blocks/Recommendation/templates/utils.js +85 -107
  55. package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +22 -0
  56. package/dist/extensions/Blocks/Recommendation/utils/recommendationBlockCount.js +10 -6
  57. package/dist/extensions/Blocks/common-control.js +22 -19
  58. package/dist/guido.css +1 -1
  59. package/dist/services/recommendationApi.js +69 -30
  60. package/dist/src/@types/config/schemas.d.ts +2 -0
  61. package/dist/src/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.d.ts +3 -0
  62. package/dist/src/components/organisms/extensions/recommendation/RemoveStrategyModal.vue.d.ts +2 -0
  63. package/dist/src/components/organisms/extensions/recommendation/StrategyInfoBoxContent.vue.d.ts +15 -0
  64. package/dist/src/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.d.ts +2 -0
  65. package/dist/src/composables/useConfig.d.ts +2 -0
  66. package/dist/src/composables/useModuleRepair.d.ts +18 -0
  67. package/dist/src/composables/useRecommendation.d.ts +1 -0
  68. package/dist/src/composables/useSyncModuleExtractor.d.ts +2 -0
  69. package/dist/src/composables/validators/useSyncModuleBlockValidator.d.ts +3 -0
  70. package/dist/src/config/migrator/recommendation/extractors.d.ts +8 -0
  71. package/dist/src/config/migrator/recommendationTitleMigrator.d.ts +5 -0
  72. package/dist/src/enums/academy.d.ts +1 -0
  73. package/dist/src/enums/date.d.ts +1 -0
  74. package/dist/src/enums/extensions/recommendationBlock.d.ts +4 -0
  75. package/dist/src/extensions/Blocks/Items/block.d.ts +35 -0
  76. package/dist/src/extensions/Blocks/Items/constants/currency.d.ts +43 -0
  77. package/dist/src/extensions/Blocks/Items/utils/constants.d.ts +6 -0
  78. package/dist/src/extensions/Blocks/Recommendation/constants/blockIds.d.ts +2 -1
  79. package/dist/src/extensions/Blocks/Recommendation/constants/controlIds.d.ts +7 -0
  80. package/dist/src/extensions/Blocks/Recommendation/constants/defaultConfig.d.ts +3 -6
  81. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +2 -2
  82. package/dist/src/extensions/Blocks/Recommendation/constants/selectors.d.ts +12 -0
  83. package/dist/src/extensions/Blocks/Recommendation/controls/cardComposition/index.d.ts +11 -0
  84. package/dist/src/extensions/Blocks/Recommendation/controls/index.d.ts +1 -0
  85. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +44 -8
  86. package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +17 -0
  87. package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +1 -0
  88. package/dist/src/extensions/Blocks/Recommendation/controls/title/index.d.ts +86 -0
  89. package/dist/src/extensions/Blocks/Recommendation/services/configService.d.ts +12 -1
  90. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +225 -10
  91. package/dist/src/extensions/Blocks/Recommendation/templates/titleRows.d.ts +13 -0
  92. package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +7 -0
  93. package/dist/src/extensions/Blocks/Recommendation/utils/nodeConfigWriter.d.ts +31 -0
  94. package/dist/src/extensions/Blocks/Recommendation/utils/recommendationBlockCount.d.ts +6 -2
  95. package/dist/src/extensions/Blocks/common-control.d.ts +4 -1
  96. package/dist/src/mock/api/recommendation-strategies.d.ts +2 -0
  97. package/dist/src/services/recommendationApi.d.ts +4 -1
  98. package/dist/src/stores/config.d.ts +18 -0
  99. package/dist/src/stores/onboarding.d.ts +377 -0
  100. package/dist/src/stores/save-as-template.d.ts +4 -3
  101. package/dist/src/utils/genericUtil.d.ts +5 -0
  102. package/dist/src/utils/itemsCurrencyRepair.d.ts +17 -0
  103. package/dist/static/assets/icons/line-change.svg.js +5 -0
  104. package/dist/static/assets/icons/line-delete.svg.js +5 -0
  105. package/dist/static/assets/icons/line-plus.svg.js +5 -0
  106. package/dist/static/styles/components/recommendation-strategy.css.js +172 -0
  107. package/dist/static/styles/customEditorStyle.css.js +3 -1
  108. package/dist/stores/onboarding.js +41 -36
  109. package/dist/utils/dateUtil.js +23 -10
  110. package/dist/utils/genericUtil.js +28 -27
  111. package/dist/utils/itemsCurrencyRepair.js +39 -0
  112. package/dist/utils/pairProductVariables.js +58 -58
  113. package/dist/utils/templatePreparation.js +35 -34
  114. package/package.json +3 -2
  115. package/dist/composables/useModuleDynamicContentRepair.js +0 -37
  116. package/dist/src/composables/useModuleDynamicContentRepair.d.ts +0 -13
@@ -1,21 +1,31 @@
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";
1
+ import { getRecommendationFeedSourceMaps as C, strategyEditPath as _, URLS as D, getOperatorOptions as L, PriceAttributes as N } from "../../../../enums/extensions/recommendationBlock.js";
2
+ import { useRecommendationApi as U } from "../../../../services/recommendationApi.js";
3
+ import { useConfigStore as E } from "../../../../stores/config.js";
4
+ import { asText as w } from "../../../../utils/genericUtil.js";
5
+ import { defineStore as A } from "pinia";
5
6
  import "../constants/selectors.js";
6
- import { DEFAULT_MOBILE_CARDS_IN_ROW as F, DEFAULT_CARDS_IN_ROW as D } from "../constants/layout.js";
7
- import { EXCLUDED_ALGORITHM_IDS as w } from "../constants/defaultConfig.js";
8
- import { getDefaultProducts as S } from "../templates/utils.js";
9
- import { generateCompleteFilterQuery as b } from "../utils/filterUtil.js";
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
- let m = null, u = null, d = null;
16
- function k() {
7
+ import { DEFAULT_MOBILE_CARDS_IN_ROW as x, DEFAULT_CARDS_IN_ROW as B } from "../constants/layout.js";
8
+ import { DEFAULT_NODE_CONFIG as M, EXCLUDED_ALGORITHM_IDS as T } from "../constants/defaultConfig.js";
9
+ import { getDefaultProducts as v } from "../templates/utils.js";
10
+ import { generateCompleteFilterQuery as G } from "../utils/filterUtil.js";
11
+ import { getPartnerRecommendationParams as O } from "../utils/partnerCustomizations.js";
12
+ import { sanitizeProductIds as z } from "../utils/productIds.js";
13
+ import { isFilterValid as V } from "../validation/filterSchema.js";
14
+ import { isConfigValid as $ } from "../validation/requiredFields.js";
15
+ const d = U();
16
+ let g = null, h = null, S = null, p = null, I = 0;
17
+ const b = /* @__PURE__ */ new Map();
18
+ let u = null, y = null;
19
+ const j = (t, e) => {
20
+ const r = t.filter((s) => !e.has(String(s.strategy_id)));
21
+ if (!r.length)
22
+ return null;
23
+ const n = r.reduce((s, i) => w(i.created_at) > w(s.created_at) ? i : s);
24
+ return String(n.strategy_id);
25
+ };
26
+ function P() {
17
27
  return {
18
- cardsInRow: D,
28
+ cardsInRow: B,
19
29
  currencySettings: {
20
30
  name: "USD",
21
31
  value: "USD",
@@ -29,13 +39,14 @@ function k() {
29
39
  productIds: [],
30
40
  id: 1,
31
41
  language: "en_US",
32
- mobileCardsInRow: F,
42
+ mobileCardsInRow: x,
33
43
  mobileLayoutEnabled: !1,
34
44
  orientation: "grid",
35
45
  recommendedProducts: [],
36
46
  sendProductRequestFlag: !1,
37
47
  shuffleProducts: !1,
38
48
  strategy: "mostPopular",
49
+ strategyId: "",
39
50
  textTrimming: !0,
40
51
  unresponsive: !1,
41
52
  size: "6",
@@ -44,28 +55,35 @@ function k() {
44
55
  priceHideIfSameAsDiscounted: !1
45
56
  };
46
57
  }
47
- function I() {
58
+ function F() {
48
59
  return {
49
- recommendationConfigs: k(),
60
+ recommendationConfigs: P(),
50
61
  recommendationProducts: [],
51
62
  filterStatus: !1,
52
63
  filterSelectionDrawerStatus: !1,
64
+ assignStrategyDrawerStatus: !1,
65
+ removeStrategyModalStatus: !1,
53
66
  filterGroup: 1,
54
67
  isInitialized: !1,
55
68
  filterSnapshot: null
56
69
  };
57
70
  }
58
- const U = () => ({
71
+ const q = () => ({
59
72
  recommendationCampaignUrls: {},
60
73
  activePredictiveAlgorithms: [],
61
74
  languages: {},
62
75
  currencyList: [],
63
76
  filterList: {},
77
+ strategies: [],
78
+ strategiesLoading: !1,
79
+ strategyUrlTemplates: {},
80
+ lastCreatedStrategyId: null,
81
+ strategiesFetched: !1,
64
82
  blockStates: {},
65
83
  currentRecommendationId: null,
66
84
  configVersion: 0
67
- }), H = P("guidoRecommendationExtension", {
68
- state: () => U(),
85
+ }), st = A("guidoRecommendationExtension", {
86
+ state: () => q(),
69
87
  getters: {
70
88
  // ====================================================================
71
89
  // Proxy Getters — Backward Compatible Access to Current Block State
@@ -75,7 +93,7 @@ const U = () => ({
75
93
  * This allows all existing code that reads `store.recommendationConfigs` to work unchanged.
76
94
  */
77
95
  recommendationConfigs(t) {
78
- return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : k();
96
+ return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : P();
79
97
  },
80
98
  /**
81
99
  * Proxy getter: delegates to blockStates[currentRecommendationId].recommendationProducts
@@ -89,6 +107,16 @@ const U = () => ({
89
107
  filterSelectionDrawerStatus(t) {
90
108
  return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].filterSelectionDrawerStatus : !1;
91
109
  },
110
+ assignStrategyDrawerStatus(t) {
111
+ return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].assignStrategyDrawerStatus : !1;
112
+ },
113
+ removeStrategyModalStatus(t) {
114
+ return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].removeStrategyModalStatus : !1;
115
+ },
116
+ assignedStrategy(t) {
117
+ const { strategyId: e } = this.recommendationConfigs;
118
+ return e ? t.strategies.find((r) => String(r.strategy_id) === e) ?? null : null;
119
+ },
92
120
  /**
93
121
  * Proxy getter: delegates to blockStates[currentRecommendationId].filterStatus
94
122
  */
@@ -120,9 +148,9 @@ const U = () => ({
120
148
  return [...new Set(t.map((e) => e.filterGroup))].sort((e, r) => e - r);
121
149
  },
122
150
  getActivePredictiveAlgorithms: (t) => {
123
- const e = g(), r = [];
124
- return t.activePredictiveAlgorithms.filter((n) => !w.includes(n)).forEach((n) => {
125
- r.push(...e.filter((c) => c.id === n));
151
+ const e = C(), r = [];
152
+ return t.activePredictiveAlgorithms.filter((n) => !T.includes(n)).forEach((n) => {
153
+ r.push(...e.filter((s) => s.id === n));
126
154
  }), r.map((n) => ({
127
155
  text: n.name,
128
156
  value: n.key
@@ -139,7 +167,7 @@ const U = () => ({
139
167
  getFilterList() {
140
168
  return Object.values(this.filterList).filter((t) => t.isFilterable !== 0 && t.isFilterable !== !1).map((t) => {
141
169
  let e;
142
- return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : C.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
170
+ return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : N.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
143
171
  text: t.displayName,
144
172
  value: e,
145
173
  type: t.attributeType
@@ -161,7 +189,7 @@ const U = () => ({
161
189
  setCurrentBlock(t) {
162
190
  this.blockStates[t] || (this.blockStates = {
163
191
  ...this.blockStates,
164
- [t]: I()
192
+ [t]: F()
165
193
  }), this.currentRecommendationId = t;
166
194
  },
167
195
  /**
@@ -193,10 +221,10 @@ const U = () => ({
193
221
  [e]: o
194
222
  };
195
223
  }
196
- const n = t.toString(), c = e.toString(), i = this.recommendationCampaignUrls[n];
224
+ const n = t.toString(), s = e.toString(), i = this.recommendationCampaignUrls[n];
197
225
  i && (this.recommendationCampaignUrls = {
198
226
  ...this.recommendationCampaignUrls,
199
- [c]: i
227
+ [s]: i
200
228
  });
201
229
  },
202
230
  /**
@@ -221,7 +249,7 @@ const U = () => ({
221
249
  * `isInitialized`) alone.
222
250
  */
223
251
  seedBlockUrlConfig(t, e) {
224
- const r = (o, s) => o === "." || o === "," || o === " " ? o : s, n = {
252
+ const r = (o, c) => o === "." || o === "," || o === " " ? o : c, n = {
225
253
  name: e.currencyCode,
226
254
  value: e.currencyCode,
227
255
  symbol: e.currencyCode,
@@ -229,17 +257,18 @@ const U = () => ({
229
257
  decimalCount: String(e.currencyDecimalCount),
230
258
  decimalSeparator: r(e.currencyDecimalSeparator, ","),
231
259
  thousandSeparator: r(e.currencyThousandSeparator, ".")
232
- }, c = !this.blockStates[t], i = c ? I() : this.blockStates[t];
260
+ }, s = !this.blockStates[t], i = s ? F() : this.blockStates[t];
233
261
  i.recommendationConfigs = {
234
262
  ...i.recommendationConfigs,
235
263
  strategy: e.strategy,
264
+ strategyId: e.strategyId,
236
265
  language: e.language,
237
266
  size: e.size,
238
267
  productIds: e.productIds,
239
268
  filters: e.filters,
240
269
  shuffleProducts: e.shuffleProducts,
241
270
  currencySettings: n
242
- }, c && (this.blockStates = {
271
+ }, s && (this.blockStates = {
243
272
  ...this.blockStates,
244
273
  [t]: i
245
274
  });
@@ -267,7 +296,7 @@ const U = () => ({
267
296
  * Creates a filter with the first available attribute and operator pre-selected.
268
297
  */
269
298
  createDefaultFilter(t, e) {
270
- const [r] = this.getFilterList, [n] = R(r == null ? void 0 : r.type);
299
+ const [r] = this.getFilterList, [n] = L(r == null ? void 0 : r.type);
271
300
  return {
272
301
  type: "standardFilter",
273
302
  attribute: (r == null ? void 0 : r.value) ?? "",
@@ -314,21 +343,121 @@ const U = () => ({
314
343
  const t = this.blockStates[this.currentRecommendationId];
315
344
  t.filterSnapshot !== null && (t.recommendationConfigs.filters = t.filterSnapshot, t.filterSnapshot = null), t.filterSelectionDrawerStatus = !1;
316
345
  },
346
+ openAssignStrategyDrawer() {
347
+ this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].assignStrategyDrawerStatus = !0);
348
+ },
349
+ closeAssignStrategyDrawer() {
350
+ this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].assignStrategyDrawerStatus = !1);
351
+ },
352
+ openRemoveStrategyModal() {
353
+ this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].removeStrategyModalStatus = !0);
354
+ },
355
+ closeRemoveStrategyModal() {
356
+ this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].removeStrategyModalStatus = !1);
357
+ },
358
+ async fetchStrategies() {
359
+ if (p && await p, this.strategiesFetched)
360
+ return;
361
+ const t = I;
362
+ p = (async () => {
363
+ this.strategiesLoading = !0;
364
+ try {
365
+ const e = await d.fetchRecommendationStrategies();
366
+ if (t !== I)
367
+ return;
368
+ if (this.strategies = e, this.strategiesFetched = !0, y) {
369
+ const r = j(e, y);
370
+ r && (this.lastCreatedStrategyId = r), y = new Set(e.map((n) => String(n.strategy_id)));
371
+ }
372
+ } finally {
373
+ this.strategiesLoading = !1;
374
+ }
375
+ })();
376
+ try {
377
+ await p;
378
+ } finally {
379
+ p = null;
380
+ }
381
+ },
382
+ invalidateStrategies() {
383
+ this.strategiesFetched = !1, I += 1;
384
+ },
385
+ /**
386
+ * Opens a Smart Recommender strategy page in a new tab and refreshes the list every time
387
+ * the user comes back. `visibilitychange` covers the tab case; `focus` covers the page
388
+ * landing in a separate window, where this document never goes hidden.
389
+ *
390
+ * Deliberately NOT one-shot: the strategy tab stays open, so a user can create a second
391
+ * strategy in it and come back again — a listener that disarmed on the first return would
392
+ * leave that one missing from the list. Armed only once the user actually opens a strategy
393
+ * page, so anyone who never does pays nothing.
394
+ */
395
+ _armStrategyPageReturn(t) {
396
+ window.open(t, "_blank", "noopener"), u == null || u();
397
+ let e = !1;
398
+ const r = () => {
399
+ document.hidden || e || (e = !0, this.invalidateStrategies(), this.fetchStrategies().catch(() => {
400
+ }).finally(() => {
401
+ e = !1;
402
+ }));
403
+ };
404
+ document.addEventListener("visibilitychange", r), window.addEventListener("focus", r), u = () => {
405
+ document.removeEventListener("visibilitychange", r), window.removeEventListener("focus", r), u = null;
406
+ };
407
+ },
408
+ /** Lets the editor tear the return listeners down when it unmounts. */
409
+ disposeStrategyPageReturn() {
410
+ u == null || u(), y = null;
411
+ },
412
+ /**
413
+ * Opens Smart Recommender's strategy creation page. Every return refreshes the list, and any
414
+ * strategy that appeared since the page was opened is remembered so the drawer preselects it —
415
+ * including a second one created without ever closing that tab.
416
+ */
417
+ openStrategyCreation() {
418
+ y = new Set(this.strategies.map((t) => String(t.strategy_id))), this._armStrategyPageReturn(D.RECOMMENDATION_STRATEGY_CREATE_PATH);
419
+ },
420
+ /**
421
+ * Opens the strategy's edit page. Every return refreshes the list so the block reflects the
422
+ * edited configuration; nothing is preselected because the strategy is already assigned.
423
+ */
424
+ openStrategyEdit(t) {
425
+ this._armStrategyPageReturn(_(t));
426
+ },
427
+ async resolveStrategyUrlTemplate(t, e) {
428
+ const r = typeof t.updated_at == "string" ? t.updated_at : "", n = r ? `${t.strategy_id}:${r}:${e}` : "", s = n ? this.strategyUrlTemplates[n] : void 0;
429
+ if (s)
430
+ return s;
431
+ const { full_path: i = "" } = await d.generateStrategyEndpoint(t, e) ?? {};
432
+ return n && i && (this.strategyUrlTemplates = {
433
+ ...this.strategyUrlTemplates,
434
+ [n]: i
435
+ }), i;
436
+ },
437
+ assignStrategy(t) {
438
+ this.patchCurrentBlockConfig({
439
+ strategyId: String(t.strategy_id),
440
+ ...t.size !== void 0 ? { size: String(t.size) } : {}
441
+ });
442
+ },
443
+ removeStrategy() {
444
+ this.patchCurrentBlockConfig({ strategyId: "", size: M.size });
445
+ },
317
446
  // ====================================================================
318
447
  // Shared Data Fetching (fetched once, used by all blocks)
319
448
  // ====================================================================
320
449
  async fetchRecommendationCreateData() {
321
450
  if (!this.activePredictiveAlgorithms.length) {
322
- if (m) {
323
- await m;
451
+ if (g) {
452
+ await g;
324
453
  return;
325
454
  }
326
- m = (async () => {
455
+ g = (async () => {
327
456
  const {
328
457
  activePredictiveAlgorithms: t,
329
458
  languages: e,
330
459
  currencies: r
331
- } = await h.fetchRecommendationCreateData();
460
+ } = await d.fetchRecommendationCreateData();
332
461
  if (this.activePredictiveAlgorithms = t, this.languages = e, this.currentRecommendationId !== null && this.blockStates[this.currentRecommendationId]) {
333
462
  const n = this.blockStates[this.currentRecommendationId];
334
463
  n.filterStatus = !!n.recommendationConfigs.filters.length;
@@ -336,26 +465,26 @@ const U = () => ({
336
465
  this.currencyList = r;
337
466
  })();
338
467
  try {
339
- await m;
468
+ await g;
340
469
  } finally {
341
- m = null;
470
+ g = null;
342
471
  }
343
472
  }
344
473
  },
345
474
  async fetchRecommendationFilters() {
346
475
  if (!Object.keys(this.filterList).length) {
347
- if (u) {
348
- await u;
476
+ if (h) {
477
+ await h;
349
478
  return;
350
479
  }
351
- u = (async () => {
352
- const t = await h.fetchRecommendationFilters();
480
+ h = (async () => {
481
+ const t = await d.fetchRecommendationFilters();
353
482
  this.filterList = t;
354
483
  })();
355
484
  try {
356
- await u;
485
+ await h;
357
486
  } finally {
358
- u = null;
487
+ h = null;
359
488
  }
360
489
  }
361
490
  },
@@ -370,10 +499,10 @@ const U = () => ({
370
499
  deleteFilterGroup(t) {
371
500
  if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
372
501
  return;
373
- const e = this.blockStates[this.currentRecommendationId], r = e.recommendationConfigs.filters.filter((i) => i.filterGroup !== t), n = [...new Set(r.map((i) => i.filterGroup))].sort((i, o) => i - o), c = new Map(n.map((i, o) => [i, o + 1]));
502
+ const e = this.blockStates[this.currentRecommendationId], r = e.recommendationConfigs.filters.filter((i) => i.filterGroup !== t), n = [...new Set(r.map((i) => i.filterGroup))].sort((i, o) => i - o), s = new Map(n.map((i, o) => [i, o + 1]));
374
503
  e.recommendationConfigs.filters = r.map((i) => ({
375
504
  ...i,
376
- filterGroup: c.get(i.filterGroup) ?? i.filterGroup
505
+ filterGroup: s.get(i.filterGroup) ?? i.filterGroup
377
506
  }));
378
507
  },
379
508
  updateFilter(t) {
@@ -384,7 +513,7 @@ const U = () => ({
384
513
  const n = [...e.recommendationConfigs.filters];
385
514
  n[r] = {
386
515
  ...t,
387
- isValid: x(t)
516
+ isValid: V(t)
388
517
  }, e.recommendationConfigs.filters = n;
389
518
  }
390
519
  },
@@ -398,10 +527,10 @@ const U = () => ({
398
527
  let i = 1;
399
528
  n = n.map((o) => o.filterGroup === t.filterGroup ? { ...o, filterNumber: i++ } : o);
400
529
  } else {
401
- const i = [...new Set(n.map((s) => s.filterGroup))].sort((s, a) => s - a), o = new Map(i.map((s, a) => [s, a + 1]));
402
- n = n.map((s) => ({
403
- ...s,
404
- filterGroup: o.get(s.filterGroup) ?? s.filterGroup
530
+ const i = [...new Set(n.map((c) => c.filterGroup))].sort((c, a) => c - a), o = new Map(i.map((c, a) => [c, a + 1]));
531
+ n = n.map((c) => ({
532
+ ...c,
533
+ filterGroup: o.get(c.filterGroup) ?? c.filterGroup
405
534
  }));
406
535
  }
407
536
  e.recommendationConfigs.filters = n;
@@ -410,19 +539,19 @@ const U = () => ({
410
539
  addFilter(t) {
411
540
  if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
412
541
  return;
413
- const e = this.blockStates[this.currentRecommendationId], r = [...e.recommendationConfigs.filters], c = r.filter(
542
+ const e = this.blockStates[this.currentRecommendationId], r = [...e.recommendationConfigs.filters], s = r.filter(
414
543
  (o) => o.filterGroup === t.filterGroup
415
544
  ).length + 1, i = r.findLastIndex((o) => o.filterGroup === t.filterGroup);
416
545
  i !== -1 ? r.splice(i + 1, 0, {
417
546
  ...t,
418
- filterNumber: c
547
+ filterNumber: s
419
548
  }) : r.push({
420
549
  ...t,
421
- filterNumber: c
550
+ filterNumber: s
422
551
  }), e.recommendationConfigs.filters = r;
423
552
  },
424
553
  generateFilterQuery() {
425
- return b(this.recommendationConfigs.filters);
554
+ return G(this.recommendationConfigs.filters);
426
555
  },
427
556
  /**
428
557
  * Validation-only check invoked at save-CTA time. Defined as an action
@@ -430,55 +559,83 @@ const U = () => ({
430
559
  * every block's recommendationConfigs across user edits.
431
560
  */
432
561
  hasInvalidBlock() {
433
- return Object.values(this.blockStates).some((t) => !L(t.recommendationConfigs, this));
562
+ return Object.values(this.blockStates).some((t) => !$(t.recommendationConfigs, this));
434
563
  },
435
564
  // ====================================================================
436
565
  // Per-Block Product Fetching
437
566
  // ====================================================================
438
567
  async fetchRecommendationProducts() {
439
568
  if (!(this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])) {
440
- if (d) {
441
- await d;
569
+ if (S) {
570
+ await S;
442
571
  return;
443
572
  }
444
- d = this._doFetchProducts();
573
+ S = this._doFetchProducts();
445
574
  try {
446
- await d;
575
+ await S;
447
576
  } finally {
448
- d = null;
577
+ S = null;
449
578
  }
450
579
  }
451
580
  },
452
581
  async _doFetchProducts() {
453
- var p;
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 = {
582
+ var f;
583
+ const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = E();
584
+ if (r.strategyId && n.isFeatureEnabled("reusableRecommendationStrategy")) {
585
+ await this._doFetchStrategyProducts(t);
586
+ return;
587
+ }
588
+ const s = r.filters.filter((m) => m.isValid), i = G(s), o = ((f = C().find((m) => m.key === r.strategy)) == null ? void 0 : f.path) || "", c = parseInt(r.size) || 6, a = {
455
589
  locale: r.language,
456
590
  currency: r.currencySettings.value,
457
- partnerName: o.partnerName,
591
+ partnerName: n.partnerName,
458
592
  size: r.size,
459
593
  details: !0,
460
- campaignId: o.variationId
594
+ campaignId: n.variationId
461
595
  };
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(
596
+ r.strategy === "manualMerchandising" ? a.productId = z(r.productIds) : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), i && (a.filter = i), r.shuffleProducts && (a.shuffle = !0), Object.assign(
463
597
  a,
464
- v(o.partnerName, r.strategy)
598
+ O(n.partnerName, r.strategy)
465
599
  );
466
- let f;
600
+ let l;
467
601
  try {
468
- f = await h.fetchRecommendationProducts(i, a);
602
+ l = await d.fetchRecommendationProducts(o, a);
469
603
  } catch {
470
- f = [];
604
+ l = [];
471
605
  }
472
- if (this.blockStates[t]) {
473
- const l = f.length > 0 ? f : S(s);
474
- l.length < s ? this.blockStates[t].recommendationProducts = [
475
- ...l,
476
- ...S(s - l.length)
477
- ] : l.length > s ? this.blockStates[t].recommendationProducts = l.slice(0, s) : this.blockStates[t].recommendationProducts = l;
606
+ this._setBlockProducts(t, l, c);
607
+ },
608
+ async _doFetchStrategyProducts(t) {
609
+ const e = (b.get(t) ?? 0) + 1;
610
+ b.set(t, e);
611
+ const { recommendationConfigs: r } = this.blockStates[t];
612
+ let n = [], s = parseInt(r.size) || 6;
613
+ try {
614
+ await this.fetchStrategies();
615
+ const i = this.strategies.find(
616
+ (o) => String(o.strategy_id) === r.strategyId
617
+ );
618
+ if (i) {
619
+ s = parseInt(String(i.size ?? "")) || s;
620
+ const o = r.currencySettings.value, a = (await this.resolveStrategyUrlTemplate(i, o)).replaceAll("{locale}", r.language).replaceAll("{currency}", o), l = a.indexOf("?"), f = l === -1 ? a : a.slice(0, l), m = (l === -1 ? "" : a.slice(l + 1)).split("&").filter((k) => k && !k.startsWith("user_id=")), R = m.length ? `${f}?${m.join("&")}` : f;
621
+ R && (n = await d.fetchRecommendationProductsByUrl(R));
622
+ }
623
+ } catch {
624
+ n = [];
478
625
  }
626
+ b.get(t) === e && this._setBlockProducts(t, n, s);
627
+ },
628
+ _setBlockProducts(t, e, r) {
629
+ if (!this.blockStates[t])
630
+ return;
631
+ const n = e.length > 0 ? e : v(r);
632
+ this.blockStates[t].recommendationProducts = [
633
+ ...n.slice(0, r),
634
+ ...v(Math.max(0, r - n.length))
635
+ ];
479
636
  }
480
637
  }
481
638
  });
482
639
  export {
483
- H as useRecommendationExtensionStore
640
+ st as useRecommendationExtensionStore
484
641
  };
@@ -1,6 +1,6 @@
1
1
  import { ATTR_PRODUCT_PRICE as f, ATTR_PRODUCT_OLD_PRICE as O } from "../../constants/selectors.js";
2
2
  import { DEFAULT_PRODUCTS_PER_ROW as w } from "../../constants/layout.js";
3
- import { getDefaultProducts as A, DEFAULTS as g, createBlockTemplate as U, buildSpacer as h, DEFAULT_CARD_COMPOSITION as Y, buildElementRenderer as B, resolveInlinePriceOrder as F, buildCellOptions as I, DEFAULT_CARD_VISIBILITY as W } from "../utils.js";
3
+ import { createBlockTemplate as A, getDefaultProducts as g, DEFAULTS as U, buildSpacer as h, DEFAULT_CARD_COMPOSITION as Y, buildElementRenderer as B, resolveInlinePriceOrder as F, buildCellOptions as I, DEFAULT_CARD_VISIBILITY as W } from "../utils.js";
4
4
  import { DEFAULT_CELL_PADDING as k, renderInlineGridPriceCell as H, buildFillerCell as x, gridElementRenderer as y } from "./elementRenderer.js";
5
5
  const G = `
6
6
  <tr class="recommendation-product-row">
@@ -69,8 +69,8 @@ function M(t, r, o, e = {}, c = {}) {
69
69
  );
70
70
  }
71
71
  function Q(t) {
72
- const r = t ? `ins-recommendation-v3-block-${t}` : void 0, o = U("grid", r), e = A(), c = M(e, w);
73
- return o.replace("{-{-TITLE-}-}", g.TITLE).replace("{-{-PRODUCT_ROWS-}-}", c).replace("{-{-MOBILE_PRODUCT_ROWS-}-}", "");
72
+ const r = t ? `ins-recommendation-v3-block-${t}` : void 0, o = A("grid", r), e = g(), c = M(e, w);
73
+ return o.replace("{-{-TITLE-}-}", U.TITLE).replace("{-{-PRODUCT_ROWS-}-}", c).replace("{-{-MOBILE_PRODUCT_ROWS-}-}", "");
74
74
  }
75
75
  export {
76
76
  Q as getDefaultTemplate,
@@ -0,0 +1,33 @@
1
+ import { RecommendationBlockId as r } from "../constants/blockIds.js";
2
+ import { DEFAULT_ROW_SPACING as l } from "../constants/layout.js";
3
+ import { CSS_CLASS_ATTRIBUTE_ROW as d, ATTR_RECOMMENDATION_TITLE as n, ATTR_DATA_VISIBILITY as A, CSS_CLASS_TITLE_CELL as _, CSS_CLASS_SPACER as c } from "../constants/selectors.js";
4
+ const a = "You May Also Like!", i = '<p style="font-size: 28px; color: #333333;"><strong>{-{-TITLE-}-}</strong></p>';
5
+ function E(s = i, t = !0, T = l) {
6
+ const e = `class="${d}" data-attribute-type="${n}" ${A}="${t ? "1" : "0"}"`, o = t ? "" : ' style="display: none;"';
7
+ return `
8
+ <tr ${e}${o}>
9
+ <td>
10
+ <table width="100%" cellpadding="0" cellspacing="0" border="0">
11
+ <tbody>
12
+ <tr>
13
+ <td
14
+ class="esd-block-text ${_} es-p10t es-p10b es-p20l es-p20r"
15
+ align="center"
16
+ esd-extension-block-id="${r.TITLE}">
17
+ ${s}
18
+ </td>
19
+ </tr>
20
+ </tbody>
21
+ </table>
22
+ </td>
23
+ </tr>
24
+ <tr ${e}${o}>
25
+ <td class="${c}" style="height: ${T}px;"></td>
26
+ </tr>
27
+ `;
28
+ }
29
+ export {
30
+ i as DEFAULT_TITLE_PARAGRAPH,
31
+ a as DEFAULT_TITLE_TEXT,
32
+ E as buildTitleRows
33
+ };