@useinsider/guido 3.22.0 → 3.23.0

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 (70) hide show
  1. package/README.md +35 -4
  2. package/dist/components/Guido.vue.js +1 -1
  3. package/dist/components/Guido.vue2.js +118 -108
  4. package/dist/components/organisms/unsubscribe/UnsubscribePageSelection.vue.js +11 -11
  5. package/dist/components/organisms/unsubscribe/UnsubscribePageSelection.vue2.js +9 -9
  6. package/dist/composables/useEditorOpenMetrics.js +167 -0
  7. package/dist/composables/useStripo.js +93 -82
  8. package/dist/config/compiler/utils/recommendationCompilerUtils.js +22 -22
  9. package/dist/config/migrator/recommendation/compositionMapper.js +56 -49
  10. package/dist/config/migrator/recommendation/extractors.js +100 -40
  11. package/dist/config/migrator/recommendation/htmlBuilder.js +285 -207
  12. package/dist/config/migrator/recommendation/settingsMapper.js +37 -36
  13. package/dist/config/migrator/recommendation/themeMapper.js +53 -41
  14. package/dist/config/migrator/recommendationMigrator.js +68 -61
  15. package/dist/extensions/Blocks/Items/controls/button/link.js +14 -17
  16. package/dist/extensions/Blocks/Items/controls/cardComposition.js +14 -17
  17. package/dist/extensions/Blocks/Items/controls/image/link.js +14 -17
  18. package/dist/extensions/Blocks/Items/controls/name/trimming.js +9 -10
  19. package/dist/extensions/Blocks/Items/controls/price/currencyLocation.js +24 -25
  20. package/dist/extensions/Blocks/Items/controls/price/currencySymbol.js +12 -13
  21. package/dist/extensions/Blocks/Items/controls/price/formattedPrice.js +29 -30
  22. package/dist/extensions/Blocks/Items/controls/price/hideDiscount.js +15 -16
  23. package/dist/extensions/Blocks/Items/controls/price/priceOrientation.js +25 -26
  24. package/dist/extensions/Blocks/Items/controls/price/singlePrice.js +27 -28
  25. package/dist/extensions/Blocks/Items/controls/settingsControl.js +75 -80
  26. package/dist/extensions/Blocks/Recommendation/block.js +33 -24
  27. package/dist/extensions/Blocks/Recommendation/controls/cardBackground/index.js +3 -3
  28. package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +27 -26
  29. package/dist/extensions/Blocks/Recommendation/controls/customAttribute/textTrim.js +13 -13
  30. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +165 -175
  31. package/dist/extensions/Blocks/Recommendation/controls/name/textTrim.js +5 -5
  32. package/dist/extensions/Blocks/Recommendation/controls/omnibusDiscount/textAfter.js +8 -8
  33. package/dist/extensions/Blocks/Recommendation/controls/omnibusDiscount/textBefore.js +15 -15
  34. package/dist/extensions/Blocks/Recommendation/controls/omnibusPrice/textAfter.js +12 -12
  35. package/dist/extensions/Blocks/Recommendation/controls/omnibusPrice/textBefore.js +10 -10
  36. package/dist/extensions/Blocks/Recommendation/controls/spacing/index.js +1 -1
  37. package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +23 -22
  38. package/dist/extensions/Blocks/Recommendation/templates/list/template.js +19 -18
  39. package/dist/extensions/Blocks/Recommendation/templates/utils.js +82 -91
  40. package/dist/extensions/Blocks/Recommendation/utils/inlinePriceOrder.js +12 -0
  41. package/dist/extensions/Blocks/Recommendation/utils/legacyStrategyMap.js +3 -2
  42. package/dist/extensions/Blocks/common-control.js +62 -55
  43. package/dist/guido.css +1 -1
  44. package/dist/library.js +12 -10
  45. package/dist/package.json.js +6 -4
  46. package/dist/public/prefetchRuntime.js +4 -0
  47. package/dist/src/composables/useEditorOpenMetrics.d.ts +27 -0
  48. package/dist/src/composables/useStripo.d.ts +2 -1
  49. package/dist/src/config/migrator/recommendation/compositionMapper.d.ts +3 -1
  50. package/dist/src/config/migrator/recommendation/extractors.d.ts +35 -6
  51. package/dist/src/config/migrator/recommendation/htmlBuilder.d.ts +3 -1
  52. package/dist/src/config/migrator/recommendation/themeMapper.d.ts +3 -1
  53. package/dist/src/config/migrator/recommendation/types.d.ts +11 -1
  54. package/dist/src/extensions/Blocks/Items/controls/cardComposition.d.ts +0 -1
  55. package/dist/src/extensions/Blocks/Recommendation/block.d.ts +1 -0
  56. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +5 -10
  57. package/dist/src/extensions/Blocks/Recommendation/templates/utils.d.ts +1 -13
  58. package/dist/src/extensions/Blocks/Recommendation/utils/inlinePriceOrder.d.ts +9 -0
  59. package/dist/src/extensions/Blocks/Recommendation/utils/legacyStrategyMap.d.ts +2 -19
  60. package/dist/src/extensions/Blocks/common-control.d.ts +2 -0
  61. package/dist/src/library.d.ts +1 -0
  62. package/dist/src/public/prefetchRuntime.d.ts +1 -0
  63. package/dist/src/stores/unsubscribe.d.ts +10 -0
  64. package/dist/src/utils/runtimePrefetch.d.ts +4 -0
  65. package/dist/src/utils/stripoRuntime.d.ts +3 -0
  66. package/dist/static/stripo-runtime-manifest.json.js +9 -0
  67. package/dist/stores/unsubscribe.js +33 -29
  68. package/dist/utils/runtimePrefetch.js +26 -0
  69. package/dist/utils/stripoRuntime.js +13 -0
  70. package/package.json +7 -2
@@ -3,9 +3,10 @@ function r(e) {
3
3
  return e;
4
4
  switch (e) {
5
5
  case "viewedTogether":
6
- return "similarViewed";
7
6
  case "purchasedTogether":
8
- return "similarBought";
7
+ case "similarViewed":
8
+ case "similarBought":
9
+ return "mostPopular";
9
10
  case "trending":
10
11
  return "trendingProducts";
11
12
  case "mostValuable":
@@ -1,12 +1,14 @@
1
- var c = Object.defineProperty;
2
- var i = (l, a, e) => a in l ? c(l, a, { enumerable: !0, configurable: !0, writable: !0, value: e }) : l[a] = e;
3
- var T = (l, a, e) => i(l, typeof a != "symbol" ? a + "" : a, e);
1
+ var u = Object.defineProperty;
2
+ var c = (l, E, e) => E in l ? u(l, E, { enumerable: !0, configurable: !0, writable: !0, value: e }) : l[E] = e;
3
+ var i = (l, E, e) => c(l, typeof E != "symbol" ? E + "" : E, e);
4
4
  import { Control as I, UIElementType as n, UEAttr as $ } from "../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
5
5
  class _ extends I {
6
6
  constructor() {
7
7
  super(...arguments);
8
- T(this, "currentNode");
9
- T(this, "lastBlockInstanceId", null);
8
+ i(this, "currentNode");
9
+ i(this, "lastBlockInstanceId", null);
10
+ // Set until the control handles the node Stripo hands a freshly rendered panel.
11
+ i(this, "isAwaitingPanelNode", !1);
10
12
  }
11
13
  getContainer() {
12
14
  var e;
@@ -18,6 +20,11 @@ class _ extends I {
18
20
  onDestroy() {
19
21
  this.lastBlockInstanceId = null;
20
22
  }
23
+ // Stripo renders a panel before it hands that panel its node, so a node still held is the last
24
+ // panel's and may be disposed. Controls Stripo renders call this first in onRender.
25
+ forgetLastPanelNode() {
26
+ this.currentNode = void 0, this.isAwaitingPanelNode = !0;
27
+ }
21
28
  /**
22
29
  * Gets the Items block container element from the current node.
23
30
  * @returns The container element or null if not found
@@ -44,18 +51,18 @@ class _ extends I {
44
51
  * @returns true if block instance changed, false otherwise
45
52
  */
46
53
  handleBlockInstanceChange(e) {
47
- const t = this.getBlockInstanceId();
48
- if (!t)
49
- return !1;
50
- const E = t !== this.lastBlockInstanceId;
51
- return e(), E && (this.lastBlockInstanceId = t), E;
54
+ const t = this.getBlockInstanceId(), o = this.isAwaitingPanelNode;
55
+ if (this.isAwaitingPanelNode = !1, !t)
56
+ return o && e(), !1;
57
+ const a = t !== this.lastBlockInstanceId;
58
+ return e(), a && (this.lastBlockInstanceId = t), a;
52
59
  }
53
- _GuLabel({ text: e, name: t = "", hint: E }) {
60
+ _GuLabel({ text: e, name: t = "", hint: o }) {
54
61
  return `
55
62
  <${n.LABEL}
56
63
  ${$.LABEL.text}="${e}"
57
64
  ${$.LABEL.name}="${t || `${e} Label`}"
58
- ${E ? `${$.LABEL.hint}="${E}"` : ""}>
65
+ ${o ? `${$.LABEL.hint}="${o}"` : ""}>
59
66
  </${n.LABEL}>
60
67
  `;
61
68
  }
@@ -73,7 +80,7 @@ class _ extends I {
73
80
  * Use in getTemplate() — the icon is registered in a hidden store so Stripo initializes it.
74
81
  * Pair with _setInfoMessageValue() in onRender() to set the text content.
75
82
  */
76
- _GuOnPageMessage({ name: e, icon: t = "not-found", type: E = "info" }) {
83
+ _GuOnPageMessage({ name: e, icon: t = "not-found", type: o = "info" }) {
77
84
  return `
78
85
  <div data-info-message="${e}" style="display: none; padding: 16px 16px 0;">
79
86
  <div class="icon-store" style="display: none;">
@@ -81,7 +88,7 @@ class _ extends I {
81
88
  ${this._GuIcon({ src: t, className: "icon" })}
82
89
  </div>
83
90
  </div>
84
- ${this._GuMessage({ name: e, type: E })}
91
+ ${this._GuMessage({ name: e, type: o })}
85
92
  </div>
86
93
  `;
87
94
  }
@@ -91,21 +98,21 @@ class _ extends I {
91
98
  * and combines it with the text in Stripo's alert-message layout.
92
99
  */
93
100
  _setInfoMessageValue(e, t) {
94
- const E = this.getContainer(), o = E.querySelector(`[data-icon-key="${e}"]`), r = o == null ? void 0 : o.querySelector("ue-icon-component"), s = (r == null ? void 0 : r.outerHTML) ?? "";
101
+ const o = this.getContainer(), a = o.querySelector(`[data-icon-key="${e}"]`), s = a == null ? void 0 : a.querySelector("ue-icon-component"), r = (s == null ? void 0 : s.outerHTML) ?? "";
95
102
  this.api.setUIEAttribute(
96
103
  e,
97
104
  "value",
98
105
  `
99
106
  <div class="service-element alert-message-main" style="align-items: start;">
100
- ${s}
107
+ ${r}
101
108
  <div class="service-element alert-message-text">
102
109
  ${t}
103
110
  </div>
104
111
  </div>
105
112
  `
106
113
  );
107
- const u = E.querySelector(`[data-info-message="${e}"]`);
108
- u && (u.style.display = "");
114
+ const T = o.querySelector(`[data-info-message="${e}"]`);
115
+ T && (T.style.display = "");
109
116
  }
110
117
  _GuToggle(e) {
111
118
  return `
@@ -124,66 +131,66 @@ class _ extends I {
124
131
  _GuSelect({
125
132
  name: e,
126
133
  placeholder: t,
127
- options: E,
128
- className: o = "es-180w",
129
- searchable: r = !1
134
+ options: o,
135
+ className: a = "es-180w",
136
+ searchable: s = !1
130
137
  }) {
131
138
  return `
132
139
  <${n.SELECTPICKER}
133
- class="${o}"
140
+ class="${a}"
134
141
  ${$.SELECTPICKER.name}="${e}"
135
- ${r ? `${$.SELECTPICKER.searchable}="true"` : ""}
142
+ ${s ? `${$.SELECTPICKER.searchable}="true"` : ""}
136
143
  ${$.SELECTPICKER.placeholder}="${t}">
137
- ${E.map((s) => this._GuSelectItem(s)).join("")}
144
+ ${o.map((r) => this._GuSelectItem(r)).join("")}
138
145
  </${n.SELECTPICKER}>
139
146
  `;
140
147
  }
141
- _GuTextInput({ name: e, placeholder: t, className: E = "", disabled: o = !1 }) {
148
+ _GuTextInput({ name: e, placeholder: t, className: o = "", disabled: a = !1 }) {
142
149
  return `
143
150
  <${n.TEXT}
144
- class=${E}
151
+ class=${o}
145
152
  ${$.TEXT.name}="${e}"
146
153
  placeholder="${t || e}"
147
- ${o ? `${$.TEXT.disabled}="true"` : ""}>
154
+ ${a ? `${$.TEXT.disabled}="true"` : ""}>
148
155
  </${n.TEXT}>
149
156
  `;
150
157
  }
151
- _GuCounter({ name: e, maxValue: t, minValue: E = 1, step: o = 1 }) {
158
+ _GuCounter({ name: e, maxValue: t, minValue: o = 1, step: a = 1 }) {
152
159
  return `
153
160
  <${n.COUNTER}
154
161
  ${$.COUNTER.name}="${e}"
155
- ${$.COUNTER.minValue}="${E}"
162
+ ${$.COUNTER.minValue}="${o}"
156
163
  ${$.COUNTER.maxValue}="${t}"
157
- ${$.COUNTER.step}="${o}">
164
+ ${$.COUNTER.step}="${a}">
158
165
  </${n.COUNTER}>
159
166
  `;
160
167
  }
161
- _GuRadioButtonItem({ text: e, value: t, icon: E }) {
168
+ _GuRadioButtonItem({ text: e, value: t, icon: o }) {
162
169
  return `
163
170
  <${n.RADIO_ITEM}
164
171
  ${$.RADIO_ITEM.value}="${t}"
165
172
  ${e ? `${$.RADIO_ITEM.text}="${e}"` : ""}
166
- ${E ? `${$.RADIO_ITEM.icon}="${E}"` : ""}>
173
+ ${o ? `${$.RADIO_ITEM.icon}="${o}"` : ""}>
167
174
  </${n.RADIO_ITEM}>
168
175
  `;
169
176
  }
170
- _GuRadioButton({ name: e, buttons: t, id: E = "" }) {
177
+ _GuRadioButton({ name: e, buttons: t, id: o = "" }) {
171
178
  return `
172
179
  <${n.RADIO_BUTTONS}
173
- ${E ? `id="${E}"` : ""}
180
+ ${o ? `id="${o}"` : ""}
174
181
  ${$.RADIO_BUTTONS.name}="${e}">
175
- ${t.map((o) => this._GuRadioButtonItem(o)).join("")}
182
+ ${t.map((a) => this._GuRadioButtonItem(a)).join("")}
176
183
  </${n.RADIO_BUTTONS}>
177
184
  `;
178
185
  }
179
- _GuButton({ name: e, label: t, id: E = "", className: o = "", icon: r = "", disabled: s = !1 }) {
186
+ _GuButton({ name: e, label: t, id: o = "", className: a = "", icon: s = "", disabled: r = !1 }) {
180
187
  return `
181
188
  <${n.BUTTON}
182
189
  ${$.BUTTON.name}="${e}"
183
- ${E ? `id="${E}"` : ""}
184
- ${o ? `class="${o}"` : ""}
185
- ${r ? `${$.BUTTON.icon}="${r}"` : ""}
186
- ${s ? `${$.BUTTON.disabled}="true"` : ""}
190
+ ${o ? `id="${o}"` : ""}
191
+ ${a ? `class="${a}"` : ""}
192
+ ${s ? `${$.BUTTON.icon}="${s}"` : ""}
193
+ ${r ? `${$.BUTTON.disabled}="true"` : ""}
187
194
  ${$.BUTTON.caption}="${t}">
188
195
  </${n.BUTTON}>
189
196
  `;
@@ -201,10 +208,10 @@ class _ extends I {
201
208
  * @param param0
202
209
  * @returns It returns a button with an icon.
203
210
  */
204
- _GuIconButton({ name: e, icon: t, className: E = "" }) {
211
+ _GuIconButton({ name: e, icon: t, className: o = "" }) {
205
212
  return `
206
213
  <${n.BUTTON}
207
- class="${E}"
214
+ class="${o}"
208
215
  ${$.BUTTON.name}="${e}"
209
216
  ${$.BUTTON.icon}="${t}">
210
217
  </${n.BUTTON}>
@@ -232,19 +239,19 @@ class _ extends I {
232
239
  * @returns HTML string for the orderable control
233
240
  */
234
241
  _GuOrderable(e, t) {
235
- let E = "";
236
- t.forEach((r) => {
237
- const s = $.ORDERABLE_ITEM && "name" in $.ORDERABLE_ITEM ? $.ORDERABLE_ITEM.name : "name";
238
- E += `
239
- <${n.ORDERABLE_ITEM} ${s}="${r.key}">
240
- ${r.content}
242
+ let o = "";
243
+ t.forEach((s) => {
244
+ const r = $.ORDERABLE_ITEM && "name" in $.ORDERABLE_ITEM ? $.ORDERABLE_ITEM.name : "name";
245
+ o += `
246
+ <${n.ORDERABLE_ITEM} ${r}="${s.key}">
247
+ ${s.content}
241
248
  </${n.ORDERABLE_ITEM}>
242
249
  `;
243
250
  });
244
- const o = $.ORDERABLE && "name" in $.ORDERABLE ? $.ORDERABLE.name : "name";
251
+ const a = $.ORDERABLE && "name" in $.ORDERABLE ? $.ORDERABLE.name : "name";
245
252
  return `
246
- <${n.ORDERABLE} ${o}="${e}">
247
- ${E}
253
+ <${n.ORDERABLE} ${a}="${e}">
254
+ ${o}
248
255
  </${n.ORDERABLE}>
249
256
  `;
250
257
  }
@@ -285,16 +292,16 @@ class _ extends I {
285
292
  `;
286
293
  }
287
294
  _GuRadioButtons(e, t) {
288
- const E = t.map((o) => `
295
+ const o = t.map((a) => `
289
296
  <${n.RADIO_ITEM}
290
- ${$.RADIO_ITEM.text}="${o.text}"
291
- ${$.RADIO_ITEM.value}="${o.value}">
297
+ ${$.RADIO_ITEM.text}="${a.text}"
298
+ ${$.RADIO_ITEM.value}="${a.value}">
292
299
  </${n.RADIO_ITEM}>
293
300
  `).join("");
294
301
  return `
295
302
  <${n.RADIO_BUTTONS}
296
303
  ${$.RADIO_BUTTONS.name}="${e}">
297
- ${E}
304
+ ${o}
298
305
  </${n.RADIO_BUTTONS}>
299
306
  `;
300
307
  }
package/dist/guido.css CHANGED
@@ -1 +1 @@
1
- @charset "UTF-8";.auth-error-modal[data-v-b4d7ae51]{position:relative;z-index:145}.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-b8f24f34] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-baf7a5dd]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.validation-error-list[data-v-e48cebe9]{gap:16px}.validation-error-row[data-v-e48cebe9]{gap:8px;padding:24px;border:1px solid #E1E1E1;border-radius:8px}.validation-error-row__icon[data-v-e48cebe9]{flex-shrink:0;font-size:24px;line-height:0}.validation-error-row__text[data-v-e48cebe9]{font-size:13px;line-height:16px;color:#292929;word-break:break-word}.guido-editor__wrapper[data-v-c5146fc5]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-c5146fc5]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-c5146fc5]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-19d8cb42] .vueperslides__bullets,[data-v-ec2027ff] .vueperslides__bullets,[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd]{width:100%;max-width:none}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd] .in-skeleton{width:100%!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd] .in-dropdown-box__container{width:413px}.assign-strategy-drawer .spaced-dot-sep{background-image:linear-gradient(90deg,#91949f 20%,#fff0 0);background-position:center bottom;background-repeat:repeat-x;background-size:5px 1px}.assign-strategy-drawer .spaced-dot-sep--top{background-position:center top}.assign-strategy-drawer .spaced-dot-sep--fc-n:first-child{background:none}.legacy-strategy-updated-modal[data-v-da2225a1]{position:relative;z-index:145}
1
+ @charset "UTF-8";.auth-error-modal[data-v-b4d7ae51]{position:relative;z-index:145}.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-b8f24f34] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-baf7a5dd]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.validation-error-list[data-v-e48cebe9]{gap:16px}.validation-error-row[data-v-e48cebe9]{gap:8px;padding:24px;border:1px solid #E1E1E1;border-radius:8px}.validation-error-row__icon[data-v-e48cebe9]{flex-shrink:0;font-size:24px;line-height:0}.validation-error-row__text[data-v-e48cebe9]{font-size:13px;line-height:16px;color:#292929;word-break:break-word}.guido-editor__wrapper[data-v-f2154cb6]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-f2154cb6]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-f2154cb6]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-eaf8e461]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-eaf8e461]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-eaf8e461]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-eaf8e461]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-eaf8e461]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-19d8cb42] .vueperslides__bullets,[data-v-ec2027ff] .vueperslides__bullets,[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd]{width:100%;max-width:none}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd] .in-skeleton{width:100%!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd] .in-dropdown-box__container{width:413px}.assign-strategy-drawer .spaced-dot-sep{background-image:linear-gradient(90deg,#91949f 20%,#fff0 0);background-position:center bottom;background-repeat:repeat-x;background-size:5px 1px}.assign-strategy-drawer .spaced-dot-sep--top{background-position:center top}.assign-strategy-drawer .spaced-dot-sep--fc-n:first-child{background:none}.legacy-strategy-updated-modal[data-v-da2225a1]{position:relative;z-index:145}
package/dist/library.js CHANGED
@@ -1,20 +1,22 @@
1
1
  import { default as a } from "./components/Guido.vue.js";
2
- import { MessageType as t, ProductType as d } from "./@types/config/schemas.js";
2
+ import { MessageType as t, ProductType as f } from "./@types/config/schemas.js";
3
3
  import "./@types/config/defaults.js";
4
- import { getValidationErrors as s, isValidConfig as p, parseConfig as g, parseConfigSafe as m, validateConfig as n } from "./@types/config/validator.js";
5
- import { assignTrackingIds as u, readTrackFloor as x, readTrackSeq as T } from "./utils/linkTrackingIds.js";
4
+ import { getValidationErrors as p, isValidConfig as s, parseConfig as m, parseConfigSafe as g, validateConfig as n } from "./@types/config/validator.js";
5
+ import { assignTrackingIds as l, readTrackFloor as x, readTrackSeq as c } from "./utils/linkTrackingIds.js";
6
6
  import { useGuidoEmailEditorStore as C } from "./stores/guido-email-editor.js";
7
+ import { prefetchGuidoRuntime as E } from "./utils/runtimePrefetch.js";
7
8
  export {
8
9
  a as Guido,
9
10
  t as MessageType,
10
- d as ProductType,
11
- u as assignTrackingIds,
12
- s as getValidationErrors,
13
- p as isValidConfig,
14
- g as parseConfig,
15
- m as parseConfigSafe,
11
+ f as ProductType,
12
+ l as assignTrackingIds,
13
+ p as getValidationErrors,
14
+ s as isValidConfig,
15
+ m as parseConfig,
16
+ g as parseConfigSafe,
17
+ E as prefetchGuidoRuntime,
16
18
  x as readTrackFloor,
17
- T as readTrackSeq,
19
+ c as readTrackSeq,
18
20
  C as useGuidoEmailEditorStore,
19
21
  n as validateConfig
20
22
  };
@@ -1,7 +1,9 @@
1
- const o = { stripo: { version: "2.81.1" } }, s = {
2
- guido: o
1
+ const o = "3.23.0", s = { stripo: { version: "2.81.1" } }, n = {
2
+ version: o,
3
+ guido: s
3
4
  };
4
5
  export {
5
- s as default,
6
- o as guido
6
+ n as default,
7
+ s as guido,
8
+ o as version
7
9
  };
@@ -0,0 +1,4 @@
1
+ import { prefetchGuidoRuntime as r } from "../utils/runtimePrefetch.js";
2
+ export {
3
+ r as prefetchGuidoRuntime
4
+ };
@@ -0,0 +1,27 @@
1
+ export type TimedOpenPhase = 'migration' | 'default_template' | 'timer_clone';
2
+ declare const PHASES: readonly ["setup", "host_ready", "migration_start", "migration_end", "default_template_start", "default_template_end", "timer_clone_start", "timer_clone_end", "plugin_start", "script_ready", "fonts_sync_ready", "blocks_config_ready", "init_editor", "token_start", "token_end", "ready"];
3
+ export type OpenPhase = typeof PHASES[number];
4
+ export type OpenOutcome = 'ready' | 'error' | 'abandoned';
5
+ export interface OpenContext {
6
+ partnerName: string;
7
+ productType: number;
8
+ templateId: string;
9
+ variationId: string;
10
+ }
11
+ export interface OpenTemplate {
12
+ html: string;
13
+ css: string;
14
+ forceRecreate: boolean;
15
+ }
16
+ export interface EditorOpenMetrics {
17
+ mark: (phase: OpenPhase) => void;
18
+ timed: <T>(phase: TimedOpenPhase, task: () => Promise<T>) => Promise<T>;
19
+ setContext: (context: OpenContext) => void;
20
+ setTemplate: (template: OpenTemplate) => void;
21
+ setScriptPreloaded: (preloaded: boolean) => void;
22
+ markReady: () => void;
23
+ markFailed: () => void;
24
+ dispose: () => void;
25
+ }
26
+ export declare const startEditorOpenMetrics: () => EditorOpenMetrics;
27
+ export {};
@@ -1,5 +1,6 @@
1
+ import type { EditorOpenMetrics } from '@@/Composables/useEditorOpenMetrics';
1
2
  import type { Metadata, Options, Template } from '@@/Types/stripo';
2
- export declare const useStripo: () => {
3
+ export declare const useStripo: (openMetrics: EditorOpenMetrics) => {
3
4
  initPlugin: (template: Template, metadata: Metadata, options: Options) => Promise<void>;
4
5
  preloadRuntime: () => void;
5
6
  };
@@ -1,2 +1,4 @@
1
1
  import { type LegacyVariable, type MappedComposition } from './types';
2
- export declare function mapComposition(variables: LegacyVariable[] | undefined): MappedComposition;
2
+ export declare function mapComposition(variables: LegacyVariable[] | undefined, { oldPriceFirst }?: {
3
+ oldPriceFirst?: boolean;
4
+ }): MappedComposition;
@@ -1,3 +1,4 @@
1
+ import type { LegacyPaddingViewport, LegacyVariable } from './types';
1
2
  export declare function extractTitleText(block: Element): string;
2
3
  /**
3
4
  * Fallback for legacy configs that carry no `p_recommendation_title` variable:
@@ -7,6 +8,31 @@ export declare function extractTitleText(block: Element): string;
7
8
  * @returns True when the legacy block renders a visible title
8
9
  */
9
10
  export declare function hasVisibleTitle(block: Element): boolean;
11
+ /**
12
+ * A rendered title container with no text showed the user no title, whatever the config's `hidden` flag says.
13
+ * @param block - The legacy recommendation block element
14
+ * @returns True when the legacy block renders an empty title container
15
+ */
16
+ export declare function hasEmptyTitle(block: Element): boolean;
17
+ /**
18
+ * Reads which price the legacy card renders first. Prices sharing a `positionIdx` are ordered by this.
19
+ * @param block - The legacy recommendation block element
20
+ * @returns True only when both prices render and the original price comes first
21
+ */
22
+ export declare function isOldPriceFirst(block: Element): boolean;
23
+ /**
24
+ * Reads the legacy "Move to next line" state from the rendered card, for blocks whose config does not carry it.
25
+ * @param block - The legacy recommendation block element
26
+ * @returns True only when both prices render in separate rows and neither row is laid out inline (`table-cell`)
27
+ */
28
+ export declare function isPriceOnNextLine(block: Element): boolean;
29
+ /**
30
+ * Legacy keeps the text color and the name's trim toggle in the rendered `<p>`, not in the config theme.
31
+ * @param variables - The legacy composition variables
32
+ * @param block - The legacy recommendation block element
33
+ * @returns The variables, with `textColor` / `textTrimming` filled from the rendered HTML where the theme lacks them
34
+ */
35
+ export declare function withRenderedTextTheme(variables: LegacyVariable[] | undefined, block: Element): LegacyVariable[] | undefined;
10
36
  /**
11
37
  * Card background lives on either the block (`bgcolor`/`style`) or per-card
12
38
  * cells (`.product-card`). Returns empty string when no background is set —
@@ -14,13 +40,16 @@ export declare function hasVisibleTitle(block: Element): boolean;
14
40
  */
15
41
  export declare function extractCardBgColor(block: Element): string;
16
42
  /**
17
- * Reads the legacy block's own `currency-*` attributes into a
18
- * `currencySettings`-shaped object that `mapCurrency` understands. Used as a
19
- * fallback when the external recommendationConfigs map has no entry for this
20
- * block, so the migrated block keeps its real currency instead of defaulting.
21
- * Returns undefined when the block carries no `currency` attribute.
43
+ * `currencySettings` for a block whose legacy config has none: the code and symbol come from the block,
44
+ * the formatting from the legacy editor's defaults, which it rendered without reading the block's attributes.
45
+ */
46
+ export declare function extractCurrencyFromBlock(block: Element): Record<string, string | number>;
47
+ /**
48
+ * Block padding as the legacy product row renders it, for configs whose theme has no `blockPadding`.
49
+ * @param block - The legacy recommendation block element
50
+ * @returns The row's `es-p{n}{side}` padding, or undefined when the block has no product row
22
51
  */
23
- export declare function extractCurrencyFromBlock(block: Element): Record<string, string> | undefined;
52
+ export declare function extractRenderedBlockPadding(block: Element): LegacyPaddingViewport | undefined;
24
53
  /**
25
54
  * True when a PM has manually opted the legacy block out of content
26
55
  * regeneration by adding the `ins-skip-compile` class. Detected before rebuild
@@ -1,4 +1,4 @@
1
- import type { MappedComposition } from './types';
1
+ import type { MappedBlockPadding, MappedComposition } from './types';
2
2
  import type { RecommendationNodeConfig } from '@@/Extensions/Blocks/Recommendation/types/nodeConfig';
3
3
  export declare function buildBlockHtml(params: {
4
4
  nodeConfig: RecommendationNodeConfig;
@@ -16,4 +16,6 @@ export declare function buildBlockHtml(params: {
16
16
  preserveInnerHtml?: string;
17
17
  /** Adds the `ins-skip-compile` opt-out class to the migrated block. */
18
18
  skipCompile?: boolean;
19
+ /** Legacy desktop block padding; without it the block keeps the default `es-p20`. */
20
+ blockPadding?: MappedBlockPadding;
19
21
  }): string;
@@ -1,5 +1,7 @@
1
- import type { LegacyButtonTheme, LegacyImageTheme, LegacyTextTheme, MappedButtonStyle, MappedImageStyle, MappedTextStyle } from './types';
1
+ import type { LegacyButtonTheme, LegacyImageTheme, LegacyPaddingViewport, LegacyTextTheme, MappedBlockPadding, MappedButtonStyle, MappedImageStyle, MappedTextStyle } from './types';
2
2
  export declare function mapTextTheme(theme: LegacyTextTheme | undefined): MappedTextStyle;
3
3
  export declare function mapButtonTheme(theme: LegacyButtonTheme | undefined): MappedButtonStyle;
4
4
  export declare function mapImageTheme(theme: LegacyImageTheme | undefined): MappedImageStyle;
5
+ /** Stripo `es-p{n}{side}` classes where a step class exists, inline `padding-{side}` otherwise; 0 needs neither. */
6
+ export declare function mapBlockPadding(padding: LegacyPaddingViewport | undefined): MappedBlockPadding | undefined;
5
7
  export declare function appendStyle(existing: string | undefined, addition: string | undefined): string;
@@ -30,7 +30,9 @@ export interface LegacyPadding {
30
30
  /** Border-radius shape — observed in two flavours: shorthand or per-corner. */
31
31
  export interface LegacyBorderRadius {
32
32
  /** Single shorthand value (e.g. `radius: 4`). */
33
- radius?: number;
33
+ radius?: number | string;
34
+ /** Shorthand the legacy button theme stores under `theme.borderRadius` (e.g. `borderRadius: "4"`). */
35
+ borderRadius?: number | string;
34
36
  /** Per-corner: top-left / top-right / bottom-right / bottom-left (in px). */
35
37
  lt?: number;
36
38
  rt?: number;
@@ -96,6 +98,7 @@ export interface LegacyButtonTheme {
96
98
  color?: LegacySides<string>;
97
99
  };
98
100
  buttonBorderRadius?: LegacyBorderRadius;
101
+ borderRadius?: LegacyBorderRadius;
99
102
  buttonAlign?: {
100
103
  align?: string;
101
104
  };
@@ -167,6 +170,13 @@ export interface MappedTextStyle {
167
170
  /** True if `textTrimming: true` in theme. */
168
171
  textTrimming: boolean;
169
172
  }
173
+ /** Resolved block wrapper padding. */
174
+ export interface MappedBlockPadding {
175
+ /** Space-separated `es-p{n}{side}` classes. */
176
+ classes: string;
177
+ /** Inline `padding-{side}` declarations for values without a step class. */
178
+ style: string;
179
+ }
170
180
  /** Resolved button styles. */
171
181
  export interface MappedButtonStyle {
172
182
  /** Inline CSS for outer `<td>` (external padding). */
@@ -11,7 +11,6 @@ export declare class ItemsBlockCardCompositionControl extends CommonControl {
11
11
  name: string;
12
12
  label: string;
13
13
  }): string;
14
- _initializeToggles(): void;
15
14
  _updateTogglesFromState(): void;
16
15
  _syncVisibilityFromAttributes(): void;
17
16
  /**
@@ -65,6 +65,7 @@ export declare class RecommendationBlock extends Block {
65
65
  */
66
66
  onDelete(node: ImmutableHtmlNode): void;
67
67
  private _ensureMobileFitRule;
68
+ private _ensureTextTrimCss;
68
69
  private _syncHeightBound;
69
70
  /**
70
71
  * Warns (dark advisory toaster) when the design holds more than one live
@@ -42,7 +42,7 @@ export declare class RecommendationBlockControl extends CommonControl {
42
42
  private get _subControls();
43
43
  getTemplate(): string;
44
44
  private _showControlsForBlock;
45
- onRender(): Promise<void>;
45
+ onRender(): void;
46
46
  onTemplateNodeUpdated(node: ImmutableHtmlNode): void;
47
47
  onDestroy(): void;
48
48
  /**
@@ -50,6 +50,7 @@ export declare class RecommendationBlockControl extends CommonControl {
50
50
  * Each sub-control manages its own form values and event listeners
51
51
  */
52
52
  private _initializeSubControls;
53
+ private _renderWithPanelNode;
53
54
  /**
54
55
  * Syncs persisted node config into the Pinia store's block state.
55
56
  *
@@ -115,20 +116,14 @@ export declare class RecommendationBlockControl extends CommonControl {
115
116
  * 2. Smart defaults for new blocks (currency, algorithm) — sequential
116
117
  * 3. Product data with correct defaults — sequential
117
118
  *
118
- * Shared by onRender() and onTemplateNodeUpdated() to avoid duplication.
119
+ * Called from onTemplateNodeUpdated() once the node config is synced.
119
120
  * Marks the block as initialized to prevent redundant fetches on re-selection.
120
121
  */
121
122
  private _fetchBlockData;
122
123
  private _isPanelOn;
123
124
  /**
124
- * Applies smart defaults for newly dropped blocks.
125
- *
126
- * For new blocks (config still matches hardcoded defaults), validates that
127
- * the default currency and algorithm are available from the API response.
128
- * If not, falls back to the first available option.
129
- *
130
- * Saved templates with user-customized config are left unchanged because
131
- * their values won't match the hardcoded defaults.
125
+ * Falls back to the first available option when the block's currency or locale is not offered (a new block on
126
+ * the hard-coded default, or a block copied from another account). Only the default strategy gets an algorithm.
132
127
  */
133
128
  private _applySmartDefaults;
134
129
  /**
@@ -1,6 +1,7 @@
1
1
  import type { CurrencyConfig } from '../types/nodeConfig';
2
2
  import type { FiltersResponse, RecommendationProduct } from '@@/Types/recommendation';
3
3
  import { ATTR_PRODUCT_IMAGE, ATTR_PRODUCT_NAME, ATTR_PRODUCT_PRICE, ATTR_PRODUCT_OLD_PRICE, ATTR_PRODUCT_OMNIBUS_PRICE, ATTR_PRODUCT_OMNIBUS_DISCOUNT, ATTR_PRODUCT_BUTTON } from '../constants';
4
+ export { resolveInlinePriceOrder } from '../utils/inlinePriceOrder';
4
5
  type PriceKey = 'price' | 'original_price' | 'discount';
5
6
  /**
6
7
  * Current currency configuration from the store, in CurrencyConfig shape.
@@ -22,18 +23,6 @@ export declare function isSamePrice(product: RecommendationProduct): boolean;
22
23
  * e.g., "rating_star" → "Rating Star"
23
24
  */
24
25
  export declare function toDisplayName(attrName: string): string;
25
- /**
26
- * Resolves the inline (side-by-side) price layout from the composition order so
27
- * it matches the stacked order. `anchor` is whichever of price / original price
28
- * comes first in the composition (the merged cell renders there); `skip` is the
29
- * other (dropped, since it's merged in); `originalFirst` puts the original price
30
- * on the left when it precedes the sale price (the default composition order).
31
- */
32
- export declare function resolveInlinePriceOrder(composition: string[]): {
33
- originalFirst: boolean;
34
- anchor: string;
35
- skip: string;
36
- };
37
26
  /**
38
27
  * Reduces a raw product-attribute value to a displayable scalar string.
39
28
  * Array-type attributes (filter types `Strings`/`Numbers`) are substituted with
@@ -328,4 +317,3 @@ export declare function getDefaultProducts(count?: number): RecommendationProduc
328
317
  * @returns HTML template string with {-{-TITLE-}-}, {-{-PRODUCT_ROWS-}-}, and {-{-MOBILE_PRODUCT_ROWS-}-} (grid only) placeholders
329
318
  */
330
319
  export declare function createBlockTemplate(layout?: Orientation, instanceClass?: string): string;
331
- export {};
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Resolves the inline price layout from the composition order: `anchor` is whichever price comes first (the merged
3
+ * cell renders there), `skip` is the other; `originalFirst` puts the original price on the left.
4
+ */
5
+ export declare function resolveInlinePriceOrder(composition: string[]): {
6
+ originalFirst: boolean;
7
+ anchor: string;
8
+ skip: string;
9
+ };
@@ -1,22 +1,5 @@
1
1
  /**
2
- * Maps legacy algorithm strategy keys (used by templates authored against the
3
- * old recommendation system) to the new keys used by `RecommendationFeedSourceMaps`.
4
- *
5
- * Renames are matched by feed-source id:
6
- * - `viewedTogether` → `similarViewed` (id 11, path `viewed-together`)
7
- * - `purchasedTogether` → `similarBought` (id 12, path `purchased-together`)
8
- * - `trending` → `trendingProducts` (id 40, path `trending`)
9
- * - `mostValuable` → `mostValuableOfPartner` (id 46, path `most-valuable`)
10
- * - `topSellers` → `mostPurchased` (id 62, path `top-sellers`)
11
- * - `mostViewed` → `mostPopular` (id 61, path `most-popular`)
12
- *
13
- * Used at two boundaries:
14
- * 1. The migrator (`settingsMapper`), so freshly migrated node configs carry
15
- * the new key.
16
- * 2. The algorithm dropdown control, so already-saved blocks that still carry
17
- * a legacy key resolve to a matching dropdown option.
18
- *
19
- * Unknown values pass through untouched so a future-added algorithm doesn't
20
- * silently default.
2
+ * Maps legacy strategy keys to `RecommendationFeedSourceMaps` keys; product-bound ones (ids 11, 12, excluded from the
3
+ * dropdown) become `mostPopular`. Unknown keys pass through so a future algorithm is not silently defaulted.
21
4
  */
22
5
  export declare function mapLegacyStrategy(legacy: string | undefined): string | undefined;