@useinsider/guido 3.18.1 → 3.18.2-beta.320e07f

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/components/Guido.vue.js +3 -3
  2. package/dist/components/Guido.vue2.js +30 -30
  3. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +13 -11
  4. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +76 -57
  5. package/dist/components/organisms/extensions/recommendation/RemoveStrategyModal.vue2.js +23 -37
  6. package/dist/components/organisms/onboarding/OnboardingWrapper.vue2.js +20 -18
  7. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.js +21 -0
  8. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue2.js +47 -0
  9. package/dist/components/organisms/save-as-template/SaveAsTemplateDrawer.vue2.js +34 -34
  10. package/dist/composables/useCustomInterfaceAppearance.js +56 -46
  11. package/dist/composables/useHtmlValidator.js +87 -82
  12. package/dist/composables/useHttp.js +24 -22
  13. package/dist/composables/useRecommendation.js +40 -35
  14. package/dist/composables/useStripo.js +30 -30
  15. package/dist/enums/extensions/recommendationBlock.js +38 -31
  16. package/dist/extensions/Blocks/Recommendation/block.js +43 -39
  17. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +21 -20
  18. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +55 -44
  19. package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +84 -52
  20. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +74 -74
  21. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +190 -90
  22. package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +26 -16
  23. package/dist/extensions/Blocks/Recommendation/utils/strategyCommit.js +24 -0
  24. package/dist/extensions/Blocks/Recommendation/validation/requiredFields.js +21 -12
  25. package/dist/guido.css +1 -1
  26. package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js +29 -28
  27. package/dist/package.json.js +1 -1
  28. package/dist/services/templateLibraryApi.js +17 -14
  29. package/dist/src/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.d.ts +2 -0
  30. package/dist/src/enums/extensions/recommendationBlock.d.ts +2 -0
  31. package/dist/src/extensions/Blocks/Recommendation/constants/defaultConfig.d.ts +1 -0
  32. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +1 -1
  33. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +7 -1
  34. package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +9 -0
  35. package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +7 -2
  36. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +87 -0
  37. package/dist/src/extensions/Blocks/Recommendation/utils/strategyCommit.d.ts +14 -0
  38. package/dist/src/extensions/Blocks/Recommendation/validation/requiredFields.d.ts +4 -0
  39. package/dist/src/stores/onboarding.d.ts +377 -0
  40. package/dist/src/utils/genericUtil.d.ts +6 -0
  41. package/dist/src/utils/liquidDynamicContent.d.ts +20 -0
  42. package/dist/static/styles/components/recommendation-strategy.css.js +34 -4
  43. package/dist/static/styles/components/skeleton.css.js +23 -0
  44. package/dist/stores/onboarding.js +41 -36
  45. package/dist/utils/genericUtil.js +63 -54
  46. package/dist/utils/liquidDynamicContent.js +15 -0
  47. package/dist/utils/templatePreparation.js +61 -59
  48. package/package.json +7 -7
@@ -1,46 +1,44 @@
1
1
  var m = Object.defineProperty;
2
- var C = (h, l, t) => l in h ? m(h, l, { enumerable: !0, configurable: !0, writable: !0, value: t }) : h[l] = t;
3
- var n = (h, l, t) => C(h, 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 n = (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
13
  import { ALGORITHM_CONTROL_ID as ut } from "./algorithm.js";
14
14
  import { CurrencyControl as P } from "./currency.js";
15
- import { CURRENCY_CONTROL_ID as ht } from "./currency.js";
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 gt } 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";
21
21
  import { LOCALE_CONTROL_ID as yt } from "./locale.js";
22
- import { PricePlacementControl as E } from "./pricePlacement.js";
22
+ import { PricePlacementControl as k } from "./pricePlacement.js";
23
23
  import { PRICE_PLACEMENT_CONTROL_ID as _t } from "./pricePlacement.js";
24
- import { ProductCountControl as k } from "./productCount.js";
24
+ import { ProductCountControl as E } from "./productCount.js";
25
25
  import { PRODUCT_COUNT_CONTROL_ID as Rt } from "./productCount.js";
26
- import { ProductLayoutControl as D } from "./productLayout.js";
26
+ import { ProductLayoutControl as F } from "./productLayout.js";
27
27
  import { PRODUCT_LAYOUT_CONTROL_ID as Tt } from "./productLayout.js";
28
- import { ShuffleControl as F } from "./shuffle.js";
28
+ import { ShuffleControl as D } from "./shuffle.js";
29
29
  import { SHUFFLE_CONTROL_ID as St } from "./shuffle.js";
30
30
  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 v, isPartnerManagedBlock as x, updateProductContentInPlace as B, regenerateProductRowsWithStyles as U } from "./utils.js";
33
- import { adjustProductsToSize as kt, formatProductPrice as Dt, getCardComposition as Ft, getCurrentLayout as wt, getMainContainerTbody as At, regenerateMobileProductRows as vt, updatePricesInPlace as xt, updateSingleProductContent as Bt } from "./utils.js";
34
- import { useDebounceFn as f } from "../../../../../node_modules/@vueuse/shared/index.js";
35
- const $ = "ui-elements-recommendation-block";
33
+ import { adjustProductsToSize as Et, formatProductPrice as Ft, getCardComposition as Dt, getCurrentLayout as wt, getMainContainerTbody as At, regenerateMobileProductRows as vt, updatePricesInPlace as xt, updateSingleProductContent as Bt } from "./utils.js";
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
39
  n(this, "store", R());
40
40
  n(this, "storeUnsubscription", () => {
41
41
  });
42
- // blockId -> fingerprint of the node config as it looked at the last sync.
43
- n(this, "syncedConfigs", /* @__PURE__ */ new Map());
44
42
  // A config change waiting to reach the node config. Deferred so it can ride the
45
43
  // re-render's single apply() — one user action must cost one undo press.
46
44
  n(this, "pendingNodeConfigWrite", null);
@@ -60,7 +58,7 @@ class at extends N {
60
58
  /**
61
59
  * Debounced product fetch to prevent rapid API calls during config changes
62
60
  */
63
- n(this, "_debouncedFetchProducts", f(async () => {
61
+ n(this, "_debouncedFetchProducts", h(async () => {
64
62
  try {
65
63
  await this.store.fetchRecommendationProducts();
66
64
  } finally {
@@ -78,7 +76,7 @@ class at extends N {
78
76
  * count. The store pads products to the configured size, so in-place only
79
77
  * fails when the size actually changed.
80
78
  */
81
- n(this, "_debouncedRegenerateWithProducts", f(() => {
79
+ n(this, "_debouncedRegenerateWithProducts", h(() => {
82
80
  const t = this.store.recommendationProducts;
83
81
  if (!this.currentNode || !this.api)
84
82
  return;
@@ -99,7 +97,7 @@ class at extends N {
99
97
  }, 100));
100
98
  }
101
99
  getId() {
102
- return $;
100
+ return W;
103
101
  }
104
102
  get _subControls() {
105
103
  return [
@@ -120,7 +118,7 @@ class at extends N {
120
118
  return this.rrsEnabled = p().isFeatureEnabled("reusableRecommendationStrategy"), this._subControls.forEach((e) => {
121
119
  var o;
122
120
  return (o = e == null ? void 0 : e.onDestroy) == null ? void 0 : o.call(e);
123
- }), this.algorithmControl = new T(), this.localeControl = new L(), this.currencyControl = new P(), this.productCountControl = new k(), this.productLayoutControl = new D(), this.filtersControl = new S(), this.shuffleControl = new F(), this.pricePlacementControl = new E(), this.layoutOrientationControl = new O(), this.strategyControl = this.rrsEnabled ? new w() : null, this._subControls.forEach((e) => {
121
+ }), this.algorithmControl = new T(), this.localeControl = new L(), this.currencyControl = new P(), this.productCountControl = new E(), this.productLayoutControl = new F(), this.filtersControl = new S(), this.shuffleControl = new D(), this.pricePlacementControl = new k(), this.layoutOrientationControl = new O(), this.strategyControl = this.rrsEnabled ? new w() : null, this._subControls.forEach((e) => {
124
122
  e && (e.api = this.api);
125
123
  }), `
126
124
  <div class="recommendation-controls-container">
@@ -142,14 +140,14 @@ class at extends N {
142
140
  const e = (i = this.getContainer()) == null ? void 0 : i.querySelector(".recommendation-controls-container");
143
141
  if (!e)
144
142
  return;
145
- const o = this._getRecommendationIdFromNode(t) === null ? null : c.getConfig(t), r = this.rrsEnabled && !!o && (!!(o != null && o.strategyId) || ((o == null ? void 0 : o.configVersion) ?? 0) >= _);
143
+ const o = this._getRecommendationIdFromNode(t) === null ? null : l.getConfig(t), r = this.rrsEnabled && !!o && (!!(o != null && o.strategyId) || ((o == null ? void 0 : o.configVersion) ?? 0) >= _);
146
144
  e.classList.toggle("strategy-block", r);
147
145
  }
148
146
  async onRender() {
149
147
  var o;
150
148
  b(this.api);
151
149
  const t = this._getRecommendationIdFromNode(this.currentNode), e = t ?? this.store.currentRecommendationId;
152
- 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)) {
153
151
  this._initializeSubControls();
154
152
  return;
155
153
  }
@@ -200,21 +198,34 @@ class at extends N {
200
198
  * fingerprint diff on this hook is the only way to notice (SD-149105).
201
199
  * An unchanged fingerprint means the move came from us, so runtime store
202
200
  * edits are never clobbered (SD-141049).
201
+ *
202
+ * The fingerprint is kept on the block's own store state so deleting the
203
+ * block drops it with the state it describes. A control-owned memo outlived
204
+ * that state and made a re-dropped saved module keep the defaults its wiped
205
+ * state was rebuilt with (SD-150347).
203
206
  */
204
207
  _syncNodeConfigIfChanged(t) {
205
208
  this.pendingNodeConfigWrite && this.pendingNodeConfigWrite.blockId !== t && this._flushPendingNodeConfig();
206
- const e = JSON.stringify(c.getConfig(this.currentNode)), o = this.syncedConfigs.get(t);
207
- this.syncedConfigs.set(t, e), o !== e && (this.pendingNodeConfigWrite || this._syncNodeConfigToStore());
209
+ const e = this.store.blockStates[t];
210
+ if (!e)
211
+ return;
212
+ const o = JSON.stringify(l.getConfig(this.currentNode)), r = e.syncedConfigFingerprint;
213
+ e.syncedConfigFingerprint = o, r !== o && (this.pendingNodeConfigWrite || this._syncNodeConfigToStore());
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;
208
219
  }
209
220
  _capturePendingNodeConfigWrite() {
210
221
  const t = this.store.currentRecommendationId;
211
222
  if (!this.currentNode || !this.api || t === null)
212
223
  return;
213
- const { filters: e, strategyId: o, size: r } = this.store.recommendationConfigs;
224
+ const { filters: e, strategy: o, strategyId: r, size: i } = this.store.recommendationConfigs;
214
225
  this.pendingNodeConfigWrite = {
215
226
  blockId: t,
216
227
  node: this.currentNode,
217
- updates: { filters: e, strategyId: o, size: r }
228
+ updates: { filters: e, strategy: o, strategyId: r, size: i }
218
229
  };
219
230
  }
220
231
  /**
@@ -229,7 +240,7 @@ class at extends N {
229
240
  */
230
241
  _stagePendingNodeConfig(t) {
231
242
  const e = this.pendingNodeConfigWrite;
232
- 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);
233
244
  }
234
245
  /**
235
246
  * Arms the guaranteed fallback write, once the product fetch has settled. The
@@ -253,12 +264,12 @@ class at extends N {
253
264
  const t = this.pendingNodeConfigWrite;
254
265
  if (this.pendingNodeConfigWrite = null, this._clearConfigFlush(), !t || !this.api)
255
266
  return;
256
- const e = t.blockId === this.store.currentRecommendationId && this.currentNode ? this.currentNode : t.node, o = c.getConfig(e);
257
- 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");
258
269
  }
259
270
  _syncNodeConfigToStore() {
260
271
  var r;
261
- const t = c.getConfig(this.currentNode), e = this.store.currentRecommendationId, o = e !== null && ((r = this.store.blockStates[e]) == null ? void 0 : r.isInitialized);
272
+ const t = l.getConfig(this.currentNode), e = this.store.currentRecommendationId, o = e !== null && ((r = this.store.blockStates[e]) == null ? void 0 : r.isInitialized);
262
273
  this.store.patchCurrentBlockConfig({
263
274
  strategy: t.strategy,
264
275
  strategyId: t.strategyId,
@@ -322,7 +333,7 @@ class at extends N {
322
333
  _applySmartDefaults() {
323
334
  if (!this.currentNode || !this.api)
324
335
  return;
325
- const t = c.getConfig(this.currentNode), e = {};
336
+ const t = l.getConfig(this.currentNode), e = {};
326
337
  let o = null, r = null, i = null;
327
338
  if (t.currency.code === a.currency.code) {
328
339
  const { currencyList: s } = this.store;
@@ -346,7 +357,7 @@ class at extends N {
346
357
  (d) => d.value === a.language
347
358
  ) || (i = s[0].value, e.language = i));
348
359
  }
349
- !o && !r && !i || (c.updateConfig(
360
+ !o && !r && !i || (l.updateConfig(
350
361
  this.api,
351
362
  this.currentNode,
352
363
  e,
@@ -407,19 +418,19 @@ class at extends N {
407
418
  return;
408
419
  }
409
420
  const s = t.$state.configVersion;
410
- s !== o && (o = s, this._capturePendingNodeConfigWrite(), this._debouncedFetchProducts());
411
- const u = t.recommendationProducts, d = u !== e, g = Array.isArray(u) && u.length > 0;
412
- d && g && (e = u, this._debouncedRegenerateWithProducts());
421
+ s !== o && (o = s, this._capturePendingNodeConfigWrite(), this._isPendingStrategyIdChange() && this._flushPendingNodeConfig(), this._debouncedFetchProducts());
422
+ const u = t.recommendationProducts, d = u !== e, f = Array.isArray(u) && u.length > 0;
423
+ d && f && (e = u, this._debouncedRegenerateWithProducts());
413
424
  });
414
425
  }
415
426
  }
416
427
  export {
417
428
  ut as ALGORITHM_CONTROL_ID,
418
429
  T as AlgorithmControl,
419
- $ as CONTROL_BLOCK_ID,
420
- ht as CURRENCY_CONTROL_ID,
430
+ W as CONTROL_BLOCK_ID,
431
+ gt as CURRENCY_CONTROL_ID,
421
432
  P as CurrencyControl,
422
- gt as FILTERS_CONTROL_ID,
433
+ ft as FILTERS_CONTROL_ID,
423
434
  S as FiltersControl,
424
435
  Ct as LAYOUT_ORIENTATION_CONTROL_ID,
425
436
  yt as LOCALE_CONTROL_ID,
@@ -428,18 +439,18 @@ export {
428
439
  _t as PRICE_PLACEMENT_CONTROL_ID,
429
440
  Rt as PRODUCT_COUNT_CONTROL_ID,
430
441
  Tt as PRODUCT_LAYOUT_CONTROL_ID,
431
- E as PricePlacementControl,
432
- k as ProductCountControl,
433
- D as ProductLayoutControl,
442
+ k as PricePlacementControl,
443
+ E as ProductCountControl,
444
+ F as ProductLayoutControl,
434
445
  at as RecommendationBlockControl,
435
446
  St as SHUFFLE_CONTROL_ID,
436
447
  Lt as STRATEGY_CONTROL_ID,
437
- F as ShuffleControl,
448
+ D as ShuffleControl,
438
449
  w as StrategyControl,
439
- kt as adjustProductsToSize,
440
- Dt as formatProductPrice,
450
+ Et as adjustProductsToSize,
451
+ Ft as formatProductPrice,
441
452
  v as getBlockElement,
442
- Ft as getCardComposition,
453
+ Dt as getCardComposition,
443
454
  wt as getCurrentLayout,
444
455
  At as getMainContainerTbody,
445
456
  x as isPartnerManagedBlock,
@@ -1,21 +1,25 @@
1
- var d = Object.defineProperty;
2
- var y = (r, s, t) => s in r ? d(r, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[s] = t;
3
- var o = (r, s, t) => y(r, typeof s != "symbol" ? s + "" : s, t);
4
- import { ACADEMY_LINKS as m } from "../../../../../enums/academy.js";
5
- import { CommonControl as h } from "../../../common-control.js";
6
- import { useRecommendationExtensionStore as u } from "../../store/recommendation.js";
7
- const p = "recommendation-strategy-control";
8
- class f extends h {
1
+ var u = Object.defineProperty;
2
+ var S = (o, n, t) => n in o ? u(o, n, { enumerable: !0, configurable: !0, writable: !0, value: t }) : o[n] = t;
3
+ var r = (o, n, t) => S(o, typeof n != "symbol" ? n + "" : n, t);
4
+ import { ACADEMY_LINKS as _ } from "../../../../../enums/academy.js";
5
+ import { useOnboardingStore as f } from "../../../../../stores/onboarding.js";
6
+ import { CommonControl as v } from "../../../common-control.js";
7
+ import { RRS_CONFIG_VERSION as b } from "../../constants/defaultConfig.js";
8
+ import { RecommendationConfigService as h } from "../../services/configService.js";
9
+ import { useRecommendationExtensionStore as C } from "../../store/recommendation.js";
10
+ const k = "recommendation-strategy-control";
11
+ class I extends v {
9
12
  constructor() {
10
13
  super(...arguments);
11
- o(this, "store", u());
12
- o(this, "storeUnsubscription", () => {
14
+ r(this, "store", C());
15
+ r(this, "onboardingStore", f());
16
+ r(this, "storeUnsubscription", () => {
13
17
  });
14
- o(this, "listeners", []);
15
- o(this, "lastPaintedState", null);
18
+ r(this, "listeners", []);
19
+ r(this, "lastPaintedState", null);
16
20
  }
17
21
  getId() {
18
- return p;
22
+ return k;
19
23
  }
20
24
  getTemplate() {
21
25
  const t = this.api.translate(
@@ -23,21 +27,34 @@ class f extends h {
23
27
  ), e = this.api.translate("For more information, you can"), a = this.api.translate("visit Academy");
24
28
  return `
25
29
  <div class="strategy-control-container">
26
- <div class="strategy-control-header">
27
- <h3 class="strategy-control-title">${this.api.translate("Recommendation Strategy")}</h3>
28
- </div>
29
- <div class="strategy-control-description-row">
30
- <p class="strategy-control-description">
31
- ${t}
32
- ${e}
33
- <a
34
- href="${m.EMAIL_RECOMMENDATION_BLOCK}"
35
- target="_blank"
36
- rel="noopener noreferrer">${a}</a>.
37
- </p>
30
+ <div data-strategy-loading-state>
31
+ <div class="strategy-control-header">
32
+ <span class="guido-skeleton guido-skeleton--strategy-title"></span>
33
+ </div>
34
+ <div class="strategy-control-description-row">
35
+ <span class="guido-skeleton guido-skeleton--strategy-description"></span>
36
+ </div>
37
+ <div class="strategy-control-skeleton-row">
38
+ <span class="guido-skeleton guido-skeleton--strategy-cta"></span>
39
+ <span class="guido-skeleton guido-skeleton--strategy-cta"></span>
40
+ </div>
38
41
  </div>
39
- <div data-strategy-empty-state>
40
- ${this._GuTwoColumns([
42
+ <div data-strategy-content style="display: none;">
43
+ <div class="strategy-control-header">
44
+ <h3 class="strategy-control-title">${this.api.translate("Recommendation Strategy")}</h3>
45
+ </div>
46
+ <div class="strategy-control-description-row">
47
+ <p class="strategy-control-description">
48
+ ${t}
49
+ ${e}
50
+ <a
51
+ href="${_.EMAIL_RECOMMENDATION_BLOCK}"
52
+ target="_blank"
53
+ rel="noopener noreferrer">${a}</a>.
54
+ </p>
55
+ </div>
56
+ <div data-strategy-empty-state style="display: none;">
57
+ ${this._GuTwoColumns([
41
58
  this._GuButton({
42
59
  name: "assignStrategy",
43
60
  label: this.api.translate("Assign Strategy"),
@@ -48,26 +65,28 @@ class f extends h {
48
65
  name: "createStrategy",
49
66
  label: this.api.translate("Create New Strategy"),
50
67
  id: "guido__btn-create-strategy",
51
- className: "strategy-control-cta primary",
52
- disabled: !0
68
+ className: "strategy-control-cta primary"
53
69
  })
54
70
  ], "strategy-control-cta-row")}
55
- </div>
56
- <div data-strategy-assigned-state style="display: none;">
57
- <div class="strategy-control-name-band">
58
- <span class="strategy-control-name" data-strategy-name></span>
59
71
  </div>
60
- <div class="strategy-control-actions">
61
- ${this._strategyAction({
72
+ <div data-strategy-assigned-state style="display: none;">
73
+ <div class="strategy-control-name-band">
74
+ <span class="strategy-control-name" data-strategy-name></span>
75
+ <span
76
+ class="guido-skeleton guido-skeleton--strategy-name" data-strategy-name-skeleton></span>
77
+ </div>
78
+ <div class="strategy-control-actions">
79
+ ${this._strategyAction({
62
80
  id: "guido__btn-change-strategy",
63
81
  label: this.api.translate("Change"),
64
82
  modifier: "change"
65
83
  })}
66
- ${this._strategyAction({
84
+ ${this._strategyAction({
67
85
  id: "guido__btn-remove-strategy",
68
86
  label: this.api.translate("Remove"),
69
87
  modifier: "remove"
70
88
  })}
89
+ </div>
71
90
  </div>
72
91
  </div>
73
92
  </div>
@@ -84,41 +103,54 @@ class f extends h {
84
103
  `;
85
104
  }
86
105
  onRender() {
87
- this._teardown(), this._setupButtonListeners(), this._renderState(), this.storeUnsubscription = this.store.$subscribe(() => {
106
+ this._teardown(), this.store.strategyPanelOpen = !0, this._setupButtonListeners(), this._renderState(), this.storeUnsubscription = this.store.$subscribe(() => {
88
107
  this._renderState();
89
- }), this.store.recommendationConfigs.strategyId && !this.store.strategies.length && this.store.fetchStrategies().catch(() => {
108
+ }), this.store.recommendationConfigs.strategyId && !this.store.strategiesFetched && this.store.fetchStrategies().catch(() => {
90
109
  });
91
110
  }
111
+ /**
112
+ * Whether the document itself says this block has no strategy.
113
+ *
114
+ * Read the node, not the store: when the main control cannot resolve the block id off the
115
+ * node it never syncs the persisted config, so the store still holds defaults (empty
116
+ * strategyId) for an assigned block.
117
+ */
118
+ _isNodeUnassigned() {
119
+ if (!h.hasConfig(this.currentNode))
120
+ return !1;
121
+ const t = h.getConfig(this.currentNode);
122
+ return !t.strategyId && (t.configVersion ?? 0) >= b;
123
+ }
92
124
  onDestroy() {
93
125
  this._teardown();
94
126
  }
95
127
  _teardown() {
96
- this.storeUnsubscription(), this.storeUnsubscription = () => {
128
+ this.store.strategyPanelOpen = !1, this.storeUnsubscription(), this.storeUnsubscription = () => {
97
129
  }, this.lastPaintedState = null, this.listeners.forEach(({ element: t, handler: e }) => t.removeEventListener("click", e)), this.listeners = [];
98
130
  }
99
131
  _setupButtonListeners() {
100
132
  const t = this.getContainer();
101
133
  if (!t)
102
134
  return;
103
- const e = (a, n) => {
104
- const i = t.querySelector(a);
105
- i && (i.addEventListener("click", n), this.listeners.push({ element: i, handler: n }));
135
+ const e = (a, i) => {
136
+ const s = t.querySelector(a);
137
+ s && (s.addEventListener("click", i), this.listeners.push({ element: s, handler: i }));
106
138
  };
107
- e("#guido__btn-assign-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-change-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-remove-strategy", () => this.store.openRemoveStrategyModal());
139
+ 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-remove-strategy", () => this.store.openRemoveStrategyModal());
108
140
  }
109
141
  _renderState() {
110
- var l;
111
- const { strategyId: t } = this.store.recommendationConfigs, e = t ? ((l = this.store.assignedStrategy) == null ? void 0 : l.name) ?? "" : "", a = `${t}\0${e}`;
112
- if (a === this.lastPaintedState)
142
+ var p;
143
+ const { strategyId: t } = this.store.recommendationConfigs, e = t ? ((p = this.store.assignedStrategy) == null ? void 0 : p.name) ?? "" : "", a = !!t && !e && (this.store.strategiesLoading || !this.store.strategiesSettled), i = `${t}\0${e}\0${a}`;
144
+ if (i === this.lastPaintedState)
113
145
  return;
114
- const n = this.getContainer();
115
- if (!n)
146
+ const s = this.getContainer();
147
+ if (!s)
116
148
  return;
117
- const i = n.querySelector("[data-strategy-empty-state]"), c = n.querySelector("[data-strategy-assigned-state]"), g = n.querySelector("[data-strategy-name]");
118
- !i || !c || (i.style.display = t ? "none" : "", c.style.display = t ? "" : "none", g && t && (g.textContent = e || `#${t}`), this.lastPaintedState = a);
149
+ const c = s.querySelector("[data-strategy-empty-state]"), g = s.querySelector("[data-strategy-assigned-state]"), l = s.querySelector("[data-strategy-loading-state]"), y = s.querySelector("[data-strategy-content]"), d = s.querySelector("[data-strategy-name]"), m = s.querySelector("[data-strategy-name-skeleton]");
150
+ !c || !g || (l && (l.style.display = "none"), y && (y.style.display = ""), c.style.display = t ? "none" : "", g.style.display = t ? "" : "none", !t && this._isNodeUnassigned() && this.onboardingStore.startOnboarding("recommendationStrategyOnboarding"), d && (d.style.display = a ? "none" : "", t && !a && (d.textContent = e || `#${t}`)), m && (m.style.display = a ? "block" : "none"), this.lastPaintedState = i);
119
151
  }
120
152
  }
121
153
  export {
122
- p as STRATEGY_CONTROL_ID,
123
- f as StrategyControl
154
+ k as STRATEGY_CONTROL_ID,
155
+ I as StrategyControl
124
156
  };