@useinsider/guido 3.19.0-beta.f02eaa1 → 3.19.0-beta.f66e9de

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 (56) hide show
  1. package/dist/components/Guido.vue.js +8 -8
  2. package/dist/components/Guido.vue2.js +44 -43
  3. package/dist/components/organisms/base/AuthErrorModal.vue.js +18 -0
  4. package/dist/components/organisms/base/AuthErrorModal.vue2.js +42 -0
  5. package/dist/components/organisms/base/Toaster.vue2.js +13 -12
  6. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +9 -7
  7. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +69 -52
  8. package/dist/components/organisms/extensions/recommendation/RemoveStrategyModal.vue2.js +28 -44
  9. package/dist/components/organisms/header/EditorActions.vue.js +4 -4
  10. package/dist/components/organisms/header/EditorActions.vue2.js +23 -25
  11. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.js +3 -3
  12. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue2.js +21 -20
  13. package/dist/composables/useActionsApi.js +52 -47
  14. package/dist/composables/useAuthError.js +54 -0
  15. package/dist/composables/useCodeEditorApi.js +23 -9
  16. package/dist/composables/useCustomInterfaceAppearance.js +61 -51
  17. package/dist/composables/useHtmlValidator.js +87 -82
  18. package/dist/composables/useHttp.js +54 -44
  19. package/dist/composables/useRecommendation.js +40 -35
  20. package/dist/composables/useStripo.js +30 -30
  21. package/dist/composables/useToaster.js +14 -20
  22. package/dist/composables/useTranslations.js +3 -2
  23. package/dist/composables/useVersionHistoryApi.js +33 -24
  24. package/dist/enums/extensions/recommendationBlock.js +32 -25
  25. package/dist/extensions/Blocks/Recommendation/block.js +61 -42
  26. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +21 -20
  27. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +63 -58
  28. package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +109 -78
  29. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +96 -97
  30. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +209 -92
  31. package/dist/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.js +1 -1
  32. package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +26 -16
  33. package/dist/extensions/Blocks/Recommendation/utils/strategyCommit.js +24 -0
  34. package/dist/extensions/Blocks/Recommendation/validation/requiredFields.js +21 -12
  35. package/dist/guido.css +1 -1
  36. package/dist/src/components/organisms/base/AuthErrorModal.vue.d.ts +2 -0
  37. package/dist/src/components/wrappers/WpModal.vue.d.ts +1 -1
  38. package/dist/src/composables/useAuthError.d.ts +13 -0
  39. package/dist/src/enums/extensions/recommendationBlock.d.ts +2 -0
  40. package/dist/src/extensions/Blocks/Recommendation/block.d.ts +10 -0
  41. package/dist/src/extensions/Blocks/Recommendation/constants/defaultConfig.d.ts +1 -0
  42. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +1 -1
  43. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +2 -0
  44. package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +8 -0
  45. package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +7 -6
  46. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +92 -0
  47. package/dist/src/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.d.ts +1 -1
  48. package/dist/src/extensions/Blocks/Recommendation/utils/strategyCommit.d.ts +14 -0
  49. package/dist/src/extensions/Blocks/Recommendation/validation/requiredFields.d.ts +4 -0
  50. package/dist/src/utils/stripoEditorApi.d.ts +4 -0
  51. package/dist/static/styles/components/recommendation-strategy.css.js +34 -4
  52. package/dist/static/styles/components/skeleton.css.js +23 -0
  53. package/dist/stores/unsubscribe.js +3 -3
  54. package/dist/utils/stripoEditorApi.js +11 -0
  55. package/dist/utils/templatePreparation.js +55 -55
  56. package/package.json +2 -1
@@ -1,13 +1,13 @@
1
- import { DEFAULT_COLUMN_SPACING as R, DEFAULT_ROW_SPACING as s, DEFAULT_MOBILE_ROW_SPACING as n, DEFAULT_MOBILE_COLUMN_SPACING as O, DEFAULT_MOBILE_CARDS_IN_ROW as e, DEFAULT_CARDS_IN_ROW as C } from "./layout.js";
2
- import { ATTR_PRODUCT_IMAGE as o, ATTR_PRODUCT_NAME as t, ATTR_PRODUCT_OLD_PRICE as _, ATTR_PRODUCT_PRICE as T, ATTR_PRODUCT_OMNIBUS_PRICE as r, ATTR_PRODUCT_OMNIBUS_DISCOUNT as I, ATTR_PRODUCT_BUTTON as i, ATTR_RECOMMENDATION_TITLE as U } from "./selectors.js";
3
- const A = 1, u = 2, D = {
1
+ import { DEFAULT_COLUMN_SPACING as i, DEFAULT_ROW_SPACING as s, DEFAULT_MOBILE_ROW_SPACING as n, DEFAULT_MOBILE_COLUMN_SPACING as O, DEFAULT_MOBILE_CARDS_IN_ROW as e, DEFAULT_CARDS_IN_ROW as C } from "./layout.js";
2
+ import { ATTR_PRODUCT_IMAGE as o, ATTR_PRODUCT_NAME as t, ATTR_PRODUCT_OLD_PRICE as _, ATTR_PRODUCT_PRICE as T, ATTR_PRODUCT_OMNIBUS_PRICE as I, ATTR_PRODUCT_OMNIBUS_DISCOUNT as R, ATTR_PRODUCT_BUTTON as r, ATTR_RECOMMENDATION_TITLE as E } from "./selectors.js";
3
+ const U = 1, u = 2, m = 2, A = {
4
4
  code: "USD",
5
5
  symbol: "USD",
6
6
  alignment: "after",
7
7
  decimalCount: 2,
8
8
  decimalSeparator: ".",
9
9
  thousandSeparator: ","
10
- }, E = {
10
+ }, D = {
11
11
  textBefore: "",
12
12
  textAfter: ""
13
13
  }, a = {
@@ -18,26 +18,26 @@ const A = 1, u = 2, D = {
18
18
  t,
19
19
  _,
20
20
  T,
21
- r,
22
21
  I,
23
- i
22
+ R,
23
+ r
24
24
  ], N = {
25
- [U]: !0,
25
+ [E]: !0,
26
26
  [o]: !0,
27
27
  [t]: !0,
28
28
  [T]: !0,
29
29
  [_]: !0,
30
- [r]: !1,
31
30
  [I]: !1,
32
- [i]: !0
33
- }, m = {
31
+ [R]: !1,
32
+ [r]: !0
33
+ }, L = {
34
34
  // Settings
35
35
  strategy: "mostPopular",
36
36
  productIds: [],
37
37
  size: "6",
38
38
  shuffleProducts: !1,
39
39
  language: "en_US",
40
- currency: D,
40
+ currency: A,
41
41
  filters: [],
42
42
  strategyId: "",
43
43
  // Layout
@@ -46,7 +46,7 @@ const A = 1, u = 2, D = {
46
46
  mobileCardsInRow: e,
47
47
  mobileLayoutEnabled: !1,
48
48
  previousMobileCardsInRow: e,
49
- columnSpacing: R,
49
+ columnSpacing: i,
50
50
  rowSpacing: s,
51
51
  mobileColumnSpacing: O,
52
52
  mobileRowSpacing: n,
@@ -55,7 +55,7 @@ const A = 1, u = 2, D = {
55
55
  visibility: N,
56
56
  previousTitleHtml: "",
57
57
  // Element settings
58
- omnibusPrice: E,
58
+ omnibusPrice: D,
59
59
  omnibusDiscount: a,
60
60
  textTrimming: !1,
61
61
  // Price placement (block-level, affects all cards)
@@ -66,17 +66,18 @@ const A = 1, u = 2, D = {
66
66
  // of "false" (the actual hiding happens server-side at send).
67
67
  priceHideIfSameAsDiscounted: !1,
68
68
  // Meta
69
- configVersion: A,
69
+ configVersion: U,
70
70
  recommendationId: 0
71
- }, L = [11, 12];
71
+ }, P = [11, 12];
72
72
  export {
73
73
  u as CURRENT_CONFIG_VERSION,
74
74
  c as DEFAULT_COMPOSITION,
75
- D as DEFAULT_CURRENCY,
76
- m as DEFAULT_NODE_CONFIG,
75
+ A as DEFAULT_CURRENCY,
76
+ L as DEFAULT_NODE_CONFIG,
77
77
  a as DEFAULT_OMNIBUS_DISCOUNT,
78
- E as DEFAULT_OMNIBUS_PRICE,
78
+ D as DEFAULT_OMNIBUS_PRICE,
79
79
  N as DEFAULT_VISIBILITY,
80
- L as EXCLUDED_ALGORITHM_IDS,
81
- A as PRE_RRS_CONFIG_VERSION
80
+ P as EXCLUDED_ALGORITHM_IDS,
81
+ U as PRE_RRS_CONFIG_VERSION,
82
+ m as RRS_CONFIG_VERSION
82
83
  };
@@ -1,20 +1,20 @@
1
1
  var m = Object.defineProperty;
2
- var C = (g, l, t) => l in g ? m(g, l, { enumerable: !0, configurable: !0, writable: !0, value: t }) : g[l] = t;
3
- var r = (g, l, t) => C(g, typeof l != "symbol" ? l + "" : l, t);
2
+ var C = (g, c, t) => c in g ? m(g, c, { enumerable: !0, configurable: !0, writable: !0, value: t }) : g[c] = t;
3
+ var i = (g, c, t) => C(g, typeof c != "symbol" ? c + "" : c, t);
4
4
  import { useConfig as p } from "../../../../../composables/useConfig.js";
5
5
  import { ModificationDescription as y } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
6
6
  import { CommonControl as N } from "../../../common-control.js";
7
- import { CURRENT_CONFIG_VERSION as _, DEFAULT_NODE_CONFIG as a } from "../../constants/defaultConfig.js";
7
+ import { RRS_CONFIG_VERSION as _, DEFAULT_NODE_CONFIG as a } from "../../constants/defaultConfig.js";
8
8
  import { RECOMMENDATION_ID_ATTR as I } from "../../constants/selectors.js";
9
- import { RecommendationConfigService as c } from "../../services/configService.js";
9
+ import { RecommendationConfigService as l } from "../../services/configService.js";
10
10
  import { useRecommendationExtensionStore as R } from "../../store/recommendation.js";
11
11
  import { registerNodeConfigWriter as b } from "../../utils/nodeConfigWriter.js";
12
12
  import { AlgorithmControl as T } from "./algorithm.js";
13
- import { ALGORITHM_CONTROL_ID as ut } from "./algorithm.js";
13
+ import { ALGORITHM_CONTROL_ID as dt } from "./algorithm.js";
14
14
  import { CurrencyControl as P } from "./currency.js";
15
15
  import { CURRENCY_CONTROL_ID as gt } from "./currency.js";
16
16
  import { FiltersControl as S } from "./filters.js";
17
- import { FILTERS_CONTROL_ID as ht } from "./filters.js";
17
+ import { FILTERS_CONTROL_ID as ft } from "./filters.js";
18
18
  import { LayoutOrientationControl as O } from "./layoutOrientation.js";
19
19
  import { LAYOUT_ORIENTATION_CONTROL_ID as Ct } from "./layoutOrientation.js";
20
20
  import { LocaleControl as L } from "./locale.js";
@@ -31,34 +31,34 @@ import { StrategyControl as w } from "./strategy.js";
31
31
  import { STRATEGY_CONTROL_ID as Lt } from "./strategy.js";
32
32
  import { setCurrencyAttributes as A, getBlockElement as B, isPartnerManagedBlock as v, updateProductContentInPlace as x, regenerateProductRowsWithStyles as U } from "./utils.js";
33
33
  import { adjustProductsToSize as Et, formatProductPrice as Ft, getCardComposition as Dt, getCurrentLayout as wt, getMainContainerTbody as At, regenerateMobileProductRows as Bt, updatePricesInPlace as vt, updateSingleProductContent as xt } from "./utils.js";
34
- import { useDebounceFn as f } from "../../../../../node_modules/@vueuse/shared/index.js";
35
- const $ = "ui-elements-recommendation-block";
34
+ import { useDebounceFn as h } from "../../../../../node_modules/@vueuse/shared/index.js";
35
+ const W = "ui-elements-recommendation-block";
36
36
  class at extends N {
37
37
  constructor() {
38
38
  super(...arguments);
39
- r(this, "store", R());
40
- r(this, "storeUnsubscription", () => {
39
+ i(this, "store", R());
40
+ i(this, "storeUnsubscription", () => {
41
41
  });
42
42
  // A config change waiting to reach the node config. Deferred so it can ride the
43
43
  // re-render's single apply() — one user action must cost one undo press.
44
- r(this, "pendingNodeConfigWrite", null);
45
- r(this, "pendingConfigFlushTimer", null);
44
+ i(this, "pendingNodeConfigWrite", null);
45
+ i(this, "pendingConfigFlushTimer", null);
46
46
  // Sub-control instances for lifecycle management
47
- r(this, "algorithmControl", null);
48
- r(this, "localeControl", null);
49
- r(this, "currencyControl", null);
50
- r(this, "productCountControl", null);
51
- r(this, "productLayoutControl", null);
52
- r(this, "filtersControl", null);
53
- r(this, "shuffleControl", null);
54
- r(this, "pricePlacementControl", null);
55
- r(this, "layoutOrientationControl", null);
56
- r(this, "strategyControl", null);
57
- r(this, "rrsEnabled", !1);
47
+ i(this, "algorithmControl", null);
48
+ i(this, "localeControl", null);
49
+ i(this, "currencyControl", null);
50
+ i(this, "productCountControl", null);
51
+ i(this, "productLayoutControl", null);
52
+ i(this, "filtersControl", null);
53
+ i(this, "shuffleControl", null);
54
+ i(this, "pricePlacementControl", null);
55
+ i(this, "layoutOrientationControl", null);
56
+ i(this, "strategyControl", null);
57
+ i(this, "rrsEnabled", !1);
58
58
  /**
59
59
  * Debounced product fetch to prevent rapid API calls during config changes
60
60
  */
61
- r(this, "_debouncedFetchProducts", f(async () => {
61
+ i(this, "_debouncedFetchProducts", h(async () => {
62
62
  try {
63
63
  await this.store.fetchRecommendationProducts();
64
64
  } finally {
@@ -76,7 +76,7 @@ class at extends N {
76
76
  * count. The store pads products to the configured size, so in-place only
77
77
  * fails when the size actually changed.
78
78
  */
79
- r(this, "_debouncedRegenerateWithProducts", f(() => {
79
+ i(this, "_debouncedRegenerateWithProducts", h(() => {
80
80
  const t = this.store.recommendationProducts;
81
81
  if (!this.currentNode || !this.api)
82
82
  return;
@@ -97,7 +97,7 @@ class at extends N {
97
97
  }, 100));
98
98
  }
99
99
  getId() {
100
- return $;
100
+ return W;
101
101
  }
102
102
  get _subControls() {
103
103
  return [
@@ -136,18 +136,18 @@ class at extends N {
136
136
  `;
137
137
  }
138
138
  _showControlsForBlock(t) {
139
- var i;
140
- const e = (i = this.getContainer()) == null ? void 0 : i.querySelector(".recommendation-controls-container");
139
+ var r;
140
+ const e = (r = this.getContainer()) == null ? void 0 : r.querySelector(".recommendation-controls-container");
141
141
  if (!e)
142
142
  return;
143
- const o = this._getRecommendationIdFromNode(t) === null ? null : c.getConfig(t), n = this.rrsEnabled && !!o && (!!(o != null && o.strategyId) || ((o == null ? void 0 : o.configVersion) ?? 0) >= _), s = this.rrsEnabled && !!o && !n;
143
+ const o = this._getRecommendationIdFromNode(t) === null ? null : l.getConfig(t), n = this.rrsEnabled && !!o && (!!(o != null && o.strategyId) || ((o == null ? void 0 : o.configVersion) ?? 0) >= _), s = this.rrsEnabled && !!o && !n;
144
144
  e.classList.toggle("strategy-block", n), e.classList.toggle("legacy-strategy-block", s);
145
145
  }
146
146
  async onRender() {
147
147
  var o;
148
148
  b(this.api);
149
149
  const t = this._getRecommendationIdFromNode(this.currentNode), e = t ?? this.store.currentRecommendationId;
150
- if (e !== null && this.store.setCurrentBlock(e), t !== null && this._syncNodeConfigIfChanged(t), this._listenStateUpdates(), this._showControlsForBlock(this.currentNode), e !== null && ((o = this.store.blockStates[e]) != null && o.isInitialized)) {
150
+ if (e !== null && this.store.setCurrentBlock(e), t !== null && this._syncNodeConfigIfChanged(t), this._listenStateUpdates(), this._showControlsForBlock(this.currentNode), t !== null && this.strategyControl && (this.strategyControl.api = this.api, this.strategyControl.currentNode = this.currentNode, this.strategyControl.onRender()), e !== null && ((o = this.store.blockStates[e]) != null && o.isInitialized)) {
151
151
  this._initializeSubControls();
152
152
  return;
153
153
  }
@@ -209,18 +209,23 @@ class at extends N {
209
209
  const e = this.store.blockStates[t];
210
210
  if (!e)
211
211
  return;
212
- const o = JSON.stringify(c.getConfig(this.currentNode)), n = e.syncedConfigFingerprint;
212
+ const o = JSON.stringify(l.getConfig(this.currentNode)), n = e.syncedConfigFingerprint;
213
213
  e.syncedConfigFingerprint = o, n !== o && (this.pendingNodeConfigWrite || this._syncNodeConfigToStore());
214
214
  }
215
+ /** Whether the deferred write would move the node's strategyId — see the caller (SD-149916). */
216
+ _isPendingStrategyIdChange() {
217
+ const t = this.pendingNodeConfigWrite;
218
+ return t ? l.getConfig(this.currentNode).strategyId !== t.updates.strategyId : !1;
219
+ }
215
220
  _capturePendingNodeConfigWrite() {
216
221
  const t = this.store.currentRecommendationId;
217
222
  if (!this.currentNode || !this.api || t === null)
218
223
  return;
219
- const { filters: e, strategyId: o, size: n, nodeConfigVersion: s } = this.store.recommendationConfigs;
224
+ const { filters: e, strategy: o, strategyId: n, size: s, nodeConfigVersion: r } = this.store.recommendationConfigs;
220
225
  this.pendingNodeConfigWrite = {
221
226
  blockId: t,
222
227
  node: this.currentNode,
223
- updates: { filters: e, strategyId: o, size: n, configVersion: s }
228
+ updates: { filters: e, strategy: o, strategyId: n, size: s, configVersion: r }
224
229
  };
225
230
  }
226
231
  /**
@@ -235,7 +240,7 @@ class at extends N {
235
240
  */
236
241
  _stagePendingNodeConfig(t) {
237
242
  const e = this.pendingNodeConfigWrite;
238
- return !e || !this.currentNode ? !1 : (c.stageConfig(t, this.currentNode, e.updates), !0);
243
+ return !e || !this.currentNode ? !1 : (l.stageConfig(t, this.currentNode, e.updates), !0);
239
244
  }
240
245
  /**
241
246
  * Arms the guaranteed fallback write, once the product fetch has settled. The
@@ -259,12 +264,12 @@ class at extends N {
259
264
  const t = this.pendingNodeConfigWrite;
260
265
  if (this.pendingNodeConfigWrite = null, this._clearConfigFlush(), !t || !this.api)
261
266
  return;
262
- const e = t.blockId === this.store.currentRecommendationId && this.currentNode ? this.currentNode : t.node, o = c.getConfig(e);
263
- JSON.stringify(o.filters) === JSON.stringify(t.updates.filters) && o.strategyId === t.updates.strategyId && o.size === t.updates.size || c.updateConfig(this.api, e, t.updates, "Update recommendation filters");
267
+ const e = t.blockId === this.store.currentRecommendationId && this.currentNode ? this.currentNode : t.node, o = l.getConfig(e);
268
+ JSON.stringify(o.filters) === JSON.stringify(t.updates.filters) && o.strategy === t.updates.strategy && o.strategyId === t.updates.strategyId && o.size === t.updates.size || l.updateConfig(this.api, e, t.updates, "Update recommendation filters");
264
269
  }
265
270
  _syncNodeConfigToStore() {
266
271
  var n;
267
- const t = c.getConfig(this.currentNode), e = this.store.currentRecommendationId, o = e !== null && ((n = this.store.blockStates[e]) == null ? void 0 : n.isInitialized);
272
+ const t = l.getConfig(this.currentNode), e = this.store.currentRecommendationId, o = e !== null && ((n = this.store.blockStates[e]) == null ? void 0 : n.isInitialized);
268
273
  this.store.patchCurrentBlockConfig({
269
274
  strategy: t.strategy,
270
275
  strategyId: t.strategyId,
@@ -329,31 +334,31 @@ class at extends N {
329
334
  _applySmartDefaults() {
330
335
  if (!this.currentNode || !this.api)
331
336
  return;
332
- const t = c.getConfig(this.currentNode), e = {};
337
+ const t = l.getConfig(this.currentNode), e = {};
333
338
  let o = null, n = null, s = null;
334
339
  if (t.currency.code === a.currency.code) {
335
- const { currencyList: i } = this.store;
336
- i.length > 0 && (i.some(
337
- (d) => d.value === `price.${a.currency.code}`
338
- ) || (o = i[0].value.replace("price.", ""), e.currency = {
340
+ const { currencyList: r } = this.store;
341
+ r.length > 0 && (r.some(
342
+ (u) => u.value === `price.${a.currency.code}`
343
+ ) || (o = r[0].value.replace("price.", ""), e.currency = {
339
344
  ...a.currency,
340
345
  code: o,
341
346
  symbol: o
342
347
  }));
343
348
  }
344
349
  if (t.strategy === a.strategy) {
345
- const i = this.store.getActivePredictiveAlgorithms;
346
- i.length > 0 && (i.some(
347
- (d) => d.value === a.strategy
348
- ) || (n = i[0].value, e.strategy = n));
350
+ const r = this.store.getActivePredictiveAlgorithms;
351
+ r.length > 0 && (r.some(
352
+ (u) => u.value === a.strategy
353
+ ) || (n = r[0].value, e.strategy = n));
349
354
  }
350
355
  if (t.language === a.language) {
351
- const i = this.store.getLanguages;
352
- i.length > 0 && (i.some(
353
- (d) => d.value === a.language
354
- ) || (s = i[0].value, e.language = s));
356
+ const r = this.store.getLanguages;
357
+ r.length > 0 && (r.some(
358
+ (u) => u.value === a.language
359
+ ) || (s = r[0].value, e.language = s));
355
360
  }
356
- !o && !n && !s || (c.updateConfig(
361
+ !o && !n && !s || (l.updateConfig(
357
362
  this.api,
358
363
  this.currentNode,
359
364
  e,
@@ -413,20 +418,20 @@ class at extends N {
413
418
  n = s, e = t.recommendationProducts, o = t.$state.configVersion;
414
419
  return;
415
420
  }
416
- const i = t.$state.configVersion;
417
- i !== o && (o = i, this._capturePendingNodeConfigWrite(), this._debouncedFetchProducts());
418
- const u = t.recommendationProducts, d = u !== e, h = Array.isArray(u) && u.length > 0;
419
- d && h && (e = u, this._debouncedRegenerateWithProducts());
421
+ const r = t.$state.configVersion;
422
+ r !== o && (o = r, this._capturePendingNodeConfigWrite(), this._isPendingStrategyIdChange() && this._flushPendingNodeConfig(), this._debouncedFetchProducts());
423
+ const d = t.recommendationProducts, u = d !== e, f = Array.isArray(d) && d.length > 0;
424
+ u && f && (e = d, this._debouncedRegenerateWithProducts());
420
425
  });
421
426
  }
422
427
  }
423
428
  export {
424
- ut as ALGORITHM_CONTROL_ID,
429
+ dt as ALGORITHM_CONTROL_ID,
425
430
  T as AlgorithmControl,
426
- $ as CONTROL_BLOCK_ID,
431
+ W as CONTROL_BLOCK_ID,
427
432
  gt as CURRENCY_CONTROL_ID,
428
433
  P as CurrencyControl,
429
- ht as FILTERS_CONTROL_ID,
434
+ ft as FILTERS_CONTROL_ID,
430
435
  S as FiltersControl,
431
436
  Ct as LAYOUT_ORIENTATION_CONTROL_ID,
432
437
  yt as LOCALE_CONTROL_ID,
@@ -1,49 +1,64 @@
1
- var p = Object.defineProperty;
2
- var v = (i, s, t) => s in i ? p(i, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : i[s] = t;
3
- var r = (i, s, t) => v(i, typeof s != "symbol" ? s + "" : s, t);
4
- import { useLegacyStrategyConversion as _ } from "../../../../../composables/useLegacyStrategyConversion.js";
5
- import { ACADEMY_LINKS as b } from "../../../../../enums/academy.js";
6
- import { useOnboardingStore as S } from "../../../../../stores/onboarding.js";
7
- import { CommonControl as f } from "../../../common-control.js";
8
- import { useRecommendationExtensionStore as $ } from "../../store/recommendation.js";
9
- const C = "recommendation-strategy-control";
10
- class N extends f {
1
+ var C = Object.defineProperty;
2
+ var $ = (c, n, t) => n in c ? C(c, n, { enumerable: !0, configurable: !0, writable: !0, value: t }) : c[n] = t;
3
+ var i = (c, n, t) => $(c, typeof n != "symbol" ? n + "" : n, t);
4
+ import { useLegacyStrategyConversion as k } from "../../../../../composables/useLegacyStrategyConversion.js";
5
+ import { ACADEMY_LINKS as L } from "../../../../../enums/academy.js";
6
+ import { useOnboardingStore as w } from "../../../../../stores/onboarding.js";
7
+ import { CommonControl as A } from "../../../common-control.js";
8
+ import { RRS_CONFIG_VERSION as N } from "../../constants/defaultConfig.js";
9
+ import { RecommendationConfigService as b } from "../../services/configService.js";
10
+ import { useRecommendationExtensionStore as R } from "../../store/recommendation.js";
11
+ const E = "recommendation-strategy-control";
12
+ class M extends A {
11
13
  constructor() {
12
14
  super(...arguments);
13
- r(this, "store", $());
14
- r(this, "onboardingStore", S());
15
- r(this, "legacyConversion", _());
16
- r(this, "storeUnsubscription", () => {
15
+ i(this, "store", R());
16
+ i(this, "onboardingStore", w());
17
+ i(this, "legacyConversion", k());
18
+ i(this, "storeUnsubscription", () => {
17
19
  });
18
- r(this, "listeners", []);
19
- r(this, "lastPaintedState", null);
20
+ i(this, "listeners", []);
21
+ i(this, "lastPaintedState", null);
20
22
  }
21
23
  getId() {
22
- return C;
24
+ return E;
23
25
  }
24
26
  getTemplate() {
25
27
  const t = this.api.translate(
26
28
  "You can assign a recommendation strategy by selecting an existing one or creating a new one to show specific content."
27
- ), e = this.api.translate("For more information, you can"), a = this.api.translate("visit Academy"), o = this.api.translate("Legacy Strategy"), n = this.api.translate(
29
+ ), e = this.api.translate("For more information, you can"), s = this.api.translate("visit Academy"), o = this.api.translate("Legacy Strategy"), a = this.api.translate(
28
30
  "Note that this is an older version of the Recommendation Strategy. We recommend you update it to the new Recommendation Strategy for an improved experience."
29
31
  );
30
32
  return `
31
33
  <div class="strategy-control-container">
32
- <div class="strategy-control-header">
33
- <h3 class="strategy-control-title">${this.api.translate("Recommendation Strategy")}</h3>
34
- </div>
35
- <div class="strategy-control-description-row">
36
- <p class="strategy-control-description">
37
- ${t}
38
- ${e}
39
- <a
40
- href="${b.EMAIL_RECOMMENDATION_BLOCK}"
41
- target="_blank"
42
- rel="noopener noreferrer">${a}</a>.
43
- </p>
34
+ <div data-strategy-loading-state>
35
+ <div class="strategy-control-header">
36
+ <span class="guido-skeleton guido-skeleton--strategy-title"></span>
37
+ </div>
38
+ <div class="strategy-control-description-row">
39
+ <span class="guido-skeleton guido-skeleton--strategy-description"></span>
40
+ </div>
41
+ <div class="strategy-control-skeleton-row">
42
+ <span class="guido-skeleton guido-skeleton--strategy-cta"></span>
43
+ <span class="guido-skeleton guido-skeleton--strategy-cta"></span>
44
+ </div>
44
45
  </div>
45
- <div data-strategy-empty-state>
46
- ${this._GuTwoColumns([
46
+ <div data-strategy-content style="display: none;">
47
+ <div class="strategy-control-header">
48
+ <h3 class="strategy-control-title">${this.api.translate("Recommendation Strategy")}</h3>
49
+ </div>
50
+ <div class="strategy-control-description-row">
51
+ <p class="strategy-control-description">
52
+ ${t}
53
+ ${e}
54
+ <a
55
+ href="${L.EMAIL_RECOMMENDATION_BLOCK}"
56
+ target="_blank"
57
+ rel="noopener noreferrer">${s}</a>.
58
+ </p>
59
+ </div>
60
+ <div data-strategy-empty-state style="display: none;">
61
+ ${this._GuTwoColumns([
47
62
  this._GuButton({
48
63
  name: "assignStrategy",
49
64
  label: this.api.translate("Assign Strategy"),
@@ -54,115 +69,131 @@ class N extends f {
54
69
  name: "createStrategy",
55
70
  label: this.api.translate("Create New Strategy"),
56
71
  id: "guido__btn-create-strategy",
57
- className: "strategy-control-cta primary",
58
- disabled: !0
72
+ className: "strategy-control-cta primary"
59
73
  })
60
74
  ], "strategy-control-cta-row")}
61
- </div>
62
- <div data-strategy-legacy-state style="display: none;">
63
- <div class="strategy-control-notice-row">
64
- <div class="strategy-control-notice">
65
- <p class="strategy-control-notice-text">${n}</p>
66
- </div>
67
75
  </div>
68
- <div class="strategy-control-name-band">
69
- <span class="strategy-control-name">${o}</span>
70
- ${this._strategyAction({
76
+ <div data-strategy-legacy-state style="display: none;">
77
+ <div class="strategy-control-notice-row">
78
+ <div class="strategy-control-notice">
79
+ <p class="strategy-control-notice-text">${a}</p>
80
+ </div>
81
+ </div>
82
+ <div class="strategy-control-name-band">
83
+ <span class="strategy-control-name">${o}</span>
84
+ ${this._strategyAction({
71
85
  id: "guido__btn-update-legacy-strategy",
72
86
  label: this.api.translate("Update"),
73
87
  modifier: "update"
74
88
  })}
75
- </div>
76
- <div class="strategy-control-actions">
77
- ${this._strategyAction({
89
+ </div>
90
+ <div class="strategy-control-actions">
91
+ ${this._strategyAction({
78
92
  id: "guido__btn-change-legacy-strategy",
79
93
  label: this.api.translate("Change"),
80
94
  modifier: "change"
81
95
  })}
82
- ${this._strategyAction({
96
+ ${this._strategyAction({
83
97
  id: "guido__btn-remove-legacy-strategy",
84
98
  label: this.api.translate("Remove"),
85
99
  modifier: "remove"
86
100
  })}
101
+ </div>
87
102
  </div>
88
- </div>
89
- <div data-strategy-assigned-state style="display: none;">
90
- <div class="strategy-control-name-band">
91
- <span class="strategy-control-name" data-strategy-name></span>
92
- </div>
93
- <div class="strategy-control-actions">
94
- ${this._strategyAction({
103
+ <div data-strategy-assigned-state style="display: none;">
104
+ <div class="strategy-control-name-band">
105
+ <span class="strategy-control-name" data-strategy-name></span>
106
+ <span
107
+ class="guido-skeleton guido-skeleton--strategy-name" data-strategy-name-skeleton></span>
108
+ </div>
109
+ <div class="strategy-control-actions">
110
+ ${this._strategyAction({
95
111
  id: "guido__btn-change-strategy",
96
112
  label: this.api.translate("Change"),
97
113
  modifier: "change"
98
114
  })}
99
- ${this._strategyAction({
115
+ ${this._strategyAction({
100
116
  id: "guido__btn-remove-strategy",
101
117
  label: this.api.translate("Remove"),
102
118
  modifier: "remove"
103
119
  })}
120
+ </div>
104
121
  </div>
105
122
  </div>
106
123
  </div>
107
124
  `;
108
125
  }
109
- _strategyAction({ id: t, label: e, modifier: a }) {
126
+ _strategyAction({ id: t, label: e, modifier: s }) {
110
127
  return `
111
128
  <button
112
129
  id="${t}"
113
130
  type="button"
114
- class="strategy-control-action strategy-control-action--${a}">
131
+ class="strategy-control-action strategy-control-action--${s}">
115
132
  <span>${e}</span>
116
133
  </button>
117
134
  `;
118
135
  }
119
136
  onRender() {
120
- this._teardown(), this._setupButtonListeners(), this._renderState(), this.storeUnsubscription = this.store.$subscribe(() => {
137
+ this._teardown(), this.store.strategyPanelOpen = !0, this._setupButtonListeners(), this._renderState(), this.storeUnsubscription = this.store.$subscribe(() => {
121
138
  this._renderState();
122
- }), this.store.recommendationConfigs.strategyId && !this.store.strategies.length && this.store.fetchStrategies().catch(() => {
139
+ }), this.store.recommendationConfigs.strategyId && !this.store.strategiesFetched && this.store.fetchStrategies().catch(() => {
123
140
  });
124
- const t = this.store.currentRecommendationId, e = t !== null && !!this.store.blockStates[t], a = this.store.isLegacyStrategyBlock;
125
- e && !this.store.recommendationConfigs.strategyId && !a && this.onboardingStore.startOnboarding("recommendationStrategyOnboarding"), e && a && this.onboardingStore.startOnboarding("recommendationLegacyStrategyOnboarding");
141
+ }
142
+ /**
143
+ * Whether the document itself says this block has no strategy.
144
+ *
145
+ * Read the node, not the store: when the main control cannot resolve the block id off the
146
+ * node it never syncs the persisted config, so the store still holds defaults (empty
147
+ * strategyId) for an assigned block.
148
+ */
149
+ _isNodeUnassigned() {
150
+ if (!b.hasConfig(this.currentNode))
151
+ return !1;
152
+ const t = b.getConfig(this.currentNode);
153
+ return !t.strategyId && (t.configVersion ?? 0) >= N;
126
154
  }
127
155
  onDestroy() {
128
156
  this._teardown();
129
157
  }
130
158
  _teardown() {
131
- this.storeUnsubscription(), this.storeUnsubscription = () => {
159
+ this.store.strategyPanelOpen = !1, this.storeUnsubscription(), this.storeUnsubscription = () => {
132
160
  }, this.lastPaintedState = null, this.listeners.forEach(({ element: t, handler: e }) => t.removeEventListener("click", e)), this.listeners = [];
133
161
  }
134
162
  _setupButtonListeners() {
135
163
  const t = this.getContainer();
136
164
  if (!t)
137
165
  return;
138
- const e = (a, o) => {
139
- const n = t.querySelector(a);
140
- n && (n.addEventListener("click", o), this.listeners.push({ element: n, handler: o }));
166
+ const e = (s, o) => {
167
+ const a = t.querySelector(s);
168
+ a && (a.addEventListener("click", o), this.listeners.push({ element: a, handler: o }));
141
169
  };
142
- e("#guido__btn-assign-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-change-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-change-legacy-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-remove-strategy", () => this.store.openRemoveStrategyModal()), e("#guido__btn-remove-legacy-strategy", () => this.store.openRemoveStrategyModal()), e("#guido__btn-update-legacy-strategy", () => {
170
+ e("#guido__btn-assign-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-create-strategy", () => this.store.openStrategyCreation()), e("#guido__btn-change-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-change-legacy-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-remove-strategy", () => this.store.openRemoveStrategyModal()), e("#guido__btn-remove-legacy-strategy", () => this.store.openRemoveStrategyModal()), e("#guido__btn-update-legacy-strategy", () => {
143
171
  this.legacyConversion.convertLegacyStrategy();
144
172
  });
145
173
  }
146
174
  _renderState() {
147
- var h;
148
- const { strategyId: t } = this.store.recommendationConfigs, e = t ? ((h = this.store.assignedStrategy) == null ? void 0 : h.name) ?? "" : "", a = this.store.legacyConversionLoading, o = this.store.isLegacyStrategyBlock, n = `${t}\0${e}\0${a}\0${o}`;
149
- if (n === this.lastPaintedState)
175
+ var _;
176
+ const { strategyId: t } = this.store.recommendationConfigs, e = t ? ((_ = this.store.assignedStrategy) == null ? void 0 : _.name) ?? "" : "", s = !!t && !e && (this.store.strategiesLoading || !this.store.strategiesSettled), o = this.store.legacyConversionLoading, a = this.store.isLegacyStrategyBlock, h = `${t}\0${e}\0${s}\0${o}\0${a}`;
177
+ if (h === this.lastPaintedState)
150
178
  return;
151
- const c = this.getContainer();
152
- if (!c)
179
+ const r = this.getContainer();
180
+ if (!r)
153
181
  return;
154
- const d = c.querySelector("[data-strategy-empty-state]"), y = c.querySelector("[data-strategy-assigned-state]"), g = c.querySelector("[data-strategy-legacy-state]"), m = c.querySelector("[data-strategy-name]");
182
+ const d = r.querySelector("[data-strategy-empty-state]"), y = r.querySelector("[data-strategy-assigned-state]"), g = r.querySelector("[data-strategy-legacy-state]"), p = r.querySelector("[data-strategy-loading-state]"), u = r.querySelector("[data-strategy-content]"), m = r.querySelector("[data-strategy-name]"), v = r.querySelector("[data-strategy-name-skeleton]");
155
183
  if (!d || !y || !g)
156
184
  return;
157
- const u = t ? y : o ? g : d;
185
+ p && (p.style.display = "none"), u && (u.style.display = "");
186
+ const f = t ? y : a ? g : d;
158
187
  [d, y, g].forEach((l) => {
159
- l.style.display = l === u ? "" : "none";
188
+ l.style.display = l === f ? "" : "none";
160
189
  }), g.querySelectorAll("button").forEach((l) => {
161
- l.disabled = a;
162
- }), g.classList.toggle("is-converting", a), m && t && (m.textContent = e || `#${t}`), this.lastPaintedState = n;
190
+ l.disabled = o;
191
+ }), g.classList.toggle("is-converting", o), !t && this._isNodeUnassigned() && this.onboardingStore.startOnboarding("recommendationStrategyOnboarding");
192
+ const S = this.store.currentRecommendationId;
193
+ a && S !== null && this.store.blockStates[S] && this.onboardingStore.startOnboarding("recommendationLegacyStrategyOnboarding"), m && (m.style.display = s ? "none" : "", t && !s && (m.textContent = e || `#${t}`)), v && (v.style.display = s ? "block" : "none"), this.lastPaintedState = h;
163
194
  }
164
195
  }
165
196
  export {
166
- C as STRATEGY_CONTROL_ID,
167
- N as StrategyControl
197
+ E as STRATEGY_CONTROL_ID,
198
+ M as StrategyControl
168
199
  };