@useinsider/guido 3.16.0-beta.f1a5d40 → 3.16.0-beta.ff4f1bd

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 (73) hide show
  1. package/README.md +6 -5
  2. package/dist/@types/config/schemas.js +12 -6
  3. package/dist/components/Guido.vue.js +6 -6
  4. package/dist/components/Guido.vue2.js +31 -30
  5. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +18 -0
  6. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +61 -0
  7. package/dist/composables/useRecommendation.js +43 -36
  8. package/dist/config/migrator/recommendationMigrator.js +6 -4
  9. package/dist/enums/extensions/recommendationBlock.js +25 -23
  10. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +13 -11
  11. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +112 -90
  12. package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +106 -0
  13. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +188 -53
  14. package/dist/guido.css +1 -1
  15. package/dist/node_modules/@useinsider/design-system-organisms/dist/index-5JHlb8rM.js +524 -0
  16. package/dist/node_modules/@useinsider/design-system-organisms/dist/index.js +8450 -0
  17. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InAccordion.js +174 -0
  18. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InBasicTextInput.js +381 -0
  19. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InBox.js +236 -0
  20. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InBulkActions.js +70 -0
  21. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InButton.js +350 -0
  22. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InButtonV2.js +371 -0
  23. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InCheckBox.js +152 -0
  24. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InChips.js +141 -0
  25. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InCustomDropDown.js +1047 -0
  26. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InDataTableV2.js +96050 -0
  27. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InDatePicker.js +2042 -0
  28. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InDrawer.js +166 -0
  29. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InDropDown.js +1098 -0
  30. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InIcons.js +55 -0
  31. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InInfoBox.js +265 -0
  32. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InLinks.js +184 -0
  33. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InLoading.js +50 -0
  34. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InModals.js +453 -0
  35. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InNoData.js +145 -0
  36. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InOnPageMessage.js +176 -0
  37. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InProgress.js +266 -0
  38. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InRadioButton.js +114 -0
  39. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InSegments.js +200 -0
  40. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InSelect.js +451 -0
  41. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InSkeleton.js +49 -0
  42. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InStatusText.js +119 -0
  43. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InTabs.js +4309 -0
  44. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InTagsText.js +129 -0
  45. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InTextInput.js +503 -0
  46. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InToasts.js +253 -0
  47. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InToggle.js +107 -0
  48. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InTooltip.js +134 -0
  49. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/InTooltipV2.js +464 -0
  50. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/chunks/_commonjsHelpers.BItOPCY9.js +28 -0
  51. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/chunks/_plugin-vue2_normalizer.WQT2Fc8L.js +23 -0
  52. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/chunks/clickOutside.qP9M0QCm.js +29 -0
  53. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/chunks/helpers.CgHNyjAJ.js +109 -0
  54. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/chunks/index.Bw_06igr.js +2339 -0
  55. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/chunks/localLocalesMixin.DYMhydo2.js +16 -0
  56. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/chunks/useLocalLocales.Ckuhy7d-.js +17 -0
  57. package/dist/node_modules/@useinsider/design-system-organisms/node_modules/@useinsider/design-system-vue/dist/chunks/vue-property-decorator.BtlM7Epa.js +188 -0
  58. package/dist/services/recommendationApi.js +77 -28
  59. package/dist/src/@types/config/schemas.d.ts +12 -0
  60. package/dist/src/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.d.ts +3 -0
  61. package/dist/src/components/wrappers/WpModal.vue.d.ts +1 -1
  62. package/dist/src/composables/useConfig.d.ts +2 -0
  63. package/dist/src/composables/useRecommendation.d.ts +1 -0
  64. package/dist/src/enums/extensions/recommendationBlock.d.ts +2 -0
  65. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +6 -3
  66. package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +26 -0
  67. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +199 -10
  68. package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +6 -0
  69. package/dist/src/mock/api/recommendation-strategies.d.ts +41 -0
  70. package/dist/src/services/recommendationApi.d.ts +4 -1
  71. package/dist/src/stores/config.d.ts +18 -0
  72. package/dist/utils/templatePreparation.js +37 -34
  73. package/package.json +3 -2
@@ -1,20 +1,20 @@
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 F } from "pinia";
1
+ import { getRecommendationFeedSourceMaps as p, getOperatorOptions as R, PriceAttributes as C } from "../../../../enums/extensions/recommendationBlock.js";
2
+ import { useRecommendationApi as w } from "../../../../services/recommendationApi.js";
3
+ import { useConfigStore as P } from "../../../../stores/config.js";
4
+ import { defineStore as G } from "pinia";
5
5
  import "../constants/selectors.js";
6
- import { DEFAULT_MOBILE_CARDS_IN_ROW as P, 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";
6
+ import { DEFAULT_MOBILE_CARDS_IN_ROW as D, DEFAULT_CARDS_IN_ROW as F } from "../constants/layout.js";
7
+ import { EXCLUDED_ALGORITHM_IDS as v } from "../constants/defaultConfig.js";
8
+ import { getDefaultProducts as y } from "../templates/utils.js";
9
9
  import { generateCompleteFilterQuery as b } from "../utils/filterUtil.js";
10
- import { getPartnerRecommendationParams as v } from "../utils/partnerCustomizations.js";
11
- import { isFilterValid as N } from "../validation/filterSchema.js";
12
- import { isConfigValid as x } from "../validation/requiredFields.js";
13
- const h = y();
14
- let m = null, u = null, d = null;
10
+ import { getPartnerRecommendationParams as U } from "../utils/partnerCustomizations.js";
11
+ import { isFilterValid as _ } from "../validation/filterSchema.js";
12
+ import { isConfigValid as L } from "../validation/requiredFields.js";
13
+ const l = w();
14
+ let m = null, u = null, d = null, f = null;
15
15
  function k() {
16
16
  return {
17
- cardsInRow: D,
17
+ cardsInRow: F,
18
18
  currencySettings: {
19
19
  name: "USD",
20
20
  value: "USD",
@@ -28,13 +28,14 @@ function k() {
28
28
  productIds: [],
29
29
  id: 1,
30
30
  language: "en_US",
31
- mobileCardsInRow: P,
31
+ mobileCardsInRow: D,
32
32
  mobileLayoutEnabled: !1,
33
33
  orientation: "grid",
34
34
  recommendedProducts: [],
35
35
  sendProductRequestFlag: !1,
36
36
  shuffleProducts: !1,
37
37
  strategy: "mostPopular",
38
+ strategyId: "",
38
39
  textTrimming: !0,
39
40
  unresponsive: !1,
40
41
  size: "6",
@@ -49,22 +50,26 @@ function I() {
49
50
  recommendationProducts: [],
50
51
  filterStatus: !1,
51
52
  filterSelectionDrawerStatus: !1,
53
+ assignStrategyDrawerStatus: !1,
52
54
  filterGroup: 1,
53
55
  isInitialized: !1,
54
56
  filterSnapshot: null
55
57
  };
56
58
  }
57
- const L = () => ({
59
+ const N = () => ({
58
60
  recommendationCampaignUrls: {},
59
61
  activePredictiveAlgorithms: [],
60
62
  languages: {},
61
63
  currencyList: [],
62
64
  filterList: {},
65
+ strategies: [],
66
+ strategiesLoading: !1,
67
+ strategyUrlTemplates: {},
63
68
  blockStates: {},
64
69
  currentRecommendationId: null,
65
70
  configVersion: 0
66
- }), $ = F("guidoRecommendationExtension", {
67
- state: () => L(),
71
+ }), q = G("guidoRecommendationExtension", {
72
+ state: () => N(),
68
73
  getters: {
69
74
  // ====================================================================
70
75
  // Proxy Getters — Backward Compatible Access to Current Block State
@@ -88,6 +93,20 @@ const L = () => ({
88
93
  filterSelectionDrawerStatus(t) {
89
94
  return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].filterSelectionDrawerStatus : !1;
90
95
  },
96
+ /**
97
+ * Proxy getter: delegates to blockStates[currentRecommendationId].assignStrategyDrawerStatus
98
+ */
99
+ assignStrategyDrawerStatus(t) {
100
+ return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].assignStrategyDrawerStatus : !1;
101
+ },
102
+ /**
103
+ * The current block's assigned strategy record from the listing,
104
+ * or null when nothing is assigned / the strategy is no longer listed.
105
+ */
106
+ assignedStrategy(t) {
107
+ const { strategyId: e } = this.recommendationConfigs;
108
+ return e ? t.strategies.find((r) => String(r.strategy_id) === e) ?? null : null;
109
+ },
91
110
  /**
92
111
  * Proxy getter: delegates to blockStates[currentRecommendationId].filterStatus
93
112
  */
@@ -119,9 +138,9 @@ const L = () => ({
119
138
  return [...new Set(t.map((e) => e.filterGroup))].sort((e, r) => e - r);
120
139
  },
121
140
  getActivePredictiveAlgorithms: (t) => {
122
- const e = g(), r = [];
123
- return t.activePredictiveAlgorithms.filter((n) => !w.includes(n)).forEach((n) => {
124
- r.push(...e.filter((c) => c.id === n));
141
+ const e = p(), r = [];
142
+ return t.activePredictiveAlgorithms.filter((n) => !v.includes(n)).forEach((n) => {
143
+ r.push(...e.filter((s) => s.id === n));
125
144
  }), r.map((n) => ({
126
145
  text: n.name,
127
146
  value: n.key
@@ -192,10 +211,10 @@ const L = () => ({
192
211
  [e]: o
193
212
  };
194
213
  }
195
- const n = t.toString(), c = e.toString(), i = this.recommendationCampaignUrls[n];
214
+ const n = t.toString(), s = e.toString(), i = this.recommendationCampaignUrls[n];
196
215
  i && (this.recommendationCampaignUrls = {
197
216
  ...this.recommendationCampaignUrls,
198
- [c]: i
217
+ [s]: i
199
218
  });
200
219
  },
201
220
  /**
@@ -220,7 +239,7 @@ const L = () => ({
220
239
  * `isInitialized`) alone.
221
240
  */
222
241
  seedBlockUrlConfig(t, e) {
223
- const r = (o, s) => o === "." || o === "," || o === " " ? o : s, n = {
242
+ const r = (o, a) => o === "." || o === "," || o === " " ? o : a, n = {
224
243
  name: e.currencyCode,
225
244
  value: e.currencyCode,
226
245
  symbol: e.currencyCode,
@@ -228,17 +247,18 @@ const L = () => ({
228
247
  decimalCount: String(e.currencyDecimalCount),
229
248
  decimalSeparator: r(e.currencyDecimalSeparator, ","),
230
249
  thousandSeparator: r(e.currencyThousandSeparator, ".")
231
- }, c = !this.blockStates[t], i = c ? I() : this.blockStates[t];
250
+ }, s = !this.blockStates[t], i = s ? I() : this.blockStates[t];
232
251
  i.recommendationConfigs = {
233
252
  ...i.recommendationConfigs,
234
253
  strategy: e.strategy,
254
+ strategyId: e.strategyId,
235
255
  language: e.language,
236
256
  size: e.size,
237
257
  productIds: e.productIds,
238
258
  filters: e.filters,
239
259
  shuffleProducts: e.shuffleProducts,
240
260
  currencySettings: n
241
- }, c && (this.blockStates = {
261
+ }, s && (this.blockStates = {
242
262
  ...this.blockStates,
243
263
  [t]: i
244
264
  });
@@ -314,6 +334,78 @@ const L = () => ({
314
334
  t.filterSnapshot !== null && (t.recommendationConfigs.filters = t.filterSnapshot, t.filterSnapshot = null), t.filterSelectionDrawerStatus = !1;
315
335
  },
316
336
  // ====================================================================
337
+ // Reusable Recommendation Strategy (SD-149105)
338
+ // ====================================================================
339
+ /**
340
+ * Opens the Assign Strategy drawer for the current block.
341
+ * Selection state lives in the drawer component until Assign is
342
+ * pressed, so closing without assigning needs no snapshot/revert.
343
+ */
344
+ openAssignStrategyDrawer() {
345
+ this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].assignStrategyDrawerStatus = !0);
346
+ },
347
+ closeAssignStrategyDrawer() {
348
+ this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].assignStrategyDrawerStatus = !1);
349
+ },
350
+ /**
351
+ * Fetches the active + EMAIL strategy listing. Always fetches fresh
352
+ * (dead-strategy detection and post-create refresh need freshness);
353
+ * only concurrent in-flight calls share one request.
354
+ */
355
+ async fetchStrategies() {
356
+ if (f) {
357
+ await f;
358
+ return;
359
+ }
360
+ f = (async () => {
361
+ this.strategiesLoading = !0;
362
+ try {
363
+ this.strategies = await l.fetchRecommendationStrategies();
364
+ } finally {
365
+ this.strategiesLoading = !1;
366
+ }
367
+ })();
368
+ try {
369
+ await f;
370
+ } finally {
371
+ f = null;
372
+ }
373
+ },
374
+ /**
375
+ * Resolves a strategy's recommendation endpoint template via
376
+ * endpoint-generate, cached per strategy id. Failures throw and are
377
+ * NOT cached, so the next attempt retries.
378
+ */
379
+ async resolveStrategyUrlTemplate(t) {
380
+ const e = String(t.strategy_id), r = this.strategyUrlTemplates[e];
381
+ if (r)
382
+ return r;
383
+ const { full_path: n } = await l.generateStrategyEndpoint(t);
384
+ return this.strategyUrlTemplates = {
385
+ ...this.strategyUrlTemplates,
386
+ [e]: n
387
+ }, n;
388
+ },
389
+ /**
390
+ * Assigns a strategy to the current block. The config write is
391
+ * synchronous (before any await) so a block switch cannot misdirect
392
+ * it; the configVersion bump persists it to node config and triggers
393
+ * the product refetch via the coordinator control's subscription.
394
+ */
395
+ assignStrategy(t) {
396
+ this.patchCurrentBlockConfig({
397
+ strategyId: String(t.strategy_id),
398
+ ...t.size !== void 0 ? { size: String(t.size) } : {}
399
+ });
400
+ },
401
+ /**
402
+ * Clears the current block's strategy; it falls back to the
403
+ * per-block algorithm settings.
404
+ */
405
+ removeStrategy() {
406
+ this.patchCurrentBlockConfig({ strategyId: "" });
407
+ },
408
+ // ====================================================================
317
409
  // Shared Data Fetching (fetched once, used by all blocks)
318
410
  // ====================================================================
319
411
  async fetchRecommendationCreateData() {
@@ -327,7 +419,7 @@ const L = () => ({
327
419
  activePredictiveAlgorithms: t,
328
420
  languages: e,
329
421
  currencies: r
330
- } = await h.fetchRecommendationCreateData();
422
+ } = await l.fetchRecommendationCreateData();
331
423
  if (this.activePredictiveAlgorithms = t, this.languages = e, this.currentRecommendationId !== null && this.blockStates[this.currentRecommendationId]) {
332
424
  const n = this.blockStates[this.currentRecommendationId];
333
425
  n.filterStatus = !!n.recommendationConfigs.filters.length;
@@ -348,7 +440,7 @@ const L = () => ({
348
440
  return;
349
441
  }
350
442
  u = (async () => {
351
- const t = await h.fetchRecommendationFilters();
443
+ const t = await l.fetchRecommendationFilters();
352
444
  this.filterList = t;
353
445
  })();
354
446
  try {
@@ -369,10 +461,10 @@ const L = () => ({
369
461
  deleteFilterGroup(t) {
370
462
  if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
371
463
  return;
372
- 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]));
464
+ 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]));
373
465
  e.recommendationConfigs.filters = r.map((i) => ({
374
466
  ...i,
375
- filterGroup: c.get(i.filterGroup) ?? i.filterGroup
467
+ filterGroup: s.get(i.filterGroup) ?? i.filterGroup
376
468
  }));
377
469
  },
378
470
  updateFilter(t) {
@@ -383,7 +475,7 @@ const L = () => ({
383
475
  const n = [...e.recommendationConfigs.filters];
384
476
  n[r] = {
385
477
  ...t,
386
- isValid: N(t)
478
+ isValid: _(t)
387
479
  }, e.recommendationConfigs.filters = n;
388
480
  }
389
481
  },
@@ -397,10 +489,10 @@ const L = () => ({
397
489
  let i = 1;
398
490
  n = n.map((o) => o.filterGroup === t.filterGroup ? { ...o, filterNumber: i++ } : o);
399
491
  } else {
400
- const i = [...new Set(n.map((s) => s.filterGroup))].sort((s, a) => s - a), o = new Map(i.map((s, a) => [s, a + 1]));
401
- n = n.map((s) => ({
402
- ...s,
403
- filterGroup: o.get(s.filterGroup) ?? s.filterGroup
492
+ const i = [...new Set(n.map((a) => a.filterGroup))].sort((a, c) => a - c), o = new Map(i.map((a, c) => [a, c + 1]));
493
+ n = n.map((a) => ({
494
+ ...a,
495
+ filterGroup: o.get(a.filterGroup) ?? a.filterGroup
404
496
  }));
405
497
  }
406
498
  e.recommendationConfigs.filters = n;
@@ -409,15 +501,15 @@ const L = () => ({
409
501
  addFilter(t) {
410
502
  if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
411
503
  return;
412
- const e = this.blockStates[this.currentRecommendationId], r = [...e.recommendationConfigs.filters], c = r.filter(
504
+ const e = this.blockStates[this.currentRecommendationId], r = [...e.recommendationConfigs.filters], s = r.filter(
413
505
  (o) => o.filterGroup === t.filterGroup
414
506
  ).length + 1, i = r.findLastIndex((o) => o.filterGroup === t.filterGroup);
415
507
  i !== -1 ? r.splice(i + 1, 0, {
416
508
  ...t,
417
- filterNumber: c
509
+ filterNumber: s
418
510
  }) : r.push({
419
511
  ...t,
420
- filterNumber: c
512
+ filterNumber: s
421
513
  }), e.recommendationConfigs.filters = r;
422
514
  },
423
515
  generateFilterQuery() {
@@ -429,7 +521,7 @@ const L = () => ({
429
521
  * every block's recommendationConfigs across user edits.
430
522
  */
431
523
  hasInvalidBlock() {
432
- return Object.values(this.blockStates).some((t) => !x(t.recommendationConfigs, this));
524
+ return Object.values(this.blockStates).some((t) => !L(t.recommendationConfigs, this));
433
525
  },
434
526
  // ====================================================================
435
527
  // Per-Block Product Fetching
@@ -449,8 +541,13 @@ const L = () => ({
449
541
  }
450
542
  },
451
543
  async _doFetchProducts() {
452
- var p;
453
- 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 = {
544
+ var S;
545
+ const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e;
546
+ if (r.strategyId) {
547
+ await this._doFetchStrategyProducts(t);
548
+ return;
549
+ }
550
+ const n = r.filters.filter((h) => h.isValid), s = b(n), i = ((S = p().find((h) => h.key === r.strategy)) == null ? void 0 : S.path) || "", o = P(), a = parseInt(r.size) || 6, c = {
454
551
  locale: r.language,
455
552
  currency: r.currencySettings.value,
456
553
  partnerName: o.partnerName,
@@ -458,26 +555,64 @@ const L = () => ({
458
555
  details: !0,
459
556
  campaignId: o.variationId
460
557
  };
461
- r.strategy === "manualMerchandising" ? a.productId = r.productIds.join(",") : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), c && (a.filter = c), r.shuffleProducts && (a.shuffle = !0), Object.assign(
462
- a,
463
- v(o.partnerName, r.strategy)
558
+ r.strategy === "manualMerchandising" ? c.productId = r.productIds.join(",") : r.strategy === "similarViewed" && (c.productId = "{itemId}"), r.strategy === "userBased" && (c.userId = "{user_id}"), s && (c.filter = s), r.shuffleProducts && (c.shuffle = !0), Object.assign(
559
+ c,
560
+ U(o.partnerName, r.strategy)
464
561
  );
465
- let f;
562
+ let g;
466
563
  try {
467
- f = await h.fetchRecommendationProducts(i, a);
564
+ g = await l.fetchRecommendationProducts(i, c);
468
565
  } catch {
469
- f = [];
566
+ g = [];
470
567
  }
471
- if (this.blockStates[t]) {
472
- const l = f.length > 0 ? f : S(s);
473
- l.length < s ? this.blockStates[t].recommendationProducts = [
474
- ...l,
475
- ...S(s - l.length)
476
- ] : l.length > s ? this.blockStates[t].recommendationProducts = l.slice(0, s) : this.blockStates[t].recommendationProducts = l;
568
+ this._setBlockProducts(t, g, a);
569
+ },
570
+ /**
571
+ * Fetches products for a strategy-backed block: listing lookup →
572
+ * endpoint-generate template → fill {locale}/{currency}, drop
573
+ * {user_id} (resolved at send time) → fetch. Any failure (dead
574
+ * strategy, resolution error) falls back to placeholder products.
575
+ */
576
+ async _doFetchStrategyProducts(t) {
577
+ const { recommendationConfigs: e } = this.blockStates[t];
578
+ let r = [], n = parseInt(e.size) || 6;
579
+ try {
580
+ this.strategies.length || await this.fetchStrategies();
581
+ const s = this.strategies.find(
582
+ (i) => String(i.strategy_id) === e.strategyId
583
+ );
584
+ if (s) {
585
+ n = parseInt(String(s.size ?? "")) || n;
586
+ const i = await this.resolveStrategyUrlTemplate(s), o = new URL(
587
+ i.replaceAll("{locale}", e.language).replaceAll("{currency}", e.currencySettings.value)
588
+ );
589
+ o.searchParams.delete("user_id"), r = await l.fetchRecommendationProductsByUrl(o.toString());
590
+ }
591
+ } catch {
592
+ r = [];
477
593
  }
594
+ this._setBlockProducts(t, r, n);
595
+ },
596
+ /**
597
+ * Writes products to a block's state, padded/clipped to `size` so
598
+ * in-place content updates (which compare DOM element count vs
599
+ * products.length) succeed:
600
+ * - API returned nothing → fill entirely with defaults
601
+ * - fewer than requested → pad with dummies
602
+ * - more than requested → clip, preventing the renderer from extending
603
+ * its slot grid (which would reset migrator-applied styles).
604
+ */
605
+ _setBlockProducts(t, e, r) {
606
+ if (!this.blockStates[t])
607
+ return;
608
+ const n = e.length > 0 ? e : y(r);
609
+ n.length < r ? this.blockStates[t].recommendationProducts = [
610
+ ...n,
611
+ ...y(r - n.length)
612
+ ] : n.length > r ? this.blockStates[t].recommendationProducts = n.slice(0, r) : this.blockStates[t].recommendationProducts = n;
478
613
  }
479
614
  }
480
615
  });
481
616
  export {
482
- $ as useRecommendationExtensionStore
617
+ q as useRecommendationExtensionStore
483
618
  };