@dutchiesdk/ecommerce-extensions-sdk 0.20.0 → 0.22.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/README.md CHANGED
@@ -307,6 +307,45 @@ const LazyFooter = createLazyRemoteBoundaryComponent(
307
307
  );
308
308
  ```
309
309
 
310
+ #### `createRemoteBoundaryComponent(Component)`
311
+
312
+ Wraps a component with the Data Bridge context provider synchronously. Use this instead of `createLazyRemoteBoundaryComponent` when you don't need code-splitting (e.g., the component is already in the same bundle, or you're registering a component that receives typed props like `ProductCardGridProps`).
313
+
314
+ **Signature:**
315
+
316
+ ```typescript
317
+ function createRemoteBoundaryComponent<P = WithRemoteBoundaryProps>(
318
+ Component: ComponentType
319
+ ): RemoteBoundaryComponent<P>;
320
+ ```
321
+
322
+ **Parameters:**
323
+
324
+ - `Component` - The React component to wrap with Data Bridge context
325
+
326
+ **Returns:** A `RemoteBoundaryComponent` with Data Bridge context and `DataBridgeVersion` attached
327
+
328
+ **Example:**
329
+
330
+ ```tsx
331
+ import {
332
+ createRemoteBoundaryComponent,
333
+ type ProductCardGridProps,
334
+ } from "@dutchiesdk/ecommerce-extensions-sdk";
335
+
336
+ const MyProductCard = ({ product, pricing, onAddToCart }: ProductCardGridProps) => {
337
+ return (
338
+ <div>
339
+ <h3>{product.name}</h3>
340
+ <p>{pricing.displayPrice}</p>
341
+ <button onClick={onAddToCart}>{pricing.buttonCopy}</button>
342
+ </div>
343
+ );
344
+ };
345
+
346
+ export default createRemoteBoundaryComponent<ProductCardGridProps>(MyProductCard);
347
+ ```
348
+
310
349
  ### Context
311
350
 
312
351
  #### `DataBridgeContext`
@@ -400,6 +439,16 @@ import type {
400
439
  MetaFields,
401
440
  StoreFrontMetaFieldsFunction,
402
441
 
442
+ // Product card types
443
+ ProductCardProductData,
444
+ ProductCardImage,
445
+ ProductCardBadgeData,
446
+ ProductCardPricingData,
447
+ ProductCardOptionData,
448
+ ProductCardOptionsData,
449
+ ProductCardGridProps,
450
+ ProductCardListItemProps,
451
+
403
452
  // Events
404
453
  Events,
405
454
  OnAfterCheckoutData,
@@ -876,6 +925,93 @@ The menu context indicates which interface the extension is running in:
876
925
  - `'store-front'` - Online storefront for customers
877
926
  - `'kiosk'` - In-store kiosk interface
878
927
 
928
+ #### Product Card Types
929
+
930
+ The SDK provides types for building custom product card extensions. These types are passed as props to components registered as `ProductCard` (grid layout) and `ProductCardListItem` (list layout) in the module registry.
931
+
932
+ ```typescript
933
+ type ProductCardImage = {
934
+ url: string;
935
+ description?: string;
936
+ };
937
+
938
+ type ProductCardProductData = {
939
+ id: string;
940
+ name: string;
941
+ brandName: string;
942
+ href: string;
943
+ strainType: string | null;
944
+ potency: string[];
945
+ images: ProductCardImage[];
946
+ fallbackImageUrl: string;
947
+ };
948
+
949
+ type ProductCardBadgeData = {
950
+ isStaffPick: boolean;
951
+ isSponsored: boolean;
952
+ isSpecialOffer: boolean;
953
+ specialNames: string[];
954
+ hideSalesLanguage: boolean;
955
+ collectionBadge: {
956
+ title: string;
957
+ color: string | null;
958
+ isExclusive: boolean;
959
+ } | null;
960
+ };
961
+
962
+ type ProductCardPricingData = {
963
+ displayPrice: string;
964
+ standardPrice: string | null;
965
+ discount: string | null;
966
+ weight: string;
967
+ showWeight: boolean;
968
+ buttonCopy: string;
969
+ };
970
+
971
+ type ProductCardOptionData = {
972
+ value: string;
973
+ label: string;
974
+ currentPrice: string;
975
+ originalPrice: string | null;
976
+ discountLabel: string | null;
977
+ };
978
+
979
+ type ProductCardOptionsData = {
980
+ items: ProductCardOptionData[];
981
+ totalCount: number;
982
+ hasMultiple: boolean;
983
+ shouldDisplayLabel: boolean;
984
+ };
985
+ ```
986
+
987
+ **Grid Card Props** (passed to `ProductCard` extensions):
988
+
989
+ ```typescript
990
+ type ProductCardGridProps = {
991
+ product: ProductCardProductData;
992
+ pricing: ProductCardPricingData;
993
+ options: ProductCardOptionsData;
994
+ badges: ProductCardBadgeData;
995
+ onLinkClick: () => void;
996
+ onAddToCart: () => void;
997
+ productIndex: number;
998
+ };
999
+ ```
1000
+
1001
+ **List Card Props** (passed to `ProductCardListItem` extensions):
1002
+
1003
+ ```typescript
1004
+ type ProductCardListItemProps = {
1005
+ product: ProductCardProductData;
1006
+ pricing: ProductCardPricingData;
1007
+ options: ProductCardOptionsData;
1008
+ badges: ProductCardBadgeData;
1009
+ onLinkClick: () => void;
1010
+ onOptionClick: (value: string) => void;
1011
+ productIndex: number;
1012
+ };
1013
+ ```
1014
+
879
1015
  ## Extension Development
880
1016
 
881
1017
  ### Creating Components
@@ -955,6 +1091,10 @@ type RemoteModuleRegistry = {
955
1091
  ProductDetailsPrimary?: ModuleRegistryEntry;
956
1092
  ListPageHero?: ModuleRegistryEntry;
957
1093
 
1094
+ // Custom product cards
1095
+ ProductCard?: ModuleRegistryEntry;
1096
+ ProductCardListItem?: ModuleRegistryEntry;
1097
+
958
1098
  // Category page components (indexed by pagination page number)
959
1099
  CategoryPageInterstitials?: ListPageEntry[];
960
1100
  CategoryPageSlots?: ListPageEntry[];
@@ -1179,6 +1319,114 @@ export default {
1179
1319
  } satisfies RemoteModuleRegistry;
1180
1320
  ```
1181
1321
 
1322
+ #### Custom Product Cards
1323
+
1324
+ Register custom product card components to replace the default grid and list cards across the storefront. The platform passes pre-computed product data, pricing, badges, and callbacks as props.
1325
+
1326
+ **Grid Card:**
1327
+
1328
+ ```tsx
1329
+ import type {
1330
+ RemoteBoundaryComponent,
1331
+ ProductCardGridProps,
1332
+ } from "@dutchiesdk/ecommerce-extensions-sdk";
1333
+ import { DataBridgeVersion } from "@dutchiesdk/ecommerce-extensions-sdk";
1334
+
1335
+ const CustomProductCard: RemoteBoundaryComponent<ProductCardGridProps> = ({
1336
+ product,
1337
+ pricing,
1338
+ badges,
1339
+ onLinkClick,
1340
+ onAddToCart,
1341
+ }) => {
1342
+ return (
1343
+ <div onClick={onLinkClick}>
1344
+ <img
1345
+ src={product.images[0]?.url || product.fallbackImageUrl}
1346
+ alt={product.name}
1347
+ />
1348
+ {badges.isStaffPick && <span>Staff Pick</span>}
1349
+ <h3>{product.name}</h3>
1350
+ <p>{product.brandName}</p>
1351
+ <p>{pricing.displayPrice}</p>
1352
+ {pricing.discount && <span>{pricing.discount} off</span>}
1353
+ <button
1354
+ onClick={(e) => {
1355
+ e.stopPropagation();
1356
+ onAddToCart();
1357
+ }}
1358
+ >
1359
+ {pricing.buttonCopy}
1360
+ </button>
1361
+ </div>
1362
+ );
1363
+ };
1364
+
1365
+ CustomProductCard.DataBridgeVersion = DataBridgeVersion;
1366
+ export default CustomProductCard;
1367
+ ```
1368
+
1369
+ **List Card:**
1370
+
1371
+ ```tsx
1372
+ import type {
1373
+ RemoteBoundaryComponent,
1374
+ ProductCardListItemProps,
1375
+ } from "@dutchiesdk/ecommerce-extensions-sdk";
1376
+ import { DataBridgeVersion } from "@dutchiesdk/ecommerce-extensions-sdk";
1377
+
1378
+ const CustomListItem: RemoteBoundaryComponent<ProductCardListItemProps> = ({
1379
+ product,
1380
+ pricing,
1381
+ options,
1382
+ onLinkClick,
1383
+ onOptionClick,
1384
+ }) => {
1385
+ return (
1386
+ <div onClick={onLinkClick}>
1387
+ <img
1388
+ src={product.images[0]?.url || product.fallbackImageUrl}
1389
+ alt={product.name}
1390
+ />
1391
+ <div>
1392
+ <h3>{product.name}</h3>
1393
+ <p>{product.brandName}</p>
1394
+ {options.items.map((option) => (
1395
+ <button
1396
+ key={option.value}
1397
+ onClick={(e) => {
1398
+ e.stopPropagation();
1399
+ onOptionClick(option.value);
1400
+ }}
1401
+ >
1402
+ {option.label} — {option.currentPrice}
1403
+ </button>
1404
+ ))}
1405
+ </div>
1406
+ </div>
1407
+ );
1408
+ };
1409
+
1410
+ CustomListItem.DataBridgeVersion = DataBridgeVersion;
1411
+ export default CustomListItem;
1412
+ ```
1413
+
1414
+ **Registration:**
1415
+
1416
+ ```tsx
1417
+ import type { RemoteModuleRegistry } from "@dutchiesdk/ecommerce-extensions-sdk";
1418
+ import { createLazyRemoteBoundaryComponent } from "@dutchiesdk/ecommerce-extensions-sdk";
1419
+
1420
+ export default {
1421
+ ProductCard: createLazyRemoteBoundaryComponent(
1422
+ () => import("./components/CustomProductCard")
1423
+ ),
1424
+ ProductCardListItem: createLazyRemoteBoundaryComponent(
1425
+ () => import("./components/CustomListItem")
1426
+ ),
1427
+ } satisfies RemoteModuleRegistry;
1428
+ ```
1429
+
1182
1430
  ### Meta Fields & SEO
1183
1431
 
1184
1432
  The `getStoreFrontMetaFields` function allows you to dynamically generate page metadata (title, description, Open Graph tags, structured data) based on the current page and available data.
@@ -24,17 +24,21 @@ var __webpack_require__ = {};
24
24
  var __webpack_exports__ = {};
25
25
  __webpack_require__.r(__webpack_exports__);
26
26
  __webpack_require__.d(__webpack_exports__, {
27
+ withRemoteBoundary: ()=>withRemoteBoundary,
27
28
  createLazyRemoteBoundaryComponent: ()=>createLazyRemoteBoundaryComponent,
28
- withRemoteBoundary: ()=>withRemoteBoundary
29
+ createRemoteBoundaryComponent: ()=>createRemoteBoundaryComponent
29
30
  });
30
31
  const jsx_runtime_namespaceObject = require("react/jsx-runtime");
31
32
  const external_react_namespaceObject = require("react");
32
33
  const ecommerce_data_bridge_cjs_namespaceObject = require("../context/ecommerce-data-bridge.cjs");
33
34
  const withRemoteBoundary = (WrappedComponent)=>{
34
- function WithRemoteBoundaryComponent({ data }) {
35
+ function WithRemoteBoundaryComponent(props) {
36
+ const { __dsdk__dataBridgeData, data, ...rest } = props;
35
37
  return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(ecommerce_data_bridge_cjs_namespaceObject.DataBridgeContext.Provider, {
36
- value: data,
37
- children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(WrappedComponent, {})
38
+ value: __dsdk__dataBridgeData ?? data,
39
+ children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(WrappedComponent, {
40
+ ...rest
41
+ })
38
42
  });
39
43
  }
40
44
  WithRemoteBoundaryComponent.DataBridgeVersion = ecommerce_data_bridge_cjs_namespaceObject.DataBridgeVersion;
@@ -44,31 +48,39 @@ function createLazyRemoteBoundaryComponent(importFn, options = {}) {
44
48
  const { fallback, onError } = options;
45
49
  const LazyComponent = /*#__PURE__*/ (0, external_react_namespaceObject.lazy)(async ()=>{
46
50
  try {
47
- const module = await importFn();
48
- const WrappedComponent = withRemoteBoundary(module.default);
49
- return {
50
- default: WrappedComponent
51
- };
51
+ return await importFn();
52
52
  } catch (error) {
53
53
  onError?.(error);
54
54
  throw error;
55
55
  }
56
56
  });
57
57
  function LazyRemoteBoundaryWrapper(props) {
58
- return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_react_namespaceObject.Suspense, {
59
- fallback: fallback || null,
60
- children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(LazyComponent, {
61
- ...props
58
+ const { __dsdk__dataBridgeData, data, ...rest } = props;
59
+ return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(ecommerce_data_bridge_cjs_namespaceObject.DataBridgeContext.Provider, {
60
+ value: __dsdk__dataBridgeData ?? data,
61
+ children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_react_namespaceObject.Suspense, {
62
+ fallback: fallback || null,
63
+ children: /*#__PURE__*/ (0, external_react_namespaceObject.createElement)(LazyComponent, rest)
62
64
  })
63
65
  });
64
66
  }
65
67
  LazyRemoteBoundaryWrapper.DataBridgeVersion = ecommerce_data_bridge_cjs_namespaceObject.DataBridgeVersion;
66
68
  return LazyRemoteBoundaryWrapper;
67
69
  }
70
+ function createRemoteBoundaryComponent(Component) {
71
+ const Wrapped = withRemoteBoundary(Component);
72
+ function RemoteBoundaryWrapper(props) {
73
+ return /*#__PURE__*/ (0, external_react_namespaceObject.createElement)(Wrapped, props);
74
+ }
75
+ RemoteBoundaryWrapper.DataBridgeVersion = ecommerce_data_bridge_cjs_namespaceObject.DataBridgeVersion;
76
+ return RemoteBoundaryWrapper;
77
+ }
68
78
  exports.createLazyRemoteBoundaryComponent = __webpack_exports__.createLazyRemoteBoundaryComponent;
79
+ exports.createRemoteBoundaryComponent = __webpack_exports__.createRemoteBoundaryComponent;
69
80
  exports.withRemoteBoundary = __webpack_exports__.withRemoteBoundary;
70
81
  for(var __webpack_i__ in __webpack_exports__)if (-1 === [
71
82
  "createLazyRemoteBoundaryComponent",
83
+ "createRemoteBoundaryComponent",
72
84
  "withRemoteBoundary"
73
85
  ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
74
86
  Object.defineProperty(exports, '__esModule', {
@@ -1,18 +1,23 @@
1
1
  import { type ComponentType, type ReactNode } from 'react';
2
- import type { RemoteBoundaryComponent } from '../types/ecommerce-extension';
2
+ import type { RemoteBoundaryComponent, SupportedDirectProps } from '../types/ecommerce-extension';
3
3
  import type { CommerceComponentsDataInterface } from '../types/interface';
4
- type WithRemoteBoundaryProps = {
4
+ export type WithRemoteBoundaryProps = {
5
+ __dsdk__dataBridgeData?: CommerceComponentsDataInterface;
6
+ /** @deprecated Use __dsdk__dataBridgeData instead */
5
7
  data?: CommerceComponentsDataInterface;
6
8
  };
7
- export declare const withRemoteBoundary: (WrappedComponent: ComponentType) => {
8
- ({ data }: WithRemoteBoundaryProps): import("react/jsx-runtime").JSX.Element;
9
+ /** Wraps a component so it receives data bridge context, while forwarding SDK-defined props (e.g. ProductCardGridProps). */
10
+ export declare const withRemoteBoundary: <P extends SupportedDirectProps = {}>(WrappedComponent: ComponentType<P>) => {
11
+ (props: P & WithRemoteBoundaryProps): import("react/jsx-runtime").JSX.Element;
9
12
  DataBridgeVersion: string;
10
13
  };
11
14
  interface LazyRemoteBoundaryOptions {
12
15
  fallback?: ReactNode;
13
16
  onError?: (error: Error) => void;
14
17
  }
15
- export declare function createLazyRemoteBoundaryComponent<P extends WithRemoteBoundaryProps = WithRemoteBoundaryProps>(importFn: () => Promise<{
16
- default: ComponentType;
17
- }>, options?: LazyRemoteBoundaryOptions): RemoteBoundaryComponent<P>;
18
+ export declare function createLazyRemoteBoundaryComponent<P extends SupportedDirectProps = {}>(importFn: () => Promise<{
19
+ default: ComponentType<P>;
20
+ }>, options?: LazyRemoteBoundaryOptions): RemoteBoundaryComponent<P & WithRemoteBoundaryProps>;
21
+ /** Wraps a component with the data bridge context (non-lazy). */
22
+ export declare function createRemoteBoundaryComponent<P extends SupportedDirectProps = {}>(Component: ComponentType<P>): RemoteBoundaryComponent<P & WithRemoteBoundaryProps>;
18
23
  export {};
@@ -30,7 +30,7 @@ __webpack_require__.d(__webpack_exports__, {
30
30
  useDataBridge: ()=>useDataBridge
31
31
  });
32
32
  const external_react_namespaceObject = require("react");
33
- const DataBridgeVersion = '0.20.0';
33
+ const DataBridgeVersion = '0.22.0';
34
34
  const DataBridgeContext = (0, external_react_namespaceObject.createContext)(void 0);
35
35
  const useDataBridge = ()=>{
36
36
  const context = (0, external_react_namespaceObject.useContext)(DataBridgeContext);
@@ -1,18 +1,23 @@
1
1
  import { type ComponentType, type ReactNode } from 'react';
2
- import type { RemoteBoundaryComponent } from '../types/ecommerce-extension';
2
+ import type { RemoteBoundaryComponent, SupportedDirectProps } from '../types/ecommerce-extension';
3
3
  import type { CommerceComponentsDataInterface } from '../types/interface';
4
- type WithRemoteBoundaryProps = {
4
+ export type WithRemoteBoundaryProps = {
5
+ __dsdk__dataBridgeData?: CommerceComponentsDataInterface;
6
+ /** @deprecated Use __dsdk__dataBridgeData instead */
5
7
  data?: CommerceComponentsDataInterface;
6
8
  };
7
- export declare const withRemoteBoundary: (WrappedComponent: ComponentType) => {
8
- ({ data }: WithRemoteBoundaryProps): import("react/jsx-runtime").JSX.Element;
9
+ /** Wraps a component so it receives data bridge context, while forwarding SDK-defined props (e.g. ProductCardGridProps). */
10
+ export declare const withRemoteBoundary: <P extends SupportedDirectProps = {}>(WrappedComponent: ComponentType<P>) => {
11
+ (props: P & WithRemoteBoundaryProps): import("react/jsx-runtime").JSX.Element;
9
12
  DataBridgeVersion: string;
10
13
  };
11
14
  interface LazyRemoteBoundaryOptions {
12
15
  fallback?: ReactNode;
13
16
  onError?: (error: Error) => void;
14
17
  }
15
- export declare function createLazyRemoteBoundaryComponent<P extends WithRemoteBoundaryProps = WithRemoteBoundaryProps>(importFn: () => Promise<{
16
- default: ComponentType;
17
- }>, options?: LazyRemoteBoundaryOptions): RemoteBoundaryComponent<P>;
18
+ export declare function createLazyRemoteBoundaryComponent<P extends SupportedDirectProps = {}>(importFn: () => Promise<{
19
+ default: ComponentType<P>;
20
+ }>, options?: LazyRemoteBoundaryOptions): RemoteBoundaryComponent<P & WithRemoteBoundaryProps>;
21
+ /** Wraps a component with the data bridge context (non-lazy). */
22
+ export declare function createRemoteBoundaryComponent<P extends SupportedDirectProps = {}>(Component: ComponentType<P>): RemoteBoundaryComponent<P & WithRemoteBoundaryProps>;
18
23
  export {};
@@ -1,11 +1,14 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import { Suspense, lazy } from "react";
2
+ import { Suspense, createElement, lazy } from "react";
3
3
  import { DataBridgeContext, DataBridgeVersion } from "../context/ecommerce-data-bridge.js";
4
4
  const withRemoteBoundary = (WrappedComponent)=>{
5
- function WithRemoteBoundaryComponent({ data }) {
5
+ function WithRemoteBoundaryComponent(props) {
6
+ const { __dsdk__dataBridgeData, data, ...rest } = props;
6
7
  return /*#__PURE__*/ jsx(DataBridgeContext.Provider, {
7
- value: data,
8
- children: /*#__PURE__*/ jsx(WrappedComponent, {})
8
+ value: __dsdk__dataBridgeData ?? data,
9
+ children: /*#__PURE__*/ jsx(WrappedComponent, {
10
+ ...rest
11
+ })
9
12
  });
10
13
  }
11
14
  WithRemoteBoundaryComponent.DataBridgeVersion = DataBridgeVersion;
@@ -15,25 +18,31 @@ function createLazyRemoteBoundaryComponent(importFn, options = {}) {
15
18
  const { fallback, onError } = options;
16
19
  const LazyComponent = /*#__PURE__*/ lazy(async ()=>{
17
20
  try {
18
- const module = await importFn();
19
- const WrappedComponent = withRemoteBoundary(module.default);
20
- return {
21
- default: WrappedComponent
22
- };
21
+ return await importFn();
23
22
  } catch (error) {
24
23
  onError?.(error);
25
24
  throw error;
26
25
  }
27
26
  });
28
27
  function LazyRemoteBoundaryWrapper(props) {
29
- return /*#__PURE__*/ jsx(Suspense, {
30
- fallback: fallback || null,
31
- children: /*#__PURE__*/ jsx(LazyComponent, {
32
- ...props
28
+ const { __dsdk__dataBridgeData, data, ...rest } = props;
29
+ return /*#__PURE__*/ jsx(DataBridgeContext.Provider, {
30
+ value: __dsdk__dataBridgeData ?? data,
31
+ children: /*#__PURE__*/ jsx(Suspense, {
32
+ fallback: fallback || null,
33
+ children: /*#__PURE__*/ createElement(LazyComponent, rest)
33
34
  })
34
35
  });
35
36
  }
36
37
  LazyRemoteBoundaryWrapper.DataBridgeVersion = DataBridgeVersion;
37
38
  return LazyRemoteBoundaryWrapper;
38
39
  }
39
- export { createLazyRemoteBoundaryComponent, withRemoteBoundary };
40
+ function createRemoteBoundaryComponent(Component) {
41
+ const Wrapped = withRemoteBoundary(Component);
42
+ function RemoteBoundaryWrapper(props) {
43
+ return /*#__PURE__*/ createElement(Wrapped, props);
44
+ }
45
+ RemoteBoundaryWrapper.DataBridgeVersion = DataBridgeVersion;
46
+ return RemoteBoundaryWrapper;
47
+ }
48
+ export { createLazyRemoteBoundaryComponent, createRemoteBoundaryComponent, withRemoteBoundary };
@@ -1,5 +1,5 @@
1
1
  import { createContext, useContext, useEffect, useState } from "react";
2
- const DataBridgeVersion = '0.20.0';
2
+ const DataBridgeVersion = '0.22.0';
3
3
  const DataBridgeContext = createContext(void 0);
4
4
  const useDataBridge = ()=>{
5
5
  const context = useContext(DataBridgeContext);
@@ -5,3 +5,4 @@ export * from './types/data';
5
5
  export * from './types/ecommerce-extension';
6
6
  export * from './types/events';
7
7
  export * from './types/interface';
8
+ export * from './types/product-card';
package/dist/esm/index.js CHANGED
@@ -5,3 +5,4 @@ export * from "./types/data.js";
5
5
  export * from "./types/ecommerce-extension.js";
6
6
  export * from "./types/events.js";
7
7
  export * from "./types/interface.js";
8
+ export * from "./types/product-card.js";
@@ -2,13 +2,16 @@ import type React from 'react';
2
2
  import type { MenuContext } from './data';
3
3
  import type { Events } from './events';
4
4
  import type { CommerceComponentsDataInterface } from './interface';
5
+ import type { ProductCardGridProps, ProductCardListItemProps } from './product-card';
6
+ /** Union of SDK-defined direct prop types that can be passed through the remote boundary. */
7
+ export type SupportedDirectProps = {} | ProductCardGridProps | ProductCardListItemProps;
5
8
  export type RemoteBoundaryComponent<P = {}> = React.FC<P> & {
6
9
  DataBridgeVersion: string;
7
10
  };
8
11
  export type MenuSpecificRemoteComponent = {
9
12
  [key in MenuContext]?: RemoteBoundaryComponent;
10
13
  };
11
- export type ModuleRegistryEntry = MenuSpecificRemoteComponent | RemoteBoundaryComponent;
14
+ export type ModuleRegistryEntry = MenuSpecificRemoteComponent | RemoteBoundaryComponent | RemoteBoundaryComponent<SupportedDirectProps>;
12
15
  export type RoutablePageRegistryEntry = {
13
16
  component: RemoteBoundaryComponent;
14
17
  path: string;
@@ -55,9 +58,15 @@ export type RemoteModuleRegistry = {
55
58
  StoreFrontHeader?: ModuleRegistryEntry;
56
59
  StoreFrontNavigation?: ModuleRegistryEntry;
57
60
  StoreFrontFooter?: ModuleRegistryEntry;
61
+ /** CSS-in-JS global stylesheet injected at the theme provider level */
62
+ GlobalStyles?: ModuleRegistryEntry;
58
63
  StoreFrontCarouselInterstitials?: ModuleRegistryEntry[];
59
64
  StoreFrontHero?: ModuleRegistryEntry;
60
65
  ProductDetailsPrimary?: ModuleRegistryEntry;
66
+ /** Custom grid product card rendered in category pages and carousels */
67
+ ProductCard?: ModuleRegistryEntry;
68
+ /** Custom list-view product card rendered in list layout */
69
+ ProductCardListItem?: ModuleRegistryEntry;
61
70
  ListPageHero?: ModuleRegistryEntry;
62
71
  /**
63
72
  * Function that provides meta fields for the current page.
@@ -0,0 +1,65 @@
1
+ export type ProductCardImage = {
2
+ url: string;
3
+ description?: string;
4
+ };
5
+ export type ProductCardProductData = {
6
+ id: string;
7
+ name: string;
8
+ brandName: string;
9
+ href: string;
10
+ strainType: string | null;
11
+ potency: string[];
12
+ images: ProductCardImage[];
13
+ fallbackImageUrl: string;
14
+ };
15
+ export type ProductCardBadgeData = {
16
+ isStaffPick: boolean;
17
+ isSponsored: boolean;
18
+ isSpecialOffer: boolean;
19
+ specialNames: string[];
20
+ hideSalesLanguage: boolean;
21
+ collectionBadge: {
22
+ title: string;
23
+ color: string | null;
24
+ isExclusive: boolean;
25
+ } | null;
26
+ };
27
+ export type ProductCardPricingData = {
28
+ displayPrice: string;
29
+ standardPrice: string | null;
30
+ discount: string | null;
31
+ weight: string;
32
+ showWeight: boolean;
33
+ buttonCopy: string;
34
+ };
35
+ export type ProductCardOptionData = {
36
+ value: string;
37
+ label: string;
38
+ currentPrice: string;
39
+ originalPrice: string | null;
40
+ discountLabel: string | null;
41
+ };
42
+ export type ProductCardOptionsData = {
43
+ items: ProductCardOptionData[];
44
+ totalCount: number;
45
+ hasMultiple: boolean;
46
+ shouldDisplayLabel: boolean;
47
+ };
48
+ export type ProductCardGridProps = {
49
+ product: ProductCardProductData;
50
+ pricing: ProductCardPricingData;
51
+ options: ProductCardOptionsData;
52
+ badges: ProductCardBadgeData;
53
+ onLinkClick: () => void;
54
+ onAddToCart: () => void;
55
+ productIndex: number;
56
+ };
57
+ export type ProductCardListItemProps = {
58
+ product: ProductCardProductData;
59
+ pricing: ProductCardPricingData;
60
+ options: ProductCardOptionsData;
61
+ badges: ProductCardBadgeData;
62
+ onLinkClick: () => void;
63
+ onOptionClick: (value: string) => void;
64
+ productIndex: number;
65
+ };
File without changes
package/dist/index.cjs CHANGED
@@ -20,6 +20,9 @@ var __webpack_modules__ = {
20
20
  },
21
21
  "./types/interface": function(module) {
22
22
  module.exports = require("./types/interface.cjs");
23
+ },
24
+ "./types/product-card": function(module) {
25
+ module.exports = require("./types/product-card.cjs");
23
26
  }
24
27
  };
25
28
  var __webpack_module_cache__ = {};
@@ -107,6 +110,12 @@ var __webpack_exports__ = {};
107
110
  return _types_interface__WEBPACK_IMPORTED_MODULE_6__[key];
108
111
  }).bind(0, __WEBPACK_IMPORT_KEY__);
109
112
  __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__);
113
+ var _types_product_card__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("./types/product-card");
114
+ var __WEBPACK_REEXPORT_OBJECT__ = {};
115
+ for(var __WEBPACK_IMPORT_KEY__ in _types_product_card__WEBPACK_IMPORTED_MODULE_7__)if ("default" !== __WEBPACK_IMPORT_KEY__) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = (function(key) {
116
+ return _types_product_card__WEBPACK_IMPORTED_MODULE_7__[key];
117
+ }).bind(0, __WEBPACK_IMPORT_KEY__);
118
+ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__);
110
119
  })();
111
120
  for(var __webpack_i__ in __webpack_exports__)exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
112
121
  Object.defineProperty(exports, '__esModule', {
package/dist/index.d.ts CHANGED
@@ -5,3 +5,4 @@ export * from './types/data';
5
5
  export * from './types/ecommerce-extension';
6
6
  export * from './types/events';
7
7
  export * from './types/interface';
8
+ export * from './types/product-card';
@@ -2,13 +2,16 @@ import type React from 'react';
2
2
  import type { MenuContext } from './data';
3
3
  import type { Events } from './events';
4
4
  import type { CommerceComponentsDataInterface } from './interface';
5
+ import type { ProductCardGridProps, ProductCardListItemProps } from './product-card';
6
+ /** Union of SDK-defined direct prop types that can be passed through the remote boundary. */
7
+ export type SupportedDirectProps = {} | ProductCardGridProps | ProductCardListItemProps;
5
8
  export type RemoteBoundaryComponent<P = {}> = React.FC<P> & {
6
9
  DataBridgeVersion: string;
7
10
  };
8
11
  export type MenuSpecificRemoteComponent = {
9
12
  [key in MenuContext]?: RemoteBoundaryComponent;
10
13
  };
11
- export type ModuleRegistryEntry = MenuSpecificRemoteComponent | RemoteBoundaryComponent;
14
+ export type ModuleRegistryEntry = MenuSpecificRemoteComponent | RemoteBoundaryComponent | RemoteBoundaryComponent<SupportedDirectProps>;
12
15
  export type RoutablePageRegistryEntry = {
13
16
  component: RemoteBoundaryComponent;
14
17
  path: string;
@@ -55,9 +58,15 @@ export type RemoteModuleRegistry = {
55
58
  StoreFrontHeader?: ModuleRegistryEntry;
56
59
  StoreFrontNavigation?: ModuleRegistryEntry;
57
60
  StoreFrontFooter?: ModuleRegistryEntry;
61
+ /** CSS-in-JS global stylesheet injected at the theme provider level */
62
+ GlobalStyles?: ModuleRegistryEntry;
58
63
  StoreFrontCarouselInterstitials?: ModuleRegistryEntry[];
59
64
  StoreFrontHero?: ModuleRegistryEntry;
60
65
  ProductDetailsPrimary?: ModuleRegistryEntry;
66
+ /** Custom grid product card rendered in category pages and carousels */
67
+ ProductCard?: ModuleRegistryEntry;
68
+ /** Custom list-view product card rendered in list layout */
69
+ ProductCardListItem?: ModuleRegistryEntry;
61
70
  ListPageHero?: ModuleRegistryEntry;
62
71
  /**
63
72
  * Function that provides meta fields for the current page.
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.r = (exports1)=>{
5
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
6
+ value: 'Module'
7
+ });
8
+ Object.defineProperty(exports1, '__esModule', {
9
+ value: true
10
+ });
11
+ };
12
+ })();
13
+ var __webpack_exports__ = {};
14
+ __webpack_require__.r(__webpack_exports__);
15
+ for(var __webpack_i__ in __webpack_exports__)exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
16
+ Object.defineProperty(exports, '__esModule', {
17
+ value: true
18
+ });
@@ -0,0 +1,65 @@
1
+ export type ProductCardImage = {
2
+ url: string;
3
+ description?: string;
4
+ };
5
+ export type ProductCardProductData = {
6
+ id: string;
7
+ name: string;
8
+ brandName: string;
9
+ href: string;
10
+ strainType: string | null;
11
+ potency: string[];
12
+ images: ProductCardImage[];
13
+ fallbackImageUrl: string;
14
+ };
15
+ export type ProductCardBadgeData = {
16
+ isStaffPick: boolean;
17
+ isSponsored: boolean;
18
+ isSpecialOffer: boolean;
19
+ specialNames: string[];
20
+ hideSalesLanguage: boolean;
21
+ collectionBadge: {
22
+ title: string;
23
+ color: string | null;
24
+ isExclusive: boolean;
25
+ } | null;
26
+ };
27
+ export type ProductCardPricingData = {
28
+ displayPrice: string;
29
+ standardPrice: string | null;
30
+ discount: string | null;
31
+ weight: string;
32
+ showWeight: boolean;
33
+ buttonCopy: string;
34
+ };
35
+ export type ProductCardOptionData = {
36
+ value: string;
37
+ label: string;
38
+ currentPrice: string;
39
+ originalPrice: string | null;
40
+ discountLabel: string | null;
41
+ };
42
+ export type ProductCardOptionsData = {
43
+ items: ProductCardOptionData[];
44
+ totalCount: number;
45
+ hasMultiple: boolean;
46
+ shouldDisplayLabel: boolean;
47
+ };
48
+ export type ProductCardGridProps = {
49
+ product: ProductCardProductData;
50
+ pricing: ProductCardPricingData;
51
+ options: ProductCardOptionsData;
52
+ badges: ProductCardBadgeData;
53
+ onLinkClick: () => void;
54
+ onAddToCart: () => void;
55
+ productIndex: number;
56
+ };
57
+ export type ProductCardListItemProps = {
58
+ product: ProductCardProductData;
59
+ pricing: ProductCardPricingData;
60
+ options: ProductCardOptionsData;
61
+ badges: ProductCardBadgeData;
62
+ onLinkClick: () => void;
63
+ onOptionClick: (value: string) => void;
64
+ productIndex: number;
65
+ };
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "version": "0.20.0",
7
+ "version": "0.22.0",
8
8
  "license": "MIT",
9
9
  "type": "module",
10
10
  "module": "./dist/esm/index.js",