@useinsider/guido 3.21.0-beta.78e343a → 3.21.0-beta.8a9421f

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.
@@ -1,44 +1,46 @@
1
- var y = Object.defineProperty;
2
- var B = (a, c, t) => c in a ? y(a, c, { enumerable: !0, configurable: !0, writable: !0, value: t }) : a[c] = t;
3
- var d = (a, c, t) => B(a, typeof c != "symbol" ? c + "" : c, t);
1
+ var A = Object.defineProperty;
2
+ var D = (m, c, e) => c in m ? A(m, c, { enumerable: !0, configurable: !0, writable: !0, value: e }) : m[c] = e;
3
+ var u = (m, c, e) => D(m, typeof c != "symbol" ? c + "" : c, e);
4
4
  import { useConfig as g } from "../../../composables/useConfig.js";
5
- import { BlockId as C } from "../../../enums/block.js";
6
- import { getMigrationBannerHtml as A } from "../../../utils/migrationBannerHtml.js";
7
- import { Block as E, BlockCompositionType as S, ModificationDescription as p } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
8
- import { CURRENT_CONFIG_VERSION as N, PRE_RRS_CONFIG_VERSION as M } from "./constants/defaultConfig.js";
9
- import { RECOMMENDATION_ID_ATTR as m } from "./constants/selectors.js";
10
- import { ensureMobileFitRule as w } from "./controls/image/index.js";
11
- import { regenerateMobileProductRows as O } from "./controls/main/utils.js";
12
- import { ensureMobileCssRulesExist as I, setMobileLayoutOptOut as R, hasMobileLayoutOptOut as x } from "./controls/mobileLayout/cssRules.js";
13
- import { RecommendationConfigService as s } from "./services/configService.js";
14
- import { useRecommendationExtensionStore as h } from "./store/recommendation.js";
5
+ import { BlockId as b } from "../../../enums/block.js";
6
+ import { getMigrationBannerHtml as E } from "../../../utils/migrationBannerHtml.js";
7
+ import { Block as S, BlockCompositionType as v, ModificationDescription as _ } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
8
+ import { CURRENT_CONFIG_VERSION as N, PRE_RRS_CONFIG_VERSION as w } from "./constants/defaultConfig.js";
9
+ import { RECOMMENDATION_ID_ATTR as f } from "./constants/selectors.js";
10
+ import { regenerateMobileProductRows as M } from "./controls/main/utils.js";
11
+ import { ensureMobileCssRulesExist as I, setMobileLayoutOptOut as R, hasMobileLayoutOptOut as O } from "./controls/mobileLayout/cssRules.js";
12
+ import { RecommendationConfigService as a } from "./services/configService.js";
13
+ import { useRecommendationExtensionStore as p } from "./store/recommendation.js";
15
14
  import { getDefaultTemplate as T } from "./templates/grid/template.js";
16
- import { useRecommendationBlockWarning as F } from "./useRecommendationBlockWarning.js";
17
- import { registerNodeConfigWriter as H } from "./utils/nodeConfigWriter.js";
18
- import { refreshDuplicatedStrategyBlocks as $ } from "./utils/strategyCommit.js";
19
- const k = C.Recommendation, u = "recommendation-block-v2", b = "hide-price";
20
- let D = !1;
21
- class tt extends E {
15
+ import { useRecommendationBlockWarning as x } from "./useRecommendationBlockWarning.js";
16
+ import { registerNodeConfigWriter as k, readBlockNodeConfigs as $ } from "./utils/nodeConfigWriter.js";
17
+ import { refreshArrivedStrategyBlocks as q, resolveSourceConfig as H, refreshDuplicatedStrategyBlocks as F } from "./utils/strategyCommit.js";
18
+ const y = b.Recommendation, d = "recommendation-block-v2", C = "hide-price";
19
+ let B = !1;
20
+ class te extends S {
22
21
  constructor() {
23
22
  super();
24
23
  /**
25
24
  * Stores the ID generated in getTemplate() so onCreated() can reuse it.
26
25
  * This avoids generating a new (different) ID in onCreated().
27
26
  */
28
- d(this, "_pendingBlockId", null);
27
+ u(this, "_pendingBlockId", null);
29
28
  /** Ids already reset under their new name, so the deferred pass skips their stale snapshot. */
30
- d(this, "_resetSourceIds", /* @__PURE__ */ new Set());
29
+ u(this, "_resetSourceIds", /* @__PURE__ */ new Set());
31
30
  /** Ids handed to duplicates the document root does not show yet: a copied module renames all its blocks at once. */
32
- d(this, "_unsettledDuplicateIds", /* @__PURE__ */ new Set());
31
+ u(this, "_unsettledDuplicateIds", /* @__PURE__ */ new Set());
32
+ u(this, "_arrivedBlocks", []);
33
+ /** Strategy each in-flight arrival or duplicate refresh is fetching, by block id, so a second one does not race it. */
34
+ u(this, "_refreshClaims", /* @__PURE__ */ new Map());
33
35
  }
34
36
  getId() {
35
- return k;
37
+ return y;
36
38
  }
37
39
  getIcon() {
38
40
  return "recommendation-icon";
39
41
  }
40
42
  getBlockCompositionType() {
41
- return S.CONTAINER;
43
+ return v.CONTAINER;
42
44
  }
43
45
  getName() {
44
46
  return this.api.translate("Recommendation Block");
@@ -49,8 +51,8 @@ class tt extends E {
49
51
  );
50
52
  }
51
53
  getSettingsPanelTitleHtml() {
52
- return A(
53
- k,
54
+ return E(
55
+ y,
54
56
  this.api.translate("Recommendation Block"),
55
57
  this.api.translate("This block is switched from the Old Version to the New Version. We recommend you check the Recommendation block and test your message to ensure it works properly.")
56
58
  );
@@ -72,8 +74,8 @@ class tt extends E {
72
74
  * attribute and overwrites dynamically added classes via setAttribute.
73
75
  */
74
76
  getTemplate() {
75
- const t = this._generateNextId();
76
- return this._pendingBlockId = t, T(t);
77
+ const e = this._generateNextId();
78
+ return this._pendingBlockId = e, T(e);
77
79
  }
78
80
  /**
79
81
  * Called when a new block is dropped into the template
@@ -82,42 +84,57 @@ class tt extends E {
82
84
  * and assigns the recommendation-id attribute + initializes configuration.
83
85
  * @param node - The newly created block node
84
86
  */
85
- onCreated(t) {
86
- const e = this._getRecommendationId(t);
87
- if (e !== null && e > 0) {
88
- if (this._ensureMobileFitRule(t), this._detectDuplicate(e)) {
89
- this._handleDuplicate(t, e), this._scheduleArrivalReset(t);
87
+ onCreated(e) {
88
+ const t = this._getRecommendationId(e);
89
+ if (t !== null && t > 0) {
90
+ if (this._pendingBlockId = null, this._detectDuplicate(t)) {
91
+ this._handleDuplicate(e, t), this._scheduleArrivalReset(e);
90
92
  return;
91
93
  }
92
- this._pendingBlockId === null && setTimeout(() => {
93
- this._getBlockElement(t) && this._detectDuplicate(e) && this._handleDuplicate(t, e);
94
- }, 0), this._scheduleArrivalReset(t);
94
+ setTimeout(() => {
95
+ if (this._getBlockElement(e)) {
96
+ if (this._detectDuplicate(t)) {
97
+ this._handleDuplicate(e, t);
98
+ return;
99
+ }
100
+ this._queueArrivalRefresh(e);
101
+ }
102
+ }, 0), this._scheduleArrivalReset(e);
95
103
  return;
96
104
  }
97
105
  const i = this._pendingBlockId ?? this._generateNextId();
98
- this._pendingBlockId = null, this._assignRecommendationId(t, i);
99
- const n = g().isFeatureEnabled("reusableRecommendationStrategy"), o = n && !s.hasConfig(t), { config: r, wasFreshDrop: l } = s.initializeConfig(
106
+ this._pendingBlockId = null, this._assignRecommendationId(e, i);
107
+ const r = g().isFeatureEnabled("reusableRecommendationStrategy"), s = r && !a.hasConfig(e), { config: n, wasFreshDrop: o } = a.initializeConfig(
100
108
  this.api,
101
- t,
109
+ e,
102
110
  {
103
111
  recommendationId: i,
104
- configVersion: n ? N : M,
105
- ...o ? { partnerName: g().partnerName.value } : {},
112
+ configVersion: r ? N : w,
113
+ ...s ? { partnerName: g().partnerName.value } : {},
106
114
  // An RRS block picks a strategy, not an algorithm, and its algorithm control is
107
115
  // hidden. Keeping the `mostPopular` default would bake a most-popular feed URL
108
116
  // at save for a block the user never configured.
109
- ...o ? { strategy: "" } : {}
117
+ ...s ? { strategy: "" } : {}
110
118
  }
111
- ), f = h();
112
- if (f.setCurrentBlock(i), this._stampHidePrice(t, r.priceHideIfSameAsDiscounted), l) {
119
+ ), l = p();
120
+ if (l.setCurrentBlock(i), this._stampHidePrice(e, n.priceHideIfSameAsDiscounted), o) {
113
121
  I(this.api);
114
- const _ = this._getBlockElement(t);
115
- _ && (R(this.api, _, !0), O({
116
- currentNode: t,
122
+ const h = this._getBlockElement(e);
123
+ h && (R(this.api, h, !0), M({
124
+ currentNode: e,
117
125
  documentModifier: this.api.getDocumentModifier()
118
126
  }));
119
127
  }
120
- f.patchCurrentBlockConfig({ language: r.language }, { triggerRefetch: !1 }), this._warnIfMultipleBlocks();
128
+ l.patchCurrentBlockConfig({ language: n.language }, { triggerRefetch: !1 }), this._warnIfMultipleBlocks();
129
+ }
130
+ /** Refreshes every block of an opened template: Stripo restores a stored document without `onCreated`. */
131
+ onDocumentInit() {
132
+ try {
133
+ const e = this.api.getDocumentRoot();
134
+ e && "querySelectorAll" in e && e.querySelectorAll(`.${d}`).forEach((t) => this._queueArrivalRefresh(t));
135
+ } catch (e) {
136
+ console.error("[recommendation] refreshing an opened strategy failed", e);
137
+ }
121
138
  }
122
139
  /**
123
140
  * Called when the document changes or template is loaded
@@ -126,24 +143,24 @@ class tt extends E {
126
143
  * and assigns recommendation-id to legacy blocks that lack one.
127
144
  * @param node - The block node that may need migration
128
145
  */
129
- onDocumentChanged(t) {
130
- if (!(!t || !("getNodeConfig" in t))) {
131
- if (!this._getRecommendationId(t)) {
132
- const e = this._generateNextId();
133
- this._assignRecommendationId(t, e), s.hasConfig(t) && s.updateConfig(
146
+ onDocumentChanged(e) {
147
+ if (!(!e || !("getNodeConfig" in e))) {
148
+ if (!this._getRecommendationId(e)) {
149
+ const t = this._generateNextId();
150
+ this._assignRecommendationId(e, t), a.hasConfig(e) && a.updateConfig(
134
151
  this.api,
135
- t,
136
- { recommendationId: e },
152
+ e,
153
+ { recommendationId: t },
137
154
  "Assign recommendation ID to legacy block"
138
155
  );
139
156
  }
140
- this._healLingeringDuplicate(t), s.needsMigration(t) && this._migrateFromLegacy(t), this._healHidePriceAttr(t), this._ensureMobileFitRule(t);
157
+ this._healLingeringDuplicate(e), a.needsMigration(e) && this._migrateFromLegacy(e), this._healHidePriceAttr(e);
141
158
  try {
142
- D || (I(this.api), D = !0);
143
- const e = s.getConfig(t), i = this._getBlockElement(t);
159
+ B || (I(this.api), B = !0);
160
+ const t = a.getConfig(e), i = this._getBlockElement(e);
144
161
  if (i) {
145
- const n = !e.mobileLayoutEnabled;
146
- x(i) !== n && R(this.api, i, n);
162
+ const r = !t.mobileLayoutEnabled;
163
+ O(i) !== r && R(this.api, i, r);
147
164
  }
148
165
  } catch {
149
166
  }
@@ -155,15 +172,9 @@ class tt extends E {
155
172
  * Cleans up the per-block state from the Pinia store.
156
173
  * @param node - The block node being deleted
157
174
  */
158
- onDelete(t) {
159
- const e = this._getRecommendationId(t);
160
- e && h().removeBlockState(e);
161
- }
162
- _ensureMobileFitRule(t) {
163
- try {
164
- w(this.api, t);
165
- } catch {
166
- }
175
+ onDelete(e) {
176
+ const t = this._getRecommendationId(e);
177
+ t && p().removeBlockState(t);
167
178
  }
168
179
  /**
169
180
  * Warns (dark advisory toaster) when the design holds more than one live
@@ -179,7 +190,7 @@ class tt extends E {
179
190
  */
180
191
  _warnIfMultipleBlocks() {
181
192
  try {
182
- F().warnIfMultipleBlocks(this.api.getDocumentRootHtmlNode());
193
+ x().warnIfMultipleBlocks(this.api.getDocumentRootHtmlNode());
183
194
  } catch {
184
195
  }
185
196
  }
@@ -188,21 +199,21 @@ class tt extends E {
188
199
  * in the document and finding the maximum existing ID + 1.
189
200
  */
190
201
  _generateNextId() {
191
- let t = 0;
192
- const e = /* @__PURE__ */ new Set();
202
+ let e = 0;
203
+ const t = /* @__PURE__ */ new Set();
193
204
  try {
194
205
  const i = this.api.getDocumentRoot();
195
- i && "querySelectorAll" in i && i.querySelectorAll(`.${u}`).forEach((o) => {
196
- if ("getAttribute" in o) {
197
- const r = o.getAttribute(m), l = r ? parseInt(r) : 0;
198
- e.add(l), l > t && (t = l);
206
+ i && "querySelectorAll" in i && i.querySelectorAll(`.${d}`).forEach((s) => {
207
+ if ("getAttribute" in s) {
208
+ const n = s.getAttribute(f), o = n ? parseInt(n) : 0;
209
+ t.add(o), o > e && (e = o);
199
210
  }
200
211
  });
201
212
  } catch {
202
213
  }
203
214
  return this._unsettledDuplicateIds.forEach((i) => {
204
- e.has(i) && this._unsettledDuplicateIds.delete(i);
205
- }), Math.max(t, ...this._unsettledDuplicateIds) + 1;
215
+ t.has(i) && this._unsettledDuplicateIds.delete(i);
216
+ }), Math.max(e, ...this._unsettledDuplicateIds) + 1;
206
217
  }
207
218
  /**
208
219
  * Drops the "already fetched" claims of a block that arrived holding a baked id
@@ -211,67 +222,119 @@ class tt extends E {
211
222
  * Deferred a tick: the collision handlers rename a sibling first, and either sibling can be
212
223
  * the renamed one depending on where the module was dropped (SD-149916).
213
224
  */
214
- _scheduleArrivalReset(t) {
225
+ _scheduleArrivalReset(e) {
215
226
  g().isFeatureEnabled("reusableRecommendationStrategy") && setTimeout(() => {
216
- const e = this._getRecommendationId(t);
217
- e !== null && e > 0 && !this._resetSourceIds.delete(e) && h().resetArrivedBlock(e);
227
+ const t = this._getRecommendationId(e);
228
+ t !== null && t > 0 && !this._resetSourceIds.delete(t) && p().resetArrivedBlock(t);
218
229
  }, 0);
219
230
  }
231
+ /**
232
+ * Re-reads the strategy of a block that arrived with saved cards, without waiting for a click.
233
+ * Blocks of one opened template or dropped module arrive in one tick and refresh together.
234
+ */
235
+ _queueArrivalRefresh(e, t) {
236
+ g().isFeatureEnabled("reusableRecommendationStrategy") && (this._arrivedBlocks.push({ node: e, id: t }) > 1 || setTimeout(() => {
237
+ const i = this._arrivedBlocks;
238
+ this._arrivedBlocks = [];
239
+ try {
240
+ this._refreshArrivedBlocks(i);
241
+ } catch (r) {
242
+ console.error("[recommendation] refreshing an arrived strategy failed", r);
243
+ }
244
+ }, 0));
245
+ }
246
+ _refreshArrivedBlocks(e) {
247
+ k(this.api);
248
+ const t = /* @__PURE__ */ new Set(), i = e.flatMap(({ node: r, id: s }) => {
249
+ const n = s ?? this._getRecommendationId(r), o = this._getBlockElement(r);
250
+ if (!n || !o || t.has(n))
251
+ return [];
252
+ const l = a.getConfig(o);
253
+ if (!this._canClaimRefresh(n, l.strategyId))
254
+ return [];
255
+ const h = { strategyId: l.strategyId };
256
+ return t.add(n), this._refreshClaims.set(n, h), [{ id: n, config: l, claim: h }];
257
+ });
258
+ i.length && q(i.map(({ id: r, config: s }) => ({ id: r, config: s }))).catch((r) => console.error("[recommendation] refreshing an arrived strategy failed", r)).finally(() => i.forEach(({ id: r, claim: s }) => this._releaseRefreshClaim(r, s)));
259
+ }
260
+ /**
261
+ * A new document reports each block to onCreated and onDocumentInit, not always in one batch, so a
262
+ * claimed block refreshes again only once the document shows it under another strategy (a restored version).
263
+ */
264
+ _canClaimRefresh(e, t) {
265
+ const i = this._refreshClaims.get(e);
266
+ if (!i)
267
+ return !0;
268
+ if (i.strategyId === t)
269
+ return !1;
270
+ const r = $(e);
271
+ return r.length > 0 && r.every((s) => s.strategyId === t);
272
+ }
273
+ _releaseRefreshClaim(e, t) {
274
+ this._refreshClaims.get(e) === t && this._refreshClaims.delete(e);
275
+ }
220
276
  /**
221
277
  * Heals a duplicate that slipped past the create-time `_detectDuplicate`
222
278
  * scan (or that was persisted by an older template before SD-142352).
223
279
  * When two blocks share a `recommendation-id`, the first occurrence in DOM
224
280
  * order is treated as the source and any later sibling is reassigned a
225
- * fresh id. The store entry and active-block focus are intentionally not
226
- * touched here: each block's persisted `esd-ext-config` carries its own
227
- * truth and the regular save-time hydration (`hydrateRecommendationStore`)
228
- * will seed the new id from that. Skipping `setCurrentBlock` avoids
281
+ * fresh id and queued for the arrival refresh, which seeds the new id's
282
+ * store entry from its persisted `esd-ext-config`. The source's store
283
+ * entry is not cloned and focus is not moved. Skipping `setCurrentBlock` avoids
229
284
  * yanking the user's current selection mid-edit when the heal fires from
230
285
  * `onDocumentChanged`.
231
286
  */
232
- _healLingeringDuplicate(t) {
233
- const e = this._getRecommendationId(t);
234
- if (!(e === null || e <= 0))
287
+ _healLingeringDuplicate(e) {
288
+ const t = this._getRecommendationId(e);
289
+ if (!(t === null || t <= 0))
235
290
  try {
236
291
  const i = this.api.getDocumentRoot();
237
292
  if (!i || !("querySelectorAll" in i))
238
293
  return;
239
- const n = i.querySelectorAll(
240
- `.${u}[${m}="${e}"]`
294
+ const r = i.querySelectorAll(
295
+ `.${d}[${f}="${t}"]`
241
296
  );
242
- if (n.length <= 1)
297
+ if (r.length <= 1)
243
298
  return;
244
- const o = this._getBlockElement(t);
245
- if (!o)
299
+ const s = this._getBlockElement(e);
300
+ if (!s)
246
301
  return;
247
- let r = -1;
248
- for (let l = 0; l < n.length; l++)
249
- if (n[l] === o) {
250
- r = l;
302
+ let n = -1;
303
+ for (let o = 0; o < r.length; o++)
304
+ if (r[o] === s) {
305
+ n = o;
251
306
  break;
252
307
  }
253
- if (r <= 0)
308
+ if (n <= 0)
254
309
  return;
255
- this._reassignDuplicateId(t, e);
310
+ this._queueArrivalRefresh(e, this._reassignDuplicateId(e, t));
256
311
  } catch {
257
312
  }
258
313
  }
259
314
  /** True when another block already holds the same id — Stripo's duplication signal. */
260
- _detectDuplicate(t) {
315
+ _detectDuplicate(e) {
261
316
  try {
262
- const e = this.api.getDocumentRoot();
263
- if (e && "querySelectorAll" in e)
264
- return e.querySelectorAll(
265
- `.${u}[${m}="${t}"]`
317
+ const t = this.api.getDocumentRoot();
318
+ if (t && "querySelectorAll" in t)
319
+ return t.querySelectorAll(
320
+ `.${d}[${f}="${e}"]`
266
321
  ).length > 1;
267
322
  } catch {
268
323
  }
269
324
  return !1;
270
325
  }
271
326
  /** Assigns a fresh id to a duplicated block and syncs DOM, node config and store. */
272
- _handleDuplicate(t, e) {
273
- const i = this._reassignDuplicateId(t, e), n = h();
274
- n.cloneBlockState(e, i), n.setCurrentBlock(i), g().isFeatureEnabled("reusableRecommendationStrategy") && (this._resetSourceIds.add(e), H(this.api), $(e, i, s.getConfig(t)).catch((o) => console.error("[recommendation] refreshing a duplicated strategy failed", o))), this._warnIfMultipleBlocks();
327
+ _handleDuplicate(e, t) {
328
+ const i = this._reassignDuplicateId(e, t), r = p();
329
+ if (r.cloneBlockState(t, i), r.setCurrentBlock(i), g().isFeatureEnabled("reusableRecommendationStrategy")) {
330
+ this._resetSourceIds.add(t), k(this.api);
331
+ const s = a.getConfig(e), n = [
332
+ { id: t, claim: { strategyId: H(t, s).strategyId } },
333
+ { id: i, claim: { strategyId: s.strategyId } }
334
+ ].filter(({ id: o }) => !this._refreshClaims.has(o));
335
+ n.forEach(({ id: o, claim: l }) => this._refreshClaims.set(o, l)), F(t, i, s).catch((o) => console.error("[recommendation] refreshing a duplicated strategy failed", o)).finally(() => n.forEach(({ id: o, claim: l }) => this._releaseRefreshClaim(o, l)));
336
+ }
337
+ this._warnIfMultipleBlocks();
275
338
  }
276
339
  /**
277
340
  * Core id-reassignment for a duplicated block: rewrites the DOM
@@ -280,17 +343,17 @@ class tt extends E {
280
343
  *
281
344
  * Used by `_handleDuplicate` at create-time (which additionally clones the
282
345
  * store entry and focuses the new block) and by `_healLingeringDuplicate`
283
- * at document-change time (which intentionally skips store/focus side
284
- * effects so older bug-affected templates can self-repair without
285
- * disturbing the user's current selection).
346
+ * at document-change time (which skips the clone and focus change so older
347
+ * bug-affected templates can self-repair without disturbing the user's
348
+ * current selection, and queues the arrival refresh for the new id).
286
349
  */
287
- _reassignDuplicateId(t, e) {
288
- const i = this._generateNextId(), n = this._getBlockElement(t);
289
- return this._unsettledDuplicateIds.add(i), this._assignRecommendationId(t, i), n && this._reassignInstanceClass(n, e, i), s.hasConfig(t) && s.updateConfig(
350
+ _reassignDuplicateId(e, t) {
351
+ const i = this._generateNextId(), r = this._getBlockElement(e);
352
+ return this._unsettledDuplicateIds.add(i), this._assignRecommendationId(e, i), r && this._reassignInstanceClass(r, t, i), a.hasConfig(e) && a.updateConfig(
290
353
  this.api,
291
- t,
354
+ e,
292
355
  { recommendationId: i },
293
- `Reassign recommendation ID on duplicate (was ${e})`
356
+ `Reassign recommendation ID on duplicate (was ${t})`
294
357
  ), i;
295
358
  }
296
359
  /**
@@ -300,12 +363,12 @@ class tt extends E {
300
363
  * the source's class would both leak stylistic edits across blocks and
301
364
  * cause the mail render to apply the source block's config to the clone.
302
365
  */
303
- _reassignInstanceClass(t, e, i) {
304
- if (!("getAttribute" in t))
366
+ _reassignInstanceClass(e, t, i) {
367
+ if (!("getAttribute" in e))
305
368
  return;
306
- const n = `ins-recommendation-v3-block-${e}`, o = `ins-recommendation-v3-block-${i}`, r = this.api.getDocumentModifier();
307
- r.modifyHtml(t).removeClass(n).setClass(o), r.apply(new p(
308
- `Reassign recommendation instance class ${n} -> ${o}`
369
+ const r = `ins-recommendation-v3-block-${t}`, s = `ins-recommendation-v3-block-${i}`, n = this.api.getDocumentModifier();
370
+ n.modifyHtml(e).removeClass(r).setClass(s), n.apply(new _(
371
+ `Reassign recommendation instance class ${r} -> ${s}`
309
372
  ));
310
373
  }
311
374
  /**
@@ -314,64 +377,64 @@ class tt extends E {
314
377
  * HTML by getTemplate(), since Stripo's Angular rendering overwrites dynamically
315
378
  * added classes via setAttribute.
316
379
  */
317
- _assignRecommendationId(t, e) {
318
- const i = this._getBlockElement(t);
380
+ _assignRecommendationId(e, t) {
381
+ const i = this._getBlockElement(e);
319
382
  if (!i)
320
383
  return;
321
- const n = this.api.getDocumentModifier();
322
- n.modifyHtml(i).setAttribute(m, e.toString()), n.apply(new p(`Assign recommendation ID ${e}`));
384
+ const r = this.api.getDocumentModifier();
385
+ r.modifyHtml(i).setAttribute(f, t.toString()), r.apply(new _(`Assign recommendation ID ${t}`));
323
386
  }
324
387
  /**
325
388
  * Stamps the `hide-price` attribute (read by email-service at send time) on
326
389
  * the block element from the config flag.
327
390
  */
328
- _stampHidePrice(t, e) {
329
- const i = this._getBlockElement(t);
330
- i && this.api.getDocumentModifier().modifyHtml(i).setAttribute(b, String(e)).apply(new p("Stamp hide-price"));
391
+ _stampHidePrice(e, t) {
392
+ const i = this._getBlockElement(e);
393
+ i && this.api.getDocumentModifier().modifyHtml(i).setAttribute(C, String(t)).apply(new _("Stamp hide-price"));
331
394
  }
332
395
  /**
333
396
  * Stamps `hide-price` from config only when the block lacks the attribute —
334
397
  * heals templates saved before this feature without dirtying current ones.
335
398
  */
336
- _healHidePriceAttr(t) {
337
- const e = this._getBlockElement(t);
338
- if (!e || !("getAttribute" in e) || e.getAttribute(b) !== null)
399
+ _healHidePriceAttr(e) {
400
+ const t = this._getBlockElement(e);
401
+ if (!t || !("getAttribute" in t) || t.getAttribute(C) !== null)
339
402
  return;
340
- const { priceHideIfSameAsDiscounted: i } = s.getConfig(t);
341
- this._stampHidePrice(t, i);
403
+ const { priceHideIfSameAsDiscounted: i } = a.getConfig(e);
404
+ this._stampHidePrice(e, i);
342
405
  }
343
406
  /**
344
407
  * Gets the recommendation-id from a block node
345
408
  */
346
- _getRecommendationId(t) {
347
- const e = this._getBlockElement(t);
348
- if (!e || !("getAttribute" in e))
409
+ _getRecommendationId(e) {
410
+ const t = this._getBlockElement(e);
411
+ if (!t || !("getAttribute" in t))
349
412
  return null;
350
- const i = e.getAttribute(m);
413
+ const i = t.getAttribute(f);
351
414
  if (!i)
352
415
  return null;
353
- const n = parseInt(i);
354
- return Number.isNaN(n) ? null : n;
416
+ const r = parseInt(i);
417
+ return Number.isNaN(r) ? null : r;
355
418
  }
356
419
  /**
357
420
  * Gets the block element (the element with BLOCK_CLASS)
358
421
  */
359
- _getBlockElement(t) {
360
- if ("getAttribute" in t) {
361
- const e = t.getAttribute("class");
362
- if (e && e.includes(u))
363
- return t;
422
+ _getBlockElement(e) {
423
+ if ("getAttribute" in e) {
424
+ const t = e.getAttribute("class");
425
+ if (t && t.includes(d))
426
+ return e;
364
427
  }
365
- return "querySelector" in t ? t.querySelector(`.${u}`) ?? null : null;
428
+ return "querySelector" in e ? e.querySelector(`.${d}`) ?? null : null;
366
429
  }
367
430
  /**
368
431
  * Migrate configuration from legacy format
369
432
  */
370
- _migrateFromLegacy(t) {
371
- s.migrateFromDataAttributes(this.api, t);
433
+ _migrateFromLegacy(e) {
434
+ a.migrateFromDataAttributes(this.api, e);
372
435
  }
373
436
  }
374
437
  export {
375
- k as BLOCK_ID,
376
- tt as RecommendationBlock
438
+ y as BLOCK_ID,
439
+ te as RecommendationBlock
377
440
  };
@@ -1,63 +1,19 @@
1
- import { EditorStatePropertyType as S, PreviewDeviceMode as E, ModificationDescription as y } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
2
- import { createImageMarginsControl as I, createImageSizeControl as M } from "../../../controlFactories.js";
3
- import { RecommendationBlockId as d } from "../../constants/blockIds.js";
4
- import { RecommendationControlId as u } from "../../constants/controlIds.js";
5
- import { BLOCK_ROOT_SELECTOR as l } from "../../constants/selectors.js";
6
- import { hasGetStyle as g } from "../../utils/tagName.js";
7
- const C = { width: "", height: "auto", "max-height": "" }, h = `${l} img.adapt-img`, R = `*${l.slice(1)}`, f = `@media only screen and (max-width: 600px) { ${h} { max-height: none !important; } }`;
8
- function O(t) {
9
- return { width: "auto", height: "auto", "max-height": `${t}px` };
10
- }
11
- function T(t) {
12
- return t.querySelectorAll(R).some((e) => "getSelector" in e && e.getSelector() === h);
13
- }
14
- function _(t, e) {
15
- return g(t) && Object.entries(e).some(([i, o]) => (t.getStyle(i) ?? "") !== o);
16
- }
17
- function p(t) {
18
- const e = t.getDocumentRootCssNode();
19
- return e && !T(e) ? e : null;
20
- }
21
- function G(t, e) {
22
- const o = e.querySelectorAll("img").some((r) => g(r) && !!r.getStyle("max-height")) ? p(t) : null;
23
- if (!o)
24
- return;
25
- const n = t.getDocumentModifier();
26
- n.modifyCss(o).appendRule(f), n.apply(new y("Add the reco image mobile fit rule"));
27
- }
28
- class x extends M(
29
- u.IMAGE_SIZE,
30
- d.IMAGE,
31
- l
32
- ) {
33
- getAdditionalModifications(e) {
34
- if (this.api.getEditorState()[S.previewDeviceMode] === E.MOBILE)
35
- return;
36
- const i = this.getFitStyles(), o = this.getTargetNodes(e).map((s) => s.querySelector("img")).filter((s) => _(s, i)), n = i["max-height"] ? p(this.api) : null;
37
- if (!o.length && !n)
38
- return;
39
- const r = this.api.getDocumentModifier();
40
- return n && r.modifyCss(n).appendRule(f), o.forEach((s) => {
41
- const a = r.modifyHtml(s);
42
- Object.entries(i).forEach(([c, m]) => {
43
- m ? a.setStyle(c, m) : a.removeStyle(c);
44
- });
45
- }), r;
46
- }
47
- getFitStyles() {
48
- const { size: e } = this.api.getValues();
49
- return (e == null ? void 0 : e.type) === "height" && e.value ? O(e.value) : C;
50
- }
51
- }
52
- const A = I(
53
- u.IMAGE_MARGINS,
54
- d.IMAGE,
55
- l
56
- ), b = {
57
- size: x,
58
- margins: A
1
+ import { createImageMarginsControl as m, createImageSizeControl as n } from "../../../controlFactories.js";
2
+ import { RecommendationBlockId as o } from "../../constants/blockIds.js";
3
+ import { RecommendationControlId as r } from "../../constants/controlIds.js";
4
+ import { BLOCK_ROOT_SELECTOR as t } from "../../constants/selectors.js";
5
+ const e = n(
6
+ r.IMAGE_SIZE,
7
+ o.IMAGE,
8
+ t
9
+ ), i = m(
10
+ r.IMAGE_MARGINS,
11
+ o.IMAGE,
12
+ t
13
+ ), C = {
14
+ size: e,
15
+ margins: i
59
16
  };
60
17
  export {
61
- b as ImageControls,
62
- G as ensureMobileFitRule
18
+ C as ImageControls
63
19
  };