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