@useinsider/guido 3.2.0-beta.e01b42a → 3.2.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 (75) hide show
  1. package/README.md +1 -0
  2. package/dist/@types/config/schemas.js +66 -54
  3. package/dist/components/Guido.vue.js +4 -4
  4. package/dist/components/Guido.vue2.js +91 -81
  5. package/dist/components/organisms/email-preview/desktop-preview/EmailSizeIndicator.vue.js +7 -7
  6. package/dist/components/organisms/email-preview/desktop-preview/EmailSizeIndicator.vue2.js +12 -20
  7. package/dist/components/organisms/header/EditorActions.vue.js +2 -2
  8. package/dist/components/organisms/header/EditorActions.vue2.js +51 -36
  9. package/dist/components/organisms/header/RightSlot.vue.js +10 -10
  10. package/dist/components/organisms/header/RightSlot.vue2.js +16 -13
  11. package/dist/components/organisms/save-as-template/SaveAsTemplateDrawer.vue2.js +18 -17
  12. package/dist/composables/useHtmlCompiler.js +23 -21
  13. package/dist/composables/useHtmlValidator.js +40 -38
  14. package/dist/composables/usePreviewMode.js +20 -16
  15. package/dist/composables/useSave.js +23 -15
  16. package/dist/composables/useStripo.js +44 -41
  17. package/dist/composables/validators/useLiquidValidator.js +42 -0
  18. package/dist/config/compiler/liquidCompilerRules.js +15 -0
  19. package/dist/config/compiler/recommendationCompilerRules.js +158 -44
  20. package/dist/config/compiler/unsubscribeCompilerRules.js +37 -37
  21. package/dist/config/compiler/utils/recommendationCompilerUtils.js +49 -46
  22. package/dist/config/migrator/checkboxMigrator.js +5 -3
  23. package/dist/config/migrator/radioButtonMigrator.js +14 -12
  24. package/dist/enums/extensions/recommendationBlock.js +14 -11
  25. package/dist/enums/recommendation.js +2 -2
  26. package/dist/extensions/Blocks/CouponBlock/template.js +24 -13
  27. package/dist/extensions/Blocks/Recommendation/constants/selectors.js +27 -11
  28. package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +185 -172
  29. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +94 -92
  30. package/dist/extensions/Blocks/Recommendation/controls/spacing/index.js +31 -31
  31. package/dist/extensions/Blocks/Recommendation/templates/grid/elementRenderer.js +7 -5
  32. package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +30 -29
  33. package/dist/extensions/Blocks/Recommendation/templates/index.js +7 -7
  34. package/dist/extensions/Blocks/Recommendation/templates/list/elementRenderer.js +3 -1
  35. package/dist/extensions/Blocks/Recommendation/templates/list/template.js +20 -20
  36. package/dist/extensions/Blocks/Recommendation/templates/utils.js +57 -50
  37. package/dist/extensions/DynamicContent/dynamic-content.js +17 -12
  38. package/dist/guido.css +1 -1
  39. package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js +218 -324
  40. package/dist/package.json.js +1 -1
  41. package/dist/services/recommendationApi.js +15 -15
  42. package/dist/services/stripoApi.js +9 -9
  43. package/dist/services/templateLibraryApi.js +48 -46
  44. package/dist/src/@types/config/index.d.ts +1 -1
  45. package/dist/src/@types/config/schemas.d.ts +28 -0
  46. package/dist/src/@types/config/types.d.ts +3 -1
  47. package/dist/src/@types/generic.d.ts +0 -1
  48. package/dist/src/@types/save-as-template.d.ts +1 -0
  49. package/dist/src/composables/useConfig.d.ts +12 -0
  50. package/dist/src/composables/validators/useLiquidValidator.d.ts +3 -0
  51. package/dist/src/config/compiler/liquidCompilerRules.d.ts +2 -0
  52. package/dist/src/config/compiler/utils/recommendationCompilerUtils.d.ts +1 -1
  53. package/dist/src/enums/extensions/recommendationBlock.d.ts +3 -0
  54. package/dist/src/extensions/Blocks/CouponBlock/template.d.ts +2 -0
  55. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +1 -1
  56. package/dist/src/extensions/Blocks/Recommendation/constants/selectors.d.ts +5 -0
  57. package/dist/src/extensions/Blocks/Recommendation/controls/cardComposition/index.d.ts +5 -0
  58. package/dist/src/extensions/Blocks/Recommendation/templates/grid/template.d.ts +4 -4
  59. package/dist/src/extensions/Blocks/Recommendation/templates/list/template.d.ts +3 -3
  60. package/dist/src/extensions/Blocks/Recommendation/templates/utils.d.ts +20 -3
  61. package/dist/src/extensions/Blocks/Recommendation/utils/tagName.d.ts +3 -3
  62. package/dist/src/services/templateLibraryApi.d.ts +1 -1
  63. package/dist/src/stores/config.d.ts +108 -0
  64. package/dist/src/stores/preview.d.ts +3 -0
  65. package/dist/src/utils/genericUtil.d.ts +1 -1
  66. package/dist/src/utils/htmlCompiler.d.ts +2 -1
  67. package/dist/static/styles/base.css.js +7 -2
  68. package/dist/static/styles/components/button.css.js +7 -13
  69. package/dist/static/styles/components/narrow-panel.css.js +0 -52
  70. package/dist/stores/preview.js +4 -3
  71. package/dist/utils/genericUtil.js +42 -20
  72. package/dist/utils/htmlCompiler.js +48 -41
  73. package/dist/utils/templatePreparation.js +36 -25
  74. package/dist/utils/tooltipUtils.js +4 -5
  75. package/package.json +4 -4
@@ -1,18 +1,18 @@
1
1
  var X = Object.defineProperty;
2
- var J = (p, f, t) => f in p ? X(p, f, { enumerable: !0, configurable: !0, writable: !0, value: t }) : p[f] = t;
3
- var T = (p, f, t) => J(p, typeof f != "symbol" ? f + "" : f, t);
4
- import { UIElementType as _, UEAttr as $, ModificationDescription as S } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
2
+ var J = (p, _, t) => _ in p ? X(p, _, { enumerable: !0, configurable: !0, writable: !0, value: t }) : p[_] = t;
3
+ var C = (p, _, t) => J(p, typeof _ != "symbol" ? _ + "" : _, t);
4
+ import { UIElementType as f, UEAttr as $, ModificationDescription as A } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
5
5
  import { CommonControl as Q } from "../../../common-control.js";
6
- import { ATTR_PRODUCT_IMAGE as L, ATTR_PRODUCT_NAME as Z, ATTR_PRODUCT_PRICE as tt, ATTR_PRODUCT_OLD_PRICE as et, ATTR_PRODUCT_OMNIBUS_PRICE as rt, ATTR_PRODUCT_OMNIBUS_DISCOUNT as ot, ATTR_PRODUCT_BUTTON as D, ATTR_DATA_CUSTOM_ATTRIBUTES as B, ATTR_CUSTOM_PREFIX as m } from "../../constants/selectors.js";
7
- import { DEFAULT_COMPOSITION as U, DEFAULT_VISIBILITY as P } from "../../constants/defaultConfig.js";
8
- import { RecommendationConfigService as st } from "../../services/configService.js";
9
- import { useRecommendationExtensionStore as it } from "../../store/recommendation.js";
10
- import { ATTRIBUTE_CELL_CLASS as nt, DEFAULT_CELL_PADDING as lt, gridElementRenderer as at } from "../../templates/grid/elementRenderer.js";
11
- import { listElementRenderer as ct } from "../../templates/list/elementRenderer.js";
12
- import { toDisplayName as ut, buildElementRenderer as w } from "../../templates/utils.js";
13
- import { getTableDisplayValue as dt } from "../../utils/tagName.js";
14
- import { getCurrentLayout as mt } from "../main/utils.js";
15
- const ht = "ui-elements-recommendation-card-composition", A = ".recommendation-attribute-row", N = ".product-card-wrapper > tbody", F = ".product-info-cell > table > tbody", M = "data-card-composition", y = "data-attribute-type", I = "data-visibility", j = {
6
+ import { ATTR_PRODUCT_IMAGE as L, ATTR_PRODUCT_NAME as Z, ATTR_PRODUCT_PRICE as tt, ATTR_PRODUCT_OLD_PRICE as et, ATTR_PRODUCT_OMNIBUS_PRICE as rt, ATTR_PRODUCT_OMNIBUS_DISCOUNT as ot, ATTR_PRODUCT_BUTTON as D, ATTR_DATA_CUSTOM_ATTRIBUTES as k, ATTR_CUSTOM_PREFIX as m, BUILT_IN_DEFAULT_ATTRIBUTES as st } from "../../constants/selectors.js";
7
+ import { DEFAULT_COMPOSITION as q, DEFAULT_VISIBILITY as P } from "../../constants/defaultConfig.js";
8
+ import { RecommendationConfigService as it } from "../../services/configService.js";
9
+ import { useRecommendationExtensionStore as nt } from "../../store/recommendation.js";
10
+ import { ATTRIBUTE_CELL_CLASS as lt, gridElementRenderer as at, DEFAULT_CELL_PADDING as ct } from "../../templates/grid/elementRenderer.js";
11
+ import { listElementRenderer as ut } from "../../templates/list/elementRenderer.js";
12
+ import { toDisplayName as dt, isDefaultAttribute as mt, buildElementRenderer as F } from "../../templates/utils.js";
13
+ import { getTableDisplayValue as ht } from "../../utils/tagName.js";
14
+ import { getCurrentLayout as pt } from "../main/utils.js";
15
+ const _t = "ui-elements-recommendation-card-composition", S = ".recommendation-attribute-row", N = ".product-card-wrapper > tbody", w = ".product-info-cell > table > tbody", M = "data-card-composition", y = "data-attribute-type", I = "data-visibility", x = {
16
16
  ADD_ATTRIBUTE: "addAttribute"
17
17
  }, g = 5, v = "reorderIcon_", h = [
18
18
  { key: L, label: "Product Image" },
@@ -22,21 +22,21 @@ const ht = "ui-elements-recommendation-card-composition", A = ".recommendation-a
22
22
  { key: rt, label: "Omnibus Price" },
23
23
  { key: ot, label: "Omnibus Discount" },
24
24
  { key: D, label: "Product Button" }
25
- ], pt = new Set(h.map((p) => p.key)), C = "customAttr_", O = "deleteAttr_";
26
- class Rt extends Q {
25
+ ], ft = new Set(h.map((p) => p.key)), T = "customAttr_", E = "deleteAttr_";
26
+ class Nt extends Q {
27
27
  constructor() {
28
28
  super(...arguments);
29
- T(this, "store", it());
30
- T(this, "unsubscribeStore", null);
31
- T(this, "eventController", null);
29
+ C(this, "store", nt());
30
+ C(this, "unsubscribeStore", null);
31
+ C(this, "eventController", null);
32
32
  /**
33
33
  * Guard flag: when true, onTemplateNodeUpdated skips _initializeComposition.
34
34
  * Used during _onReorder to prevent multiple intermediate rebuilds.
35
35
  */
36
- T(this, "reorderInProgress", !1);
36
+ C(this, "reorderInProgress", !1);
37
37
  }
38
38
  getId() {
39
- return ht;
39
+ return _t;
40
40
  }
41
41
  // ========================================================================
42
42
  // Lifecycle
@@ -49,9 +49,9 @@ class Rt extends Q {
49
49
  `).join(""), r = Array.from(
50
50
  { length: g },
51
51
  (l, u) => `
52
- <div data-custom-select-key="${C}${u}" style="display: none;">
52
+ <div data-custom-select-key="${T}${u}" style="display: none;">
53
53
  ${this._GuSelect({
54
- name: `${C}${u}`,
54
+ name: `${T}${u}`,
55
55
  placeholder: this.api.translate("Select Attribute"),
56
56
  options: []
57
57
  })}
@@ -61,43 +61,43 @@ class Rt extends Q {
61
61
  { length: e },
62
62
  (l, u) => `
63
63
  <div data-reorder-icon-key="${v}${u}" style="display: none;">
64
- <${_.BUTTON}
64
+ <${f.BUTTON}
65
65
  class="drag-handle-btn flat-inline flat-white"
66
66
  ${$.BUTTON.name}="${v}${u}"
67
67
  >
68
- <${_.ICON}
68
+ <${f.ICON}
69
69
  src="reorder"
70
70
  class="icon-button"
71
- ></${_.ICON}>
72
- </${_.BUTTON}>
71
+ ></${f.ICON}>
72
+ </${f.BUTTON}>
73
73
  </div>
74
74
  `
75
75
  ).join(""), s = Array.from(
76
76
  { length: g },
77
77
  (l, u) => `
78
- <div data-custom-delete-key="${O}${u}" style="display: none;">
79
- <${_.BUTTON}
78
+ <div data-custom-delete-key="${E}${u}" style="display: none;">
79
+ <${f.BUTTON}
80
80
  class="custom-attr-delete flat-inline flat-white"
81
- ${$.BUTTON.name}="${O}${u}"
81
+ ${$.BUTTON.name}="${E}${u}"
82
82
  >
83
- <${_.ICON}
83
+ <${f.ICON}
84
84
  src="delete"
85
85
  class="icon-button"
86
- ></${_.ICON}>
87
- </${_.BUTTON}>
86
+ ></${f.ICON}>
87
+ </${f.BUTTON}>
88
88
  </div>
89
89
  `
90
- ).join(""), n = "https://academy.insiderone.com/docs/new-editor-email-recommendation-block", i = this.api.translate(
90
+ ).join(""), i = "https://academy.insiderone.com/docs/new-editor-email-recommendation-block", n = this.api.translate(
91
91
  "Drag and drop the card elements to reorder them, adjust their visibility or add new attributes up to 5."
92
- ), a = this.api.translate("For more information, you can"), c = this.api.translate("visit Academy");
92
+ ), c = this.api.translate("For more information, you can"), a = this.api.translate("visit Academy");
93
93
  return `
94
94
  <div class="recommendation-controls-container" data-card-composition-control>
95
95
  <div class="container">
96
96
  <p class="card-composition-description">
97
- ${i}
98
- ${a}
97
+ ${n}
98
+ ${c}
99
99
  <!-- cspell:disable-next-line -->
100
- <a href="${n}" target="_blank" rel="noopener noreferrer">${c}</a>.
100
+ <a href="${i}" target="_blank" rel="noopener noreferrer">${a}</a>.
101
101
  </p>
102
102
  </div>
103
103
 
@@ -120,7 +120,7 @@ class Rt extends Q {
120
120
  <div class="orderable-list" data-composition-list></div>
121
121
 
122
122
  ${this._GuButton({
123
- name: j.ADD_ATTRIBUTE,
123
+ name: x.ADD_ATTRIBUTE,
124
124
  label: this.api.translate("Add Attribute"),
125
125
  id: "guido__btn-add-attribute"
126
126
  })}
@@ -150,7 +150,7 @@ class Rt extends Q {
150
150
  });
151
151
  });
152
152
  for (let t = 0; t < g; t++) {
153
- const r = `${C}${t}`, e = t;
153
+ const r = `${T}${t}`, e = t;
154
154
  this.api.onValueChanged(r, (o) => {
155
155
  this._onCustomAttributeChanged(e, o);
156
156
  });
@@ -161,14 +161,14 @@ class Rt extends Q {
161
161
  // ========================================================================
162
162
  _readCompositionFromNode() {
163
163
  if (!this.currentNode || !("getAttribute" in this.currentNode))
164
- return [...U];
164
+ return [...q];
165
165
  const t = this.currentNode.getAttribute(M);
166
- return t ? t.split(",").filter(Boolean) : [...U];
166
+ return t ? t.split(",").filter(Boolean) : [...q];
167
167
  }
168
168
  _readCustomAttributesFromNode() {
169
169
  if (!this.currentNode || !("getAttribute" in this.currentNode))
170
170
  return [];
171
- const t = this.currentNode.getAttribute(B);
171
+ const t = this.currentNode.getAttribute(k);
172
172
  if (!t)
173
173
  return [];
174
174
  try {
@@ -180,7 +180,7 @@ class Rt extends Q {
180
180
  _readVisibilityFromRows() {
181
181
  if (!this.currentNode)
182
182
  return this._getDefaultVisibilities();
183
- const t = Array.from(this.currentNode.querySelectorAll(A)), r = this._extractVisibilityFromRows(t);
183
+ const t = Array.from(this.currentNode.querySelectorAll(S)), r = this._extractVisibilityFromRows(t);
184
184
  return this._mergeWithDefaults(r);
185
185
  }
186
186
  _getDefaultVisibilities() {
@@ -222,20 +222,20 @@ class Rt extends Q {
222
222
  if (!o || this._tryReorderInPlace(o, t))
223
223
  return !1;
224
224
  const s = new Set(r);
225
- let n = 0, i = 0;
226
- const a = t.map((c) => {
227
- if (pt.has(c)) {
228
- const l = h.find((u) => u.key === c);
229
- return this._createBuiltInItemHtml(l, i++);
225
+ let i = 0, n = 0;
226
+ const c = t.map((a) => {
227
+ if (ft.has(a)) {
228
+ const l = h.find((u) => u.key === a);
229
+ return this._createBuiltInItemHtml(l, n++);
230
230
  }
231
- if (c.startsWith(m)) {
232
- const l = c.substring(m.length);
231
+ if (a.startsWith(m)) {
232
+ const l = a.substring(m.length);
233
233
  if (s.has(l))
234
- return this._createCustomItemHtml(c, n++, i++);
234
+ return this._createCustomItemHtml(a, i++, n++);
235
235
  }
236
236
  return "";
237
237
  }).join("");
238
- return this._rescueTogglesToStore(e), this._rescueSelectsToStore(e), this._rescueDeleteButtonsToStore(e), this._rescueReorderIconsToStore(e), o.innerHTML = a, this._moveTogglesIntoItems(e), this._moveSelectsIntoItems(e, r.length), this._moveDeleteButtonsIntoItems(e, r.length), this._moveReorderIconsIntoItems(e, i), !0;
238
+ return this._rescueTogglesToStore(e), this._rescueSelectsToStore(e), this._rescueDeleteButtonsToStore(e), this._rescueReorderIconsToStore(e), o.innerHTML = c, this._moveTogglesIntoItems(e), this._moveSelectsIntoItems(e, r.length), this._moveDeleteButtonsIntoItems(e, r.length), this._moveReorderIconsIntoItems(e, n), !0;
239
239
  }
240
240
  /**
241
241
  * Attempts to reorder existing orderable-item elements to match the composition order.
@@ -247,27 +247,27 @@ class Rt extends Q {
247
247
  const e = Array.from(t.querySelectorAll(".orderable-item"));
248
248
  if (e.length !== r.length)
249
249
  return !1;
250
- const o = e.map((c) => c.dataset.key).filter(Boolean);
250
+ const o = e.map((a) => a.dataset.key).filter(Boolean);
251
251
  if (o.length !== r.length)
252
252
  return !1;
253
- const s = [...o].sort().join(","), n = [...r].sort().join(",");
254
- if (s !== n || r.some((c) => c.startsWith(m)))
253
+ const s = [...o].sort().join(","), i = [...r].sort().join(",");
254
+ if (s !== i || r.some((a) => a.startsWith(m)))
255
255
  return !1;
256
- const i = /* @__PURE__ */ new Map();
257
- e.forEach((c) => {
258
- const { key: l } = c.dataset;
256
+ const n = /* @__PURE__ */ new Map();
257
+ e.forEach((a) => {
258
+ const { key: l } = a.dataset;
259
259
  if (l) {
260
- const u = i.get(l) || [];
261
- u.push(c), i.set(l, u);
260
+ const u = n.get(l) || [];
261
+ u.push(a), n.set(l, u);
262
262
  }
263
263
  });
264
- const a = /* @__PURE__ */ new Map();
265
- return r.forEach((c) => {
266
- const l = i.get(c);
264
+ const c = /* @__PURE__ */ new Map();
265
+ return r.forEach((a) => {
266
+ const l = n.get(a);
267
267
  if (!l)
268
268
  return;
269
- const u = a.get(c) || 0;
270
- a.set(c, u + 1), l[u] && t.appendChild(l[u]);
269
+ const u = c.get(a) || 0;
270
+ c.set(a, u + 1), l[u] && t.appendChild(l[u]);
271
271
  }), !0;
272
272
  }
273
273
  _createBuiltInItemHtml(t, r) {
@@ -297,10 +297,10 @@ class Rt extends Q {
297
297
  * Falls back to a single option for the currently selected attribute.
298
298
  */
299
299
  _getSelectOptions(t, r = []) {
300
- const { filterList: e } = this.store, o = Object.values(e);
301
- if (o.length > 0) {
302
- const n = new Set(r);
303
- return n.delete(t), o.filter((i) => !n.has(i.attributeName)).map((i) => ({
300
+ const e = this._getAddableFilters();
301
+ if (e.length > 0) {
302
+ const s = new Set(r);
303
+ return s.delete(t), e.filter((i) => !s.has(i.attributeName)).map((i) => ({
304
304
  text: i.displayName,
305
305
  value: i.attributeName
306
306
  }));
@@ -315,7 +315,7 @@ class Rt extends Q {
315
315
  _initializeCustomSelects(t) {
316
316
  t.length !== 0 && setTimeout(() => {
317
317
  t.forEach((r, e) => {
318
- const o = `${C}${e}`, s = this._getSelectOptions(r, t);
318
+ const o = `${T}${e}`, s = this._getSelectOptions(r, t);
319
319
  this.api.setUIEAttribute(o, $.SELECTPICKER.items, s), this.api.updateValues({ [o]: r });
320
320
  });
321
321
  }, 0);
@@ -339,10 +339,10 @@ class Rt extends Q {
339
339
  */
340
340
  _moveSelectsIntoItems(t, r) {
341
341
  for (let e = 0; e < r; e++) {
342
- const o = `${C}${e}`, s = t.querySelector(`[data-custom-select-key="${o}"]`), n = t.querySelector(`[data-custom-select-slot="${e}"]`);
343
- if (s && n) {
344
- const i = s.querySelector("ue-select");
345
- i && n.appendChild(i);
342
+ const o = `${T}${e}`, s = t.querySelector(`[data-custom-select-key="${o}"]`), i = t.querySelector(`[data-custom-select-slot="${e}"]`);
343
+ if (s && i) {
344
+ const n = s.querySelector("ue-select");
345
+ n && i.appendChild(n);
346
346
  }
347
347
  }
348
348
  }
@@ -367,10 +367,10 @@ class Rt extends Q {
367
367
  */
368
368
  _rescueSelectsToStore(t) {
369
369
  for (let r = 0; r < g; r++) {
370
- const e = `${C}${r}`, o = t.querySelector(`[data-custom-select-key="${e}"]`), s = t.querySelector(`[data-custom-select-slot="${r}"]`);
370
+ const e = `${T}${r}`, o = t.querySelector(`[data-custom-select-key="${e}"]`), s = t.querySelector(`[data-custom-select-slot="${r}"]`);
371
371
  if (s) {
372
- const n = s.querySelector("ue-select");
373
- n && o && o.appendChild(n);
372
+ const i = s.querySelector("ue-select");
373
+ i && o && o.appendChild(i);
374
374
  }
375
375
  }
376
376
  }
@@ -380,10 +380,10 @@ class Rt extends Q {
380
380
  */
381
381
  _moveDeleteButtonsIntoItems(t, r) {
382
382
  for (let e = 0; e < r; e++) {
383
- const o = `${O}${e}`, s = t.querySelector(`[data-custom-delete-key="${o}"]`), n = t.querySelector(`[data-custom-delete-slot="${e}"]`);
384
- if (s && n) {
385
- const i = s.querySelector("ue-button");
386
- i && n.appendChild(i);
383
+ const o = `${E}${e}`, s = t.querySelector(`[data-custom-delete-key="${o}"]`), i = t.querySelector(`[data-custom-delete-slot="${e}"]`);
384
+ if (s && i) {
385
+ const n = s.querySelector("ue-button");
386
+ n && i.appendChild(n);
387
387
  }
388
388
  }
389
389
  }
@@ -393,10 +393,10 @@ class Rt extends Q {
393
393
  */
394
394
  _rescueDeleteButtonsToStore(t) {
395
395
  for (let r = 0; r < g; r++) {
396
- const e = `${O}${r}`, o = t.querySelector(`[data-custom-delete-key="${e}"]`), s = t.querySelector(`[data-custom-delete-slot="${r}"]`);
396
+ const e = `${E}${r}`, o = t.querySelector(`[data-custom-delete-key="${e}"]`), s = t.querySelector(`[data-custom-delete-slot="${r}"]`);
397
397
  if (s) {
398
- const n = s.querySelector("ue-button");
399
- n && o && o.appendChild(n);
398
+ const i = s.querySelector("ue-button");
399
+ i && o && o.appendChild(i);
400
400
  }
401
401
  }
402
402
  }
@@ -406,10 +406,10 @@ class Rt extends Q {
406
406
  */
407
407
  _moveReorderIconsIntoItems(t, r) {
408
408
  for (let e = 0; e < r; e++) {
409
- const o = `${v}${e}`, s = t.querySelector(`[data-reorder-icon-key="${o}"]`), n = t.querySelector(`[data-reorder-icon-slot="${e}"]`);
410
- if (s && n) {
411
- const i = s.querySelector("ue-button");
412
- i && n.appendChild(i);
409
+ const o = `${v}${e}`, s = t.querySelector(`[data-reorder-icon-key="${o}"]`), i = t.querySelector(`[data-reorder-icon-slot="${e}"]`);
410
+ if (s && i) {
411
+ const n = s.querySelector("ue-button");
412
+ n && i.appendChild(n);
413
413
  }
414
414
  }
415
415
  }
@@ -420,10 +420,10 @@ class Rt extends Q {
420
420
  _rescueReorderIconsToStore(t) {
421
421
  const r = h.length + g;
422
422
  for (let e = 0; e < r; e++) {
423
- const o = `${v}${e}`, s = t.querySelector(`[data-reorder-icon-key="${o}"]`), n = t.querySelector(`[data-reorder-icon-slot="${e}"]`);
424
- if (n) {
425
- const i = n.querySelector("ue-button");
426
- i && s && s.appendChild(i);
423
+ const o = `${v}${e}`, s = t.querySelector(`[data-reorder-icon-key="${o}"]`), i = t.querySelector(`[data-reorder-icon-slot="${e}"]`);
424
+ if (i) {
425
+ const n = i.querySelector("ue-button");
426
+ n && s && s.appendChild(n);
427
427
  }
428
428
  }
429
429
  }
@@ -437,29 +437,29 @@ class Rt extends Q {
437
437
  return;
438
438
  const e = r.querySelector("[data-composition-list]"), o = r.querySelector("#guido__btn-add-attribute");
439
439
  e && (this._setupDragAndDrop(e, t), this._setupDeleteHandler(e, t)), o && o.addEventListener("click", () => {
440
- const s = new Set(this._readCustomAttributesFromNode()), i = Object.values(this.store.filterList).find((a) => !s.has(a.attributeName));
440
+ const s = new Set(this._readCustomAttributesFromNode()), i = this._getAddableFilters().find((n) => !s.has(n.attributeName));
441
441
  i && this._onAddAttribute(i.attributeName, i.displayName);
442
442
  }, { signal: t });
443
443
  }
444
444
  _setupDragAndDrop(t, r) {
445
445
  let e = null, o = null;
446
446
  t.addEventListener("dragstart", (s) => {
447
- var a;
448
- const i = s.target.closest(".orderable-item");
449
- i && (e = i, i.classList.add("dragging"), (a = s.dataTransfer) == null || a.setData("text/plain", i.dataset.key || ""));
447
+ var c;
448
+ const n = s.target.closest(".orderable-item");
449
+ n && (e = n, n.classList.add("dragging"), (c = s.dataTransfer) == null || c.setData("text/plain", n.dataset.key || ""));
450
450
  }, { signal: r }), t.addEventListener("dragend", () => {
451
451
  e && e.classList.remove("dragging"), e = null, o == null || o.classList.remove("drag-over"), o = null;
452
452
  }, { signal: r }), t.addEventListener("dragover", (s) => {
453
453
  s.preventDefault();
454
- const i = s.target.closest(".orderable-item"), a = i && i !== e ? i : null;
455
- a !== o && (o == null || o.classList.remove("drag-over"), o = a, o == null || o.classList.add("drag-over"));
454
+ const n = s.target.closest(".orderable-item"), c = n && n !== e ? n : null;
455
+ c !== o && (o == null || o.classList.remove("drag-over"), o = c, o == null || o.classList.add("drag-over"));
456
456
  }, { signal: r }), t.addEventListener("drop", (s) => {
457
457
  s.preventDefault();
458
- const i = s.target.closest(".orderable-item");
459
- if (!i || !e || i === e)
458
+ const n = s.target.closest(".orderable-item");
459
+ if (!n || !e || n === e)
460
460
  return;
461
- const a = i.getBoundingClientRect(), c = a.top + a.height / 2;
462
- s.clientY < c ? t.insertBefore(e, i) : t.insertBefore(e, i.nextSibling), o == null || o.classList.remove("drag-over"), o = null, e.classList.remove("dragging");
461
+ const c = n.getBoundingClientRect(), a = c.top + c.height / 2;
462
+ s.clientY < a ? t.insertBefore(e, n) : t.insertBefore(e, n.nextSibling), o == null || o.classList.remove("drag-over"), o = null, e.classList.remove("dragging");
463
463
  const u = t.querySelectorAll(".orderable-item"), d = Array.from(u).map((b) => b.dataset.key).filter(Boolean);
464
464
  this._onReorder(d), e = null;
465
465
  }, { signal: r });
@@ -469,8 +469,8 @@ class Rt extends Q {
469
469
  const s = e.target.closest(".custom-attr-delete");
470
470
  if (!s)
471
471
  return;
472
- const n = s.closest("[data-custom-index]"), i = n == null ? void 0 : n.dataset.customIndex;
473
- i !== void 0 && this._onDeleteCustomAttribute(Number(i));
472
+ const i = s.closest("[data-custom-index]"), n = i == null ? void 0 : i.dataset.customIndex;
473
+ n !== void 0 && this._onDeleteCustomAttribute(Number(n));
474
474
  }, { signal: r });
475
475
  }
476
476
  // ========================================================================
@@ -490,8 +490,8 @@ class Rt extends Q {
490
490
  const r = this._readCustomAttributesFromNode();
491
491
  if (r[t] === void 0)
492
492
  return;
493
- const o = this._readCompositionFromNode(), s = this._findNthCustomKeyIndex(o, t), n = o.filter((a, c) => c !== s), i = r.filter((a, c) => c !== t);
494
- this._updateBothAttributes(n, i), this._removeCustomAttributeHtml(n), this._renderOrderableItems(n, i), this._initializeCustomSelects(i), this._updateAddButtonState();
493
+ const o = this._readCompositionFromNode(), s = this._findNthCustomKeyIndex(o, t), i = o.filter((c, a) => a !== s), n = r.filter((c, a) => a !== t);
494
+ this._updateBothAttributes(i, n), this._removeCustomAttributeHtml(i), this._renderOrderableItems(i, n), this._initializeCustomSelects(n), this._updateAddButtonState();
495
495
  }
496
496
  /**
497
497
  * Handles changing a custom attribute's selection via its inline _GuSelect.
@@ -501,10 +501,10 @@ class Rt extends Q {
501
501
  const e = this._readCustomAttributesFromNode(), o = e[t];
502
502
  if (o === void 0 || o === r)
503
503
  return;
504
- const s = `${m}${r}`, n = this._readCompositionFromNode(), i = this._findNthCustomKeyIndex(n, t);
505
- i !== -1 && (n[i] = s), e[t] = r;
506
- const a = this._getDisplayNameForAttribute(r);
507
- this._updateBothAttributes(n, e), this._injectCustomAttributeHtml(r, a, s, n), this._renderOrderableItems(n, e), this._initializeCustomSelects(e);
504
+ const s = `${m}${r}`, i = this._readCompositionFromNode(), n = this._findNthCustomKeyIndex(i, t);
505
+ n !== -1 && (i[n] = s), e[t] = r;
506
+ const c = this._getDisplayNameForAttribute(r);
507
+ this._updateBothAttributes(i, e), this._injectCustomAttributeHtml(r, c, s, i), this._renderOrderableItems(i, e), this._initializeCustomSelects(e);
508
508
  }
509
509
  _onReorder(t) {
510
510
  const r = t.filter((e) => e.startsWith(m)).map((e) => e.substring(m.length));
@@ -528,54 +528,54 @@ class Rt extends Q {
528
528
  const s = this.currentNode.querySelectorAll(N);
529
529
  if (!(s != null && s.length))
530
530
  return;
531
- const n = st.getConfig(this.currentNode), a = `0 ${Math.floor(n.columnSpacing / 2)}px`, c = this.api.getDocumentModifier(), l = this.store.recommendationProducts.length;
531
+ const i = it.getConfig(this.currentNode), c = `0 ${Math.floor(i.columnSpacing / 2)}px`, a = this.api.getDocumentModifier(), l = this.store.recommendationProducts.length;
532
532
  let u = 0;
533
533
  s.forEach((d) => {
534
- var H;
535
- const b = d.querySelector(A), R = ((H = b == null ? void 0 : b.querySelectorAll(`.${nt}`)) == null ? void 0 : H.length) || 1, x = (100 / R).toFixed(2), { bgStyle: V, bgAttr: W } = this._extractSegmentBgFromCard(d), K = o.map((k) => {
536
- if (k === e) {
534
+ var U;
535
+ const b = d.querySelector(S), R = ((U = b == null ? void 0 : b.querySelectorAll(`.${lt}`)) == null ? void 0 : U.length) || 1, V = (100 / R).toFixed(2), { bgStyle: j, bgAttr: W } = this._extractSegmentBgFromCard(d), K = o.map((B) => {
536
+ if (B === e) {
537
537
  const z = Array.from(
538
538
  { length: R },
539
- (ft, q) => {
540
- const G = l > 0 ? (u + q) % l : q, Y = this._resolveAttributeContent(t, r, G);
539
+ (gt, H) => {
540
+ const G = l > 0 ? (u + H) % l : H, Y = this._resolveAttributeContent(t, r, G);
541
541
  return this._getGridCellHtml(
542
542
  t,
543
543
  Y,
544
- x,
545
544
  V,
545
+ j,
546
546
  W,
547
- a
547
+ c
548
548
  );
549
549
  }
550
550
  ).join("");
551
551
  return `<tr class="recommendation-attribute-row" ${y}="${e}" ${I}="1">${z}</tr>`;
552
552
  }
553
- const E = d.querySelector(
554
- `${A}[${y}="${k}"]`
553
+ const O = d.querySelector(
554
+ `${S}[${y}="${B}"]`
555
555
  );
556
- return E && "getOuterHTML" in E ? E.getOuterHTML() : "";
556
+ return O && "getOuterHTML" in O ? O.getOuterHTML() : "";
557
557
  }).join("");
558
- u += R, l > 0 && u >= l && (u = 0), c.modifyHtml(d).setInnerHtml(K);
559
- }), c.apply(new S(`${this.api.translate("Add custom attribute")}: ${r}`));
558
+ u += R, l > 0 && u >= l && (u = 0), a.modifyHtml(d).setInnerHtml(K);
559
+ }), a.apply(new A(`${this.api.translate("Add custom attribute")}: ${r}`));
560
560
  }
561
561
  _injectListAttributeRow(t, r, e, o) {
562
- const s = this.currentNode.querySelectorAll(F);
562
+ const s = this.currentNode.querySelectorAll(w);
563
563
  if (!(s != null && s.length))
564
564
  return;
565
- const n = o.filter((a) => a !== L && a !== D), i = this.api.getDocumentModifier();
566
- s.forEach((a, c) => {
567
- const l = n.map((u) => {
565
+ const i = o.filter((c) => c !== L && c !== D), n = this.api.getDocumentModifier();
566
+ s.forEach((c, a) => {
567
+ const l = i.map((u) => {
568
568
  if (u === e) {
569
- const b = this._resolveAttributeContent(t, r, c);
569
+ const b = this._resolveAttributeContent(t, r, a);
570
570
  return this._getListRowHtml(t, b, e);
571
571
  }
572
- const d = a.querySelector(
573
- `${A}[${y}="${u}"]`
572
+ const d = c.querySelector(
573
+ `${S}[${y}="${u}"]`
574
574
  );
575
575
  return d && "getOuterHTML" in d ? d.getOuterHTML() : "";
576
576
  }).join("");
577
- i.modifyHtml(a).setInnerHtml(l);
578
- }), i.apply(new S(`${this.api.translate("Add custom attribute")}: ${r}`));
577
+ n.modifyHtml(c).setInnerHtml(l);
578
+ }), n.apply(new A(`${this.api.translate("Add custom attribute")}: ${r}`));
579
579
  }
580
580
  /**
581
581
  * Removes a custom attribute by rebuilding product card content without it.
@@ -588,17 +588,17 @@ class Rt extends Q {
588
588
  if (r === "grid") {
589
589
  const o = this.currentNode.querySelectorAll(N);
590
590
  o == null || o.forEach((s) => {
591
- const n = this._buildCompositionHtml(s, t);
592
- e.modifyHtml(s).setInnerHtml(n);
591
+ const i = this._buildCompositionHtml(s, t);
592
+ e.modifyHtml(s).setInnerHtml(i);
593
593
  });
594
594
  } else {
595
- const o = t.filter((n) => n !== L && n !== D), s = this.currentNode.querySelectorAll(F);
596
- s == null || s.forEach((n) => {
597
- const i = this._buildCompositionHtml(n, o);
598
- e.modifyHtml(n).setInnerHtml(i);
595
+ const o = t.filter((i) => i !== L && i !== D), s = this.currentNode.querySelectorAll(w);
596
+ s == null || s.forEach((i) => {
597
+ const n = this._buildCompositionHtml(i, o);
598
+ e.modifyHtml(i).setInnerHtml(n);
599
599
  });
600
600
  }
601
- e.apply(new S(this.api.translate("Remove custom attribute")));
601
+ e.apply(new A(this.api.translate("Remove custom attribute")));
602
602
  }
603
603
  // ========================================================================
604
604
  // DOM Mutation (Block Root Attributes, Reorder)
@@ -611,7 +611,7 @@ class Rt extends Q {
611
611
  * producing a flicker on the custom attribute dropdowns.
612
612
  */
613
613
  _updateBothAttributes(t, r) {
614
- this.currentNode && this.api.getDocumentModifier().modifyHtml(this.currentNode).setAttribute(M, t.join(",")).setAttribute(B, JSON.stringify(r)).apply(new S(this.api.translate("Update card composition")));
614
+ this.currentNode && this.api.getDocumentModifier().modifyHtml(this.currentNode).setAttribute(M, t.join(",")).setAttribute(k, JSON.stringify(r)).apply(new A(this.api.translate("Update card composition")));
615
615
  }
616
616
  /**
617
617
  * Reorders attribute rows within each product card based on composition order.
@@ -627,7 +627,7 @@ class Rt extends Q {
627
627
  r.forEach((o) => {
628
628
  const s = this._buildCompositionHtml(o, t);
629
629
  e.modifyHtml(o).setInnerHtml(s);
630
- }), e.apply(new S(this.api.translate("Reorder product attributes")));
630
+ }), e.apply(new A(this.api.translate("Reorder product attributes")));
631
631
  }
632
632
  /**
633
633
  * Builds HTML string with attributes ordered according to composition.
@@ -635,7 +635,7 @@ class Rt extends Q {
635
635
  */
636
636
  _buildCompositionHtml(t, r) {
637
637
  return r.reduce((e, o) => {
638
- const s = t.querySelector(`${A}[${y}="${o}"]`);
638
+ const s = t.querySelector(`${S}[${y}="${o}"]`);
639
639
  return s && "getOuterHTML" in s ? e + s.getOuterHTML() : e;
640
640
  }, "");
641
641
  }
@@ -645,14 +645,14 @@ class Rt extends Q {
645
645
  _applyVisibilityToBlock(t, r) {
646
646
  if (!this.currentNode)
647
647
  return;
648
- const e = this.currentNode.querySelectorAll(`${A}[${y}="${t}"]`);
648
+ const e = this.currentNode.querySelectorAll(`${S}[${y}="${t}"]`);
649
649
  if (!(e != null && e.length))
650
650
  return;
651
- const o = r ? "1" : "0", s = r ? this.api.translate("visible") : this.api.translate("hidden"), n = `${this.api.translate("Set visibility")}: ${t} → ${s}`, i = this.api.getDocumentModifier();
652
- e.forEach((a) => {
653
- const c = dt(a), l = r ? c : "none";
654
- i.modifyHtml(a).setStyle("display", l).setAttribute(I, o);
655
- }), i.apply(new S(n));
651
+ const o = r ? "1" : "0", s = r ? this.api.translate("visible") : this.api.translate("hidden"), i = `${this.api.translate("Set visibility")}: ${t} → ${s}`, n = this.api.getDocumentModifier();
652
+ e.forEach((c) => {
653
+ const a = ht(c), l = r ? a : "none";
654
+ n.modifyHtml(c).setStyle("display", l).setAttribute(I, o);
655
+ }), n.apply(new A(i));
656
656
  }
657
657
  // ========================================================================
658
658
  // Utilities
@@ -673,7 +673,7 @@ class Rt extends Q {
673
673
  return -1;
674
674
  }
675
675
  _getCurrentLayout() {
676
- return this.store.recommendationConfigs.orientation || mt(this.currentNode);
676
+ return this.store.recommendationConfigs.orientation || pt(this.currentNode);
677
677
  }
678
678
  /**
679
679
  * Extracts background color properties from existing card elements.
@@ -685,18 +685,18 @@ class Rt extends Q {
685
685
  var o;
686
686
  const r = t.querySelector(".product-card-segment");
687
687
  if (r && "getAttribute" in r) {
688
- const n = (r.getAttribute("style") || "").match(/background-color:\s*([^;]+)/);
689
- if (n) {
690
- const i = r.getAttribute("bgcolor") || "";
691
- return { bgStyle: `background-color: ${n[1].trim()};`, bgAttr: i };
688
+ const i = (r.getAttribute("style") || "").match(/background-color:\s*([^;]+)/);
689
+ if (i) {
690
+ const n = r.getAttribute("bgcolor") || "";
691
+ return { bgStyle: `background-color: ${i[1].trim()};`, bgAttr: n };
692
692
  }
693
693
  }
694
694
  const e = (o = this.currentNode) == null ? void 0 : o.querySelector(".product-card-wrapper");
695
695
  if (e && "getStyle" in e) {
696
696
  const s = e.getStyle("background-color");
697
697
  if (s && s !== "transparent") {
698
- const n = "getAttribute" in e && e.getAttribute("bgcolor") || "";
699
- return { bgStyle: `background-color: ${s};`, bgAttr: n };
698
+ const i = "getAttribute" in e && e.getAttribute("bgcolor") || "";
699
+ return { bgStyle: `background-color: ${s};`, bgAttr: i };
700
700
  }
701
701
  }
702
702
  return { bgStyle: "", bgAttr: "" };
@@ -724,9 +724,9 @@ class Rt extends Q {
724
724
  * or when all available filters have already been added (no unused attributes left).
725
725
  */
726
726
  _updateAddButtonState() {
727
- const t = this._readCustomAttributesFromNode(), r = t.length >= g, e = new Set(t), o = Object.values(this.store.filterList), s = o.length > 0 && o.every((n) => e.has(n.attributeName));
727
+ const t = this._readCustomAttributesFromNode(), r = t.length >= g, e = new Set(t), o = this._getAddableFilters(), s = o.length > 0 && o.every((i) => e.has(i.attributeName));
728
728
  this.api.setUIEAttribute(
729
- j.ADD_ATTRIBUTE,
729
+ x.ADD_ATTRIBUTE,
730
730
  $.BUTTON.disabled,
731
731
  r || s ? "true" : "false"
732
732
  );
@@ -745,37 +745,50 @@ class Rt extends Q {
745
745
  o !== r && (r = o, this._initializeComposition());
746
746
  });
747
747
  }
748
+ /**
749
+ * Returns filters eligible for the custom attribute dropdown,
750
+ * excluding default attributes already covered by built-in toggle items.
751
+ */
752
+ _getAddableFilters() {
753
+ return Object.values(this.store.filterList).filter((t) => !(t.type === "defaultAttribute" && st.has(t.attributeName)));
754
+ }
748
755
  /**
749
756
  * Looks up the display name for an attribute from the store's filterList.
750
757
  * Falls back to Title Case conversion of the snake_case attribute name.
751
758
  */
752
759
  _getDisplayNameForAttribute(t) {
753
760
  const r = Object.values(this.store.filterList).find((e) => e.attributeName === t);
754
- return r ? r.displayName : ut(t);
761
+ return r ? r.displayName : dt(t);
755
762
  }
756
763
  /**
757
764
  * Resolves the display content for a custom attribute cell.
758
765
  * Uses the real product value from the store when available, falls back to displayName.
759
766
  */
760
767
  _resolveAttributeContent(t, r, e) {
761
- var i;
762
- const s = this.store.recommendationProducts[e], n = (i = s == null ? void 0 : s.product_attributes) == null ? void 0 : i[t];
763
- return n != null ? String(n) : r;
764
- }
765
- _getGridCellHtml(t, r, e, o = "", s = "", n = "") {
766
- const i = `${m}${t}`, a = w(at, [i]), c = { product_attributes: { [t]: r } };
767
- let l = a[i](c);
768
- return l = l.replace("<td", `<td width="${e}%"`), n && (l = l.replace(
769
- `padding: ${lt}`,
770
- `padding: ${n}`
768
+ var n;
769
+ const s = this.store.recommendationProducts[e], i = mt(t, this.store.filterList) ? s == null ? void 0 : s[t] : (n = s == null ? void 0 : s.product_attributes) == null ? void 0 : n[t];
770
+ return typeof i == "string" ? i : typeof i == "number" ? String(i) : r;
771
+ }
772
+ _getGridCellHtml(t, r, e, o = "", s = "", i = "") {
773
+ const n = `${m}${t}`, c = F(at, [n], this.store.filterList), a = {
774
+ [t]: r,
775
+ product_attributes: { [t]: r }
776
+ };
777
+ let l = c[n](a);
778
+ return l = l.replace("<td", `<td width="${e}%"`), i && (l = l.replace(
779
+ `padding: ${ct}`,
780
+ `padding: ${i}`
771
781
  )), o && (l = l.replace(/style="table-layout: fixed;"/, `style="table-layout: fixed; ${o}"`)), s && (l = l.replace(/border="0"/, `border="0" bgcolor="${s}"`)), l;
772
782
  }
773
783
  _getListRowHtml(t, r, e) {
774
- const o = w(ct, [e]), s = { product_attributes: { [t]: r } }, i = o[e](s).replace(/<tr>/, "").replace(/<\/tr>/, "");
775
- return `<tr class="recommendation-attribute-row" ${y}="${e}" ${I}="1">${i}</tr>`;
784
+ const o = F(ut, [e], this.store.filterList), s = {
785
+ [t]: r,
786
+ product_attributes: { [t]: r }
787
+ }, n = o[e](s).replace(/<tr>/, "").replace(/<\/tr>/, "");
788
+ return `<tr class="recommendation-attribute-row" ${y}="${e}" ${I}="1">${n}</tr>`;
776
789
  }
777
790
  }
778
791
  export {
779
- ht as COMPOSITION_CONTROL_BLOCK_ID,
780
- Rt as RecommendationCardCompositionControl
792
+ _t as COMPOSITION_CONTROL_BLOCK_ID,
793
+ Nt as RecommendationCardCompositionControl
781
794
  };