@useinsider/guido 3.21.1 → 3.21.2

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.
@@ -7,13 +7,13 @@ function L(t, r, e, o, c = "") {
7
7
  const i = `{{${c}${t}_${r}_${e}}}`, n = `{{${c}${t}_${r}_currency}}`;
8
8
  return o === "before" ? `${n} ${i}` : `${i} ${n}`;
9
9
  }
10
- function _(t) {
10
+ function A(t) {
11
11
  let r = t;
12
12
  for (; r.children.length === 1; )
13
13
  [r] = r.children;
14
14
  return r;
15
15
  }
16
- function A(t, r, e, o, c, i) {
16
+ function y(t, r, e, o, c, i) {
17
17
  switch (r) {
18
18
  case "productImage": {
19
19
  const n = t.querySelector("img");
@@ -24,7 +24,7 @@ function A(t, r, e, o, c, i) {
24
24
  }
25
25
  case "productName": {
26
26
  const n = t.querySelector("p");
27
- n && (_(n).textContent = `{{${i}${e}_${o}_name}}`);
27
+ n && (A(n).textContent = `{{${i}${e}_${o}_name}}`);
28
28
  break;
29
29
  }
30
30
  // Inline mode ("Move to next line" OFF) merges BOTH prices into one row
@@ -32,16 +32,16 @@ function A(t, r, e, o, c, i) {
32
32
  // substitute by cell content, not by the row's anchor (SD-145161).
33
33
  case "productPrice":
34
34
  case "productOldPrice": {
35
- const n = (l, d) => {
36
- l && (_(l).textContent = L(
35
+ const n = (a, l) => {
36
+ a && (A(a).textContent = L(
37
37
  e,
38
38
  o,
39
- d,
39
+ l,
40
40
  c,
41
41
  i
42
42
  ));
43
- }, s = t.querySelector(".product-price p"), a = t.querySelector(".product-old-price p"), u = !s && !a ? t.querySelector("p") : null;
44
- n(s ?? (r === "productPrice" ? u : null), "price"), n(a ?? (r === "productOldPrice" ? u : null), "original_price");
43
+ }, s = t.querySelector(".product-price p"), d = t.querySelector(".product-old-price p"), u = !s && !d ? t.querySelector("p") : null;
44
+ n(s ?? (r === "productPrice" ? u : null), "price"), n(d ?? (r === "productOldPrice" ? u : null), "original_price");
45
45
  break;
46
46
  }
47
47
  case "productButton": {
@@ -70,8 +70,8 @@ function A(t, r, e, o, c, i) {
70
70
  default: {
71
71
  const n = t.getAttribute("product-attr") ? t : t.querySelector("[product-attr]");
72
72
  if (n) {
73
- const s = n.getAttribute("product-attr"), a = n.querySelector("p");
74
- a && (_(a).textContent = `{{${i}${e}_${o}_${s}}}`);
73
+ const s = n.getAttribute("product-attr"), d = n.querySelector("p");
74
+ d && (A(d).textContent = `{{${i}${e}_${o}_${s}}}`);
75
75
  }
76
76
  break;
77
77
  }
@@ -88,54 +88,54 @@ function b(t, r, e, o) {
88
88
  function R(t, r, e) {
89
89
  return b(t, r, 0, e);
90
90
  }
91
- function D(t, r, e, o) {
91
+ function w(t, r, e, o) {
92
92
  if (!t.innerHTML.includes("{{"))
93
93
  return;
94
94
  const { open: c, close: i } = b(t.ownerDocument, r, e, o);
95
95
  t.insertBefore(c, t.firstChild), t.appendChild(i);
96
96
  }
97
- function w(t, r, e, o) {
97
+ function D(t, r, e, o) {
98
98
  var n, s;
99
99
  if (!t.innerHTML.includes("{{"))
100
100
  return;
101
101
  const { open: c, close: i } = b(t.ownerDocument, r, e, o);
102
102
  (n = t.parentNode) == null || n.insertBefore(c, t), (s = t.parentNode) == null || s.insertBefore(i, t.nextSibling);
103
103
  }
104
- function W(t, r, e, o) {
104
+ function v(t, r, e, o) {
105
105
  t.querySelectorAll(".recommendation-product-row").forEach((i, n) => {
106
- i.querySelectorAll("[data-attribute-type]").forEach((a) => {
107
- const u = a.getAttribute("data-attribute-type") || "", l = a.querySelectorAll(".attribute-cell");
108
- l.length > 0 ? l.forEach((d) => {
109
- A(d, u, r, n, e, o);
110
- }) : A(a, u, r, n, e, o);
111
- }), w(i, r, n, o);
106
+ i.querySelectorAll("[data-attribute-type]").forEach((d) => {
107
+ const u = d.getAttribute("data-attribute-type") || "", a = d.querySelectorAll(".attribute-cell");
108
+ a.length > 0 ? a.forEach((l) => {
109
+ y(l, u, r, n, e, o);
110
+ }) : y(d, u, r, n, e, o);
111
+ }), D(i, r, n, o);
112
112
  });
113
113
  }
114
- function v(t, r, e, o) {
114
+ function H(t, r, e, o) {
115
115
  const c = t.querySelectorAll(".recommendation-product-row");
116
116
  if (!c.length)
117
117
  return;
118
118
  const [i] = c, n = i.querySelector("[data-attribute-type]"), s = n ? n.querySelectorAll(".attribute-cell").length : 1;
119
- c.forEach((a, u) => {
120
- a.querySelectorAll("[data-attribute-type]").forEach((d) => {
121
- const p = d.getAttribute("data-attribute-type") || "";
122
- d.querySelectorAll(".attribute-cell").forEach((f, m) => {
123
- const h = u * s + m;
124
- A(f, p, r, h, e, o), D(f, r, h, o);
119
+ c.forEach((d, u) => {
120
+ d.querySelectorAll("[data-attribute-type]").forEach((l) => {
121
+ const p = l.getAttribute("data-attribute-type") || "";
122
+ l.querySelectorAll(".attribute-cell").forEach((f, h) => {
123
+ const S = u * s + h;
124
+ y(f, p, r, S, e, o), w(f, r, S, o);
125
125
  });
126
126
  });
127
127
  });
128
128
  }
129
- function H(t, r, e, o) {
129
+ function W(t, r, e, o) {
130
130
  t.querySelectorAll(".ins-recommendation-product-container").forEach((i) => {
131
- v(i, r, e, o);
131
+ H(i, r, e, o);
132
132
  });
133
133
  }
134
134
  function F(t, r, e) {
135
135
  const o = t.getAttribute("data-layout") || "grid", c = t.getAttribute("currency-alignment") || "after";
136
- o === "list" ? W(t, r, c, e) : H(t, r, c, e);
136
+ o === "list" ? v(t, r, c, e) : W(t, r, c, e);
137
137
  }
138
- function y(t, r, e) {
138
+ function _(t, r, e) {
139
139
  const o = new RegExp(`${r}\\s*:\\s*(\\d+)\\s*px`, "i"), c = t.match(o);
140
140
  return c ? parseInt(c[1]) : e;
141
141
  }
@@ -150,7 +150,7 @@ function C(t) {
150
150
  const e = (t.getAttribute("style") || "").match(/(?:^|[;\s])width\s*:\s*(\d+(?:\.\d+)?(?:px|%))/i);
151
151
  return e && $(e[1]) ? e[1] : null;
152
152
  }
153
- function G(t, r) {
153
+ function x(t, r) {
154
154
  let e = t.parentElement;
155
155
  for (; e && e !== r; ) {
156
156
  if (e.tagName === "TD" && C(e))
@@ -159,35 +159,37 @@ function G(t, r) {
159
159
  }
160
160
  return null;
161
161
  }
162
- function V(t) {
163
- const r = t.getAttribute("style") || "", e = y(r, "width", 600), o = y(r, "padding", 0) * 2, c = Math.max(0, e - o);
162
+ function G(t) {
163
+ const r = t.getAttribute("style") || "", e = _(r, "width", 600), o = _(r, "padding", 0) * 2, c = Math.max(0, e - o);
164
164
  c !== 0 && t.querySelectorAll("img.adapt-img").forEach((i) => {
165
165
  if (i.hasAttribute("width"))
166
166
  return;
167
- const n = G(i, t);
167
+ const n = x(i, t);
168
168
  if (!n)
169
169
  return;
170
- const s = C(n), a = y(n.getAttribute("style") || "", "padding", 0) * 2, u = s.endsWith("%") ? Math.floor(c * parseFloat(s) / 100) : parseInt(s), l = Math.max(1, u - a);
171
- i.setAttribute("width", String(l));
172
- const d = i.getAttribute("style") || "";
173
- if (!/\bwidth\s*:\s*\d/i.test(d)) {
174
- const p = d && !d.trim().endsWith(";") ? "; " : "";
175
- i.setAttribute("style", `${d}${p}width: ${l}px`);
170
+ const s = C(n), d = _(n.getAttribute("style") || "", "padding", 0) * 2, u = s.endsWith("%") ? Math.floor(c * parseFloat(s) / 100) : parseInt(s), a = Math.max(1, u - d), l = i.getAttribute("style") || "", p = /(?:^|[;\s])max-height\s*:\s*(\d+(?:\.\d+)?)px/i.exec(l);
171
+ if (p) {
172
+ i.setAttribute("width", String(Math.max(1, Math.min(a, Math.floor(parseFloat(p[1])))))), i.removeAttribute("height");
173
+ return;
174
+ }
175
+ if (i.setAttribute("width", String(a)), !/\bwidth\s*:\s*\d/i.test(l)) {
176
+ const m = l && !l.trim().endsWith(";") ? "; " : "";
177
+ i.setAttribute("style", `${l}${m}width: ${a}px`);
176
178
  }
177
179
  });
178
180
  }
179
- const E = "MSO_MOBILE_HIDE_START", U = "MSO_MOBILE_HIDE_END";
180
- function X(t, r) {
181
+ const E = "MSO_MOBILE_HIDE_START", V = "MSO_MOBILE_HIDE_END";
182
+ function U(t, r) {
181
183
  t.querySelectorAll(q).forEach((e) => {
182
184
  var i, n;
183
185
  const o = e.querySelector(M);
184
186
  if (!o || o.children.length === 0)
185
187
  return;
186
188
  const c = e.previousSibling;
187
- (c == null ? void 0 : c.nodeType) === Node.COMMENT_NODE && c.data === E || ((i = e.parentNode) == null || i.insertBefore(r.createComment(E), e), (n = e.parentNode) == null || n.insertBefore(r.createComment(U), e.nextSibling));
189
+ (c == null ? void 0 : c.nodeType) === Node.COMMENT_NODE && c.data === E || ((i = e.parentNode) == null || i.insertBefore(r.createComment(E), e), (n = e.parentNode) == null || n.insertBefore(r.createComment(V), e.nextSibling));
188
190
  });
189
191
  }
190
- function j(t, r) {
192
+ function X(t, r) {
191
193
  const e = t.match(/<!DOCTYPE[^>]*>/i);
192
194
  return (e ? `${e[0]}
193
195
  ` : "") + r.documentElement.outerHTML;
@@ -200,17 +202,17 @@ function Q(t) {
200
202
  i.recommendationCampaignUrls = {};
201
203
  const { isFeatureEnabled: n } = g(), s = n("liquidSyntax") ? "reco_" : "";
202
204
  return o.forEach((u) => {
203
- var d, p, S, f;
204
- const l = u.getAttribute("recommendation-id");
205
- if (l) {
206
- if ((d = u.parentNode) == null || d.insertBefore(e.createComment("REC_START"), u), (p = u.parentNode) == null || p.insertBefore(e.createComment("REC_END"), u.nextSibling), u.querySelectorAll('[data-visibility="0"]').forEach((m) => m.remove()), c(l), X(u, e), !T(u)) {
207
- F(u, l, s);
208
- const { open: m, close: h } = R(e, l, s);
209
- (S = u.parentNode) == null || S.insertBefore(m, u), (f = u.parentNode) == null || f.insertBefore(h, u.nextSibling);
205
+ var l, p, m, f;
206
+ const a = u.getAttribute("recommendation-id");
207
+ if (a) {
208
+ if ((l = u.parentNode) == null || l.insertBefore(e.createComment("REC_START"), u), (p = u.parentNode) == null || p.insertBefore(e.createComment("REC_END"), u.nextSibling), u.querySelectorAll('[data-visibility="0"]').forEach((h) => h.remove()), c(a), U(u, e), !T(u)) {
209
+ F(u, a, s);
210
+ const { open: h, close: S } = R(e, a, s);
211
+ (m = u.parentNode) == null || m.insertBefore(h, u), (f = u.parentNode) == null || f.insertBefore(S, u.nextSibling);
210
212
  }
211
- V(u);
213
+ G(u);
212
214
  }
213
- }), j(r, e).replaceAll("<!--{%", "{%").replaceAll("%}-->", "%}").replaceAll("&lt;!--{%", "{%").replaceAll("%}--&gt;", "%}");
215
+ }), X(r, e).replaceAll("<!--{%", "{%").replaceAll("%}-->", "%}").replaceAll("&lt;!--{%", "{%").replaceAll("%}--&gt;", "%}");
214
216
  }
215
217
  export {
216
218
  L as formatPriceVariable,
@@ -1,23 +1,24 @@
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);
1
+ var b = Object.defineProperty;
2
+ var A = (m, c, e) => c in m ? b(m, c, { enumerable: !0, configurable: !0, writable: !0, value: e }) : m[c] = e;
3
+ var u = (m, c, e) => A(m, typeof c != "symbol" ? c + "" : c, e);
4
4
  import { useConfig as g } from "../../../composables/useConfig.js";
5
- import { BlockId as b } from "../../../enums/block.js";
5
+ import { BlockId as D } from "../../../enums/block.js";
6
6
  import { getMigrationBannerHtml as E } from "../../../utils/migrationBannerHtml.js";
7
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";
8
+ import { CURRENT_CONFIG_VERSION as N, PRE_RRS_CONFIG_VERSION as M } from "./constants/defaultConfig.js";
9
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";
10
+ import { ensureMobileFitRule as w, syncHeightBound as O } from "./controls/image/index.js";
11
+ import { regenerateMobileProductRows as H } from "./controls/main/utils.js";
12
+ import { ensureMobileCssRulesExist as I, setMobileLayoutOptOut as R, hasMobileLayoutOptOut as T } from "./controls/mobileLayout/cssRules.js";
12
13
  import { RecommendationConfigService as a } from "./services/configService.js";
13
14
  import { useRecommendationExtensionStore as p } from "./store/recommendation.js";
14
- import { getDefaultTemplate as T } from "./templates/grid/template.js";
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";
15
+ import { getDefaultTemplate as x } from "./templates/grid/template.js";
16
+ import { useRecommendationBlockWarning as F } from "./useRecommendationBlockWarning.js";
17
+ import { registerNodeConfigWriter as y, readBlockNodeConfigs as $ } from "./utils/nodeConfigWriter.js";
18
+ import { refreshArrivedStrategyBlocks as q, resolveSourceConfig as L, refreshDuplicatedStrategyBlocks as P } from "./utils/strategyCommit.js";
19
+ const k = D.Recommendation, h = "recommendation-block-v2", C = "hide-price";
19
20
  let B = !1;
20
- class te extends S {
21
+ class se extends S {
21
22
  constructor() {
22
23
  super();
23
24
  /**
@@ -34,7 +35,7 @@ class te extends S {
34
35
  u(this, "_refreshClaims", /* @__PURE__ */ new Map());
35
36
  }
36
37
  getId() {
37
- return y;
38
+ return k;
38
39
  }
39
40
  getIcon() {
40
41
  return "recommendation-icon";
@@ -52,7 +53,7 @@ class te extends S {
52
53
  }
53
54
  getSettingsPanelTitleHtml() {
54
55
  return E(
55
- y,
56
+ k,
56
57
  this.api.translate("Recommendation Block"),
57
58
  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.")
58
59
  );
@@ -75,7 +76,7 @@ class te extends S {
75
76
  */
76
77
  getTemplate() {
77
78
  const e = this._generateNextId();
78
- return this._pendingBlockId = e, T(e);
79
+ return this._pendingBlockId = e, x(e);
79
80
  }
80
81
  /**
81
82
  * Called when a new block is dropped into the template
@@ -87,7 +88,7 @@ class te extends S {
87
88
  onCreated(e) {
88
89
  const t = this._getRecommendationId(e);
89
90
  if (t !== null && t > 0) {
90
- if (this._pendingBlockId = null, this._detectDuplicate(t)) {
91
+ if (this._pendingBlockId = null, this._ensureMobileFitRule(e), this._detectDuplicate(t)) {
91
92
  this._handleDuplicate(e, t), this._scheduleArrivalReset(e);
92
93
  return;
93
94
  }
@@ -109,7 +110,7 @@ class te extends S {
109
110
  e,
110
111
  {
111
112
  recommendationId: i,
112
- configVersion: r ? N : w,
113
+ configVersion: r ? N : M,
113
114
  ...s ? { partnerName: g().partnerName.value } : {},
114
115
  // An RRS block picks a strategy, not an algorithm, and its algorithm control is
115
116
  // hidden. Keeping the `mostPopular` default would bake a most-popular feed URL
@@ -119,8 +120,8 @@ class te extends S {
119
120
  ), l = p();
120
121
  if (l.setCurrentBlock(i), this._stampHidePrice(e, n.priceHideIfSameAsDiscounted), o) {
121
122
  I(this.api);
122
- const h = this._getBlockElement(e);
123
- h && (R(this.api, h, !0), M({
123
+ const d = this._getBlockElement(e);
124
+ d && (R(this.api, d, !0), H({
124
125
  currentNode: e,
125
126
  documentModifier: this.api.getDocumentModifier()
126
127
  }));
@@ -131,7 +132,7 @@ class te extends S {
131
132
  onDocumentInit() {
132
133
  try {
133
134
  const e = this.api.getDocumentRoot();
134
- e && "querySelectorAll" in e && e.querySelectorAll(`.${d}`).forEach((t) => this._queueArrivalRefresh(t));
135
+ e && "querySelectorAll" in e && e.querySelectorAll(`.${h}`).forEach((t) => this._queueArrivalRefresh(t));
135
136
  } catch (e) {
136
137
  console.error("[recommendation] refreshing an opened strategy failed", e);
137
138
  }
@@ -154,13 +155,13 @@ class te extends S {
154
155
  "Assign recommendation ID to legacy block"
155
156
  );
156
157
  }
157
- this._healLingeringDuplicate(e), a.needsMigration(e) && this._migrateFromLegacy(e), this._healHidePriceAttr(e);
158
+ this._healLingeringDuplicate(e), a.needsMigration(e) && this._migrateFromLegacy(e), this._healHidePriceAttr(e), this._ensureMobileFitRule(e), this._syncHeightBound(e);
158
159
  try {
159
160
  B || (I(this.api), B = !0);
160
161
  const t = a.getConfig(e), i = this._getBlockElement(e);
161
162
  if (i) {
162
163
  const r = !t.mobileLayoutEnabled;
163
- O(i) !== r && R(this.api, i, r);
164
+ T(i) !== r && R(this.api, i, r);
164
165
  }
165
166
  } catch {
166
167
  }
@@ -176,6 +177,20 @@ class te extends S {
176
177
  const t = this._getRecommendationId(e);
177
178
  t && p().removeBlockState(t);
178
179
  }
180
+ _ensureMobileFitRule(e) {
181
+ try {
182
+ w(this.api, e);
183
+ } catch {
184
+ }
185
+ }
186
+ _syncHeightBound(e) {
187
+ const t = this._getBlockElement(e);
188
+ if (t)
189
+ try {
190
+ O(this.api, t);
191
+ } catch {
192
+ }
193
+ }
179
194
  /**
180
195
  * Warns (dark advisory toaster) when the design holds more than one live
181
196
  * recommendation block. Triggered from the user-add paths only (fresh drop
@@ -190,7 +205,7 @@ class te extends S {
190
205
  */
191
206
  _warnIfMultipleBlocks() {
192
207
  try {
193
- x().warnIfMultipleBlocks(this.api.getDocumentRootHtmlNode());
208
+ F().warnIfMultipleBlocks(this.api.getDocumentRootHtmlNode());
194
209
  } catch {
195
210
  }
196
211
  }
@@ -203,7 +218,7 @@ class te extends S {
203
218
  const t = /* @__PURE__ */ new Set();
204
219
  try {
205
220
  const i = this.api.getDocumentRoot();
206
- i && "querySelectorAll" in i && i.querySelectorAll(`.${d}`).forEach((s) => {
221
+ i && "querySelectorAll" in i && i.querySelectorAll(`.${h}`).forEach((s) => {
207
222
  if ("getAttribute" in s) {
208
223
  const n = s.getAttribute(f), o = n ? parseInt(n) : 0;
209
224
  t.add(o), o > e && (e = o);
@@ -244,7 +259,7 @@ class te extends S {
244
259
  }, 0));
245
260
  }
246
261
  _refreshArrivedBlocks(e) {
247
- k(this.api);
262
+ y(this.api);
248
263
  const t = /* @__PURE__ */ new Set(), i = e.flatMap(({ node: r, id: s }) => {
249
264
  const n = s ?? this._getRecommendationId(r), o = this._getBlockElement(r);
250
265
  if (!n || !o || t.has(n))
@@ -252,8 +267,8 @@ class te extends S {
252
267
  const l = a.getConfig(o);
253
268
  if (!this._canClaimRefresh(n, l.strategyId))
254
269
  return [];
255
- const h = { strategyId: l.strategyId };
256
- return t.add(n), this._refreshClaims.set(n, h), [{ id: n, config: l, claim: h }];
270
+ const d = { strategyId: l.strategyId };
271
+ return t.add(n), this._refreshClaims.set(n, d), [{ id: n, config: l, claim: d }];
257
272
  });
258
273
  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
274
  }
@@ -292,7 +307,7 @@ class te extends S {
292
307
  if (!i || !("querySelectorAll" in i))
293
308
  return;
294
309
  const r = i.querySelectorAll(
295
- `.${d}[${f}="${t}"]`
310
+ `.${h}[${f}="${t}"]`
296
311
  );
297
312
  if (r.length <= 1)
298
313
  return;
@@ -317,7 +332,7 @@ class te extends S {
317
332
  const t = this.api.getDocumentRoot();
318
333
  if (t && "querySelectorAll" in t)
319
334
  return t.querySelectorAll(
320
- `.${d}[${f}="${e}"]`
335
+ `.${h}[${f}="${e}"]`
321
336
  ).length > 1;
322
337
  } catch {
323
338
  }
@@ -327,12 +342,12 @@ class te extends S {
327
342
  _handleDuplicate(e, t) {
328
343
  const i = this._reassignDuplicateId(e, t), r = p();
329
344
  if (r.cloneBlockState(t, i), r.setCurrentBlock(i), g().isFeatureEnabled("reusableRecommendationStrategy")) {
330
- this._resetSourceIds.add(t), k(this.api);
345
+ this._resetSourceIds.add(t), y(this.api);
331
346
  const s = a.getConfig(e), n = [
332
- { id: t, claim: { strategyId: H(t, s).strategyId } },
347
+ { id: t, claim: { strategyId: L(t, s).strategyId } },
333
348
  { id: i, claim: { strategyId: s.strategyId } }
334
349
  ].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)));
350
+ n.forEach(({ id: o, claim: l }) => this._refreshClaims.set(o, l)), P(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
351
  }
337
352
  this._warnIfMultipleBlocks();
338
353
  }
@@ -422,10 +437,10 @@ class te extends S {
422
437
  _getBlockElement(e) {
423
438
  if ("getAttribute" in e) {
424
439
  const t = e.getAttribute("class");
425
- if (t && t.includes(d))
440
+ if (t && t.includes(h))
426
441
  return e;
427
442
  }
428
- return "querySelector" in e ? e.querySelector(`.${d}`) ?? null : null;
443
+ return "querySelector" in e ? e.querySelector(`.${h}`) ?? null : null;
429
444
  }
430
445
  /**
431
446
  * Migrate configuration from legacy format
@@ -435,6 +450,6 @@ class te extends S {
435
450
  }
436
451
  }
437
452
  export {
438
- y as BLOCK_ID,
439
- te as RecommendationBlock
453
+ k as BLOCK_ID,
454
+ se as RecommendationBlock
440
455
  };
@@ -1,19 +1,79 @@
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
1
+ import { EditorStatePropertyType as E, PreviewDeviceMode as I, ModificationDescription as h } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
2
+ import { createImageMarginsControl as M, createImageSizeControl as C } from "../../../controlFactories.js";
3
+ import { RecommendationBlockId as c } from "../../constants/blockIds.js";
4
+ import { RecommendationControlId as g } from "../../constants/controlIds.js";
5
+ import { BLOCK_ROOT_SELECTOR as l } from "../../constants/selectors.js";
6
+ import { hasGetStyle as a, hasGetAttribute as O } from "../../utils/tagName.js";
7
+ const R = { width: "", height: "auto", "max-height": "" }, f = `${l} img.adapt-img`, x = `*${l.slice(1)}`, p = `@media only screen and (max-width: 600px) { ${f} { max-height: none !important; } }`;
8
+ function _(t) {
9
+ return { width: "auto", height: "auto", "max-height": `${t}px` };
10
+ }
11
+ function A(t) {
12
+ return t.querySelectorAll(x).some((e) => "getSelector" in e && e.getSelector() === f);
13
+ }
14
+ function T(t, e) {
15
+ return a(t) && Object.entries(e).some(([o, n]) => (t.getStyle(o) ?? "") !== n);
16
+ }
17
+ function S(t) {
18
+ const e = t.getDocumentRootCssNode();
19
+ return e && !A(e) ? e : null;
20
+ }
21
+ function H(t, e) {
22
+ const n = e.querySelectorAll("img").some((r) => a(r) && !!r.getStyle("max-height")) ? S(t) : null;
23
+ if (!n)
24
+ return;
25
+ const i = t.getDocumentModifier();
26
+ i.modifyCss(n).appendRule(p), i.apply(new h("Add the reco image mobile fit rule"));
27
+ }
28
+ const B = `[esd-extension-block-id="${c.IMAGE}"]`, L = /^\d+px$/;
29
+ function y(t) {
30
+ return O(t) && Number(t.getAttribute("height")) || 0;
31
+ }
32
+ function b(t) {
33
+ const e = y(t), o = a(t) ? t.getStyle("max-height") ?? "" : "";
34
+ return L.test(o) && e > 0 && o !== `${e}px`;
35
+ }
36
+ function U(t, e) {
37
+ const o = e.querySelectorAll(B).map((i) => i.querySelector("img")).filter(b);
38
+ if (!o.length)
39
+ return;
40
+ const n = t.getDocumentModifier();
41
+ o.forEach((i) => n.modifyHtml(i).setStyle("max-height", `${y(i)}px`)), n.apply(new h("Sync the reco image height bound").asHidden());
42
+ }
43
+ class D extends C(
44
+ g.IMAGE_SIZE,
45
+ c.IMAGE,
46
+ l
47
+ ) {
48
+ getAdditionalModifications(e) {
49
+ if (this.api.getEditorState()[E.previewDeviceMode] === I.MOBILE)
50
+ return;
51
+ const o = this.getFitStyles(), n = this.getTargetNodes(e).map((s) => s.querySelector("img")).filter((s) => T(s, o)), i = o["max-height"] ? S(this.api) : null;
52
+ if (!n.length && !i)
53
+ return;
54
+ const r = this.api.getDocumentModifier();
55
+ return i && r.modifyCss(i).appendRule(p), n.forEach((s) => {
56
+ const m = r.modifyHtml(s);
57
+ Object.entries(o).forEach(([u, d]) => {
58
+ d ? m.setStyle(u, d) : m.removeStyle(u);
59
+ });
60
+ }), r;
61
+ }
62
+ getFitStyles() {
63
+ const { size: e } = this.api.getValues();
64
+ return (e == null ? void 0 : e.type) === "height" && e.value ? _(e.value) : R;
65
+ }
66
+ }
67
+ const F = M(
68
+ g.IMAGE_MARGINS,
69
+ c.IMAGE,
70
+ l
71
+ ), P = {
72
+ size: D,
73
+ margins: F
16
74
  };
17
75
  export {
18
- C as ImageControls
76
+ P as ImageControls,
77
+ H as ensureMobileFitRule,
78
+ U as syncHeightBound
19
79
  };
@@ -1,10 +1,10 @@
1
1
  import { extractWrapperTags as A } from "../../../../utils/preserveTextStyles.js";
2
2
  import { RecommendationBlockId as c } from "../constants/blockIds.js";
3
- import { DESKTOP_CONTAINER_SELECTOR as b, ATTR_PRODUCT_NAME as k, ATTR_PRODUCT_PRICE as y, ATTR_PRODUCT_OLD_PRICE as p, ATTR_PRODUCT_OMNIBUS_PRICE as R, ATTR_PRODUCT_OMNIBUS_DISCOUNT as _, ATTR_PRODUCT_BUTTON as x, ATTR_PRODUCT_IMAGE as q, ATTR_PRODUCT_ATTR as v } from "../constants/selectors.js";
3
+ import { DESKTOP_CONTAINER_SELECTOR as g, ATTR_PRODUCT_NAME as k, ATTR_PRODUCT_PRICE as y, ATTR_PRODUCT_OLD_PRICE as p, ATTR_PRODUCT_OMNIBUS_PRICE as R, ATTR_PRODUCT_OMNIBUS_DISCOUNT as _, ATTR_PRODUCT_BUTTON as x, ATTR_PRODUCT_IMAGE as q, ATTR_PRODUCT_ATTR as v } from "../constants/selectors.js";
4
4
  import { CSS_CLASS_TEXT_TRIM as B } from "../controls/shared/textTrimCssRules.js";
5
5
  import { toCustomCompositionKey as U } from "../templates/utils.js";
6
6
  import { resolveRowVisibilityKeys as N, isMergedInlinePriceRow as C } from "./compositionKeys.js";
7
- import { hasQuerySelectorAll as I, hasGetAttribute as l, hasGetStyle as O, hasGetComputedStyle as M } from "./tagName.js";
7
+ import { hasQuerySelectorAll as I, hasGetAttribute as l, hasGetStyle as h, hasGetComputedStyle as M } from "./tagName.js";
8
8
  const s = [
9
9
  "font-size",
10
10
  "font-family",
@@ -37,9 +37,10 @@ const s = [
37
37
  "width",
38
38
  "height",
39
39
  "max-width",
40
+ "max-height",
40
41
  "border-radius",
41
42
  "margin"
42
- ], g = /* @__PURE__ */ new Set(["transparent", "rgba(0, 0, 0, 0)"]), L = [
43
+ ], b = /* @__PURE__ */ new Set(["transparent", "rgba(0, 0, 0, 0)"]), L = [
43
44
  { attrKey: k, blockId: c.NAME, kind: "text" },
44
45
  { attrKey: y, blockId: c.PRICE, kind: "text" },
45
46
  { attrKey: p, blockId: c.OLD_PRICE, kind: "text" },
@@ -48,14 +49,14 @@ const s = [
48
49
  { attrKey: x, blockId: c.BUTTON, kind: "button" },
49
50
  { attrKey: q, blockId: c.IMAGE, kind: "image" }
50
51
  ];
51
- function h(t) {
52
+ function O(t) {
52
53
  return t && "getInnerHTML" in t && typeof t.getInnerHTML == "function" ? t.getInnerHTML().trim() : "";
53
54
  }
54
55
  function K(t) {
55
56
  return t && "getInnerText" in t && typeof t.getInnerText == "function" ? t.getInnerText().trim() : "";
56
57
  }
57
58
  function a(t, e, r) {
58
- !e || !O(e) || r.forEach((n) => {
59
+ !e || !h(e) || r.forEach((n) => {
59
60
  const o = e.getStyle(n);
60
61
  o && o !== "inherit" && o !== "initial" && (t[n] = o);
61
62
  });
@@ -64,10 +65,10 @@ function E(t) {
64
65
  return Object.entries(t).map(([e, r]) => `${e}: ${r};`).join(" ");
65
66
  }
66
67
  function P(t) {
67
- if (!t || !O(t))
68
+ if (!t || !h(t))
68
69
  return;
69
70
  const e = t.getStyle("background-color") || t.getStyle("background");
70
- return e && !g.has(e) ? e : void 0;
71
+ return e && !b.has(e) ? e : void 0;
71
72
  }
72
73
  function S(t, e) {
73
74
  const r = {};
@@ -76,11 +77,11 @@ function S(t, e) {
76
77
  function $(t) {
77
78
  const e = t.querySelector("p"), r = {};
78
79
  a(r, t, s), a(r, e, s), a(r, t.querySelector("strong"), s), a(r, t.querySelector("em"), s), a(r, t.querySelector("s"), s);
79
- const n = E(r), { openTags: o, closeTags: i } = A(h(e));
80
+ const n = E(r), { openTags: o, closeTags: i } = A(O(e));
80
81
  return !n && !o ? null : { pStyle: n || void 0, openTags: o, closeTags: i };
81
82
  }
82
83
  function H(t) {
83
- const e = t.querySelector(".es-button-border"), r = t.querySelector("a.es-button") ?? t.querySelector("a"), n = S(e, D), o = S(r, w), i = e && "getAttribute" in e ? e.getAttribute("class") ?? "" : "", u = /\bes-fw\b/.test(i), { openTags: T, closeTags: d } = A(h(r)), m = K(r);
84
+ const e = t.querySelector(".es-button-border"), r = t.querySelector("a.es-button") ?? t.querySelector("a"), n = S(e, D), o = S(r, w), i = e && "getAttribute" in e ? e.getAttribute("class") ?? "" : "", u = /\bes-fw\b/.test(i), { openTags: T, closeTags: d } = A(O(r)), m = K(r);
84
85
  return !n && !o && !u && !T && !m ? null : {
85
86
  buttonBorderStyle: n || void 0,
86
87
  buttonAnchorStyle: o || void 0,
@@ -100,7 +101,7 @@ function j(t, e) {
100
101
  function f(t, e) {
101
102
  if (!t || !("querySelector" in t))
102
103
  return;
103
- const r = t.querySelector(b) ?? t;
104
+ const r = t.querySelector(g) ?? t;
104
105
  if (L.forEach(({ attrKey: i, blockId: u, kind: T }) => {
105
106
  const d = r.querySelector(`[esd-extension-block-id="${u}"]`);
106
107
  d && e(d, i, T);
@@ -126,20 +127,20 @@ function V(t) {
126
127
  function X(t) {
127
128
  if (!t || !("querySelector" in t))
128
129
  return;
129
- const e = t.querySelector(b) ?? t, r = e.querySelector(".product-card-segment") ?? e.querySelector(".product-card-wrapper");
130
+ const e = t.querySelector(g) ?? t, r = e.querySelector(".product-card-segment") ?? e.querySelector(".product-card-wrapper");
130
131
  return P(r);
131
132
  }
132
133
  function z(t) {
133
134
  if (!t)
134
135
  return;
135
136
  const e = l(t) ? t.getAttribute("bgcolor") : null;
136
- if (e && !g.has(e))
137
+ if (e && !b.has(e))
137
138
  return e;
138
139
  const r = P(t);
139
140
  if (r)
140
141
  return r;
141
142
  const n = M(t) ? t.getComputedStyle("background-color") : void 0;
142
- return n && !g.has(n) ? n : void 0;
143
+ return n && !b.has(n) ? n : void 0;
143
144
  }
144
145
  function Q(t) {
145
146
  const e = {};
@@ -170,7 +171,7 @@ function J(t) {
170
171
  function Z(t) {
171
172
  if (!t || !("querySelector" in t))
172
173
  return !1;
173
- const e = t.querySelector(b) ?? t;
174
+ const e = t.querySelector(g) ?? t;
174
175
  return C(e.querySelector(`[data-attribute-type="${y}"]`)) || C(e.querySelector(`[data-attribute-type="${p}"]`));
175
176
  }
176
177
  function tt(t) {
@@ -195,7 +196,7 @@ function rt(t) {
195
196
  const e = {};
196
197
  if (!t || !("querySelector" in t))
197
198
  return e;
198
- const r = t.querySelector(b) ?? t;
199
+ const r = t.querySelector(g) ?? t;
199
200
  return I(r) && r.querySelectorAll(".recommendation-attribute-row").forEach((n) => {
200
201
  if (!l(n))
201
202
  return;
@@ -64,6 +64,8 @@ export declare class RecommendationBlock extends Block {
64
64
  * @param node - The block node being deleted
65
65
  */
66
66
  onDelete(node: ImmutableHtmlNode): void;
67
+ private _ensureMobileFitRule;
68
+ private _syncHeightBound;
67
69
  /**
68
70
  * Warns (dark advisory toaster) when the design holds more than one live
69
71
  * recommendation block. Triggered from the user-add paths only (fresh drop
@@ -3,35 +3,49 @@
3
3
  *
4
4
  * Controls for styling the product image element in recommendation cards.
5
5
  */
6
+ import type { CssNodeModifier, HtmlNodeModifier, ImmutableCssNode, ImmutableHtmlNode, TemplateModifier } from '@stripoinc/ui-editor-extensions';
7
+ import { ModificationDescription } from '@stripoinc/ui-editor-extensions';
8
+ interface FitRuleApi {
9
+ getDocumentRootCssNode: () => ImmutableCssNode | null;
10
+ getDocumentModifier: () => TemplateModifier<HtmlNodeModifier, CssNodeModifier>;
11
+ }
12
+ export declare function ensureMobileFitRule(api: FitRuleApi, block: ImmutableHtmlNode): void;
13
+ export declare function syncHeightBound(api: Pick<FitRuleApi, 'getDocumentModifier'>, block: ImmutableHtmlNode): void;
14
+ declare const SizeControl_base: {
15
+ new (): {
16
+ getId(): string;
17
+ getTargetNodes(root: ImmutableHtmlNode): ImmutableHtmlNode[];
18
+ getParentControlId(): string;
19
+ api: import("@stripoinc/ui-editor-extensions").ControlApi;
20
+ getLabels(): import("@stripoinc/ui-editor-extensions").ControlLabels | undefined;
21
+ getModificationDescription(): ModificationDescription | undefined;
22
+ getAdditionalModifications(_root: ImmutableHtmlNode): TemplateModifier<HtmlNodeModifier, CssNodeModifier> | undefined;
23
+ isVisible(_node: ImmutableHtmlNode): boolean;
24
+ getElementLockCategory(): import("@stripoinc/ui-editor-extensions").ElementLockCategory | undefined;
25
+ };
26
+ };
27
+ declare class SizeControl extends SizeControl_base {
28
+ getAdditionalModifications(root: ImmutableHtmlNode): TemplateModifier<HtmlNodeModifier, CssNodeModifier> | undefined;
29
+ private getFitStyles;
30
+ }
6
31
  /**
7
32
  * Grouped Image Controls
8
33
  * Use this object for cleaner imports in extension.ts
9
34
  */
10
35
  export declare const ImageControls: {
11
- readonly size: {
12
- new (): {
13
- getId(): string;
14
- getTargetNodes(root: import("@stripoinc/ui-editor-extensions").ImmutableHtmlNode): import("@stripoinc/ui-editor-extensions").ImmutableHtmlNode[];
15
- getParentControlId(): string;
16
- api: import("@stripoinc/ui-editor-extensions").ControlApi;
17
- getLabels(): import("@stripoinc/ui-editor-extensions").ControlLabels | undefined;
18
- getModificationDescription(): import("@stripoinc/ui-editor-extensions").ModificationDescription | undefined;
19
- getAdditionalModifications(_root: import("@stripoinc/ui-editor-extensions").ImmutableHtmlNode): import("@stripoinc/ui-editor-extensions").TemplateModifier<import("@stripoinc/ui-editor-extensions").HtmlNodeModifier, import("@stripoinc/ui-editor-extensions").CssNodeModifier> | undefined;
20
- isVisible(_node: import("@stripoinc/ui-editor-extensions").ImmutableHtmlNode): boolean;
21
- getElementLockCategory(): import("@stripoinc/ui-editor-extensions").ElementLockCategory | undefined;
22
- };
23
- };
36
+ readonly size: typeof SizeControl;
24
37
  readonly margins: {
25
38
  new (): {
26
39
  getId(): string;
27
- getTargetNodes(root: import("@stripoinc/ui-editor-extensions").ImmutableHtmlNode): import("@stripoinc/ui-editor-extensions").ImmutableHtmlNode[];
40
+ getTargetNodes(root: ImmutableHtmlNode): ImmutableHtmlNode[];
28
41
  getParentControlId(): string;
29
42
  api: import("@stripoinc/ui-editor-extensions").ControlApi;
30
43
  getLabels(): import("@stripoinc/ui-editor-extensions").ControlLabels | undefined;
31
- getModificationDescription(): import("@stripoinc/ui-editor-extensions").ModificationDescription | undefined;
32
- getAdditionalModifications(_root: import("@stripoinc/ui-editor-extensions").ImmutableHtmlNode): import("@stripoinc/ui-editor-extensions").TemplateModifier<import("@stripoinc/ui-editor-extensions").HtmlNodeModifier, import("@stripoinc/ui-editor-extensions").CssNodeModifier> | undefined;
33
- isVisible(_node: import("@stripoinc/ui-editor-extensions").ImmutableHtmlNode): boolean;
44
+ getModificationDescription(): ModificationDescription | undefined;
45
+ getAdditionalModifications(_root: ImmutableHtmlNode): TemplateModifier<HtmlNodeModifier, CssNodeModifier> | undefined;
46
+ isVisible(_node: ImmutableHtmlNode): boolean;
34
47
  getElementLockCategory(): import("@stripoinc/ui-editor-extensions").ElementLockCategory | undefined;
35
48
  };
36
49
  };
37
50
  };
51
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useinsider/guido",
3
- "version": "3.21.1",
3
+ "version": "3.21.2",
4
4
  "description": "Guido is a Vue + TypeScript wrapper for Email Plugin. Easily embed the email editor in your Vue applications.",
5
5
  "main": "./dist/guido.umd.cjs",
6
6
  "module": "./dist/library.js",