@useinsider/guido 3.17.0-beta.ddd4dde → 3.17.0-beta.e324492

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 (95) hide show
  1. package/README.md +1 -0
  2. package/dist/@types/config/schemas.js +7 -6
  3. package/dist/components/Guido.vue.js +10 -10
  4. package/dist/components/Guido.vue2.js +82 -76
  5. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +21 -0
  6. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +106 -0
  7. package/dist/components/organisms/extensions/recommendation/RemoveStrategyModal.vue.js +17 -0
  8. package/dist/components/organisms/extensions/recommendation/RemoveStrategyModal.vue2.js +57 -0
  9. package/dist/components/organisms/extensions/recommendation/StrategyInfoBoxContent.vue.js +19 -0
  10. package/dist/components/organisms/extensions/recommendation/StrategyInfoBoxContent.vue2.js +63 -0
  11. package/dist/composables/useCustomInterfaceAppearance.js +52 -38
  12. package/dist/composables/useRecommendation.js +41 -34
  13. package/dist/composables/useStripo.js +14 -14
  14. package/dist/config/i18n/en/labels.json.js +1 -1
  15. package/dist/config/migrator/index.js +9 -8
  16. package/dist/config/migrator/recommendation/compositionMapper.js +20 -20
  17. package/dist/config/migrator/recommendation/extractors.js +29 -24
  18. package/dist/config/migrator/recommendation/htmlBuilder.js +116 -130
  19. package/dist/config/migrator/recommendation/settingsMapper.js +17 -17
  20. package/dist/config/migrator/recommendationMigrator.js +31 -25
  21. package/dist/config/migrator/recommendationTitleMigrator.js +119 -0
  22. package/dist/enums/academy.js +2 -1
  23. package/dist/enums/date.js +5 -3
  24. package/dist/enums/extensions/recommendationBlock.js +3 -1
  25. package/dist/extensions/Blocks/Items/block.js +49 -98
  26. package/dist/extensions/Blocks/Items/controls/price/currencyLocation.js +24 -25
  27. package/dist/extensions/Blocks/Items/controls/price/currencySymbol.js +11 -12
  28. package/dist/extensions/Blocks/Items/template.js +152 -153
  29. package/dist/extensions/Blocks/Recommendation/block.js +35 -29
  30. package/dist/extensions/Blocks/Recommendation/constants/blockIds.js +1 -1
  31. package/dist/extensions/Blocks/Recommendation/constants/controlIds.js +1 -1
  32. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +29 -27
  33. package/dist/extensions/Blocks/Recommendation/constants/selectors.js +35 -28
  34. package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +309 -236
  35. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +247 -180
  36. package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +124 -0
  37. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +1 -0
  38. package/dist/extensions/Blocks/Recommendation/controls/title/index.js +44 -0
  39. package/dist/extensions/Blocks/Recommendation/extension.js +31 -29
  40. package/dist/extensions/Blocks/Recommendation/services/configService.js +54 -36
  41. package/dist/extensions/Blocks/Recommendation/settingsPanel.js +23 -4
  42. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +177 -80
  43. package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +3 -3
  44. package/dist/extensions/Blocks/Recommendation/templates/titleRows.js +33 -0
  45. package/dist/extensions/Blocks/Recommendation/templates/utils.js +85 -107
  46. package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +22 -0
  47. package/dist/extensions/Blocks/common-control.js +22 -19
  48. package/dist/guido.css +1 -1
  49. package/dist/services/recommendationApi.js +69 -30
  50. package/dist/src/@types/config/schemas.d.ts +2 -0
  51. package/dist/src/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.d.ts +3 -0
  52. package/dist/src/components/organisms/extensions/recommendation/RemoveStrategyModal.vue.d.ts +2 -0
  53. package/dist/src/components/organisms/extensions/recommendation/StrategyInfoBoxContent.vue.d.ts +15 -0
  54. package/dist/src/composables/useConfig.d.ts +2 -0
  55. package/dist/src/composables/useRecommendation.d.ts +1 -0
  56. package/dist/src/config/migrator/recommendation/extractors.d.ts +8 -0
  57. package/dist/src/config/migrator/recommendationTitleMigrator.d.ts +5 -0
  58. package/dist/src/enums/academy.d.ts +1 -0
  59. package/dist/src/enums/date.d.ts +1 -0
  60. package/dist/src/enums/extensions/recommendationBlock.d.ts +2 -0
  61. package/dist/src/extensions/Blocks/Items/block.d.ts +0 -21
  62. package/dist/src/extensions/Blocks/Recommendation/constants/blockIds.d.ts +2 -1
  63. package/dist/src/extensions/Blocks/Recommendation/constants/controlIds.d.ts +7 -0
  64. package/dist/src/extensions/Blocks/Recommendation/constants/defaultConfig.d.ts +3 -6
  65. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +2 -2
  66. package/dist/src/extensions/Blocks/Recommendation/constants/selectors.d.ts +12 -0
  67. package/dist/src/extensions/Blocks/Recommendation/controls/cardComposition/index.d.ts +11 -0
  68. package/dist/src/extensions/Blocks/Recommendation/controls/index.d.ts +1 -0
  69. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +48 -8
  70. package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +16 -0
  71. package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +1 -0
  72. package/dist/src/extensions/Blocks/Recommendation/controls/title/index.d.ts +86 -0
  73. package/dist/src/extensions/Blocks/Recommendation/services/configService.d.ts +12 -1
  74. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +188 -10
  75. package/dist/src/extensions/Blocks/Recommendation/templates/titleRows.d.ts +13 -0
  76. package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +7 -0
  77. package/dist/src/extensions/Blocks/Recommendation/utils/nodeConfigWriter.d.ts +31 -0
  78. package/dist/src/extensions/Blocks/common-control.d.ts +4 -1
  79. package/dist/src/mock/api/recommendation-strategies.d.ts +2 -0
  80. package/dist/src/services/recommendationApi.d.ts +4 -1
  81. package/dist/src/stores/config.d.ts +18 -0
  82. package/dist/src/stores/save-as-template.d.ts +4 -3
  83. package/dist/src/utils/genericUtil.d.ts +5 -0
  84. package/dist/static/assets/icons/line-change.svg.js +5 -0
  85. package/dist/static/assets/icons/line-delete.svg.js +5 -0
  86. package/dist/static/assets/icons/line-plus.svg.js +5 -0
  87. package/dist/static/styles/components/recommendation-strategy.css.js +155 -0
  88. package/dist/static/styles/customEditorStyle.css.js +3 -1
  89. package/dist/utils/dateUtil.js +23 -10
  90. package/dist/utils/genericUtil.js +28 -27
  91. package/dist/utils/pairProductVariables.js +59 -60
  92. package/dist/utils/templatePreparation.js +47 -45
  93. package/package.json +2 -1
  94. package/dist/extensions/Blocks/Items/constants/currency.js +0 -11
  95. package/dist/src/extensions/Blocks/Items/constants/currency.d.ts +0 -19
@@ -1,54 +1,69 @@
1
- var f = Object.defineProperty;
2
- var p = (d, l, t) => l in d ? f(d, l, { enumerable: !0, configurable: !0, writable: !0, value: t }) : d[l] = t;
3
- var s = (d, l, t) => p(d, typeof l != "symbol" ? l + "" : l, t);
4
- import { CommonControl as g } from "../../../common-control.js";
5
- import { DEFAULT_NODE_CONFIG as c } from "../../constants/defaultConfig.js";
6
- import { RecommendationConfigService as h } from "../../services/configService.js";
7
- import { useRecommendationExtensionStore as y } from "../../store/recommendation.js";
8
- import { AlgorithmControl as N } from "./algorithm.js";
9
- import { ALGORITHM_CONTROL_ID as tt } from "./algorithm.js";
10
- import { CurrencyControl as R } from "./currency.js";
11
- import { CURRENCY_CONTROL_ID as ot } from "./currency.js";
12
- import { FiltersControl as I } from "./filters.js";
13
- import { FILTERS_CONTROL_ID as nt } from "./filters.js";
14
- import { LayoutOrientationControl as _ } from "./layoutOrientation.js";
15
- import { LAYOUT_ORIENTATION_CONTROL_ID as st } from "./layoutOrientation.js";
16
- import { LocaleControl as b } from "./locale.js";
17
- import { LOCALE_CONTROL_ID as lt } from "./locale.js";
18
- import { PricePlacementControl as T } from "./pricePlacement.js";
19
- import { PRICE_PLACEMENT_CONTROL_ID as ut } from "./pricePlacement.js";
20
- import { ProductCountControl as O } from "./productCount.js";
21
- import { PRODUCT_COUNT_CONTROL_ID as ht } from "./productCount.js";
22
- import { ProductLayoutControl as P } from "./productLayout.js";
23
- import { PRODUCT_LAYOUT_CONTROL_ID as Ct } from "./productLayout.js";
24
- import { ShuffleControl as S } from "./shuffle.js";
25
- import { SHUFFLE_CONTROL_ID as pt } from "./shuffle.js";
26
- import { setCurrencyAttributes as L, getBlockElement as k, isPartnerManagedBlock as D, updateProductContentInPlace as E, regenerateProductRowsWithStyles as A } from "./utils.js";
27
- import { adjustProductsToSize as yt, formatProductPrice as Nt, getCardComposition as Rt, getCurrentLayout as It, regenerateMobileProductRows as _t, updatePricesInPlace as bt, updateSingleProductContent as Tt } from "./utils.js";
28
- import { useDebounceFn as m } from "../../../../../node_modules/@vueuse/shared/index.js";
29
- const v = "recommendation-id", w = "ui-elements-recommendation-block";
30
- class Q extends g {
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);
4
+ import { useConfig as p } from "../../../../../composables/useConfig.js";
5
+ import { ModificationDescription as y } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
6
+ import { CommonControl as N } from "../../../common-control.js";
7
+ import { CURRENT_CONFIG_VERSION as _, DEFAULT_NODE_CONFIG as a } from "../../constants/defaultConfig.js";
8
+ import { RECOMMENDATION_ID_ATTR as I } from "../../constants/selectors.js";
9
+ import { RecommendationConfigService as c } from "../../services/configService.js";
10
+ import { useRecommendationExtensionStore as R } from "../../store/recommendation.js";
11
+ import { registerNodeConfigWriter as b } from "../../utils/nodeConfigWriter.js";
12
+ import { AlgorithmControl as T } from "./algorithm.js";
13
+ import { ALGORITHM_CONTROL_ID as ut } from "./algorithm.js";
14
+ import { CurrencyControl as P } from "./currency.js";
15
+ import { CURRENCY_CONTROL_ID as ht } from "./currency.js";
16
+ import { FiltersControl as S } from "./filters.js";
17
+ import { FILTERS_CONTROL_ID as gt } from "./filters.js";
18
+ import { LayoutOrientationControl as O } from "./layoutOrientation.js";
19
+ import { LAYOUT_ORIENTATION_CONTROL_ID as Ct } from "./layoutOrientation.js";
20
+ import { LocaleControl as L } from "./locale.js";
21
+ import { LOCALE_CONTROL_ID as yt } from "./locale.js";
22
+ import { PricePlacementControl as E } from "./pricePlacement.js";
23
+ import { PRICE_PLACEMENT_CONTROL_ID as _t } from "./pricePlacement.js";
24
+ import { ProductCountControl as k } from "./productCount.js";
25
+ import { PRODUCT_COUNT_CONTROL_ID as Rt } from "./productCount.js";
26
+ import { ProductLayoutControl as F } from "./productLayout.js";
27
+ import { PRODUCT_LAYOUT_CONTROL_ID as Tt } from "./productLayout.js";
28
+ import { ShuffleControl as D } from "./shuffle.js";
29
+ import { SHUFFLE_CONTROL_ID as St } from "./shuffle.js";
30
+ import { StrategyControl as w } from "./strategy.js";
31
+ import { STRATEGY_CONTROL_ID as Lt } from "./strategy.js";
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 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 f } from "../../../../../node_modules/@vueuse/shared/index.js";
35
+ const $ = "ui-elements-recommendation-block";
36
+ class at extends N {
31
37
  constructor() {
32
38
  super(...arguments);
33
- s(this, "store", y());
34
- s(this, "storeUnsubscription", () => {
39
+ n(this, "store", R());
40
+ n(this, "storeUnsubscription", () => {
35
41
  });
36
- s(this, "syncedBlockIds", /* @__PURE__ */ new Set());
42
+ // A config change waiting to reach the node config. Deferred so it can ride the
43
+ // re-render's single apply() — one user action must cost one undo press.
44
+ n(this, "pendingNodeConfigWrite", null);
45
+ n(this, "pendingConfigFlushTimer", null);
37
46
  // Sub-control instances for lifecycle management
38
- s(this, "algorithmControl", null);
39
- s(this, "localeControl", null);
40
- s(this, "currencyControl", null);
41
- s(this, "productCountControl", null);
42
- s(this, "productLayoutControl", null);
43
- s(this, "filtersControl", null);
44
- s(this, "shuffleControl", null);
45
- s(this, "pricePlacementControl", null);
46
- s(this, "layoutOrientationControl", null);
47
+ n(this, "algorithmControl", null);
48
+ n(this, "localeControl", null);
49
+ n(this, "currencyControl", null);
50
+ n(this, "productCountControl", null);
51
+ n(this, "productLayoutControl", null);
52
+ n(this, "filtersControl", null);
53
+ n(this, "shuffleControl", null);
54
+ n(this, "pricePlacementControl", null);
55
+ n(this, "layoutOrientationControl", null);
56
+ n(this, "strategyControl", null);
57
+ n(this, "rrsEnabled", !1);
47
58
  /**
48
59
  * Debounced product fetch to prevent rapid API calls during config changes
49
60
  */
50
- s(this, "_debouncedFetchProducts", m(() => {
51
- this.store.fetchRecommendationProducts();
61
+ n(this, "_debouncedFetchProducts", f(async () => {
62
+ try {
63
+ await this.store.fetchRecommendationProducts();
64
+ } finally {
65
+ this._scheduleConfigFlush();
66
+ }
52
67
  }, 500));
53
68
  /**
54
69
  * Debounced content update when products arrive from API.
@@ -61,16 +76,20 @@ class Q extends g {
61
76
  * count. The store pads products to the configured size, so in-place only
62
77
  * fails when the size actually changed.
63
78
  */
64
- s(this, "_debouncedRegenerateWithProducts", m(() => {
79
+ n(this, "_debouncedRegenerateWithProducts", f(() => {
65
80
  const t = this.store.recommendationProducts;
66
- if (!this.currentNode || !this.api || D(this.currentNode))
81
+ if (!this.currentNode || !this.api)
82
+ return;
83
+ const e = this.api.getDocumentModifier(), o = this._stagePendingNodeConfig(e);
84
+ if (x(this.currentNode)) {
85
+ o && (e.apply(new y("Update recommendation configuration")), this.pendingNodeConfigWrite = null, this._clearConfigFlush());
67
86
  return;
68
- const e = this.api.getDocumentModifier();
69
- E({
87
+ }
88
+ B({
70
89
  currentNode: this.currentNode,
71
90
  documentModifier: e,
72
91
  products: t
73
- }) || A({
92
+ }) || U({
74
93
  currentNode: this.currentNode,
75
94
  documentModifier: e,
76
95
  products: t
@@ -78,23 +97,32 @@ class Q extends g {
78
97
  }, 100));
79
98
  }
80
99
  getId() {
81
- return w;
100
+ return $;
82
101
  }
83
- getTemplate() {
84
- return this.algorithmControl = new N(), this.localeControl = new b(), this.currencyControl = new R(), this.productCountControl = new O(), this.productLayoutControl = new P(), this.filtersControl = new I(), this.shuffleControl = new S(), this.pricePlacementControl = new T(), this.layoutOrientationControl = new _(), [
102
+ get _subControls() {
103
+ return [
104
+ this.layoutOrientationControl,
105
+ this.productCountControl,
85
106
  this.algorithmControl,
86
107
  this.localeControl,
87
108
  this.currencyControl,
88
- this.productCountControl,
89
109
  this.productLayoutControl,
90
110
  this.filtersControl,
91
111
  this.shuffleControl,
92
112
  this.pricePlacementControl,
93
- this.layoutOrientationControl
94
- ].forEach((e) => {
95
- e.api = this.api;
113
+ this.strategyControl
114
+ ];
115
+ }
116
+ getTemplate() {
117
+ var t;
118
+ return this.rrsEnabled = p().isFeatureEnabled("reusableRecommendationStrategy"), this._subControls.forEach((e) => {
119
+ var o;
120
+ return (o = e == null ? void 0 : e.onDestroy) == null ? void 0 : o.call(e);
121
+ }), this.algorithmControl = new T(), this.localeControl = new L(), this.currencyControl = new P(), this.productCountControl = new k(), this.productLayoutControl = new F(), this.filtersControl = new S(), this.shuffleControl = new D(), this.pricePlacementControl = new E(), this.layoutOrientationControl = new O(), this.strategyControl = this.rrsEnabled ? new w() : null, this._subControls.forEach((e) => {
122
+ e && (e.api = this.api);
96
123
  }), `
97
124
  <div class="recommendation-controls-container">
125
+ ${((t = this.strategyControl) == null ? void 0 : t.getTemplate()) ?? ""}
98
126
  ${this.layoutOrientationControl.getTemplate()}
99
127
  ${this.productCountControl.getTemplate()}
100
128
  ${this.productLayoutControl.getTemplate()}
@@ -107,50 +135,39 @@ class Q extends g {
107
135
  </div>
108
136
  `;
109
137
  }
138
+ _showControlsForBlock(t) {
139
+ var i;
140
+ const e = (i = this.getContainer()) == null ? void 0 : i.querySelector(".recommendation-controls-container");
141
+ if (!e)
142
+ return;
143
+ 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) >= _);
144
+ e.classList.toggle("strategy-block", r);
145
+ }
110
146
  async onRender() {
111
147
  var o;
148
+ b(this.api);
112
149
  const t = this._getRecommendationIdFromNode(this.currentNode), e = t ?? this.store.currentRecommendationId;
113
- if (e !== null && this.store.setCurrentBlock(e), t !== null && !this.syncedBlockIds.has(t) && (this.syncedBlockIds.add(t), this._syncNodeConfigToStore()), this._listenStateUpdates(), 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), e !== null && ((o = this.store.blockStates[e]) != null && o.isInitialized)) {
114
151
  this._initializeSubControls();
115
152
  return;
116
153
  }
117
154
  await this._fetchBlockData(e), this._initializeSubControls();
118
155
  }
119
156
  onTemplateNodeUpdated(t) {
120
- var r;
157
+ var o;
121
158
  super.onTemplateNodeUpdated(t);
122
159
  const e = this._getRecommendationIdFromNode(t);
123
- e !== null && e !== this.store.currentRecommendationId && this.store.setCurrentBlock(e), e !== null && !this.syncedBlockIds.has(e) && (this.syncedBlockIds.add(e), this._syncNodeConfigToStore()), e !== null && !((r = this.store.blockStates[e]) != null && r.isInitialized) && this._fetchBlockData(e).then(() => {
160
+ e !== null && e !== this.store.currentRecommendationId && this.store.setCurrentBlock(e), e !== null && this._syncNodeConfigIfChanged(e), this._showControlsForBlock(t), e !== null && !((o = this.store.blockStates[e]) != null && o.isInitialized) && this._fetchBlockData(e).then(() => {
124
161
  this._initializeSubControls();
125
- }), [
126
- this.layoutOrientationControl,
127
- this.productCountControl,
128
- this.algorithmControl,
129
- this.localeControl,
130
- this.currencyControl,
131
- this.productLayoutControl,
132
- this.filtersControl,
133
- this.shuffleControl,
134
- this.pricePlacementControl
135
- ].forEach((n) => {
162
+ }), this._subControls.forEach((r) => {
136
163
  var i;
137
- n != null && n.api && (n.currentNode = t, (i = n.onTemplateNodeUpdated) == null || i.call(n, t));
164
+ r != null && r.api && (r.currentNode = t, (i = r.onTemplateNodeUpdated) == null || i.call(r, t));
138
165
  });
139
166
  }
140
167
  onDestroy() {
141
- this.storeUnsubscription(), [
142
- this.layoutOrientationControl,
143
- this.productCountControl,
144
- this.algorithmControl,
145
- this.localeControl,
146
- this.currencyControl,
147
- this.productLayoutControl,
148
- this.filtersControl,
149
- this.shuffleControl,
150
- this.pricePlacementControl
151
- ].forEach((e) => {
152
- var o;
153
- return (o = e == null ? void 0 : e.onDestroy) == null ? void 0 : o.call(e);
168
+ this.storeUnsubscription(), this._flushPendingNodeConfig(), this._subControls.forEach((t) => {
169
+ var e;
170
+ return (e = t == null ? void 0 : t.onDestroy) == null ? void 0 : e.call(t);
154
171
  });
155
172
  }
156
173
  /**
@@ -158,25 +175,14 @@ class Q extends g {
158
175
  * Each sub-control manages its own form values and event listeners
159
176
  */
160
177
  _initializeSubControls() {
161
- [
162
- this.layoutOrientationControl,
163
- this.productCountControl,
164
- this.algorithmControl,
165
- this.localeControl,
166
- this.currencyControl,
167
- this.productLayoutControl,
168
- this.filtersControl,
169
- this.shuffleControl,
170
- this.pricePlacementControl
171
- ].forEach((e) => {
172
- var o;
173
- e && (e.api = this.api, e.currentNode = this.currentNode, (o = e.onRender) == null || o.call(e));
178
+ this._subControls.forEach((t) => {
179
+ var e;
180
+ t && (t.api = this.api, t.currentNode = this.currentNode, (e = t.onRender) == null || e.call(t));
174
181
  });
175
182
  }
176
183
  /**
177
184
  * Syncs persisted node config into the Pinia store's block state.
178
185
  *
179
- * setCurrentBlock() creates a default entry (USD, en_US, mostPopular).
180
186
  * For saved templates, the real config lives in the node (e.g., TRY, tr_TR).
181
187
  * This method reads it and patches the store so fetchRecommendationProducts()
182
188
  * uses the correct values.
@@ -184,11 +190,84 @@ class Q extends g {
184
190
  * Uses triggerRefetch: false because the fetch hasn't happened yet —
185
191
  * values are being prepared for the upcoming initial fetch.
186
192
  */
193
+ /**
194
+ * Re-syncs the store when the node config moved since we last read it.
195
+ *
196
+ * Undo/redo, the code editor and version-history restore rewrite the node
197
+ * config behind the store's back — Stripo exposes no undo signal, so a
198
+ * fingerprint diff on this hook is the only way to notice (SD-149105).
199
+ * An unchanged fingerprint means the move came from us, so runtime store
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).
206
+ */
207
+ _syncNodeConfigIfChanged(t) {
208
+ this.pendingNodeConfigWrite && this.pendingNodeConfigWrite.blockId !== t && this._flushPendingNodeConfig();
209
+ const e = this.store.blockStates[t];
210
+ if (!e)
211
+ return;
212
+ const o = JSON.stringify(c.getConfig(this.currentNode)), r = e.syncedConfigFingerprint;
213
+ e.syncedConfigFingerprint = o, r !== o && (this.pendingNodeConfigWrite || this._syncNodeConfigToStore());
214
+ }
215
+ _capturePendingNodeConfigWrite() {
216
+ const t = this.store.currentRecommendationId;
217
+ if (!this.currentNode || !this.api || t === null)
218
+ return;
219
+ const { filters: e, strategyId: o, size: r } = this.store.recommendationConfigs;
220
+ this.pendingNodeConfigWrite = {
221
+ blockId: t,
222
+ node: this.currentNode,
223
+ updates: { filters: e, strategyId: o, size: r }
224
+ };
225
+ }
226
+ /**
227
+ * Accumulates the pending write into `documentModifier` without applying, so the
228
+ * caller's apply() commits config and re-render as ONE undo entry.
229
+ *
230
+ * Deliberately does not consume the pending record: the product helpers call
231
+ * apply() only when they actually changed something, so this batch may never be
232
+ * committed and the flush has to stay able to write it standalone.
233
+ * @param documentModifier - The batch to accumulate into
234
+ * @returns Whether anything was staged
235
+ */
236
+ _stagePendingNodeConfig(t) {
237
+ const e = this.pendingNodeConfigWrite;
238
+ return !e || !this.currentNode ? !1 : (c.stageConfig(t, this.currentNode, e.updates), !0);
239
+ }
240
+ /**
241
+ * Arms the guaranteed fallback write, once the product fetch has settled. The
242
+ * delay only has to outlast the re-render debounce that fetch triggers — firing
243
+ * earlier writes the config on its own and the undo entry splits in two again.
244
+ */
245
+ _scheduleConfigFlush() {
246
+ this._clearConfigFlush(), this.pendingConfigFlushTimer = setTimeout(() => {
247
+ this.pendingConfigFlushTimer = null, this._flushPendingNodeConfig();
248
+ }, 800);
249
+ }
250
+ _clearConfigFlush() {
251
+ this.pendingConfigFlushTimer !== null && (clearTimeout(this.pendingConfigFlushTimer), this.pendingConfigFlushTimer = null);
252
+ }
253
+ /**
254
+ * Writes the deferred change standalone when the batch it was staged into never
255
+ * committed. Always targets the LIVE node — the captured one is an immutable
256
+ * snapshot the intervening re-render staled, and saveConfig swallows that failure.
257
+ */
258
+ _flushPendingNodeConfig() {
259
+ const t = this.pendingNodeConfigWrite;
260
+ if (this.pendingNodeConfigWrite = null, this._clearConfigFlush(), !t || !this.api)
261
+ 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");
264
+ }
187
265
  _syncNodeConfigToStore() {
188
266
  var r;
189
- const t = h.getConfig(this.currentNode), e = this.store.currentRecommendationId, o = e !== null && ((r = this.store.blockStates[e]) == null ? void 0 : r.isInitialized);
267
+ const t = c.getConfig(this.currentNode), e = this.store.currentRecommendationId, o = e !== null && ((r = this.store.blockStates[e]) == null ? void 0 : r.isInitialized);
190
268
  this.store.patchCurrentBlockConfig({
191
269
  strategy: t.strategy,
270
+ strategyId: t.strategyId,
192
271
  language: t.language,
193
272
  size: t.size,
194
273
  productIds: t.productIds,
@@ -249,36 +328,36 @@ class Q extends g {
249
328
  _applySmartDefaults() {
250
329
  if (!this.currentNode || !this.api)
251
330
  return;
252
- const t = h.getConfig(this.currentNode), e = {};
253
- let o = null, r = null, n = null;
254
- if (t.currency.code === c.currency.code) {
255
- const { currencyList: i } = this.store;
256
- i.length > 0 && (i.some(
257
- (u) => u.value === `price.${c.currency.code}`
258
- ) || (o = i[0].value.replace("price.", ""), e.currency = {
259
- ...c.currency,
331
+ const t = c.getConfig(this.currentNode), e = {};
332
+ let o = null, r = null, i = null;
333
+ if (t.currency.code === a.currency.code) {
334
+ const { currencyList: s } = this.store;
335
+ s.length > 0 && (s.some(
336
+ (d) => d.value === `price.${a.currency.code}`
337
+ ) || (o = s[0].value.replace("price.", ""), e.currency = {
338
+ ...a.currency,
260
339
  code: o,
261
340
  symbol: o
262
341
  }));
263
342
  }
264
- if (t.strategy === c.strategy) {
265
- const i = this.store.getActivePredictiveAlgorithms;
266
- i.length > 0 && (i.some(
267
- (u) => u.value === c.strategy
268
- ) || (r = i[0].value, e.strategy = r));
343
+ if (t.strategy === a.strategy) {
344
+ const s = this.store.getActivePredictiveAlgorithms;
345
+ s.length > 0 && (s.some(
346
+ (d) => d.value === a.strategy
347
+ ) || (r = s[0].value, e.strategy = r));
269
348
  }
270
- if (t.language === c.language) {
271
- const i = this.store.getLanguages;
272
- i.length > 0 && (i.some(
273
- (u) => u.value === c.language
274
- ) || (n = i[0].value, e.language = n));
349
+ if (t.language === a.language) {
350
+ const s = this.store.getLanguages;
351
+ s.length > 0 && (s.some(
352
+ (d) => d.value === a.language
353
+ ) || (i = s[0].value, e.language = i));
275
354
  }
276
- !o && !r && !n || (h.updateConfig(
355
+ !o && !r && !i || (c.updateConfig(
277
356
  this.api,
278
357
  this.currentNode,
279
358
  e,
280
359
  "Applied smart defaults"
281
- ), o && e.currency && L({
360
+ ), o && e.currency && A({
282
361
  currentNode: this.currentNode,
283
362
  documentModifier: this.api.getDocumentModifier(),
284
363
  currency: e.currency
@@ -288,24 +367,24 @@ class Q extends g {
288
367
  name: o,
289
368
  value: o,
290
369
  symbol: o,
291
- alignment: c.currency.alignment === "before" ? "0" : "1",
292
- decimalCount: c.currency.decimalCount.toString(),
293
- decimalSeparator: c.currency.decimalSeparator,
294
- thousandSeparator: c.currency.thousandSeparator
370
+ alignment: a.currency.alignment === "before" ? "0" : "1",
371
+ decimalCount: a.currency.decimalCount.toString(),
372
+ decimalSeparator: a.currency.decimalSeparator,
373
+ thousandSeparator: a.currency.thousandSeparator
295
374
  }
296
375
  } : {},
297
376
  ...r ? { strategy: r } : {},
298
- ...n ? { language: n } : {}
377
+ ...i ? { language: i } : {}
299
378
  }, { triggerRefetch: !1 }));
300
379
  }
301
380
  /**
302
381
  * Reads the recommendation-id attribute from the block element within the node
303
382
  */
304
383
  _getRecommendationIdFromNode(t) {
305
- const e = k(t);
384
+ const e = v(t);
306
385
  if (!e || !("getAttribute" in e))
307
386
  return null;
308
- const o = e.getAttribute(v);
387
+ const o = e.getAttribute(I);
309
388
  if (!o)
310
389
  return null;
311
390
  const r = parseInt(o);
@@ -328,64 +407,52 @@ class Q extends g {
328
407
  const { store: t } = this;
329
408
  let e = t.recommendationProducts, o = t.$state.configVersion, r = t.currentRecommendationId;
330
409
  this.storeUnsubscription = t.$subscribe(() => {
331
- const n = t.currentRecommendationId;
332
- if (n !== r) {
333
- r = n, e = t.recommendationProducts, o = t.$state.configVersion;
410
+ const i = t.currentRecommendationId;
411
+ if (i !== r) {
412
+ r = i, e = t.recommendationProducts, o = t.$state.configVersion;
334
413
  return;
335
414
  }
336
- const i = t.$state.configVersion;
337
- i !== o && (o = i, this._persistFiltersToNodeConfig(), this._debouncedFetchProducts());
338
- const a = t.recommendationProducts, u = a !== e, C = Array.isArray(a) && a.length > 0;
339
- u && C && (e = a, this._debouncedRegenerateWithProducts());
415
+ const s = t.$state.configVersion;
416
+ s !== o && (o = s, this._capturePendingNodeConfigWrite(), this._debouncedFetchProducts());
417
+ const u = t.recommendationProducts, d = u !== e, g = Array.isArray(u) && u.length > 0;
418
+ d && g && (e = u, this._debouncedRegenerateWithProducts());
340
419
  });
341
420
  }
342
- /**
343
- * Persists the current filter state from Pinia store to the Stripo node config.
344
- * This ensures filters survive template save/reload cycles.
345
- */
346
- _persistFiltersToNodeConfig() {
347
- if (!this.currentNode || !this.api)
348
- return;
349
- const { filters: t } = this.store.recommendationConfigs, e = h.getConfig(this.currentNode).filters;
350
- JSON.stringify(e) !== JSON.stringify(t) && h.updateConfig(
351
- this.api,
352
- this.currentNode,
353
- { filters: t },
354
- "Update recommendation filters"
355
- );
356
- }
357
421
  }
358
422
  export {
359
- tt as ALGORITHM_CONTROL_ID,
360
- N as AlgorithmControl,
361
- w as CONTROL_BLOCK_ID,
362
- ot as CURRENCY_CONTROL_ID,
363
- R as CurrencyControl,
364
- nt as FILTERS_CONTROL_ID,
365
- I as FiltersControl,
366
- st as LAYOUT_ORIENTATION_CONTROL_ID,
367
- lt as LOCALE_CONTROL_ID,
368
- _ as LayoutOrientationControl,
369
- b as LocaleControl,
370
- ut as PRICE_PLACEMENT_CONTROL_ID,
371
- ht as PRODUCT_COUNT_CONTROL_ID,
372
- Ct as PRODUCT_LAYOUT_CONTROL_ID,
373
- T as PricePlacementControl,
374
- O as ProductCountControl,
375
- P as ProductLayoutControl,
376
- Q as RecommendationBlockControl,
377
- pt as SHUFFLE_CONTROL_ID,
378
- S as ShuffleControl,
379
- yt as adjustProductsToSize,
380
- Nt as formatProductPrice,
381
- k as getBlockElement,
382
- Rt as getCardComposition,
383
- It as getCurrentLayout,
384
- D as isPartnerManagedBlock,
385
- _t as regenerateMobileProductRows,
386
- A as regenerateProductRowsWithStyles,
387
- L as setCurrencyAttributes,
388
- bt as updatePricesInPlace,
389
- E as updateProductContentInPlace,
390
- Tt as updateSingleProductContent
423
+ ut as ALGORITHM_CONTROL_ID,
424
+ T as AlgorithmControl,
425
+ $ as CONTROL_BLOCK_ID,
426
+ ht as CURRENCY_CONTROL_ID,
427
+ P as CurrencyControl,
428
+ gt as FILTERS_CONTROL_ID,
429
+ S as FiltersControl,
430
+ Ct as LAYOUT_ORIENTATION_CONTROL_ID,
431
+ yt as LOCALE_CONTROL_ID,
432
+ O as LayoutOrientationControl,
433
+ L as LocaleControl,
434
+ _t as PRICE_PLACEMENT_CONTROL_ID,
435
+ Rt as PRODUCT_COUNT_CONTROL_ID,
436
+ Tt as PRODUCT_LAYOUT_CONTROL_ID,
437
+ E as PricePlacementControl,
438
+ k as ProductCountControl,
439
+ F as ProductLayoutControl,
440
+ at as RecommendationBlockControl,
441
+ St as SHUFFLE_CONTROL_ID,
442
+ Lt as STRATEGY_CONTROL_ID,
443
+ D as ShuffleControl,
444
+ w as StrategyControl,
445
+ kt as adjustProductsToSize,
446
+ Ft as formatProductPrice,
447
+ v as getBlockElement,
448
+ Dt as getCardComposition,
449
+ wt as getCurrentLayout,
450
+ At as getMainContainerTbody,
451
+ x as isPartnerManagedBlock,
452
+ vt as regenerateMobileProductRows,
453
+ U as regenerateProductRowsWithStyles,
454
+ A as setCurrencyAttributes,
455
+ xt as updatePricesInPlace,
456
+ B as updateProductContentInPlace,
457
+ Bt as updateSingleProductContent
391
458
  };