@useinsider/guido 3.7.2-beta.0bf502c → 3.7.2-beta.13c9a35
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.
- package/dist/@types/config/schemas.js +70 -66
- package/dist/composables/usePreviewMode.js +15 -14
- package/dist/composables/useRecommendationPreview.js +100 -0
- package/dist/composables/useStripo.js +54 -68
- package/dist/config/compiler/utils/recommendationCompilerUtils.js +90 -82
- package/dist/config/i18n/en/toasters.json.js +0 -1
- package/dist/config/migrator/recommendation/htmlBuilder.js +59 -58
- package/dist/config/migrator/recommendation/settingsMapper.js +38 -33
- package/dist/extensions/Blocks/Recommendation/block.js +60 -41
- package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +41 -32
- package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +369 -288
- package/dist/extensions/Blocks/Recommendation/controls/main/index.js +96 -84
- package/dist/extensions/Blocks/Recommendation/controls/main/pricePlacement.js +133 -0
- package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +82 -80
- package/dist/extensions/Blocks/Recommendation/iconsRegistry.js +21 -7
- package/dist/extensions/Blocks/Recommendation/recommendation.css.js +64 -4
- package/dist/extensions/Blocks/Recommendation/store/recommendation.js +7 -5
- package/dist/extensions/Blocks/Recommendation/templates/grid/elementRenderer.js +101 -72
- package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +31 -30
- package/dist/extensions/Blocks/Recommendation/templates/index.js +9 -7
- package/dist/extensions/Blocks/Recommendation/templates/list/elementRenderer.js +74 -59
- package/dist/extensions/Blocks/Recommendation/templates/list/template.js +21 -21
- package/dist/extensions/Blocks/Recommendation/templates/utils.js +88 -57
- package/dist/src/@types/config/schemas.d.ts +16 -0
- package/dist/src/composables/useConfig.d.ts +4 -0
- package/dist/src/composables/useRecommendationPreview.d.ts +10 -0
- package/dist/src/config/migrator/recommendation/settingsMapper.d.ts +1 -1
- package/dist/src/extensions/Blocks/Recommendation/block.d.ts +10 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/cardComposition/index.d.ts +29 -3
- package/dist/src/extensions/Blocks/Recommendation/controls/index.d.ts +1 -1
- package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +3 -1
- package/dist/src/extensions/Blocks/Recommendation/controls/main/pricePlacement.d.ts +59 -0
- package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +2 -0
- package/dist/src/extensions/Blocks/Recommendation/templates/grid/elementRenderer.d.ts +16 -0
- package/dist/src/extensions/Blocks/Recommendation/templates/grid/template.d.ts +4 -4
- package/dist/src/extensions/Blocks/Recommendation/templates/list/elementRenderer.d.ts +13 -0
- package/dist/src/extensions/Blocks/Recommendation/templates/list/template.d.ts +3 -2
- package/dist/src/extensions/Blocks/Recommendation/templates/utils.d.ts +33 -1
- package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +15 -0
- package/dist/src/stores/config.d.ts +36 -0
- package/package.json +1 -1
|
@@ -1,103 +1,103 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import { UIElementType as
|
|
5
|
-
import { CommonControl as
|
|
6
|
-
import { ATTR_PRODUCT_IMAGE as
|
|
7
|
-
import { DEFAULT_COMPOSITION as
|
|
8
|
-
import { RecommendationConfigService as
|
|
1
|
+
var tt = Object.defineProperty;
|
|
2
|
+
var et = (g, b, t) => b in g ? tt(g, b, { enumerable: !0, configurable: !0, writable: !0, value: t }) : g[b] = t;
|
|
3
|
+
var I = (g, b, t) => et(g, typeof b != "symbol" ? b + "" : b, t);
|
|
4
|
+
import { UIElementType as _, UEAttr as E, ModificationDescription as A } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
|
|
5
|
+
import { CommonControl as rt } from "../../../common-control.js";
|
|
6
|
+
import { ATTR_PRODUCT_IMAGE as k, ATTR_PRODUCT_NAME as ot, ATTR_PRODUCT_PRICE as S, ATTR_PRODUCT_OLD_PRICE as v, ATTR_PRODUCT_OMNIBUS_PRICE as it, ATTR_PRODUCT_OMNIBUS_DISCOUNT as st, ATTR_PRODUCT_BUTTON as U, ATTR_DATA_CUSTOM_ATTRIBUTES as F, ATTR_CUSTOM_PREFIX as p, BUILT_IN_DEFAULT_ATTRIBUTES as nt } from "../../constants/selectors.js";
|
|
7
|
+
import { DEFAULT_COMPOSITION as x, DEFAULT_VISIBILITY as M } from "../../constants/defaultConfig.js";
|
|
8
|
+
import { RecommendationConfigService as P } from "../../services/configService.js";
|
|
9
9
|
import { useRecommendationExtensionStore as lt } from "../../store/recommendation.js";
|
|
10
|
-
import { ATTRIBUTE_CELL_CLASS as at, gridElementRenderer as ct, DEFAULT_CELL_PADDING as
|
|
10
|
+
import { ATTRIBUTE_CELL_CLASS as at, gridElementRenderer as ct, DEFAULT_CELL_PADDING as dt, buildFillerCell as ut } from "../../templates/grid/elementRenderer.js";
|
|
11
11
|
import { listElementRenderer as mt } from "../../templates/list/elementRenderer.js";
|
|
12
|
-
import {
|
|
13
|
-
import { getTableDisplayValue as
|
|
14
|
-
import { getCurrentLayout as
|
|
15
|
-
const
|
|
12
|
+
import { resolveInlinePriceOrder as ht, toDisplayName as pt, isDefaultAttribute as gt, toDisplayableAttributeValue as bt, buildElementRenderer as V } from "../../templates/utils.js";
|
|
13
|
+
import { getTableDisplayValue as _t } from "../../utils/tagName.js";
|
|
14
|
+
import { regenerateProductRowsWithStyles as ft, getCurrentLayout as yt } from "../main/utils.js";
|
|
15
|
+
const St = "ui-elements-recommendation-card-composition", T = ".recommendation-attribute-row", H = ".product-card-wrapper > tbody", j = ".product-info-cell > table > tbody", W = "data-card-composition", y = "data-attribute-type", O = "data-visibility", K = {
|
|
16
16
|
ADD_ATTRIBUTE: "addAttribute"
|
|
17
|
-
},
|
|
18
|
-
{ key:
|
|
19
|
-
{ key:
|
|
20
|
-
{ key:
|
|
21
|
-
{ key:
|
|
22
|
-
{ key:
|
|
17
|
+
}, f = 5, N = "reorderIcon_", Ct = '<svg width="14" height="10" viewBox="0 0 14 10" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><circle cx="2" cy="2.5" r="1.2"/><circle cx="7" cy="2.5" r="1.2"/><circle cx="12" cy="2.5" r="1.2"/><circle cx="2" cy="7.5" r="1.2"/><circle cx="7" cy="7.5" r="1.2"/><circle cx="12" cy="7.5" r="1.2"/></svg>', m = [
|
|
18
|
+
{ key: k, label: "Product Image" },
|
|
19
|
+
{ key: ot, label: "Product Name" },
|
|
20
|
+
{ key: S, label: "Product Price" },
|
|
21
|
+
{ key: v, label: "Product Original Price" },
|
|
22
|
+
{ key: it, label: "Omnibus Price" },
|
|
23
23
|
{ key: st, label: "Omnibus Discount" },
|
|
24
24
|
{ key: U, label: "Product Button" }
|
|
25
|
-
],
|
|
26
|
-
class Ut extends
|
|
25
|
+
], At = new Set(m.map((g) => g.key)), $ = "customAttr_", R = "deleteAttr_";
|
|
26
|
+
class Ut extends rt {
|
|
27
27
|
constructor() {
|
|
28
28
|
super(...arguments);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
I(this, "store", lt());
|
|
30
|
+
I(this, "unsubscribeStore", null);
|
|
31
|
+
I(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
|
-
|
|
36
|
+
I(this, "reorderInProgress", !1);
|
|
37
37
|
}
|
|
38
38
|
getId() {
|
|
39
|
-
return
|
|
39
|
+
return St;
|
|
40
40
|
}
|
|
41
41
|
// ========================================================================
|
|
42
42
|
// Lifecycle
|
|
43
43
|
// ========================================================================
|
|
44
44
|
getTemplate() {
|
|
45
|
-
const t =
|
|
46
|
-
<div data-toggle-key="${
|
|
47
|
-
${this._GuToggle(`visibility_${
|
|
45
|
+
const t = m.map((a) => `
|
|
46
|
+
<div data-toggle-key="${a.key}" style="display: none;">
|
|
47
|
+
${this._GuToggle(`visibility_${a.key}`)}
|
|
48
48
|
</div>
|
|
49
49
|
`).join(""), r = Array.from(
|
|
50
|
-
{ length:
|
|
51
|
-
(
|
|
52
|
-
<div data-custom-select-key="${
|
|
50
|
+
{ length: f },
|
|
51
|
+
(a, d) => `
|
|
52
|
+
<div data-custom-select-key="${$}${d}" style="display: none;">
|
|
53
53
|
${this._GuSelect({
|
|
54
|
-
name: `${
|
|
54
|
+
name: `${$}${d}`,
|
|
55
55
|
placeholder: this.api.translate("Select Attribute"),
|
|
56
56
|
options: []
|
|
57
57
|
})}
|
|
58
58
|
</div>
|
|
59
59
|
`
|
|
60
|
-
).join(""), e =
|
|
60
|
+
).join(""), e = m.length + f, i = Array.from(
|
|
61
61
|
{ length: e },
|
|
62
|
-
(
|
|
63
|
-
<div data-reorder-icon-key="${
|
|
64
|
-
<${
|
|
62
|
+
(a, d) => `
|
|
63
|
+
<div data-reorder-icon-key="${N}${d}" style="display: none;">
|
|
64
|
+
<${_.BUTTON}
|
|
65
65
|
class="drag-handle-btn flat-inline flat-white"
|
|
66
|
-
${
|
|
66
|
+
${E.BUTTON.name}="${N}${d}"
|
|
67
67
|
>
|
|
68
|
-
<${
|
|
68
|
+
<${_.ICON}
|
|
69
69
|
src="reorder"
|
|
70
70
|
class="icon-button"
|
|
71
|
-
></${
|
|
72
|
-
</${
|
|
71
|
+
></${_.ICON}>
|
|
72
|
+
</${_.BUTTON}>
|
|
73
73
|
</div>
|
|
74
74
|
`
|
|
75
|
-
).join(""),
|
|
76
|
-
{ length:
|
|
77
|
-
(
|
|
78
|
-
<div data-custom-delete-key="${R}${
|
|
79
|
-
<${
|
|
75
|
+
).join(""), o = Array.from(
|
|
76
|
+
{ length: f },
|
|
77
|
+
(a, d) => `
|
|
78
|
+
<div data-custom-delete-key="${R}${d}" style="display: none;">
|
|
79
|
+
<${_.BUTTON}
|
|
80
80
|
class="custom-attr-delete flat-inline flat-white"
|
|
81
|
-
${
|
|
81
|
+
${E.BUTTON.name}="${R}${d}"
|
|
82
82
|
>
|
|
83
|
-
<${
|
|
83
|
+
<${_.ICON}
|
|
84
84
|
src="delete"
|
|
85
85
|
class="icon-button"
|
|
86
|
-
></${
|
|
87
|
-
</${
|
|
86
|
+
></${_.ICON}>
|
|
87
|
+
</${_.BUTTON}>
|
|
88
88
|
</div>
|
|
89
89
|
`
|
|
90
|
-
).join(""),
|
|
90
|
+
).join(""), s = "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
|
-
),
|
|
92
|
+
), c = this.api.translate("For more information, you can"), l = 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
97
|
${n}
|
|
98
|
-
${
|
|
98
|
+
${c}
|
|
99
99
|
<!-- cspell:disable-next-line -->
|
|
100
|
-
<a href="${
|
|
100
|
+
<a href="${s}" target="_blank" rel="noopener noreferrer">${l}</a>.
|
|
101
101
|
</p>
|
|
102
102
|
</div>
|
|
103
103
|
|
|
@@ -110,17 +110,17 @@ class Ut extends Z {
|
|
|
110
110
|
</div>
|
|
111
111
|
|
|
112
112
|
<div class="custom-delete-store" style="display: none;">
|
|
113
|
-
${
|
|
113
|
+
${o}
|
|
114
114
|
</div>
|
|
115
115
|
|
|
116
116
|
<div class="reorder-icon-store" style="display: none;">
|
|
117
|
-
${
|
|
117
|
+
${i}
|
|
118
118
|
</div>
|
|
119
119
|
|
|
120
120
|
<div class="orderable-list" data-composition-list></div>
|
|
121
121
|
|
|
122
122
|
${this._GuButton({
|
|
123
|
-
name:
|
|
123
|
+
name: K.ADD_ATTRIBUTE,
|
|
124
124
|
label: this.api.translate("Add Attribute"),
|
|
125
125
|
id: "guido__btn-add-attribute"
|
|
126
126
|
})}
|
|
@@ -140,19 +140,19 @@ class Ut extends Z {
|
|
|
140
140
|
// Initialization
|
|
141
141
|
// ========================================================================
|
|
142
142
|
_initializeComposition() {
|
|
143
|
-
const t = this._readCompositionFromNode(), r = this._readCustomAttributesFromNode(), e = this._readVisibilityFromRows(),
|
|
144
|
-
this.api.updateValues(
|
|
143
|
+
const t = this._readCompositionFromNode(), r = this._readCustomAttributesFromNode(), e = this._readVisibilityFromRows(), i = this._renderOrderableItems(t, r), o = this._buildVisibilityValues(e);
|
|
144
|
+
this.api.updateValues(o), i && this._initializeCustomSelects(r), this._updateAddButtonState();
|
|
145
145
|
}
|
|
146
146
|
_registerValueChangeListeners() {
|
|
147
|
-
|
|
147
|
+
m.forEach((t) => {
|
|
148
148
|
this.api.onValueChanged(`visibility_${t.key}`, (r) => {
|
|
149
149
|
this._applyVisibilityToBlock(t.key, r);
|
|
150
150
|
});
|
|
151
151
|
});
|
|
152
|
-
for (let t = 0; t <
|
|
153
|
-
const r = `${
|
|
154
|
-
this.api.onValueChanged(r, (
|
|
155
|
-
this._onCustomAttributeChanged(e,
|
|
152
|
+
for (let t = 0; t < f; t++) {
|
|
153
|
+
const r = `${$}${t}`, e = t;
|
|
154
|
+
this.api.onValueChanged(r, (i) => {
|
|
155
|
+
this._onCustomAttributeChanged(e, i);
|
|
156
156
|
});
|
|
157
157
|
}
|
|
158
158
|
}
|
|
@@ -161,14 +161,14 @@ class Ut extends Z {
|
|
|
161
161
|
// ========================================================================
|
|
162
162
|
_readCompositionFromNode() {
|
|
163
163
|
if (!this.currentNode || !("getAttribute" in this.currentNode))
|
|
164
|
-
return [...
|
|
165
|
-
const t = this.currentNode.getAttribute(
|
|
166
|
-
return t ? t.split(",").filter(Boolean) : [...
|
|
164
|
+
return [...x];
|
|
165
|
+
const t = this.currentNode.getAttribute(W);
|
|
166
|
+
return t ? t.split(",").filter(Boolean) : [...x];
|
|
167
167
|
}
|
|
168
168
|
_readCustomAttributesFromNode() {
|
|
169
169
|
if (!this.currentNode || !("getAttribute" in this.currentNode))
|
|
170
170
|
return [];
|
|
171
|
-
const t = this.currentNode.getAttribute(
|
|
171
|
+
const t = this.currentNode.getAttribute(F);
|
|
172
172
|
if (!t)
|
|
173
173
|
return [];
|
|
174
174
|
try {
|
|
@@ -180,31 +180,31 @@ class Ut extends Z {
|
|
|
180
180
|
_readVisibilityFromRows() {
|
|
181
181
|
if (!this.currentNode)
|
|
182
182
|
return this._getDefaultVisibilities();
|
|
183
|
-
const t = Array.from(this.currentNode.querySelectorAll(
|
|
183
|
+
const t = Array.from(this.currentNode.querySelectorAll(T)), r = this._extractVisibilityFromRows(t);
|
|
184
184
|
return this._mergeWithDefaults(r);
|
|
185
185
|
}
|
|
186
186
|
_getDefaultVisibilities() {
|
|
187
|
-
return { ...
|
|
187
|
+
return { ...M };
|
|
188
188
|
}
|
|
189
189
|
_extractVisibilityFromRows(t) {
|
|
190
190
|
const r = {};
|
|
191
191
|
return t.forEach((e) => {
|
|
192
192
|
if (!("getAttribute" in e))
|
|
193
193
|
return;
|
|
194
|
-
const
|
|
195
|
-
|
|
194
|
+
const i = e.getAttribute(y), o = e.getAttribute(O);
|
|
195
|
+
i && o !== null && (r[i] = this._parseVisibilityValue(o));
|
|
196
196
|
}), r;
|
|
197
197
|
}
|
|
198
198
|
_parseVisibilityValue(t) {
|
|
199
199
|
return t === "1" || t === "true";
|
|
200
200
|
}
|
|
201
201
|
_mergeWithDefaults(t) {
|
|
202
|
-
return Object.entries(
|
|
202
|
+
return Object.entries(M).forEach(([r, e]) => {
|
|
203
203
|
r in t || (t[r] = e);
|
|
204
204
|
}), t;
|
|
205
205
|
}
|
|
206
206
|
_buildVisibilityValues(t) {
|
|
207
|
-
return
|
|
207
|
+
return m.reduce((r, e) => (r[`visibility_${e.key}`] = t[e.key] ?? !0, r), {});
|
|
208
208
|
}
|
|
209
209
|
// ========================================================================
|
|
210
210
|
// UI Rendering (Orderable List)
|
|
@@ -218,24 +218,30 @@ class Ut extends Z {
|
|
|
218
218
|
const e = this._getControlContainer();
|
|
219
219
|
if (!e)
|
|
220
220
|
return !1;
|
|
221
|
-
const
|
|
222
|
-
if (!
|
|
221
|
+
const i = e.querySelector("[data-composition-list]");
|
|
222
|
+
if (!i)
|
|
223
|
+
return !1;
|
|
224
|
+
const o = !P.getConfig(this.currentNode).priceMovedToNextLine;
|
|
225
|
+
if (!(i.dataset.inlinePrices !== String(o)) && this._tryReorderInPlace(i, t))
|
|
223
226
|
return !1;
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
return this.
|
|
227
|
+
i.dataset.inlinePrices = String(o);
|
|
228
|
+
const n = new Set(r), c = ht(t);
|
|
229
|
+
let l = 0, a = 0;
|
|
230
|
+
const d = t.map((u) => {
|
|
231
|
+
if (o && (u === S || u === v))
|
|
232
|
+
return u === c.anchor ? this._createPriceGroupItemHtml(a++, c.originalFirst) : "";
|
|
233
|
+
if (At.has(u)) {
|
|
234
|
+
const h = m.find((C) => C.key === u);
|
|
235
|
+
return this._createBuiltInItemHtml(h, a++);
|
|
230
236
|
}
|
|
231
|
-
if (
|
|
232
|
-
const
|
|
233
|
-
if (
|
|
234
|
-
return this._createCustomItemHtml(
|
|
237
|
+
if (u.startsWith(p)) {
|
|
238
|
+
const h = u.substring(p.length);
|
|
239
|
+
if (n.has(h))
|
|
240
|
+
return this._createCustomItemHtml(u, l++, a++);
|
|
235
241
|
}
|
|
236
242
|
return "";
|
|
237
243
|
}).join("");
|
|
238
|
-
return this._rescueTogglesToStore(e), this._rescueSelectsToStore(e), this._rescueDeleteButtonsToStore(e), this._rescueReorderIconsToStore(e),
|
|
244
|
+
return this._rescueTogglesToStore(e), this._rescueSelectsToStore(e), this._rescueDeleteButtonsToStore(e), this._rescueReorderIconsToStore(e), i.innerHTML = d, this._moveTogglesIntoItems(e), this._moveSelectsIntoItems(e, r.length), this._moveDeleteButtonsIntoItems(e, r.length), this._moveReorderIconsIntoItems(e, a), !0;
|
|
239
245
|
}
|
|
240
246
|
/**
|
|
241
247
|
* Attempts to reorder existing orderable-item elements to match the composition order.
|
|
@@ -247,27 +253,27 @@ class Ut extends Z {
|
|
|
247
253
|
const e = Array.from(t.querySelectorAll(".orderable-item"));
|
|
248
254
|
if (e.length !== r.length)
|
|
249
255
|
return !1;
|
|
250
|
-
const
|
|
251
|
-
if (
|
|
256
|
+
const i = e.map((l) => l.dataset.key).filter(Boolean);
|
|
257
|
+
if (i.length !== r.length)
|
|
252
258
|
return !1;
|
|
253
|
-
const
|
|
254
|
-
if (
|
|
259
|
+
const o = [...i].sort().join(","), s = [...r].sort().join(",");
|
|
260
|
+
if (o !== s || r.some((l) => l.startsWith(p)))
|
|
255
261
|
return !1;
|
|
256
262
|
const n = /* @__PURE__ */ new Map();
|
|
257
|
-
e.forEach((
|
|
258
|
-
const { key:
|
|
259
|
-
if (
|
|
260
|
-
const
|
|
261
|
-
|
|
263
|
+
e.forEach((l) => {
|
|
264
|
+
const { key: a } = l.dataset;
|
|
265
|
+
if (a) {
|
|
266
|
+
const d = n.get(a) || [];
|
|
267
|
+
d.push(l), n.set(a, d);
|
|
262
268
|
}
|
|
263
269
|
});
|
|
264
|
-
const
|
|
265
|
-
return r.forEach((
|
|
266
|
-
const
|
|
267
|
-
if (!
|
|
270
|
+
const c = /* @__PURE__ */ new Map();
|
|
271
|
+
return r.forEach((l) => {
|
|
272
|
+
const a = n.get(l);
|
|
273
|
+
if (!a)
|
|
268
274
|
return;
|
|
269
|
-
const
|
|
270
|
-
|
|
275
|
+
const d = c.get(l) || 0;
|
|
276
|
+
c.set(l, d + 1), a[d] && t.appendChild(a[d]);
|
|
271
277
|
}), !0;
|
|
272
278
|
}
|
|
273
279
|
_createBuiltInItemHtml(t, r) {
|
|
@@ -279,6 +285,33 @@ class Ut extends Z {
|
|
|
279
285
|
</div>
|
|
280
286
|
`;
|
|
281
287
|
}
|
|
288
|
+
/**
|
|
289
|
+
* Inline mode: the merged "Product Prices" group item. It moves as a unit in
|
|
290
|
+
* the main list (both keys stay adjacent) and contains a nested 2-item drag
|
|
291
|
+
* to reorder Product Price ↔ Product Original Price — which flips the inline
|
|
292
|
+
* render order via `resolveInlinePriceOrder`. The group keeps a single
|
|
293
|
+
* visibility toggle (`data-action-for="productPrice"`). Nested sub-items use a
|
|
294
|
+
* plain drag handle (no UE button → untouched by the reorder-icon rescue).
|
|
295
|
+
*/
|
|
296
|
+
_createPriceGroupItemHtml(t, r) {
|
|
297
|
+
var n, c;
|
|
298
|
+
const e = ((n = m.find((l) => l.key === S)) == null ? void 0 : n.label) ?? "Product Price", i = ((c = m.find((l) => l.key === v)) == null ? void 0 : c.label) ?? "Product Original Price", o = (l, a) => `
|
|
299
|
+
<div class="price-suborderable-item" draggable="true" data-subkey="${l}">
|
|
300
|
+
<span class="sub-drag-handle">${Ct}</span>
|
|
301
|
+
<span class="item-label">${this.api.translate(a)}</span>
|
|
302
|
+
</div>`, s = r ? o(v, i) + o(S, e) : o(S, e) + o(v, i);
|
|
303
|
+
return `
|
|
304
|
+
<div class="orderable-item price-group-item" draggable="true"
|
|
305
|
+
data-key="${S}" data-group="prices">
|
|
306
|
+
<div class="price-group-header">
|
|
307
|
+
<span class="drag-handle" data-reorder-icon-slot="${t}"></span>
|
|
308
|
+
<span class="item-label">${this.api.translate("Product Prices")}</span>
|
|
309
|
+
<div class="item-action" data-action-for="${S}"></div>
|
|
310
|
+
</div>
|
|
311
|
+
<div class="price-suborderable-list">${s}</div>
|
|
312
|
+
</div>
|
|
313
|
+
`;
|
|
314
|
+
}
|
|
282
315
|
_createCustomItemHtml(t, r, e) {
|
|
283
316
|
return `
|
|
284
317
|
<div class="orderable-item" draggable="true"
|
|
@@ -299,10 +332,10 @@ class Ut extends Z {
|
|
|
299
332
|
_getSelectOptions(t, r = []) {
|
|
300
333
|
const e = this._getAddableFilters();
|
|
301
334
|
if (e.length > 0) {
|
|
302
|
-
const
|
|
303
|
-
return
|
|
304
|
-
text:
|
|
305
|
-
value:
|
|
335
|
+
const o = new Set(r);
|
|
336
|
+
return o.delete(t), e.filter((s) => !o.has(s.attributeName)).map((s) => ({
|
|
337
|
+
text: s.displayName,
|
|
338
|
+
value: s.attributeName
|
|
306
339
|
}));
|
|
307
340
|
}
|
|
308
341
|
return [{ text: this._getDisplayNameForAttribute(t), value: t }];
|
|
@@ -315,8 +348,8 @@ class Ut extends Z {
|
|
|
315
348
|
_initializeCustomSelects(t) {
|
|
316
349
|
t.length !== 0 && setTimeout(() => {
|
|
317
350
|
t.forEach((r, e) => {
|
|
318
|
-
const
|
|
319
|
-
this.api.setUIEAttribute(
|
|
351
|
+
const i = `${$}${e}`, o = this._getSelectOptions(r, t);
|
|
352
|
+
this.api.setUIEAttribute(i, E.SELECTPICKER.items, o), this.api.updateValues({ [i]: r });
|
|
320
353
|
});
|
|
321
354
|
}, 0);
|
|
322
355
|
}
|
|
@@ -325,11 +358,11 @@ class Ut extends Z {
|
|
|
325
358
|
* Stripo initializes toggles at template parse time; moving the DOM node preserves bindings.
|
|
326
359
|
*/
|
|
327
360
|
_moveTogglesIntoItems(t) {
|
|
328
|
-
|
|
329
|
-
const e = t.querySelector(`[data-toggle-key="${r.key}"]`),
|
|
330
|
-
if (e &&
|
|
331
|
-
const
|
|
332
|
-
|
|
361
|
+
m.forEach((r) => {
|
|
362
|
+
const e = t.querySelector(`[data-toggle-key="${r.key}"]`), i = t.querySelector(`[data-action-for="${r.key}"]`);
|
|
363
|
+
if (e && i) {
|
|
364
|
+
const o = e.querySelector("ue-switcher");
|
|
365
|
+
o && i.appendChild(o);
|
|
333
366
|
}
|
|
334
367
|
});
|
|
335
368
|
}
|
|
@@ -339,10 +372,10 @@ class Ut extends Z {
|
|
|
339
372
|
*/
|
|
340
373
|
_moveSelectsIntoItems(t, r) {
|
|
341
374
|
for (let e = 0; e < r; e++) {
|
|
342
|
-
const
|
|
343
|
-
if (
|
|
344
|
-
const n =
|
|
345
|
-
n &&
|
|
375
|
+
const i = `${$}${e}`, o = t.querySelector(`[data-custom-select-key="${i}"]`), s = t.querySelector(`[data-custom-select-slot="${e}"]`);
|
|
376
|
+
if (o && s) {
|
|
377
|
+
const n = o.querySelector("ue-select");
|
|
378
|
+
n && s.appendChild(n);
|
|
346
379
|
}
|
|
347
380
|
}
|
|
348
381
|
}
|
|
@@ -353,11 +386,11 @@ class Ut extends Z {
|
|
|
353
386
|
* previously-moved toggles, making them permanently lost.
|
|
354
387
|
*/
|
|
355
388
|
_rescueTogglesToStore(t) {
|
|
356
|
-
|
|
357
|
-
const e = t.querySelector(`[data-toggle-key="${r.key}"]`),
|
|
358
|
-
if (
|
|
359
|
-
const
|
|
360
|
-
|
|
389
|
+
m.forEach((r) => {
|
|
390
|
+
const e = t.querySelector(`[data-toggle-key="${r.key}"]`), i = t.querySelector(`[data-action-for="${r.key}"]`);
|
|
391
|
+
if (i) {
|
|
392
|
+
const o = i.querySelector("ue-switcher");
|
|
393
|
+
o && e && e.appendChild(o);
|
|
361
394
|
}
|
|
362
395
|
});
|
|
363
396
|
}
|
|
@@ -366,11 +399,11 @@ class Ut extends Z {
|
|
|
366
399
|
* Same rescue pattern as _rescueTogglesToStore — prevents innerHTML from destroying them.
|
|
367
400
|
*/
|
|
368
401
|
_rescueSelectsToStore(t) {
|
|
369
|
-
for (let r = 0; r <
|
|
370
|
-
const e = `${
|
|
371
|
-
if (
|
|
372
|
-
const
|
|
373
|
-
|
|
402
|
+
for (let r = 0; r < f; r++) {
|
|
403
|
+
const e = `${$}${r}`, i = t.querySelector(`[data-custom-select-key="${e}"]`), o = t.querySelector(`[data-custom-select-slot="${r}"]`);
|
|
404
|
+
if (o) {
|
|
405
|
+
const s = o.querySelector("ue-select");
|
|
406
|
+
s && i && i.appendChild(s);
|
|
374
407
|
}
|
|
375
408
|
}
|
|
376
409
|
}
|
|
@@ -380,10 +413,10 @@ class Ut extends Z {
|
|
|
380
413
|
*/
|
|
381
414
|
_moveDeleteButtonsIntoItems(t, r) {
|
|
382
415
|
for (let e = 0; e < r; e++) {
|
|
383
|
-
const
|
|
384
|
-
if (
|
|
385
|
-
const n =
|
|
386
|
-
n &&
|
|
416
|
+
const i = `${R}${e}`, o = t.querySelector(`[data-custom-delete-key="${i}"]`), s = t.querySelector(`[data-custom-delete-slot="${e}"]`);
|
|
417
|
+
if (o && s) {
|
|
418
|
+
const n = o.querySelector("ue-button");
|
|
419
|
+
n && s.appendChild(n);
|
|
387
420
|
}
|
|
388
421
|
}
|
|
389
422
|
}
|
|
@@ -392,11 +425,11 @@ class Ut extends Z {
|
|
|
392
425
|
* Same rescue pattern as _rescueSelectsToStore — prevents innerHTML from destroying them.
|
|
393
426
|
*/
|
|
394
427
|
_rescueDeleteButtonsToStore(t) {
|
|
395
|
-
for (let r = 0; r <
|
|
396
|
-
const e = `${R}${r}`,
|
|
397
|
-
if (
|
|
398
|
-
const
|
|
399
|
-
|
|
428
|
+
for (let r = 0; r < f; r++) {
|
|
429
|
+
const e = `${R}${r}`, i = t.querySelector(`[data-custom-delete-key="${e}"]`), o = t.querySelector(`[data-custom-delete-slot="${r}"]`);
|
|
430
|
+
if (o) {
|
|
431
|
+
const s = o.querySelector("ue-button");
|
|
432
|
+
s && i && i.appendChild(s);
|
|
400
433
|
}
|
|
401
434
|
}
|
|
402
435
|
}
|
|
@@ -406,10 +439,10 @@ class Ut extends Z {
|
|
|
406
439
|
*/
|
|
407
440
|
_moveReorderIconsIntoItems(t, r) {
|
|
408
441
|
for (let e = 0; e < r; e++) {
|
|
409
|
-
const
|
|
410
|
-
if (
|
|
411
|
-
const n =
|
|
412
|
-
n &&
|
|
442
|
+
const i = `${N}${e}`, o = t.querySelector(`[data-reorder-icon-key="${i}"]`), s = t.querySelector(`[data-reorder-icon-slot="${e}"]`);
|
|
443
|
+
if (o && s) {
|
|
444
|
+
const n = o.querySelector("ue-button");
|
|
445
|
+
n && s.appendChild(n);
|
|
413
446
|
}
|
|
414
447
|
}
|
|
415
448
|
}
|
|
@@ -418,12 +451,12 @@ class Ut extends Z {
|
|
|
418
451
|
* Same rescue pattern as _rescueDeleteButtonsToStore — prevents innerHTML from destroying them.
|
|
419
452
|
*/
|
|
420
453
|
_rescueReorderIconsToStore(t) {
|
|
421
|
-
const r =
|
|
454
|
+
const r = m.length + f;
|
|
422
455
|
for (let e = 0; e < r; e++) {
|
|
423
|
-
const
|
|
424
|
-
if (
|
|
425
|
-
const n =
|
|
426
|
-
n &&
|
|
456
|
+
const i = `${N}${e}`, o = t.querySelector(`[data-reorder-icon-key="${i}"]`), s = t.querySelector(`[data-reorder-icon-slot="${e}"]`);
|
|
457
|
+
if (s) {
|
|
458
|
+
const n = s.querySelector("ue-button");
|
|
459
|
+
n && o && o.appendChild(n);
|
|
427
460
|
}
|
|
428
461
|
}
|
|
429
462
|
}
|
|
@@ -435,41 +468,83 @@ class Ut extends Z {
|
|
|
435
468
|
const { signal: t } = this.eventController, r = this._getControlContainer();
|
|
436
469
|
if (!r)
|
|
437
470
|
return;
|
|
438
|
-
const e = r.querySelector("[data-composition-list]"),
|
|
439
|
-
e && (this._setupDragAndDrop(e, t), this._setupDeleteHandler(e, t)),
|
|
440
|
-
const
|
|
441
|
-
|
|
471
|
+
const e = r.querySelector("[data-composition-list]"), i = r.querySelector("#guido__btn-add-attribute");
|
|
472
|
+
e && (this._setupDragAndDrop(e, t), this._setupDeleteHandler(e, t)), i && i.addEventListener("click", () => {
|
|
473
|
+
const o = new Set(this._readCustomAttributesFromNode()), s = this._getAddableFilters().find((n) => !o.has(n.attributeName));
|
|
474
|
+
s && this._onAddAttribute(s.attributeName, s.displayName);
|
|
442
475
|
}, { signal: t });
|
|
443
476
|
}
|
|
477
|
+
/**
|
|
478
|
+
* Builds the composition key order from the orderable list, expanding the
|
|
479
|
+
* inline "Product Prices" group into its two sub-keys (in nested DOM order)
|
|
480
|
+
* so both price keys stay adjacent and in the user-chosen order.
|
|
481
|
+
*/
|
|
482
|
+
_extractCompositionOrder(t) {
|
|
483
|
+
const r = [];
|
|
484
|
+
return t.querySelectorAll(".orderable-item").forEach((e) => {
|
|
485
|
+
const i = e;
|
|
486
|
+
i.dataset.group === "prices" ? i.querySelectorAll(".price-suborderable-item").forEach((o) => {
|
|
487
|
+
const s = o.dataset.subkey;
|
|
488
|
+
s && r.push(s);
|
|
489
|
+
}) : i.dataset.key && r.push(i.dataset.key);
|
|
490
|
+
}), r;
|
|
491
|
+
}
|
|
444
492
|
_setupDragAndDrop(t, r) {
|
|
445
|
-
|
|
446
|
-
|
|
493
|
+
this._registerDragHandlers(t, r, {
|
|
494
|
+
itemSelector: ".orderable-item",
|
|
495
|
+
ignoreSelector: ".price-suborderable-item",
|
|
496
|
+
getDropParent: () => t
|
|
497
|
+
}), this._registerDragHandlers(t, r, {
|
|
498
|
+
itemSelector: ".price-suborderable-item",
|
|
499
|
+
getDropParent: (e) => e.parentElement
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Wires drag/drop reordering for one item level on the shared list. Both the
|
|
504
|
+
* top-level items and the nested price sub-items use this; they never fight
|
|
505
|
+
* because each only sets its `dragged` ref when its own `itemSelector` matches
|
|
506
|
+
* at dragstart (and the top-level one additionally ignores drags originating
|
|
507
|
+
* inside `ignoreSelector`). Every drop re-reads the full composition via
|
|
508
|
+
* `_extractCompositionOrder`, so both levels commit through `_onReorder`
|
|
509
|
+
* identically.
|
|
510
|
+
*/
|
|
511
|
+
_registerDragHandlers(t, r, e) {
|
|
512
|
+
let i = null, o = null;
|
|
513
|
+
const s = (n) => n.target.closest(e.itemSelector);
|
|
514
|
+
t.addEventListener("dragstart", (n) => {
|
|
447
515
|
var a;
|
|
448
|
-
const
|
|
449
|
-
|
|
516
|
+
const c = n.target;
|
|
517
|
+
if (e.ignoreSelector && c.closest(e.ignoreSelector))
|
|
518
|
+
return;
|
|
519
|
+
const l = s(n);
|
|
520
|
+
l && (i = l, l.classList.add("dragging"), (a = n.dataTransfer) == null || a.setData("text/plain", l.dataset.key ?? l.dataset.subkey ?? ""));
|
|
450
521
|
}, { signal: r }), t.addEventListener("dragend", () => {
|
|
451
|
-
|
|
452
|
-
}, { signal: r }), t.addEventListener("dragover", (
|
|
453
|
-
|
|
454
|
-
const n = s.target.closest(".orderable-item"), a = n && n !== e ? n : null;
|
|
455
|
-
a !== o && (o == null || o.classList.remove("drag-over"), o = a, o == null || o.classList.add("drag-over"));
|
|
456
|
-
}, { signal: r }), t.addEventListener("drop", (s) => {
|
|
457
|
-
s.preventDefault();
|
|
458
|
-
const n = s.target.closest(".orderable-item");
|
|
459
|
-
if (!n || !e || n === e)
|
|
522
|
+
i == null || i.classList.remove("dragging"), o == null || o.classList.remove("drag-over"), i = null, o = null;
|
|
523
|
+
}, { signal: r }), t.addEventListener("dragover", (n) => {
|
|
524
|
+
if (!i)
|
|
460
525
|
return;
|
|
461
|
-
const
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
526
|
+
const c = s(n);
|
|
527
|
+
if (!c)
|
|
528
|
+
return;
|
|
529
|
+
n.preventDefault();
|
|
530
|
+
const l = c !== i ? c : null;
|
|
531
|
+
l !== o && (o == null || o.classList.remove("drag-over"), o = l, o == null || o.classList.add("drag-over"));
|
|
532
|
+
}, { signal: r }), t.addEventListener("drop", (n) => {
|
|
533
|
+
var d;
|
|
534
|
+
const c = i && s(n);
|
|
535
|
+
if (!i || !c || c === i)
|
|
536
|
+
return;
|
|
537
|
+
n.preventDefault();
|
|
538
|
+
const l = c.getBoundingClientRect(), a = n.clientY < l.top + l.height / 2;
|
|
539
|
+
(d = e.getDropParent(c)) == null || d.insertBefore(i, a ? c : c.nextSibling), o == null || o.classList.remove("drag-over"), i.classList.remove("dragging"), i = null, o = null, this._onReorder(this._extractCompositionOrder(t));
|
|
465
540
|
}, { signal: r });
|
|
466
541
|
}
|
|
467
542
|
_setupDeleteHandler(t, r) {
|
|
468
543
|
t.addEventListener("click", (e) => {
|
|
469
|
-
const
|
|
470
|
-
if (!
|
|
544
|
+
const o = e.target.closest(".custom-attr-delete");
|
|
545
|
+
if (!o)
|
|
471
546
|
return;
|
|
472
|
-
const
|
|
547
|
+
const s = o.closest("[data-custom-index]"), n = s == null ? void 0 : s.dataset.customIndex;
|
|
473
548
|
n !== void 0 && this._onDeleteCustomAttribute(Number(n));
|
|
474
549
|
}, { signal: r });
|
|
475
550
|
}
|
|
@@ -477,10 +552,10 @@ class Ut extends Z {
|
|
|
477
552
|
// Actions (Add, Delete, Reorder)
|
|
478
553
|
// ========================================================================
|
|
479
554
|
_onAddAttribute(t, r) {
|
|
480
|
-
const e = `${
|
|
481
|
-
|
|
482
|
-
const
|
|
483
|
-
this._updateBothAttributes(
|
|
555
|
+
const e = `${p}${t}`, i = this._readCompositionFromNode();
|
|
556
|
+
i.push(e);
|
|
557
|
+
const o = [...this._readCustomAttributesFromNode(), t];
|
|
558
|
+
this._updateBothAttributes(i, o), this._injectCustomAttributeHtml(t, r, e, i), this._renderOrderableItems(i, o), this._initializeCustomSelects(o), this._updateAddButtonState();
|
|
484
559
|
}
|
|
485
560
|
/**
|
|
486
561
|
* Removes a single custom attribute by its index in the customAttrs array.
|
|
@@ -490,27 +565,32 @@ class Ut extends Z {
|
|
|
490
565
|
const r = this._readCustomAttributesFromNode();
|
|
491
566
|
if (r[t] === void 0)
|
|
492
567
|
return;
|
|
493
|
-
const
|
|
494
|
-
this._updateBothAttributes(
|
|
568
|
+
const i = this._readCompositionFromNode(), o = this._findNthCustomKeyIndex(i, t), s = i.filter((c, l) => l !== o), n = r.filter((c, l) => l !== t);
|
|
569
|
+
this._updateBothAttributes(s, n), this._removeCustomAttributeHtml(s), this._renderOrderableItems(s, n), this._initializeCustomSelects(n), this._updateAddButtonState();
|
|
495
570
|
}
|
|
496
571
|
/**
|
|
497
572
|
* Handles changing a custom attribute's selection via its inline _GuSelect.
|
|
498
573
|
* Uses the customIndex to target only the specific instance, supporting duplicates.
|
|
499
574
|
*/
|
|
500
575
|
_onCustomAttributeChanged(t, r) {
|
|
501
|
-
const e = this._readCustomAttributesFromNode(),
|
|
502
|
-
if (
|
|
576
|
+
const e = this._readCustomAttributesFromNode(), i = e[t];
|
|
577
|
+
if (i === void 0 || i === r)
|
|
503
578
|
return;
|
|
504
|
-
const
|
|
505
|
-
n !== -1 && (
|
|
506
|
-
const
|
|
507
|
-
this._updateBothAttributes(
|
|
579
|
+
const o = `${p}${r}`, s = this._readCompositionFromNode(), n = this._findNthCustomKeyIndex(s, t);
|
|
580
|
+
n !== -1 && (s[n] = o), e[t] = r;
|
|
581
|
+
const c = this._getDisplayNameForAttribute(r);
|
|
582
|
+
this._updateBothAttributes(s, e), this._injectCustomAttributeHtml(r, c, o, s), this._renderOrderableItems(s, e), this._initializeCustomSelects(e);
|
|
508
583
|
}
|
|
509
584
|
_onReorder(t) {
|
|
510
|
-
const r = t.filter((e) => e.startsWith(
|
|
585
|
+
const r = t.filter((e) => e.startsWith(p)).map((e) => e.substring(p.length));
|
|
511
586
|
this.reorderInProgress = !0;
|
|
512
587
|
try {
|
|
513
|
-
this._updateBothAttributes(t, r)
|
|
588
|
+
this._updateBothAttributes(t, r);
|
|
589
|
+
const e = !P.getConfig(this.currentNode).priceMovedToNextLine;
|
|
590
|
+
this._getCurrentLayout() === "grid" && !e ? this._reorderProductAttributes(t) : this.currentNode && ft({
|
|
591
|
+
currentNode: this.currentNode,
|
|
592
|
+
documentModifier: this.api.getDocumentModifier()
|
|
593
|
+
});
|
|
514
594
|
} finally {
|
|
515
595
|
this.reorderInProgress = !1;
|
|
516
596
|
}
|
|
@@ -519,66 +599,66 @@ class Ut extends Z {
|
|
|
519
599
|
// ========================================================================
|
|
520
600
|
// HTML Injection / Removal (Product Card DOM)
|
|
521
601
|
// ========================================================================
|
|
522
|
-
_injectCustomAttributeHtml(t, r, e,
|
|
602
|
+
_injectCustomAttributeHtml(t, r, e, i) {
|
|
523
603
|
if (!this.currentNode)
|
|
524
604
|
return;
|
|
525
|
-
this._getCurrentLayout() === "grid" ? this._injectGridAttributeRow(t, r, e,
|
|
605
|
+
this._getCurrentLayout() === "grid" ? this._injectGridAttributeRow(t, r, e, i) : this._injectListAttributeRow(t, r, e, i);
|
|
526
606
|
}
|
|
527
|
-
_injectGridAttributeRow(t, r, e,
|
|
528
|
-
const
|
|
529
|
-
if (!(
|
|
607
|
+
_injectGridAttributeRow(t, r, e, i) {
|
|
608
|
+
const o = this.currentNode.querySelectorAll(H);
|
|
609
|
+
if (!(o != null && o.length))
|
|
530
610
|
return;
|
|
531
|
-
const
|
|
532
|
-
let
|
|
533
|
-
|
|
534
|
-
var
|
|
535
|
-
const
|
|
536
|
-
if (
|
|
537
|
-
const
|
|
538
|
-
{ length:
|
|
539
|
-
(
|
|
540
|
-
const
|
|
611
|
+
const s = P.getConfig(this.currentNode), c = `0 ${Math.floor(s.columnSpacing / 2)}px`, l = this.api.getDocumentModifier(), a = this.store.recommendationProducts.length;
|
|
612
|
+
let d = 0;
|
|
613
|
+
o.forEach((u) => {
|
|
614
|
+
var w;
|
|
615
|
+
const h = u.querySelector(T), C = ((w = h == null ? void 0 : h.querySelectorAll(`.${at}`)) == null ? void 0 : w.length) || 1, q = (100 / C).toFixed(2), { bgStyle: G, bgAttr: z } = this._extractSegmentBgFromCard(u), D = a > 0 ? Math.min(C, a - d) : C, Y = i.map((B) => {
|
|
616
|
+
if (B === e) {
|
|
617
|
+
const X = Array.from(
|
|
618
|
+
{ length: D },
|
|
619
|
+
(Tt, Q) => {
|
|
620
|
+
const Z = this._resolveAttributeContent(
|
|
541
621
|
t,
|
|
542
622
|
r,
|
|
543
|
-
|
|
623
|
+
d + Q
|
|
544
624
|
);
|
|
545
625
|
return this._getGridCellHtml(
|
|
546
626
|
t,
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
627
|
+
Z,
|
|
628
|
+
q,
|
|
629
|
+
G,
|
|
630
|
+
z,
|
|
631
|
+
c
|
|
552
632
|
);
|
|
553
633
|
}
|
|
554
|
-
).join(""),
|
|
555
|
-
return `<tr class="recommendation-attribute-row" ${y}="${e}" ${
|
|
634
|
+
).join(""), J = ut(q, c).repeat(C - D);
|
|
635
|
+
return `<tr class="recommendation-attribute-row" ${y}="${e}" ${O}="1">${X}${J}</tr>`;
|
|
556
636
|
}
|
|
557
|
-
const
|
|
558
|
-
`${
|
|
637
|
+
const L = u.querySelector(
|
|
638
|
+
`${T}[${y}="${B}"]`
|
|
559
639
|
);
|
|
560
|
-
return
|
|
640
|
+
return L && "getOuterHTML" in L ? L.getOuterHTML() : "";
|
|
561
641
|
}).join("");
|
|
562
|
-
|
|
563
|
-
}),
|
|
642
|
+
d += D, a > 0 && d >= a && (d = 0), l.modifyHtml(u).setInnerHtml(Y);
|
|
643
|
+
}), l.apply(new A(`${this.api.translate("Add custom attribute")}: ${r}`));
|
|
564
644
|
}
|
|
565
|
-
_injectListAttributeRow(t, r, e,
|
|
566
|
-
const
|
|
567
|
-
if (!(
|
|
645
|
+
_injectListAttributeRow(t, r, e, i) {
|
|
646
|
+
const o = this.currentNode.querySelectorAll(j);
|
|
647
|
+
if (!(o != null && o.length))
|
|
568
648
|
return;
|
|
569
|
-
const
|
|
570
|
-
|
|
571
|
-
const
|
|
572
|
-
if (
|
|
573
|
-
const
|
|
574
|
-
return this._getListRowHtml(t,
|
|
649
|
+
const s = i.filter((c) => c !== k && c !== U), n = this.api.getDocumentModifier();
|
|
650
|
+
o.forEach((c, l) => {
|
|
651
|
+
const a = s.map((d) => {
|
|
652
|
+
if (d === e) {
|
|
653
|
+
const h = this._resolveAttributeContent(t, r, l);
|
|
654
|
+
return this._getListRowHtml(t, h, e);
|
|
575
655
|
}
|
|
576
|
-
const
|
|
577
|
-
`${
|
|
656
|
+
const u = c.querySelector(
|
|
657
|
+
`${T}[${y}="${d}"]`
|
|
578
658
|
);
|
|
579
|
-
return
|
|
659
|
+
return u && "getOuterHTML" in u ? u.getOuterHTML() : "";
|
|
580
660
|
}).join("");
|
|
581
|
-
n.modifyHtml(
|
|
661
|
+
n.modifyHtml(c).setInnerHtml(a);
|
|
582
662
|
}), n.apply(new A(`${this.api.translate("Add custom attribute")}: ${r}`));
|
|
583
663
|
}
|
|
584
664
|
/**
|
|
@@ -590,16 +670,16 @@ class Ut extends Z {
|
|
|
590
670
|
return;
|
|
591
671
|
const r = this._getCurrentLayout(), e = this.api.getDocumentModifier();
|
|
592
672
|
if (r === "grid") {
|
|
593
|
-
const
|
|
594
|
-
|
|
595
|
-
const
|
|
596
|
-
e.modifyHtml(
|
|
673
|
+
const i = this.currentNode.querySelectorAll(H);
|
|
674
|
+
i == null || i.forEach((o) => {
|
|
675
|
+
const s = this._buildCompositionHtml(o, t);
|
|
676
|
+
e.modifyHtml(o).setInnerHtml(s);
|
|
597
677
|
});
|
|
598
678
|
} else {
|
|
599
|
-
const
|
|
600
|
-
|
|
601
|
-
const n = this._buildCompositionHtml(
|
|
602
|
-
e.modifyHtml(
|
|
679
|
+
const i = t.filter((s) => s !== k && s !== U), o = this.currentNode.querySelectorAll(j);
|
|
680
|
+
o == null || o.forEach((s) => {
|
|
681
|
+
const n = this._buildCompositionHtml(s, i);
|
|
682
|
+
e.modifyHtml(s).setInnerHtml(n);
|
|
603
683
|
});
|
|
604
684
|
}
|
|
605
685
|
e.apply(new A(this.api.translate("Remove custom attribute")));
|
|
@@ -615,7 +695,7 @@ class Ut extends Z {
|
|
|
615
695
|
* producing a flicker on the custom attribute dropdowns.
|
|
616
696
|
*/
|
|
617
697
|
_updateBothAttributes(t, r) {
|
|
618
|
-
this.currentNode && this.api.getDocumentModifier().modifyHtml(this.currentNode).setAttribute(
|
|
698
|
+
this.currentNode && this.api.getDocumentModifier().modifyHtml(this.currentNode).setAttribute(W, t.join(",")).setAttribute(F, JSON.stringify(r)).apply(new A(this.api.translate("Update card composition")));
|
|
619
699
|
}
|
|
620
700
|
/**
|
|
621
701
|
* Reorders attribute rows within each product card based on composition order.
|
|
@@ -624,13 +704,13 @@ class Ut extends Z {
|
|
|
624
704
|
_reorderProductAttributes(t) {
|
|
625
705
|
if (!this.currentNode)
|
|
626
706
|
return;
|
|
627
|
-
const r = this.currentNode.querySelectorAll(
|
|
707
|
+
const r = this.currentNode.querySelectorAll(H);
|
|
628
708
|
if (!(r != null && r.length))
|
|
629
709
|
return;
|
|
630
710
|
const e = this.api.getDocumentModifier();
|
|
631
|
-
r.forEach((
|
|
632
|
-
const
|
|
633
|
-
e.modifyHtml(
|
|
711
|
+
r.forEach((i) => {
|
|
712
|
+
const o = this._buildCompositionHtml(i, t);
|
|
713
|
+
e.modifyHtml(i).setInnerHtml(o);
|
|
634
714
|
}), e.apply(new A(this.api.translate("Reorder product attributes")));
|
|
635
715
|
}
|
|
636
716
|
/**
|
|
@@ -638,9 +718,9 @@ class Ut extends Z {
|
|
|
638
718
|
* Queries existing rows from the container by data-attribute-type.
|
|
639
719
|
*/
|
|
640
720
|
_buildCompositionHtml(t, r) {
|
|
641
|
-
return r.reduce((e,
|
|
642
|
-
const
|
|
643
|
-
return
|
|
721
|
+
return r.reduce((e, i) => {
|
|
722
|
+
const o = t.querySelector(`${T}[${y}="${i}"]`);
|
|
723
|
+
return o && "getOuterHTML" in o ? e + o.getOuterHTML() : e;
|
|
644
724
|
}, "");
|
|
645
725
|
}
|
|
646
726
|
// ========================================================================
|
|
@@ -649,14 +729,14 @@ class Ut extends Z {
|
|
|
649
729
|
_applyVisibilityToBlock(t, r) {
|
|
650
730
|
if (!this.currentNode)
|
|
651
731
|
return;
|
|
652
|
-
const e = this.currentNode.querySelectorAll(`${
|
|
732
|
+
const e = this.currentNode.querySelectorAll(`${T}[${y}="${t}"]`);
|
|
653
733
|
if (!(e != null && e.length))
|
|
654
734
|
return;
|
|
655
|
-
const
|
|
656
|
-
e.forEach((
|
|
657
|
-
const
|
|
658
|
-
n.modifyHtml(
|
|
659
|
-
}), n.apply(new A(
|
|
735
|
+
const i = r ? "1" : "0", o = r ? this.api.translate("visible") : this.api.translate("hidden"), s = `${this.api.translate("Set visibility")}: ${t} → ${o}`, n = this.api.getDocumentModifier();
|
|
736
|
+
e.forEach((c) => {
|
|
737
|
+
const l = _t(c), a = r ? l : "none";
|
|
738
|
+
n.modifyHtml(c).setStyle("display", a).setAttribute(O, i);
|
|
739
|
+
}), n.apply(new A(s));
|
|
660
740
|
}
|
|
661
741
|
// ========================================================================
|
|
662
742
|
// Utilities
|
|
@@ -668,16 +748,16 @@ class Ut extends Z {
|
|
|
668
748
|
*/
|
|
669
749
|
_findNthCustomKeyIndex(t, r) {
|
|
670
750
|
let e = 0;
|
|
671
|
-
for (let
|
|
672
|
-
if (t[
|
|
751
|
+
for (let i = 0; i < t.length; i++)
|
|
752
|
+
if (t[i].startsWith(p)) {
|
|
673
753
|
if (e === r)
|
|
674
|
-
return
|
|
754
|
+
return i;
|
|
675
755
|
e++;
|
|
676
756
|
}
|
|
677
757
|
return -1;
|
|
678
758
|
}
|
|
679
759
|
_getCurrentLayout() {
|
|
680
|
-
return this.store.recommendationConfigs.orientation ||
|
|
760
|
+
return this.store.recommendationConfigs.orientation || yt(this.currentNode);
|
|
681
761
|
}
|
|
682
762
|
/**
|
|
683
763
|
* Extracts background color properties from existing card elements.
|
|
@@ -686,21 +766,21 @@ class Ut extends Z {
|
|
|
686
766
|
* Used when injecting new attribute cells to match the card's current background.
|
|
687
767
|
*/
|
|
688
768
|
_extractSegmentBgFromCard(t) {
|
|
689
|
-
var
|
|
769
|
+
var i;
|
|
690
770
|
const r = t.querySelector(".product-card-segment");
|
|
691
771
|
if (r && "getAttribute" in r) {
|
|
692
|
-
const
|
|
693
|
-
if (
|
|
772
|
+
const s = (r.getAttribute("style") || "").match(/background-color:\s*([^;]+)/);
|
|
773
|
+
if (s) {
|
|
694
774
|
const n = r.getAttribute("bgcolor") || "";
|
|
695
|
-
return { bgStyle: `background-color: ${
|
|
775
|
+
return { bgStyle: `background-color: ${s[1].trim()};`, bgAttr: n };
|
|
696
776
|
}
|
|
697
777
|
}
|
|
698
|
-
const e = (
|
|
778
|
+
const e = (i = this.currentNode) == null ? void 0 : i.querySelector(".product-card-wrapper");
|
|
699
779
|
if (e && "getStyle" in e) {
|
|
700
|
-
const
|
|
701
|
-
if (
|
|
702
|
-
const
|
|
703
|
-
return { bgStyle: `background-color: ${
|
|
780
|
+
const o = e.getStyle("background-color");
|
|
781
|
+
if (o && o !== "transparent") {
|
|
782
|
+
const s = "getAttribute" in e && e.getAttribute("bgcolor") || "";
|
|
783
|
+
return { bgStyle: `background-color: ${o};`, bgAttr: s };
|
|
704
784
|
}
|
|
705
785
|
}
|
|
706
786
|
return { bgStyle: "", bgAttr: "" };
|
|
@@ -710,17 +790,18 @@ class Ut extends Z {
|
|
|
710
790
|
return t ? t.querySelector("[data-card-composition-control]") : null;
|
|
711
791
|
}
|
|
712
792
|
/**
|
|
713
|
-
*
|
|
714
|
-
*
|
|
715
|
-
*
|
|
793
|
+
* Ensures composition reorder is enabled. Both grid and list layouts now
|
|
794
|
+
* support reordering — top-level items and the nested price sub-items are all
|
|
795
|
+
* draggable. (Items render with `draggable="true"`; this just clears any stale
|
|
796
|
+
* disabled state.)
|
|
716
797
|
*/
|
|
717
798
|
_updateOrderableState() {
|
|
718
|
-
const
|
|
719
|
-
if (!
|
|
799
|
+
const t = this._getControlContainer();
|
|
800
|
+
if (!t)
|
|
720
801
|
return;
|
|
721
|
-
const
|
|
722
|
-
|
|
723
|
-
|
|
802
|
+
const r = t.querySelector("[data-composition-list]");
|
|
803
|
+
r && (r.classList.remove("orderable-disabled"), r.querySelectorAll(".orderable-item").forEach((e) => {
|
|
804
|
+
e.setAttribute("draggable", "true");
|
|
724
805
|
}));
|
|
725
806
|
}
|
|
726
807
|
/**
|
|
@@ -728,11 +809,11 @@ class Ut extends Z {
|
|
|
728
809
|
* or when all available filters have already been added (no unused attributes left).
|
|
729
810
|
*/
|
|
730
811
|
_updateAddButtonState() {
|
|
731
|
-
const t = this._readCustomAttributesFromNode(), r = t.length >=
|
|
812
|
+
const t = this._readCustomAttributesFromNode(), r = t.length >= f, e = new Set(t), i = this._getAddableFilters(), o = i.length > 0 && i.every((s) => e.has(s.attributeName));
|
|
732
813
|
this.api.setUIEAttribute(
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
r ||
|
|
814
|
+
K.ADD_ATTRIBUTE,
|
|
815
|
+
E.BUTTON.disabled,
|
|
816
|
+
r || o ? "true" : "false"
|
|
736
817
|
);
|
|
737
818
|
}
|
|
738
819
|
/**
|
|
@@ -745,8 +826,8 @@ class Ut extends Z {
|
|
|
745
826
|
this.unsubscribeStore = this.store.$subscribe(() => {
|
|
746
827
|
const e = this.store.recommendationConfigs.orientation;
|
|
747
828
|
e !== t && (t = e, this._updateOrderableState());
|
|
748
|
-
const
|
|
749
|
-
|
|
829
|
+
const i = Object.keys(this.store.filterList).sort().join(",");
|
|
830
|
+
i !== r && (r = i, this._initializeComposition());
|
|
750
831
|
});
|
|
751
832
|
}
|
|
752
833
|
/**
|
|
@@ -754,7 +835,7 @@ class Ut extends Z {
|
|
|
754
835
|
* excluding default attributes already covered by built-in toggle items.
|
|
755
836
|
*/
|
|
756
837
|
_getAddableFilters() {
|
|
757
|
-
return Object.values(this.store.filterList).filter((t) => !(t.type === "defaultAttribute" &&
|
|
838
|
+
return Object.values(this.store.filterList).filter((t) => !(t.type === "defaultAttribute" && nt.has(t.attributeName)));
|
|
758
839
|
}
|
|
759
840
|
/**
|
|
760
841
|
* Looks up the display name for an attribute from the store's filterList.
|
|
@@ -762,7 +843,7 @@ class Ut extends Z {
|
|
|
762
843
|
*/
|
|
763
844
|
_getDisplayNameForAttribute(t) {
|
|
764
845
|
const r = Object.values(this.store.filterList).find((e) => e.attributeName === t);
|
|
765
|
-
return r ? r.displayName :
|
|
846
|
+
return r ? r.displayName : pt(t);
|
|
766
847
|
}
|
|
767
848
|
/**
|
|
768
849
|
* Resolves the display content for a custom attribute cell.
|
|
@@ -770,29 +851,29 @@ class Ut extends Z {
|
|
|
770
851
|
*/
|
|
771
852
|
_resolveAttributeContent(t, r, e) {
|
|
772
853
|
var n;
|
|
773
|
-
const
|
|
774
|
-
return
|
|
854
|
+
const o = this.store.recommendationProducts[e], s = gt(t, this.store.filterList) ? o == null ? void 0 : o[t] : (n = o == null ? void 0 : o.product_attributes) == null ? void 0 : n[t];
|
|
855
|
+
return bt(s) ?? r;
|
|
775
856
|
}
|
|
776
|
-
_getGridCellHtml(t, r, e,
|
|
777
|
-
const n = `${
|
|
857
|
+
_getGridCellHtml(t, r, e, i = "", o = "", s = "") {
|
|
858
|
+
const n = `${p}${t}`, c = V(ct, [n], this.store.filterList), l = {
|
|
778
859
|
[t]: r,
|
|
779
860
|
product_attributes: { [t]: r }
|
|
780
861
|
};
|
|
781
|
-
let
|
|
782
|
-
return
|
|
783
|
-
`padding: ${
|
|
784
|
-
`padding: ${
|
|
785
|
-
)),
|
|
862
|
+
let a = c[n](l);
|
|
863
|
+
return a = a.replace("<td", `<td width="${e}%"`), s && (a = a.replace(
|
|
864
|
+
`padding: ${dt}`,
|
|
865
|
+
`padding: ${s}`
|
|
866
|
+
)), i && (a = a.replace(/style="table-layout: fixed;"/, `style="table-layout: fixed; ${i}"`)), o && (a = a.replace(/border="0"/, `border="0" bgcolor="${o}"`)), a;
|
|
786
867
|
}
|
|
787
868
|
_getListRowHtml(t, r, e) {
|
|
788
|
-
const
|
|
869
|
+
const i = V(mt, [e], this.store.filterList), o = {
|
|
789
870
|
[t]: r,
|
|
790
871
|
product_attributes: { [t]: r }
|
|
791
|
-
}, n =
|
|
792
|
-
return `<tr class="recommendation-attribute-row" ${y}="${e}" ${
|
|
872
|
+
}, n = i[e](o).replace(/<tr>/, "").replace(/<\/tr>/, "");
|
|
873
|
+
return `<tr class="recommendation-attribute-row" ${y}="${e}" ${O}="1">${n}</tr>`;
|
|
793
874
|
}
|
|
794
875
|
}
|
|
795
876
|
export {
|
|
796
|
-
|
|
877
|
+
St as COMPOSITION_CONTROL_BLOCK_ID,
|
|
797
878
|
Ut as RecommendationCardCompositionControl
|
|
798
879
|
};
|