@nosto/nosto-react
Version:
Component library to simply implementing Nosto on React.
345 lines (344 loc) • 10.5 kB
JavaScript
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
};