UNPKG

@nosto/nosto-react

Version:

Component library to simply implementing Nosto on React.

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