@nosto/nosto-react 2.2.1 → 2.3.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/LICENSE +1 -1
- package/dist/index.d.ts +23 -192
- package/dist/index.es.js +249 -221
- package/dist/index.umd.js +1 -1
- package/package.json +20 -17
- package/src/components/Nosto404.tsx +2 -25
- package/src/components/NostoCategory.tsx +2 -30
- package/src/components/NostoCheckout.tsx +2 -25
- package/src/components/NostoHome.tsx +2 -26
- package/src/components/NostoOrder.tsx +2 -33
- package/src/components/NostoOther.tsx +2 -25
- package/src/components/NostoPlacement.tsx +1 -1
- package/src/components/NostoProduct.tsx +2 -32
- package/src/components/NostoProvider.tsx +5 -9
- package/src/components/NostoSearch.tsx +2 -30
- package/src/components/NostoSession.tsx +2 -42
- package/src/context.ts +2 -2
- package/src/hooks/scriptLoader.ts +4 -4
- package/src/hooks/useDeepCompareEffect.ts +1 -4
- package/src/hooks/useLoadClientScript.ts +26 -17
- package/src/hooks/useNosto404.tsx +25 -0
- package/src/hooks/useNostoApi.ts +4 -7
- package/src/hooks/useNostoCategory.tsx +31 -0
- package/src/hooks/useNostoCheckout.tsx +25 -0
- package/src/hooks/useNostoContext.ts +2 -3
- package/src/hooks/useNostoHome.tsx +25 -0
- package/src/hooks/useNostoOrder.tsx +35 -0
- package/src/hooks/useNostoOther.tsx +25 -0
- package/src/hooks/useNostoProduct.tsx +43 -0
- package/src/hooks/useNostoSearch.tsx +31 -0
- package/src/hooks/useNostoSession.tsx +34 -0
- package/src/hooks/useRenderCampaigns.tsx +12 -9
- package/src/index.ts +23 -3
- package/src/types.ts +1 -923
- package/src/utils/types.ts +5 -3
- package/src/components/helpers.ts +0 -3
- package/src/components/index.ts +0 -11
- package/src/hooks/index.ts +0 -5
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useNostoApi } from "./useNostoApi"
|
|
2
|
+
import { useRenderCampaigns } from "./useRenderCampaigns"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @group Hooks
|
|
6
|
+
*/
|
|
7
|
+
export type NostoCategoryProps = {
|
|
8
|
+
category: string
|
|
9
|
+
placements?: string[]
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* You can personalise your category and collection pages by using the useNostoCategory hook.
|
|
14
|
+
*
|
|
15
|
+
* @group Hooks
|
|
16
|
+
*/
|
|
17
|
+
export function useNostoCategory({ category, placements }: NostoCategoryProps) {
|
|
18
|
+
const { renderCampaigns } = useRenderCampaigns()
|
|
19
|
+
|
|
20
|
+
useNostoApi(
|
|
21
|
+
async api => {
|
|
22
|
+
const data = await api
|
|
23
|
+
.defaultSession()
|
|
24
|
+
.viewCategory(category)
|
|
25
|
+
.setPlacements(placements || api.placements.getPlacements())
|
|
26
|
+
.load()
|
|
27
|
+
renderCampaigns(data)
|
|
28
|
+
},
|
|
29
|
+
[category]
|
|
30
|
+
)
|
|
31
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useNostoApi } from "./useNostoApi"
|
|
2
|
+
import { useRenderCampaigns } from "./useRenderCampaigns"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @group Hooks
|
|
6
|
+
*/
|
|
7
|
+
export type NostoCheckoutProps = { placements?: string[] }
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* You can personalise your cart and checkout pages by using the useNostoCheckout hook.
|
|
11
|
+
*
|
|
12
|
+
* @group Hooks
|
|
13
|
+
*/
|
|
14
|
+
export function useNostoCheckout(props?: NostoCheckoutProps) {
|
|
15
|
+
const { renderCampaigns } = useRenderCampaigns()
|
|
16
|
+
|
|
17
|
+
useNostoApi(async api => {
|
|
18
|
+
const data = await api
|
|
19
|
+
.defaultSession()
|
|
20
|
+
.viewCart()
|
|
21
|
+
.setPlacements(props?.placements || api.placements.getPlacements())
|
|
22
|
+
.load()
|
|
23
|
+
renderCampaigns(data)
|
|
24
|
+
})
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useNostoApi } from "./useNostoApi"
|
|
2
|
+
import { useRenderCampaigns } from "./useRenderCampaigns"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @group Hooks
|
|
6
|
+
*/
|
|
7
|
+
export type NostoHomeProps = { placements?: string[] }
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* You can personalise your home page by using the useNostoHome hook.
|
|
11
|
+
*
|
|
12
|
+
* @group Hooks
|
|
13
|
+
*/
|
|
14
|
+
export function useNostoHome(props?: NostoHomeProps) {
|
|
15
|
+
const { renderCampaigns } = useRenderCampaigns()
|
|
16
|
+
|
|
17
|
+
useNostoApi(async api => {
|
|
18
|
+
const data = await api
|
|
19
|
+
.defaultSession()
|
|
20
|
+
.viewFrontPage()
|
|
21
|
+
.setPlacements(props?.placements || api.placements.getPlacements())
|
|
22
|
+
.load()
|
|
23
|
+
renderCampaigns(data)
|
|
24
|
+
})
|
|
25
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { snakeize } from "../utils/snakeize"
|
|
2
|
+
import { useRenderCampaigns } from "./useRenderCampaigns"
|
|
3
|
+
import { useNostoApi } from "./useNostoApi"
|
|
4
|
+
import { ToCamelCase } from "../utils/types"
|
|
5
|
+
import { WebsiteOrder as Order } from "@nosto/nosto-js/client"
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @group Hooks
|
|
9
|
+
*/
|
|
10
|
+
export type NostoOrderProps = {
|
|
11
|
+
order: Order | ToCamelCase<Order>
|
|
12
|
+
placements?: string[]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* You can personalise your order-confirmation/thank-you page by using the `useNostoOrder` hook.
|
|
17
|
+
*
|
|
18
|
+
* @group Hooks
|
|
19
|
+
*/
|
|
20
|
+
export function useNostoOrder({ order, placements }: NostoOrderProps) {
|
|
21
|
+
const { renderCampaigns } = useRenderCampaigns()
|
|
22
|
+
|
|
23
|
+
useNostoApi(
|
|
24
|
+
async api => {
|
|
25
|
+
const data = await api
|
|
26
|
+
.defaultSession()
|
|
27
|
+
.addOrder(snakeize(order))
|
|
28
|
+
.setPlacements(placements || api.placements.getPlacements())
|
|
29
|
+
.load()
|
|
30
|
+
renderCampaigns(data)
|
|
31
|
+
},
|
|
32
|
+
[order],
|
|
33
|
+
{ deep: true }
|
|
34
|
+
)
|
|
35
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useNostoApi } from "./useNostoApi"
|
|
2
|
+
import { useRenderCampaigns } from "./useRenderCampaigns"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @group Hooks
|
|
6
|
+
*/
|
|
7
|
+
export type NostoOtherProps = { placements?: string[] }
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* You can personalise your miscellaneous pages by using the useNostoOther hook.
|
|
11
|
+
*
|
|
12
|
+
* @group Hooks
|
|
13
|
+
*/
|
|
14
|
+
export function useNostoOther(props?: NostoOtherProps) {
|
|
15
|
+
const { renderCampaigns } = useRenderCampaigns()
|
|
16
|
+
|
|
17
|
+
useNostoApi(async api => {
|
|
18
|
+
const data = await api
|
|
19
|
+
.defaultSession()
|
|
20
|
+
.viewOther()
|
|
21
|
+
.setPlacements(props?.placements || api.placements.getPlacements())
|
|
22
|
+
.load()
|
|
23
|
+
renderCampaigns(data)
|
|
24
|
+
})
|
|
25
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useNostoApi } from "./useNostoApi"
|
|
2
|
+
import { useRenderCampaigns } from "./useRenderCampaigns"
|
|
3
|
+
import { Product } from "@nosto/nosto-js/client"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @group Hooks
|
|
7
|
+
*/
|
|
8
|
+
export type NostoProductProps = {
|
|
9
|
+
product: string
|
|
10
|
+
reference?: string
|
|
11
|
+
tagging?: Product
|
|
12
|
+
placements?: string[]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* You can personalise your product pages by using the useNostoProduct hook.
|
|
17
|
+
*
|
|
18
|
+
* @group Hooks
|
|
19
|
+
*/
|
|
20
|
+
export function useNostoProduct({ product, tagging, placements, reference }: NostoProductProps) {
|
|
21
|
+
const { renderCampaigns } = useRenderCampaigns()
|
|
22
|
+
|
|
23
|
+
if (tagging && !tagging.product_id) {
|
|
24
|
+
throw new Error("The product object must contain a product_id property")
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const productId = tagging?.product_id ?? product
|
|
28
|
+
|
|
29
|
+
useNostoApi(
|
|
30
|
+
async api => {
|
|
31
|
+
const action = api
|
|
32
|
+
.defaultSession()
|
|
33
|
+
.viewProduct(tagging ?? product)
|
|
34
|
+
.setPlacements(placements || api.placements.getPlacements())
|
|
35
|
+
if (reference) {
|
|
36
|
+
action.setRef(productId, reference)
|
|
37
|
+
}
|
|
38
|
+
const data = await action.load()
|
|
39
|
+
renderCampaigns(data)
|
|
40
|
+
},
|
|
41
|
+
[productId, tagging?.selected_sku_id]
|
|
42
|
+
)
|
|
43
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useNostoApi } from "./useNostoApi"
|
|
2
|
+
import { useRenderCampaigns } from "./useRenderCampaigns"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @group Components
|
|
6
|
+
*/
|
|
7
|
+
export type NostoSearchProps = {
|
|
8
|
+
query: string
|
|
9
|
+
placements?: string[]
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* You can personalise your search pages by using the useNostoSearch hook.
|
|
14
|
+
*
|
|
15
|
+
* @group Hooks
|
|
16
|
+
*/
|
|
17
|
+
export function useNostoSearch({ query, placements }: NostoSearchProps) {
|
|
18
|
+
const { renderCampaigns } = useRenderCampaigns()
|
|
19
|
+
|
|
20
|
+
useNostoApi(
|
|
21
|
+
async api => {
|
|
22
|
+
const data = await api
|
|
23
|
+
.defaultSession()
|
|
24
|
+
.viewSearch(query)
|
|
25
|
+
.setPlacements(placements || api.placements.getPlacements())
|
|
26
|
+
.load()
|
|
27
|
+
renderCampaigns(data)
|
|
28
|
+
},
|
|
29
|
+
[query]
|
|
30
|
+
)
|
|
31
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { snakeize } from "../utils/snakeize"
|
|
2
|
+
import { PushedCustomer as CustomerSnakeCase, Cart as CartSnakeCase } from "@nosto/nosto-js/client"
|
|
3
|
+
import { ToCamelCase } from "../utils/types"
|
|
4
|
+
import { useNostoContext } from "./useNostoContext"
|
|
5
|
+
import { useDeepCompareEffect } from "./useDeepCompareEffect"
|
|
6
|
+
import { nostojs } from "@nosto/nosto-js"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @group Hooks
|
|
10
|
+
*/
|
|
11
|
+
export type NostoSessionProps = {
|
|
12
|
+
cart?: CartSnakeCase | ToCamelCase<CartSnakeCase>
|
|
13
|
+
customer?: CustomerSnakeCase | ToCamelCase<CustomerSnakeCase>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Nosto React requires that you pass it the details of current cart contents and the details of the currently logged-in customer, if any, on every route change.
|
|
18
|
+
*
|
|
19
|
+
* @group Hooks
|
|
20
|
+
*/
|
|
21
|
+
export function useNostoSession({ cart, customer }: NostoSessionProps = {}) {
|
|
22
|
+
const { clientScriptLoaded } = useNostoContext()
|
|
23
|
+
|
|
24
|
+
useDeepCompareEffect(() => {
|
|
25
|
+
const currentCart = cart ? snakeize(cart) : undefined
|
|
26
|
+
const currentCustomer = customer ? snakeize(customer) : undefined
|
|
27
|
+
|
|
28
|
+
if (clientScriptLoaded) {
|
|
29
|
+
nostojs(api => {
|
|
30
|
+
api.defaultSession().setCart(currentCart).setCustomer(currentCustomer).viewOther().load({ skipPageViews: true })
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
}, [clientScriptLoaded, cart, customer])
|
|
34
|
+
}
|
|
@@ -1,28 +1,31 @@
|
|
|
1
1
|
import { cloneElement, useRef } from "react"
|
|
2
2
|
import { createRoot, Root } from "react-dom/client"
|
|
3
|
-
import {
|
|
3
|
+
import { Recommendation } from "../types"
|
|
4
4
|
import { useNostoContext } from "./useNostoContext"
|
|
5
5
|
import { RecommendationComponent } from "../context"
|
|
6
|
+
import { ActionResponse, API } from "@nosto/nosto-js/client"
|
|
7
|
+
import { nostojs } from "@nosto/nosto-js"
|
|
6
8
|
|
|
7
9
|
type CampaignData = Pick<ActionResponse, "campaigns" | "recommendations">
|
|
8
10
|
|
|
9
11
|
// RecommendationComponent for client-side rendering:
|
|
10
|
-
function RecommendationComponentWrapper(props: {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
function RecommendationComponentWrapper(props: {
|
|
13
|
+
recommendationComponent: RecommendationComponent
|
|
14
|
+
nostoRecommendation: Recommendation
|
|
15
|
+
}) {
|
|
14
16
|
return cloneElement(props.recommendationComponent, {
|
|
15
17
|
// eslint-disable-next-line react/prop-types
|
|
16
|
-
nostoRecommendation: props.nostoRecommendation
|
|
18
|
+
nostoRecommendation: props.nostoRecommendation
|
|
17
19
|
})
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
function injectCampaigns(data: CampaignData) {
|
|
23
|
+
// @ts-expect-error not defined
|
|
21
24
|
if (!window.nostojs) {
|
|
22
25
|
throw new Error("Nosto has not yet been initialized")
|
|
23
26
|
}
|
|
24
|
-
|
|
25
|
-
api.placements.injectCampaigns(data.recommendations)
|
|
27
|
+
nostojs(api => {
|
|
28
|
+
api.placements.injectCampaigns(data.recommendations as Parameters<API['placements']['injectCampaigns']>[0])
|
|
26
29
|
})
|
|
27
30
|
}
|
|
28
31
|
|
|
@@ -58,4 +61,4 @@ export function useRenderCampaigns() {
|
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
return { renderCampaigns }
|
|
61
|
-
}
|
|
64
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
|
-
export type {
|
|
2
|
-
export
|
|
1
|
+
export type { Product, PushedCustomer as Customer, Cart, WebsiteOrder as Order } from "@nosto/nosto-js/client"
|
|
2
|
+
export type { Recommendation } from "./types"
|
|
3
3
|
export { type ScriptLoadOptions } from "./hooks/scriptLoader"
|
|
4
4
|
export { NostoContext, type NostoContextType } from "./context"
|
|
5
|
-
export { useNostoContext } from "./hooks/useNostoContext"
|
|
5
|
+
export { useNostoContext } from "./hooks/useNostoContext"
|
|
6
|
+
export * from "./components/Nosto404"
|
|
7
|
+
export * from "./components/NostoCategory"
|
|
8
|
+
export * from "./components/NostoCheckout"
|
|
9
|
+
export * from "./components/NostoHome"
|
|
10
|
+
export * from "./components/NostoOrder"
|
|
11
|
+
export * from "./components/NostoOther"
|
|
12
|
+
export * from "./components/NostoPlacement"
|
|
13
|
+
export * from "./components/NostoProduct"
|
|
14
|
+
export * from "./components/NostoProvider"
|
|
15
|
+
export * from "./components/NostoSearch"
|
|
16
|
+
export * from "./components/NostoSession"
|
|
17
|
+
export * from "./hooks/useNosto404"
|
|
18
|
+
export * from "./hooks/useNostoCategory"
|
|
19
|
+
export * from "./hooks/useNostoCheckout"
|
|
20
|
+
export * from "./hooks/useNostoHome"
|
|
21
|
+
export * from "./hooks/useNostoOrder"
|
|
22
|
+
export * from "./hooks/useNostoOther"
|
|
23
|
+
export * from "./hooks/useNostoProduct"
|
|
24
|
+
export * from "./hooks/useNostoSearch"
|
|
25
|
+
export * from "./hooks/useNostoSession"
|