@useinsider/guido 3.19.0-beta.cac604e → 3.19.0-beta.cd25cc8

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 (67) hide show
  1. package/dist/components/Guido.vue.js +6 -6
  2. package/dist/components/Guido.vue2.js +96 -85
  3. package/dist/components/organisms/base/AuthErrorModal.vue.js +18 -0
  4. package/dist/components/organisms/base/AuthErrorModal.vue2.js +42 -0
  5. package/dist/components/wrappers/WpModal.vue.js +1 -1
  6. package/dist/components/wrappers/WpModal.vue2.js +4 -3
  7. package/dist/composables/useAuthError.js +52 -0
  8. package/dist/composables/useAutoSave.js +11 -11
  9. package/dist/composables/useCortexBlueprintBridge.js +122 -54
  10. package/dist/composables/useEmailTemplateApplier.js +111 -50
  11. package/dist/composables/useHttp.js +64 -54
  12. package/dist/composables/useLegacyStrategyConversion.js +23 -19
  13. package/dist/composables/useStripo.js +24 -20
  14. package/dist/composables/useToaster.js +17 -15
  15. package/dist/composables/validators/useLiquidValidator.js +15 -15
  16. package/dist/config/migrator/index.js +14 -13
  17. package/dist/config/migrator/itemsBlockMigrator.js +236 -248
  18. package/dist/config/migrator/recommendationMigrator.js +28 -21
  19. package/dist/config/migrator/recommendationPartnerMigrator.js +56 -0
  20. package/dist/enums/extensions/recommendationBlock.js +30 -29
  21. package/dist/extensions/Blocks/Items/constants/cardLayout.js +20 -0
  22. package/dist/extensions/Blocks/Items/controls/name/trimming.js +18 -17
  23. package/dist/extensions/Blocks/Items/controls/settingsControl.js +114 -105
  24. package/dist/extensions/Blocks/Items/enums/productEnums.js +14 -9
  25. package/dist/extensions/Blocks/Items/layouts/horizontal.html.js +11 -9
  26. package/dist/extensions/Blocks/Items/template.js +219 -204
  27. package/dist/extensions/Blocks/Recommendation/block.js +53 -85
  28. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +90 -73
  29. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +209 -203
  30. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +126 -112
  31. package/dist/extensions/Blocks/Recommendation/utils/blockUrlConfig.js +25 -0
  32. package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +26 -21
  33. package/dist/extensions/Blocks/Recommendation/utils/partnerScope.js +11 -12
  34. package/dist/extensions/Blocks/Recommendation/utils/strategyCommit.js +40 -17
  35. package/dist/guido.css +1 -1
  36. package/dist/src/components/organisms/base/AuthErrorModal.vue.d.ts +2 -0
  37. package/dist/src/components/wrappers/WpModal.vue.d.ts +5 -1
  38. package/dist/src/composables/useAuthError.d.ts +12 -0
  39. package/dist/src/composables/useCortexBlueprintBridge.d.ts +2 -3
  40. package/dist/src/composables/useEmailTemplateApplier.d.ts +18 -5
  41. package/dist/src/composables/useGuidoActions.d.ts +2 -0
  42. package/dist/src/composables/useHttp.d.ts +2 -0
  43. package/dist/src/config/migrator/index.d.ts +2 -1
  44. package/dist/src/config/migrator/recommendationPartnerMigrator.d.ts +19 -0
  45. package/dist/src/enums/extensions/recommendationBlock.d.ts +1 -1
  46. package/dist/src/extensions/Blocks/Items/constants/cardLayout.d.ts +44 -0
  47. package/dist/src/extensions/Blocks/Items/enums/productEnums.d.ts +3 -0
  48. package/dist/src/extensions/Blocks/Items/template.d.ts +19 -0
  49. package/dist/src/extensions/Blocks/Recommendation/block.d.ts +0 -6
  50. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +2 -0
  51. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +16 -7
  52. package/dist/src/extensions/Blocks/Recommendation/utils/blockUrlConfig.d.ts +4 -0
  53. package/dist/src/extensions/Blocks/Recommendation/utils/nodeConfigWriter.d.ts +3 -1
  54. package/dist/src/extensions/Blocks/Recommendation/utils/partnerScope.d.ts +13 -7
  55. package/dist/src/extensions/Blocks/Recommendation/utils/strategyCommit.d.ts +7 -0
  56. package/dist/src/mock/cortexChatStore.d.ts +12 -0
  57. package/dist/src/stores/guido-email-editor.d.ts +20 -10
  58. package/dist/src/stores/onboarding.d.ts +4 -0
  59. package/dist/src/stores/recommendation.d.ts +5 -0
  60. package/dist/src/utils/dateUtil.d.ts +10 -0
  61. package/dist/src/utils/genericUtil.d.ts +3 -0
  62. package/dist/static/styles/components/version-history.css.js +2 -6
  63. package/dist/stores/guido-email-editor.js +3 -1
  64. package/dist/stores/onboarding.js +4 -0
  65. package/dist/utils/pairProductVariables.js +71 -71
  66. package/dist/utils/templatePreparation.js +61 -85
  67. package/package.json +1 -1
@@ -1,27 +1,31 @@
1
- import { useToaster as D } from "../../../../composables/useToaster.js";
2
- import { useTranslations as L } from "../../../../composables/useTranslations.js";
3
- import { getRecommendationFeedSourceMaps as F, strategyEditPath as U, URLS as E, getOperatorOptions as N, PriceAttributes as M } from "../../../../enums/extensions/recommendationBlock.js";
4
- import { ToasterTypeOptions as A } from "../../../../enums/toaster.js";
5
- import { useRecommendationApi as T } from "../../../../services/recommendationApi.js";
1
+ import { useToaster as U } from "../../../../composables/useToaster.js";
2
+ import { useTranslations as M } from "../../../../composables/useTranslations.js";
3
+ import { getRecommendationFeedSourceMaps as w, strategyEditPath as N, strategyCreatePath as B, getOperatorOptions as z, PriceAttributes as E } from "../../../../enums/extensions/recommendationBlock.js";
4
+ import { ToasterTypeOptions as O } from "../../../../enums/toaster.js";
5
+ import { useRecommendationApi as A } from "../../../../services/recommendationApi.js";
6
6
  import { useConfigStore as R } from "../../../../stores/config.js";
7
- import { defineStore as B } from "pinia";
7
+ import { defineStore as x } from "pinia";
8
8
  import "../constants/selectors.js";
9
- import { DEFAULT_MOBILE_CARDS_IN_ROW as O, DEFAULT_CARDS_IN_ROW as z } from "../constants/layout.js";
10
- import { CURRENT_CONFIG_VERSION as C, DEFAULT_NODE_CONFIG as x, EXCLUDED_ALGORITHM_IDS as V } from "../constants/defaultConfig.js";
11
- import { getDefaultProducts as w } from "../templates/utils.js";
12
- import { generateCompleteFilterQuery as P } from "../utils/filterUtil.js";
13
- import { isLegacyStrategyConfig as j } from "../utils/legacyStrategyMigration.js";
14
- import { getPartnerRecommendationParams as $ } from "../utils/partnerCustomizations.js";
15
- import { sanitizeProductIds as K } from "../utils/productIds.js";
16
- import { isFilterValid as q } from "../validation/filterSchema.js";
17
- import { getInvalidFields as H, isConfigValid as J } from "../validation/requiredFields.js";
18
- const m = T();
19
- let S = null, p = null, y = null, b = "", k = null, I = 0;
20
- const g = /* @__PURE__ */ new Map();
9
+ import { DEFAULT_MOBILE_CARDS_IN_ROW as T, DEFAULT_CARDS_IN_ROW as V } from "../constants/layout.js";
10
+ import { CURRENT_CONFIG_VERSION as C, DEFAULT_NODE_CONFIG as j, EXCLUDED_ALGORITHM_IDS as $ } from "../constants/defaultConfig.js";
11
+ import { getDefaultProducts as P } from "../templates/utils.js";
12
+ import { generateCompleteFilterQuery as G } from "../utils/filterUtil.js";
13
+ import { isLegacyStrategyConfig as q } from "../utils/legacyStrategyMigration.js";
14
+ import { getPartnerRecommendationParams as K } from "../utils/partnerCustomizations.js";
15
+ import { sanitizeProductIds as H } from "../utils/productIds.js";
16
+ import { isFilterValid as J } from "../validation/filterSchema.js";
17
+ import { getInvalidFields as Q, isConfigValid as W } from "../validation/requiredFields.js";
18
+ const u = A();
19
+ let S = null, y = null, p = null, I = "", k = null, b = 0;
20
+ const m = /* @__PURE__ */ new Map(), D = /* @__PURE__ */ new Map();
21
+ function X(t) {
22
+ const e = D.get(t);
23
+ return e && e.token === m.get(t) ? e.outcome : !1;
24
+ }
21
25
  let l = null;
22
- function _() {
26
+ function L() {
23
27
  return {
24
- cardsInRow: z,
28
+ cardsInRow: V,
25
29
  currencySettings: {
26
30
  name: "USD",
27
31
  value: "USD",
@@ -35,7 +39,7 @@ function _() {
35
39
  productIds: [],
36
40
  id: 1,
37
41
  language: "en_US",
38
- mobileCardsInRow: O,
42
+ mobileCardsInRow: T,
39
43
  mobileLayoutEnabled: !1,
40
44
  orientation: "grid",
41
45
  recommendedProducts: [],
@@ -56,9 +60,9 @@ function _() {
56
60
  priceHideIfSameAsDiscounted: !1
57
61
  };
58
62
  }
59
- function G() {
63
+ function _() {
60
64
  return {
61
- recommendationConfigs: _(),
65
+ recommendationConfigs: L(),
62
66
  recommendationProducts: [],
63
67
  filterStatus: !1,
64
68
  filterSelectionDrawerStatus: !1,
@@ -72,7 +76,7 @@ function G() {
72
76
  legacyConversionLoading: !1
73
77
  };
74
78
  }
75
- const Q = () => ({
79
+ const Y = () => ({
76
80
  recommendationCampaignUrls: {},
77
81
  activePredictiveAlgorithms: [],
78
82
  languages: {},
@@ -87,8 +91,8 @@ const Q = () => ({
87
91
  currentRecommendationId: null,
88
92
  strategyPanelOpen: !1,
89
93
  configVersion: 0
90
- }), ft = B("guidoRecommendationExtension", {
91
- state: () => Q(),
94
+ }), St = x("guidoRecommendationExtension", {
95
+ state: () => Y(),
92
96
  getters: {
93
97
  // ====================================================================
94
98
  // Proxy Getters — Backward Compatible Access to Current Block State
@@ -98,7 +102,7 @@ const Q = () => ({
98
102
  * This allows all existing code that reads `store.recommendationConfigs` to work unchanged.
99
103
  */
100
104
  recommendationConfigs(t) {
101
- return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : _();
105
+ return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : L();
102
106
  },
103
107
  /**
104
108
  * Proxy getter: delegates to blockStates[currentRecommendationId].recommendationProducts
@@ -119,7 +123,7 @@ const Q = () => ({
119
123
  return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].removeStrategyModalStatus : !1;
120
124
  },
121
125
  isLegacyStrategyBlock() {
122
- return R().isFeatureEnabled("reusableRecommendationStrategy") && j(this.recommendationConfigs);
126
+ return R().isFeatureEnabled("reusableRecommendationStrategy") && q(this.recommendationConfigs);
123
127
  },
124
128
  legacyConversionLoading(t) {
125
129
  return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].legacyConversionLoading ?? !1 : !1;
@@ -162,8 +166,8 @@ const Q = () => ({
162
166
  return [...new Set(t.map((e) => e.filterGroup))].sort((e, r) => e - r);
163
167
  },
164
168
  getActivePredictiveAlgorithms: (t) => {
165
- const e = F(), r = [];
166
- return t.activePredictiveAlgorithms.filter((n) => !V.includes(n)).forEach((n) => {
169
+ const e = w(), r = [];
170
+ return t.activePredictiveAlgorithms.filter((n) => !$.includes(n)).forEach((n) => {
167
171
  r.push(...e.filter((s) => s.id === n));
168
172
  }), r.map((n) => ({
169
173
  text: n.name,
@@ -181,7 +185,7 @@ const Q = () => ({
181
185
  getFilterList() {
182
186
  return Object.values(this.filterList).filter((t) => t.isFilterable !== 0 && t.isFilterable !== !1).map((t) => {
183
187
  let e;
184
- return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : M.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
188
+ return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : E.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
185
189
  text: t.displayName,
186
190
  value: e,
187
191
  type: t.attributeType
@@ -203,7 +207,7 @@ const Q = () => ({
203
207
  setCurrentBlock(t) {
204
208
  this.blockStates[t] || (this.blockStates = {
205
209
  ...this.blockStates,
206
- [t]: G()
210
+ [t]: _()
207
211
  }), this.currentRecommendationId = t;
208
212
  },
209
213
  /**
@@ -275,7 +279,7 @@ const Q = () => ({
275
279
  decimalCount: String(e.currencyDecimalCount),
276
280
  decimalSeparator: r(e.currencyDecimalSeparator, ","),
277
281
  thousandSeparator: r(e.currencyThousandSeparator, ".")
278
- }, s = !this.blockStates[t], i = s ? G() : this.blockStates[t];
282
+ }, s = !this.blockStates[t], i = s ? _() : this.blockStates[t];
279
283
  i.recommendationConfigs = {
280
284
  ...i.recommendationConfigs,
281
285
  strategy: e.strategy,
@@ -314,7 +318,7 @@ const Q = () => ({
314
318
  * Creates a filter with the first available attribute and operator pre-selected.
315
319
  */
316
320
  createDefaultFilter(t, e) {
317
- const [r] = this.getFilterList, [n] = N(r == null ? void 0 : r.type);
321
+ const [r] = this.getFilterList, [n] = z(r == null ? void 0 : r.type);
318
322
  return {
319
323
  type: "standardFilter",
320
324
  attribute: (r == null ? void 0 : r.value) ?? "",
@@ -387,15 +391,15 @@ const Q = () => ({
387
391
  }
388
392
  if (this.strategiesFetched)
389
393
  return;
390
- const t = I, e = (async () => {
394
+ const t = b, e = (async () => {
391
395
  this.strategiesLoading = !0;
392
396
  try {
393
- const r = await m.fetchRecommendationStrategies();
394
- if (t !== I)
397
+ const r = await u.fetchRecommendationStrategies();
398
+ if (t !== b)
395
399
  return;
396
400
  this.strategies = r, this.strategiesFetched = !0;
397
401
  } finally {
398
- this.strategiesLoading = !1, t === I && (this.strategiesSettled = !0);
402
+ this.strategiesLoading = !1, t === b && (this.strategiesSettled = !0);
399
403
  }
400
404
  })();
401
405
  k = e;
@@ -405,25 +409,6 @@ const Q = () => ({
405
409
  k = null;
406
410
  }
407
411
  },
408
- /**
409
- * Drops what the store still holds for a block whose account-scoped config was just
410
- * reset in the document (SD-151945), so the panel re-seeds from the emptied node.
411
- */
412
- resetPartnerScopedConfig(t) {
413
- const e = t.toString();
414
- if (this.recommendationCampaignUrls[e] !== void 0) {
415
- const n = { ...this.recommendationCampaignUrls };
416
- delete n[e], this.recommendationCampaignUrls = n;
417
- }
418
- const r = this.blockStates[t];
419
- r && (r.recommendationConfigs = {
420
- ...r.recommendationConfigs,
421
- strategyId: "",
422
- strategy: "",
423
- filters: [],
424
- productIds: []
425
- }, r.isInitialized = !1, r.syncedConfigFingerprint = null, this.currentRecommendationId === t && this.configVersion++);
426
- },
427
412
  /**
428
413
  * Clears what a block inherited from the id it arrived holding, so the panel fetches for it.
429
414
  * A re-dropped saved module can keep the source's id — and its "already fetched" entry —
@@ -435,7 +420,7 @@ const Q = () => ({
435
420
  }));
436
421
  },
437
422
  invalidateStrategies() {
438
- this.strategiesFetched = !1, this.strategiesSettled = !1, I += 1;
423
+ this.strategiesFetched = !1, this.strategiesSettled = !1, b += 1;
439
424
  },
440
425
  /**
441
426
  * Opens a Smart Recommender strategy page in a new tab and refreshes the list every time
@@ -453,9 +438,9 @@ const Q = () => ({
453
438
  _armStrategyPageReturn(t) {
454
439
  const e = window.open(t, "_blank");
455
440
  if (!e)
456
- return D().showToaster({
457
- type: A.Error,
458
- message: L()("discovery-strategy.error-description")
441
+ return U().showToaster({
442
+ type: O.Error,
443
+ message: M()("discovery-strategy.error-description")
459
444
  }), !1;
460
445
  e.opener = null, l == null || l();
461
446
  let r = !1;
@@ -490,20 +475,20 @@ const Q = () => ({
490
475
  * new strategy is offered; the user picks it themselves.
491
476
  */
492
477
  openStrategyCreation() {
493
- return this._armStrategyPageReturn(E.RECOMMENDATION_STRATEGY_CREATE_PATH);
478
+ return this._armStrategyPageReturn(B());
494
479
  },
495
480
  /**
496
481
  * Opens the strategy's edit page. Every return refreshes the list so the block reflects the
497
482
  * edited configuration.
498
483
  */
499
484
  openStrategyEdit(t) {
500
- return this._armStrategyPageReturn(U(t));
485
+ return this._armStrategyPageReturn(N(t));
501
486
  },
502
487
  async resolveStrategyUrlTemplate(t, e) {
503
488
  const r = typeof t.updated_at == "string" ? t.updated_at : "", n = r ? `${t.strategy_id}:${r}:${e}` : "", s = n ? this.strategyUrlTemplates[n] : void 0;
504
489
  if (s)
505
490
  return s;
506
- const { full_path: i = "" } = await m.generateStrategyEndpoint(t, e) ?? {};
491
+ const { full_path: i = "" } = await u.generateStrategyEndpoint(t, e) ?? {};
507
492
  return n && i && (this.strategyUrlTemplates = {
508
493
  ...this.strategyUrlTemplates,
509
494
  [n]: i
@@ -521,7 +506,7 @@ const Q = () => ({
521
506
  throw new Error("[Guido] convertLegacyStrategy called without an active block");
522
507
  this.blockStates[r].legacyConversionLoading = !0;
523
508
  try {
524
- const n = await m.migrateLegacyStrategy(t, e);
509
+ const n = await u.migrateLegacyStrategy(t, e);
525
510
  this.invalidateStrategies();
526
511
  try {
527
512
  await this.fetchStrategies();
@@ -552,7 +537,7 @@ const Q = () => ({
552
537
  this.patchCurrentBlockConfig({
553
538
  strategyId: "",
554
539
  strategy: "",
555
- size: x.size,
540
+ size: j.size,
556
541
  nodeConfigVersion: C
557
542
  });
558
543
  },
@@ -570,7 +555,7 @@ const Q = () => ({
570
555
  activePredictiveAlgorithms: t,
571
556
  languages: e,
572
557
  currencies: r
573
- } = await m.fetchRecommendationCreateData();
558
+ } = await u.fetchRecommendationCreateData();
574
559
  if (this.activePredictiveAlgorithms = t, this.languages = e, this.currentRecommendationId !== null && this.blockStates[this.currentRecommendationId]) {
575
560
  const n = this.blockStates[this.currentRecommendationId];
576
561
  n.filterStatus = !!n.recommendationConfigs.filters.length;
@@ -586,18 +571,18 @@ const Q = () => ({
586
571
  },
587
572
  async fetchRecommendationFilters() {
588
573
  if (!Object.keys(this.filterList).length) {
589
- if (p) {
590
- await p;
574
+ if (y) {
575
+ await y;
591
576
  return;
592
577
  }
593
- p = (async () => {
594
- const t = await m.fetchRecommendationFilters();
578
+ y = (async () => {
579
+ const t = await u.fetchRecommendationFilters();
595
580
  this.filterList = t;
596
581
  })();
597
582
  try {
598
- await p;
583
+ await y;
599
584
  } finally {
600
- p = null;
585
+ y = null;
601
586
  }
602
587
  }
603
588
  },
@@ -626,7 +611,7 @@ const Q = () => ({
626
611
  const n = [...e.recommendationConfigs.filters];
627
612
  n[r] = {
628
613
  ...t,
629
- isValid: q(t)
614
+ isValid: J(t)
630
615
  }, e.recommendationConfigs.filters = n;
631
616
  }
632
617
  },
@@ -640,7 +625,7 @@ const Q = () => ({
640
625
  let i = 1;
641
626
  n = n.map((o) => o.filterGroup === t.filterGroup ? { ...o, filterNumber: i++ } : o);
642
627
  } else {
643
- const i = [...new Set(n.map((a) => a.filterGroup))].sort((a, d) => a - d), o = new Map(i.map((a, d) => [a, d + 1]));
628
+ const i = [...new Set(n.map((a) => a.filterGroup))].sort((a, f) => a - f), o = new Map(i.map((a, f) => [a, f + 1]));
644
629
  n = n.map((a) => ({
645
630
  ...a,
646
631
  filterGroup: o.get(a.filterGroup) ?? a.filterGroup
@@ -664,7 +649,7 @@ const Q = () => ({
664
649
  }), e.recommendationConfigs.filters = r;
665
650
  },
666
651
  generateFilterQuery() {
667
- return P(this.recommendationConfigs.filters);
652
+ return G(this.recommendationConfigs.filters);
668
653
  },
669
654
  /**
670
655
  * Validation-only check invoked at save-CTA time. Defined as an action
@@ -672,14 +657,14 @@ const Q = () => ({
672
657
  * every block's recommendationConfigs across user edits.
673
658
  */
674
659
  hasInvalidBlock() {
675
- return Object.values(this.blockStates).some((t) => !J(t.recommendationConfigs, this));
660
+ return Object.values(this.blockStates).some((t) => !W(t.recommendationConfigs, this));
676
661
  },
677
662
  /**
678
663
  * Which required fields are missing across the design's blocks, so the save
679
664
  * toaster can name the cause instead of always showing the generic message.
680
665
  */
681
666
  invalidBlockFields() {
682
- return Object.values(this.blockStates).flatMap((t) => H(t.recommendationConfigs, this));
667
+ return Object.values(this.blockStates).flatMap((t) => Q(t.recommendationConfigs, this));
683
668
  },
684
669
  // ====================================================================
685
670
  // Per-Block Product Fetching
@@ -690,17 +675,17 @@ const Q = () => ({
690
675
  const t = [
691
676
  this.currentRecommendationId,
692
677
  this.configVersion,
693
- I
678
+ b
694
679
  ].join(":");
695
- if (y && b === t) {
696
- await y;
680
+ if (p && I === t) {
681
+ await p;
697
682
  return;
698
683
  }
699
- b = t, y = this._doFetchProducts();
684
+ I = t, p = this._doFetchProducts();
700
685
  try {
701
- await y;
686
+ await p;
702
687
  } finally {
703
- b === t && (y = null, b = "");
688
+ I === t && (p = null, I = "");
704
689
  }
705
690
  },
706
691
  async _doFetchProducts() {
@@ -710,14 +695,14 @@ const Q = () => ({
710
695
  await this._doFetchStrategyProducts(t);
711
696
  return;
712
697
  }
713
- const s = (g.get(t) ?? 0) + 1;
714
- g.set(t, s);
698
+ const s = (m.get(t) ?? 0) + 1;
699
+ m.set(t, s);
715
700
  const i = parseInt(r.size) || 6;
716
701
  if (!r.strategy) {
717
702
  this._setBlockProducts(t, [], i);
718
703
  return;
719
704
  }
720
- const o = r.filters.filter((f) => f.isValid), a = P(o), d = ((h = F().find((f) => f.key === r.strategy)) == null ? void 0 : h.path) || "", c = {
705
+ const o = r.filters.filter((g) => g.isValid), a = G(o), f = ((h = w().find((g) => g.key === r.strategy)) == null ? void 0 : h.path) || "", c = {
721
706
  locale: r.language,
722
707
  currency: r.currencySettings.value,
723
708
  partnerName: n.partnerName,
@@ -725,58 +710,87 @@ const Q = () => ({
725
710
  details: !0,
726
711
  campaignId: n.variationId
727
712
  };
728
- r.strategy === "manualMerchandising" ? c.productId = K(r.productIds) : r.strategy === "similarViewed" && (c.productId = "{itemId}"), r.strategy === "userBased" && (c.userId = "{user_id}"), a && (c.filter = a), r.shuffleProducts && (c.shuffle = !0), Object.assign(
713
+ r.strategy === "manualMerchandising" ? c.productId = H(r.productIds) : r.strategy === "similarViewed" && (c.productId = "{itemId}"), r.strategy === "userBased" && (c.userId = "{user_id}"), a && (c.filter = a), r.shuffleProducts && (c.shuffle = !0), Object.assign(
729
714
  c,
730
- $(n.partnerName, r.strategy)
715
+ K(n.partnerName, r.strategy)
731
716
  );
732
- let u;
717
+ let d;
733
718
  try {
734
- u = await m.fetchRecommendationProducts(d, c);
719
+ d = await u.fetchRecommendationProducts(f, c);
735
720
  } catch {
736
- u = [];
721
+ d = [];
737
722
  }
738
- g.get(t) === s && this._setBlockProducts(t, u, i);
723
+ m.get(t) === s && this._setBlockProducts(t, d, i);
739
724
  },
740
725
  /**
741
726
  * Block-scoped counterpart of `fetchRecommendationProducts`, which only ever serves the
742
727
  * selected block. The legacy conversion must refresh the products of the block that
743
728
  * started it even after the user selected another one.
729
+ * @returns whether real products arrived
744
730
  */
745
- async fetchStrategyProductsForBlock(t) {
746
- var e;
747
- (e = this.blockStates[t]) != null && e.recommendationConfigs.strategyId && await this._doFetchStrategyProducts(t);
731
+ async fetchStrategyProductsForBlock(t, e = {}) {
732
+ var r;
733
+ return (r = this.blockStates[t]) != null && r.recommendationConfigs.strategyId ? this._doFetchStrategyProducts(t, e) : !1;
748
734
  },
749
- async _doFetchStrategyProducts(t) {
750
- const e = (g.get(t) ?? 0) + 1;
751
- g.set(t, e);
752
- const { recommendationConfigs: r } = this.blockStates[t];
753
- let n = [], s = parseInt(r.size) || 6;
735
+ /**
736
+ * Reloads a block's products and adopts its strategy's current size, which may have
737
+ * moved since the block was assigned.
738
+ * @returns whether a fresh listing holds the strategy and its products arrived
739
+ */
740
+ async refreshStrategyBlock(t) {
741
+ var s;
742
+ const e = (s = this.blockStates[t]) == null ? void 0 : s.recommendationConfigs.strategyId;
743
+ if (!e)
744
+ return !1;
745
+ try {
746
+ await this.fetchStrategies();
747
+ } catch {
748
+ return !1;
749
+ }
750
+ const r = this.strategiesFetched ? this.strategies.find((i) => String(i.strategy_id) === e) : void 0;
751
+ if (!r || !await this.fetchStrategyProductsForBlock(t, { keepOnFailure: !0 }))
752
+ return !1;
753
+ const n = this.blockStates[t];
754
+ return (n == null ? void 0 : n.recommendationConfigs.strategyId) !== e ? !1 : (r.size !== void 0 && (n.recommendationConfigs = {
755
+ ...n.recommendationConfigs,
756
+ size: String(r.size)
757
+ }), !0);
758
+ },
759
+ _doFetchStrategyProducts(t, e = {}) {
760
+ const r = (m.get(t) ?? 0) + 1;
761
+ m.set(t, r);
762
+ const n = this._loadStrategyProducts(t, r, e);
763
+ return D.set(t, { token: r, outcome: n }), n;
764
+ },
765
+ async _loadStrategyProducts(t, e, { keepOnFailure: r = !1 }) {
766
+ const { recommendationConfigs: n } = this.blockStates[t];
767
+ let s = [], i = parseInt(n.size) || 6;
754
768
  try {
755
769
  await this.fetchStrategies();
756
- const i = this.strategies.find(
757
- (o) => String(o.strategy_id) === r.strategyId
770
+ const o = this.strategies.find(
771
+ (a) => String(a.strategy_id) === n.strategyId
758
772
  );
759
- if (i) {
760
- s = parseInt(String(i.size ?? "")) || s;
761
- const o = r.currencySettings.value, d = (await this.resolveStrategyUrlTemplate(i, o)).replaceAll("{locale}", r.language).replaceAll("{currency}", o), c = d.indexOf("?"), u = c === -1 ? d : d.slice(0, c), h = (c === -1 ? "" : d.slice(c + 1)).split("&").filter((v) => v && !v.startsWith("user_id=")), f = h.length ? `${u}?${h.join("&")}` : u;
762
- f && (n = await m.fetchRecommendationProductsByUrl(f));
773
+ if (o) {
774
+ i = parseInt(String(o.size ?? "")) || i;
775
+ const a = n.currencySettings.value, c = (await this.resolveStrategyUrlTemplate(o, a)).replaceAll("{locale}", n.language).replaceAll("{currency}", a), d = c.indexOf("?"), h = d === -1 ? c : c.slice(0, d), g = (d === -1 ? "" : c.slice(d + 1)).split("&").filter((F) => F && !F.startsWith("user_id=")), v = g.length ? `${h}?${g.join("&")}` : h;
776
+ v && (s = await u.fetchRecommendationProductsByUrl(v));
763
777
  }
764
778
  } catch {
765
- n = [];
779
+ s = [];
766
780
  }
767
- g.get(t) === e && this._setBlockProducts(t, n, s);
781
+ return m.get(t) !== e ? X(t) : !s.length && r ? !1 : (this._setBlockProducts(t, s, i), s.length > 0);
768
782
  },
769
783
  _setBlockProducts(t, e, r) {
770
784
  if (!this.blockStates[t])
771
785
  return;
772
- const n = e.length > 0 ? e : w(r);
786
+ const n = e.length > 0 ? e : P(r);
773
787
  this.blockStates[t].recommendationProducts = [
774
788
  ...n.slice(0, r),
775
- ...w(Math.max(0, r - n.length))
789
+ ...P(Math.max(0, r - n.length))
776
790
  ];
777
791
  }
778
792
  }
779
793
  });
780
794
  export {
781
- ft as useRecommendationExtensionStore
795
+ St as useRecommendationExtensionStore
782
796
  };
@@ -0,0 +1,25 @@
1
+ import { RRS_CONFIG_VERSION as d, DEFAULT_CURRENCY as t, DEFAULT_NODE_CONFIG as e } from "../constants/defaultConfig.js";
2
+ import { mapLegacyStrategy as n } from "./legacyStrategyMap.js";
3
+ function S(r) {
4
+ var a, u, c, s, l, o;
5
+ const y = !!r.strategyId || (r.configVersion ?? 0) >= d;
6
+ return {
7
+ strategy: n(r.strategy) || (y ? "" : e.strategy),
8
+ strategyId: r.strategyId ?? e.strategyId,
9
+ language: r.language ?? e.language,
10
+ size: r.size ?? e.size,
11
+ // Copied: the source can be a live node config or the shared defaults.
12
+ productIds: [...r.productIds ?? e.productIds],
13
+ filters: structuredClone(r.filters ?? e.filters),
14
+ shuffleProducts: r.shuffleProducts ?? e.shuffleProducts,
15
+ currencyCode: ((a = r.currency) == null ? void 0 : a.code) ?? t.code,
16
+ currencySymbol: ((u = r.currency) == null ? void 0 : u.symbol) ?? t.symbol,
17
+ currencyAlignment: ((c = r.currency) == null ? void 0 : c.alignment) ?? t.alignment,
18
+ currencyDecimalCount: ((s = r.currency) == null ? void 0 : s.decimalCount) ?? t.decimalCount,
19
+ currencyDecimalSeparator: ((l = r.currency) == null ? void 0 : l.decimalSeparator) ?? t.decimalSeparator,
20
+ currencyThousandSeparator: ((o = r.currency) == null ? void 0 : o.thousandSeparator) ?? t.thousandSeparator
21
+ };
22
+ }
23
+ export {
24
+ S as toBlockUrlConfig
25
+ };
@@ -1,32 +1,37 @@
1
- import { ModificationDescription as g } from "../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
2
- import { RECOMMENDATION_ID_ATTR as s } from "../constants/selectors.js";
3
- import { isPartnerManagedBlock as p, updateProductContentInPlace as C, regenerateProductRowsWithStyles as N } from "../controls/main/utils.js";
4
- import { RecommendationConfigService as m } from "../services/configService.js";
5
- let o = null;
6
- function D(n) {
7
- o = n;
1
+ import { ModificationDescription as m } from "../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
2
+ import { RECOMMENDATION_ID_ATTR as a } from "../constants/selectors.js";
3
+ import { isPartnerManagedBlock as C, updateProductContentInPlace as N, regenerateProductRowsWithStyles as p } from "../controls/main/utils.js";
4
+ import { RecommendationConfigService as l } from "../services/configService.js";
5
+ let e = null;
6
+ function O(n) {
7
+ e = n;
8
8
  }
9
- function P(n, r, c, l) {
10
- const i = o == null ? void 0 : o.getDocumentRootHtmlNode();
11
- if (!o || !i || !("querySelector" in i))
9
+ function R(n) {
10
+ const o = e == null ? void 0 : e.getDocumentRootHtmlNode();
11
+ return !o || !("querySelectorAll" in o) ? [] : o.querySelectorAll(`[${a}="${n}"]`).map((i) => l.getConfig(i));
12
+ }
13
+ function P(n, o, i, u) {
14
+ const c = e == null ? void 0 : e.getDocumentRootHtmlNode();
15
+ if (!e || !c || !("querySelector" in c))
12
16
  return !1;
13
- const e = i.querySelector(`[${s}="${n}"]`);
14
- if (!e)
17
+ const t = c.querySelector(`[${a}="${n}"]`);
18
+ if (!t)
15
19
  return !1;
16
- const t = o.getDocumentModifier(), a = m.getConfig(e), d = Object.keys(r).some((u) => JSON.stringify(a[u]) !== JSON.stringify(r[u]));
17
- if (m.stageConfig(t, e, r), p(e))
18
- return t.apply(new g(l)), !0;
20
+ const r = e.getDocumentModifier(), d = l.getConfig(t), s = Object.keys(o).some((g) => JSON.stringify(d[g]) !== JSON.stringify(o[g]));
21
+ if (l.stageConfig(r, t, o), C(t))
22
+ return r.apply(new m(u)), !0;
19
23
  let f = !1;
20
- return C({
21
- currentNode: e,
22
- documentModifier: t,
23
- products: c,
24
+ return N({
25
+ currentNode: t,
26
+ documentModifier: r,
27
+ products: i,
24
28
  onApplied: () => {
25
29
  f = !0;
26
30
  }
27
- }) || (f = N({ currentNode: e, documentModifier: t, products: c })), !f && d && t.apply(new g(l)), !0;
31
+ }) || (f = p({ currentNode: t, documentModifier: r, products: i })), !f && s && r.apply(new m(u)), !0;
28
32
  }
29
33
  export {
30
34
  P as commitBlockChangeOutsidePanel,
31
- D as registerNodeConfigWriter
35
+ R as readBlockNodeConfigs,
36
+ O as registerNodeConfigWriter
32
37
  };
@@ -1,6 +1,5 @@
1
- import { ATTR_CUSTOM_PREFIX as f, RECOMMENDATION_ID_ATTR as o } from "../constants/selectors.js";
2
- const s = new RegExp(`\\s${o}="(\\d+)"`, "g");
3
- function u(t) {
1
+ import { ATTR_CUSTOM_PREFIX as f } from "../constants/selectors.js";
2
+ function o(t) {
4
3
  if (typeof t == "string")
5
4
  return t.trim() !== "";
6
5
  if (t && typeof t == "object" && "strategyId" in t) {
@@ -9,18 +8,18 @@ function u(t) {
9
8
  }
10
9
  return !1;
11
10
  }
12
- function a(t) {
13
- return new Set([...t.matchAll(s)].map((r) => Number(r[1])));
11
+ function u({ config: t, blockId: r, partnerName: e, campaignUrls: n, rrsEnabled: i }) {
12
+ return e ? t.partnerName ? t.partnerName !== e : !i || !t.strategyId || !n ? !1 : !o(n[String(r)]) : !1;
14
13
  }
15
- function g({ config: t, blockId: r, partnerName: e, campaignUrls: n, loadedIds: i }) {
16
- return e ? t.partnerName ? t.partnerName !== e : !t.strategyId || !n || !i.has(r) ? !1 : !u(n[String(r)]) : !1;
14
+ function a({ config: t, campaignUrls: r, rrsEnabled: e }) {
15
+ return !t.strategyId || e && !!r;
17
16
  }
18
- function p(t) {
17
+ function g(t) {
19
18
  return t.filter((r) => !r.startsWith(f));
20
19
  }
21
20
  export {
22
- g as carriesForeignPartnerConfig,
23
- u as isDefinedCampaignUrl,
24
- a as loadedRecommendationIds,
25
- p as withoutCustomAttributes
21
+ a as canJudgeUnstampedBlock,
22
+ u as carriesForeignPartnerConfig,
23
+ o as isDefinedCampaignUrl,
24
+ g as withoutCustomAttributes
26
25
  };