@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 +248 -0
- package/dist/components/remote-boundary.cjs +25 -13
- package/dist/components/remote-boundary.d.ts +12 -7
- package/dist/context/ecommerce-data-bridge.cjs +1 -1
- package/dist/esm/components/remote-boundary.d.ts +12 -7
- package/dist/esm/components/remote-boundary.js +23 -14
- package/dist/esm/context/ecommerce-data-bridge.js +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/types/ecommerce-extension.d.ts +10 -1
- package/dist/esm/types/product-card.d.ts +65 -0
- package/dist/esm/types/product-card.js +0 -0
- package/dist/index.cjs +9 -0
- package/dist/index.d.ts +1 -0
- package/dist/types/ecommerce-extension.d.ts +10 -1
- package/dist/types/product-card.cjs +18 -0
- package/dist/types/product-card.d.ts +65 -0
- package/package.json +1 -1
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
8
|
-
|
|
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
|
|
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.
|
|
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
|
-
|
|
8
|
-
|
|
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
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
|
|
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.
|
|
2
|
+
const DataBridgeVersion = '0.22.0';
|
|
3
3
|
const DataBridgeContext = createContext(void 0);
|
|
4
4
|
const useDataBridge = ()=>{
|
|
5
5
|
const context = useContext(DataBridgeContext);
|
package/dist/esm/index.d.ts
CHANGED
package/dist/esm/index.js
CHANGED
|
@@ -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
|
@@ -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
|
+
};
|