@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 CHANGED
@@ -42,8 +42,8 @@ _\*\*Note: The search feature is available when implemented via our code editor.
42
42
 
43
43
  #### Required versions
44
44
 
45
- - npm: 9.8.1
46
- - node: v18.18.0
45
+ - npm: 10.9.0
46
+ - node: v22.12.0
47
47
 
48
48
  ### Installation
49
49
 
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?: string;
328
- marketId?: string | number;
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 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";
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 _ = D({
4
+ const O = k({
5
5
  account: "",
6
6
  currentVariation: "",
7
7
  responseMode: "HTML",
8
8
  clientScriptLoaded: !1
9
9
  });
10
- function L() {
11
- return V(_);
10
+ function P() {
11
+ return x(O);
12
12
  }
13
- const g = (e) => String(e) === "[object Object]";
14
- function A(e) {
15
- if (!g(e)) return !1;
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 !(!g(n) || !n.hasOwnProperty("isPrototypeOf"));
19
+ return !(!N(n) || !n.hasOwnProperty("isPrototypeOf"));
20
20
  }
21
- function v(e, t) {
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, r) => v(n, t[r]));
28
- if (A(e) && A(t)) {
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(([r, o]) => v(o, t[r]));
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 I(e, t) {
35
- return O(e, z(t));
34
+ function g(e, t) {
35
+ return S(e, V(t));
36
36
  }
37
- function z(e) {
38
- const t = N(e), n = N(0);
39
- return v(e, t.current) || (t.current = e, n.current += 1), x(() => t.current, [n.current]);
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 k() {
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 G() {
46
+ function H() {
47
47
  return typeof window.nosto < "u";
48
48
  }
49
- const J = {
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 U(e) {
55
- return J[e ?? "production"];
56
- }
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);
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 Z(e, t) {
62
- return new Promise((n, r) => {
63
- const o = document.createElement("script");
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);
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 C(e) {
86
+ async function w(e) {
68
87
  return window.nostojs(e);
69
88
  }
70
- k();
71
- function d(e, t, n) {
72
- const { clientScriptLoaded: r } = L();
73
- (n != null && n.deep ? I : O)(() => {
74
- r && C(e);
75
- }, [r, ...t ?? []]);
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 B(e) {
78
- return H(e.recommendationComponent, {
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 T(e) {
84
- C((t) => t.placements.injectCampaigns(e));
102
+ function b(e) {
103
+ w((t) => t.placements.injectCampaigns(e));
85
104
  }
86
- function K(e) {
105
+ function $(e) {
87
106
  if (!window.nostojs)
88
107
  throw new Error("Nosto has not yet been initialized");
89
- T(e.recommendations);
108
+ b(e.recommendations);
90
109
  }
91
- function l() {
92
- const { responseMode: e, recommendationComponent: t } = L(), n = N({});
110
+ function d() {
111
+ const { responseMode: e, recommendationComponent: t } = P(), n = h({});
93
112
  if (e == "HTML")
94
- return { renderCampaigns: K };
95
- function r(o) {
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) ?? {};
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 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,
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: y
125
+ nostoRecommendation: m
107
126
  }
108
127
  )
109
128
  ));
110
129
  }
111
130
  }
112
- return { renderCampaigns: r };
131
+ return { renderCampaigns: o };
113
132
  }
114
- function Q(e) {
115
- const { renderCampaigns: t } = l();
116
- d(async (n) => {
117
- const r = await n.defaultSession().viewNotFound().setPlacements((e == null ? void 0 : e.placements) || n.placements.getPlacements()).load();
118
- t(r);
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 fe(e) {
122
- return Q(e), null;
140
+ function ie(e) {
141
+ return G(e), null;
123
142
  }
124
- function X({ category: e, placements: t }) {
125
- const { renderCampaigns: n } = l();
126
- d(
127
- async (r) => {
128
- const o = await r.defaultSession().viewCategory(e).setPlacements(t || r.placements.getPlacements()).load();
129
- n(o);
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 pe(e) {
135
- return X(e), null;
153
+ function ue(e) {
154
+ return J(e), null;
136
155
  }
137
- function Y(e) {
138
- const { renderCampaigns: t } = l();
139
- d(async (n) => {
140
- const r = await n.defaultSession().viewCart().setPlacements((e == null ? void 0 : e.placements) || n.placements.getPlacements()).load();
141
- t(r);
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 Ce(e) {
145
- return Y(e), null;
163
+ function de(e) {
164
+ return W(e), null;
146
165
  }
147
- function ee(e) {
148
- const { renderCampaigns: t } = l();
149
- d(async (n) => {
150
- const r = await n.defaultSession().viewFrontPage().setPlacements((e == null ? void 0 : e.placements) || n.placements.getPlacements()).load();
151
- t(r);
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 we(e) {
155
- return ee(e), null;
173
+ function le(e) {
174
+ return Z(e), null;
156
175
  }
157
176
  function p(e) {
158
- return !e || typeof e != "object" || te(e) || ne(e) ? e : Array.isArray(e) ? e.map(p) : Object.keys(e).reduce((t, n) => {
159
- const r = n[0].toLowerCase() + n.slice(1).replace(/([A-Z]+)/g, (o, c) => "_" + c.toLowerCase());
160
- return t[r] = p(e[n]), 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 te(e) {
182
+ function B(e) {
164
183
  return Object.prototype.toString.call(e) === "[object Date]";
165
184
  }
166
- function ne(e) {
185
+ function K(e) {
167
186
  return Object.prototype.toString.call(e) === "[object RegExp]";
168
187
  }
169
- function oe({ order: e, placements: t }) {
170
- const { renderCampaigns: n } = l();
171
- d(
172
- async (r) => {
173
- const o = await r.defaultSession().addOrder(p(e)).setPlacements(t || r.placements.getPlacements()).load();
174
- n(o);
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 he(e) {
181
- return oe(e), null;
199
+ function me(e) {
200
+ return Q(e), null;
182
201
  }
183
- function re(e) {
184
- const { renderCampaigns: t } = l();
185
- d(async (n) => {
186
- const r = await n.defaultSession().viewOther().setPlacements((e == null ? void 0 : e.placements) || n.placements.getPlacements()).load();
187
- t(r);
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 ye(e) {
191
- return re(e), null;
209
+ function fe(e) {
210
+ return X(e), null;
192
211
  }
193
- function Se({ id: e, pageType: t }) {
194
- return /* @__PURE__ */ j("div", { className: "nosto_element", id: e }, e + (t || ""));
212
+ function pe({ id: e, pageType: t }) {
213
+ return /* @__PURE__ */ v("div", { className: "nosto_element", id: e }, e + (t || ""));
195
214
  }
196
- function ce({ product: e, tagging: t, placements: n, reference: r }) {
197
- const { renderCampaigns: o } = l();
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
- d(
202
- async (s) => {
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);
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 Pe(e) {
212
- return ce(e), null;
230
+ function we(e) {
231
+ return Y(e), null;
213
232
  }
214
- function se(e, t) {
215
- return new Promise((n, r) => {
216
- const o = document.createElement("script");
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);
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 b = { "nosto-client-script": "" };
221
- function ae(e) {
239
+ const te = { "nosto-client-script": "" };
240
+ function ne(e) {
222
241
  const {
223
- host: t = "connect.nosto.com",
224
- scriptLoader: n = se,
225
- account: r,
242
+ scriptLoader: t = ee,
243
+ account: n,
226
244
  shopifyMarkets: o,
227
- loadScript: c = !0
228
- } = e, [s, u] = q(!1);
229
- return O(() => {
230
- function i() {
231
- u(!0);
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
- 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);
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 w() {
253
- await W({
254
- merchantId: r,
255
+ async function i() {
256
+ await z({
257
+ merchantId: n,
258
+ shopifyInternational: o,
255
259
  options: {
256
- attributes: b
260
+ attributes: te
257
261
  },
258
- scriptLoader: n
259
- }), i();
262
+ scriptLoader: t
263
+ }), s();
260
264
  }
261
- !G() && !o && w(), o && S();
262
- }, [o == null ? void 0 : o.marketId, o == null ? void 0 : o.language]), { clientScriptLoaded: s };
265
+ (!H() || o) && i();
266
+ }, [o == null ? void 0 : o.marketId, o == null ? void 0 : o.language]), { clientScriptLoaded: c };
263
267
  }
264
- function Ne(e) {
265
- const { account: t, multiCurrency: n = !1, children: r, recommendationComponent: o } = e, c = n ? e.currentVariation : "";
266
- if (o && !F(o))
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 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,
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: u,
282
+ clientScriptLoaded: s,
279
283
  currentVariation: c,
280
- responseMode: s,
281
- recommendationComponent: o
284
+ responseMode: a,
285
+ recommendationComponent: r
282
286
  },
283
- children: r
287
+ children: o
284
288
  }
285
289
  );
286
290
  }
287
- function ie({ query: e, placements: t }) {
288
- const { renderCampaigns: n } = l();
289
- d(
290
- async (r) => {
291
- const o = await r.defaultSession().viewSearch(e).setPlacements(t || r.placements.getPlacements()).load();
292
- n(o);
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 ve(e) {
298
- return ie(e), null;
301
+ function he(e) {
302
+ return oe(e), null;
299
303
  }
300
- function ue({ cart: e, customer: t } = {}) {
301
- const { clientScriptLoaded: n } = L();
302
- I(() => {
303
- const r = e ? p(e) : void 0, o = t ? p(t) : void 0;
304
- n && C((c) => {
305
- c.defaultSession().setCart(r).setCustomer(o).viewOther().load({ skipPageViews: !0 });
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 Oe(e) {
310
- return ue(e), null;
313
+ function ye(e) {
314
+ return re(e), null;
311
315
  }
312
316
  export {
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,
325
- Q as useNosto404,
326
- X as useNostoCategory,
327
- Y as useNostoCheckout,
328
- L as useNostoContext,
329
- ee as useNostoHome,
330
- oe as useNostoOrder,
331
- re as useNostoOther,
332
- ce as useNostoProduct,
333
- ie as useNostoSearch,
334
- ue as useNostoSession
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(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"})});
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.0",
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?: string
41
- marketId?: string | number
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() && !shopifyMarkets) {
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 }