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