UNPKG

@nosto/nosto-react

Version:

Component library to simply implementing Nosto on React.

345 lines (344 loc) 10.5 kB
import { createContext as k, useContext as x, useEffect as S, useRef as h, useMemo as I, cloneElement as _, useState as M, isValidElement as T } from "react"; import { jsx as v } from "react/jsx-runtime"; import { createRoot as D } from "react-dom/client"; const O = k({ account: "", currentVariation: "", responseMode: "HTML", clientScriptLoaded: !1 }); function P() { return x(O); } const g = (e) => String(e) === "[object Object]"; function L(e) { if (!g(e)) return !1; const t = e.constructor; if (t === void 0) return !0; const n = t.prototype; return !(!g(n) || !n.hasOwnProperty("isPrototypeOf")); } function y(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) => y(n, t[o])); if (L(e) && L(t)) { const n = Object.entries(e); return n.length !== Object.keys(t).length ? !1 : n.every(([o, r]) => y(r, t[o])); } return !1; } function j(e, t) { return S(e, V(t)); } function V(e) { const t = h(e), n = h(0); return y(e, t.current) || (t.current = e, n.current += 1), I(() => t.current, [n.current]); } function N() { window.nostojs = window.nostojs ?? function(e) { (window.nostojs.q = window.nostojs.q ?? []).push(e); }; } async function m(e) { return window.nostojs(e); } typeof window < "u" && (N(), m((e) => { e.internal.getSettings(); })); function q() { return typeof window.nosto < "u"; } const H = { production: "https://connect.nosto.com/", staging: "https://connect.staging.nosto.com/", local: "https://connect.nosto.com/" }; function R(e) { return H[e ?? "production"]; } function F({ merchantId: e, env: t, options: n, shopifyInternational: o, scriptLoader: r }) { var c, i; const s = document.querySelector("script[nosto-language], script[nosto-market-id]"), a = String((o == null ? void 0 : o.marketId) || ""), u = (o == null ? void 0 : o.language) || "", C = (s == null ? void 0 : s.getAttribute("nosto-language")) !== u || (s == null ? void 0 : s.getAttribute("nosto-market-id")) !== a; if (!s || C) { const f = document.querySelector("#nosto-sandbox"); (c = s == null ? void 0 : s.parentNode) == null || c.removeChild(s), (i = f == null ? void 0 : f.parentNode) == null || i.removeChild(f); const p = new URL("/script/shopify/market/nosto.js", R(t)); p.searchParams.append("merchant", e), p.searchParams.append("market", a), p.searchParams.append("locale", u.toLowerCase()); const b = { ...n == null ? void 0 : n.attributes, "nosto-language": u, "nosto-market-id": a }; return (r ?? E)(p.toString(), { ...n, attributes: b }); } return Promise.resolve(); } function z(e) { if (e.shopifyInternational) return F(e); const { merchantId: t, env: n, options: o, scriptLoader: r } = e, c = r ?? E, i = new URL(`/include/${t}`, R(n)); return c(i.toString(), o); } function E(e, t) { return new Promise((n, o) => { const r = document.createElement("script"); 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, i]) => r.setAttribute(c, i)), (t == null ? void 0 : t.position) === "head" ? document.head.appendChild(r) : document.body.appendChild(r); }); } typeof window < "u" && N(); function d(e, t, n) { const { clientScriptLoaded: o } = P(); (n != null && n.deep ? j : S)(() => { o && m(e); }, [o, ...t ?? []]); } function U(e) { return _(e.recommendationComponent, { // eslint-disable-next-line react/prop-types nostoRecommendation: e.nostoRecommendation }); } function A(e) { m((t) => t.placements.injectCampaigns(e)); } function $(e) { if (!window.nostojs) throw new Error("Nosto has not yet been initialized"); A(e.recommendations); } function l() { const { responseMode: e, recommendationComponent: t } = P(), n = h({}); if (e == "HTML") return { renderCampaigns: $ }; if (!t) throw new Error("recommendationComponent is required for client-side rendering using hook"); function o(r) { var i, s; A(((i = r.campaigns) == null ? void 0 : i.content) ?? {}); const c = ((s = r.campaigns) == null ? void 0 : s.recommendations) ?? {}; for (const a in c) { const u = c[a], C = "#" + a, f = document.querySelector(C); f && (n.current[a] || (n.current[a] = D(f)), n.current[a].render( /* @__PURE__ */ v( U, { recommendationComponent: t, nostoRecommendation: u } ) )); } } return { renderCampaigns: o }; } function G(e) { const { renderCampaigns: t } = l(); d(async (n) => { const o = await n.defaultSession().viewNotFound().setPlacements((e == null ? void 0 : e.placements) || n.placements.getPlacements()).load(); t(o); }); } function ae(e) { return G(e), null; } function J({ category: e, placements: t }) { const { renderCampaigns: n } = l(); d( async (o) => { const r = await o.defaultSession().viewCategory(e).setPlacements(t || o.placements.getPlacements()).load(); n(r); }, [e] ); } function ue(e) { return J(e), null; } function W(e) { const { renderCampaigns: t } = l(); d(async (n) => { const o = await n.defaultSession().viewCart().setPlacements((e == null ? void 0 : e.placements) || n.placements.getPlacements()).load(); t(o); }); } function de(e) { return W(e), null; } function Z(e) { const { renderCampaigns: t } = l(); d(async (n) => { const o = await n.defaultSession().viewFrontPage().setPlacements((e == null ? void 0 : e.placements) || n.placements.getPlacements()).load(); t(o); }); } function le(e) { return Z(e), null; } function w(e) { return !e || typeof e != "object" || B(e) || K(e) ? e : Array.isArray(e) ? e.map(w) : Object.keys(e).reduce((t, n) => { const o = n[0].toLowerCase() + n.slice(1).replace(/([A-Z]+)/g, (r, c) => "_" + c.toLowerCase()); return t[o] = w(e[n]), t; }, {}); } function B(e) { return Object.prototype.toString.call(e) === "[object Date]"; } function K(e) { return Object.prototype.toString.call(e) === "[object RegExp]"; } function Q({ order: e, placements: t }) { const { renderCampaigns: n } = l(); d( async (o) => { const r = await o.defaultSession().addOrder(w(e)).setPlacements(t || o.placements.getPlacements()).load(); n(r); }, [e], { deep: !0 } ); } function me(e) { return Q(e), null; } function X(e) { const { renderCampaigns: t } = l(); d(async (n) => { const o = await n.defaultSession().viewOther().setPlacements((e == null ? void 0 : e.placements) || n.placements.getPlacements()).load(); t(o); }); } function fe(e) { return X(e), null; } function pe({ id: e, pageType: t, children: n }) { return /* @__PURE__ */ v("div", { className: "nosto_element", id: e, children: n }, e + (t || "")); } function Y({ product: e, tagging: t, placements: n, reference: o }) { const { renderCampaigns: r } = l(); 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; d( async (i) => { const s = i.defaultSession().viewProduct(t ?? e).setPlacements(n || i.placements.getPlacements()); o && s.setRef(c, o); const a = await s.load(); r(a); }, [c, t == null ? void 0 : t.selected_sku_id] ); } function we(e) { return Y(e), null; } function ee(e, t) { return new Promise((n, o) => { const r = document.createElement("script"); 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, i]) => r.setAttribute(c, i)), (t == null ? void 0 : t.position) === "head" ? document.head.appendChild(r) : document.body.appendChild(r); }); } const te = { "nosto-client-script": "" }; function ne(e) { const { scriptLoader: t = ee, account: n, shopifyMarkets: o, loadScript: r = !0 } = e, [c, i] = M(!1); return S(() => { function s() { i(!0); } if (N(), m((u) => u.setAutoLoad(!1)), !r) { m(s); return; } async function a() { await z({ merchantId: n, shopifyInternational: o, options: { attributes: te }, scriptLoader: t }), s(); } (!q() || o) && a(); }, [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: r, renderMode: c } = e, i = n ? e.currentVariation : ""; if (r && !T(r)) throw new Error( "The recommendationComponent prop must be a valid React element. Please provide a valid React element." ); const s = c || (r ? "JSON_ORIGINAL" : "HTML"), { clientScriptLoaded: a } = ne(e); return a && m((u) => { u.defaultSession().setVariation(i).setResponseMode(s); }), /* @__PURE__ */ v( O.Provider, { value: { account: t, clientScriptLoaded: a, currentVariation: i, responseMode: s, recommendationComponent: r }, children: o } ); } function oe({ query: e, placements: t }) { const { renderCampaigns: n } = l(); d( async (o) => { const r = await o.defaultSession().viewSearch(e).setPlacements(t || o.placements.getPlacements()).load(); n(r); }, [e] ); } function he(e) { return oe(e), null; } function re({ cart: e, customer: t } = {}) { const { clientScriptLoaded: n } = P(); j(() => { const o = e ? w(e) : void 0, r = t ? w(t) : void 0; n && m((c) => { c.defaultSession().setCart(o).setCustomer(r).viewOther().load({ skipPageViews: !0 }); }); }, [n, e, t]); } function ye(e) { return re(e), null; } export { ae as Nosto404, ue as NostoCategory, de as NostoCheckout, O as NostoContext, le as NostoHome, me as NostoOrder, fe as NostoOther, pe as NostoPlacement, we as NostoProduct, Ce as NostoProvider, he as NostoSearch, ye as NostoSession, G as useNosto404, J as useNostoCategory, W as useNostoCheckout, P as useNostoContext, Z as useNostoHome, Q as useNostoOrder, X as useNostoOther, Y as useNostoProduct, oe as useNostoSearch, re as useNostoSession };