@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 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
package/dist/index.es.js CHANGED
@@ -1,22 +1,22 @@
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 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 q(T);
11
+ return V(_);
12
12
  }
13
- const A = (e) => String(e) === "[object Object]";
14
- function b(e) {
15
- if (!A(e)) return !1;
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 !(!A(n) || !n.hasOwnProperty("isPrototypeOf"));
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 (b(e) && b(t)) {
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 $(e, t) {
35
- return E(e, U(t));
34
+ function I(e, t) {
35
+ return O(e, z(t));
36
36
  }
37
- function U(e) {
38
- const t = P(e), n = P(0);
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 D() {
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 W() {
46
+ function G() {
47
47
  return typeof window.nosto < "u";
48
48
  }
49
- const B = {
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 G(e) {
55
- return B[e ?? "production"];
54
+ function U(e) {
55
+ return J[e ?? "production"];
56
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);
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 Y(e, t) {
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 w(e) {
67
+ async function C(e) {
68
68
  return window.nostojs(e);
69
69
  }
70
- D();
70
+ k();
71
71
  function d(e, t, n) {
72
72
  const { clientScriptLoaded: r } = L();
73
- (n != null && n.deep ? $ : E)(() => {
74
- r && w(e);
73
+ (n != null && n.deep ? I : O)(() => {
74
+ r && C(e);
75
75
  }, [r, ...t ?? []]);
76
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
- };
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
- w((t) => {
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 = P({});
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
- 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,
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: u
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 we(e) {
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 Ce(e) {
134
+ function pe(e) {
147
135
  return X(e), null;
148
136
  }
149
- function ee(e) {
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 he(e) {
157
- return ee(e), null;
144
+ function Ce(e) {
145
+ return Y(e), null;
158
146
  }
159
- function te(e) {
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 ye(e) {
167
- return te(e), null;
154
+ function we(e) {
155
+ return ee(e), null;
168
156
  }
169
157
  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) => {
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 ne(e) {
163
+ function te(e) {
176
164
  return Object.prototype.toString.call(e) === "[object Date]";
177
165
  }
178
- function oe(e) {
166
+ function ne(e) {
179
167
  return Object.prototype.toString.call(e) === "[object RegExp]";
180
168
  }
181
- function re({ order: e, placements: t }) {
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 Se(e) {
193
- return re(e), null;
180
+ function he(e) {
181
+ return oe(e), null;
194
182
  }
195
- function ce(e) {
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 Ne(e) {
203
- return ce(e), null;
190
+ function ye(e) {
191
+ return re(e), null;
204
192
  }
205
- function Pe({ id: e, pageType: t }) {
206
- return /* @__PURE__ */ R("div", { className: "nosto_element", id: e }, e + (t || ""));
193
+ function Se({ id: e, pageType: t }) {
194
+ return /* @__PURE__ */ j("div", { className: "nosto_element", id: e }, e + (t || ""));
207
195
  }
208
- function se({ product: e, tagging: t, placements: n, reference: r }) {
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 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);
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 ve(e) {
224
- return se(e), null;
211
+ function Pe(e) {
212
+ return ce(e), null;
225
213
  }
226
- function ae(e, t) {
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
- function ie(e) {
233
- return window.nosto && "reload" in window.nosto ? (window.nosto.reload(e), !0) : !1;
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 = ae,
224
+ scriptLoader: n = se,
239
225
  account: r,
240
226
  shopifyMarkets: o,
241
227
  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);
228
+ } = e, [s, u] = q(!1);
229
+ return O(() => {
230
+ function i() {
231
+ u(!0);
248
232
  }
249
- async function S(i, m = {}) {
250
- const f = `//${t}${i}`, N = { "nosto-client-script": "", ...m };
251
- await n(f, { attributes: N }), u();
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 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);
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
- (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 });
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 (D(), !c) {
265
- w(u);
248
+ if (k(), !c) {
249
+ C(i);
266
250
  return;
267
251
  }
268
- async function _() {
269
- await J({
252
+ async function w() {
253
+ await W({
270
254
  merchantId: r,
271
255
  options: {
272
- attributes: { "nosto-client-script": "" }
256
+ attributes: b
273
257
  },
274
258
  scriptLoader: n
275
- }), u();
259
+ }), i();
276
260
  }
277
- !W() && !o && _(), o && C();
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 Oe(e) {
264
+ function Ne(e) {
281
265
  const { account: t, multiCurrency: n = !1, children: r, recommendationComponent: o } = e, c = n ? e.currentVariation : "";
282
- if (o && !M(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: a } = ue(e);
287
- return a && w((u) => {
288
- u.defaultSession().setVariation(c).setResponseMode(s);
289
- }), /* @__PURE__ */ R(
290
- T.Provider,
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: a,
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 de({ query: e, placements: t }) {
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 Ee(e) {
314
- return de(e), null;
297
+ function ve(e) {
298
+ return ie(e), null;
315
299
  }
316
- function le({ cart: e, customer: t } = {}) {
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 && w((c) => {
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 Re(e) {
326
- return le(e), null;
309
+ function Oe(e) {
310
+ return ue(e), null;
327
311
  }
328
312
  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,
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
- ee as useNostoCheckout,
327
+ Y as useNostoCheckout,
344
328
  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
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(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(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.3.0",
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
- "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": "*",
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
  },
@@ -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 = { "nosto-client-script": "", ...extraAttributes }
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: { "nosto-client-script": ""}
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
- 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) {