@useinsider/guido 3.23.0-beta.31d0f5f → 3.23.0-beta.9f6bfbf
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/README.md +1 -0
- package/dist/@types/config/schemas.js +17 -15
- package/dist/components/Guido.vue.js +1 -1
- package/dist/components/Guido.vue2.js +58 -56
- package/dist/composables/useModuleRepair.js +14 -12
- package/dist/config/migrator/index.js +16 -15
- package/dist/config/migrator/itemsPriceFormatMigrator.js +20 -0
- package/dist/extensions/Blocks/Items/block.js +115 -77
- package/dist/extensions/Blocks/Items/constants/currency.js +59 -14
- package/dist/extensions/Blocks/Items/controls/price/currencyLocation.js +33 -22
- package/dist/extensions/Blocks/Items/controls/price/currencySymbol.js +62 -51
- package/dist/extensions/Blocks/Items/controls/price/formattedPrice.js +18 -17
- package/dist/extensions/Blocks/Items/controls/price/singlePrice.js +42 -31
- package/dist/extensions/Blocks/Items/controls/priceFormat.js +145 -0
- package/dist/extensions/Blocks/Items/controls/settingsControl.js +141 -120
- package/dist/extensions/Blocks/Items/enums/controlEnums.js +1 -1
- package/dist/extensions/Blocks/Items/extension.js +9 -8
- package/dist/extensions/Blocks/Items/items.css.js +19 -0
- package/dist/extensions/Blocks/Items/settingsPanel.js +34 -25
- package/dist/extensions/Blocks/Items/template.js +250 -212
- package/dist/extensions/Blocks/Items/utils/priceFormatOps.js +185 -0
- package/dist/extensions/Blocks/Recommendation/utils/priceFormatter.js +1 -0
- package/dist/guido.css +1 -1
- package/dist/package.json.js +1 -1
- package/dist/src/@types/config/schemas.d.ts +4 -0
- package/dist/src/composables/useConfig.d.ts +2 -0
- package/dist/src/config/migrator/index.d.ts +4 -1
- package/dist/src/config/migrator/itemsPriceFormatMigrator.d.ts +1 -0
- package/dist/src/extensions/Blocks/Items/block.d.ts +6 -9
- package/dist/src/extensions/Blocks/Items/constants/currency.d.ts +32 -0
- package/dist/src/extensions/Blocks/Items/controls/priceFormat.d.ts +23 -0
- package/dist/src/extensions/Blocks/Items/controls/settingsControl.d.ts +1 -0
- package/dist/src/extensions/Blocks/Items/enums/controlEnums.d.ts +1 -0
- package/dist/src/extensions/Blocks/Items/template.d.ts +4 -1
- package/dist/src/extensions/Blocks/Items/utils/nodeConfigUtils.d.ts +3 -0
- package/dist/src/extensions/Blocks/Items/utils/priceFormatOps.d.ts +61 -0
- package/dist/src/extensions/Blocks/Recommendation/utils/priceFormatter.d.ts +12 -0
- package/dist/src/stores/config.d.ts +20 -0
- package/dist/src/utils/itemsCurrencyRepair.d.ts +5 -1
- package/dist/utils/itemsCurrencyRepair.js +29 -24
- package/dist/utils/pairProductVariables.js +119 -99
- package/package.json +1 -1
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { formatNumber as w } from "../../Recommendation/utils/priceFormatter.js";
|
|
2
|
+
import { escapeHtml as q } from "../../../../utils/htmlEscape.js";
|
|
3
|
+
import { extractWrapperTags as B } from "../../../../utils/preserveTextStyles.js";
|
|
4
|
+
import { ITEMS_PRICE_FORMAT_ATTR as c, priceFormatFromConfig as _, normalizeDecimalCount as V, LEGACY_PRICE_PARAGRAPH_ATTRS as O, ITEMS_CURRENCY_ATTR as b } from "../constants/currency.js";
|
|
5
|
+
import { productPairs as W } from "../enums/productEnums.js";
|
|
6
|
+
import { DefaultConfigValues as I } from "../enums/settingsEnums.js";
|
|
7
|
+
import { escapeReplacement as z } from "./nodeConfigUtils.js";
|
|
8
|
+
const J = 'p[product-attr="price"], p[product-attr="originalPrice"]', K = [
|
|
9
|
+
...Object.values(c),
|
|
10
|
+
"data-type"
|
|
11
|
+
], L = "CART_ITEMS";
|
|
12
|
+
function X() {
|
|
13
|
+
return { rootSet: {}, paragraphRemove: [], configPatch: null, texts: null, changed: !1 };
|
|
14
|
+
}
|
|
15
|
+
function h(t) {
|
|
16
|
+
return t != null;
|
|
17
|
+
}
|
|
18
|
+
function Pt(t) {
|
|
19
|
+
return t === "price" || t === "originalPrice" ? t : null;
|
|
20
|
+
}
|
|
21
|
+
function N(t) {
|
|
22
|
+
const n = W.PAIRS_FOR_EXTENSION, r = t != null && t.type && t.type in n.price ? t.type : L, o = (t == null ? void 0 : t.priceSinglePrice) === !0, e = n.price[r], i = n.originalPrice[r];
|
|
23
|
+
return {
|
|
24
|
+
price: o ? e.DEFAULT_SINGLE_PRICE : e.DEFAULT_PRICE,
|
|
25
|
+
originalPrice: o ? i.DEFAULT_SINGLE_PRICE : i.DEFAULT_PRICE
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function P({ amount: t, format: n, symbol: r, alignment: o }) {
|
|
29
|
+
const e = w(Number(t), n), i = q((r ?? "").trim());
|
|
30
|
+
return i ? o === "1" ? `${e} ${i}` : `${i} ${e}` : e;
|
|
31
|
+
}
|
|
32
|
+
function Tt(t) {
|
|
33
|
+
const n = N(t), r = {
|
|
34
|
+
format: _(t),
|
|
35
|
+
symbol: (t == null ? void 0 : t.priceCurrencySymbol) ?? I.productPriceCurrencySymbolControlValue,
|
|
36
|
+
alignment: (t == null ? void 0 : t.priceCurrencyLocation) ?? "0"
|
|
37
|
+
};
|
|
38
|
+
return {
|
|
39
|
+
price: P({ amount: n.price, ...r }),
|
|
40
|
+
originalPrice: P({ amount: n.originalPrice, ...r })
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const x = / |\u00a0|\s+/g, Q = "(?: | |\\s)+", Z = /&(amp|lt|gt|quot|#x27|#39);/g, tt = { amp: "&", lt: "<", gt: ">", quot: '"', "#x27": "'", "#39": "'" }, rt = {
|
|
44
|
+
"&": "(?:&|&)",
|
|
45
|
+
"<": "(?:<|<)",
|
|
46
|
+
">": "(?:>|>)",
|
|
47
|
+
'"': '(?:"|")',
|
|
48
|
+
"'": "(?:'|'|')"
|
|
49
|
+
}, et = (t) => t.replace(Z, (n, r) => tt[r]), nt = (t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
50
|
+
function ot(t) {
|
|
51
|
+
return Array.from(t, (n) => rt[n] ?? nt(n)).join("");
|
|
52
|
+
}
|
|
53
|
+
function D(t, n) {
|
|
54
|
+
const r = (o) => o.replace(x, " ").trim();
|
|
55
|
+
return r(t ?? "") === r(et(n ?? ""));
|
|
56
|
+
}
|
|
57
|
+
function it(t, n, r) {
|
|
58
|
+
const o = t.trim(), e = n.trim().split(x).filter(Boolean), i = e.length ? new RegExp(e.map(ot).join(Q)) : null;
|
|
59
|
+
if (i != null && i.test(o))
|
|
60
|
+
return o.replace(i, z(r));
|
|
61
|
+
const { openTags: s, closeTags: u } = B(o);
|
|
62
|
+
return `${s}${r}${u}`;
|
|
63
|
+
}
|
|
64
|
+
function ct(t, n) {
|
|
65
|
+
if (!t)
|
|
66
|
+
return null;
|
|
67
|
+
const r = Object.fromEntries(
|
|
68
|
+
Object.entries(n).filter(([o, e]) => t[o] !== e)
|
|
69
|
+
);
|
|
70
|
+
return Object.keys(r).length > 0 ? r : null;
|
|
71
|
+
}
|
|
72
|
+
function Ct(t, { convertLegacy: n }) {
|
|
73
|
+
const { rootAttrs: r, paragraphs: o, config: e } = t, i = h(r[c.DECIMAL_COUNT]);
|
|
74
|
+
if (!i && !n)
|
|
75
|
+
return X();
|
|
76
|
+
const s = o.find((a) => a.kind === "price") ?? o[0], u = (a) => (s == null ? void 0 : s.attrs[a]) ?? null, l = i ? r[c.SINGLE_PRICE] : u("data-single_price"), m = typeof (e == null ? void 0 : e.priceSinglePrice) == "boolean" ? e.priceSinglePrice : l === "true", A = e == null ? void 0 : e.priceCurrencyLocation, j = u(b.POSITION) === "after" ? "1" : "0", H = i ? r[c.ALIGNMENT] : j, E = (typeof A == "string" && A.trim() !== "" ? A : H) === "1" ? "1" : "0", U = i ? r[c.SYMBOL] : u(b.SYMBOL), S = typeof (e == null ? void 0 : e.priceCurrencySymbol) == "string" ? e.priceCurrencySymbol : U ?? I.productPriceCurrencySymbolControlValue, p = _({
|
|
77
|
+
priceThousandSeparator: (e == null ? void 0 : e.priceThousandSeparator) ?? (i ? r[c.THOUSAND_SEPARATOR] ?? void 0 : void 0),
|
|
78
|
+
priceDecimalSeparator: (e == null ? void 0 : e.priceDecimalSeparator) ?? (i ? r[c.DECIMAL_SEPARATOR] ?? void 0 : void 0),
|
|
79
|
+
priceDecimalCount: (e == null ? void 0 : e.priceDecimalCount) ?? (i ? V(r[c.DECIMAL_COUNT]) : void 0)
|
|
80
|
+
}), G = {
|
|
81
|
+
[c.SYMBOL]: S.trim(),
|
|
82
|
+
[c.ALIGNMENT]: E,
|
|
83
|
+
[c.THOUSAND_SEPARATOR]: p.thousandSeparator,
|
|
84
|
+
[c.DECIMAL_SEPARATOR]: p.decimalSeparator,
|
|
85
|
+
[c.DECIMAL_COUNT]: String(p.decimalCount),
|
|
86
|
+
[c.SINGLE_PRICE]: m ? "true" : "false"
|
|
87
|
+
}, T = Object.fromEntries(
|
|
88
|
+
Object.entries(G).filter(([a, d]) => r[a] !== d)
|
|
89
|
+
), C = O.filter(
|
|
90
|
+
(a) => o.some((d) => h(d.attrs[a]))
|
|
91
|
+
), $ = {
|
|
92
|
+
priceThousandSeparator: p.thousandSeparator,
|
|
93
|
+
priceDecimalSeparator: p.decimalSeparator,
|
|
94
|
+
priceDecimalCount: p.decimalCount,
|
|
95
|
+
priceSinglePrice: m,
|
|
96
|
+
priceCurrencyLocation: E,
|
|
97
|
+
priceCurrencySymbol: S
|
|
98
|
+
}, f = ct(e, $), k = (e == null ? void 0 : e.type) ?? r["data-type"] ?? L, R = N({ type: k, priceSinglePrice: m }), y = (a) => P({ amount: a, format: p, symbol: S, alignment: E }), g = { price: y(R.price), originalPrice: y(R.originalPrice) }, Y = o.some((a) => !D(a.text, g[a.kind]));
|
|
99
|
+
return {
|
|
100
|
+
rootSet: T,
|
|
101
|
+
paragraphRemove: C,
|
|
102
|
+
configPatch: f,
|
|
103
|
+
texts: g,
|
|
104
|
+
changed: Object.keys(T).length > 0 || C.length > 0 || f !== null || Y
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function at(t) {
|
|
108
|
+
const n = {};
|
|
109
|
+
return K.forEach((r) => {
|
|
110
|
+
n[r] = t.rootAttr(r) ?? null;
|
|
111
|
+
}), {
|
|
112
|
+
rootAttrs: n,
|
|
113
|
+
config: t.config,
|
|
114
|
+
paragraphs: t.paragraphs.map((r) => {
|
|
115
|
+
const o = {};
|
|
116
|
+
return O.forEach((e) => {
|
|
117
|
+
o[e] = r.attr(e) ?? null;
|
|
118
|
+
}), { kind: r.kind, attrs: o, text: r.text.trim() };
|
|
119
|
+
})
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function M(t) {
|
|
123
|
+
const n = t.getAttribute("esd-ext-config");
|
|
124
|
+
if (!n)
|
|
125
|
+
return null;
|
|
126
|
+
try {
|
|
127
|
+
const r = JSON.parse(n);
|
|
128
|
+
return r && typeof r == "object" ? r : null;
|
|
129
|
+
} catch {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function F(t) {
|
|
134
|
+
return Array.from(t.querySelectorAll(J)).map((n) => ({
|
|
135
|
+
kind: n.getAttribute("product-attr"),
|
|
136
|
+
element: n
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
139
|
+
function v(t) {
|
|
140
|
+
return t.textContent;
|
|
141
|
+
}
|
|
142
|
+
function ft(t) {
|
|
143
|
+
return at({
|
|
144
|
+
rootAttr: (n) => t.getAttribute(n),
|
|
145
|
+
config: M(t),
|
|
146
|
+
paragraphs: F(t).map(({ kind: n, element: r }) => ({
|
|
147
|
+
kind: n,
|
|
148
|
+
attr: (o) => r.getAttribute(o),
|
|
149
|
+
text: v(r)
|
|
150
|
+
}))
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
function Rt(t, n) {
|
|
154
|
+
if (!n.changed)
|
|
155
|
+
return !1;
|
|
156
|
+
let r = !1;
|
|
157
|
+
if (Object.entries(n.rootSet).forEach(([o, e]) => {
|
|
158
|
+
t.getAttribute(o) !== e && (t.setAttribute(o, e), r = !0);
|
|
159
|
+
}), F(t).forEach(({ kind: o, element: e }) => {
|
|
160
|
+
var u;
|
|
161
|
+
n.paragraphRemove.forEach((l) => {
|
|
162
|
+
e.hasAttribute(l) && (e.removeAttribute(l), r = !0);
|
|
163
|
+
});
|
|
164
|
+
const i = (u = n.texts) == null ? void 0 : u[o], s = v(e).trim();
|
|
165
|
+
i !== void 0 && !D(s, i) && (e.innerHTML = it(e.innerHTML, s, i), r = !0);
|
|
166
|
+
}), n.configPatch) {
|
|
167
|
+
const o = M(t);
|
|
168
|
+
o && (t.setAttribute("esd-ext-config", JSON.stringify({ ...o, ...n.configPatch })), r = !0);
|
|
169
|
+
}
|
|
170
|
+
return r;
|
|
171
|
+
}
|
|
172
|
+
export {
|
|
173
|
+
J as PRICE_PARAGRAPH_SELECTOR,
|
|
174
|
+
Rt as applyPriceFormatOpsToElement,
|
|
175
|
+
at as buildPriceFormatSnapshot,
|
|
176
|
+
P as formatItemsDummyPrice,
|
|
177
|
+
Pt as paragraphKindOf,
|
|
178
|
+
Ct as planPriceFormatOps,
|
|
179
|
+
Tt as priceTextsFromConfig,
|
|
180
|
+
M as readPersistedConfigAttribute,
|
|
181
|
+
it as replacePriceText,
|
|
182
|
+
N as resolvePriceDummyAmounts,
|
|
183
|
+
D as samePriceText,
|
|
184
|
+
ft as snapshotPriceFormatFromElement
|
|
185
|
+
};
|
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-
|
|
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-49dc1b30]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-49dc1b30]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-49dc1b30]{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/package.json.js
CHANGED
|
@@ -414,6 +414,8 @@ export declare const FeaturesSchema: v.ObjectSchema<{
|
|
|
414
414
|
/** Allow persisting a template that still has validation errors (drawer "Save and Continue" soft-save). Host sets false for transactional + unsubscribe. */
|
|
415
415
|
readonly allowSaveWithErrors: v.OptionalSchema<v.BooleanSchema<undefined>, true>;
|
|
416
416
|
readonly reusableRecommendationStrategy: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
|
|
417
|
+
/** Items block: Recommendation-style price formatting (root currency-* attrs, raw price tags). Released dark. */
|
|
418
|
+
readonly itemsPriceFormatting: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
|
|
417
419
|
}, undefined>;
|
|
418
420
|
/**
|
|
419
421
|
* Default block types available in Stripo
|
|
@@ -832,6 +834,8 @@ export declare const GuidoConfigSchema: v.ObjectSchema<{
|
|
|
832
834
|
/** Allow persisting a template that still has validation errors (drawer "Save and Continue" soft-save). Host sets false for transactional + unsubscribe. */
|
|
833
835
|
readonly allowSaveWithErrors: v.OptionalSchema<v.BooleanSchema<undefined>, true>;
|
|
834
836
|
readonly reusableRecommendationStrategy: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
|
|
837
|
+
/** Items block: Recommendation-style price formatting (root currency-* attrs, raw price tags). Released dark. */
|
|
838
|
+
readonly itemsPriceFormatting: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
|
|
835
839
|
}, undefined>, {}>;
|
|
836
840
|
/** Block configuration */
|
|
837
841
|
readonly blocks: v.OptionalSchema<v.ObjectSchema<{
|
|
@@ -104,6 +104,7 @@ export declare const useConfig: () => {
|
|
|
104
104
|
linkTrackingIds: boolean;
|
|
105
105
|
allowSaveWithErrors: boolean;
|
|
106
106
|
reusableRecommendationStrategy: boolean;
|
|
107
|
+
itemsPriceFormatting: boolean;
|
|
107
108
|
};
|
|
108
109
|
blocks: {
|
|
109
110
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -243,6 +244,7 @@ export declare const useConfig: () => {
|
|
|
243
244
|
linkTrackingIds: boolean;
|
|
244
245
|
allowSaveWithErrors: boolean;
|
|
245
246
|
reusableRecommendationStrategy: boolean;
|
|
247
|
+
itemsPriceFormatting: boolean;
|
|
246
248
|
} | null>;
|
|
247
249
|
blocks: import("vue").ComputedRef<{
|
|
248
250
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
import type { LegacyRecommendationConfig } from '@@/Types/config';
|
|
2
2
|
import { type PartnerScopeMigrationOptions } from './recommendationPartnerMigrator';
|
|
3
|
-
export
|
|
3
|
+
export interface MigrationFeatureFlags {
|
|
4
|
+
itemsPriceFormatting?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare const migrate: (html: string, recommendationConfigs?: Record<string, LegacyRecommendationConfig>, partnerScope?: PartnerScopeMigrationOptions, features?: MigrationFeatureFlags) => Promise<string>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function migrateItemsPriceFormat(html: string): string;
|
|
@@ -71,15 +71,12 @@ export declare class ItemsBlock extends Block {
|
|
|
71
71
|
*/
|
|
72
72
|
private _resolveInstanceId;
|
|
73
73
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* Config is the source of truth — never derive from visible text.
|
|
77
|
-
*
|
|
78
|
-
* Authority split lives in `currencyAttrTargets` (SD-147588) — position only when a location
|
|
79
|
-
* is recorded, symbol only when customized — so this heal and the module-drop repair can't drift.
|
|
80
|
-
*
|
|
81
|
-
* Returns true only when an attr actually changed, so the caller can skip an empty apply that
|
|
82
|
-
* would otherwise re-trigger onDocumentChanged and loop.
|
|
74
|
+
* Single self-heal slot: the flag only decides whether a legacy root is converted; a root
|
|
75
|
+
* already in the new format is reconciled from config regardless. Returns whether anything was queued.
|
|
83
76
|
*/
|
|
84
77
|
private _reconcileCurrencyDomAttributes;
|
|
78
|
+
/** Legacy `<p>` contract via `currencyAttrTargets`: position when recorded, symbol only when custom. */
|
|
79
|
+
private _reconcileLegacyCurrencyAttributes;
|
|
80
|
+
private _priceParagraphs;
|
|
81
|
+
private _isPriceFormattingEnabled;
|
|
85
82
|
}
|
|
@@ -41,3 +41,35 @@ export declare function currencyAttrTargets(config: {
|
|
|
41
41
|
priceCurrencyLocation?: string;
|
|
42
42
|
priceCurrencySymbol?: string;
|
|
43
43
|
}): CurrencyAttrTargets;
|
|
44
|
+
export declare const ITEMS_PRICE_FORMAT_ATTR: {
|
|
45
|
+
readonly SYMBOL: "currency-symbol";
|
|
46
|
+
readonly ALIGNMENT: "currency-alignment";
|
|
47
|
+
readonly THOUSAND_SEPARATOR: "currency-thousand-separator";
|
|
48
|
+
readonly DECIMAL_SEPARATOR: "currency-decimal-separator";
|
|
49
|
+
readonly DECIMAL_COUNT: "currency-decimal-count";
|
|
50
|
+
readonly SINGLE_PRICE: "data-single_price";
|
|
51
|
+
};
|
|
52
|
+
/** Price `<p>` attrs of the legacy model; a new-format block carries none of them. */
|
|
53
|
+
export declare const LEGACY_PRICE_PARAGRAPH_ATTRS: readonly ["data-formated", "data-single_price", "data-curency", "data-currency_symbol"];
|
|
54
|
+
export declare const PRICE_FORMAT_CONFIG_KEYS: readonly ["priceThousandSeparator", "priceDecimalSeparator", "priceDecimalCount"];
|
|
55
|
+
export interface ItemsPriceFormat {
|
|
56
|
+
thousandSeparator: string;
|
|
57
|
+
decimalSeparator: string;
|
|
58
|
+
decimalCount: number;
|
|
59
|
+
}
|
|
60
|
+
/** en-US, the shape the legacy pre-formatted price tags produced. */
|
|
61
|
+
export declare const DEFAULT_ITEMS_PRICE_FORMAT: ItemsPriceFormat;
|
|
62
|
+
export interface PriceFormatConfigSlice {
|
|
63
|
+
priceThousandSeparator?: string;
|
|
64
|
+
priceDecimalSeparator?: string;
|
|
65
|
+
priceDecimalCount?: number;
|
|
66
|
+
}
|
|
67
|
+
export declare function normalizeDecimalCount(value: unknown): number;
|
|
68
|
+
/** Config → format, defaulting each missing key independently. */
|
|
69
|
+
export declare function priceFormatFromConfig(config: PriceFormatConfigSlice | null | undefined): ItemsPriceFormat;
|
|
70
|
+
export declare function isNewPriceFormatConfig(config: PriceFormatConfigSlice | null | undefined): boolean;
|
|
71
|
+
export interface AttributeReader {
|
|
72
|
+
getAttribute(name: string): string | null | undefined;
|
|
73
|
+
}
|
|
74
|
+
/** The export/control switch: a root carrying `currency-decimal-count` is in the new format. */
|
|
75
|
+
export declare function isNewPriceFormatRoot(root: AttributeReader | null | undefined): boolean;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ControlApi, ImmutableHtmlNode } from '@stripoinc/ui-editor-extensions';
|
|
2
|
+
import { CommonControl } from '../../common-control';
|
|
3
|
+
import { ItemsBlockControlId } from '../enums/controlEnums';
|
|
4
|
+
import { type ItemsBlockConfig } from '../utils/nodeConfigUtils';
|
|
5
|
+
export declare const CONTROL_BLOCK_ID = ItemsBlockControlId.PRICE_FORMAT;
|
|
6
|
+
export declare function isNewPriceFormatBlock(currentNode: ImmutableHtmlNode | undefined): boolean;
|
|
7
|
+
/** One apply: the config patch, the root attrs the export reads, and both price texts re-rendered. */
|
|
8
|
+
export declare function applyPriceFormatChange(currentNode: ImmutableHtmlNode | undefined, api: ControlApi, patch: Partial<ItemsBlockConfig>, description: string): void;
|
|
9
|
+
export declare class ItemsBlockPriceFormatControl extends CommonControl {
|
|
10
|
+
private lastWritten;
|
|
11
|
+
getId(): string;
|
|
12
|
+
getTemplate(): string;
|
|
13
|
+
onRender(): void;
|
|
14
|
+
onTemplateNodeUpdated(node: ImmutableHtmlNode): void;
|
|
15
|
+
onDestroy(): void;
|
|
16
|
+
_onThousandSeparatorChange(value: string): void;
|
|
17
|
+
_onDecimalSeparatorChange(value: string): void;
|
|
18
|
+
_onDecimalCountChange(value: string): void;
|
|
19
|
+
private _currentFormat;
|
|
20
|
+
private _write;
|
|
21
|
+
private _formValues;
|
|
22
|
+
private _getSelectRow;
|
|
23
|
+
}
|
|
@@ -35,6 +35,7 @@ export declare class ItemsBlockControl extends CommonControl {
|
|
|
35
35
|
_reFillTemplate(itemsType?: ProductType): void;
|
|
36
36
|
_recalculateTrimming(): void;
|
|
37
37
|
private _getParagraphFromBlock;
|
|
38
|
+
private _replacePriceText;
|
|
38
39
|
private _escapeRegex;
|
|
39
40
|
private _removeCurrencySymbol;
|
|
40
41
|
private _replacePriceNumber;
|
|
@@ -46,6 +46,7 @@ export declare enum ItemsBlockControlId {
|
|
|
46
46
|
PRICE_CURRENCY_SYMBOL = "items-block-price-currency-symbol-control",
|
|
47
47
|
PRICE_CURRENCY_LOCATION = "items-block-price-currency-location-control",
|
|
48
48
|
PRICE_ORIENTATION = "items-block-price-orientation-control",
|
|
49
|
+
PRICE_FORMAT = "items-block-price-format-control",
|
|
49
50
|
NAME_ALIGN = "items-block-name-align-control",
|
|
50
51
|
NAME_COLOR = "items-block-name-color-control",
|
|
51
52
|
NAME_SIZE = "items-block-name-size-control",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ItemsPriceFormat } from './constants/currency';
|
|
1
2
|
import { type ItemsBlockConfig } from './utils/nodeConfigUtils';
|
|
2
3
|
declare const migrationTemplate = "ADD YOUR MIGRATION HERE";
|
|
3
4
|
type ProductType = 'CART_ITEMS' | 'BROWSED_ITEMS' | 'PURCHASED_ITEMS';
|
|
@@ -36,6 +37,8 @@ type TemplateParameters = {
|
|
|
36
37
|
quantityStyles?: string;
|
|
37
38
|
/** Price orientation within the card ('vertical' = stacked, 'horizontal' = side-by-side) */
|
|
38
39
|
priceOrientation?: PriceOrientationType;
|
|
40
|
+
/** New price model (itemsPriceFormatting): root attrs + raw dummy amounts; absent = legacy output. */
|
|
41
|
+
priceFormat?: ItemsPriceFormat;
|
|
39
42
|
};
|
|
40
43
|
/**
|
|
41
44
|
* Applies price orientation styles to the generated HTML template.
|
|
@@ -67,5 +70,5 @@ export declare const applyPriceOrientationStyles: (html: string, layoutOrientati
|
|
|
67
70
|
* @param params.formattedPrice - Whether to use formatted price display
|
|
68
71
|
* @returns HTML template string for the Items Block
|
|
69
72
|
*/
|
|
70
|
-
export declare function getDefaultTemplate({ orientation, itemsType, itemId, currencySymbol, currencyLocation, migrate, formattedPrice, configBlockAttributes, nodeConfig, nameStyles, buttonStyles, priceStyles, originalPriceStyles, quantityStyles, priceOrientation, }: TemplateParameters): string;
|
|
73
|
+
export declare function getDefaultTemplate({ orientation, itemsType, itemId, currencySymbol, currencyLocation, migrate, formattedPrice, configBlockAttributes, nodeConfig, nameStyles, buttonStyles, priceStyles, originalPriceStyles, quantityStyles, priceOrientation, priceFormat, }: TemplateParameters): string;
|
|
71
74
|
export default migrationTemplate;
|
|
@@ -18,6 +18,9 @@ export interface ItemsBlockConfig {
|
|
|
18
18
|
priceCurrencySymbol: string;
|
|
19
19
|
priceCurrencyLocation: string;
|
|
20
20
|
priceOrientation: 'vertical' | 'horizontal';
|
|
21
|
+
priceThousandSeparator?: string;
|
|
22
|
+
priceDecimalSeparator?: string;
|
|
23
|
+
priceDecimalCount?: number;
|
|
21
24
|
quantityControlEnabled: boolean;
|
|
22
25
|
buttonLink: string;
|
|
23
26
|
imageLink: string;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type ItemsPriceFormat } from '../constants/currency';
|
|
2
|
+
import { type ItemsBlockConfig } from './nodeConfigUtils';
|
|
3
|
+
export type PriceParagraphKind = 'price' | 'originalPrice';
|
|
4
|
+
export declare const PRICE_PARAGRAPH_SELECTOR = "p[product-attr=\"price\"], p[product-attr=\"originalPrice\"]";
|
|
5
|
+
type AttrMap = Record<string, string | null | undefined>;
|
|
6
|
+
export interface PriceParagraphSnapshot {
|
|
7
|
+
kind: PriceParagraphKind;
|
|
8
|
+
attrs: AttrMap;
|
|
9
|
+
text: string;
|
|
10
|
+
}
|
|
11
|
+
export interface PriceFormatSnapshot {
|
|
12
|
+
rootAttrs: AttrMap;
|
|
13
|
+
paragraphs: PriceParagraphSnapshot[];
|
|
14
|
+
config: Partial<ItemsBlockConfig> | null;
|
|
15
|
+
}
|
|
16
|
+
export interface PriceTexts {
|
|
17
|
+
price: string;
|
|
18
|
+
originalPrice: string;
|
|
19
|
+
}
|
|
20
|
+
export interface PriceFormatOps {
|
|
21
|
+
rootSet: Record<string, string>;
|
|
22
|
+
paragraphRemove: string[];
|
|
23
|
+
configPatch: Partial<ItemsBlockConfig> | null;
|
|
24
|
+
texts: PriceTexts | null;
|
|
25
|
+
changed: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface PlanPriceFormatOptions {
|
|
28
|
+
convertLegacy: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface FormatDummyPriceInput {
|
|
31
|
+
amount: string | number;
|
|
32
|
+
format: ItemsPriceFormat;
|
|
33
|
+
symbol: string | null | undefined;
|
|
34
|
+
alignment: string | null | undefined;
|
|
35
|
+
}
|
|
36
|
+
export declare function paragraphKindOf(productAttr: string | null | undefined): PriceParagraphKind | null;
|
|
37
|
+
export declare function resolvePriceDummyAmounts(config: Pick<Partial<ItemsBlockConfig>, 'type' | 'priceSinglePrice'> | null | undefined): PriceTexts;
|
|
38
|
+
export declare function formatItemsDummyPrice({ amount, format, symbol, alignment }: FormatDummyPriceInput): string;
|
|
39
|
+
export declare function priceTextsFromConfig(config: Partial<ItemsBlockConfig> | null | undefined): PriceTexts;
|
|
40
|
+
/** `text` is decoded DOM text, `html` the rendered markup text (entities allowed). */
|
|
41
|
+
export declare function samePriceText(text: string | null | undefined, html: string | null | undefined): boolean;
|
|
42
|
+
/** Swaps the whole price text inside the paragraph markup, keeping the style wrappers around it. */
|
|
43
|
+
export declare function replacePriceText(innerHtml: string, currentText: string, newText: string): string;
|
|
44
|
+
export declare function planPriceFormatOps(snapshot: PriceFormatSnapshot, { convertLegacy }: PlanPriceFormatOptions): PriceFormatOps;
|
|
45
|
+
export interface PriceParagraphSource {
|
|
46
|
+
kind: PriceParagraphKind;
|
|
47
|
+
attr(name: string): string | null | undefined;
|
|
48
|
+
text: string;
|
|
49
|
+
}
|
|
50
|
+
export interface PriceFormatSnapshotSource {
|
|
51
|
+
rootAttr(name: string): string | null | undefined;
|
|
52
|
+
paragraphs: PriceParagraphSource[];
|
|
53
|
+
config: Partial<ItemsBlockConfig> | null;
|
|
54
|
+
}
|
|
55
|
+
/** Shared snapshot builder so DOM (migrator, repair) and Stripo-node callers read the same attrs. */
|
|
56
|
+
export declare function buildPriceFormatSnapshot(source: PriceFormatSnapshotSource): PriceFormatSnapshot;
|
|
57
|
+
export declare function readPersistedConfigAttribute(root: Element): Partial<ItemsBlockConfig> | null;
|
|
58
|
+
export declare function snapshotPriceFormatFromElement(root: Element): PriceFormatSnapshot;
|
|
59
|
+
/** DOM applier for parsed HTML (migrator, module repair). Returns whether anything was written. */
|
|
60
|
+
export declare function applyPriceFormatOpsToElement(root: Element, ops: PriceFormatOps): boolean;
|
|
61
|
+
export {};
|
|
@@ -14,6 +14,18 @@ export interface FormatPriceOptions {
|
|
|
14
14
|
/** Currency configuration */
|
|
15
15
|
currency: CurrencyConfig;
|
|
16
16
|
}
|
|
17
|
+
export interface FormatNumberOptions {
|
|
18
|
+
thousandSeparator: string;
|
|
19
|
+
decimalSeparator: string;
|
|
20
|
+
decimalCount: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Formats a number with custom thousand and decimal separators
|
|
24
|
+
* @param value - The numeric value to format
|
|
25
|
+
* @param options - Formatting options
|
|
26
|
+
* @returns Formatted number string
|
|
27
|
+
*/
|
|
28
|
+
export declare function formatNumber(value: number, options: FormatNumberOptions): string;
|
|
17
29
|
/**
|
|
18
30
|
* Formats a numeric price according to currency settings
|
|
19
31
|
* @example
|