@useinsider/guido 3.18.1-beta.d931f79 → 3.18.1-beta.db1e41e

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.
@@ -1,23 +1,23 @@
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";
3
- import { useConfigStore as P } from "../../../../stores/config.js";
4
- import { defineStore as L } from "pinia";
1
+ import { getRecommendationFeedSourceMaps as k, strategyEditPath as G, URLS as D, getOperatorOptions as _, PriceAttributes as L } from "../../../../enums/extensions/recommendationBlock.js";
2
+ import { useRecommendationApi as E } from "../../../../services/recommendationApi.js";
3
+ import { useConfigStore as F } from "../../../../stores/config.js";
4
+ import { defineStore as N } 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 w } 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 d = A();
15
- let h = null, g = null, S = null, y = "", b = null, p = 0;
16
- const I = /* @__PURE__ */ new Map();
6
+ import { DEFAULT_MOBILE_CARDS_IN_ROW as U, DEFAULT_CARDS_IN_ROW as A } from "../constants/layout.js";
7
+ import { DEFAULT_NODE_CONFIG as x, EXCLUDED_ALGORITHM_IDS as B } from "../constants/defaultConfig.js";
8
+ import { getDefaultProducts as C } from "../templates/utils.js";
9
+ import { generateCompleteFilterQuery as v } from "../utils/filterUtil.js";
10
+ import { getPartnerRecommendationParams as M } from "../utils/partnerCustomizations.js";
11
+ import { sanitizeProductIds as O } from "../utils/productIds.js";
12
+ import { isFilterValid as T } from "../validation/filterSchema.js";
13
+ import { getInvalidFields as z, isConfigValid as V } from "../validation/requiredFields.js";
14
+ const d = E();
15
+ let h = null, g = null, S = null, p = null, y = 0;
16
+ const b = /* @__PURE__ */ new Map();
17
17
  let l = null;
18
- function G() {
18
+ function P() {
19
19
  return {
20
- cardsInRow: x,
20
+ cardsInRow: A,
21
21
  currencySettings: {
22
22
  name: "USD",
23
23
  value: "USD",
@@ -31,7 +31,7 @@ function G() {
31
31
  productIds: [],
32
32
  id: 1,
33
33
  language: "en_US",
34
- mobileCardsInRow: E,
34
+ mobileCardsInRow: U,
35
35
  mobileLayoutEnabled: !1,
36
36
  orientation: "grid",
37
37
  recommendedProducts: [],
@@ -41,7 +41,7 @@ function G() {
41
41
  // that default is what reached buildCampaignUrl and baked a most-popular feed URL
42
42
  // for a block the user never configured (SD-149916). Legacy blocks still get their real
43
43
  // algorithm from the node-config sync or the save-time seed.
44
- strategy: P().isFeatureEnabled("reusableRecommendationStrategy") ? "" : "mostPopular",
44
+ strategy: F().isFeatureEnabled("reusableRecommendationStrategy") ? "" : "mostPopular",
45
45
  strategyId: "",
46
46
  textTrimming: !0,
47
47
  unresponsive: !1,
@@ -51,9 +51,9 @@ function G() {
51
51
  priceHideIfSameAsDiscounted: !1
52
52
  };
53
53
  }
54
- function F() {
54
+ function w() {
55
55
  return {
56
- recommendationConfigs: G(),
56
+ recommendationConfigs: P(),
57
57
  recommendationProducts: [],
58
58
  filterStatus: !1,
59
59
  filterSelectionDrawerStatus: !1,
@@ -64,7 +64,7 @@ function F() {
64
64
  filterSnapshot: null
65
65
  };
66
66
  }
67
- const $ = () => ({
67
+ const j = () => ({
68
68
  recommendationCampaignUrls: {},
69
69
  activePredictiveAlgorithms: [],
70
70
  languages: {},
@@ -79,8 +79,8 @@ const $ = () => ({
79
79
  currentRecommendationId: null,
80
80
  strategyPanelOpen: !1,
81
81
  configVersion: 0
82
- }), nt = L("guidoRecommendationExtension", {
83
- state: () => $(),
82
+ }), nt = N("guidoRecommendationExtension", {
83
+ state: () => j(),
84
84
  getters: {
85
85
  // ====================================================================
86
86
  // Proxy Getters — Backward Compatible Access to Current Block State
@@ -90,7 +90,7 @@ const $ = () => ({
90
90
  * This allows all existing code that reads `store.recommendationConfigs` to work unchanged.
91
91
  */
92
92
  recommendationConfigs(t) {
93
- return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : G();
93
+ return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : P();
94
94
  },
95
95
  /**
96
96
  * Proxy getter: delegates to blockStates[currentRecommendationId].recommendationProducts
@@ -145,12 +145,12 @@ const $ = () => ({
145
145
  return [...new Set(t.map((e) => e.filterGroup))].sort((e, r) => e - r);
146
146
  },
147
147
  getActivePredictiveAlgorithms: (t) => {
148
- const e = C(), r = [];
149
- return t.activePredictiveAlgorithms.filter((i) => !M.includes(i)).forEach((i) => {
150
- r.push(...e.filter((s) => s.id === i));
151
- }), r.map((i) => ({
152
- text: i.name,
153
- value: i.key
148
+ const e = k(), r = [];
149
+ return t.activePredictiveAlgorithms.filter((n) => !B.includes(n)).forEach((n) => {
150
+ r.push(...e.filter((s) => s.id === n));
151
+ }), r.map((n) => ({
152
+ text: n.name,
153
+ value: n.key
154
154
  }));
155
155
  },
156
156
  getLanguages: (t) => Object.entries(t.languages).map(([e, r]) => ({
@@ -164,7 +164,7 @@ const $ = () => ({
164
164
  getFilterList() {
165
165
  return Object.values(this.filterList).filter((t) => t.isFilterable !== 0 && t.isFilterable !== !1).map((t) => {
166
166
  let e;
167
- return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : U.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
167
+ return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : L.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
168
168
  text: t.displayName,
169
169
  value: e,
170
170
  type: t.attributeType
@@ -186,7 +186,7 @@ const $ = () => ({
186
186
  setCurrentBlock(t) {
187
187
  this.blockStates[t] || (this.blockStates = {
188
188
  ...this.blockStates,
189
- [t]: F()
189
+ [t]: w()
190
190
  }), this.currentRecommendationId = t;
191
191
  },
192
192
  /**
@@ -196,13 +196,13 @@ const $ = () => ({
196
196
  removeBlockState(t) {
197
197
  const e = t.toString();
198
198
  if (this.recommendationCampaignUrls[e]) {
199
- const i = { ...this.recommendationCampaignUrls };
200
- delete i[e], this.recommendationCampaignUrls = i;
199
+ const n = { ...this.recommendationCampaignUrls };
200
+ delete n[e], this.recommendationCampaignUrls = n;
201
201
  }
202
202
  const r = { ...this.blockStates };
203
203
  if (delete r[t], this.blockStates = r, this.currentRecommendationId === t) {
204
- const i = Object.keys(this.blockStates).map(Number);
205
- this.currentRecommendationId = i.length > 0 ? i[0] : null;
204
+ const n = Object.keys(this.blockStates).map(Number);
205
+ this.currentRecommendationId = n.length > 0 ? n[0] : null;
206
206
  }
207
207
  },
208
208
  /**
@@ -218,10 +218,10 @@ const $ = () => ({
218
218
  [e]: o
219
219
  };
220
220
  }
221
- const i = t.toString(), s = e.toString(), n = this.recommendationCampaignUrls[i];
222
- n && (this.recommendationCampaignUrls = {
221
+ const n = t.toString(), s = e.toString(), i = this.recommendationCampaignUrls[n];
222
+ i && (this.recommendationCampaignUrls = {
223
223
  ...this.recommendationCampaignUrls,
224
- [s]: n
224
+ [s]: i
225
225
  });
226
226
  },
227
227
  /**
@@ -246,7 +246,7 @@ const $ = () => ({
246
246
  * `isInitialized`) alone.
247
247
  */
248
248
  seedBlockUrlConfig(t, e) {
249
- const r = (o, c) => o === "." || o === "," || o === " " ? o : c, i = {
249
+ const r = (o, c) => o === "." || o === "," || o === " " ? o : c, n = {
250
250
  name: e.currencyCode,
251
251
  value: e.currencyCode,
252
252
  symbol: e.currencyCode,
@@ -254,9 +254,9 @@ const $ = () => ({
254
254
  decimalCount: String(e.currencyDecimalCount),
255
255
  decimalSeparator: r(e.currencyDecimalSeparator, ","),
256
256
  thousandSeparator: r(e.currencyThousandSeparator, ".")
257
- }, s = !this.blockStates[t], n = s ? F() : this.blockStates[t];
258
- n.recommendationConfigs = {
259
- ...n.recommendationConfigs,
257
+ }, s = !this.blockStates[t], i = s ? w() : this.blockStates[t];
258
+ i.recommendationConfigs = {
259
+ ...i.recommendationConfigs,
260
260
  strategy: e.strategy,
261
261
  strategyId: e.strategyId,
262
262
  language: e.language,
@@ -264,10 +264,10 @@ const $ = () => ({
264
264
  productIds: e.productIds,
265
265
  filters: e.filters,
266
266
  shuffleProducts: e.shuffleProducts,
267
- currencySettings: i
267
+ currencySettings: n
268
268
  }, s && (this.blockStates = {
269
269
  ...this.blockStates,
270
- [t]: n
270
+ [t]: i
271
271
  });
272
272
  },
273
273
  /**
@@ -286,18 +286,18 @@ const $ = () => ({
286
286
  ...t.currencySettings || {}
287
287
  }
288
288
  };
289
- const { triggerRefetch: i = !0 } = e;
290
- i && this.configVersion++;
289
+ const { triggerRefetch: n = !0 } = e;
290
+ n && this.configVersion++;
291
291
  },
292
292
  /**
293
293
  * Creates a filter with the first available attribute and operator pre-selected.
294
294
  */
295
295
  createDefaultFilter(t, e) {
296
- const [r] = this.getFilterList, [i] = N(r == null ? void 0 : r.type);
296
+ const [r] = this.getFilterList, [n] = _(r == null ? void 0 : r.type);
297
297
  return {
298
298
  type: "standardFilter",
299
299
  attribute: (r == null ? void 0 : r.value) ?? "",
300
- operator: (i == null ? void 0 : i.value) ?? "",
300
+ operator: (n == null ? void 0 : n.value) ?? "",
301
301
  innerGroupOperator: "*",
302
302
  outerGroupOperator: "*",
303
303
  filterNumber: e,
@@ -353,39 +353,38 @@ const $ = () => ({
353
353
  this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].removeStrategyModalStatus = !1);
354
354
  },
355
355
  async fetchStrategies() {
356
- for (; b; )
356
+ for (; p; )
357
357
  try {
358
- await b;
358
+ await p;
359
359
  } catch {
360
360
  }
361
361
  if (this.strategiesFetched)
362
362
  return;
363
- const t = p, e = (async () => {
363
+ const t = y, e = (async () => {
364
364
  this.strategiesLoading = !0;
365
365
  try {
366
366
  const r = await d.fetchRecommendationStrategies();
367
- if (t !== p)
367
+ if (t !== y)
368
368
  return;
369
369
  this.strategies = r, this.strategiesFetched = !0;
370
370
  } finally {
371
- this.strategiesLoading = !1, t === p && (this.strategiesSettled = !0);
371
+ this.strategiesLoading = !1, t === y && (this.strategiesSettled = !0);
372
372
  }
373
373
  })();
374
- b = e;
374
+ p = e;
375
375
  try {
376
376
  await e;
377
377
  } finally {
378
- b = null;
378
+ p = null;
379
379
  }
380
380
  },
381
381
  invalidateStrategies() {
382
- this.strategiesFetched = !1, this.strategiesSettled = !1, p += 1;
382
+ this.strategiesFetched = !1, this.strategiesSettled = !1, y += 1;
383
383
  },
384
384
  /**
385
385
  * Opens a Smart Recommender strategy page in a new tab and refreshes the list every time
386
- * the user comes back. `visibilitychange` only: a `focus` listener would also fire when
387
- * focus merely returns from the Stripo canvas iframe to the panel, refetching and
388
- * regenerating the canvas while the user never left the editor (SD-149916).
386
+ * the user comes back. `visibilitychange` covers the tab case; `focus` covers the page
387
+ * landing in a separate window, where this document never goes hidden.
389
388
  *
390
389
  * Deliberately NOT one-shot: the strategy tab stays open, so a user can create a second
391
390
  * strategy in it and come back again — a listener that disarmed on the first return would
@@ -399,14 +398,14 @@ const $ = () => ({
399
398
  return;
400
399
  e.opener = null, l == null || l();
401
400
  let r = !1;
402
- const i = () => {
401
+ const n = () => {
403
402
  document.hidden || r || (e != null && e.closed && (l == null || l()), r = !0, this.invalidateStrategies(), this.fetchStrategies().then(() => this._refreshAssignedStrategyProducts()).catch(() => {
404
403
  }).finally(() => {
405
404
  r = !1;
406
405
  }));
407
406
  };
408
- document.addEventListener("visibilitychange", i), l = () => {
409
- document.removeEventListener("visibilitychange", i), l = null;
407
+ document.addEventListener("visibilitychange", n), window.addEventListener("focus", n), l = () => {
408
+ document.removeEventListener("visibilitychange", n), window.removeEventListener("focus", n), l = null;
410
409
  };
411
410
  },
412
411
  /**
@@ -430,24 +429,24 @@ const $ = () => ({
430
429
  * new strategy is offered; the user picks it themselves.
431
430
  */
432
431
  openStrategyCreation() {
433
- this._armStrategyPageReturn(_.RECOMMENDATION_STRATEGY_CREATE_PATH);
432
+ this._armStrategyPageReturn(D.RECOMMENDATION_STRATEGY_CREATE_PATH);
434
433
  },
435
434
  /**
436
435
  * Opens the strategy's edit page. Every return refreshes the list so the block reflects the
437
436
  * edited configuration.
438
437
  */
439
438
  openStrategyEdit(t) {
440
- this._armStrategyPageReturn(D(t));
439
+ this._armStrategyPageReturn(G(t));
441
440
  },
442
441
  async resolveStrategyUrlTemplate(t, e) {
443
- const r = typeof t.updated_at == "string" ? t.updated_at : "", i = r ? `${t.strategy_id}:${r}:${e}` : "", s = i ? this.strategyUrlTemplates[i] : void 0;
442
+ const r = typeof t.updated_at == "string" ? t.updated_at : "", n = r ? `${t.strategy_id}:${r}:${e}` : "", s = n ? this.strategyUrlTemplates[n] : void 0;
444
443
  if (s)
445
444
  return s;
446
- const { full_path: n = "" } = await d.generateStrategyEndpoint(t, e) ?? {};
447
- return i && n && (this.strategyUrlTemplates = {
445
+ const { full_path: i = "" } = await d.generateStrategyEndpoint(t, e) ?? {};
446
+ return n && i && (this.strategyUrlTemplates = {
448
447
  ...this.strategyUrlTemplates,
449
- [i]: n
450
- }), n;
448
+ [n]: i
449
+ }), i;
451
450
  },
452
451
  assignStrategy(t) {
453
452
  this.patchCurrentBlockConfig({
@@ -459,7 +458,7 @@ const $ = () => ({
459
458
  this.patchCurrentBlockConfig({
460
459
  strategyId: "",
461
460
  strategy: "",
462
- size: B.size
461
+ size: x.size
463
462
  });
464
463
  },
465
464
  // ====================================================================
@@ -478,8 +477,8 @@ const $ = () => ({
478
477
  currencies: r
479
478
  } = await d.fetchRecommendationCreateData();
480
479
  if (this.activePredictiveAlgorithms = t, this.languages = e, this.currentRecommendationId !== null && this.blockStates[this.currentRecommendationId]) {
481
- const i = this.blockStates[this.currentRecommendationId];
482
- i.filterStatus = !!i.recommendationConfigs.filters.length;
480
+ const n = this.blockStates[this.currentRecommendationId];
481
+ n.filterStatus = !!n.recommendationConfigs.filters.length;
483
482
  }
484
483
  this.currencyList = r;
485
484
  })();
@@ -518,41 +517,41 @@ const $ = () => ({
518
517
  deleteFilterGroup(t) {
519
518
  if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
520
519
  return;
521
- const e = this.blockStates[this.currentRecommendationId], r = e.recommendationConfigs.filters.filter((n) => n.filterGroup !== t), i = [...new Set(r.map((n) => n.filterGroup))].sort((n, o) => n - o), s = new Map(i.map((n, o) => [n, o + 1]));
522
- e.recommendationConfigs.filters = r.map((n) => ({
523
- ...n,
524
- filterGroup: s.get(n.filterGroup) ?? n.filterGroup
520
+ 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]));
521
+ e.recommendationConfigs.filters = r.map((i) => ({
522
+ ...i,
523
+ filterGroup: s.get(i.filterGroup) ?? i.filterGroup
525
524
  }));
526
525
  },
527
526
  updateFilter(t) {
528
527
  if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
529
528
  return;
530
- const e = this.blockStates[this.currentRecommendationId], r = e.recommendationConfigs.filters.findIndex((i) => i.filterNumber === t.filterNumber && i.filterGroup === t.filterGroup);
529
+ const e = this.blockStates[this.currentRecommendationId], r = e.recommendationConfigs.filters.findIndex((n) => n.filterNumber === t.filterNumber && n.filterGroup === t.filterGroup);
531
530
  if (r !== -1) {
532
- const i = [...e.recommendationConfigs.filters];
533
- i[r] = {
531
+ const n = [...e.recommendationConfigs.filters];
532
+ n[r] = {
534
533
  ...t,
535
- isValid: z(t)
536
- }, e.recommendationConfigs.filters = i;
534
+ isValid: T(t)
535
+ }, e.recommendationConfigs.filters = n;
537
536
  }
538
537
  },
539
538
  deleteFilter(t) {
540
539
  if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
541
540
  return;
542
- const e = this.blockStates[this.currentRecommendationId], r = [...e.recommendationConfigs.filters].findIndex((i) => i.filterNumber === t.filterNumber && i.filterGroup === t.filterGroup);
541
+ const e = this.blockStates[this.currentRecommendationId], r = [...e.recommendationConfigs.filters].findIndex((n) => n.filterNumber === t.filterNumber && n.filterGroup === t.filterGroup);
543
542
  if (r !== -1) {
544
- let i = [...e.recommendationConfigs.filters];
545
- if (i.splice(r, 1), i.some((n) => n.filterGroup === t.filterGroup)) {
546
- let n = 1;
547
- i = i.map((o) => o.filterGroup === t.filterGroup ? { ...o, filterNumber: n++ } : o);
543
+ let n = [...e.recommendationConfigs.filters];
544
+ if (n.splice(r, 1), n.some((i) => i.filterGroup === t.filterGroup)) {
545
+ let i = 1;
546
+ n = n.map((o) => o.filterGroup === t.filterGroup ? { ...o, filterNumber: i++ } : o);
548
547
  } else {
549
- const n = [...new Set(i.map((c) => c.filterGroup))].sort((c, a) => c - a), o = new Map(n.map((c, a) => [c, a + 1]));
550
- i = i.map((c) => ({
548
+ const i = [...new Set(n.map((c) => c.filterGroup))].sort((c, a) => c - a), o = new Map(i.map((c, a) => [c, a + 1]));
549
+ n = n.map((c) => ({
551
550
  ...c,
552
551
  filterGroup: o.get(c.filterGroup) ?? c.filterGroup
553
552
  }));
554
553
  }
555
- e.recommendationConfigs.filters = i;
554
+ e.recommendationConfigs.filters = n;
556
555
  }
557
556
  },
558
557
  addFilter(t) {
@@ -560,8 +559,8 @@ const $ = () => ({
560
559
  return;
561
560
  const e = this.blockStates[this.currentRecommendationId], r = [...e.recommendationConfigs.filters], s = r.filter(
562
561
  (o) => o.filterGroup === t.filterGroup
563
- ).length + 1, n = r.findLastIndex((o) => o.filterGroup === t.filterGroup);
564
- n !== -1 ? r.splice(n + 1, 0, {
562
+ ).length + 1, i = r.findLastIndex((o) => o.filterGroup === t.filterGroup);
563
+ i !== -1 ? r.splice(i + 1, 0, {
565
564
  ...t,
566
565
  filterNumber: s
567
566
  }) : r.push({
@@ -570,7 +569,7 @@ const $ = () => ({
570
569
  }), e.recommendationConfigs.filters = r;
571
570
  },
572
571
  generateFilterQuery() {
573
- return w(this.recommendationConfigs.filters);
572
+ return v(this.recommendationConfigs.filters);
574
573
  },
575
574
  /**
576
575
  * Validation-only check invoked at save-CTA time. Defined as an action
@@ -578,41 +577,36 @@ const $ = () => ({
578
577
  * every block's recommendationConfigs across user edits.
579
578
  */
580
579
  hasInvalidBlock() {
581
- return Object.values(this.blockStates).some((t) => !j(t.recommendationConfigs, this));
580
+ return Object.values(this.blockStates).some((t) => !V(t.recommendationConfigs, this));
582
581
  },
583
582
  /**
584
583
  * Which required fields are missing across the design's blocks, so the save
585
584
  * toaster can name the cause instead of always showing the generic message.
586
585
  */
587
586
  invalidBlockFields() {
588
- return Object.values(this.blockStates).flatMap((t) => V(t.recommendationConfigs, this));
587
+ return Object.values(this.blockStates).flatMap((t) => z(t.recommendationConfigs, this));
589
588
  },
590
589
  // ====================================================================
591
590
  // Per-Block Product Fetching
592
591
  // ====================================================================
593
592
  async fetchRecommendationProducts() {
594
- if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
595
- return;
596
- const t = [
597
- this.currentRecommendationId,
598
- this.configVersion,
599
- p
600
- ].join(":");
601
- if (S && y === t) {
602
- await S;
603
- return;
604
- }
605
- y = t, S = this._doFetchProducts();
606
- try {
607
- await S;
608
- } finally {
609
- y === t && (S = null, y = "");
593
+ if (!(this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])) {
594
+ if (S) {
595
+ await S;
596
+ return;
597
+ }
598
+ S = this._doFetchProducts();
599
+ try {
600
+ await S;
601
+ } finally {
602
+ S = null;
603
+ }
610
604
  }
611
605
  },
612
606
  async _doFetchProducts() {
613
607
  var f;
614
- const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, i = P();
615
- if (r.strategyId && i.isFeatureEnabled("reusableRecommendationStrategy")) {
608
+ const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = F();
609
+ if (r.strategyId && n.isFeatureEnabled("reusableRecommendationStrategy")) {
616
610
  await this._doFetchStrategyProducts(t);
617
611
  return;
618
612
  }
@@ -621,17 +615,17 @@ const $ = () => ({
621
615
  this._setBlockProducts(t, [], s);
622
616
  return;
623
617
  }
624
- const n = r.filters.filter((m) => m.isValid), o = w(n), c = ((f = C().find((m) => m.key === r.strategy)) == null ? void 0 : f.path) || "", a = {
618
+ const i = r.filters.filter((m) => m.isValid), o = v(i), c = ((f = k().find((m) => m.key === r.strategy)) == null ? void 0 : f.path) || "", a = {
625
619
  locale: r.language,
626
620
  currency: r.currencySettings.value,
627
- partnerName: i.partnerName,
621
+ partnerName: n.partnerName,
628
622
  size: r.size,
629
623
  details: !0,
630
- campaignId: i.variationId
624
+ campaignId: n.variationId
631
625
  };
632
- r.strategy === "manualMerchandising" ? a.productId = T(r.productIds) : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), o && (a.filter = o), r.shuffleProducts && (a.shuffle = !0), Object.assign(
626
+ r.strategy === "manualMerchandising" ? a.productId = O(r.productIds) : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), o && (a.filter = o), r.shuffleProducts && (a.shuffle = !0), Object.assign(
633
627
  a,
634
- O(i.partnerName, r.strategy)
628
+ M(n.partnerName, r.strategy)
635
629
  );
636
630
  let u;
637
631
  try {
@@ -642,32 +636,32 @@ const $ = () => ({
642
636
  this._setBlockProducts(t, u, s);
643
637
  },
644
638
  async _doFetchStrategyProducts(t) {
645
- const e = (I.get(t) ?? 0) + 1;
646
- I.set(t, e);
639
+ const e = (b.get(t) ?? 0) + 1;
640
+ b.set(t, e);
647
641
  const { recommendationConfigs: r } = this.blockStates[t];
648
- let i = [], s = parseInt(r.size) || 6;
642
+ let n = [], s = parseInt(r.size) || 6;
649
643
  try {
650
644
  await this.fetchStrategies();
651
- const n = this.strategies.find(
645
+ const i = this.strategies.find(
652
646
  (o) => String(o.strategy_id) === r.strategyId
653
647
  );
654
- if (n) {
655
- s = parseInt(String(n.size ?? "")) || s;
656
- const o = r.currencySettings.value, a = (await this.resolveStrategyUrlTemplate(n, o)).replaceAll("{locale}", r.language).replaceAll("{currency}", o), u = a.indexOf("?"), f = u === -1 ? a : a.slice(0, u), m = (u === -1 ? "" : a.slice(u + 1)).split("&").filter((k) => k && !k.startsWith("user_id=")), R = m.length ? `${f}?${m.join("&")}` : f;
657
- R && (i = await d.fetchRecommendationProductsByUrl(R));
648
+ if (i) {
649
+ s = parseInt(String(i.size ?? "")) || s;
650
+ const o = r.currencySettings.value, a = (await this.resolveStrategyUrlTemplate(i, o)).replaceAll("{locale}", r.language).replaceAll("{currency}", o), u = a.indexOf("?"), f = u === -1 ? a : a.slice(0, u), m = (u === -1 ? "" : a.slice(u + 1)).split("&").filter((R) => R && !R.startsWith("user_id=")), I = m.length ? `${f}?${m.join("&")}` : f;
651
+ I && (n = await d.fetchRecommendationProductsByUrl(I));
658
652
  }
659
653
  } catch {
660
- i = [];
654
+ n = [];
661
655
  }
662
- I.get(t) === e && this._setBlockProducts(t, i, s);
656
+ b.get(t) === e && this._setBlockProducts(t, n, s);
663
657
  },
664
658
  _setBlockProducts(t, e, r) {
665
659
  if (!this.blockStates[t])
666
660
  return;
667
- const i = e.length > 0 ? e : v(r);
661
+ const n = e.length > 0 ? e : C(r);
668
662
  this.blockStates[t].recommendationProducts = [
669
- ...i.slice(0, r),
670
- ...v(Math.max(0, r - i.length))
663
+ ...n.slice(0, r),
664
+ ...C(Math.max(0, r - n.length))
671
665
  ];
672
666
  }
673
667
  }
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-6c26ded2]{width:100%;max-width:none}.assign-strategy-drawer-content .assign-strategy-select[data-v-6c26ded2] .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-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-b447f626]{width:100%;max-width:none}.assign-strategy-drawer-content .assign-strategy-select[data-v-b447f626] .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}
@@ -10,7 +10,6 @@
10
10
  import type { RecommendationNodeConfig, CurrencyConfig, OmnibusTextConfig } from '../types/nodeConfig';
11
11
  export declare const PRE_RRS_CONFIG_VERSION = 1;
12
12
  export declare const CURRENT_CONFIG_VERSION = 2;
13
- export declare const RRS_CONFIG_VERSION = 2;
14
13
  /**
15
14
  * Default currency configuration
16
15
  * Uses USD as the base currency with standard formatting
@@ -10,4 +10,4 @@ export { RecommendationBlockId } from './blockIds';
10
10
  export { RecommendationControlId } from './controlIds';
11
11
  export { BLOCK_ROOT_SELECTOR, CONTAINER_SELECTOR, DESKTOP_CONTAINER_SELECTOR, MOBILE_CONTAINER_SELECTOR, MOBILE_ROW_SELECTOR, CSS_CLASS_RECO_BUTTON, CSS_CLASS_SKIP_COMPILE, RECOMMENDATION_VARIABLE_BUILTIN_ATTRIBUTES, CURRENCY_ATTR, ATTR_PRODUCT_IMAGE, ATTR_PRODUCT_NAME, ATTR_PRODUCT_PRICE, ATTR_PRODUCT_OLD_PRICE, ATTR_PRODUCT_OMNIBUS_PRICE, ATTR_PRODUCT_OMNIBUS_DISCOUNT, ATTR_PRODUCT_BUTTON, ATTR_RECOMMENDATION_TITLE, SELECTOR_TITLE_CELL, ATTR_CUSTOM_PREFIX, ATTR_DATA_CARD_COMPOSITION, ATTR_DATA_CUSTOM_ATTRIBUTES, ATTR_PRODUCT_ATTR, CSS_CLASS_ATTRIBUTE_ROW, CSS_CLASS_SPACER, SELECTOR_ATTRIBUTE_ROW, ATTR_DATA_ATTRIBUTE_TYPE, ATTR_DATA_VISIBILITY, PRODUCT_ATTRIBUTE_PREFIX, BUILT_IN_DEFAULT_ATTRIBUTES, } from './selectors';
12
12
  export { LAYOUT_VALUES, LAYOUT_OPTIONS, DEFAULT_PRODUCTS_PER_ROW, DEFAULT_CARDS_IN_ROW, DEFAULT_MOBILE_CARDS_IN_ROW, MAX_PRODUCT_COUNT, MIN_PRODUCT_COUNT, MAX_PRODUCTS_PER_ROW, MIN_PRODUCTS_PER_ROW, MAX_MOBILE_PRODUCTS_PER_ROW, MIN_MOBILE_PRODUCTS_PER_ROW, DEFAULT_COLUMN_SPACING, DEFAULT_ROW_SPACING, DEFAULT_MOBILE_COLUMN_SPACING, DEFAULT_MOBILE_ROW_SPACING, MIN_SPACING, MAX_SPACING, SPACING_STEP, } from './layout';
13
- export { DEFAULT_NODE_CONFIG, DEFAULT_CURRENCY, DEFAULT_COMPOSITION, DEFAULT_VISIBILITY, CURRENT_CONFIG_VERSION, PRE_RRS_CONFIG_VERSION, RRS_CONFIG_VERSION, EXCLUDED_ALGORITHM_IDS, } from './defaultConfig';
13
+ export { DEFAULT_NODE_CONFIG, DEFAULT_CURRENCY, DEFAULT_COMPOSITION, DEFAULT_VISIBILITY, CURRENT_CONFIG_VERSION, PRE_RRS_CONFIG_VERSION, EXCLUDED_ALGORITHM_IDS, } from './defaultConfig';
@@ -472,9 +472,8 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
472
472
  invalidateStrategies(): void;
473
473
  /**
474
474
  * Opens a Smart Recommender strategy page in a new tab and refreshes the list every time
475
- * the user comes back. `visibilitychange` only: a `focus` listener would also fire when
476
- * focus merely returns from the Stripo canvas iframe to the panel, refetching and
477
- * regenerating the canvas while the user never left the editor (SD-149916).
475
+ * the user comes back. `visibilitychange` covers the tab case; `focus` covers the page
476
+ * landing in a separate window, where this document never goes hidden.
478
477
  *
479
478
  * Deliberately NOT one-shot: the strategy tab stays open, so a user can create a second
480
479
  * strategy in it and come back again — a listener that disarmed on the first return would
@@ -68,6 +68,23 @@ const n = `.strategy-control-header {
68
68
  line-height: 24px;
69
69
  }
70
70
 
71
+ /*
72
+ * Mirrors the design system's InSkeleton 1:1 (gradient stops, 200% size, 1.6s linear).
73
+ * The Stripo panel lives in the editor's shadow root and is built from raw HTML strings,
74
+ * so the Vue component cannot be used there. Hex values are literal in the DS too.
75
+ */
76
+ .guido-skeleton {
77
+ display: none;
78
+ border-radius: 4px;
79
+ background: linear-gradient(90deg, #f0f0f0 39.5%, #e1e1e1 66.02%, #f0f0f0 89.42%);
80
+ background-size: 200% 100%;
81
+ animation: guido-skeleton-shine 1.6s linear infinite;
82
+ }
83
+
84
+ @keyframes guido-skeleton-shine {
85
+ to { background-position-x: -200%; }
86
+ }
87
+
71
88
  /* Each skeleton mirrors the footprint of the element it stands in for, so retiring
72
89
  the loading state does not shift the panel. */
73
90
  .guido-skeleton--strategy-title {