@okendo/shopify-hydrogen 2.3.2 → 2.5.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.
Files changed (29) hide show
  1. package/README.md +339 -591
  2. package/dist/cjs/index.js +1 -1
  3. package/dist/cjs/types/components/OkendoLoyalty/OkendoLoyaltyEmbeddedWidget.d.ts +9 -0
  4. package/dist/cjs/types/components/OkendoLoyalty/index.d.ts +1 -0
  5. package/dist/cjs/types/components/OkendoProvider/OkendoProvider.d.ts +23 -15
  6. package/dist/cjs/types/components/OkendoReviews/OkendoReviews.d.ts +4 -7
  7. package/dist/cjs/types/components/OkendoReviewsCarousel/OkendoReviewsCarousel.d.ts +4 -7
  8. package/dist/cjs/types/components/OkendoStarRating/OkendoStarRating.d.ts +4 -7
  9. package/dist/cjs/types/components/index.d.ts +1 -0
  10. package/dist/cjs/types/fragments/fragments.d.ts +2 -2
  11. package/dist/cjs/types/internal/OkendoWidget/OkendoWidget.d.ts +4 -2
  12. package/dist/cjs/types/internal/utils.d.ts +1 -0
  13. package/dist/esm/index.js +1 -1
  14. package/dist/esm/types/components/OkendoLoyalty/OkendoLoyaltyEmbeddedWidget.d.ts +9 -0
  15. package/dist/esm/types/components/OkendoLoyalty/index.d.ts +1 -0
  16. package/dist/esm/types/components/OkendoProvider/OkendoProvider.d.ts +23 -15
  17. package/dist/esm/types/components/OkendoReviews/OkendoReviews.d.ts +4 -7
  18. package/dist/esm/types/components/OkendoReviewsCarousel/OkendoReviewsCarousel.d.ts +4 -7
  19. package/dist/esm/types/components/OkendoStarRating/OkendoStarRating.d.ts +4 -7
  20. package/dist/esm/types/components/index.d.ts +1 -0
  21. package/dist/esm/types/fragments/fragments.d.ts +2 -2
  22. package/dist/esm/types/internal/OkendoWidget/OkendoWidget.d.ts +4 -2
  23. package/dist/esm/types/internal/utils.d.ts +1 -0
  24. package/dist/index.d.ts +45 -37
  25. package/package.json +6 -6
  26. package/dist/cjs/types/internal/OkendoContext.d.ts +0 -10
  27. package/dist/esm/types/internal/OkendoContext.d.ts +0 -10
  28. package/readme-res/okendo-star-rating-and-reviews-widgets.png +0 -0
  29. package/readme-res/okendo-star-rating-widget.png +0 -0
package/dist/cjs/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e=require("react"),t=require("@remix-run/react");const n=e.createContext(void 0),r=({children:t})=>{const[r,a]=e.useState(!1);return e.createElement(n.Provider,{value:{okendoDataLoaded:r,setOkendoDataLoaded:a}},t)},a=()=>{const t=e.useContext(n);return void 0===t?null:t},o="cdn-static.okendo.io",s=({nonce:t="",okendoProviderData:n,productUrlFormatter:r,awaited:s,cdnDomain:i})=>{const d=a(),l=e.useRef(!1);if(e.useEffect((()=>{if(n&&d?.setOkendoDataLoaded(!0),n&&s&&!l.current){const e=document.createElement("script");e.src=`https://${i||o}/reviews-widget-plus/js/okendo-reviews.js`,document.head.appendChild(e),l.current=!0}}),[n,d,s,i]),!n)return null;const{reviewsHeaderConfig:c,cssVariables:u,customCss:p,initScriptContents:m,preRenderStyleTags:g,starSymbols:v}=n,k=(u??"").replace('<style id="oke-css-vars">',"").replace("</style>",""),w=p?p.replace('<style id="oke-reviews-custom-css">',"").replace("</style>",""):"";return e.createElement(e.Fragment,null,e.createElement("script",{nonce:t,id:"oke-reviews-settings",type:"application/json",dangerouslySetInnerHTML:{__html:JSON.stringify(c)}}),e.createElement("style",{nonce:t,id:"oke-css-vars",dangerouslySetInnerHTML:{__html:k}}),w&&e.createElement("style",{nonce:t,id:"oke-reviews-custom-css",dangerouslySetInnerHTML:{__html:w}}),!s&&m&&e.createElement("script",{nonce:t,dangerouslySetInnerHTML:{__html:m}}),e.createElement("script",{nonce:t,type:"text/javascript",dangerouslySetInnerHTML:{__html:`window.okeProductUrlFormatter = ${"function"==typeof r?r.toString():"string"==typeof r?r:"(product) =>\n product && product.productHandle\n ? \"/products/\" + product.productHandle + \"/\" + (product.variantId ? '?variantId=' + product.variantId : '')\n : undefined"}`}}),g&&e.createElement("div",{dangerouslySetInnerHTML:{__html:g}}),v&&e.createElement("div",{dangerouslySetInnerHTML:{__html:v}}))};const i=({dataAttributes:t,metafieldContent:n=""})=>{const r=e.useRef(null),a=e.useRef(!1),o=function(t){const n=e.useRef();return e.useEffect((()=>{n.current=t})),n.current}(t),s=()=>{r.current&&(window.okeWidgetApi.initWidget(r.current),a.current=!0)};return e.useEffect((()=>{if(!o||t["data-oke-widget"]!==o["data-oke-widget"]||t["data-oke-star-rating"]!==o["data-oke-star-rating"]||t["data-oke-reviews-product-id"]!==o["data-oke-reviews-product-id"]||!a.current)return window.okeWidgetApi&&r.current?s():document.addEventListener("oke-script-loaded",s),()=>{document.removeEventListener("oke-script-loaded",s)}}),[t,o]),e.createElement("div",{ref:r,key:JSON.stringify(t),...t,dangerouslySetInnerHTML:n?{__html:n}:void 0})},d=/^[0-9]*$/;function l(e){if(e)return`shopify-${d.test(e)?e:e.split("/").slice(-1)[0]}`}exports.OKENDO_PRODUCT_REVIEWS_FRAGMENT='#graphql\n\tfragment OkendoReviewsSnippet on Product {\n\t\tokendoReviewsSnippet: metafield(\n\t\t\tnamespace: "$app:reviews"\n\t\t\tkey: "reviews_widget_snippet"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n',exports.OKENDO_PRODUCT_STAR_RATING_FRAGMENT='#graphql\n\tfragment OkendoStarRatingSnippet on Product {\n\t\tokendoStarRatingSnippet: metafield(\n\t\t\tnamespace: "$app:reviews"\n\t\t\tkey: "star_rating_snippet"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n',exports.OkendoProvider=({nonce:n="",okendoProviderData:a,productUrlFormatter:o,cdnDomain:i,children:d})=>e.createElement(r,null,a&&"then"in a?e.createElement(e.Suspense,null,e.createElement(t.Await,{resolve:a},(t=>e.createElement(s,{nonce:n,okendoProviderData:t,productUrlFormatter:o,cdnDomain:i,awaited:!0})))):e.createElement(s,{nonce:n,okendoProviderData:a,productUrlFormatter:o,cdnDomain:i}),d),exports.OkendoReviews=({productId:t,okendoReviewsSnippet:n,placeholder:r})=>{const o=a(),s=t?.length?l(t):null,d=t?.length?n:null,c={"data-oke-widget":"","data-oke-reviews-product-id":s};return null===o||o.okendoDataLoaded?e.createElement(i,{dataAttributes:c,metafieldContent:d?.value}):r||e.createElement("div",{style:{height:"350px"}})},exports.OkendoReviewsCarousel=({productId:t,groupId:n,headerBadgeUrl:r,placeholder:o})=>{const s=a(),d={"data-oke-carousel":"","data-oke-reviews-product-id":t?.length?l(t):null,"data-oke-reviews-group-id":n?.length?n:null,"data-oke-header-badge-url":r};return null===s||s.okendoDataLoaded?e.createElement(i,{dataAttributes:d}):o||e.createElement("div",{style:{height:"350px"}})},exports.OkendoStarRating=({productId:t,okendoStarRatingSnippet:n,placeholder:r})=>{const o=a(),s={"data-oke-star-rating":"","data-oke-reviews-product-id":l(t)};return null===o||o.okendoDataLoaded?e.createElement(i,{dataAttributes:s,metafieldContent:n?.value}):r||e.createElement("div",{style:{height:"20px"}})},exports.getOkendoProviderData=async({context:e,subscriberId:t,apiDomain:n,cdnDomain:r})=>{const a=`https://${n||"api.okendo.io/v1"}/stores/${t}/widget_plus_settings`,s=await fetch(a);if(!s.ok)return console.error(`Failed to retrieve subscriber settings for subscriber ID '${t}'.`),null;const{reviewsHeaderConfig:i,cssVariables:d,customCss:l,starSymbols:c}=await s.json(),u=await fetch(`https://${r||o}/reviews-widget-plus/js/okendo-reviews.js`);if(!u.ok)return console.error("Failed to retrieve widget initialisation script."),null;const p=await u.text(),{shop:{widgetPreRenderStyleTags:m}}=await e.storefront.query('#graphql\n\t\tquery metafields {\n\t\t\tshop {\n\t\t\t\twidgetPreRenderStyleTags: metafield(\n\t\t\t\t\tnamespace: "$app:reviews"\n\t\t\t\t\tkey: "widget_pre_render_style_tags"\n\t\t\t\t) {\n\t\t\t\t\tvalue\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t'),g=m?.value??"";return g||console.warn("Failed to retrieve pre-rendered widget style settings."),{reviewsHeaderConfig:i,cssVariables:d,customCss:l,initScriptContents:p,preRenderStyleTags:g,starSymbols:c}};
1
+ "use strict";var e=require("react-router"),t=require("react");const n=/^[0-9]*$/,r="app--1576377";function s(e){if(e)return`shopify-${n.test(e)?e:e.split("/").slice(-1)[0]}`}const a="cdn-static.okendo.io",o=({nonce:e="",okendoProviderData:n,productUrlFormatter:r,cdnDomain:s})=>{const o=t.useRef(!1),i=t.useRef(!1);if(t.useEffect((()=>{if(n&&n.loyaltySettings&&!1===o.current){const e=document.createElement("script");e.src=`https://${s||a}/loyalty/js/init-onsite.js`,document.head.appendChild(e);const t=document.createElement("script");t.type="application/json",t.id="oke-loyalty-settings";const r=n.loyaltySettings?n.loyaltySettings.replace('<script type="application/json" id="oke-loyalty-settings">',"").replace('<\/script><script src="https://rhys-cdn.okendo.dev/loyalty/js/init-onsite.js" defer><\/script>',""):"";t.innerHTML=r,document.head.appendChild(t),o.current=!0}}),[n,s]),t.useEffect((()=>{if(n&&!i.current){const e=document.createElement("script");e.src=`https://${s||a}/reviews-widget-plus/js/okendo-reviews.js`,document.head.appendChild(e),i.current=!0}}),[n,s]),!n)return null;const{reviewsHeaderConfig:d,cssVariables:l,customCss:c,preRenderStyleTags:u,starSymbols:p}=n,y=(l??"").replace('<style id="oke-css-vars">',"").replace("</style>",""),m=c?c.replace('<style id="oke-reviews-custom-css">',"").replace("</style>",""):"";return t.createElement(t.Fragment,null,t.createElement("script",{nonce:e,id:"oke-reviews-settings",type:"application/json",dangerouslySetInnerHTML:{__html:JSON.stringify(d)}}),t.createElement("style",{nonce:e,id:"oke-css-vars",dangerouslySetInnerHTML:{__html:y}}),m&&t.createElement("style",{nonce:e,id:"oke-reviews-custom-css",dangerouslySetInnerHTML:{__html:m}}),t.createElement("script",{nonce:e,type:"text/javascript",dangerouslySetInnerHTML:{__html:`window.okeProductUrlFormatter = ${"function"==typeof r?r.toString():"string"==typeof r?r:"(product) =>\n product && product.productHandle\n ? \"/products/\" + product.productHandle + \"/\" + (product.variantId ? '?variantId=' + product.variantId : '')\n : undefined"}`}}),u&&t.createElement("div",{dangerouslySetInnerHTML:{__html:u}}),p&&t.createElement("div",{dangerouslySetInnerHTML:{__html:p}}))};const i=({style:e,className:n,dataAttributes:r,metafieldContent:s=""})=>{const a=t.useRef(null),o=t.useRef(!1),i=function(e){const n=t.useRef();return t.useEffect((()=>{n.current=e})),n.current}(r),d=()=>{a.current&&(window.okeWidgetApi.initWidget(a.current),o.current=!0)};return t.useEffect((()=>{if(!i||r["data-oke-widget"]!==i["data-oke-widget"]||r["data-oke-star-rating"]!==i["data-oke-star-rating"]||r["data-oke-reviews-product-id"]!==i["data-oke-reviews-product-id"]||!o.current)return window.okeWidgetApi&&a.current?d():document.addEventListener("oke-script-loaded",d),()=>{document.removeEventListener("oke-script-loaded",d)}}),[r,i]),t.createElement("div",{ref:a,style:e,className:n,key:JSON.stringify(r),...r,dangerouslySetInnerHTML:s?{__html:s}:void 0})},d=`#graphql\n\tfragment OkendoStarRatingSnippet on Product {\n\t\tokendoStarRatingSnippet: metafield(\n\t\t\tnamespace: "${r}--reviews"\n\t\t\tkey: "star_rating_snippet"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n`,l=`#graphql\n\tfragment OkendoReviewsSnippet on Product {\n\t\tokendoReviewsSnippet: metafield(\n\t\t\tnamespace: "${r}--reviews"\n\t\t\tkey: "reviews_widget_snippet"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n`;exports.OKENDO_PRODUCT_REVIEWS_FRAGMENT=l,exports.OKENDO_PRODUCT_STAR_RATING_FRAGMENT=d,exports.OkendoLoyaltyEmbeddedWidget=function(){const n=e.useLocation();return t.useEffect((()=>{window?.okeLoyaltyApi?.initialiseWidgets()}),[n.pathname]),t.createElement("div",{"data-oke-loyalty-embedded-widget":""})},exports.OkendoProvider=({nonce:n="",okendoProviderData:r,customerAccessToken:s,productUrlFormatter:a,cdnDomain:i,children:d})=>t.createElement(t.Fragment,null,t.createElement(t.Suspense,null,t.createElement(e.Await,{resolve:r},(e=>t.createElement(o,{nonce:n,okendoProviderData:e,productUrlFormatter:a,cdnDomain:i})))),s&&t.createElement("script",{nonce:n,id:"oke-loyalty-customer-access-token",type:"application/json",dangerouslySetInnerHTML:{__html:JSON.stringify({customerAccessToken:s})}}),d),exports.OkendoReviews=({style:e,className:n,productId:r,okendoReviewsSnippet:a})=>{const o=r?.length?s(r):null,d=r?.length?a:null,l={"data-oke-widget":"","data-oke-reviews-product-id":o};return t.createElement(i,{style:e,className:n,dataAttributes:l,metafieldContent:d?.value})},exports.OkendoReviewsCarousel=({style:e,className:n,productId:r,groupId:a,headerBadgeUrl:o})=>{const d={"data-oke-carousel":"","data-oke-reviews-product-id":r?.length?s(r):null,"data-oke-reviews-group-id":a?.length?a:null,"data-oke-header-badge-url":o};return t.createElement(i,{style:e,className:n,dataAttributes:d})},exports.OkendoStarRating=({style:e,className:n,productId:r,okendoStarRatingSnippet:a})=>{const o={"data-oke-star-rating":"","data-oke-reviews-product-id":s(r)};return t.createElement(i,{style:e,className:n,dataAttributes:o,metafieldContent:a?.value})},exports.getOkendoProviderData=async({context:e,subscriberId:t,apiDomain:n,okendoProducts:s=["reviews"],appNamespace:a})=>{if(!s.length)return null;const o=`loyaltySettings: metafield(\n namespace: "${a??r}--loyalty",\n key: "loyalty_settings"\n ) {\n value\n }`,i=`widgetPreRenderStyleTags: metafield(\n namespace: "${a??r}--reviews",\n key: "widget_pre_render_style_tags"\n ) {\n value\n }`,d=`#graphql\n query metafields {\n shop {\n ${s.includes("loyalty")?o:""}\n ${s.includes("reviews")?i:""}\n }\n }\n `,{shop:{loyaltySettings:l,widgetPreRenderStyleTags:c}}=await e.storefront.query(d);let u=null;if(s.includes("loyalty")&&(u={...u??{},loyaltySettings:l?.value??""}),s.includes("reviews")){const e=`https://${n||"api.okendo.io/v1"}/stores/${t}/widget_plus_settings`,r=await fetch(e);if(!r.ok)return console.error(`Failed to retrieve subscriber settings for subscriber ID '${t}'.`),u;const{reviewsHeaderConfig:s,cssVariables:a,customCss:o,starSymbols:i}=await r.json(),d=c?.value??"";d||console.warn("Failed to retrieve pre-rendered widget style settings."),u={...u??{},reviewsHeaderConfig:s,cssVariables:a,customCss:o,preRenderStyleTags:d,starSymbols:i}}return u};
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ declare global {
3
+ interface Window {
4
+ okeLoyaltyApi?: {
5
+ initialiseWidgets: () => void;
6
+ };
7
+ }
8
+ }
9
+ export declare function OkendoLoyaltyEmbeddedWidget(): React.JSX.Element;
@@ -0,0 +1 @@
1
+ export * from './OkendoLoyaltyEmbeddedWidget';
@@ -1,22 +1,29 @@
1
1
  import type { WidgetPlus } from '@okendo/reviews-common';
2
- import type { Storefront } from '@shopify/hydrogen';
2
+ import type { CustomerAccount, Storefront } from '@shopify/hydrogen';
3
3
  import React, { type PropsWithChildren } from 'react';
4
- interface OkendoProviderData {
4
+ type OkendoProviderData = Partial<OkendoReviewsProviderData & OkendoLoyaltyProviderData>;
5
+ type OkendoProduct = 'reviews' | 'loyalty';
6
+ interface OkendoReviewsProviderData {
5
7
  reviewsHeaderConfig: WidgetPlus.ReviewsHeaderConfig;
6
8
  cssVariables: string;
7
9
  customCss?: string;
8
- initScriptContents: string;
9
10
  preRenderStyleTags: string;
10
11
  starSymbols: string;
11
12
  }
12
- export declare const getOkendoProviderData: ({ context, subscriberId, apiDomain, cdnDomain, }: {
13
- context: {
14
- storefront: Storefront;
15
- };
13
+ interface OkendoLoyaltyProviderData {
14
+ loyaltySettings: string;
15
+ }
16
+ export declare const getOkendoProviderData: ({ context, subscriberId, apiDomain, okendoProducts, appNamespace, }: {
17
+ context: StorefrontContext;
16
18
  subscriberId: string;
17
19
  apiDomain?: string;
18
- cdnDomain?: string;
20
+ okendoProducts?: OkendoProduct[];
21
+ appNamespace?: string;
19
22
  }) => Promise<OkendoProviderData | null>;
23
+ interface StorefrontContext {
24
+ customerAccount: CustomerAccount;
25
+ storefront: Storefront;
26
+ }
20
27
  interface ReviewProduct {
21
28
  productHandle?: string;
22
29
  productId: string;
@@ -29,16 +36,17 @@ interface OkendoProviderProps {
29
36
  */
30
37
  nonce?: string;
31
38
  /**
32
- * Either:
33
- * - the data returned by the promise returned by `getOkendoProviderData`, using this will allow the
34
- * Okendo widgets to show instantly on page load, but it will slightly increase the page load time;
35
- * - the promise returned by `getOkendoProviderData`, using this will make the Okendo widgets
36
- * show slightly after page load, but it have the advantage of not increasing the page load time.
39
+ * The promise returned by `getOkendoProviderData`.
40
+ */
41
+ okendoProviderData: Promise<OkendoProviderData | null>;
42
+ /**
43
+ * Used by the loyalty widget to verify the user's identity via the Storefront API.
44
+ * Can be retrieved via `await context.customerAccount.getAccessToken()` in the loader function.
37
45
  */
38
- okendoProviderData: Partial<OkendoProviderData> | null | Promise<Partial<OkendoProviderData> | null>;
46
+ customerAccessToken?: string;
39
47
  /** An optional product URL formatter */
40
48
  productUrlFormatter?: (product: ReviewProduct) => string;
41
49
  cdnDomain?: string;
42
50
  }
43
- export declare const OkendoProvider: ({ nonce, okendoProviderData, productUrlFormatter, cdnDomain, children, }: OkendoProviderProps & PropsWithChildren) => React.JSX.Element;
51
+ export declare const OkendoProvider: ({ nonce, okendoProviderData, customerAccessToken, productUrlFormatter, cdnDomain, children, }: OkendoProviderProps & PropsWithChildren) => React.JSX.Element;
44
52
  export {};
@@ -1,16 +1,13 @@
1
- import React from 'react';
1
+ import React, { type CSSProperties } from 'react';
2
2
  import { type MetafieldValue } from '../../internal/types';
3
3
  export interface WithOkendoReviewsSnippet {
4
4
  okendoReviewsSnippet?: MetafieldValue | null;
5
5
  }
6
6
  interface OkendoReviewsProps {
7
+ style?: CSSProperties;
8
+ className?: string;
7
9
  productId?: string;
8
10
  okendoReviewsSnippet?: MetafieldValue | null;
9
- /**
10
- * Only used if the promise returned by `getOkendoProviderData` is given to the OkendoProvider
11
- * without being awaited; in this case, the placeholder here will be shown until the widget is ready
12
- */
13
- placeholder?: JSX.Element;
14
11
  }
15
- export declare const OkendoReviews: ({ productId, okendoReviewsSnippet, placeholder }: OkendoReviewsProps) => React.JSX.Element;
12
+ export declare const OkendoReviews: ({ style, className, productId, okendoReviewsSnippet }: OkendoReviewsProps) => React.JSX.Element;
16
13
  export {};
@@ -1,13 +1,10 @@
1
- import React from 'react';
1
+ import React, { type CSSProperties } from 'react';
2
2
  interface OkendoReviewsCarouselProps {
3
+ style?: CSSProperties;
4
+ className?: string;
3
5
  productId?: string;
4
6
  groupId?: string;
5
7
  headerBadgeUrl?: string;
6
- /**
7
- * Only used if the promise returned by `getOkendoProviderData` is given to the OkendoProvider
8
- * without being awaited; in this case, the placeholder here will be shown until the widget is ready
9
- */
10
- placeholder?: JSX.Element;
11
8
  }
12
- export declare const OkendoReviewsCarousel: ({ productId, groupId, headerBadgeUrl, placeholder }: OkendoReviewsCarouselProps) => React.JSX.Element;
9
+ export declare const OkendoReviewsCarousel: ({ style, className, productId, groupId, headerBadgeUrl }: OkendoReviewsCarouselProps) => React.JSX.Element;
13
10
  export {};
@@ -1,16 +1,13 @@
1
- import React, { type ReactNode } from 'react';
1
+ import React, { type CSSProperties } from 'react';
2
2
  import { type MetafieldValue } from '../../internal/types';
3
3
  export interface WithOkendoStarRatingSnippet {
4
4
  okendoStarRatingSnippet?: MetafieldValue | null;
5
5
  }
6
6
  interface OkendoStarRatingProps {
7
+ style?: CSSProperties;
8
+ className?: string;
7
9
  productId: string;
8
10
  okendoStarRatingSnippet?: MetafieldValue | null;
9
- /**
10
- * Only used if the promise returned by `getOkendoProviderData` is given to the OkendoProvider
11
- * without being awaited; in this case, the placeholder here will be shown until the widget is ready
12
- */
13
- placeholder?: ReactNode;
14
11
  }
15
- export declare const OkendoStarRating: ({ productId, okendoStarRatingSnippet, placeholder }: OkendoStarRatingProps) => string | number | true | Iterable<React.ReactNode> | React.JSX.Element;
12
+ export declare const OkendoStarRating: ({ style, className, productId, okendoStarRatingSnippet }: OkendoStarRatingProps) => React.JSX.Element;
16
13
  export {};
@@ -1,3 +1,4 @@
1
+ export * from "./OkendoLoyalty";
1
2
  export * from "./OkendoProvider";
2
3
  export * from "./OkendoReviews";
3
4
  export * from "./OkendoReviewsCarousel";
@@ -1,2 +1,2 @@
1
- export declare const OKENDO_PRODUCT_STAR_RATING_FRAGMENT: "#graphql\n\tfragment OkendoStarRatingSnippet on Product {\n\t\tokendoStarRatingSnippet: metafield(\n\t\t\tnamespace: \"$app:reviews\"\n\t\t\tkey: \"star_rating_snippet\"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n";
2
- export declare const OKENDO_PRODUCT_REVIEWS_FRAGMENT: "#graphql\n\tfragment OkendoReviewsSnippet on Product {\n\t\tokendoReviewsSnippet: metafield(\n\t\t\tnamespace: \"$app:reviews\"\n\t\t\tkey: \"reviews_widget_snippet\"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n";
1
+ export declare const OKENDO_PRODUCT_STAR_RATING_FRAGMENT: "#graphql\n\tfragment OkendoStarRatingSnippet on Product {\n\t\tokendoStarRatingSnippet: metafield(\n\t\t\tnamespace: \"app--1576377--reviews\"\n\t\t\tkey: \"star_rating_snippet\"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n";
2
+ export declare const OKENDO_PRODUCT_REVIEWS_FRAGMENT: "#graphql\n\tfragment OkendoReviewsSnippet on Product {\n\t\tokendoReviewsSnippet: metafield(\n\t\t\tnamespace: \"app--1576377--reviews\"\n\t\t\tkey: \"reviews_widget_snippet\"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n";
@@ -1,6 +1,8 @@
1
1
  import type { ReviewsWidgetPlus } from '@okendo/reviews-widget-plus/dist-utils/ReviewsWidgetPlus';
2
- import React from 'react';
2
+ import React, { type CSSProperties } from 'react';
3
3
  export interface OkendoWidgetProps {
4
+ style?: CSSProperties;
5
+ className?: string;
4
6
  dataAttributes: {
5
7
  'data-oke-widget'?: string;
6
8
  'data-oke-star-rating'?: string;
@@ -13,4 +15,4 @@ declare global {
13
15
  okeWidgetApi: ReviewsWidgetPlus.WidgetWindowApi;
14
16
  }
15
17
  }
16
- export declare const OkendoWidget: ({ dataAttributes, metafieldContent }: OkendoWidgetProps) => React.JSX.Element;
18
+ export declare const OkendoWidget: ({ style, className, dataAttributes, metafieldContent }: OkendoWidgetProps) => React.JSX.Element;
@@ -1,3 +1,4 @@
1
+ export declare const OKENDO_APP_NAMESPACE = "app--1576377";
1
2
  /**
2
3
  * Gets the product ID with Okendo formatting.
3
4
  * @param productId The Shopify Product ID e.g. gid://shopify/Product/10079785100.
package/dist/esm/index.js CHANGED
@@ -1 +1 @@
1
- import e,{createContext as t,useState as n,useContext as r,Suspense as a,useRef as o,useEffect as i}from"react";import{Await as d}from"@remix-run/react";const s=t(void 0),l=({children:t})=>{const[r,a]=n(!1);return e.createElement(s.Provider,{value:{okendoDataLoaded:r,setOkendoDataLoaded:a}},t)},c=()=>{const e=r(s);return void 0===e?null:e},u="cdn-static.okendo.io",p=async({context:e,subscriberId:t,apiDomain:n,cdnDomain:r})=>{const a=`https://${n||"api.okendo.io/v1"}/stores/${t}/widget_plus_settings`,o=await fetch(a);if(!o.ok)return console.error(`Failed to retrieve subscriber settings for subscriber ID '${t}'.`),null;const{reviewsHeaderConfig:i,cssVariables:d,customCss:s,starSymbols:l}=await o.json(),c=await fetch(`https://${r||u}/reviews-widget-plus/js/okendo-reviews.js`);if(!c.ok)return console.error("Failed to retrieve widget initialisation script."),null;const p=await c.text(),{shop:{widgetPreRenderStyleTags:m}}=await e.storefront.query('#graphql\n\t\tquery metafields {\n\t\t\tshop {\n\t\t\t\twidgetPreRenderStyleTags: metafield(\n\t\t\t\t\tnamespace: "$app:reviews"\n\t\t\t\t\tkey: "widget_pre_render_style_tags"\n\t\t\t\t) {\n\t\t\t\t\tvalue\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t'),g=m?.value??"";return g||console.warn("Failed to retrieve pre-rendered widget style settings."),{reviewsHeaderConfig:i,cssVariables:d,customCss:s,initScriptContents:p,preRenderStyleTags:g,starSymbols:l}},m=({nonce:t="",okendoProviderData:n,productUrlFormatter:r,cdnDomain:o,children:i})=>e.createElement(l,null,n&&"then"in n?e.createElement(a,null,e.createElement(d,{resolve:n},(n=>e.createElement(g,{nonce:t,okendoProviderData:n,productUrlFormatter:r,cdnDomain:o,awaited:!0})))):e.createElement(g,{nonce:t,okendoProviderData:n,productUrlFormatter:r,cdnDomain:o}),i),g=({nonce:t="",okendoProviderData:n,productUrlFormatter:r,awaited:a,cdnDomain:d})=>{const s=c(),l=o(!1);if(i((()=>{if(n&&s?.setOkendoDataLoaded(!0),n&&a&&!l.current){const e=document.createElement("script");e.src=`https://${d||u}/reviews-widget-plus/js/okendo-reviews.js`,document.head.appendChild(e),l.current=!0}}),[n,s,a,d]),!n)return null;const{reviewsHeaderConfig:p,cssVariables:m,customCss:g,initScriptContents:v,preRenderStyleTags:k,starSymbols:w}=n,y=(m??"").replace('<style id="oke-css-vars">',"").replace("</style>",""),h=g?g.replace('<style id="oke-reviews-custom-css">',"").replace("</style>",""):"";return e.createElement(e.Fragment,null,e.createElement("script",{nonce:t,id:"oke-reviews-settings",type:"application/json",dangerouslySetInnerHTML:{__html:JSON.stringify(p)}}),e.createElement("style",{nonce:t,id:"oke-css-vars",dangerouslySetInnerHTML:{__html:y}}),h&&e.createElement("style",{nonce:t,id:"oke-reviews-custom-css",dangerouslySetInnerHTML:{__html:h}}),!a&&v&&e.createElement("script",{nonce:t,dangerouslySetInnerHTML:{__html:v}}),e.createElement("script",{nonce:t,type:"text/javascript",dangerouslySetInnerHTML:{__html:`window.okeProductUrlFormatter = ${"function"==typeof r?r.toString():"string"==typeof r?r:"(product) =>\n product && product.productHandle\n ? \"/products/\" + product.productHandle + \"/\" + (product.variantId ? '?variantId=' + product.variantId : '')\n : undefined"}`}}),k&&e.createElement("div",{dangerouslySetInnerHTML:{__html:k}}),w&&e.createElement("div",{dangerouslySetInnerHTML:{__html:w}}))};const v=({dataAttributes:t,metafieldContent:n=""})=>{const r=o(null),a=o(!1),d=function(e){const t=o();return i((()=>{t.current=e})),t.current}(t),s=()=>{r.current&&(window.okeWidgetApi.initWidget(r.current),a.current=!0)};return i((()=>{if(!d||t["data-oke-widget"]!==d["data-oke-widget"]||t["data-oke-star-rating"]!==d["data-oke-star-rating"]||t["data-oke-reviews-product-id"]!==d["data-oke-reviews-product-id"]||!a.current)return window.okeWidgetApi&&r.current?s():document.addEventListener("oke-script-loaded",s),()=>{document.removeEventListener("oke-script-loaded",s)}}),[t,d]),e.createElement("div",{ref:r,key:JSON.stringify(t),...t,dangerouslySetInnerHTML:n?{__html:n}:void 0})},k=/^[0-9]*$/;function w(e){if(e)return`shopify-${k.test(e)?e:e.split("/").slice(-1)[0]}`}const y=({productId:t,okendoReviewsSnippet:n,placeholder:r})=>{const a=c(),o=t?.length?w(t):null,i=t?.length?n:null,d={"data-oke-widget":"","data-oke-reviews-product-id":o};return null===a||a.okendoDataLoaded?e.createElement(v,{dataAttributes:d,metafieldContent:i?.value}):r||e.createElement("div",{style:{height:"350px"}})},h=({productId:t,groupId:n,headerBadgeUrl:r,placeholder:a})=>{const o=c(),i={"data-oke-carousel":"","data-oke-reviews-product-id":t?.length?w(t):null,"data-oke-reviews-group-id":n?.length?n:null,"data-oke-header-badge-url":r};return null===o||o.okendoDataLoaded?e.createElement(v,{dataAttributes:i}):a||e.createElement("div",{style:{height:"350px"}})},f=({productId:t,okendoStarRatingSnippet:n,placeholder:r})=>{const a=c(),o={"data-oke-star-rating":"","data-oke-reviews-product-id":w(t)};return null===a||a.okendoDataLoaded?e.createElement(v,{dataAttributes:o,metafieldContent:n?.value}):r||e.createElement("div",{style:{height:"20px"}})},S='#graphql\n\tfragment OkendoStarRatingSnippet on Product {\n\t\tokendoStarRatingSnippet: metafield(\n\t\t\tnamespace: "$app:reviews"\n\t\t\tkey: "star_rating_snippet"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n',_='#graphql\n\tfragment OkendoReviewsSnippet on Product {\n\t\tokendoReviewsSnippet: metafield(\n\t\t\tnamespace: "$app:reviews"\n\t\t\tkey: "reviews_widget_snippet"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n';export{_ as OKENDO_PRODUCT_REVIEWS_FRAGMENT,S as OKENDO_PRODUCT_STAR_RATING_FRAGMENT,m as OkendoProvider,y as OkendoReviews,h as OkendoReviewsCarousel,f as OkendoStarRating,p as getOkendoProviderData};
1
+ import{useLocation as e,Await as t}from"react-router";import n,{useEffect as r,Suspense as s,useRef as a}from"react";function o(){const t=e();return r((()=>{window?.okeLoyaltyApi?.initialiseWidgets()}),[t.pathname]),n.createElement("div",{"data-oke-loyalty-embedded-widget":""})}const i=/^[0-9]*$/,l="app--1576377";function d(e){if(e)return`shopify-${i.test(e)?e:e.split("/").slice(-1)[0]}`}const c="cdn-static.okendo.io",u=async({context:e,subscriberId:t,apiDomain:n,okendoProducts:r=["reviews"],appNamespace:s})=>{if(!r.length)return null;const a=`loyaltySettings: metafield(\n namespace: "${s??l}--loyalty",\n key: "loyalty_settings"\n ) {\n value\n }`,o=`widgetPreRenderStyleTags: metafield(\n namespace: "${s??l}--reviews",\n key: "widget_pre_render_style_tags"\n ) {\n value\n }`,i=`#graphql\n query metafields {\n shop {\n ${r.includes("loyalty")?a:""}\n ${r.includes("reviews")?o:""}\n }\n }\n `,{shop:{loyaltySettings:d,widgetPreRenderStyleTags:c}}=await e.storefront.query(i);let u=null;if(r.includes("loyalty")&&(u={...u??{},loyaltySettings:d?.value??""}),r.includes("reviews")){const e=`https://${n||"api.okendo.io/v1"}/stores/${t}/widget_plus_settings`,r=await fetch(e);if(!r.ok)return console.error(`Failed to retrieve subscriber settings for subscriber ID '${t}'.`),u;const{reviewsHeaderConfig:s,cssVariables:a,customCss:o,starSymbols:i}=await r.json(),l=c?.value??"";l||console.warn("Failed to retrieve pre-rendered widget style settings."),u={...u??{},reviewsHeaderConfig:s,cssVariables:a,customCss:o,preRenderStyleTags:l,starSymbols:i}}return u},p=({nonce:e="",okendoProviderData:r,customerAccessToken:a,productUrlFormatter:o,cdnDomain:i,children:l})=>n.createElement(n.Fragment,null,n.createElement(s,null,n.createElement(t,{resolve:r},(t=>n.createElement(m,{nonce:e,okendoProviderData:t,productUrlFormatter:o,cdnDomain:i})))),a&&n.createElement("script",{nonce:e,id:"oke-loyalty-customer-access-token",type:"application/json",dangerouslySetInnerHTML:{__html:JSON.stringify({customerAccessToken:a})}}),l),m=({nonce:e="",okendoProviderData:t,productUrlFormatter:s,cdnDomain:o})=>{const i=a(!1),l=a(!1);if(r((()=>{if(t&&t.loyaltySettings&&!1===i.current){const e=document.createElement("script");e.src=`https://${o||c}/loyalty/js/init-onsite.js`,document.head.appendChild(e);const n=document.createElement("script");n.type="application/json",n.id="oke-loyalty-settings";const r=t.loyaltySettings?t.loyaltySettings.replace('<script type="application/json" id="oke-loyalty-settings">',"").replace('<\/script><script src="https://rhys-cdn.okendo.dev/loyalty/js/init-onsite.js" defer><\/script>',""):"";n.innerHTML=r,document.head.appendChild(n),i.current=!0}}),[t,o]),r((()=>{if(t&&!l.current){const e=document.createElement("script");e.src=`https://${o||c}/reviews-widget-plus/js/okendo-reviews.js`,document.head.appendChild(e),l.current=!0}}),[t,o]),!t)return null;const{reviewsHeaderConfig:d,cssVariables:u,customCss:p,preRenderStyleTags:m,starSymbols:y}=t,g=(u??"").replace('<style id="oke-css-vars">',"").replace("</style>",""),v=p?p.replace('<style id="oke-reviews-custom-css">',"").replace("</style>",""):"";return n.createElement(n.Fragment,null,n.createElement("script",{nonce:e,id:"oke-reviews-settings",type:"application/json",dangerouslySetInnerHTML:{__html:JSON.stringify(d)}}),n.createElement("style",{nonce:e,id:"oke-css-vars",dangerouslySetInnerHTML:{__html:g}}),v&&n.createElement("style",{nonce:e,id:"oke-reviews-custom-css",dangerouslySetInnerHTML:{__html:v}}),n.createElement("script",{nonce:e,type:"text/javascript",dangerouslySetInnerHTML:{__html:`window.okeProductUrlFormatter = ${"function"==typeof s?s.toString():"string"==typeof s?s:"(product) =>\n product && product.productHandle\n ? \"/products/\" + product.productHandle + \"/\" + (product.variantId ? '?variantId=' + product.variantId : '')\n : undefined"}`}}),m&&n.createElement("div",{dangerouslySetInnerHTML:{__html:m}}),y&&n.createElement("div",{dangerouslySetInnerHTML:{__html:y}}))};const y=({style:e,className:t,dataAttributes:s,metafieldContent:o=""})=>{const i=a(null),l=a(!1),d=function(e){const t=a();return r((()=>{t.current=e})),t.current}(s),c=()=>{i.current&&(window.okeWidgetApi.initWidget(i.current),l.current=!0)};return r((()=>{if(!d||s["data-oke-widget"]!==d["data-oke-widget"]||s["data-oke-star-rating"]!==d["data-oke-star-rating"]||s["data-oke-reviews-product-id"]!==d["data-oke-reviews-product-id"]||!l.current)return window.okeWidgetApi&&i.current?c():document.addEventListener("oke-script-loaded",c),()=>{document.removeEventListener("oke-script-loaded",c)}}),[s,d]),n.createElement("div",{ref:i,style:e,className:t,key:JSON.stringify(s),...s,dangerouslySetInnerHTML:o?{__html:o}:void 0})},g=({style:e,className:t,productId:r,okendoReviewsSnippet:s})=>{const a=r?.length?d(r):null,o=r?.length?s:null,i={"data-oke-widget":"","data-oke-reviews-product-id":a};return n.createElement(y,{style:e,className:t,dataAttributes:i,metafieldContent:o?.value})},v=({style:e,className:t,productId:r,groupId:s,headerBadgeUrl:a})=>{const o={"data-oke-carousel":"","data-oke-reviews-product-id":r?.length?d(r):null,"data-oke-reviews-group-id":s?.length?s:null,"data-oke-header-badge-url":a};return n.createElement(y,{style:e,className:t,dataAttributes:o})},k=({style:e,className:t,productId:r,okendoStarRatingSnippet:s})=>{const a={"data-oke-star-rating":"","data-oke-reviews-product-id":d(r)};return n.createElement(y,{style:e,className:t,dataAttributes:a,metafieldContent:s?.value})},w=`#graphql\n\tfragment OkendoStarRatingSnippet on Product {\n\t\tokendoStarRatingSnippet: metafield(\n\t\t\tnamespace: "${l}--reviews"\n\t\t\tkey: "star_rating_snippet"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n`,f=`#graphql\n\tfragment OkendoReviewsSnippet on Product {\n\t\tokendoReviewsSnippet: metafield(\n\t\t\tnamespace: "${l}--reviews"\n\t\t\tkey: "reviews_widget_snippet"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n`;export{f as OKENDO_PRODUCT_REVIEWS_FRAGMENT,w as OKENDO_PRODUCT_STAR_RATING_FRAGMENT,o as OkendoLoyaltyEmbeddedWidget,p as OkendoProvider,g as OkendoReviews,v as OkendoReviewsCarousel,k as OkendoStarRating,u as getOkendoProviderData};
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ declare global {
3
+ interface Window {
4
+ okeLoyaltyApi?: {
5
+ initialiseWidgets: () => void;
6
+ };
7
+ }
8
+ }
9
+ export declare function OkendoLoyaltyEmbeddedWidget(): React.JSX.Element;
@@ -0,0 +1 @@
1
+ export * from './OkendoLoyaltyEmbeddedWidget';
@@ -1,22 +1,29 @@
1
1
  import type { WidgetPlus } from '@okendo/reviews-common';
2
- import type { Storefront } from '@shopify/hydrogen';
2
+ import type { CustomerAccount, Storefront } from '@shopify/hydrogen';
3
3
  import React, { type PropsWithChildren } from 'react';
4
- interface OkendoProviderData {
4
+ type OkendoProviderData = Partial<OkendoReviewsProviderData & OkendoLoyaltyProviderData>;
5
+ type OkendoProduct = 'reviews' | 'loyalty';
6
+ interface OkendoReviewsProviderData {
5
7
  reviewsHeaderConfig: WidgetPlus.ReviewsHeaderConfig;
6
8
  cssVariables: string;
7
9
  customCss?: string;
8
- initScriptContents: string;
9
10
  preRenderStyleTags: string;
10
11
  starSymbols: string;
11
12
  }
12
- export declare const getOkendoProviderData: ({ context, subscriberId, apiDomain, cdnDomain, }: {
13
- context: {
14
- storefront: Storefront;
15
- };
13
+ interface OkendoLoyaltyProviderData {
14
+ loyaltySettings: string;
15
+ }
16
+ export declare const getOkendoProviderData: ({ context, subscriberId, apiDomain, okendoProducts, appNamespace, }: {
17
+ context: StorefrontContext;
16
18
  subscriberId: string;
17
19
  apiDomain?: string;
18
- cdnDomain?: string;
20
+ okendoProducts?: OkendoProduct[];
21
+ appNamespace?: string;
19
22
  }) => Promise<OkendoProviderData | null>;
23
+ interface StorefrontContext {
24
+ customerAccount: CustomerAccount;
25
+ storefront: Storefront;
26
+ }
20
27
  interface ReviewProduct {
21
28
  productHandle?: string;
22
29
  productId: string;
@@ -29,16 +36,17 @@ interface OkendoProviderProps {
29
36
  */
30
37
  nonce?: string;
31
38
  /**
32
- * Either:
33
- * - the data returned by the promise returned by `getOkendoProviderData`, using this will allow the
34
- * Okendo widgets to show instantly on page load, but it will slightly increase the page load time;
35
- * - the promise returned by `getOkendoProviderData`, using this will make the Okendo widgets
36
- * show slightly after page load, but it have the advantage of not increasing the page load time.
39
+ * The promise returned by `getOkendoProviderData`.
40
+ */
41
+ okendoProviderData: Promise<OkendoProviderData | null>;
42
+ /**
43
+ * Used by the loyalty widget to verify the user's identity via the Storefront API.
44
+ * Can be retrieved via `await context.customerAccount.getAccessToken()` in the loader function.
37
45
  */
38
- okendoProviderData: Partial<OkendoProviderData> | null | Promise<Partial<OkendoProviderData> | null>;
46
+ customerAccessToken?: string;
39
47
  /** An optional product URL formatter */
40
48
  productUrlFormatter?: (product: ReviewProduct) => string;
41
49
  cdnDomain?: string;
42
50
  }
43
- export declare const OkendoProvider: ({ nonce, okendoProviderData, productUrlFormatter, cdnDomain, children, }: OkendoProviderProps & PropsWithChildren) => React.JSX.Element;
51
+ export declare const OkendoProvider: ({ nonce, okendoProviderData, customerAccessToken, productUrlFormatter, cdnDomain, children, }: OkendoProviderProps & PropsWithChildren) => React.JSX.Element;
44
52
  export {};
@@ -1,16 +1,13 @@
1
- import React from 'react';
1
+ import React, { type CSSProperties } from 'react';
2
2
  import { type MetafieldValue } from '../../internal/types';
3
3
  export interface WithOkendoReviewsSnippet {
4
4
  okendoReviewsSnippet?: MetafieldValue | null;
5
5
  }
6
6
  interface OkendoReviewsProps {
7
+ style?: CSSProperties;
8
+ className?: string;
7
9
  productId?: string;
8
10
  okendoReviewsSnippet?: MetafieldValue | null;
9
- /**
10
- * Only used if the promise returned by `getOkendoProviderData` is given to the OkendoProvider
11
- * without being awaited; in this case, the placeholder here will be shown until the widget is ready
12
- */
13
- placeholder?: JSX.Element;
14
11
  }
15
- export declare const OkendoReviews: ({ productId, okendoReviewsSnippet, placeholder }: OkendoReviewsProps) => React.JSX.Element;
12
+ export declare const OkendoReviews: ({ style, className, productId, okendoReviewsSnippet }: OkendoReviewsProps) => React.JSX.Element;
16
13
  export {};
@@ -1,13 +1,10 @@
1
- import React from 'react';
1
+ import React, { type CSSProperties } from 'react';
2
2
  interface OkendoReviewsCarouselProps {
3
+ style?: CSSProperties;
4
+ className?: string;
3
5
  productId?: string;
4
6
  groupId?: string;
5
7
  headerBadgeUrl?: string;
6
- /**
7
- * Only used if the promise returned by `getOkendoProviderData` is given to the OkendoProvider
8
- * without being awaited; in this case, the placeholder here will be shown until the widget is ready
9
- */
10
- placeholder?: JSX.Element;
11
8
  }
12
- export declare const OkendoReviewsCarousel: ({ productId, groupId, headerBadgeUrl, placeholder }: OkendoReviewsCarouselProps) => React.JSX.Element;
9
+ export declare const OkendoReviewsCarousel: ({ style, className, productId, groupId, headerBadgeUrl }: OkendoReviewsCarouselProps) => React.JSX.Element;
13
10
  export {};
@@ -1,16 +1,13 @@
1
- import React, { type ReactNode } from 'react';
1
+ import React, { type CSSProperties } from 'react';
2
2
  import { type MetafieldValue } from '../../internal/types';
3
3
  export interface WithOkendoStarRatingSnippet {
4
4
  okendoStarRatingSnippet?: MetafieldValue | null;
5
5
  }
6
6
  interface OkendoStarRatingProps {
7
+ style?: CSSProperties;
8
+ className?: string;
7
9
  productId: string;
8
10
  okendoStarRatingSnippet?: MetafieldValue | null;
9
- /**
10
- * Only used if the promise returned by `getOkendoProviderData` is given to the OkendoProvider
11
- * without being awaited; in this case, the placeholder here will be shown until the widget is ready
12
- */
13
- placeholder?: ReactNode;
14
11
  }
15
- export declare const OkendoStarRating: ({ productId, okendoStarRatingSnippet, placeholder }: OkendoStarRatingProps) => string | number | true | Iterable<React.ReactNode> | React.JSX.Element;
12
+ export declare const OkendoStarRating: ({ style, className, productId, okendoStarRatingSnippet }: OkendoStarRatingProps) => React.JSX.Element;
16
13
  export {};
@@ -1,3 +1,4 @@
1
+ export * from "./OkendoLoyalty";
1
2
  export * from "./OkendoProvider";
2
3
  export * from "./OkendoReviews";
3
4
  export * from "./OkendoReviewsCarousel";
@@ -1,2 +1,2 @@
1
- export declare const OKENDO_PRODUCT_STAR_RATING_FRAGMENT: "#graphql\n\tfragment OkendoStarRatingSnippet on Product {\n\t\tokendoStarRatingSnippet: metafield(\n\t\t\tnamespace: \"$app:reviews\"\n\t\t\tkey: \"star_rating_snippet\"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n";
2
- export declare const OKENDO_PRODUCT_REVIEWS_FRAGMENT: "#graphql\n\tfragment OkendoReviewsSnippet on Product {\n\t\tokendoReviewsSnippet: metafield(\n\t\t\tnamespace: \"$app:reviews\"\n\t\t\tkey: \"reviews_widget_snippet\"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n";
1
+ export declare const OKENDO_PRODUCT_STAR_RATING_FRAGMENT: "#graphql\n\tfragment OkendoStarRatingSnippet on Product {\n\t\tokendoStarRatingSnippet: metafield(\n\t\t\tnamespace: \"app--1576377--reviews\"\n\t\t\tkey: \"star_rating_snippet\"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n";
2
+ export declare const OKENDO_PRODUCT_REVIEWS_FRAGMENT: "#graphql\n\tfragment OkendoReviewsSnippet on Product {\n\t\tokendoReviewsSnippet: metafield(\n\t\t\tnamespace: \"app--1576377--reviews\"\n\t\t\tkey: \"reviews_widget_snippet\"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n";
@@ -1,6 +1,8 @@
1
1
  import type { ReviewsWidgetPlus } from '@okendo/reviews-widget-plus/dist-utils/ReviewsWidgetPlus';
2
- import React from 'react';
2
+ import React, { type CSSProperties } from 'react';
3
3
  export interface OkendoWidgetProps {
4
+ style?: CSSProperties;
5
+ className?: string;
4
6
  dataAttributes: {
5
7
  'data-oke-widget'?: string;
6
8
  'data-oke-star-rating'?: string;
@@ -13,4 +15,4 @@ declare global {
13
15
  okeWidgetApi: ReviewsWidgetPlus.WidgetWindowApi;
14
16
  }
15
17
  }
16
- export declare const OkendoWidget: ({ dataAttributes, metafieldContent }: OkendoWidgetProps) => React.JSX.Element;
18
+ export declare const OkendoWidget: ({ style, className, dataAttributes, metafieldContent }: OkendoWidgetProps) => React.JSX.Element;
@@ -1,3 +1,4 @@
1
+ export declare const OKENDO_APP_NAMESPACE = "app--1576377";
1
2
  /**
2
3
  * Gets the product ID with Okendo formatting.
3
4
  * @param productId The Shopify Product ID e.g. gid://shopify/Product/10079785100.
package/dist/index.d.ts CHANGED
@@ -1,23 +1,39 @@
1
+ import React, { PropsWithChildren, CSSProperties } from 'react';
1
2
  import { WidgetPlus } from '@okendo/reviews-common';
2
- import { Storefront } from '@shopify/hydrogen';
3
- import React, { PropsWithChildren, ReactNode } from 'react';
3
+ import { CustomerAccount, Storefront } from '@shopify/hydrogen';
4
4
 
5
- interface OkendoProviderData {
5
+ declare global {
6
+ interface Window {
7
+ okeLoyaltyApi?: {
8
+ initialiseWidgets: () => void;
9
+ };
10
+ }
11
+ }
12
+ declare function OkendoLoyaltyEmbeddedWidget(): React.JSX.Element;
13
+
14
+ type OkendoProviderData = Partial<OkendoReviewsProviderData & OkendoLoyaltyProviderData>;
15
+ type OkendoProduct = 'reviews' | 'loyalty';
16
+ interface OkendoReviewsProviderData {
6
17
  reviewsHeaderConfig: WidgetPlus.ReviewsHeaderConfig;
7
18
  cssVariables: string;
8
19
  customCss?: string;
9
- initScriptContents: string;
10
20
  preRenderStyleTags: string;
11
21
  starSymbols: string;
12
22
  }
13
- declare const getOkendoProviderData: ({ context, subscriberId, apiDomain, cdnDomain, }: {
14
- context: {
15
- storefront: Storefront;
16
- };
23
+ interface OkendoLoyaltyProviderData {
24
+ loyaltySettings: string;
25
+ }
26
+ declare const getOkendoProviderData: ({ context, subscriberId, apiDomain, okendoProducts, appNamespace, }: {
27
+ context: StorefrontContext;
17
28
  subscriberId: string;
18
29
  apiDomain?: string;
19
- cdnDomain?: string;
30
+ okendoProducts?: OkendoProduct[];
31
+ appNamespace?: string;
20
32
  }) => Promise<OkendoProviderData | null>;
33
+ interface StorefrontContext {
34
+ customerAccount: CustomerAccount;
35
+ storefront: Storefront;
36
+ }
21
37
  interface ReviewProduct {
22
38
  productHandle?: string;
23
39
  productId: string;
@@ -30,18 +46,19 @@ interface OkendoProviderProps {
30
46
  */
31
47
  nonce?: string;
32
48
  /**
33
- * Either:
34
- * - the data returned by the promise returned by `getOkendoProviderData`, using this will allow the
35
- * Okendo widgets to show instantly on page load, but it will slightly increase the page load time;
36
- * - the promise returned by `getOkendoProviderData`, using this will make the Okendo widgets
37
- * show slightly after page load, but it have the advantage of not increasing the page load time.
49
+ * The promise returned by `getOkendoProviderData`.
50
+ */
51
+ okendoProviderData: Promise<OkendoProviderData | null>;
52
+ /**
53
+ * Used by the loyalty widget to verify the user's identity via the Storefront API.
54
+ * Can be retrieved via `await context.customerAccount.getAccessToken()` in the loader function.
38
55
  */
39
- okendoProviderData: Partial<OkendoProviderData> | null | Promise<Partial<OkendoProviderData> | null>;
56
+ customerAccessToken?: string;
40
57
  /** An optional product URL formatter */
41
58
  productUrlFormatter?: (product: ReviewProduct) => string;
42
59
  cdnDomain?: string;
43
60
  }
44
- declare const OkendoProvider: ({ nonce, okendoProviderData, productUrlFormatter, cdnDomain, children, }: OkendoProviderProps & PropsWithChildren) => React.JSX.Element;
61
+ declare const OkendoProvider: ({ nonce, okendoProviderData, customerAccessToken, productUrlFormatter, cdnDomain, children, }: OkendoProviderProps & PropsWithChildren) => React.JSX.Element;
45
62
 
46
63
  interface MetafieldValue {
47
64
  value: string;
@@ -51,43 +68,34 @@ interface WithOkendoReviewsSnippet {
51
68
  okendoReviewsSnippet?: MetafieldValue | null;
52
69
  }
53
70
  interface OkendoReviewsProps {
71
+ style?: CSSProperties;
72
+ className?: string;
54
73
  productId?: string;
55
74
  okendoReviewsSnippet?: MetafieldValue | null;
56
- /**
57
- * Only used if the promise returned by `getOkendoProviderData` is given to the OkendoProvider
58
- * without being awaited; in this case, the placeholder here will be shown until the widget is ready
59
- */
60
- placeholder?: JSX.Element;
61
75
  }
62
- declare const OkendoReviews: ({ productId, okendoReviewsSnippet, placeholder }: OkendoReviewsProps) => React.JSX.Element;
76
+ declare const OkendoReviews: ({ style, className, productId, okendoReviewsSnippet }: OkendoReviewsProps) => React.JSX.Element;
63
77
 
64
78
  interface OkendoReviewsCarouselProps {
79
+ style?: CSSProperties;
80
+ className?: string;
65
81
  productId?: string;
66
82
  groupId?: string;
67
83
  headerBadgeUrl?: string;
68
- /**
69
- * Only used if the promise returned by `getOkendoProviderData` is given to the OkendoProvider
70
- * without being awaited; in this case, the placeholder here will be shown until the widget is ready
71
- */
72
- placeholder?: JSX.Element;
73
84
  }
74
- declare const OkendoReviewsCarousel: ({ productId, groupId, headerBadgeUrl, placeholder }: OkendoReviewsCarouselProps) => React.JSX.Element;
85
+ declare const OkendoReviewsCarousel: ({ style, className, productId, groupId, headerBadgeUrl }: OkendoReviewsCarouselProps) => React.JSX.Element;
75
86
 
76
87
  interface WithOkendoStarRatingSnippet {
77
88
  okendoStarRatingSnippet?: MetafieldValue | null;
78
89
  }
79
90
  interface OkendoStarRatingProps {
91
+ style?: CSSProperties;
92
+ className?: string;
80
93
  productId: string;
81
94
  okendoStarRatingSnippet?: MetafieldValue | null;
82
- /**
83
- * Only used if the promise returned by `getOkendoProviderData` is given to the OkendoProvider
84
- * without being awaited; in this case, the placeholder here will be shown until the widget is ready
85
- */
86
- placeholder?: ReactNode;
87
95
  }
88
- declare const OkendoStarRating: ({ productId, okendoStarRatingSnippet, placeholder }: OkendoStarRatingProps) => string | number | true | Iterable<React.ReactNode> | React.JSX.Element;
96
+ declare const OkendoStarRating: ({ style, className, productId, okendoStarRatingSnippet }: OkendoStarRatingProps) => React.JSX.Element;
89
97
 
90
- declare const OKENDO_PRODUCT_STAR_RATING_FRAGMENT: "#graphql\n\tfragment OkendoStarRatingSnippet on Product {\n\t\tokendoStarRatingSnippet: metafield(\n\t\t\tnamespace: \"$app:reviews\"\n\t\t\tkey: \"star_rating_snippet\"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n";
91
- declare const OKENDO_PRODUCT_REVIEWS_FRAGMENT: "#graphql\n\tfragment OkendoReviewsSnippet on Product {\n\t\tokendoReviewsSnippet: metafield(\n\t\t\tnamespace: \"$app:reviews\"\n\t\t\tkey: \"reviews_widget_snippet\"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n";
98
+ declare const OKENDO_PRODUCT_STAR_RATING_FRAGMENT: "#graphql\n\tfragment OkendoStarRatingSnippet on Product {\n\t\tokendoStarRatingSnippet: metafield(\n\t\t\tnamespace: \"app--1576377--reviews\"\n\t\t\tkey: \"star_rating_snippet\"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n";
99
+ declare const OKENDO_PRODUCT_REVIEWS_FRAGMENT: "#graphql\n\tfragment OkendoReviewsSnippet on Product {\n\t\tokendoReviewsSnippet: metafield(\n\t\t\tnamespace: \"app--1576377--reviews\"\n\t\t\tkey: \"reviews_widget_snippet\"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n";
92
100
 
93
- export { OKENDO_PRODUCT_REVIEWS_FRAGMENT, OKENDO_PRODUCT_STAR_RATING_FRAGMENT, OkendoProvider, OkendoReviews, OkendoReviewsCarousel, OkendoStarRating, type WithOkendoReviewsSnippet, type WithOkendoStarRatingSnippet, getOkendoProviderData };
101
+ export { OKENDO_PRODUCT_REVIEWS_FRAGMENT, OKENDO_PRODUCT_STAR_RATING_FRAGMENT, OkendoLoyaltyEmbeddedWidget, OkendoProvider, OkendoReviews, OkendoReviewsCarousel, OkendoStarRating, type WithOkendoReviewsSnippet, type WithOkendoStarRatingSnippet, getOkendoProviderData };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@okendo/shopify-hydrogen",
3
- "version": "2.3.2",
4
- "description": "Okendo React components for Shopify Hydrogen 2 (Remix)",
3
+ "version": "2.5.0",
4
+ "description": "Okendo React components for Shopify Hydrogen",
5
5
  "author": "Okendo",
6
6
  "license": "SEE LICENSE IN LICENSE.txt",
7
7
  "engines": {
@@ -20,8 +20,8 @@
20
20
  "eslint": "eslint src"
21
21
  },
22
22
  "devDependencies": {
23
- "@okendo/reviews-common": "^7.14.0",
24
- "@okendo/reviews-widget-plus": "^0.70.23",
23
+ "@okendo/reviews-common": "^7.111.2",
24
+ "@okendo/reviews-widget-plus": "^0.77.0",
25
25
  "@okendo/tsconfig": "0.0.2",
26
26
  "@rollup/plugin-commonjs": "^25.0.7",
27
27
  "@rollup/plugin-node-resolve": "^15.2.3",
@@ -41,9 +41,9 @@
41
41
  "typescript": "^5.3.3"
42
42
  },
43
43
  "peerDependencies": {
44
- "@remix-run/react": "*",
45
44
  "@shopify/hydrogen": "*",
46
45
  "@shopify/remix-oxygen": "*",
47
- "react": "*"
46
+ "react": "*",
47
+ "react-router": "*"
48
48
  }
49
49
  }
@@ -1,10 +0,0 @@
1
- import React, { type Dispatch, type PropsWithChildren, type SetStateAction } from 'react';
2
- export declare const OkendoContext: React.Context<{
3
- okendoDataLoaded: boolean;
4
- setOkendoDataLoaded: Dispatch<SetStateAction<boolean>>;
5
- } | undefined>;
6
- export declare const OkendoContextProvider: ({ children }: PropsWithChildren) => React.JSX.Element;
7
- export declare const useOkendoContext: () => {
8
- okendoDataLoaded: boolean;
9
- setOkendoDataLoaded: Dispatch<SetStateAction<boolean>>;
10
- } | null;