@nosto/nosto-react 0.2.1 → 0.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.
@@ -1,4 +1,4 @@
1
- (function(i,d){typeof exports=="object"&&typeof module!="undefined"?d(exports,require("react")):typeof define=="function"&&define.amd?define(["exports","react"],d):(i=typeof globalThis!="undefined"?globalThis:i||self,d(i["@nosto/nosto-react"]={},i.React))})(this,function(i,d){"use strict";function O(s){return s&&typeof s=="object"&&"default"in s?s:{default:s}}function F(s){if(s&&s.__esModule)return s;var e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});return s&&Object.keys(s).forEach(function(r){if(r!=="default"){var n=Object.getOwnPropertyDescriptor(s,r);Object.defineProperty(e,r,n.get?n:{enumerable:!0,get:function(){return s[r]}})}}),e.default=s,Object.freeze(e)}var w=O(d),N=F(d);const S=d.createContext({account:void 0,currentVariation:"",renderFunction:void 0});function p(){const s=d.useContext(S);if(!s)throw new Error("No nosto context found");return s}var _={exports:{}},v={};/**
1
+ (function(u,m){typeof exports=="object"&&typeof module!="undefined"?m(exports,require("react"),require("react-dom/client")):typeof define=="function"&&define.amd?define(["exports","react","react-dom/client"],m):(u=typeof globalThis!="undefined"?globalThis:u||self,m(u["@nosto/nosto-react"]={},u.React,u.ReactDOM))})(this,function(u,m,x){"use strict";function D(t){return t&&typeof t=="object"&&"default"in t?t:{default:t}}var R=D(m);const V=m.createContext({account:"",currentVariation:"",pageType:"",responseMode:"HTML",clientScriptLoaded:!1,useRenderCampaigns:()=>{}});function h(){const t=m.useContext(V);if(!t)throw new Error("No nosto context found");return t}var E={exports:{}},b={};/**
2
2
  * @license React
3
3
  * react-jsx-runtime.production.min.js
4
4
  *
@@ -6,4 +6,4 @@
6
6
  *
7
7
  * This source code is licensed under the MIT license found in the
8
8
  * LICENSE file in the root directory of this source tree.
9
- */var E=w.default,T=Symbol.for("react.element"),V=Symbol.for("react.fragment"),x=Object.prototype.hasOwnProperty,R=E.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,A={key:!0,ref:!0,__self:!0,__source:!0};function P(s,e,r){var n,o={},l=null,t=null;r!==void 0&&(l=""+r),e.key!==void 0&&(l=""+e.key),e.ref!==void 0&&(t=e.ref);for(n in e)x.call(e,n)&&!A.hasOwnProperty(n)&&(o[n]=e[n]);if(s&&s.defaultProps)for(n in e=s.defaultProps,e)o[n]===void 0&&(o[n]=e[n]);return{$$typeof:T,type:s,key:l,ref:t,props:o,_owner:R.current}}v.Fragment=V,v.jsx=P,v.jsxs=P,_.exports=v;const c=_.exports.jsx,f=_.exports.jsxs,u=_.exports.Fragment,H=()=>{const{clientScriptLoaded:s,currentVariation:e,renderFunction:r,responseMode:n}=p();return d.useEffect(()=>{s&&window.nostojs(o=>{o.defaultSession().setVariation(e).setResponseMode(n).viewNotFound().setPlacements(o.placements.getPlacements()).load().then(l=>{n=="HTML"?o.placements.injectCampaigns(l.recommendations):r(l.campaigns)})})},[s,e,r]),c(u,{children:c("div",{className:"nosto_page_type",style:{display:"none"},children:"notfound"})})},I=()=>{const{clientScriptLoaded:s,currentVariation:e,renderFunction:r,responseMode:n}=p();return d.useEffect(()=>{s&&window.nostojs(o=>{o.defaultSession().setVariation(e).setResponseMode(n).viewOther().setPlacements(o.placements.getPlacements()).load().then(l=>{n=="HTML"?o.placements.injectCampaigns(l.recommendations):r(l.campaigns)})})},[s,e,r]),c(u,{children:c("div",{className:"nosto_page_type",style:{display:"none"},children:"other"})})},D=()=>{const{clientScriptLoaded:s,currentVariation:e,renderFunction:r,responseMode:n}=p();return d.useEffect(()=>{s&&window.nostojs(o=>{o.defaultSession().setVariation(e).setResponseMode(n).viewCart().setPlacements(o.placements.getPlacements()).load().then(l=>{n=="HTML"?o.placements.injectCampaigns(l.recommendations):r(l.campaigns)})})},[s,e,r]),c(u,{children:c("div",{className:"nosto_page_type",style:{display:"none"},children:"cart"})})},U=({product:s,tagging:e})=>{const{clientScriptLoaded:r,currentVariation:n,renderFunction:o,responseMode:l}=p();return d.useEffect(()=>{r&&window.nostojs(t=>{t.defaultSession().setResponseMode(l).viewProduct(s).setPlacements(t.placements.getPlacements()).load().then(a=>{l=="HTML"?t.placements.injectCampaigns(a.recommendations):o(a.campaigns)})},[r,n,s,o])}),f(u,{children:[c("div",{className:"nosto_page_type",style:{display:"none"},children:"product"}),f("div",{className:"nosto_product",style:{display:"none"},children:[(e==null?void 0:e.variationId)&&c("span",{className:"variation_id",children:e.variationId}),s&&c("span",{className:"product_id",children:s}),(e==null?void 0:e.name)&&c("span",{className:"name",children:e.name}),(e==null?void 0:e.url)&&c("span",{className:"url",children:e.url.toString()}),(e==null?void 0:e.imageUrl)&&c("span",{className:"image_url",children:e.imageUrl.toString()}),(e==null?void 0:e.availability)&&c("span",{className:"availability",children:e.availability}),(e==null?void 0:e.price)&&c("span",{className:"price",children:e.price}),(e==null?void 0:e.listPrice)&&c("span",{className:"list_price",children:e.listPrice}),(e==null?void 0:e.priceCurrencyCode)&&c("span",{className:"price_currency_code",children:e.priceCurrencyCode}),(e==null?void 0:e.brand)&&c("span",{className:"brand",children:e.brand}),(e==null?void 0:e.description)&&c("span",{className:"description",children:e.description}),(e==null?void 0:e.googleCategory)&&c("span",{className:"description",children:e.googleCategory}),(e==null?void 0:e.condition)&&c("span",{className:"condition",children:e.condition}),(e==null?void 0:e.gender)&&c("span",{className:"gender",children:e.gender}),(e==null?void 0:e.ageGroup)&&c("span",{className:"age_group",children:e.ageGroup}),(e==null?void 0:e.gtin)&&c("span",{className:"gtin",children:e.gtin}),(e==null?void 0:e.category)&&(e==null?void 0:e.category.map((t,a)=>c("span",{className:"category",children:t},a))),(e==null?void 0:e.tags1)&&e.tags1.map((t,a)=>c("span",{className:"tag1",children:t},a)),(e==null?void 0:e.tags2)&&e.tags2.map((t,a)=>c("span",{className:"tag2",children:t},a)),(e==null?void 0:e.tags3)&&e.tags3.map((t,a)=>c("span",{className:"tag3",children:t},a)),(e==null?void 0:e.ratingValue)&&c("span",{className:"rating_value",children:e.ratingValue}),(e==null?void 0:e.reviewCount)&&c("span",{className:"review_count",children:e.reviewCount}),(e==null?void 0:e.alternateImageUrls)&&e.alternateImageUrls.map((t,a)=>c("span",{className:"alternate_image_url",children:t.toString()},a)),(e==null?void 0:e.customFields)&&Object.keys(e.customFields).map((t,a)=>e.customFields&&e.customFields[t]&&c("span",{className:t,children:e.customFields[t]},a)),(e==null?void 0:e.skus)&&e.skus.map((t,a)=>f("span",{className:"nosto_sku",children:[(t==null?void 0:t.id)&&c("span",{className:"product_id",children:t.id}),(t==null?void 0:t.name)&&c("span",{className:"name",children:t.name}),(t==null?void 0:t.price)&&c("span",{className:"price",children:t.price}),(t==null?void 0:t.listPrice)&&c("span",{className:"list_price",children:t.listPrice}),(t==null?void 0:t.url)&&c("span",{className:"url",children:t.url.toString()}),(t==null?void 0:t.imageUrl)&&c("span",{className:"image_url",children:t.imageUrl.toString()}),(t==null?void 0:t.gtin)&&c("span",{className:"gtin",children:t.gtin}),(t==null?void 0:t.availability)&&c("span",{className:"availability",children:t.availability}),(t==null?void 0:t.customFields)&&Object.keys(t.customFields).map((y,C)=>t.customFields&&t.customFields[y]&&c("span",{className:y,children:t.customFields[y]},C))]},a))]})]})},b=({category:s})=>{const{clientScriptLoaded:e,currentVariation:r,renderFunction:n,responseMode:o}=p();return d.useEffect(()=>{e&&window.nostojs(l=>{l.defaultSession().setVariation(r).setResponseMode(o).viewCategory(s).setPlacements(l.placements.getPlacements()).load().then(t=>{o=="HTML"?l.placements.injectCampaigns(t.recommendations):n(t.campaigns)})})},[e,s,r,n]),f(u,{children:[c("div",{className:"nosto_page_type",style:{display:"none"},children:"category"}),c("div",{className:"nosto_category",style:{display:"none"},children:s})]})},z=({query:s})=>{const{clientScriptLoaded:e,currentVariation:r,renderFunction:n,responseMode:o}=p();return d.useEffect(()=>{e&&window.nostojs(l=>{l.defaultSession().setVariation(r).setResponseMode(o).viewSearch(s).setPlacements(l.placements.getPlacements()).load().then(t=>{o=="HTML"?l.placements.injectCampaigns(t.recommendations):n(t.campaigns)})})},[e,r,s,n]),f(u,{children:[c("div",{className:"nosto_page_type",style:{display:"none"},children:"search"}),c("div",{className:"nosto_search",style:{display:"none"},children:s})]})};var j=function s(e){return!e||typeof e!="object"||q(e)||B(e)?e:Array.isArray(e)?e.map(s):Object.keys(e).reduce(function(r,n){var o=n[0].toLowerCase()+n.slice(1).replace(/([A-Z]+)/g,function(l,t){return"_"+t.toLowerCase()});return r[o]=s(e[n]),r},{})},q=function(s){return Object.prototype.toString.call(s)==="[object Date]"},B=function(s){return Object.prototype.toString.call(s)==="[object RegExp]"};const G=({order:s})=>{const{clientScriptLoaded:e,currentVariation:r,renderFunction:n,responseMode:o}=p();return d.useEffect(()=>{e&&window.nostojs(l=>{l.defaultSession().setVariation(r).setResponseMode(o).addOrder(j(s)).setPlacements(l.placements.getPlacements()).load().then(t=>{o=="HTML"?l.placements.injectCampaigns(t.recommendations):n(t.campaigns)})})},[e,r,n]),f(u,{children:[c("div",{className:"nosto_page_type",style:{display:"none"},children:"order"}),c("div",{className:"nosto_order",style:{display:"none"},children:s.purchase.number})]})},J=()=>{const{clientScriptLoaded:s,currentVariation:e,renderFunction:r,responseMode:n}=p();return d.useEffect(()=>{s&&window.nostojs(o=>{o.defaultSession().setVariation(e).setResponseMode(n).viewFrontPage().setPlacements(o.placements.getPlacements()).load().then(l=>{n=="HTML"?o.placements.injectCampaigns(l.recommendations):r(l.campaigns)})})},[s,e,r]),c(u,{children:c("div",{className:"nosto_page_type",style:{display:"none"},children:"front"})})},$=({id:s})=>c("div",{className:"nosto_element",id:s}),W=({account:s,currentVariation:e="",multiCurrency:r=!1,host:n,children:o,renderFunction:l})=>{const[t,a]=w.default.useState(!1),y=w.default.useMemo(()=>t,[t]),C=typeof l=="function"?"JSON_ORIGINAL":"HTML";return e=r?e:"",d.useEffect(()=>{if(!document.querySelectorAll("[nosto-client-script]").length){const m=document.createElement("script");m.type="text/javascript",m.src="//"+(n||"connect.nosto.com")+"/include/"+s,m.async=!0,m.setAttribute("nosto-client-script",""),m.onload=()=>{console.log("Nosto client script loaded"),a(!0)},document.head.appendChild(m)}window.nostojs=m=>(window.nostojs.q=window.nostojs.q||[]).push(m),window.nostojs(m=>m.setAutoLoad(!1))},[]),c(S.Provider,{value:{account:s,clientScriptLoaded:y,currentVariation:e,renderFunction:l,responseMode:C},children:o})};var M=Object.prototype.hasOwnProperty;function L(s,e,r){for(r of s.keys())if(h(r,e))return r}function h(s,e){var r,n,o;if(s===e)return!0;if(s&&e&&(r=s.constructor)===e.constructor){if(r===Date)return s.getTime()===e.getTime();if(r===RegExp)return s.toString()===e.toString();if(r===Array){if((n=s.length)===e.length)for(;n--&&h(s[n],e[n]););return n===-1}if(r===Set){if(s.size!==e.size)return!1;for(n of s)if(o=n,o&&typeof o=="object"&&(o=L(e,o),!o)||!e.has(o))return!1;return!0}if(r===Map){if(s.size!==e.size)return!1;for(n of s)if(o=n[0],o&&typeof o=="object"&&(o=L(e,o),!o)||!h(n[1],e.get(o)))return!1;return!0}if(r===ArrayBuffer)s=new Uint8Array(s),e=new Uint8Array(e);else if(r===DataView){if((n=s.byteLength)===e.byteLength)for(;n--&&s.getInt8(n)===e.getInt8(n););return n===-1}if(ArrayBuffer.isView(s)){if((n=s.byteLength)===e.byteLength)for(;n--&&s[n]===e[n];);return n===-1}if(!r||typeof s=="object"){n=0;for(r in s)if(M.call(s,r)&&++n&&!M.call(e,r)||!(r in e)||!h(s[r],e[r]))return!1;return Object.keys(e).length===n}}return s!==s&&e!==e}function Y(s){var e=N.useRef(s),r=N.useRef(0);return h(s,e.current)||(e.current=s,r.current+=1),N.useMemo(function(){return e.current},[r.current])}function Z(s,e){return N.useEffect(s,Y(e))}const K=({cart:s,customer:e})=>{const{clientScriptLoaded:r}=p();return Z(()=>{const n=s?j(s):void 0,o=e?j(e):void 0;r&&window.nostojs(l=>{l.defaultSession().setResponseMode("HTML").setCart(n).setCustomer(o).viewOther().load()})},[r,s||[],e||{}]),c(u,{})};i.Nosto404=H,i.NostoCategory=b,i.NostoCheckout=D,i.NostoContext=S,i.NostoHome=J,i.NostoOrder=G,i.NostoOther=I,i.NostoPlacement=$,i.NostoProduct=U,i.NostoProvider=W,i.NostoSearch=z,i.NostoSession=K,i.useNostoContext=p,Object.defineProperties(i,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
9
+ */var H=R.default,$=Symbol.for("react.element"),G=Symbol.for("react.fragment"),z=Object.prototype.hasOwnProperty,J=H.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,W={key:!0,ref:!0,__self:!0,__source:!0};function A(t,n,e){var r,c={},d=null,i=null;e!==void 0&&(d=""+e),n.key!==void 0&&(d=""+n.key),n.ref!==void 0&&(i=n.ref);for(r in n)z.call(n,r)&&!W.hasOwnProperty(r)&&(c[r]=n[r]);if(t&&t.defaultProps)for(r in n=t.defaultProps,n)c[r]===void 0&&(c[r]=n[r]);return{$$typeof:$,type:t,key:d,ref:i,props:c,_owner:J.current}}b.Fragment=G,b.jsx=A,b.jsxs=A,E.exports=b;const s=E.exports.jsx,w=E.exports.jsxs,_=E.exports.Fragment;function B(){const{clientScriptLoaded:t,currentVariation:n,responseMode:e,recommendationComponent:r,useRenderCampaigns:c}=h(),{renderCampaigns:d,pageTypeUpdated:i}=c("404");return m.useEffect(()=>{t&&i&&window.nostojs(a=>{a.defaultSession().setVariation(n).setResponseMode(e).viewNotFound().setPlacements(a.placements.getPlacements()).load().then(p=>{d(p,a)})})},[t,n,r,i]),s(_,{children:s("div",{className:"nosto_page_type",style:{display:"none"},children:"notfound"})})}function Y(){const{clientScriptLoaded:t,currentVariation:n,responseMode:e,recommendationComponent:r,useRenderCampaigns:c}=h(),{renderCampaigns:d,pageTypeUpdated:i}=c("other");return m.useEffect(()=>{t&&i&&window.nostojs(a=>{a.defaultSession().setVariation(n).setResponseMode(e).viewOther().setPlacements(a.placements.getPlacements()).load().then(p=>{d(p,a)})})},[t,n,r,i]),s(_,{children:s("div",{className:"nosto_page_type",style:{display:"none"},children:"other"})})}function Z(){const{clientScriptLoaded:t,currentVariation:n,responseMode:e,recommendationComponent:r,useRenderCampaigns:c}=h(),{renderCampaigns:d,pageTypeUpdated:i}=c("checkout");return m.useEffect(()=>{t&&i&&window.nostojs(a=>{a.defaultSession().setVariation(n).setResponseMode(e).viewCart().setPlacements(a.placements.getPlacements()).load().then(p=>{d(p,a)})})},[t,n,r,i]),s(_,{children:s("div",{className:"nosto_page_type",style:{display:"none"},children:"cart"})})}function F(t){const n=c=>String(c)==="[object Object]";if(!n(t))return!1;const e=t.constructor;if(e===void 0)return!0;const r=e.prototype;return!(!n(r)||!r.hasOwnProperty("isPrototypeOf"))}function U(t,n){if(t===n)return!0;if(t instanceof Date&&n instanceof Date)return t.getTime()===n.getTime();if(t instanceof Array&&n instanceof Array)return t.length!==n.length?!1:t.every((e,r)=>U(e,n[r]));if(F(t)&&F(n)){const e=Object.entries(t);return e.length!==Object.keys(n).length?!1:e.every(([r,c])=>U(c,n[r]))}return!1}function I(t,n){return m.useEffect(t,K(n))}function K(t){const n=m.useRef(t),e=m.useRef(0);return U(t,n.current)||(n.current=t,e.current+=1),m.useMemo(()=>n.current,[e.current])}function Q(t){const{product:n,tagging:e}=t,{clientScriptLoaded:r,currentVariation:c,responseMode:d,recommendationComponent:i,useRenderCampaigns:a}=h(),{renderCampaigns:p,pageTypeUpdated:f}=a("product");return I(()=>{r&&f&&window.nostojs(o=>{o.defaultSession().setResponseMode(d).viewProduct(n).setPlacements(o.placements.getPlacements()).load().then(y=>{p(y,o)})})},[r,c,n,i,f]),w(_,{children:[s("div",{className:"nosto_page_type",style:{display:"none"},children:"product"}),w("div",{className:"nosto_product",style:{display:"none"},children:[(e==null?void 0:e.variationId)&&s("span",{className:"variation_id",children:e.variationId}),n&&s("span",{className:"product_id",children:n}),(e==null?void 0:e.name)&&s("span",{className:"name",children:e.name}),(e==null?void 0:e.url)&&s("span",{className:"url",children:e.url.toString()}),(e==null?void 0:e.imageUrl)&&s("span",{className:"image_url",children:e.imageUrl.toString()}),(e==null?void 0:e.availability)&&s("span",{className:"availability",children:e.availability}),(e==null?void 0:e.price)&&s("span",{className:"price",children:e.price}),(e==null?void 0:e.listPrice)&&s("span",{className:"list_price",children:e.listPrice}),(e==null?void 0:e.priceCurrencyCode)&&s("span",{className:"price_currency_code",children:e.priceCurrencyCode}),(e==null?void 0:e.brand)&&s("span",{className:"brand",children:e.brand}),(e==null?void 0:e.description)&&s("span",{className:"description",children:e.description}),(e==null?void 0:e.googleCategory)&&s("span",{className:"description",children:e.googleCategory}),(e==null?void 0:e.condition)&&s("span",{className:"condition",children:e.condition}),(e==null?void 0:e.gender)&&s("span",{className:"gender",children:e.gender}),(e==null?void 0:e.ageGroup)&&s("span",{className:"age_group",children:e.ageGroup}),(e==null?void 0:e.gtin)&&s("span",{className:"gtin",children:e.gtin}),(e==null?void 0:e.category)&&(e==null?void 0:e.category.map((o,y)=>s("span",{className:"category",children:o},y))),(e==null?void 0:e.tags1)&&e.tags1.map((o,y)=>s("span",{className:"tag1",children:o},y)),(e==null?void 0:e.tags2)&&e.tags2.map((o,y)=>s("span",{className:"tag2",children:o},y)),(e==null?void 0:e.tags3)&&e.tags3.map((o,y)=>s("span",{className:"tag3",children:o},y)),(e==null?void 0:e.ratingValue)&&s("span",{className:"rating_value",children:e.ratingValue}),(e==null?void 0:e.reviewCount)&&s("span",{className:"review_count",children:e.reviewCount}),(e==null?void 0:e.alternateImageUrls)&&e.alternateImageUrls.map((o,y)=>s("span",{className:"alternate_image_url",children:o.toString()},y)),(e==null?void 0:e.customFields)&&Object.keys(e.customFields).map((o,y)=>e.customFields&&e.customFields[o]&&s("span",{className:o,children:e.customFields[o]},y)),(e==null?void 0:e.skus)&&e.skus.map((o,y)=>w("span",{className:"nosto_sku",children:[(o==null?void 0:o.id)&&s("span",{className:"product_id",children:o.id}),(o==null?void 0:o.name)&&s("span",{className:"name",children:o.name}),(o==null?void 0:o.price)&&s("span",{className:"price",children:o.price}),(o==null?void 0:o.listPrice)&&s("span",{className:"list_price",children:o.listPrice}),(o==null?void 0:o.url)&&s("span",{className:"url",children:o.url.toString()}),(o==null?void 0:o.imageUrl)&&s("span",{className:"image_url",children:o.imageUrl.toString()}),(o==null?void 0:o.gtin)&&s("span",{className:"gtin",children:o.gtin}),(o==null?void 0:o.availability)&&s("span",{className:"availability",children:o.availability}),(o==null?void 0:o.customFields)&&Object.keys(o.customFields).map((j,O)=>o.customFields&&o.customFields[j]&&s("span",{className:j,children:o.customFields[j]},O))]},y))]})]})}function X(t){const{category:n}=t,{clientScriptLoaded:e,currentVariation:r,responseMode:c,recommendationComponent:d,useRenderCampaigns:i}=h(),{renderCampaigns:a,pageTypeUpdated:p}=i("home");return m.useEffect(()=>{e&&p&&window.nostojs(f=>{f.defaultSession().setVariation(r).setResponseMode(c).viewCategory(n).setPlacements(f.placements.getPlacements()).load().then(o=>{a(o,f)})})},[e,n,r,d,p]),w(_,{children:[s("div",{className:"nosto_page_type",style:{display:"none"},children:"category"}),s("div",{className:"nosto_category",style:{display:"none"},children:n})]})}function g(t){const{query:n}=t,{clientScriptLoaded:e,currentVariation:r,responseMode:c,recommendationComponent:d,useRenderCampaigns:i}=h(),{renderCampaigns:a,pageTypeUpdated:p}=i("search");return m.useEffect(()=>{e&&p&&window.nostojs(f=>{f.defaultSession().setVariation(r).setResponseMode(c).viewSearch(n).setPlacements(f.placements.getPlacements()).load().then(o=>{a(o,f)})})},[e,r,n,d,p]),w(_,{children:[s("div",{className:"nosto_page_type",style:{display:"none"},children:"search"}),s("div",{className:"nosto_search",style:{display:"none"},children:n})]})}function P(t){return!t||typeof t!="object"||k(t)||ee(t)?t:Array.isArray(t)?t.map(P):Object.keys(t).reduce((n,e)=>{var r=e[0].toLowerCase()+e.slice(1).replace(/([A-Z]+)/g,(c,d)=>"_"+d.toLowerCase());return n[r]=P(t[e]),n},{})}function k(t){return Object.prototype.toString.call(t)==="[object Date]"}function ee(t){return Object.prototype.toString.call(t)==="[object RegExp]"}function te(t){const{order:n}=t,{clientScriptLoaded:e,currentVariation:r,responseMode:c,recommendationComponent:d,useRenderCampaigns:i}=h(),{renderCampaigns:a,pageTypeUpdated:p}=i("order");return m.useEffect(()=>{e&&p&&window.nostojs(f=>{f.defaultSession().setVariation(r).setResponseMode(c).addOrder(P(n)).setPlacements(f.placements.getPlacements()).load().then(o=>{a(o,f)})})},[e,r,d,p]),w(_,{children:[s("div",{className:"nosto_page_type",style:{display:"none"},children:"order"}),s("div",{className:"nosto_order",style:{display:"none"},children:n.purchase.number})]})}function ne(){const{clientScriptLoaded:t,currentVariation:n,responseMode:e,recommendationComponent:r,useRenderCampaigns:c}=h(),{renderCampaigns:d,pageTypeUpdated:i}=c("home");return m.useEffect(()=>{t&&i&&window.nostojs(a=>{a.defaultSession().setVariation(n).setResponseMode(e).viewFrontPage().setPlacements(a.placements.getPlacements()).load().then(p=>{d(p,a)})})},[t,n,r,i]),s(_,{children:s("div",{className:"nosto_page_type",style:{display:"none"},children:"front"})})}function oe(t){const{id:n,pageType:e}=t;return s("div",{className:"nosto_element",id:n},n+(e||""))}function se(t){let{account:n,currentVariation:e="",multiCurrency:r=!1,host:c,children:d,recommendationComponent:i,shopifyMarkets:a}=t;const[p,f]=R.default.useState(!1),o=R.default.useMemo(()=>p,[p]);e=r?e:"";const y=m.isValidElement(i)?"JSON_ORIGINAL":"HTML";function j(v){return R.default.cloneElement(i,{nostoRecommendation:v.nostoRecommendation})}const[O,ae]=m.useState(""),ce=function(v=""){const S=m.useRef({});m.useEffect(()=>{O!=v&&ae(v)},[]);const M=v==O;function l(N,C){if(y=="HTML")C.placements.injectCampaigns(N.recommendations);else{const L=N.campaigns.recommendations;for(const T in L){let ie=L[T],de="#"+T,q=()=>document.querySelector(de);q()&&(S.current[T]||(S.current[T]=x.createRoot(q())),S.current[T].render(s(j,{nostoRecommendation:ie})))}}}return{renderCampaigns:l,pageTypeUpdated:M}};return m.useEffect(()=>{var v,S,M;if(window.nostojs||(window.nostojs=l=>{(window.nostojs.q=window.nostojs.q||[]).push(l)},window.nostojs(l=>l.setAutoLoad(!1))),!document.querySelectorAll("[nosto-client-script]").length&&!a){const l=document.createElement("script");l.type="text/javascript",l.src="//"+(c||"connect.nosto.com")+"/include/"+n,l.async=!0,l.setAttribute("nosto-client-script",""),l.onload=()=>{var N;typeof jest!="undefined"&&((N=window.nosto)==null||N.reload({site:"localhost"})),f(!0)},document.body.appendChild(l)}if(a){const l=document.querySelector("[nosto-client-script]"),N=document.querySelector("#nosto-sandbox");if(!l||(l==null?void 0:l.getAttribute("nosto-language"))!=(a==null?void 0:a.language)||(l==null?void 0:l.getAttribute("nosto-market-id"))!=(a==null?void 0:a.marketId)){p&&f(!1),(v=l==null?void 0:l.parentNode)==null||v.removeChild(l),(S=N==null?void 0:N.parentNode)==null||S.removeChild(N);const C=document.createElement("script");C.type="text/javascript",C.src="//"+(c||"connect.nosto.com")+`/script/shopify/market/nosto.js?merchant=${n}&market=${a.marketId||""}&locale=${((M=a==null?void 0:a.language)==null?void 0:M.toLowerCase())||""}`,C.async=!0,C.setAttribute("nosto-client-script",""),C.setAttribute("nosto-language",(a==null?void 0:a.language)||""),C.setAttribute("nosto-market-id",String(a==null?void 0:a.marketId)),C.onload=()=>{var L;typeof jest!="undefined"&&((L=window.nosto)==null||L.reload({site:"localhost"})),f(!0)},document.body.appendChild(C)}}},[p,a]),s(V.Provider,{value:{account:n,clientScriptLoaded:o,currentVariation:e,responseMode:y,recommendationComponent:i,useRenderCampaigns:ce,pageType:O},children:d})}function re(t){const{cart:n,customer:e}=t,{clientScriptLoaded:r}=h();return I(()=>{const c=n?P(n):void 0,d=e?P(e):void 0;r&&window.nostojs(i=>{i.defaultSession().setResponseMode("HTML").setCart(c).setCustomer(d).viewOther().load()})},[r,n,e]),s(_,{})}u.Nosto404=B,u.NostoCategory=X,u.NostoCheckout=Z,u.NostoContext=V,u.NostoHome=ne,u.NostoOrder=te,u.NostoOther=Y,u.NostoPlacement=oe,u.NostoProduct=Q,u.NostoProvider=se,u.NostoSearch=g,u.NostoSession=re,u.useNostoContext=h,Object.defineProperties(u,{__esModule:{value:!0},[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": "0.2.1",
4
+ "version": "0.4.0",
5
5
  "author": "Mridang Agarwalla, Dominik Gilg",
6
6
  "license": "ISC",
7
7
  "repository": {
@@ -14,31 +14,39 @@
14
14
  ],
15
15
  "scripts": {
16
16
  "dev": "vite",
17
- "build": "tsc && vite build",
17
+ "build": "tsc && vite build && typedoc src/index.client.ts",
18
18
  "preview": "vite preview",
19
19
  "prepare": "vite build",
20
20
  "typecheck": "tsc",
21
21
  "tslint": "tslint 'src/**/*.ts?(x)'",
22
22
  "clean": "rimraf dist",
23
- "prettier": "prettier '*/**/*.{ts,tsx,js,jsx,html,css,less}' --list-different",
24
- "prettier:fix": "prettier '*/**/*.{ts,tsx,js,jsx,html,css,less}' --write"
23
+ "prettier": "prettier '{src,spec}/*/**' --list-different",
24
+ "prettier:fix": "prettier '{src,spec}/*/**' --write",
25
+ "test": "jest spec"
25
26
  },
26
27
  "files": [
27
28
  "dist",
28
29
  "src"
29
30
  ],
30
- "dependencies": {
31
- "snakeize": "^0.1.0",
32
- "use-deep-compare-effect": "^1.3.1",
33
- "@vitejs/plugin-react": "^1.3.0"
34
- },
35
31
  "devDependencies": {
32
+ "@testing-library/jest-dom": "^5.16.5",
33
+ "@testing-library/react": "^14.0.0",
34
+ "@testing-library/user-event": "^14.4.3",
35
+ "@types/jest": "^29.5.0",
36
36
  "@types/react": "^18.0.0",
37
37
  "@types/react-dom": "^18.0.0",
38
- "vite": "^2.9.9",
39
- "typescript": "^4.6.3",
38
+ "@types/user-event": "^4.1.1",
39
+ "@vitejs/plugin-react": "^1.3.0",
40
+ "jest": "^29.5.0",
41
+ "jest-environment-jsdom": "^29.5.0",
40
42
  "prettier": "^2.0.5",
41
- "rimraf": "^3.0.2"
43
+ "react": "*",
44
+ "react-dom": "*",
45
+ "rimraf": "^3.0.2",
46
+ "ts-jest": "^29.1.0",
47
+ "typedoc": "^0.24.1",
48
+ "typescript": "^4.6.3",
49
+ "vite": "^2.9.9"
42
50
  },
43
51
  "main": "./dist/index.umd.client.js",
44
52
  "module": "./dist/index.es.client.js",
@@ -53,5 +61,13 @@
53
61
  "bugs": {
54
62
  "url": "https://github.com/Nosto/nosto-react/issues"
55
63
  },
56
- "homepage": "https://github.com/Nosto/nosto-react#readme"
64
+ "homepage": "https://github.com/Nosto/nosto-react#readme",
65
+ "jest": {
66
+ "preset": "ts-jest",
67
+ "testEnvironment": "jsdom",
68
+ "testEnvironmentOptions": {
69
+ "resources": "usable",
70
+ "runScripts": "dangerously"
71
+ }
72
+ }
57
73
  }
@@ -1,14 +1,45 @@
1
- import React, { useEffect } from "react";
1
+ import { useEffect } from "react";
2
2
  import { useNostoContext } from "../Provider/context.client";
3
3
 
4
- const NostoCategory: React.FC<{ category: string }> = ({ category }) => {
5
- const { clientScriptLoaded, currentVariation, renderFunction, responseMode } =
6
- useNostoContext();
4
+ /**
5
+ * You can personalise your category and collection pages by using the NostoCategory component.
6
+ * The component requires that you provide it the the slash-delimited slug representation of the current category.
7
+ *
8
+ * By default, your account, when created, has two category placements named `categorypage-nosto-1` and `categorypage-nosto-2`.
9
+ * You may omit these and use any identifier you need. The identifiers used here are simply provided to illustrate the example.
10
+ *
11
+ * @example
12
+ * ```
13
+ * <div className="category-page">
14
+ * <NostoPlacement id="categorypage-nosto-1" />
15
+ * <NostoPlacement id="categorypage-nosto-2" />
16
+ * <NostoCategory category={category.name} />
17
+ * </div>
18
+ * ```
19
+ *
20
+ * **Note:** Be sure to pass in the correct category representation.
21
+ * If the category being viewed is `Mens >> Jackets`, you must provide the name as `/Mens/Jackets`.
22
+ * You must ensure that the category path provided here matches that of the categories tagged in your products.
23
+ *
24
+ * @group Personalisation Components
25
+ */
26
+ export default function NostoCategory(props: {
27
+ category: string;
28
+ }): JSX.Element {
29
+ const { category } = props;
30
+ const {
31
+ clientScriptLoaded,
32
+ currentVariation,
33
+ responseMode,
34
+ recommendationComponent,
35
+ useRenderCampaigns,
36
+ } = useNostoContext();
37
+
38
+ const { renderCampaigns, pageTypeUpdated } = useRenderCampaigns("home");
7
39
 
8
40
  useEffect(() => {
9
- // @ts-ignore
10
- if (clientScriptLoaded) {
11
- window.nostojs((api: any) => {
41
+ if (clientScriptLoaded && pageTypeUpdated) {
42
+ window.nostojs((api) => {
12
43
  api
13
44
  .defaultSession()
14
45
  .setVariation(currentVariation)
@@ -16,18 +47,18 @@ const NostoCategory: React.FC<{ category: string }> = ({ category }) => {
16
47
  .viewCategory(category)
17
48
  .setPlacements(api.placements.getPlacements())
18
49
  .load()
19
- .then((data: object) => {
20
- if (responseMode == "HTML") {
21
- // @ts-ignore
22
- api.placements.injectCampaigns(data.recommendations);
23
- } else {
24
- // @ts-ignore
25
- renderFunction(data.campaigns);
26
- }
50
+ .then((data) => {
51
+ renderCampaigns(data, api);
27
52
  });
28
53
  });
29
54
  }
30
- }, [clientScriptLoaded, category, currentVariation, renderFunction]);
55
+ }, [
56
+ clientScriptLoaded,
57
+ category,
58
+ currentVariation,
59
+ recommendationComponent,
60
+ pageTypeUpdated,
61
+ ]);
31
62
 
32
63
  return (
33
64
  <>
@@ -39,6 +70,4 @@ const NostoCategory: React.FC<{ category: string }> = ({ category }) => {
39
70
  </div>
40
71
  </>
41
72
  );
42
- };
43
-
44
- export default NostoCategory;
73
+ }
@@ -1,14 +1,40 @@
1
- import React, { useEffect } from "react";
1
+ import { useEffect } from "react";
2
2
  import { useNostoContext } from "../Provider/context.client";
3
3
 
4
- const NostoCheckout: React.FC = () => {
5
- const { clientScriptLoaded, currentVariation, renderFunction, responseMode } =
6
- useNostoContext();
4
+ /**
5
+ * You can personalise your cart and checkout pages by using the NostoCheckout component.
6
+ * The component does not require any props.
7
+ *
8
+ * By default, your account, when created, has two cart-page placements named `categorypage-nosto-1` and `categorypage-nosto-2`.
9
+ * You may omit these and use any identifier you need.
10
+ * The identifiers used here are simply provided to illustrate the example.
11
+ *
12
+ * @example
13
+ * ```
14
+ * <div className="checkout-page">
15
+ * <NostoPlacement id="checkout-nosto-1" />
16
+ * <NostoPlacement id="checkout-nosto-2" />
17
+ * <NostoCheckout />
18
+ * </div>
19
+ * ```
20
+ *
21
+ * @group Personalisation Components
22
+ */
23
+
24
+ export default function NostoCheckout(): JSX.Element {
25
+ const {
26
+ clientScriptLoaded,
27
+ currentVariation,
28
+ responseMode,
29
+ recommendationComponent,
30
+ useRenderCampaigns,
31
+ } = useNostoContext();
32
+
33
+ const { renderCampaigns, pageTypeUpdated } = useRenderCampaigns("checkout");
7
34
 
8
35
  useEffect(() => {
9
- // @ts-ignore
10
- if (clientScriptLoaded) {
11
- window.nostojs((api: any) => {
36
+ if (clientScriptLoaded && pageTypeUpdated) {
37
+ window.nostojs((api) => {
12
38
  api
13
39
  .defaultSession()
14
40
  .setVariation(currentVariation)
@@ -16,18 +42,17 @@ const NostoCheckout: React.FC = () => {
16
42
  .viewCart()
17
43
  .setPlacements(api.placements.getPlacements())
18
44
  .load()
19
- .then((data: object) => {
20
- if (responseMode == "HTML") {
21
- // @ts-ignore
22
- api.placements.injectCampaigns(data.recommendations);
23
- } else {
24
- // @ts-ignore
25
- renderFunction(data.campaigns);
26
- }
45
+ .then((data) => {
46
+ renderCampaigns(data, api);
27
47
  });
28
48
  });
29
49
  }
30
- }, [clientScriptLoaded, currentVariation, renderFunction]);
50
+ }, [
51
+ clientScriptLoaded,
52
+ currentVariation,
53
+ recommendationComponent,
54
+ pageTypeUpdated,
55
+ ]);
31
56
 
32
57
  return (
33
58
  <>
@@ -36,6 +61,4 @@ const NostoCheckout: React.FC = () => {
36
61
  </div>
37
62
  </>
38
63
  );
39
- };
40
-
41
- export default NostoCheckout;
64
+ }
@@ -1,14 +1,40 @@
1
- import React, { useEffect } from "react";
1
+ import { useEffect } from "react";
2
2
  import { useNostoContext } from "../Provider/context.client";
3
3
 
4
- const NostoFohofo: React.FC = () => {
5
- const { clientScriptLoaded, currentVariation, renderFunction, responseMode } =
6
- useNostoContext();
4
+ /**
5
+ * You can personalise your cart and checkout pages by using the `Nosto404` component.
6
+ * The component does not require any props.
7
+ *
8
+ * By default, your account, when created, has three 404-page placements named `notfound-nosto-1`, `notfound-nosto-2` and `notfound-nosto-3`.
9
+ * You may omit these and use any identifier you need.
10
+ * The identifiers used here are simply provided to illustrate the example.
11
+ *
12
+ * @example
13
+ * ```
14
+ * <div className="notfound-page">
15
+ * <NostoPlacement id="notfound-nosto-1" />
16
+ * <NostoPlacement id="notfound-nosto-2" />
17
+ * <NostoPlacement id="notfound-nosto-3" />
18
+ * <Nosto404 />
19
+ * </div>
20
+ * ```
21
+ *
22
+ * @group Personalisation Components
23
+ */
24
+ export default function Nosto404(): JSX.Element {
25
+ const {
26
+ clientScriptLoaded,
27
+ currentVariation,
28
+ responseMode,
29
+ recommendationComponent,
30
+ useRenderCampaigns,
31
+ } = useNostoContext();
32
+
33
+ const { renderCampaigns, pageTypeUpdated } = useRenderCampaigns("404");
7
34
 
8
35
  useEffect(() => {
9
- // @ts-ignore
10
- if (clientScriptLoaded) {
11
- window.nostojs((api: any) => {
36
+ if (clientScriptLoaded && pageTypeUpdated) {
37
+ window.nostojs((api) => {
12
38
  api
13
39
  .defaultSession()
14
40
  .setVariation(currentVariation)
@@ -16,18 +42,17 @@ const NostoFohofo: React.FC = () => {
16
42
  .viewNotFound()
17
43
  .setPlacements(api.placements.getPlacements())
18
44
  .load()
19
- .then((data: object) => {
20
- if (responseMode == "HTML") {
21
- // @ts-ignore
22
- api.placements.injectCampaigns(data.recommendations);
23
- } else {
24
- // @ts-ignore
25
- renderFunction(data.campaigns);
26
- }
45
+ .then((data) => {
46
+ renderCampaigns(data, api);
27
47
  });
28
48
  });
29
49
  }
30
- }, [clientScriptLoaded, currentVariation, renderFunction]);
50
+ }, [
51
+ clientScriptLoaded,
52
+ currentVariation,
53
+ recommendationComponent,
54
+ pageTypeUpdated,
55
+ ]);
31
56
 
32
57
  return (
33
58
  <>
@@ -36,6 +61,4 @@ const NostoFohofo: React.FC = () => {
36
61
  </div>
37
62
  </>
38
63
  );
39
- };
40
-
41
- export default NostoFohofo;
64
+ }
@@ -1,14 +1,43 @@
1
- import React, { useEffect } from "react";
1
+ import { useEffect } from "react";
2
2
  import { useNostoContext } from "../Provider/context.client";
3
3
 
4
- const NostoHome: React.FC = () => {
5
- const { clientScriptLoaded, currentVariation, renderFunction, responseMode } =
6
- useNostoContext();
4
+ /**
5
+ * The `NostoHome` component must be used to personalise the home page. The component does not require any props.
6
+ *
7
+ * By default, your account, when created, has four front-page placements named `frontpage-nosto-1`, `frontpage-nosto-2`, `frontpage-nosto-3` and `frontpage-nosto-4`.
8
+ * You may omit these and use any identifier you need.
9
+ * The identifiers used here are simply provided to illustrate the example.
10
+ *
11
+ * The `<NostoHome \>` component needs to be added after the placements.
12
+ * Content and recommendations will be rendered through this component.
13
+ *
14
+ * @example
15
+ * ```
16
+ * <div className="front-page">
17
+ * <NostoPlacement id="frontpage-nosto-1" />
18
+ * <NostoPlacement id="frontpage-nosto-2" />
19
+ * <NostoPlacement id="frontpage-nosto-3" />
20
+ * <NostoPlacement id="frontpage-nosto-4" />
21
+ * <NostoHome />
22
+ * </div>
23
+ * ```
24
+ *
25
+ * @group Personalisation Components
26
+ */
27
+ export default function NostoHome(): JSX.Element {
28
+ const {
29
+ clientScriptLoaded,
30
+ currentVariation,
31
+ responseMode,
32
+ recommendationComponent,
33
+ useRenderCampaigns,
34
+ } = useNostoContext();
35
+
36
+ const { renderCampaigns, pageTypeUpdated } = useRenderCampaigns("home");
7
37
 
8
38
  useEffect(() => {
9
- // @ts-ignore
10
- if (clientScriptLoaded) {
11
- window.nostojs((api: any) => {
39
+ if (clientScriptLoaded && pageTypeUpdated) {
40
+ window.nostojs((api) => {
12
41
  api
13
42
  .defaultSession()
14
43
  .setVariation(currentVariation)
@@ -16,18 +45,17 @@ const NostoHome: React.FC = () => {
16
45
  .viewFrontPage()
17
46
  .setPlacements(api.placements.getPlacements())
18
47
  .load()
19
- .then((data: object) => {
20
- if (responseMode == "HTML") {
21
- // @ts-ignore
22
- api.placements.injectCampaigns(data.recommendations);
23
- } else {
24
- // @ts-ignore
25
- renderFunction(data.campaigns);
26
- }
48
+ .then((data) => {
49
+ renderCampaigns(data, api);
27
50
  });
28
51
  });
29
52
  }
30
- }, [clientScriptLoaded, currentVariation, renderFunction]);
53
+ }, [
54
+ clientScriptLoaded,
55
+ currentVariation,
56
+ recommendationComponent,
57
+ pageTypeUpdated,
58
+ ]);
31
59
 
32
60
  return (
33
61
  <>
@@ -36,6 +64,4 @@ const NostoHome: React.FC = () => {
36
64
  </div>
37
65
  </>
38
66
  );
39
- };
40
-
41
- export default NostoHome;
67
+ }
@@ -1,20 +1,44 @@
1
1
  import { Purchase } from "../../types";
2
- import React, { useEffect } from "react";
3
- import snakeize from "snakeize";
2
+ import { useEffect } from "react";
4
3
  import { useNostoContext } from "../Provider/context.client";
4
+ import { snakeize } from "../../utils/snakeize";
5
5
 
6
- export interface OrderProps {
7
- purchase: Purchase;
8
- }
6
+ /**
7
+ * You can personalise your order-confirmation/thank-you page by using the `NostoOrder` component.
8
+ * The component requires that you provide it with the details of the order.
9
+ *
10
+ * By default, your account, when created, has one other-page placement named `thankyou-nosto-1`.
11
+ * You may omit this and use any identifier you need. The identifier used here is simply provided to illustrate the example.
12
+ *
13
+ * The order prop requires a value that adheres to the type `Purchase`.
14
+ *
15
+ * @example
16
+ * ```
17
+ * <div className="thankyou-page">
18
+ * <NostoPlacement id="thankyou-nosto-1" />
19
+ * <NostoOrder order={{ purchase: toOrder(order) }} />
20
+ * </div>
21
+ * ```
22
+ *
23
+ * @group Personalisation Components
24
+ */
25
+ export default function NostoOrder(props: {
26
+ order: { purchase: Purchase };
27
+ }): JSX.Element {
28
+ const { order } = props;
29
+ const {
30
+ clientScriptLoaded,
31
+ currentVariation,
32
+ responseMode,
33
+ recommendationComponent,
34
+ useRenderCampaigns,
35
+ } = useNostoContext();
9
36
 
10
- const NostoOrder: React.FC<{ order: OrderProps }> = ({ order }) => {
11
- const { clientScriptLoaded, currentVariation, renderFunction, responseMode } =
12
- useNostoContext();
37
+ const { renderCampaigns, pageTypeUpdated } = useRenderCampaigns("order");
13
38
 
14
39
  useEffect(() => {
15
- // @ts-ignore
16
- if (clientScriptLoaded) {
17
- window.nostojs((api: any) => {
40
+ if (clientScriptLoaded && pageTypeUpdated) {
41
+ window.nostojs((api) => {
18
42
  api
19
43
  .defaultSession()
20
44
  .setVariation(currentVariation)
@@ -22,18 +46,17 @@ const NostoOrder: React.FC<{ order: OrderProps }> = ({ order }) => {
22
46
  .addOrder(snakeize(order))
23
47
  .setPlacements(api.placements.getPlacements())
24
48
  .load()
25
- .then((data: object) => {
26
- if (responseMode == "HTML") {
27
- // @ts-ignore
28
- api.placements.injectCampaigns(data.recommendations);
29
- } else {
30
- // @ts-ignore
31
- renderFunction(data.campaigns);
32
- }
49
+ .then((data) => {
50
+ renderCampaigns(data, api);
33
51
  });
34
52
  });
35
53
  }
36
- }, [clientScriptLoaded, currentVariation, renderFunction]);
54
+ }, [
55
+ clientScriptLoaded,
56
+ currentVariation,
57
+ recommendationComponent,
58
+ pageTypeUpdated,
59
+ ]);
37
60
 
38
61
  return (
39
62
  <>
@@ -45,6 +68,4 @@ const NostoOrder: React.FC<{ order: OrderProps }> = ({ order }) => {
45
68
  </div>
46
69
  </>
47
70
  );
48
- };
49
-
50
- export default NostoOrder;
71
+ }
@@ -1,14 +1,39 @@
1
1
  import React, { useEffect } from "react";
2
2
  import { useNostoContext } from "../Provider/context.client";
3
3
 
4
- const NostoOther: React.FC = () => {
5
- const { clientScriptLoaded, currentVariation, renderFunction, responseMode } =
6
- useNostoContext();
4
+ /**
5
+ * You can personalise your miscellaneous pages by using the NostoOther component.
6
+ * The component does not require any props.
7
+ *
8
+ * By default, your account, when created, has two other-page placements named `other-nosto-1` and `other-nosto-2`.
9
+ * You may omit these and use any identifier you need.
10
+ * The identifiers used here are simply provided to illustrate the example.
11
+ *
12
+ * @example
13
+ * ```
14
+ * <div className="other-page">
15
+ * <NostoPlacement id="other-nosto-1" />
16
+ * <NostoPlacement id="other-nosto-2" />
17
+ * <NostoOther />
18
+ * </div>;
19
+ * ```
20
+ *
21
+ * @group Personalisation Components
22
+ */
23
+ export default function NostoOther(): JSX.Element {
24
+ const {
25
+ clientScriptLoaded,
26
+ currentVariation,
27
+ responseMode,
28
+ recommendationComponent,
29
+ useRenderCampaigns,
30
+ } = useNostoContext();
31
+
32
+ const { renderCampaigns, pageTypeUpdated } = useRenderCampaigns("other");
7
33
 
8
34
  useEffect(() => {
9
- // @ts-ignore
10
- if (clientScriptLoaded) {
11
- window.nostojs((api: any) => {
35
+ if (clientScriptLoaded && pageTypeUpdated) {
36
+ window.nostojs((api) => {
12
37
  api
13
38
  .defaultSession()
14
39
  .setVariation(currentVariation)
@@ -16,18 +41,17 @@ const NostoOther: React.FC = () => {
16
41
  .viewOther()
17
42
  .setPlacements(api.placements.getPlacements())
18
43
  .load()
19
- .then((data: object) => {
20
- if (responseMode == "HTML") {
21
- // @ts-ignore
22
- api.placements.injectCampaigns(data.recommendations);
23
- } else {
24
- // @ts-ignore
25
- renderFunction(data.campaigns);
26
- }
44
+ .then((data) => {
45
+ renderCampaigns(data, api);
27
46
  });
28
47
  });
29
48
  }
30
- }, [clientScriptLoaded, currentVariation, renderFunction]);
49
+ }, [
50
+ clientScriptLoaded,
51
+ currentVariation,
52
+ recommendationComponent,
53
+ pageTypeUpdated,
54
+ ]);
31
55
 
32
56
  return (
33
57
  <>
@@ -36,6 +60,4 @@ const NostoOther: React.FC = () => {
36
60
  </div>
37
61
  </>
38
62
  );
39
- };
40
-
41
- export default NostoOther;
63
+ }