@useinsider/guido 2.1.0-beta.f869a80 → 2.1.0-beta.f9ab899

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 (75) hide show
  1. package/dist/@types/config/schemas.js +1 -1
  2. package/dist/components/organisms/base/Toaster.vue.js +4 -4
  3. package/dist/components/organisms/base/Toaster.vue2.js +12 -9
  4. package/dist/components/organisms/email-preview/desktop-preview/EmailSizeIndicator.vue.js +5 -5
  5. package/dist/components/organisms/email-preview/desktop-preview/EmailSizeIndicator.vue2.js +2 -2
  6. package/dist/components/organisms/extensions/recommendation/FilterItem.vue.js +13 -11
  7. package/dist/components/organisms/extensions/recommendation/FilterItem.vue2.js +23 -54
  8. package/dist/components/organisms/extensions/recommendation/FilterSelectionDrawer.vue.js +5 -7
  9. package/dist/components/organisms/extensions/recommendation/FilterSelectionDrawer.vue2.js +21 -34
  10. package/dist/components/organisms/extensions/recommendation/Filters.vue.js +11 -11
  11. package/dist/components/organisms/extensions/recommendation/Filters.vue2.js +36 -48
  12. package/dist/components/organisms/extensions/recommendation/LogicAdapter.vue2.js +9 -11
  13. package/dist/components/organisms/unsubscribe/UnsubscribePageSelection.vue.js +1 -1
  14. package/dist/components/organisms/unsubscribe/UnsubscribePageSelection.vue2.js +19 -19
  15. package/dist/composables/useRecommendation.js +9 -9
  16. package/dist/composables/useStripo.js +25 -23
  17. package/dist/composables/useVersionHistoryApi.js +1 -1
  18. package/dist/config/i18n/en/index.js +11 -0
  19. package/dist/config/i18n/en/labels.json.js +7 -0
  20. package/dist/config/i18n/en/toasters.json.js +56 -0
  21. package/dist/config/i18n/en/tooltips.json.js +82 -0
  22. package/dist/config/i18n/index.js +7 -0
  23. package/dist/config/migrator/itemsBlockMigrator.js +65 -64
  24. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +36 -33
  25. package/dist/extensions/Blocks/Recommendation/constants/layout.js +16 -14
  26. package/dist/extensions/Blocks/Recommendation/constants/selectors.js +13 -12
  27. package/dist/extensions/Blocks/Recommendation/controls/button/index.js +9 -9
  28. package/dist/extensions/Blocks/Recommendation/controls/image/index.js +1 -1
  29. package/dist/extensions/Blocks/Recommendation/controls/layout/index.js +37 -27
  30. package/dist/extensions/Blocks/Recommendation/controls/main/algorithm.js +16 -16
  31. package/dist/extensions/Blocks/Recommendation/controls/main/currency.js +30 -32
  32. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +177 -125
  33. package/dist/extensions/Blocks/Recommendation/controls/main/locale.js +9 -9
  34. package/dist/extensions/Blocks/Recommendation/controls/main/productLayout.js +46 -38
  35. package/dist/extensions/Blocks/Recommendation/controls/main/shuffle.js +16 -16
  36. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +269 -215
  37. package/dist/extensions/Blocks/Recommendation/controls/name/index.js +10 -10
  38. package/dist/extensions/Blocks/Recommendation/controls/name/textTrim.js +5 -5
  39. package/dist/extensions/Blocks/Recommendation/controls/oldPrice/index.js +14 -14
  40. package/dist/extensions/Blocks/Recommendation/controls/omnibusDiscount/index.js +9 -9
  41. package/dist/extensions/Blocks/Recommendation/controls/omnibusDiscount/textAfter.js +3 -3
  42. package/dist/extensions/Blocks/Recommendation/controls/omnibusDiscount/textBefore.js +1 -1
  43. package/dist/extensions/Blocks/Recommendation/controls/omnibusPrice/index.js +9 -9
  44. package/dist/extensions/Blocks/Recommendation/controls/omnibusPrice/textAfter.js +3 -3
  45. package/dist/extensions/Blocks/Recommendation/controls/omnibusPrice/textBefore.js +3 -3
  46. package/dist/extensions/Blocks/Recommendation/controls/price/index.js +3 -3
  47. package/dist/extensions/Blocks/Recommendation/controls/spacing/index.js +225 -102
  48. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +123 -128
  49. package/dist/extensions/Blocks/Recommendation/utils/filterUtil.js +8 -8
  50. package/dist/extensions/Blocks/Unsubscribe/block.js +29 -29
  51. package/dist/extensions/Blocks/Unsubscribe/control.js +12 -9
  52. package/dist/extensions/Blocks/Unsubscribe/elements/preview.js +13 -11
  53. package/dist/extensions/Blocks/Unsubscribe/styles.css.js +31 -1
  54. package/dist/guido.css +1 -1
  55. package/dist/src/components/organisms/extensions/recommendation/FilterItem.vue.d.ts +0 -1
  56. package/dist/src/components/organisms/extensions/recommendation/Filters.vue.d.ts +1 -17
  57. package/dist/src/config/i18n/en/index.d.ts +1 -0
  58. package/dist/src/config/i18n/index.d.ts +16 -0
  59. package/dist/src/extensions/Blocks/Recommendation/constants/defaultConfig.d.ts +6 -0
  60. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +3 -3
  61. package/dist/src/extensions/Blocks/Recommendation/constants/layout.d.ts +6 -2
  62. package/dist/src/extensions/Blocks/Recommendation/constants/selectors.d.ts +6 -1
  63. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +33 -15
  64. package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +24 -14
  65. package/dist/src/extensions/Blocks/Recommendation/controls/spacing/index.d.ts +49 -17
  66. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +3 -18
  67. package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +8 -0
  68. package/dist/src/extensions/Blocks/Unsubscribe/control.d.ts +1 -0
  69. package/dist/static/styles/components/notification.css.js +18 -0
  70. package/dist/static/styles/components/tools.css.js +6 -2
  71. package/dist/static/styles/variables.css.js +2 -0
  72. package/dist/stores/unsubscribe.js +37 -34
  73. package/package.json +1 -1
  74. package/dist/extensions/Blocks/Recommendation/validation/filterSchema.js +0 -29
  75. package/dist/src/extensions/Blocks/Recommendation/validation/filterSchema.d.ts +0 -15
@@ -1,65 +1,77 @@
1
- var m = Object.defineProperty;
2
- var h = (c, s, t) => s in c ? m(c, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : c[s] = t;
3
- var n = (c, s, t) => h(c, typeof s != "symbol" ? s + "" : s, t);
4
- import { CommonControl as f } from "../../../common-control.js";
5
- import { RecommendationConfigService as l } from "../../services/configService.js";
6
- import { useRecommendationExtensionStore as C } from "../../store/recommendation.js";
7
- import { AlgorithmControl as p } from "./algorithm.js";
8
- import { ALGORITHM_CONTROL_ID as W } from "./algorithm.js";
9
- import { CurrencyControl as g } from "./currency.js";
10
- import { CURRENCY_CONTROL_ID as H } from "./currency.js";
11
- import { FiltersControl as R } from "./filters.js";
12
- import { FILTERS_CONTROL_ID as j } from "./filters.js";
13
- import { LocaleControl as N } from "./locale.js";
14
- import { LOCALE_CONTROL_ID as K } from "./locale.js";
15
- import { ProductLayoutControl as y } from "./productLayout.js";
16
- import { PRODUCT_LAYOUT_CONTROL_ID as J } from "./productLayout.js";
17
- import { ShuffleControl as _ } from "./shuffle.js";
18
- import { SHUFFLE_CONTROL_ID as X } from "./shuffle.js";
19
- import { regenerateProductRowsWithStyles as b, getBlockElement as I, updateProductContentInPlace as P } from "./utils.js";
20
- import { formatProductPrice as tt, getCardComposition as et, getCurrentLayout as ot, reapplySpacing as rt, regenerateMobileProductRows as it, regenerateProductRows as nt, setCurrencyAttributes as st, updatePricesInPlace as ct, updateSingleProductContent as at } from "./utils.js";
21
- import { useDebounceFn as u } from "../../../../../node_modules/@vueuse/shared/index.js";
22
- const T = "recommendation-id", S = "ui-elements-recommendation-block";
23
- class z extends f {
1
+ var g = Object.defineProperty;
2
+ var C = (d, c, t) => c in d ? g(d, c, { enumerable: !0, configurable: !0, writable: !0, value: t }) : d[c] = t;
3
+ var i = (d, c, t) => C(d, typeof c != "symbol" ? c + "" : c, t);
4
+ import { CommonControl as p } from "../../../common-control.js";
5
+ import { DEFAULT_NODE_CONFIG as a } from "../../constants/defaultConfig.js";
6
+ import { RecommendationConfigService as m } from "../../services/configService.js";
7
+ import { useRecommendationExtensionStore as y } from "../../store/recommendation.js";
8
+ import { AlgorithmControl as R } from "./algorithm.js";
9
+ import { ALGORITHM_CONTROL_ID as H } from "./algorithm.js";
10
+ import { CurrencyControl as b } from "./currency.js";
11
+ import { CURRENCY_CONTROL_ID as K } from "./currency.js";
12
+ import { FiltersControl as N } from "./filters.js";
13
+ import { FILTERS_CONTROL_ID as J } from "./filters.js";
14
+ import { LocaleControl as _ } from "./locale.js";
15
+ import { LOCALE_CONTROL_ID as X } from "./locale.js";
16
+ import { ProductLayoutControl as S } from "./productLayout.js";
17
+ import { PRODUCT_LAYOUT_CONTROL_ID as tt } from "./productLayout.js";
18
+ import { ShuffleControl as I } from "./shuffle.js";
19
+ import { SHUFFLE_CONTROL_ID as ot } from "./shuffle.js";
20
+ import { getBlockElement as P, updateProductContentInPlace as L, regenerateProductRowsWithStyles as T } from "./utils.js";
21
+ import { adjustProductsToSize as nt, formatProductPrice as st, getCardComposition as it, getCurrentLayout as at, reapplySpacing as ct, regenerateMobileProductRows as lt, regenerateProductRows as ut, setCurrencyAttributes as dt, updatePricesInPlace as mt, updateSingleProductContent as ht } from "./utils.js";
22
+ import { useDebounceFn as h } from "../../../../../node_modules/@vueuse/shared/index.js";
23
+ const k = "recommendation-id", D = "ui-elements-recommendation-block";
24
+ class W extends p {
24
25
  constructor() {
25
26
  super(...arguments);
26
- n(this, "store", C());
27
- n(this, "storeUnsubscription", () => {
27
+ i(this, "store", y());
28
+ i(this, "storeUnsubscription", () => {
28
29
  });
29
30
  // Sub-control instances for lifecycle management
30
- n(this, "algorithmControl", null);
31
- n(this, "localeControl", null);
32
- n(this, "currencyControl", null);
33
- n(this, "productLayoutControl", null);
34
- n(this, "filtersControl", null);
35
- n(this, "shuffleControl", null);
31
+ i(this, "algorithmControl", null);
32
+ i(this, "localeControl", null);
33
+ i(this, "currencyControl", null);
34
+ i(this, "productLayoutControl", null);
35
+ i(this, "filtersControl", null);
36
+ i(this, "shuffleControl", null);
36
37
  /**
37
38
  * Debounced product fetch to prevent rapid API calls during config changes
38
39
  */
39
- n(this, "_debouncedFetchProducts", u(() => {
40
+ i(this, "_debouncedFetchProducts", h(() => {
40
41
  this.store.fetchRecommendationProducts();
41
42
  }, 500));
42
43
  /**
43
- * Debounced regeneration when products arrive from API
44
- * Tries in-place update first to preserve styles, falls back to full regeneration
44
+ * Debounced content update when products arrive from API.
45
+ *
46
+ * Tries in-place update first (preserves user-applied styles) — this succeeds
47
+ * when the product count matches the DOM (algorithm/locale/currency changes).
48
+ *
49
+ * Falls back to full regeneration when product count differs from DOM — this
50
+ * happens after "Number of Products" changes where the DOM still has the old
51
+ * count. The store pads products to the configured size, so in-place only
52
+ * fails when the size actually changed.
45
53
  */
46
- n(this, "_debouncedRegenerateWithProducts", u(() => {
54
+ i(this, "_debouncedRegenerateWithProducts", h(() => {
47
55
  const t = this.store.recommendationProducts;
48
56
  if (!this.currentNode || !this.api)
49
57
  return;
50
58
  const e = this.api.getDocumentModifier();
51
- P({
59
+ L({
52
60
  currentNode: this.currentNode,
53
61
  documentModifier: e,
54
62
  products: t
55
- }) || this._regenerateWithProducts(t);
63
+ }) || T({
64
+ currentNode: this.currentNode,
65
+ documentModifier: e,
66
+ products: t
67
+ });
56
68
  }, 100));
57
69
  }
58
70
  getId() {
59
- return S;
71
+ return D;
60
72
  }
61
73
  getTemplate() {
62
- return this.algorithmControl = new p(), this.localeControl = new N(), this.currencyControl = new g(), this.productLayoutControl = new y(), this.filtersControl = new R(), this.shuffleControl = new _(), `
74
+ return this.algorithmControl = new R(), this.localeControl = new _(), this.currencyControl = new b(), this.productLayoutControl = new S(), this.filtersControl = new N(), this.shuffleControl = new I(), `
63
75
  <div class="recommendation-controls-container">
64
76
  ${this.algorithmControl.getTemplate()}
65
77
  ${this.localeControl.getTemplate()}
@@ -79,35 +91,20 @@ class z extends f {
79
91
  }
80
92
  await this._fetchBlockData(t), this._initializeSubControls();
81
93
  }
82
- /**
83
- * Immediately regenerate products with styles (no debounce)
84
- * Used for initial load after fetch completes
85
- */
86
- _regenerateWithProducts(t) {
87
- if (!this.currentNode || !this.api) {
88
- console.warn("[Recommendation] Cannot regenerate - missing currentNode or api");
89
- return;
90
- }
91
- b({
92
- currentNode: this.currentNode,
93
- documentModifier: this.api.getDocumentModifier(),
94
- products: t
95
- });
96
- }
97
94
  onTemplateNodeUpdated(t) {
98
- var r;
95
+ var s;
99
96
  super.onTemplateNodeUpdated(t);
100
97
  const e = this._getRecommendationIdFromNode(t);
101
- e !== null && e !== this.store.currentRecommendationId && this.store.setCurrentBlock(e), this._syncNodeConfigToStore(), e !== null && !((r = this.store.blockStates[e]) != null && r.isInitialized) && this._fetchBlockData(e), [
98
+ e !== null && e !== this.store.currentRecommendationId && this.store.setCurrentBlock(e), this._syncNodeConfigToStore(), e !== null && !((s = this.store.blockStates[e]) != null && s.isInitialized) && this._fetchBlockData(e), [
102
99
  this.algorithmControl,
103
100
  this.localeControl,
104
101
  this.currencyControl,
105
102
  this.productLayoutControl,
106
103
  this.filtersControl,
107
104
  this.shuffleControl
108
- ].forEach((i) => {
109
- var a;
110
- i != null && i.api && (i.currentNode = t, (a = i.onTemplateNodeUpdated) == null || a.call(i, t));
105
+ ].forEach((r) => {
106
+ var n;
107
+ r != null && r.api && (r.currentNode = t, (n = r.onTemplateNodeUpdated) == null || n.call(r, t));
111
108
  });
112
109
  }
113
110
  onDestroy() {
@@ -152,17 +149,13 @@ class z extends f {
152
149
  * values are being prepared for the upcoming initial fetch.
153
150
  */
154
151
  _syncNodeConfigToStore() {
155
- var r;
156
- const t = l.getConfig(this.currentNode), e = this.store.currentRecommendationId, o = e !== null && ((r = this.store.blockStates[e]) == null ? void 0 : r.isInitialized);
152
+ const t = m.getConfig(this.currentNode);
157
153
  this.store.patchCurrentBlockConfig({
158
154
  strategy: t.strategy,
159
155
  language: t.language,
160
156
  size: t.size,
161
157
  productIds: t.productIds,
162
- // Only sync filters from node config during initial load.
163
- // After initialization, the Pinia store is the source of truth
164
- // for filters (edited via the filter drawer).
165
- ...o ? {} : { filters: t.filters },
158
+ filters: t.filters,
166
159
  shuffleProducts: t.shuffleProducts,
167
160
  currencySettings: {
168
161
  name: t.currency.code,
@@ -176,35 +169,97 @@ class z extends f {
176
169
  }, { triggerRefetch: !1 });
177
170
  }
178
171
  /**
179
- * Fetches initial data for a block (filters, algorithms, products).
172
+ * Fetches initial data for a block in three phases:
173
+ * 1. Shared reference data (algorithms, currencies, filters) — parallel
174
+ * 2. Smart defaults for new blocks (currency, algorithm) — sequential
175
+ * 3. Product data with correct defaults — sequential
176
+ *
180
177
  * Shared by onRender() and onTemplateNodeUpdated() to avoid duplication.
181
178
  * Marks the block as initialized to prevent redundant fetches on re-selection.
182
179
  */
183
180
  async _fetchBlockData(t) {
184
181
  t !== null && this.store.markBlockInitialized(t), (await Promise.allSettled([
185
- this.store.fetchRecommendationFilters(),
186
182
  this.store.fetchRecommendationCreateData(),
187
- this.store.fetchRecommendationProducts()
188
- ])).forEach((o, r) => {
189
- o.status === "rejected" && console.warn(`Recommendation block: ${[
190
- "fetchRecommendationFilters",
191
- "fetchRecommendationCreateData",
192
- "fetchRecommendationProducts"
193
- ][r]} failed`, o.reason);
194
- });
183
+ this.store.fetchRecommendationFilters()
184
+ ])).forEach((o, s) => {
185
+ o.status === "rejected" && console.warn(`Recommendation block: ${["fetchRecommendationCreateData", "fetchRecommendationFilters"][s]} failed`, o.reason);
186
+ }), this._applySmartDefaults();
187
+ try {
188
+ await this.store.fetchRecommendationProducts();
189
+ } catch (o) {
190
+ console.warn("Recommendation block: fetchRecommendationProducts failed", o);
191
+ }
192
+ }
193
+ /**
194
+ * Applies smart defaults for newly dropped blocks.
195
+ *
196
+ * For new blocks (config still matches hardcoded defaults), validates that
197
+ * the default currency and algorithm are available from the API response.
198
+ * If not, falls back to the first available option.
199
+ *
200
+ * Saved templates with user-customized config are left unchanged because
201
+ * their values won't match the hardcoded defaults.
202
+ */
203
+ _applySmartDefaults() {
204
+ if (!this.currentNode || !this.api)
205
+ return;
206
+ const t = m.getConfig(this.currentNode), e = {};
207
+ let o = null, s = null, r = null;
208
+ if (t.currency.code === a.currency.code) {
209
+ const { currencyList: n } = this.store;
210
+ n.length > 0 && (n.some(
211
+ (u) => u.value === `price.${a.currency.code}`
212
+ ) || (o = n[0].value.replace("price.", ""), e.currency = {
213
+ ...a.currency,
214
+ code: o,
215
+ symbol: o
216
+ }));
217
+ }
218
+ if (t.strategy === a.strategy) {
219
+ const n = this.store.getActivePredictiveAlgorithms;
220
+ n.length > 0 && (n.some(
221
+ (u) => u.value === a.strategy
222
+ ) || (s = n[0].value, e.strategy = s));
223
+ }
224
+ if (t.language === a.language) {
225
+ const n = this.store.getLanguages;
226
+ n.length > 0 && (n.some(
227
+ (u) => u.value === a.language
228
+ ) || (r = n[0].value, e.language = r));
229
+ }
230
+ !o && !s && !r || (m.updateConfig(
231
+ this.api,
232
+ this.currentNode,
233
+ e,
234
+ "Applied smart defaults"
235
+ ), this.store.patchCurrentBlockConfig({
236
+ ...o ? {
237
+ currencySettings: {
238
+ name: o,
239
+ value: o,
240
+ symbol: o,
241
+ alignment: a.currency.alignment === "before" ? "0" : "1",
242
+ decimalCount: a.currency.decimalCount.toString(),
243
+ decimalSeparator: a.currency.decimalSeparator,
244
+ thousandSeparator: a.currency.thousandSeparator
245
+ }
246
+ } : {},
247
+ ...s ? { strategy: s } : {},
248
+ ...r ? { language: r } : {}
249
+ }, { triggerRefetch: !1 }));
195
250
  }
196
251
  /**
197
252
  * Reads the recommendation-id attribute from the block element within the node
198
253
  */
199
254
  _getRecommendationIdFromNode(t) {
200
- const e = I(t);
255
+ const e = P(t);
201
256
  if (!e || !("getAttribute" in e))
202
257
  return null;
203
- const o = e.getAttribute(T);
258
+ const o = e.getAttribute(k);
204
259
  if (!o)
205
260
  return null;
206
- const r = parseInt(o);
207
- return Number.isNaN(r) ? null : r;
261
+ const s = parseInt(o);
262
+ return Number.isNaN(s) ? null : s;
208
263
  }
209
264
  /**
210
265
  * Listen to store changes that require product refresh or regeneration.
@@ -212,58 +267,55 @@ class z extends f {
212
267
  * Uses configVersion counter (incremented only by patchCurrentBlockConfig)
213
268
  * to distinguish user-initiated config changes from internal mutations
214
269
  * (e.g., fetchRecommendationCreateData setting preferred currency).
270
+ *
271
+ * Tracks currentRecommendationId to detect block switches. When the user
272
+ * selects a different recommendation block, the proxy getters (e.g.,
273
+ * recommendationProducts) return the new block's data — a different array
274
+ * reference that would be falsely detected as "new products arrived".
275
+ * We skip that tick and update tracking references instead.
215
276
  */
216
277
  _listenStateUpdates() {
217
278
  const { store: t } = this;
218
- let e = t.recommendationProducts, o = t.$state.configVersion;
279
+ let e = t.recommendationProducts, o = t.$state.configVersion, s = t.currentRecommendationId;
219
280
  this.storeUnsubscription = t.$subscribe(() => {
220
- const r = t.$state.configVersion;
221
- r !== o && (o = r, this._persistFiltersToNodeConfig(), this._debouncedFetchProducts());
222
- const i = t.recommendationProducts, a = i !== e, d = Array.isArray(i) && i.length > 0;
223
- a && d && (e = i, this._debouncedRegenerateWithProducts());
281
+ const r = t.currentRecommendationId;
282
+ if (r !== s) {
283
+ s = r, e = t.recommendationProducts, o = t.$state.configVersion;
284
+ return;
285
+ }
286
+ const n = t.$state.configVersion;
287
+ n !== o && (o = n, this._debouncedFetchProducts());
288
+ const l = t.recommendationProducts, u = l !== e, f = Array.isArray(l) && l.length > 0;
289
+ u && f && (e = l, this._debouncedRegenerateWithProducts());
224
290
  });
225
291
  }
226
- /**
227
- * Persists the current filter state from Pinia store to the Stripo node config.
228
- * This ensures filters survive template save/reload cycles.
229
- */
230
- _persistFiltersToNodeConfig() {
231
- if (!this.currentNode || !this.api)
232
- return;
233
- const { filters: t } = this.store.recommendationConfigs;
234
- l.updateConfig(
235
- this.api,
236
- this.currentNode,
237
- { filters: t },
238
- "Update recommendation filters"
239
- );
240
- }
241
292
  }
242
293
  export {
243
- W as ALGORITHM_CONTROL_ID,
244
- p as AlgorithmControl,
245
- S as CONTROL_BLOCK_ID,
246
- H as CURRENCY_CONTROL_ID,
247
- g as CurrencyControl,
248
- j as FILTERS_CONTROL_ID,
249
- R as FiltersControl,
250
- K as LOCALE_CONTROL_ID,
251
- N as LocaleControl,
252
- J as PRODUCT_LAYOUT_CONTROL_ID,
253
- y as ProductLayoutControl,
254
- z as RecommendationBlockControl,
255
- X as SHUFFLE_CONTROL_ID,
256
- _ as ShuffleControl,
257
- tt as formatProductPrice,
258
- I as getBlockElement,
259
- et as getCardComposition,
260
- ot as getCurrentLayout,
261
- rt as reapplySpacing,
262
- it as regenerateMobileProductRows,
263
- nt as regenerateProductRows,
264
- b as regenerateProductRowsWithStyles,
265
- st as setCurrencyAttributes,
266
- ct as updatePricesInPlace,
267
- P as updateProductContentInPlace,
268
- at as updateSingleProductContent
294
+ H as ALGORITHM_CONTROL_ID,
295
+ R as AlgorithmControl,
296
+ D as CONTROL_BLOCK_ID,
297
+ K as CURRENCY_CONTROL_ID,
298
+ b as CurrencyControl,
299
+ J as FILTERS_CONTROL_ID,
300
+ N as FiltersControl,
301
+ X as LOCALE_CONTROL_ID,
302
+ _ as LocaleControl,
303
+ tt as PRODUCT_LAYOUT_CONTROL_ID,
304
+ S as ProductLayoutControl,
305
+ W as RecommendationBlockControl,
306
+ ot as SHUFFLE_CONTROL_ID,
307
+ I as ShuffleControl,
308
+ nt as adjustProductsToSize,
309
+ st as formatProductPrice,
310
+ P as getBlockElement,
311
+ it as getCardComposition,
312
+ at as getCurrentLayout,
313
+ ct as reapplySpacing,
314
+ lt as regenerateMobileProductRows,
315
+ ut as regenerateProductRows,
316
+ T as regenerateProductRowsWithStyles,
317
+ dt as setCurrencyAttributes,
318
+ mt as updatePricesInPlace,
319
+ L as updateProductContentInPlace,
320
+ ht as updateSingleProductContent
269
321
  };
@@ -2,20 +2,20 @@ var s = Object.defineProperty;
2
2
  var r = (o, t, e) => t in o ? s(o, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[t] = e;
3
3
  var a = (o, t, e) => r(o, typeof t != "symbol" ? t + "" : t, e);
4
4
  import { UEAttr as l } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
5
- import { CommonControl as m } from "../../../common-control.js";
5
+ import { CommonControl as c } from "../../../common-control.js";
6
6
  import { RecommendationConfigService as i } from "../../services/configService.js";
7
- import { useRecommendationExtensionStore as c } from "../../store/recommendation.js";
8
- const g = "recommendation-locale-control", n = {
7
+ import { useRecommendationExtensionStore as g } from "../../store/recommendation.js";
8
+ const m = "recommendation-locale-control", n = {
9
9
  LOCALE: "language"
10
10
  };
11
- class C extends m {
11
+ class E extends c {
12
12
  constructor() {
13
13
  super(...arguments);
14
14
  // Store is used ONLY for API-fetched data (language options), not for config
15
- a(this, "store", c());
15
+ a(this, "store", g());
16
16
  }
17
17
  getId() {
18
- return g;
18
+ return m;
19
19
  }
20
20
  getTemplate() {
21
21
  return `
@@ -51,7 +51,7 @@ class C extends m {
51
51
  );
52
52
  }
53
53
  _onLocaleChange(e) {
54
- this.currentNode && (i.updateConfig(
54
+ !this.currentNode || i.getConfig(this.currentNode).language === e || (i.updateConfig(
55
55
  this.api,
56
56
  this.currentNode,
57
57
  { language: e },
@@ -65,6 +65,6 @@ class C extends m {
65
65
  }
66
66
  }
67
67
  export {
68
- g as LOCALE_CONTROL_ID,
69
- C as LocaleControl
68
+ m as LOCALE_CONTROL_ID,
69
+ E as LocaleControl
70
70
  };
@@ -1,41 +1,41 @@
1
- var _ = Object.defineProperty;
2
- var c = (i, o, t) => o in i ? _(i, o, { enumerable: !0, configurable: !0, writable: !0, value: t }) : i[o] = t;
3
- var d = (i, o, t) => c(i, typeof o != "symbol" ? o + "" : o, t);
4
- import { EditorStatePropertyType as u, PreviewDeviceMode as R } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
5
- import { CommonControl as h } from "../../../common-control.js";
6
- import { MAX_PRODUCT_COUNT as C, MAX_PRODUCTS_PER_ROW as p, MAX_MOBILE_PRODUCTS_PER_ROW as m } from "../../constants/layout.js";
7
- import { RecommendationConfigService as s } from "../../services/configService.js";
1
+ var u = Object.defineProperty;
2
+ var _ = (n, r, t) => r in n ? u(n, r, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[r] = t;
3
+ var a = (n, r, t) => _(n, typeof r != "symbol" ? r + "" : r, t);
4
+ import { EditorStatePropertyType as c, PreviewDeviceMode as C } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
5
+ import { CommonControl as R } from "../../../common-control.js";
6
+ import { MAX_PRODUCT_COUNT as h, MAX_PRODUCTS_PER_ROW as p, MAX_MOBILE_PRODUCTS_PER_ROW as g, DEFAULT_COLUMN_SPACING as m, DEFAULT_MOBILE_COLUMN_SPACING as O } from "../../constants/layout.js";
7
+ import { RecommendationConfigService as i } from "../../services/configService.js";
8
8
  import { useRecommendationExtensionStore as l } from "../../store/recommendation.js";
9
- import { ensureMobileCssRulesExist as O } from "../mobileLayout/cssRules.js";
10
- import { getCurrentLayout as I, regenerateMobileProductRows as g, regenerateProductRowsWithStyles as b } from "./utils.js";
11
- import { useDebounceFn as N } from "../../../../../node_modules/@vueuse/shared/index.js";
12
- const P = "recommendation-product-layout-control", e = {
9
+ import { ensureMobileCssRulesExist as I } from "../mobileLayout/cssRules.js";
10
+ import { getCurrentLayout as N, regenerateMobileProductRows as f, adjustProductsToSize as b, regenerateProductRowsWithStyles as P } from "./utils.js";
11
+ import { useDebounceFn as L } from "../../../../../node_modules/@vueuse/shared/index.js";
12
+ const M = "recommendation-product-layout-control", e = {
13
13
  PRODUCT_COUNT: "size",
14
14
  PRODUCT_IN_ROW: "cardsInRow",
15
15
  PRODUCT_IN_ROW_LABEL: "cardsInRowLabel",
16
16
  MOBILE_CARDS_IN_ROW: "mobileCardsInRow",
17
17
  MOBILE_CARDS_IN_ROW_LABEL: "mobileCardsInRowLabel"
18
18
  };
19
- class S extends h {
19
+ class V extends R {
20
20
  constructor() {
21
21
  super(...arguments);
22
22
  // Store is used for backward compatibility with product fetching and regeneration
23
- d(this, "store", l());
24
- d(this, "storeUnsubscription", () => {
23
+ a(this, "store", l());
24
+ a(this, "storeUnsubscription", () => {
25
25
  });
26
- d(this, "_debouncedRegenerateProductRows", N(() => {
26
+ a(this, "_debouncedRegenerateProductRows", L(() => {
27
27
  this._regenerateProductRows();
28
28
  }, 500));
29
29
  }
30
30
  getId() {
31
- return P;
31
+ return M;
32
32
  }
33
33
  getTemplate() {
34
34
  return `
35
35
  <div class="product-layout-control-container">
36
36
  ${this._GuTwoColumns([
37
37
  this._GuLabel({ text: "Number of Products" }),
38
- this._GuCounter({ name: e.PRODUCT_COUNT, maxValue: C }),
38
+ this._GuCounter({ name: e.PRODUCT_COUNT, maxValue: h }),
39
39
  this._GuLabel({
40
40
  text: "Products in One Row on Desktop",
41
41
  name: e.PRODUCT_IN_ROW_LABEL
@@ -47,7 +47,7 @@ class S extends h {
47
47
  }),
48
48
  this._GuCounter({
49
49
  name: e.MOBILE_CARDS_IN_ROW,
50
- maxValue: m
50
+ maxValue: g
51
51
  })
52
52
  ])}
53
53
  </div>
@@ -63,7 +63,7 @@ class S extends h {
63
63
  this.storeUnsubscription();
64
64
  }
65
65
  _setFormValues() {
66
- const t = s.getConfig(this.currentNode);
66
+ const t = i.getConfig(this.currentNode);
67
67
  this.api.updateValues({
68
68
  [e.PRODUCT_COUNT]: t.size,
69
69
  [e.PRODUCT_IN_ROW]: t.cardsInRow,
@@ -75,7 +75,7 @@ class S extends h {
75
75
  * using Stripo's EditorStatePropertyType API.
76
76
  */
77
77
  _isMobileMode() {
78
- return this.api.getEditorState()[u.previewDeviceMode] === R.MOBILE;
78
+ return this.api.getEditorState()[c.previewDeviceMode] === C.MOBILE;
79
79
  }
80
80
  /**
81
81
  * Updates counter visibility based on layout orientation and editor mode.
@@ -84,8 +84,8 @@ class S extends h {
84
84
  * - Grid + mobile mode: show mobile counter, hide desktop counter
85
85
  */
86
86
  _updateProductsInRowVisibility() {
87
- const r = (s.getConfig(this.currentNode).layout || I(this.currentNode)) === "grid", n = this._isMobileMode();
88
- this.api.setVisibility(e.PRODUCT_IN_ROW, r && !n), this.api.setVisibility(e.PRODUCT_IN_ROW_LABEL, r && !n), this.api.setVisibility(e.MOBILE_CARDS_IN_ROW, r && n), this.api.setVisibility(e.MOBILE_CARDS_IN_ROW_LABEL, r && n);
87
+ const o = (i.getConfig(this.currentNode).layout || N(this.currentNode)) === "grid", d = this._isMobileMode();
88
+ this.api.setVisibility(e.PRODUCT_IN_ROW, o && !d), this.api.setVisibility(e.PRODUCT_IN_ROW_LABEL, o && !d), this.api.setVisibility(e.MOBILE_CARDS_IN_ROW, o && d), this.api.setVisibility(e.MOBILE_CARDS_IN_ROW_LABEL, o && d);
89
89
  }
90
90
  /**
91
91
  * Subscribes to editor preview mode changes via Stripo API.
@@ -94,43 +94,51 @@ class S extends h {
94
94
  */
95
95
  _subscribeToEditorModeChanges() {
96
96
  this.api.onEditorStatePropUpdated(
97
- u.previewDeviceMode,
97
+ c.previewDeviceMode,
98
98
  () => {
99
99
  this._updateProductsInRowVisibility();
100
100
  }
101
101
  );
102
102
  }
103
103
  _onProductCountChange(t) {
104
- this.currentNode && (s.updateConfig(
104
+ !this.currentNode || i.getConfig(this.currentNode).size === t || (i.updateConfig(
105
105
  this.api,
106
106
  this.currentNode,
107
107
  { size: t },
108
108
  `Changed product count to ${t}`
109
- ), this.store.patchCurrentBlockConfig({ size: t }), this._debouncedRegenerateProductRows());
109
+ ), this.store.patchCurrentBlockConfig({ size: t }));
110
110
  }
111
111
  _onProductsInRowChange(t) {
112
- this.currentNode && (s.updateConfig(
112
+ if (!this.currentNode || i.getConfig(this.currentNode).cardsInRow === t)
113
+ return;
114
+ const o = t === 1 ? 0 : m;
115
+ i.updateConfig(
113
116
  this.api,
114
117
  this.currentNode,
115
- { cardsInRow: t },
118
+ { cardsInRow: t, columnSpacing: o },
116
119
  `Changed products per row to ${t}`
117
- ), this.store.patchCurrentBlockConfig({ cardsInRow: t }), this._debouncedRegenerateProductRows());
120
+ ), this.store.patchCurrentBlockConfig({ cardsInRow: t }, { triggerRefetch: !1 }), this._debouncedRegenerateProductRows();
118
121
  }
119
122
  _onMobileCardsInRowChange(t) {
120
- this.currentNode && (s.updateConfig(
123
+ if (!this.currentNode || i.getConfig(this.currentNode).mobileCardsInRow === t)
124
+ return;
125
+ const o = t === 1 ? 0 : O;
126
+ i.updateConfig(
121
127
  this.api,
122
128
  this.currentNode,
123
- { mobileCardsInRow: t },
129
+ { mobileCardsInRow: t, mobileColumnSpacing: o },
124
130
  `Changed mobile products per row to ${t}`
125
- ), O(this.api), g({
131
+ ), I(this.api), f({
126
132
  currentNode: this.currentNode,
127
133
  documentModifier: this.api.getDocumentModifier()
128
- }));
134
+ });
129
135
  }
130
136
  _regenerateProductRows() {
131
- b({
137
+ const t = i.getConfig(this.currentNode), s = parseInt(t.size) || 6, o = b(this.store.recommendationProducts, s);
138
+ P({
132
139
  currentNode: this.currentNode,
133
- documentModifier: this.api.getDocumentModifier()
140
+ documentModifier: this.api.getDocumentModifier(),
141
+ products: o
134
142
  });
135
143
  }
136
144
  _listenToFormUpdates() {
@@ -149,12 +157,12 @@ class S extends h {
149
157
  _listenStateUpdates() {
150
158
  let t = this.store.recommendationConfigs.orientation;
151
159
  this.storeUnsubscription = this.store.$subscribe(() => {
152
- const a = this.store.recommendationConfigs.orientation;
153
- a !== t && (t = a, this._updateProductsInRowVisibility());
160
+ const s = this.store.recommendationConfigs.orientation;
161
+ s !== t && (t = s, this._updateProductsInRowVisibility());
154
162
  });
155
163
  }
156
164
  }
157
165
  export {
158
- P as PRODUCT_LAYOUT_CONTROL_ID,
159
- S as ProductLayoutControl
166
+ M as PRODUCT_LAYOUT_CONTROL_ID,
167
+ V as ProductLayoutControl
160
168
  };