@nosto/nosto-react 2.4.0 → 2.5.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.
- package/README.md +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.es.js +211 -207
- package/dist/index.umd.js +1 -1
- package/package.json +2 -2
- package/src/components/NostoProvider.tsx +2 -2
- package/src/hooks/useLoadClientScript.ts +2 -40
package/README.md
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -324,8 +324,8 @@ export declare interface NostoProviderProps {
|
|
|
324
324
|
* Enables Shopify markets with language and market id
|
|
325
325
|
*/
|
|
326
326
|
shopifyMarkets?: {
|
|
327
|
-
language
|
|
328
|
-
marketId
|
|
327
|
+
language: string;
|
|
328
|
+
marketId: string | number;
|
|
329
329
|
};
|
|
330
330
|
/**
|
|
331
331
|
* Load nosto script (should be false if loading the script outside of nosto-react)
|
package/dist/index.es.js
CHANGED
|
@@ -1,335 +1,339 @@
|
|
|
1
|
-
import { createContext as
|
|
2
|
-
import { jsx as
|
|
1
|
+
import { createContext as k, useContext as x, useEffect as S, useRef as h, useMemo as I, cloneElement as _, useState as T, isValidElement as D } from "react";
|
|
2
|
+
import { jsx as v } from "react/jsx-runtime";
|
|
3
3
|
import { createRoot as M } from "react-dom/client";
|
|
4
|
-
const
|
|
4
|
+
const O = k({
|
|
5
5
|
account: "",
|
|
6
6
|
currentVariation: "",
|
|
7
7
|
responseMode: "HTML",
|
|
8
8
|
clientScriptLoaded: !1
|
|
9
9
|
});
|
|
10
|
-
function
|
|
11
|
-
return
|
|
10
|
+
function P() {
|
|
11
|
+
return x(O);
|
|
12
12
|
}
|
|
13
|
-
const
|
|
14
|
-
function
|
|
15
|
-
if (!
|
|
13
|
+
const N = (e) => String(e) === "[object Object]";
|
|
14
|
+
function L(e) {
|
|
15
|
+
if (!N(e)) return !1;
|
|
16
16
|
const t = e.constructor;
|
|
17
17
|
if (t === void 0) return !0;
|
|
18
18
|
const n = t.prototype;
|
|
19
|
-
return !(!
|
|
19
|
+
return !(!N(n) || !n.hasOwnProperty("isPrototypeOf"));
|
|
20
20
|
}
|
|
21
|
-
function
|
|
21
|
+
function y(e, t) {
|
|
22
22
|
if (e === t)
|
|
23
23
|
return !0;
|
|
24
24
|
if (e instanceof Date && t instanceof Date)
|
|
25
25
|
return e.getTime() === t.getTime();
|
|
26
26
|
if (e instanceof Array && t instanceof Array)
|
|
27
|
-
return e.length !== t.length ? !1 : e.every((n,
|
|
28
|
-
if (
|
|
27
|
+
return e.length !== t.length ? !1 : e.every((n, o) => y(n, t[o]));
|
|
28
|
+
if (L(e) && L(t)) {
|
|
29
29
|
const n = Object.entries(e);
|
|
30
|
-
return n.length !== Object.keys(t).length ? !1 : n.every(([
|
|
30
|
+
return n.length !== Object.keys(t).length ? !1 : n.every(([o, r]) => y(r, t[o]));
|
|
31
31
|
}
|
|
32
32
|
return !1;
|
|
33
33
|
}
|
|
34
|
-
function
|
|
35
|
-
return
|
|
34
|
+
function g(e, t) {
|
|
35
|
+
return S(e, V(t));
|
|
36
36
|
}
|
|
37
|
-
function
|
|
38
|
-
const t =
|
|
39
|
-
return
|
|
37
|
+
function V(e) {
|
|
38
|
+
const t = h(e), n = h(0);
|
|
39
|
+
return y(e, t.current) || (t.current = e, n.current += 1), I(() => t.current, [n.current]);
|
|
40
40
|
}
|
|
41
|
-
function
|
|
41
|
+
function j() {
|
|
42
42
|
window.nostojs = window.nostojs ?? function(e) {
|
|
43
43
|
(window.nostojs.q = window.nostojs.q ?? []).push(e);
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
|
-
function
|
|
46
|
+
function H() {
|
|
47
47
|
return typeof window.nosto < "u";
|
|
48
48
|
}
|
|
49
|
-
const
|
|
49
|
+
const q = {
|
|
50
50
|
production: "https://connect.nosto.com/",
|
|
51
51
|
staging: "https://connect.staging.nosto.com/",
|
|
52
52
|
local: "https://connect.nosto.com/"
|
|
53
53
|
};
|
|
54
|
-
function
|
|
55
|
-
return
|
|
56
|
-
}
|
|
57
|
-
function
|
|
58
|
-
|
|
59
|
-
|
|
54
|
+
function R(e) {
|
|
55
|
+
return q[e ?? "production"];
|
|
56
|
+
}
|
|
57
|
+
function F({ merchantId: e, env: t, options: n, shopifyInternational: o, scriptLoader: r }) {
|
|
58
|
+
var c, a;
|
|
59
|
+
const s = document.querySelector("script[nosto-language], script[nosto-market-id]"), i = String((o == null ? void 0 : o.marketId) || ""), m = (o == null ? void 0 : o.language) || "", C = (s == null ? void 0 : s.getAttribute("nosto-language")) !== m || (s == null ? void 0 : s.getAttribute("nosto-market-id")) !== i;
|
|
60
|
+
if (!s || C) {
|
|
61
|
+
const l = document.querySelector("#nosto-sandbox");
|
|
62
|
+
(c = s == null ? void 0 : s.parentNode) == null || c.removeChild(s), (a = l == null ? void 0 : l.parentNode) == null || a.removeChild(l);
|
|
63
|
+
const f = new URL("/script/shopify/market/nosto.js", R(t));
|
|
64
|
+
f.searchParams.append("merchant", e), f.searchParams.append("market", i), f.searchParams.append("locale", m.toLowerCase());
|
|
65
|
+
const A = {
|
|
66
|
+
...n == null ? void 0 : n.attributes,
|
|
67
|
+
"nosto-language": m,
|
|
68
|
+
"nosto-market-id": i
|
|
69
|
+
};
|
|
70
|
+
return (r ?? E)(f.toString(), { ...n, attributes: A });
|
|
71
|
+
}
|
|
72
|
+
return Promise.resolve();
|
|
60
73
|
}
|
|
61
|
-
function
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
74
|
+
function z(e) {
|
|
75
|
+
if (e.shopifyInternational)
|
|
76
|
+
return F(e);
|
|
77
|
+
const { merchantId: t, env: n, options: o, scriptLoader: r } = e, c = r ?? E, a = new URL(`/include/${t}`, R(n));
|
|
78
|
+
return c(a.toString(), o);
|
|
79
|
+
}
|
|
80
|
+
function E(e, t) {
|
|
81
|
+
return new Promise((n, o) => {
|
|
82
|
+
const r = document.createElement("script");
|
|
83
|
+
r.src = e, r.async = !0, r.type = "text/javascript", r.onload = () => n(), r.onerror = () => o(), Object.entries((t == null ? void 0 : t.attributes) ?? {}).forEach(([c, a]) => r.setAttribute(c, a)), (t == null ? void 0 : t.position) === "head" ? document.head.appendChild(r) : document.body.appendChild(r);
|
|
65
84
|
});
|
|
66
85
|
}
|
|
67
|
-
async function
|
|
86
|
+
async function w(e) {
|
|
68
87
|
return window.nostojs(e);
|
|
69
88
|
}
|
|
70
|
-
|
|
71
|
-
function
|
|
72
|
-
const { clientScriptLoaded:
|
|
73
|
-
(n != null && n.deep ?
|
|
74
|
-
|
|
75
|
-
}, [
|
|
89
|
+
typeof window < "u" && j();
|
|
90
|
+
function u(e, t, n) {
|
|
91
|
+
const { clientScriptLoaded: o } = P();
|
|
92
|
+
(n != null && n.deep ? g : S)(() => {
|
|
93
|
+
o && w(e);
|
|
94
|
+
}, [o, ...t ?? []]);
|
|
76
95
|
}
|
|
77
|
-
function
|
|
78
|
-
return
|
|
96
|
+
function U(e) {
|
|
97
|
+
return _(e.recommendationComponent, {
|
|
79
98
|
// eslint-disable-next-line react/prop-types
|
|
80
99
|
nostoRecommendation: e.nostoRecommendation
|
|
81
100
|
});
|
|
82
101
|
}
|
|
83
|
-
function
|
|
84
|
-
|
|
102
|
+
function b(e) {
|
|
103
|
+
w((t) => t.placements.injectCampaigns(e));
|
|
85
104
|
}
|
|
86
|
-
function
|
|
105
|
+
function $(e) {
|
|
87
106
|
if (!window.nostojs)
|
|
88
107
|
throw new Error("Nosto has not yet been initialized");
|
|
89
|
-
|
|
108
|
+
b(e.recommendations);
|
|
90
109
|
}
|
|
91
|
-
function
|
|
92
|
-
const { responseMode: e, recommendationComponent: t } =
|
|
110
|
+
function d() {
|
|
111
|
+
const { responseMode: e, recommendationComponent: t } = P(), n = h({});
|
|
93
112
|
if (e == "HTML")
|
|
94
|
-
return { renderCampaigns:
|
|
95
|
-
function r
|
|
96
|
-
var
|
|
97
|
-
|
|
98
|
-
const c = ((
|
|
113
|
+
return { renderCampaigns: $ };
|
|
114
|
+
function o(r) {
|
|
115
|
+
var a, s;
|
|
116
|
+
b(((a = r.campaigns) == null ? void 0 : a.content) ?? {});
|
|
117
|
+
const c = ((s = r.campaigns) == null ? void 0 : s.recommendations) ?? {};
|
|
99
118
|
for (const i in c) {
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
/* @__PURE__ */
|
|
103
|
-
|
|
119
|
+
const m = c[i], C = "#" + i, l = document.querySelector(C);
|
|
120
|
+
l && (n.current[i] || (n.current[i] = M(l)), n.current[i].render(
|
|
121
|
+
/* @__PURE__ */ v(
|
|
122
|
+
U,
|
|
104
123
|
{
|
|
105
124
|
recommendationComponent: t,
|
|
106
|
-
nostoRecommendation:
|
|
125
|
+
nostoRecommendation: m
|
|
107
126
|
}
|
|
108
127
|
)
|
|
109
128
|
));
|
|
110
129
|
}
|
|
111
130
|
}
|
|
112
|
-
return { renderCampaigns:
|
|
131
|
+
return { renderCampaigns: o };
|
|
113
132
|
}
|
|
114
|
-
function
|
|
115
|
-
const { renderCampaigns: t } =
|
|
116
|
-
|
|
117
|
-
const
|
|
118
|
-
t(
|
|
133
|
+
function G(e) {
|
|
134
|
+
const { renderCampaigns: t } = d();
|
|
135
|
+
u(async (n) => {
|
|
136
|
+
const o = await n.defaultSession().viewNotFound().setPlacements((e == null ? void 0 : e.placements) || n.placements.getPlacements()).load();
|
|
137
|
+
t(o);
|
|
119
138
|
});
|
|
120
139
|
}
|
|
121
|
-
function
|
|
122
|
-
return
|
|
140
|
+
function ie(e) {
|
|
141
|
+
return G(e), null;
|
|
123
142
|
}
|
|
124
|
-
function
|
|
125
|
-
const { renderCampaigns: n } =
|
|
126
|
-
|
|
127
|
-
async (
|
|
128
|
-
const
|
|
129
|
-
n(
|
|
143
|
+
function J({ category: e, placements: t }) {
|
|
144
|
+
const { renderCampaigns: n } = d();
|
|
145
|
+
u(
|
|
146
|
+
async (o) => {
|
|
147
|
+
const r = await o.defaultSession().viewCategory(e).setPlacements(t || o.placements.getPlacements()).load();
|
|
148
|
+
n(r);
|
|
130
149
|
},
|
|
131
150
|
[e]
|
|
132
151
|
);
|
|
133
152
|
}
|
|
134
|
-
function
|
|
135
|
-
return
|
|
153
|
+
function ue(e) {
|
|
154
|
+
return J(e), null;
|
|
136
155
|
}
|
|
137
|
-
function
|
|
138
|
-
const { renderCampaigns: t } =
|
|
139
|
-
|
|
140
|
-
const
|
|
141
|
-
t(
|
|
156
|
+
function W(e) {
|
|
157
|
+
const { renderCampaigns: t } = d();
|
|
158
|
+
u(async (n) => {
|
|
159
|
+
const o = await n.defaultSession().viewCart().setPlacements((e == null ? void 0 : e.placements) || n.placements.getPlacements()).load();
|
|
160
|
+
t(o);
|
|
142
161
|
});
|
|
143
162
|
}
|
|
144
|
-
function
|
|
145
|
-
return
|
|
163
|
+
function de(e) {
|
|
164
|
+
return W(e), null;
|
|
146
165
|
}
|
|
147
|
-
function
|
|
148
|
-
const { renderCampaigns: t } =
|
|
149
|
-
|
|
150
|
-
const
|
|
151
|
-
t(
|
|
166
|
+
function Z(e) {
|
|
167
|
+
const { renderCampaigns: t } = d();
|
|
168
|
+
u(async (n) => {
|
|
169
|
+
const o = await n.defaultSession().viewFrontPage().setPlacements((e == null ? void 0 : e.placements) || n.placements.getPlacements()).load();
|
|
170
|
+
t(o);
|
|
152
171
|
});
|
|
153
172
|
}
|
|
154
|
-
function
|
|
155
|
-
return
|
|
173
|
+
function le(e) {
|
|
174
|
+
return Z(e), null;
|
|
156
175
|
}
|
|
157
176
|
function p(e) {
|
|
158
|
-
return !e || typeof e != "object" ||
|
|
159
|
-
const
|
|
160
|
-
return t[
|
|
177
|
+
return !e || typeof e != "object" || B(e) || K(e) ? e : Array.isArray(e) ? e.map(p) : Object.keys(e).reduce((t, n) => {
|
|
178
|
+
const o = n[0].toLowerCase() + n.slice(1).replace(/([A-Z]+)/g, (r, c) => "_" + c.toLowerCase());
|
|
179
|
+
return t[o] = p(e[n]), t;
|
|
161
180
|
}, {});
|
|
162
181
|
}
|
|
163
|
-
function
|
|
182
|
+
function B(e) {
|
|
164
183
|
return Object.prototype.toString.call(e) === "[object Date]";
|
|
165
184
|
}
|
|
166
|
-
function
|
|
185
|
+
function K(e) {
|
|
167
186
|
return Object.prototype.toString.call(e) === "[object RegExp]";
|
|
168
187
|
}
|
|
169
|
-
function
|
|
170
|
-
const { renderCampaigns: n } =
|
|
171
|
-
|
|
172
|
-
async (
|
|
173
|
-
const
|
|
174
|
-
n(
|
|
188
|
+
function Q({ order: e, placements: t }) {
|
|
189
|
+
const { renderCampaigns: n } = d();
|
|
190
|
+
u(
|
|
191
|
+
async (o) => {
|
|
192
|
+
const r = await o.defaultSession().addOrder(p(e)).setPlacements(t || o.placements.getPlacements()).load();
|
|
193
|
+
n(r);
|
|
175
194
|
},
|
|
176
195
|
[e],
|
|
177
196
|
{ deep: !0 }
|
|
178
197
|
);
|
|
179
198
|
}
|
|
180
|
-
function
|
|
181
|
-
return
|
|
199
|
+
function me(e) {
|
|
200
|
+
return Q(e), null;
|
|
182
201
|
}
|
|
183
|
-
function
|
|
184
|
-
const { renderCampaigns: t } =
|
|
185
|
-
|
|
186
|
-
const
|
|
187
|
-
t(
|
|
202
|
+
function X(e) {
|
|
203
|
+
const { renderCampaigns: t } = d();
|
|
204
|
+
u(async (n) => {
|
|
205
|
+
const o = await n.defaultSession().viewOther().setPlacements((e == null ? void 0 : e.placements) || n.placements.getPlacements()).load();
|
|
206
|
+
t(o);
|
|
188
207
|
});
|
|
189
208
|
}
|
|
190
|
-
function
|
|
191
|
-
return
|
|
209
|
+
function fe(e) {
|
|
210
|
+
return X(e), null;
|
|
192
211
|
}
|
|
193
|
-
function
|
|
194
|
-
return /* @__PURE__ */
|
|
212
|
+
function pe({ id: e, pageType: t }) {
|
|
213
|
+
return /* @__PURE__ */ v("div", { className: "nosto_element", id: e }, e + (t || ""));
|
|
195
214
|
}
|
|
196
|
-
function
|
|
197
|
-
const { renderCampaigns:
|
|
215
|
+
function Y({ product: e, tagging: t, placements: n, reference: o }) {
|
|
216
|
+
const { renderCampaigns: r } = d();
|
|
198
217
|
if (t && !t.product_id)
|
|
199
218
|
throw new Error("The product object must contain a product_id property");
|
|
200
219
|
const c = (t == null ? void 0 : t.product_id) ?? e;
|
|
201
|
-
|
|
202
|
-
async (
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
const i = await
|
|
206
|
-
|
|
220
|
+
u(
|
|
221
|
+
async (a) => {
|
|
222
|
+
const s = a.defaultSession().viewProduct(t ?? e).setPlacements(n || a.placements.getPlacements());
|
|
223
|
+
o && s.setRef(c, o);
|
|
224
|
+
const i = await s.load();
|
|
225
|
+
r(i);
|
|
207
226
|
},
|
|
208
227
|
[c, t == null ? void 0 : t.selected_sku_id]
|
|
209
228
|
);
|
|
210
229
|
}
|
|
211
|
-
function
|
|
212
|
-
return
|
|
230
|
+
function we(e) {
|
|
231
|
+
return Y(e), null;
|
|
213
232
|
}
|
|
214
|
-
function
|
|
215
|
-
return new Promise((n,
|
|
216
|
-
const
|
|
217
|
-
|
|
233
|
+
function ee(e, t) {
|
|
234
|
+
return new Promise((n, o) => {
|
|
235
|
+
const r = document.createElement("script");
|
|
236
|
+
r.type = "text/javascript", r.src = e, r.async = !0, r.onload = () => n(), r.onerror = () => o(), Object.entries((t == null ? void 0 : t.attributes) ?? {}).forEach(([c, a]) => r.setAttribute(c, a)), (t == null ? void 0 : t.position) === "head" ? document.head.appendChild(r) : document.body.appendChild(r);
|
|
218
237
|
});
|
|
219
238
|
}
|
|
220
|
-
const
|
|
221
|
-
function
|
|
239
|
+
const te = { "nosto-client-script": "" };
|
|
240
|
+
function ne(e) {
|
|
222
241
|
const {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
account: r,
|
|
242
|
+
scriptLoader: t = ee,
|
|
243
|
+
account: n,
|
|
226
244
|
shopifyMarkets: o,
|
|
227
|
-
loadScript:
|
|
228
|
-
} = e, [
|
|
229
|
-
return
|
|
230
|
-
function
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
async function y(a, m = {}) {
|
|
234
|
-
const f = `//${t}${a}`, P = { ...b, ...m };
|
|
235
|
-
await n(f, { attributes: P }), i();
|
|
245
|
+
loadScript: r = !0
|
|
246
|
+
} = e, [c, a] = T(!1);
|
|
247
|
+
return S(() => {
|
|
248
|
+
function s() {
|
|
249
|
+
a(!0);
|
|
236
250
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
const a = document.querySelector("[nosto-client-script]"), m = String((o == null ? void 0 : o.marketId) || ""), f = (o == null ? void 0 : o.language) || "", P = (a == null ? void 0 : a.getAttribute("nosto-language")) !== f || (a == null ? void 0 : a.getAttribute("nosto-market-id")) !== m;
|
|
240
|
-
if (!a || P) {
|
|
241
|
-
s && u(!1);
|
|
242
|
-
const h = document.querySelector("#nosto-sandbox");
|
|
243
|
-
(R = a == null ? void 0 : a.parentNode) == null || R.removeChild(a), (E = h == null ? void 0 : h.parentNode) == null || E.removeChild(h);
|
|
244
|
-
const $ = `/script/shopify/market/nosto.js?merchant=${r}&market=${m}&locale=${f.toLowerCase()}`;
|
|
245
|
-
y($, { "nosto-language": f, "nosto-market-id": m });
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
if (k(), !c) {
|
|
249
|
-
C(i);
|
|
251
|
+
if (j(), !r) {
|
|
252
|
+
w(s);
|
|
250
253
|
return;
|
|
251
254
|
}
|
|
252
|
-
async function
|
|
253
|
-
await
|
|
254
|
-
merchantId:
|
|
255
|
+
async function i() {
|
|
256
|
+
await z({
|
|
257
|
+
merchantId: n,
|
|
258
|
+
shopifyInternational: o,
|
|
255
259
|
options: {
|
|
256
|
-
attributes:
|
|
260
|
+
attributes: te
|
|
257
261
|
},
|
|
258
|
-
scriptLoader:
|
|
259
|
-
}),
|
|
262
|
+
scriptLoader: t
|
|
263
|
+
}), s();
|
|
260
264
|
}
|
|
261
|
-
!
|
|
262
|
-
}, [o == null ? void 0 : o.marketId, o == null ? void 0 : o.language]), { clientScriptLoaded:
|
|
265
|
+
(!H() || o) && i();
|
|
266
|
+
}, [o == null ? void 0 : o.marketId, o == null ? void 0 : o.language]), { clientScriptLoaded: c };
|
|
263
267
|
}
|
|
264
|
-
function
|
|
265
|
-
const { account: t, multiCurrency: n = !1, children:
|
|
266
|
-
if (
|
|
268
|
+
function Ce(e) {
|
|
269
|
+
const { account: t, multiCurrency: n = !1, children: o, recommendationComponent: r } = e, c = n ? e.currentVariation : "";
|
|
270
|
+
if (r && !D(r))
|
|
267
271
|
throw new Error(
|
|
268
272
|
"The recommendationComponent prop must be a valid React element. Please provide a valid React element."
|
|
269
273
|
);
|
|
270
|
-
const
|
|
271
|
-
return
|
|
272
|
-
i.defaultSession().setVariation(c).setResponseMode(
|
|
273
|
-
}), /* @__PURE__ */
|
|
274
|
-
|
|
274
|
+
const a = r ? "JSON_ORIGINAL" : "HTML", { clientScriptLoaded: s } = ne(e);
|
|
275
|
+
return s && w((i) => {
|
|
276
|
+
i.defaultSession().setVariation(c).setResponseMode(a);
|
|
277
|
+
}), /* @__PURE__ */ v(
|
|
278
|
+
O.Provider,
|
|
275
279
|
{
|
|
276
280
|
value: {
|
|
277
281
|
account: t,
|
|
278
|
-
clientScriptLoaded:
|
|
282
|
+
clientScriptLoaded: s,
|
|
279
283
|
currentVariation: c,
|
|
280
|
-
responseMode:
|
|
281
|
-
recommendationComponent:
|
|
284
|
+
responseMode: a,
|
|
285
|
+
recommendationComponent: r
|
|
282
286
|
},
|
|
283
|
-
children:
|
|
287
|
+
children: o
|
|
284
288
|
}
|
|
285
289
|
);
|
|
286
290
|
}
|
|
287
|
-
function
|
|
288
|
-
const { renderCampaigns: n } =
|
|
289
|
-
|
|
290
|
-
async (
|
|
291
|
-
const
|
|
292
|
-
n(
|
|
291
|
+
function oe({ query: e, placements: t }) {
|
|
292
|
+
const { renderCampaigns: n } = d();
|
|
293
|
+
u(
|
|
294
|
+
async (o) => {
|
|
295
|
+
const r = await o.defaultSession().viewSearch(e).setPlacements(t || o.placements.getPlacements()).load();
|
|
296
|
+
n(r);
|
|
293
297
|
},
|
|
294
298
|
[e]
|
|
295
299
|
);
|
|
296
300
|
}
|
|
297
|
-
function
|
|
298
|
-
return
|
|
301
|
+
function he(e) {
|
|
302
|
+
return oe(e), null;
|
|
299
303
|
}
|
|
300
|
-
function
|
|
301
|
-
const { clientScriptLoaded: n } =
|
|
302
|
-
|
|
303
|
-
const
|
|
304
|
-
n &&
|
|
305
|
-
c.defaultSession().setCart(
|
|
304
|
+
function re({ cart: e, customer: t } = {}) {
|
|
305
|
+
const { clientScriptLoaded: n } = P();
|
|
306
|
+
g(() => {
|
|
307
|
+
const o = e ? p(e) : void 0, r = t ? p(t) : void 0;
|
|
308
|
+
n && w((c) => {
|
|
309
|
+
c.defaultSession().setCart(o).setCustomer(r).viewOther().load({ skipPageViews: !0 });
|
|
306
310
|
});
|
|
307
311
|
}, [n, e, t]);
|
|
308
312
|
}
|
|
309
|
-
function
|
|
310
|
-
return
|
|
313
|
+
function ye(e) {
|
|
314
|
+
return re(e), null;
|
|
311
315
|
}
|
|
312
316
|
export {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
317
|
+
ie as Nosto404,
|
|
318
|
+
ue as NostoCategory,
|
|
319
|
+
de as NostoCheckout,
|
|
320
|
+
O as NostoContext,
|
|
321
|
+
le as NostoHome,
|
|
322
|
+
me as NostoOrder,
|
|
323
|
+
fe as NostoOther,
|
|
324
|
+
pe as NostoPlacement,
|
|
325
|
+
we as NostoProduct,
|
|
326
|
+
Ce as NostoProvider,
|
|
327
|
+
he as NostoSearch,
|
|
328
|
+
ye as NostoSession,
|
|
329
|
+
G as useNosto404,
|
|
330
|
+
J as useNostoCategory,
|
|
331
|
+
W as useNostoCheckout,
|
|
332
|
+
P as useNostoContext,
|
|
333
|
+
Z as useNostoHome,
|
|
334
|
+
Q as useNostoOrder,
|
|
335
|
+
X as useNostoOther,
|
|
336
|
+
Y as useNostoProduct,
|
|
337
|
+
oe as useNostoSearch,
|
|
338
|
+
re as useNostoSession
|
|
335
339
|
};
|
package/dist/index.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(r,u){typeof exports=="object"&&typeof module<"u"?u(exports,require("react"),require("react/jsx-runtime"),require("react-dom/client")):typeof define=="function"&&define.amd?define(["exports","react","react/jsx-runtime","react-dom/client"],u):(r=typeof globalThis<"u"?globalThis:r||self,u(r["@nosto/nosto-react"]={},r.React,r["react/jsx-runtime"],r.client))})(this,function(r,u,y,V){"use strict";const S=u.createContext({account:"",currentVariation:"",responseMode:"HTML",clientScriptLoaded:!1});function w(){return u.useContext(S)}const O=e=>String(e)==="[object Object]";function j(e){if(!O(e))return!1;const t=e.constructor;if(t===void 0)return!0;const n=t.prototype;return!(!O(n)||!n.hasOwnProperty("isPrototypeOf"))}function P(e,t){if(e===t)return!0;if(e instanceof Date&&t instanceof Date)return e.getTime()===t.getTime();if(e instanceof Array&&t instanceof Array)return e.length!==t.length?!1:e.every((n,o)=>P(n,t[o]));if(j(e)&&j(t)){const n=Object.entries(e);return n.length!==Object.keys(t).length?!1:n.every(([o,s])=>P(s,t[o]))}return!1}function L(e,t){return u.useEffect(e,F(t))}function F(e){const t=u.useRef(e),n=u.useRef(0);return P(e,t.current)||(t.current=e,n.current+=1),u.useMemo(()=>t.current,[n.current])}function g(){window.nostojs=window.nostojs??function(e){(window.nostojs.q=window.nostojs.q??[]).push(e)}}function z(){return typeof window.nosto<"u"}const U={production:"https://connect.nosto.com/",staging:"https://connect.staging.nosto.com/",local:"https://connect.nosto.com/"};function R(e){return U[e??"production"]}function $({merchantId:e,env:t,options:n,shopifyInternational:o,scriptLoader:s}){var c,a;const i=document.querySelector("script[nosto-language], script[nosto-market-id]"),d=String((o==null?void 0:o.marketId)||""),C=(o==null?void 0:o.language)||"",v=(i==null?void 0:i.getAttribute("nosto-language"))!==C||(i==null?void 0:i.getAttribute("nosto-market-id"))!==d;if(!i||v){const f=document.querySelector("#nosto-sandbox");(c=i==null?void 0:i.parentNode)==null||c.removeChild(i),(a=f==null?void 0:f.parentNode)==null||a.removeChild(f);const N=new URL("/script/shopify/market/nosto.js",R(t));N.searchParams.append("merchant",e),N.searchParams.append("market",d),N.searchParams.append("locale",C.toLowerCase());const ue={...n==null?void 0:n.attributes,"nosto-language":C,"nosto-market-id":d};return(s??E)(N.toString(),{...n,attributes:ue})}return Promise.resolve()}function G(e){if(e.shopifyInternational)return $(e);const{merchantId:t,env:n,options:o,scriptLoader:s}=e,c=s??E,a=new URL(`/include/${t}`,R(n));return c(a.toString(),o)}function E(e,t){return new Promise((n,o)=>{const s=document.createElement("script");s.src=e,s.async=!0,s.type="text/javascript",s.onload=()=>n(),s.onerror=()=>o(),Object.entries((t==null?void 0:t.attributes)??{}).forEach(([c,a])=>s.setAttribute(c,a)),(t==null?void 0:t.position)==="head"?document.head.appendChild(s):document.body.appendChild(s)})}async function p(e){return window.nostojs(e)}typeof window<"u"&&g();function l(e,t,n){const{clientScriptLoaded:o}=w();(n!=null&&n.deep?L:u.useEffect)(()=>{o&&p(e)},[o,...t??[]])}function J(e){return u.cloneElement(e.recommendationComponent,{nostoRecommendation:e.nostoRecommendation})}function b(e){p(t=>t.placements.injectCampaigns(e))}function W(e){if(!window.nostojs)throw new Error("Nosto has not yet been initialized");b(e.recommendations)}function m(){const{responseMode:e,recommendationComponent:t}=w(),n=u.useRef({});if(e=="HTML")return{renderCampaigns:W};function o(s){var a,i;b(((a=s.campaigns)==null?void 0:a.content)??{});const c=((i=s.campaigns)==null?void 0:i.recommendations)??{};for(const d in c){const C=c[d],v="#"+d,f=document.querySelector(v);f&&(n.current[d]||(n.current[d]=V.createRoot(f)),n.current[d].render(y.jsx(J,{recommendationComponent:t,nostoRecommendation:C})))}}return{renderCampaigns:o}}function k(e){const{renderCampaigns:t}=m();l(async n=>{const o=await n.defaultSession().viewNotFound().setPlacements((e==null?void 0:e.placements)||n.placements.getPlacements()).load();t(o)})}function Z(e){return k(e),null}function A({category:e,placements:t}){const{renderCampaigns:n}=m();l(async o=>{const s=await o.defaultSession().viewCategory(e).setPlacements(t||o.placements.getPlacements()).load();n(s)},[e])}function B(e){return A(e),null}function I(e){const{renderCampaigns:t}=m();l(async n=>{const o=await n.defaultSession().viewCart().setPlacements((e==null?void 0:e.placements)||n.placements.getPlacements()).load();t(o)})}function K(e){return I(e),null}function T(e){const{renderCampaigns:t}=m();l(async n=>{const o=await n.defaultSession().viewFrontPage().setPlacements((e==null?void 0:e.placements)||n.placements.getPlacements()).load();t(o)})}function Q(e){return T(e),null}function h(e){return!e||typeof e!="object"||X(e)||Y(e)?e:Array.isArray(e)?e.map(h):Object.keys(e).reduce((t,n)=>{const o=n[0].toLowerCase()+n.slice(1).replace(/([A-Z]+)/g,(s,c)=>"_"+c.toLowerCase());return t[o]=h(e[n]),t},{})}function X(e){return Object.prototype.toString.call(e)==="[object Date]"}function Y(e){return Object.prototype.toString.call(e)==="[object RegExp]"}function _({order:e,placements:t}){const{renderCampaigns:n}=m();l(async o=>{const s=await o.defaultSession().addOrder(h(e)).setPlacements(t||o.placements.getPlacements()).load();n(s)},[e],{deep:!0})}function x(e){return _(e),null}function q(e){const{renderCampaigns:t}=m();l(async n=>{const o=await n.defaultSession().viewOther().setPlacements((e==null?void 0:e.placements)||n.placements.getPlacements()).load();t(o)})}function ee(e){return q(e),null}function te({id:e,pageType:t}){return y.jsx("div",{className:"nosto_element",id:e},e+(t||""))}function H({product:e,tagging:t,placements:n,reference:o}){const{renderCampaigns:s}=m();if(t&&!t.product_id)throw new Error("The product object must contain a product_id property");const c=(t==null?void 0:t.product_id)??e;l(async a=>{const i=a.defaultSession().viewProduct(t??e).setPlacements(n||a.placements.getPlacements());o&&i.setRef(c,o);const d=await i.load();s(d)},[c,t==null?void 0:t.selected_sku_id])}function ne(e){return H(e),null}function oe(e,t){return new Promise((n,o)=>{const s=document.createElement("script");s.type="text/javascript",s.src=e,s.async=!0,s.onload=()=>n(),s.onerror=()=>o(),Object.entries((t==null?void 0:t.attributes)??{}).forEach(([c,a])=>s.setAttribute(c,a)),(t==null?void 0:t.position)==="head"?document.head.appendChild(s):document.body.appendChild(s)})}const se={"nosto-client-script":""};function re(e){const{scriptLoader:t=oe,account:n,shopifyMarkets:o,loadScript:s=!0}=e,[c,a]=u.useState(!1);return u.useEffect(()=>{function i(){a(!0)}if(g(),!s){p(i);return}async function d(){await G({merchantId:n,shopifyInternational:o,options:{attributes:se},scriptLoader:t}),i()}(!z()||o)&&d()},[o==null?void 0:o.marketId,o==null?void 0:o.language]),{clientScriptLoaded:c}}function ce(e){const{account:t,multiCurrency:n=!1,children:o,recommendationComponent:s}=e,c=n?e.currentVariation:"";if(s&&!u.isValidElement(s))throw new Error("The recommendationComponent prop must be a valid React element. Please provide a valid React element.");const a=s?"JSON_ORIGINAL":"HTML",{clientScriptLoaded:i}=re(e);return i&&p(d=>{d.defaultSession().setVariation(c).setResponseMode(a)}),y.jsx(S.Provider,{value:{account:t,clientScriptLoaded:i,currentVariation:c,responseMode:a,recommendationComponent:s},children:o})}function M({query:e,placements:t}){const{renderCampaigns:n}=m();l(async o=>{const s=await o.defaultSession().viewSearch(e).setPlacements(t||o.placements.getPlacements()).load();n(s)},[e])}function ie(e){return M(e),null}function D({cart:e,customer:t}={}){const{clientScriptLoaded:n}=w();L(()=>{const o=e?h(e):void 0,s=t?h(t):void 0;n&&p(c=>{c.defaultSession().setCart(o).setCustomer(s).viewOther().load({skipPageViews:!0})})},[n,e,t])}function ae(e){return D(e),null}r.Nosto404=Z,r.NostoCategory=B,r.NostoCheckout=K,r.NostoContext=S,r.NostoHome=Q,r.NostoOrder=x,r.NostoOther=ee,r.NostoPlacement=te,r.NostoProduct=ne,r.NostoProvider=ce,r.NostoSearch=ie,r.NostoSession=ae,r.useNosto404=k,r.useNostoCategory=A,r.useNostoCheckout=I,r.useNostoContext=w,r.useNostoHome=T,r.useNostoOrder=_,r.useNostoOther=q,r.useNostoProduct=H,r.useNostoSearch=M,r.useNostoSession=D,Object.defineProperty(r,Symbol.toStringTag,{value:"Module"})});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nosto/nosto-react",
|
|
3
3
|
"description": "Component library to simply implementing Nosto on React.",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.5.0",
|
|
5
5
|
"author": "Mridang Agarwalla, Dominik Gilg",
|
|
6
6
|
"license": "ISC",
|
|
7
7
|
"repository": {
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"react-dom": "^18.3.1 || ^19.0.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@nosto/nosto-js": "
|
|
38
|
+
"@nosto/nosto-js": "^1.3.1",
|
|
39
39
|
"@testing-library/jest-dom": "^6.4.8",
|
|
40
40
|
"@testing-library/react": "^16.0.0",
|
|
41
41
|
"@testing-library/user-event": "^14.4.3",
|
|
@@ -37,8 +37,8 @@ export interface NostoProviderProps {
|
|
|
37
37
|
* Enables Shopify markets with language and market id
|
|
38
38
|
*/
|
|
39
39
|
shopifyMarkets?: {
|
|
40
|
-
language
|
|
41
|
-
marketId
|
|
40
|
+
language: string
|
|
41
|
+
marketId: string | number
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
44
|
* Load nosto script (should be false if loading the script outside of nosto-react)
|
|
@@ -9,7 +9,6 @@ const defaultAttributes = { "nosto-client-script": "" }
|
|
|
9
9
|
|
|
10
10
|
export function useLoadClientScript(props: NostoScriptProps) {
|
|
11
11
|
const {
|
|
12
|
-
host = "connect.nosto.com",
|
|
13
12
|
scriptLoader = scriptLoaderFn,
|
|
14
13
|
account,
|
|
15
14
|
shopifyMarkets,
|
|
@@ -22,39 +21,6 @@ export function useLoadClientScript(props: NostoScriptProps) {
|
|
|
22
21
|
setClientScriptLoaded(true)
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
// Create and append script element
|
|
26
|
-
async function injectScriptElement(urlPartial: string, extraAttributes: Record<string, string> = {}) {
|
|
27
|
-
const scriptSrc = `//${host}${urlPartial}`
|
|
28
|
-
const attributes = { ...defaultAttributes, ...extraAttributes }
|
|
29
|
-
await scriptLoader(scriptSrc, { attributes })
|
|
30
|
-
scriptOnload()
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function prepareShopifyMarketsScript() {
|
|
34
|
-
const existingScript = document.querySelector("[nosto-client-script]")
|
|
35
|
-
|
|
36
|
-
const marketId = String(shopifyMarkets?.marketId || "")
|
|
37
|
-
const language = shopifyMarkets?.language || ""
|
|
38
|
-
|
|
39
|
-
const attributeMismatch =
|
|
40
|
-
existingScript?.getAttribute("nosto-language") !== language ||
|
|
41
|
-
existingScript?.getAttribute("nosto-market-id") !== marketId
|
|
42
|
-
|
|
43
|
-
if (!existingScript || attributeMismatch) {
|
|
44
|
-
if (clientScriptLoaded) {
|
|
45
|
-
setClientScriptLoaded(false)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const nostoSandbox = document.querySelector("#nosto-sandbox")
|
|
49
|
-
|
|
50
|
-
existingScript?.parentNode?.removeChild(existingScript)
|
|
51
|
-
nostoSandbox?.parentNode?.removeChild(nostoSandbox)
|
|
52
|
-
|
|
53
|
-
const urlPartial = `/script/shopify/market/nosto.js?merchant=${account}&market=${marketId}&locale=${language.toLowerCase()}`
|
|
54
|
-
injectScriptElement(urlPartial, { "nosto-language": language, "nosto-market-id": marketId })
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
24
|
initNostoStub()
|
|
59
25
|
|
|
60
26
|
if (!loadScript) {
|
|
@@ -65,6 +31,7 @@ export function useLoadClientScript(props: NostoScriptProps) {
|
|
|
65
31
|
async function initClientScript() {
|
|
66
32
|
await init({
|
|
67
33
|
merchantId: account,
|
|
34
|
+
shopifyInternational: shopifyMarkets,
|
|
68
35
|
options: {
|
|
69
36
|
attributes: defaultAttributes
|
|
70
37
|
},
|
|
@@ -74,14 +41,9 @@ export function useLoadClientScript(props: NostoScriptProps) {
|
|
|
74
41
|
}
|
|
75
42
|
|
|
76
43
|
// Load Nosto client script if not already loaded externally
|
|
77
|
-
if (!isNostoLoaded()
|
|
44
|
+
if (!isNostoLoaded() || shopifyMarkets) {
|
|
78
45
|
initClientScript()
|
|
79
46
|
}
|
|
80
|
-
|
|
81
|
-
// Load Shopify Markets scripts
|
|
82
|
-
if (shopifyMarkets) {
|
|
83
|
-
prepareShopifyMarketsScript()
|
|
84
|
-
}
|
|
85
47
|
}, [shopifyMarkets?.marketId, shopifyMarkets?.language])
|
|
86
48
|
|
|
87
49
|
return { clientScriptLoaded }
|