@useinsider/guido 3.18.2-beta.45f708c → 3.18.2-beta.6dbea61

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 (48) hide show
  1. package/dist/components/Guido.vue.js +3 -3
  2. package/dist/components/Guido.vue2.js +30 -30
  3. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +11 -13
  4. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +51 -70
  5. package/dist/components/organisms/extensions/recommendation/RemoveStrategyModal.vue2.js +37 -23
  6. package/dist/components/organisms/onboarding/OnboardingWrapper.vue2.js +18 -20
  7. package/dist/components/organisms/save-as-template/SaveAsTemplateDrawer.vue2.js +34 -34
  8. package/dist/composables/useCustomInterfaceAppearance.js +46 -56
  9. package/dist/composables/useHtmlValidator.js +79 -84
  10. package/dist/composables/useHttp.js +22 -24
  11. package/dist/composables/useRecommendation.js +35 -40
  12. package/dist/composables/useStripo.js +30 -30
  13. package/dist/enums/extensions/recommendationBlock.js +31 -38
  14. package/dist/extensions/Blocks/Recommendation/block.js +39 -43
  15. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +20 -21
  16. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +44 -55
  17. package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +52 -84
  18. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +74 -74
  19. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +90 -190
  20. package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +16 -26
  21. package/dist/extensions/Blocks/Recommendation/validation/requiredFields.js +12 -21
  22. package/dist/guido.css +1 -1
  23. package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js +28 -29
  24. package/dist/package.json.js +1 -1
  25. package/dist/services/templateLibraryApi.js +14 -17
  26. package/dist/src/enums/extensions/recommendationBlock.d.ts +0 -2
  27. package/dist/src/extensions/Blocks/Recommendation/constants/defaultConfig.d.ts +0 -1
  28. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +1 -1
  29. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +1 -7
  30. package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +0 -9
  31. package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +2 -7
  32. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +0 -87
  33. package/dist/src/extensions/Blocks/Recommendation/validation/requiredFields.d.ts +0 -4
  34. package/dist/src/stores/onboarding.d.ts +0 -377
  35. package/dist/src/utils/genericUtil.d.ts +0 -6
  36. package/dist/static/styles/components/recommendation-strategy.css.js +4 -34
  37. package/dist/stores/onboarding.js +36 -41
  38. package/dist/utils/genericUtil.js +54 -63
  39. package/dist/utils/templatePreparation.js +59 -61
  40. package/package.json +3 -3
  41. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.js +0 -21
  42. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue2.js +0 -47
  43. package/dist/extensions/Blocks/Recommendation/utils/strategyCommit.js +0 -24
  44. package/dist/src/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.d.ts +0 -2
  45. package/dist/src/extensions/Blocks/Recommendation/utils/strategyCommit.d.ts +0 -14
  46. package/dist/src/utils/liquidDynamicContent.d.ts +0 -20
  47. package/dist/static/styles/components/skeleton.css.js +0 -23
  48. package/dist/utils/liquidDynamicContent.js +0 -15
@@ -1,23 +1,22 @@
1
- import { getRecommendationFeedSourceMaps as C, strategyEditPath as D, URLS as _, getOperatorOptions as N, PriceAttributes as U } from "../../../../enums/extensions/recommendationBlock.js";
2
- import { useRecommendationApi as A } from "../../../../services/recommendationApi.js";
1
+ import { getRecommendationFeedSourceMaps as b, getOperatorOptions as G, PriceAttributes as v } from "../../../../enums/extensions/recommendationBlock.js";
2
+ import { useRecommendationApi as D } from "../../../../services/recommendationApi.js";
3
3
  import { useConfigStore as P } from "../../../../stores/config.js";
4
- import { defineStore as L } from "pinia";
4
+ import { defineStore as F } from "pinia";
5
5
  import "../constants/selectors.js";
6
- import { DEFAULT_MOBILE_CARDS_IN_ROW as E, DEFAULT_CARDS_IN_ROW as x } from "../constants/layout.js";
7
- import { DEFAULT_NODE_CONFIG as B, EXCLUDED_ALGORITHM_IDS as M } from "../constants/defaultConfig.js";
8
- import { getDefaultProducts as v } from "../templates/utils.js";
9
- import { generateCompleteFilterQuery as F } from "../utils/filterUtil.js";
10
- import { getPartnerRecommendationParams as O } from "../utils/partnerCustomizations.js";
11
- import { sanitizeProductIds as T } from "../utils/productIds.js";
12
- import { isFilterValid as z } from "../validation/filterSchema.js";
13
- import { getInvalidFields as V, isConfigValid as j } from "../validation/requiredFields.js";
14
- const f = A();
15
- let S = null, p = null, y = null, I = "", R = null, b = 0;
16
- const h = /* @__PURE__ */ new Map();
17
- let l = null;
18
- function G() {
6
+ import { DEFAULT_MOBILE_CARDS_IN_ROW as _, DEFAULT_CARDS_IN_ROW as U } from "../constants/layout.js";
7
+ import { DEFAULT_NODE_CONFIG as N, EXCLUDED_ALGORITHM_IDS as L } from "../constants/defaultConfig.js";
8
+ import { getDefaultProducts as R } from "../templates/utils.js";
9
+ import { generateCompleteFilterQuery as k } from "../utils/filterUtil.js";
10
+ import { getPartnerRecommendationParams as x } from "../utils/partnerCustomizations.js";
11
+ import { sanitizeProductIds as A } from "../utils/productIds.js";
12
+ import { isFilterValid as B } from "../validation/filterSchema.js";
13
+ import { isConfigValid as M } from "../validation/requiredFields.js";
14
+ const u = D();
15
+ let f = null, h = null, g = null, S = null;
16
+ const p = /* @__PURE__ */ new Map();
17
+ function w() {
19
18
  return {
20
- cardsInRow: x,
19
+ cardsInRow: U,
21
20
  currencySettings: {
22
21
  name: "USD",
23
22
  value: "USD",
@@ -31,17 +30,13 @@ function G() {
31
30
  productIds: [],
32
31
  id: 1,
33
32
  language: "en_US",
34
- mobileCardsInRow: E,
33
+ mobileCardsInRow: _,
35
34
  mobileLayoutEnabled: !1,
36
35
  orientation: "grid",
37
36
  recommendedProducts: [],
38
37
  sendProductRequestFlag: !1,
39
38
  shuffleProducts: !1,
40
- // With RRS on, a block that has not been synced yet must not claim an algorithm:
41
- // that default is what reached buildCampaignUrl and baked a most-popular feed URL
42
- // for a block the user never configured (SD-149916). Legacy blocks still get their real
43
- // algorithm from the node-config sync or the save-time seed.
44
- strategy: P().isFeatureEnabled("reusableRecommendationStrategy") ? "" : "mostPopular",
39
+ strategy: "mostPopular",
45
40
  strategyId: "",
46
41
  textTrimming: !0,
47
42
  unresponsive: !1,
@@ -51,9 +46,9 @@ function G() {
51
46
  priceHideIfSameAsDiscounted: !1
52
47
  };
53
48
  }
54
- function w() {
49
+ function C() {
55
50
  return {
56
- recommendationConfigs: G(),
51
+ recommendationConfigs: w(),
57
52
  recommendationProducts: [],
58
53
  filterStatus: !1,
59
54
  filterSelectionDrawerStatus: !1,
@@ -61,11 +56,10 @@ function w() {
61
56
  removeStrategyModalStatus: !1,
62
57
  filterGroup: 1,
63
58
  isInitialized: !1,
64
- filterSnapshot: null,
65
- syncedConfigFingerprint: null
59
+ filterSnapshot: null
66
60
  };
67
61
  }
68
- const $ = () => ({
62
+ const z = () => ({
69
63
  recommendationCampaignUrls: {},
70
64
  activePredictiveAlgorithms: [],
71
65
  languages: {},
@@ -74,14 +68,11 @@ const $ = () => ({
74
68
  strategies: [],
75
69
  strategiesLoading: !1,
76
70
  strategyUrlTemplates: {},
77
- strategiesFetched: !1,
78
- strategiesSettled: !1,
79
71
  blockStates: {},
80
72
  currentRecommendationId: null,
81
- strategyPanelOpen: !1,
82
73
  configVersion: 0
83
- }), it = L("guidoRecommendationExtension", {
84
- state: () => $(),
74
+ }), Y = F("guidoRecommendationExtension", {
75
+ state: () => z(),
85
76
  getters: {
86
77
  // ====================================================================
87
78
  // Proxy Getters — Backward Compatible Access to Current Block State
@@ -91,7 +82,7 @@ const $ = () => ({
91
82
  * This allows all existing code that reads `store.recommendationConfigs` to work unchanged.
92
83
  */
93
84
  recommendationConfigs(t) {
94
- return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : G();
85
+ return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : w();
95
86
  },
96
87
  /**
97
88
  * Proxy getter: delegates to blockStates[currentRecommendationId].recommendationProducts
@@ -146,8 +137,8 @@ const $ = () => ({
146
137
  return [...new Set(t.map((e) => e.filterGroup))].sort((e, r) => e - r);
147
138
  },
148
139
  getActivePredictiveAlgorithms: (t) => {
149
- const e = C(), r = [];
150
- return t.activePredictiveAlgorithms.filter((n) => !M.includes(n)).forEach((n) => {
140
+ const e = b(), r = [];
141
+ return t.activePredictiveAlgorithms.filter((n) => !L.includes(n)).forEach((n) => {
151
142
  r.push(...e.filter((s) => s.id === n));
152
143
  }), r.map((n) => ({
153
144
  text: n.name,
@@ -165,7 +156,7 @@ const $ = () => ({
165
156
  getFilterList() {
166
157
  return Object.values(this.filterList).filter((t) => t.isFilterable !== 0 && t.isFilterable !== !1).map((t) => {
167
158
  let e;
168
- return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : U.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
159
+ return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : v.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
169
160
  text: t.displayName,
170
161
  value: e,
171
162
  type: t.attributeType
@@ -187,7 +178,7 @@ const $ = () => ({
187
178
  setCurrentBlock(t) {
188
179
  this.blockStates[t] || (this.blockStates = {
189
180
  ...this.blockStates,
190
- [t]: w()
181
+ [t]: C()
191
182
  }), this.currentRecommendationId = t;
192
183
  },
193
184
  /**
@@ -247,15 +238,15 @@ const $ = () => ({
247
238
  * `isInitialized`) alone.
248
239
  */
249
240
  seedBlockUrlConfig(t, e) {
250
- const r = (o, a) => o === "." || o === "," || o === " " ? o : a, n = {
241
+ const r = (o, c) => o === "." || o === "," || o === " " ? o : c, n = {
251
242
  name: e.currencyCode,
252
243
  value: e.currencyCode,
253
- symbol: e.currencySymbol,
244
+ symbol: e.currencyCode,
254
245
  alignment: e.currencyAlignment === "before" ? "0" : "1",
255
246
  decimalCount: String(e.currencyDecimalCount),
256
247
  decimalSeparator: r(e.currencyDecimalSeparator, ","),
257
248
  thousandSeparator: r(e.currencyThousandSeparator, ".")
258
- }, s = !this.blockStates[t], i = s ? w() : this.blockStates[t];
249
+ }, s = !this.blockStates[t], i = s ? C() : this.blockStates[t];
259
250
  i.recommendationConfigs = {
260
251
  ...i.recommendationConfigs,
261
252
  strategy: e.strategy,
@@ -294,7 +285,7 @@ const $ = () => ({
294
285
  * Creates a filter with the first available attribute and operator pre-selected.
295
286
  */
296
287
  createDefaultFilter(t, e) {
297
- const [r] = this.getFilterList, [n] = N(r == null ? void 0 : r.type);
288
+ const [r] = this.getFilterList, [n] = G(r == null ? void 0 : r.type);
298
289
  return {
299
290
  type: "standardFilter",
300
291
  attribute: (r == null ? void 0 : r.value) ?? "",
@@ -354,97 +345,29 @@ const $ = () => ({
354
345
  this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].removeStrategyModalStatus = !1);
355
346
  },
356
347
  async fetchStrategies() {
357
- for (; R; )
358
- try {
359
- await R;
360
- } catch {
361
- }
362
- if (this.strategiesFetched)
348
+ if (S) {
349
+ await S;
363
350
  return;
364
- const t = b, e = (async () => {
351
+ }
352
+ S = (async () => {
365
353
  this.strategiesLoading = !0;
366
354
  try {
367
- const r = await f.fetchRecommendationStrategies();
368
- if (t !== b)
369
- return;
370
- this.strategies = r, this.strategiesFetched = !0;
355
+ this.strategies = await u.fetchRecommendationStrategies();
371
356
  } finally {
372
- this.strategiesLoading = !1, t === b && (this.strategiesSettled = !0);
357
+ this.strategiesLoading = !1;
373
358
  }
374
359
  })();
375
- R = e;
376
360
  try {
377
- await e;
361
+ await S;
378
362
  } finally {
379
- R = null;
363
+ S = null;
380
364
  }
381
365
  },
382
- invalidateStrategies() {
383
- this.strategiesFetched = !1, this.strategiesSettled = !1, b += 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` only: a `focus` listener would also fire when
388
- * focus merely returns from the Stripo canvas iframe to the panel, refetching and
389
- * regenerating the canvas while the user never left the editor (SD-149916).
390
- *
391
- * Deliberately NOT one-shot: the strategy tab stays open, so a user can create a second
392
- * strategy in it and come back again — a listener that disarmed on the first return would
393
- * leave that one missing from the list. It disarms on the first return AFTER that tab is
394
- * closed instead, so an ordinary alt-tab later in the session costs nothing. Armed only
395
- * once the user actually opens a strategy page, so anyone who never does pays nothing.
396
- */
397
- _armStrategyPageReturn(t) {
398
- const e = window.open(t, "_blank");
399
- if (!e)
400
- return;
401
- e.opener = null, l == null || l();
402
- let r = !1;
403
- const n = () => {
404
- document.hidden || r || (e != null && e.closed && (l == null || l()), r = !0, this.invalidateStrategies(), this.fetchStrategies().then(() => this._refreshAssignedStrategyProducts()).catch(() => {
405
- }).finally(() => {
406
- r = !1;
407
- }));
408
- };
409
- document.addEventListener("visibilitychange", n), l = () => {
410
- document.removeEventListener("visibilitychange", n), l = null;
411
- };
412
- },
413
- /**
414
- * Reloads the products of the block the user is on, so an edit made in the strategy tab
415
- * lands on the canvas instead of waiting for the assign drawer to be reopened.
416
- *
417
- * Only the selected block: the canvas regeneration is driven off the active block's
418
- * product array, so refreshing an unselected block would fetch without redrawing it.
419
- */
420
- async _refreshAssignedStrategyProducts() {
421
- var e;
422
- const t = this.currentRecommendationId;
423
- t === null || !((e = this.blockStates[t]) != null && e.recommendationConfigs.strategyId) || await this.fetchRecommendationProducts();
424
- },
425
- /** Lets the editor tear the return listeners down when it unmounts. */
426
- disposeStrategyPageReturn() {
427
- l == null || l();
428
- },
429
- /**
430
- * Opens Smart Recommender's strategy creation page. Every return refreshes the list so the
431
- * new strategy is offered; the user picks it themselves.
432
- */
433
- openStrategyCreation() {
434
- this._armStrategyPageReturn(_.RECOMMENDATION_STRATEGY_CREATE_PATH);
435
- },
436
- /**
437
- * Opens the strategy's edit page. Every return refreshes the list so the block reflects the
438
- * edited configuration.
439
- */
440
- openStrategyEdit(t) {
441
- this._armStrategyPageReturn(D(t));
442
- },
443
366
  async resolveStrategyUrlTemplate(t, e) {
444
367
  const r = typeof t.updated_at == "string" ? t.updated_at : "", n = r ? `${t.strategy_id}:${r}:${e}` : "", s = n ? this.strategyUrlTemplates[n] : void 0;
445
368
  if (s)
446
369
  return s;
447
- const { full_path: i = "" } = await f.generateStrategyEndpoint(t, e) ?? {};
370
+ const { full_path: i = "" } = await u.generateStrategyEndpoint(t, e) ?? {};
448
371
  return n && i && (this.strategyUrlTemplates = {
449
372
  ...this.strategyUrlTemplates,
450
373
  [n]: i
@@ -457,27 +380,23 @@ const $ = () => ({
457
380
  });
458
381
  },
459
382
  removeStrategy() {
460
- this.patchCurrentBlockConfig({
461
- strategyId: "",
462
- strategy: "",
463
- size: B.size
464
- });
383
+ this.patchCurrentBlockConfig({ strategyId: "", size: N.size });
465
384
  },
466
385
  // ====================================================================
467
386
  // Shared Data Fetching (fetched once, used by all blocks)
468
387
  // ====================================================================
469
388
  async fetchRecommendationCreateData() {
470
389
  if (!this.activePredictiveAlgorithms.length) {
471
- if (S) {
472
- await S;
390
+ if (f) {
391
+ await f;
473
392
  return;
474
393
  }
475
- S = (async () => {
394
+ f = (async () => {
476
395
  const {
477
396
  activePredictiveAlgorithms: t,
478
397
  languages: e,
479
398
  currencies: r
480
- } = await f.fetchRecommendationCreateData();
399
+ } = await u.fetchRecommendationCreateData();
481
400
  if (this.activePredictiveAlgorithms = t, this.languages = e, this.currentRecommendationId !== null && this.blockStates[this.currentRecommendationId]) {
482
401
  const n = this.blockStates[this.currentRecommendationId];
483
402
  n.filterStatus = !!n.recommendationConfigs.filters.length;
@@ -485,26 +404,26 @@ const $ = () => ({
485
404
  this.currencyList = r;
486
405
  })();
487
406
  try {
488
- await S;
407
+ await f;
489
408
  } finally {
490
- S = null;
409
+ f = null;
491
410
  }
492
411
  }
493
412
  },
494
413
  async fetchRecommendationFilters() {
495
414
  if (!Object.keys(this.filterList).length) {
496
- if (p) {
497
- await p;
415
+ if (h) {
416
+ await h;
498
417
  return;
499
418
  }
500
- p = (async () => {
501
- const t = await f.fetchRecommendationFilters();
419
+ h = (async () => {
420
+ const t = await u.fetchRecommendationFilters();
502
421
  this.filterList = t;
503
422
  })();
504
423
  try {
505
- await p;
424
+ await h;
506
425
  } finally {
507
- p = null;
426
+ h = null;
508
427
  }
509
428
  }
510
429
  },
@@ -533,7 +452,7 @@ const $ = () => ({
533
452
  const n = [...e.recommendationConfigs.filters];
534
453
  n[r] = {
535
454
  ...t,
536
- isValid: z(t)
455
+ isValid: B(t)
537
456
  }, e.recommendationConfigs.filters = n;
538
457
  }
539
458
  },
@@ -547,10 +466,10 @@ const $ = () => ({
547
466
  let i = 1;
548
467
  n = n.map((o) => o.filterGroup === t.filterGroup ? { ...o, filterNumber: i++ } : o);
549
468
  } else {
550
- const i = [...new Set(n.map((a) => a.filterGroup))].sort((a, u) => a - u), o = new Map(i.map((a, u) => [a, u + 1]));
551
- n = n.map((a) => ({
552
- ...a,
553
- filterGroup: o.get(a.filterGroup) ?? a.filterGroup
469
+ const i = [...new Set(n.map((c) => c.filterGroup))].sort((c, a) => c - a), o = new Map(i.map((c, a) => [c, a + 1]));
470
+ n = n.map((c) => ({
471
+ ...c,
472
+ filterGroup: o.get(c.filterGroup) ?? c.filterGroup
554
473
  }));
555
474
  }
556
475
  e.recommendationConfigs.filters = n;
@@ -571,7 +490,7 @@ const $ = () => ({
571
490
  }), e.recommendationConfigs.filters = r;
572
491
  },
573
492
  generateFilterQuery() {
574
- return F(this.recommendationConfigs.filters);
493
+ return k(this.recommendationConfigs.filters);
575
494
  },
576
495
  /**
577
496
  * Validation-only check invoked at save-CTA time. Defined as an action
@@ -579,52 +498,33 @@ const $ = () => ({
579
498
  * every block's recommendationConfigs across user edits.
580
499
  */
581
500
  hasInvalidBlock() {
582
- return Object.values(this.blockStates).some((t) => !j(t.recommendationConfigs, this));
583
- },
584
- /**
585
- * Which required fields are missing across the design's blocks, so the save
586
- * toaster can name the cause instead of always showing the generic message.
587
- */
588
- invalidBlockFields() {
589
- return Object.values(this.blockStates).flatMap((t) => V(t.recommendationConfigs, this));
501
+ return Object.values(this.blockStates).some((t) => !M(t.recommendationConfigs, this));
590
502
  },
591
503
  // ====================================================================
592
504
  // Per-Block Product Fetching
593
505
  // ====================================================================
594
506
  async fetchRecommendationProducts() {
595
- if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
596
- return;
597
- const t = [
598
- this.currentRecommendationId,
599
- this.configVersion,
600
- b
601
- ].join(":");
602
- if (y && I === t) {
603
- await y;
604
- return;
605
- }
606
- I = t, y = this._doFetchProducts();
607
- try {
608
- await y;
609
- } finally {
610
- I === t && (y = null, I = "");
507
+ if (!(this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])) {
508
+ if (g) {
509
+ await g;
510
+ return;
511
+ }
512
+ g = this._doFetchProducts();
513
+ try {
514
+ await g;
515
+ } finally {
516
+ g = null;
517
+ }
611
518
  }
612
519
  },
613
520
  async _doFetchProducts() {
614
- var g;
521
+ var d;
615
522
  const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = P();
616
523
  if (r.strategyId && n.isFeatureEnabled("reusableRecommendationStrategy")) {
617
524
  await this._doFetchStrategyProducts(t);
618
525
  return;
619
526
  }
620
- const s = (h.get(t) ?? 0) + 1;
621
- h.set(t, s);
622
- const i = parseInt(r.size) || 6;
623
- if (!r.strategy) {
624
- this._setBlockProducts(t, [], i);
625
- return;
626
- }
627
- const o = r.filters.filter((d) => d.isValid), a = F(o), u = ((g = C().find((d) => d.key === r.strategy)) == null ? void 0 : g.path) || "", c = {
527
+ const s = r.filters.filter((m) => m.isValid), i = k(s), o = ((d = b().find((m) => m.key === r.strategy)) == null ? void 0 : d.path) || "", c = parseInt(r.size) || 6, a = {
628
528
  locale: r.language,
629
529
  currency: r.currencySettings.value,
630
530
  partnerName: n.partnerName,
@@ -632,21 +532,21 @@ const $ = () => ({
632
532
  details: !0,
633
533
  campaignId: n.variationId
634
534
  };
635
- r.strategy === "manualMerchandising" ? c.productId = T(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(
636
- c,
637
- O(n.partnerName, r.strategy)
535
+ r.strategy === "manualMerchandising" ? a.productId = A(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(
536
+ a,
537
+ x(n.partnerName, r.strategy)
638
538
  );
639
- let m;
539
+ let l;
640
540
  try {
641
- m = await f.fetchRecommendationProducts(u, c);
541
+ l = await u.fetchRecommendationProducts(o, a);
642
542
  } catch {
643
- m = [];
543
+ l = [];
644
544
  }
645
- h.get(t) === s && this._setBlockProducts(t, m, i);
545
+ this._setBlockProducts(t, l, c);
646
546
  },
647
547
  async _doFetchStrategyProducts(t) {
648
- const e = (h.get(t) ?? 0) + 1;
649
- h.set(t, e);
548
+ const e = (p.get(t) ?? 0) + 1;
549
+ p.set(t, e);
650
550
  const { recommendationConfigs: r } = this.blockStates[t];
651
551
  let n = [], s = parseInt(r.size) || 6;
652
552
  try {
@@ -656,25 +556,25 @@ const $ = () => ({
656
556
  );
657
557
  if (i) {
658
558
  s = parseInt(String(i.size ?? "")) || s;
659
- const o = r.currencySettings.value, u = (await this.resolveStrategyUrlTemplate(i, o)).replaceAll("{locale}", r.language).replaceAll("{currency}", o), c = u.indexOf("?"), m = c === -1 ? u : u.slice(0, c), g = (c === -1 ? "" : u.slice(c + 1)).split("&").filter((k) => k && !k.startsWith("user_id=")), d = g.length ? `${m}?${g.join("&")}` : m;
660
- d && (n = await f.fetchRecommendationProductsByUrl(d));
559
+ const o = r.currencySettings.value, a = (await this.resolveStrategyUrlTemplate(i, o)).replaceAll("{locale}", r.language).replaceAll("{currency}", o), l = a.indexOf("?"), d = l === -1 ? a : a.slice(0, l), m = (l === -1 ? "" : a.slice(l + 1)).split("&").filter((I) => I && !I.startsWith("user_id=")), y = m.length ? `${d}?${m.join("&")}` : d;
560
+ y && (n = await u.fetchRecommendationProductsByUrl(y));
661
561
  }
662
562
  } catch {
663
563
  n = [];
664
564
  }
665
- h.get(t) === e && this._setBlockProducts(t, n, s);
565
+ p.get(t) === e && this._setBlockProducts(t, n, s);
666
566
  },
667
567
  _setBlockProducts(t, e, r) {
668
568
  if (!this.blockStates[t])
669
569
  return;
670
- const n = e.length > 0 ? e : v(r);
570
+ const n = e.length > 0 ? e : R(r);
671
571
  this.blockStates[t].recommendationProducts = [
672
572
  ...n.slice(0, r),
673
- ...v(Math.max(0, r - n.length))
573
+ ...R(Math.max(0, r - n.length))
674
574
  ];
675
575
  }
676
576
  }
677
577
  });
678
578
  export {
679
- it as useRecommendationExtensionStore
579
+ Y as useRecommendationExtensionStore
680
580
  };
@@ -1,32 +1,22 @@
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 f } from "../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
2
+ import { RECOMMENDATION_ID_ATTR as m } from "../constants/selectors.js";
3
+ import { isPartnerManagedBlock as a, updateProductContentInPlace as d, regenerateProductRowsWithStyles as l } from "../controls/main/utils.js";
4
+ import { RecommendationConfigService as s } from "../services/configService.js";
5
+ let e = null;
6
+ function N(r) {
7
+ e = r;
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 D(r, c, i, u) {
10
+ const n = e == null ? void 0 : e.getDocumentRootHtmlNode();
11
+ if (!e || !n || !("querySelector" in n))
12
12
  return !1;
13
- const e = i.querySelector(`[${s}="${n}"]`);
14
- if (!e)
13
+ const t = n.querySelector(`[${m}="${r}"]`);
14
+ if (!t)
15
15
  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;
19
- let f = !1;
20
- return C({
21
- currentNode: e,
22
- documentModifier: t,
23
- products: c,
24
- onApplied: () => {
25
- f = !0;
26
- }
27
- }) || (f = N({ currentNode: e, documentModifier: t, products: c })), !f && d && t.apply(new g(l)), !0;
16
+ const o = e.getDocumentModifier();
17
+ return s.stageConfig(o, t, c), a(t) ? (o.apply(new f(u)), !0) : (d({ currentNode: t, documentModifier: o, products: i }) || l({ currentNode: t, documentModifier: o, products: i }), !0);
28
18
  }
29
19
  export {
30
- P as commitBlockChangeOutsidePanel,
31
- D as registerNodeConfigWriter
20
+ D as commitBlockChangeOutsidePanel,
21
+ N as registerNodeConfigWriter
32
22
  };
@@ -1,43 +1,34 @@
1
- const o = "strategy", u = [
1
+ const l = [
2
2
  {
3
3
  key: "locale",
4
4
  getValue: (e) => e.language,
5
5
  getAvailableOptions: (e) => Object.keys(e.languages)
6
6
  },
7
- {
8
- // A block feeds from either an assigned strategy (RRS) or an algorithm (legacy).
9
- // Only a fresh RRS block has neither, and its feed URL would otherwise be built
10
- // from an empty algorithm path.
11
- key: o,
12
- getValue: (e) => e.strategyId || e.strategy
13
- },
14
7
  {
15
8
  key: "currency",
16
9
  getValue: (e) => e.currencySettings.value,
17
10
  getAvailableOptions: (e) => e.currencyList.map((n) => n.text),
18
11
  canBeEmpty: !0
19
12
  }
20
- ], l = "newsletter.recommendation-fill-required-fields", g = "newsletter.recommendation-assign-strategy";
21
- function c(e, n, i = u) {
13
+ ], o = "newsletter.recommendation-fill-required-fields";
14
+ function c(e, n, i = l) {
22
15
  return i.filter((t) => {
23
- var s;
16
+ var u;
24
17
  if (t.condition && !t.condition(e))
25
18
  return !1;
26
- const a = (s = t.getAvailableOptions) == null ? void 0 : s.call(t, n);
27
- if (t.canBeEmpty && (a == null ? void 0 : a.length) === 0)
19
+ const r = (u = t.getAvailableOptions) == null ? void 0 : u.call(t, n);
20
+ if (t.canBeEmpty && (r == null ? void 0 : r.length) === 0)
28
21
  return !1;
29
- const r = t.getValue(e);
30
- return r ? a !== void 0 && !a.includes(r) : !0;
22
+ const a = t.getValue(e);
23
+ return a ? r !== void 0 && !r.includes(a) : !0;
31
24
  }).map((t) => t.key);
32
25
  }
33
- function y(e, n) {
26
+ function s(e, n) {
34
27
  return c(e, n).length === 0;
35
28
  }
36
29
  export {
37
- u as REQUIRED_RECOMMENDATION_FIELDS,
38
- g as RecommendationAssignStrategyKey,
39
- l as RecommendationRequiredFieldsKey,
40
- o as STRATEGY_FIELD_KEY,
30
+ l as REQUIRED_RECOMMENDATION_FIELDS,
31
+ o as RecommendationRequiredFieldsKey,
41
32
  c as getInvalidFields,
42
- y as isConfigValid
33
+ s as isConfigValid
43
34
  };
package/dist/guido.css CHANGED
@@ -1 +1 @@
1
- @charset "UTF-8";.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-1ca6baf0]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-cc5ee925]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-cc5ee925]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-cc5ee925]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-ec2027ff] .vueperslides__bullets,[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-521cf6b3]{width:100%;max-width:none}.assign-strategy-drawer-content .assign-strategy-select[data-v-521cf6b3] .in-dropdown-box__container{width:413px}.assign-strategy-drawer .spaced-dot-sep{background-image:linear-gradient(90deg,#91949f 20%,#fff0 0);background-position:center bottom;background-repeat:repeat-x;background-size:5px 1px}.assign-strategy-drawer .spaced-dot-sep--top{background-position:center top}.assign-strategy-drawer .spaced-dot-sep--fc-n:first-child{background:none}
1
+ @charset "UTF-8";.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-1ca6baf0]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-050dfa52]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-050dfa52]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-050dfa52]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-2580a7d9]{width:100%;max-width:none}.assign-strategy-drawer-content .assign-strategy-select[data-v-2580a7d9] .in-dropdown-box__container{width:413px}.assign-strategy-drawer .spaced-dot-sep{background-image:linear-gradient(90deg,#91949f 20%,#fff0 0);background-position:center bottom;background-repeat:repeat-x;background-size:5px 1px}.assign-strategy-drawer .spaced-dot-sep--top{background-position:center top}.assign-strategy-drawer .spaced-dot-sep--fc-n:first-child{background:none}