@useinsider/guido 3.18.2-beta.45f708c → 3.18.2-beta.545d1bd

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 (46) hide show
  1. package/dist/components/Guido.vue.js +1 -1
  2. package/dist/components/Guido.vue2.js +60 -54
  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/composables/useActionsApi.js +24 -20
  8. package/dist/composables/useCortexBlueprintBridge.js +115 -54
  9. package/dist/composables/useCustomInterfaceAppearance.js +46 -56
  10. package/dist/composables/useEmailTemplateApplier.js +93 -50
  11. package/dist/composables/useHtmlValidator.js +79 -84
  12. package/dist/composables/useRecommendation.js +35 -40
  13. package/dist/composables/useStripo.js +30 -30
  14. package/dist/enums/extensions/recommendationBlock.js +31 -38
  15. package/dist/extensions/Blocks/Recommendation/block.js +39 -43
  16. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +20 -21
  17. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +35 -40
  18. package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +52 -84
  19. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +74 -74
  20. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +90 -189
  21. package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +16 -26
  22. package/dist/extensions/Blocks/Recommendation/validation/requiredFields.js +12 -21
  23. package/dist/guido.css +1 -1
  24. package/dist/src/composables/useCortexBlueprintBridge.d.ts +4 -3
  25. package/dist/src/composables/useEmailTemplateApplier.d.ts +22 -2
  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 +0 -2
  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 -75
  33. package/dist/src/extensions/Blocks/Recommendation/validation/requiredFields.d.ts +0 -4
  34. package/dist/src/stores/guido-email-editor.d.ts +29 -7
  35. package/dist/src/stores/onboarding.d.ts +0 -377
  36. package/dist/static/styles/components/recommendation-strategy.css.js +4 -34
  37. package/dist/stores/guido-email-editor.js +5 -1
  38. package/dist/stores/onboarding.js +36 -41
  39. package/dist/utils/templatePreparation.js +55 -55
  40. package/package.json +1 -1
  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/static/styles/components/skeleton.css.js +0 -23
@@ -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";
3
- import { useConfigStore as P } from "../../../../stores/config.js";
4
- import { defineStore as L } from "pinia";
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
+ import { useConfigStore as F } from "../../../../stores/config.js";
4
+ import { defineStore as P } 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, g = null, h = 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,
@@ -65,7 +60,7 @@ function w() {
65
60
  syncedConfigFingerprint: null
66
61
  };
67
62
  }
68
- const $ = () => ({
63
+ const z = () => ({
69
64
  recommendationCampaignUrls: {},
70
65
  activePredictiveAlgorithms: [],
71
66
  languages: {},
@@ -74,14 +69,11 @@ const $ = () => ({
74
69
  strategies: [],
75
70
  strategiesLoading: !1,
76
71
  strategyUrlTemplates: {},
77
- strategiesFetched: !1,
78
- strategiesSettled: !1,
79
72
  blockStates: {},
80
73
  currentRecommendationId: null,
81
- strategyPanelOpen: !1,
82
74
  configVersion: 0
83
- }), it = L("guidoRecommendationExtension", {
84
- state: () => $(),
75
+ }), Y = P("guidoRecommendationExtension", {
76
+ state: () => z(),
85
77
  getters: {
86
78
  // ====================================================================
87
79
  // Proxy Getters — Backward Compatible Access to Current Block State
@@ -91,7 +83,7 @@ const $ = () => ({
91
83
  * This allows all existing code that reads `store.recommendationConfigs` to work unchanged.
92
84
  */
93
85
  recommendationConfigs(t) {
94
- return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : G();
86
+ return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : w();
95
87
  },
96
88
  /**
97
89
  * Proxy getter: delegates to blockStates[currentRecommendationId].recommendationProducts
@@ -146,8 +138,8 @@ const $ = () => ({
146
138
  return [...new Set(t.map((e) => e.filterGroup))].sort((e, r) => e - r);
147
139
  },
148
140
  getActivePredictiveAlgorithms: (t) => {
149
- const e = C(), r = [];
150
- return t.activePredictiveAlgorithms.filter((n) => !M.includes(n)).forEach((n) => {
141
+ const e = b(), r = [];
142
+ return t.activePredictiveAlgorithms.filter((n) => !L.includes(n)).forEach((n) => {
151
143
  r.push(...e.filter((s) => s.id === n));
152
144
  }), r.map((n) => ({
153
145
  text: n.name,
@@ -165,7 +157,7 @@ const $ = () => ({
165
157
  getFilterList() {
166
158
  return Object.values(this.filterList).filter((t) => t.isFilterable !== 0 && t.isFilterable !== !1).map((t) => {
167
159
  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, {
160
+ return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : v.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
169
161
  text: t.displayName,
170
162
  value: e,
171
163
  type: t.attributeType
@@ -187,7 +179,7 @@ const $ = () => ({
187
179
  setCurrentBlock(t) {
188
180
  this.blockStates[t] || (this.blockStates = {
189
181
  ...this.blockStates,
190
- [t]: w()
182
+ [t]: C()
191
183
  }), this.currentRecommendationId = t;
192
184
  },
193
185
  /**
@@ -247,7 +239,7 @@ const $ = () => ({
247
239
  * `isInitialized`) alone.
248
240
  */
249
241
  seedBlockUrlConfig(t, e) {
250
- const r = (o, a) => o === "." || o === "," || o === " " ? o : a, n = {
242
+ const r = (o, c) => o === "." || o === "," || o === " " ? o : c, n = {
251
243
  name: e.currencyCode,
252
244
  value: e.currencyCode,
253
245
  symbol: e.currencySymbol,
@@ -255,7 +247,7 @@ const $ = () => ({
255
247
  decimalCount: String(e.currencyDecimalCount),
256
248
  decimalSeparator: r(e.currencyDecimalSeparator, ","),
257
249
  thousandSeparator: r(e.currencyThousandSeparator, ".")
258
- }, s = !this.blockStates[t], i = s ? w() : this.blockStates[t];
250
+ }, s = !this.blockStates[t], i = s ? C() : this.blockStates[t];
259
251
  i.recommendationConfigs = {
260
252
  ...i.recommendationConfigs,
261
253
  strategy: e.strategy,
@@ -294,7 +286,7 @@ const $ = () => ({
294
286
  * Creates a filter with the first available attribute and operator pre-selected.
295
287
  */
296
288
  createDefaultFilter(t, e) {
297
- const [r] = this.getFilterList, [n] = N(r == null ? void 0 : r.type);
289
+ const [r] = this.getFilterList, [n] = G(r == null ? void 0 : r.type);
298
290
  return {
299
291
  type: "standardFilter",
300
292
  attribute: (r == null ? void 0 : r.value) ?? "",
@@ -354,97 +346,29 @@ const $ = () => ({
354
346
  this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].removeStrategyModalStatus = !1);
355
347
  },
356
348
  async fetchStrategies() {
357
- for (; R; )
358
- try {
359
- await R;
360
- } catch {
361
- }
362
- if (this.strategiesFetched)
349
+ if (S) {
350
+ await S;
363
351
  return;
364
- const t = b, e = (async () => {
352
+ }
353
+ S = (async () => {
365
354
  this.strategiesLoading = !0;
366
355
  try {
367
- const r = await f.fetchRecommendationStrategies();
368
- if (t !== b)
369
- return;
370
- this.strategies = r, this.strategiesFetched = !0;
356
+ this.strategies = await u.fetchRecommendationStrategies();
371
357
  } finally {
372
- this.strategiesLoading = !1, t === b && (this.strategiesSettled = !0);
358
+ this.strategiesLoading = !1;
373
359
  }
374
360
  })();
375
- R = e;
376
361
  try {
377
- await e;
362
+ await S;
378
363
  } finally {
379
- R = null;
364
+ S = null;
380
365
  }
381
366
  },
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
367
  async resolveStrategyUrlTemplate(t, e) {
444
368
  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
369
  if (s)
446
370
  return s;
447
- const { full_path: i = "" } = await f.generateStrategyEndpoint(t, e) ?? {};
371
+ const { full_path: i = "" } = await u.generateStrategyEndpoint(t, e) ?? {};
448
372
  return n && i && (this.strategyUrlTemplates = {
449
373
  ...this.strategyUrlTemplates,
450
374
  [n]: i
@@ -457,27 +381,23 @@ const $ = () => ({
457
381
  });
458
382
  },
459
383
  removeStrategy() {
460
- this.patchCurrentBlockConfig({
461
- strategyId: "",
462
- strategy: "",
463
- size: B.size
464
- });
384
+ this.patchCurrentBlockConfig({ strategyId: "", size: N.size });
465
385
  },
466
386
  // ====================================================================
467
387
  // Shared Data Fetching (fetched once, used by all blocks)
468
388
  // ====================================================================
469
389
  async fetchRecommendationCreateData() {
470
390
  if (!this.activePredictiveAlgorithms.length) {
471
- if (S) {
472
- await S;
391
+ if (f) {
392
+ await f;
473
393
  return;
474
394
  }
475
- S = (async () => {
395
+ f = (async () => {
476
396
  const {
477
397
  activePredictiveAlgorithms: t,
478
398
  languages: e,
479
399
  currencies: r
480
- } = await f.fetchRecommendationCreateData();
400
+ } = await u.fetchRecommendationCreateData();
481
401
  if (this.activePredictiveAlgorithms = t, this.languages = e, this.currentRecommendationId !== null && this.blockStates[this.currentRecommendationId]) {
482
402
  const n = this.blockStates[this.currentRecommendationId];
483
403
  n.filterStatus = !!n.recommendationConfigs.filters.length;
@@ -485,26 +405,26 @@ const $ = () => ({
485
405
  this.currencyList = r;
486
406
  })();
487
407
  try {
488
- await S;
408
+ await f;
489
409
  } finally {
490
- S = null;
410
+ f = null;
491
411
  }
492
412
  }
493
413
  },
494
414
  async fetchRecommendationFilters() {
495
415
  if (!Object.keys(this.filterList).length) {
496
- if (p) {
497
- await p;
416
+ if (g) {
417
+ await g;
498
418
  return;
499
419
  }
500
- p = (async () => {
501
- const t = await f.fetchRecommendationFilters();
420
+ g = (async () => {
421
+ const t = await u.fetchRecommendationFilters();
502
422
  this.filterList = t;
503
423
  })();
504
424
  try {
505
- await p;
425
+ await g;
506
426
  } finally {
507
- p = null;
427
+ g = null;
508
428
  }
509
429
  }
510
430
  },
@@ -533,7 +453,7 @@ const $ = () => ({
533
453
  const n = [...e.recommendationConfigs.filters];
534
454
  n[r] = {
535
455
  ...t,
536
- isValid: z(t)
456
+ isValid: B(t)
537
457
  }, e.recommendationConfigs.filters = n;
538
458
  }
539
459
  },
@@ -547,10 +467,10 @@ const $ = () => ({
547
467
  let i = 1;
548
468
  n = n.map((o) => o.filterGroup === t.filterGroup ? { ...o, filterNumber: i++ } : o);
549
469
  } 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
470
+ const i = [...new Set(n.map((c) => c.filterGroup))].sort((c, a) => c - a), o = new Map(i.map((c, a) => [c, a + 1]));
471
+ n = n.map((c) => ({
472
+ ...c,
473
+ filterGroup: o.get(c.filterGroup) ?? c.filterGroup
554
474
  }));
555
475
  }
556
476
  e.recommendationConfigs.filters = n;
@@ -571,7 +491,7 @@ const $ = () => ({
571
491
  }), e.recommendationConfigs.filters = r;
572
492
  },
573
493
  generateFilterQuery() {
574
- return F(this.recommendationConfigs.filters);
494
+ return k(this.recommendationConfigs.filters);
575
495
  },
576
496
  /**
577
497
  * Validation-only check invoked at save-CTA time. Defined as an action
@@ -579,52 +499,33 @@ const $ = () => ({
579
499
  * every block's recommendationConfigs across user edits.
580
500
  */
581
501
  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));
502
+ return Object.values(this.blockStates).some((t) => !M(t.recommendationConfigs, this));
590
503
  },
591
504
  // ====================================================================
592
505
  // Per-Block Product Fetching
593
506
  // ====================================================================
594
507
  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 = "");
508
+ if (!(this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])) {
509
+ if (h) {
510
+ await h;
511
+ return;
512
+ }
513
+ h = this._doFetchProducts();
514
+ try {
515
+ await h;
516
+ } finally {
517
+ h = null;
518
+ }
611
519
  }
612
520
  },
613
521
  async _doFetchProducts() {
614
- var g;
615
- const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = P();
522
+ var d;
523
+ const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = F();
616
524
  if (r.strategyId && n.isFeatureEnabled("reusableRecommendationStrategy")) {
617
525
  await this._doFetchStrategyProducts(t);
618
526
  return;
619
527
  }
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 = {
528
+ 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
529
  locale: r.language,
629
530
  currency: r.currencySettings.value,
630
531
  partnerName: n.partnerName,
@@ -632,21 +533,21 @@ const $ = () => ({
632
533
  details: !0,
633
534
  campaignId: n.variationId
634
535
  };
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)
536
+ 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(
537
+ a,
538
+ x(n.partnerName, r.strategy)
638
539
  );
639
- let m;
540
+ let l;
640
541
  try {
641
- m = await f.fetchRecommendationProducts(u, c);
542
+ l = await u.fetchRecommendationProducts(o, a);
642
543
  } catch {
643
- m = [];
544
+ l = [];
644
545
  }
645
- h.get(t) === s && this._setBlockProducts(t, m, i);
546
+ this._setBlockProducts(t, l, c);
646
547
  },
647
548
  async _doFetchStrategyProducts(t) {
648
- const e = (h.get(t) ?? 0) + 1;
649
- h.set(t, e);
549
+ const e = (p.get(t) ?? 0) + 1;
550
+ p.set(t, e);
650
551
  const { recommendationConfigs: r } = this.blockStates[t];
651
552
  let n = [], s = parseInt(r.size) || 6;
652
553
  try {
@@ -656,25 +557,25 @@ const $ = () => ({
656
557
  );
657
558
  if (i) {
658
559
  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));
560
+ 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;
561
+ y && (n = await u.fetchRecommendationProductsByUrl(y));
661
562
  }
662
563
  } catch {
663
564
  n = [];
664
565
  }
665
- h.get(t) === e && this._setBlockProducts(t, n, s);
566
+ p.get(t) === e && this._setBlockProducts(t, n, s);
666
567
  },
667
568
  _setBlockProducts(t, e, r) {
668
569
  if (!this.blockStates[t])
669
570
  return;
670
- const n = e.length > 0 ? e : v(r);
571
+ const n = e.length > 0 ? e : R(r);
671
572
  this.blockStates[t].recommendationProducts = [
672
573
  ...n.slice(0, r),
673
- ...v(Math.max(0, r - n.length))
574
+ ...R(Math.max(0, r - n.length))
674
575
  ];
675
576
  }
676
577
  }
677
578
  });
678
579
  export {
679
- it as useRecommendationExtensionStore
580
+ Y as useRecommendationExtensionStore
680
581
  };
@@ -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-7674b645]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-7674b645]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-7674b645]{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}
@@ -17,12 +17,13 @@
17
17
  * - `error` segments (and message-level `isError` / `isCancelled`) trigger
18
18
  * a localized toaster.
19
19
  *
20
+ * Every apply settles into a terminal `applyAcks` entry on the public store, so
21
+ * cortex can move its Apply button on the truth of the editor write rather than
22
+ * on the click.
23
+ *
20
24
  * In dev (`import.meta.env.DEV`) every observed segment + message-level flag
21
25
  * change is also `console.debug`-logged with the prefix `[guido:cortex]` so a
22
26
  * developer can watch the agent stream in real time. In production this is
23
27
  * gated behind `localStorage.guido:debug:ai === '1'`.
24
- *
25
- * If cortex-fe isn't loaded the chat store is undefined and the bridge is a
26
- * no-op (intentional — Guido must still work standalone).
27
28
  */
28
29
  export declare const useCortexBlueprintBridge: () => void;