@shopify/hydrogen-react 2022.7.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 +218 -0
- package/dist/dev/ExternalVideo.cjs +39 -0
- package/dist/dev/ExternalVideo.cjs.map +1 -0
- package/dist/dev/ExternalVideo.js +39 -0
- package/dist/dev/ExternalVideo.js.map +1 -0
- package/dist/dev/Image.cjs +104 -0
- package/dist/dev/Image.cjs.map +1 -0
- package/dist/dev/Image.js +104 -0
- package/dist/dev/Image.js.map +1 -0
- package/dist/dev/MediaFile.cjs +57 -0
- package/dist/dev/MediaFile.cjs.map +1 -0
- package/dist/dev/MediaFile.js +57 -0
- package/dist/dev/MediaFile.js.map +1 -0
- package/dist/dev/Metafield.cjs +295 -0
- package/dist/dev/Metafield.cjs.map +1 -0
- package/dist/dev/Metafield.js +295 -0
- package/dist/dev/Metafield.js.map +1 -0
- package/dist/dev/ModelViewer.cjs +145 -0
- package/dist/dev/ModelViewer.cjs.map +1 -0
- package/dist/dev/ModelViewer.js +145 -0
- package/dist/dev/ModelViewer.js.map +1 -0
- package/dist/dev/Money.cjs +40 -0
- package/dist/dev/Money.cjs.map +1 -0
- package/dist/dev/Money.js +40 -0
- package/dist/dev/Money.js.map +1 -0
- package/dist/dev/ProductPrice.cjs +61 -0
- package/dist/dev/ProductPrice.cjs.map +1 -0
- package/dist/dev/ProductPrice.js +61 -0
- package/dist/dev/ProductPrice.js.map +1 -0
- package/dist/dev/ProductProvider.cjs +161 -0
- package/dist/dev/ProductProvider.cjs.map +1 -0
- package/dist/dev/ProductProvider.js +161 -0
- package/dist/dev/ProductProvider.js.map +1 -0
- package/dist/dev/ShopPayButton.cjs +64 -0
- package/dist/dev/ShopPayButton.cjs.map +1 -0
- package/dist/dev/ShopPayButton.js +64 -0
- package/dist/dev/ShopPayButton.js.map +1 -0
- package/dist/dev/ShopifyProvider.cjs +46 -0
- package/dist/dev/ShopifyProvider.cjs.map +1 -0
- package/dist/dev/ShopifyProvider.js +46 -0
- package/dist/dev/ShopifyProvider.js.map +1 -0
- package/dist/dev/Video.cjs +44 -0
- package/dist/dev/Video.cjs.map +1 -0
- package/dist/dev/Video.js +44 -0
- package/dist/dev/Video.js.map +1 -0
- package/dist/dev/flatten-connection.cjs +23 -0
- package/dist/dev/flatten-connection.cjs.map +1 -0
- package/dist/dev/flatten-connection.js +23 -0
- package/dist/dev/flatten-connection.js.map +1 -0
- package/dist/dev/image-size.cjs +80 -0
- package/dist/dev/image-size.cjs.map +1 -0
- package/dist/dev/image-size.js +80 -0
- package/dist/dev/image-size.js.map +1 -0
- package/dist/dev/index.cjs +35 -0
- package/dist/dev/index.cjs.map +1 -0
- package/dist/dev/index.js +35 -0
- package/dist/dev/index.js.map +1 -0
- package/dist/dev/load-script.cjs +52 -0
- package/dist/dev/load-script.cjs.map +1 -0
- package/dist/dev/load-script.js +52 -0
- package/dist/dev/load-script.js.map +1 -0
- package/dist/dev/storefront-api-constants.cjs +5 -0
- package/dist/dev/storefront-api-constants.cjs.map +1 -0
- package/dist/dev/storefront-api-constants.js +5 -0
- package/dist/dev/storefront-api-constants.js.map +1 -0
- package/dist/dev/storefront-client.cjs +72 -0
- package/dist/dev/storefront-client.cjs.map +1 -0
- package/dist/dev/storefront-client.js +72 -0
- package/dist/dev/storefront-client.js.map +1 -0
- package/dist/dev/useMoney.cjs +72 -0
- package/dist/dev/useMoney.cjs.map +1 -0
- package/dist/dev/useMoney.js +72 -0
- package/dist/dev/useMoney.js.map +1 -0
- package/dist/prod/ExternalVideo.cjs +39 -0
- package/dist/prod/ExternalVideo.cjs.map +1 -0
- package/dist/prod/ExternalVideo.js +39 -0
- package/dist/prod/ExternalVideo.js.map +1 -0
- package/dist/prod/Image.cjs +99 -0
- package/dist/prod/Image.cjs.map +1 -0
- package/dist/prod/Image.js +99 -0
- package/dist/prod/Image.js.map +1 -0
- package/dist/prod/MediaFile.cjs +59 -0
- package/dist/prod/MediaFile.cjs.map +1 -0
- package/dist/prod/MediaFile.js +59 -0
- package/dist/prod/MediaFile.js.map +1 -0
- package/dist/prod/Metafield.cjs +288 -0
- package/dist/prod/Metafield.cjs.map +1 -0
- package/dist/prod/Metafield.js +288 -0
- package/dist/prod/Metafield.js.map +1 -0
- package/dist/prod/ModelViewer.cjs +143 -0
- package/dist/prod/ModelViewer.cjs.map +1 -0
- package/dist/prod/ModelViewer.js +143 -0
- package/dist/prod/ModelViewer.js.map +1 -0
- package/dist/prod/Money.cjs +40 -0
- package/dist/prod/Money.cjs.map +1 -0
- package/dist/prod/Money.js +40 -0
- package/dist/prod/Money.js.map +1 -0
- package/dist/prod/ProductPrice.cjs +61 -0
- package/dist/prod/ProductPrice.cjs.map +1 -0
- package/dist/prod/ProductPrice.js +61 -0
- package/dist/prod/ProductPrice.js.map +1 -0
- package/dist/prod/ProductProvider.cjs +161 -0
- package/dist/prod/ProductProvider.cjs.map +1 -0
- package/dist/prod/ProductProvider.js +161 -0
- package/dist/prod/ProductProvider.js.map +1 -0
- package/dist/prod/ShopPayButton.cjs +64 -0
- package/dist/prod/ShopPayButton.cjs.map +1 -0
- package/dist/prod/ShopPayButton.js +64 -0
- package/dist/prod/ShopPayButton.js.map +1 -0
- package/dist/prod/ShopifyProvider.cjs +46 -0
- package/dist/prod/ShopifyProvider.cjs.map +1 -0
- package/dist/prod/ShopifyProvider.js +46 -0
- package/dist/prod/ShopifyProvider.js.map +1 -0
- package/dist/prod/Video.cjs +44 -0
- package/dist/prod/Video.cjs.map +1 -0
- package/dist/prod/Video.js +44 -0
- package/dist/prod/Video.js.map +1 -0
- package/dist/prod/flatten-connection.cjs +18 -0
- package/dist/prod/flatten-connection.cjs.map +1 -0
- package/dist/prod/flatten-connection.js +18 -0
- package/dist/prod/flatten-connection.js.map +1 -0
- package/dist/prod/image-size.cjs +80 -0
- package/dist/prod/image-size.cjs.map +1 -0
- package/dist/prod/image-size.js +80 -0
- package/dist/prod/image-size.js.map +1 -0
- package/dist/prod/index.cjs +35 -0
- package/dist/prod/index.cjs.map +1 -0
- package/dist/prod/index.js +35 -0
- package/dist/prod/index.js.map +1 -0
- package/dist/prod/load-script.cjs +52 -0
- package/dist/prod/load-script.cjs.map +1 -0
- package/dist/prod/load-script.js +52 -0
- package/dist/prod/load-script.js.map +1 -0
- package/dist/prod/storefront-api-constants.cjs +5 -0
- package/dist/prod/storefront-api-constants.cjs.map +1 -0
- package/dist/prod/storefront-api-constants.js +5 -0
- package/dist/prod/storefront-api-constants.js.map +1 -0
- package/dist/prod/storefront-client.cjs +57 -0
- package/dist/prod/storefront-client.cjs.map +1 -0
- package/dist/prod/storefront-client.js +57 -0
- package/dist/prod/storefront-client.js.map +1 -0
- package/dist/prod/useMoney.cjs +72 -0
- package/dist/prod/useMoney.cjs.map +1 -0
- package/dist/prod/useMoney.js +72 -0
- package/dist/prod/useMoney.js.map +1 -0
- package/dist/types/ExternalVideo.d.ts +67 -0
- package/dist/types/Image.d.ts +54 -0
- package/dist/types/MediaFile.d.ts +31 -0
- package/dist/types/Metafield.d.ts +58 -0
- package/dist/types/ModelViewer.d.ts +57 -0
- package/dist/types/Money.d.ts +29 -0
- package/dist/types/ProductPrice.d.ts +22 -0
- package/dist/types/ProductProvider.d.ts +74 -0
- package/dist/types/ShopPayButton.d.ts +42 -0
- package/dist/types/ShopifyProvider.d.ts +42 -0
- package/dist/types/Video.d.ts +20 -0
- package/dist/types/flatten-connection.d.ts +17 -0
- package/dist/types/image-size.d.ts +36 -0
- package/dist/types/index.d.cts +15 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/load-script.d.ts +11 -0
- package/dist/types/storefront-api-constants.d.ts +1 -0
- package/dist/types/storefront-api-response.types.d.ts +68 -0
- package/dist/types/storefront-api-types.d.ts +6537 -0
- package/dist/types/storefront-client.d.ts +63 -0
- package/dist/types/useMoney.d.ts +55 -0
- package/dist/umd/hydrogen-react.dev.js +1472 -0
- package/dist/umd/hydrogen-react.dev.js.map +1 -0
- package/dist/umd/hydrogen-react.prod.js +3 -0
- package/dist/umd/hydrogen-react.prod.js.map +1 -0
- package/package.json +106 -0
- package/storefront.schema.json +1 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { useState, useCallback, useEffect } from "react";
|
|
2
|
+
import { useLoadScript } from "./load-script.js";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
function ModelViewer(props) {
|
|
5
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
6
|
+
const [modelViewer, setModelViewer] = useState(void 0);
|
|
7
|
+
const callbackRef = useCallback((node) => {
|
|
8
|
+
setModelViewer(node);
|
|
9
|
+
}, []);
|
|
10
|
+
const {
|
|
11
|
+
data,
|
|
12
|
+
children,
|
|
13
|
+
className,
|
|
14
|
+
...passthroughProps
|
|
15
|
+
} = props;
|
|
16
|
+
const modelViewerLoadedStatus = useLoadScript("https://unpkg.com/@google/model-viewer@v1.12.1/dist/model-viewer.min.js", {
|
|
17
|
+
module: true
|
|
18
|
+
});
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (!modelViewer) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (passthroughProps.onError)
|
|
24
|
+
modelViewer.addEventListener("error", passthroughProps.onError);
|
|
25
|
+
if (passthroughProps.onLoad)
|
|
26
|
+
modelViewer.addEventListener("load", passthroughProps.onLoad);
|
|
27
|
+
if (passthroughProps.onPreload)
|
|
28
|
+
modelViewer.addEventListener("preload", passthroughProps.onPreload);
|
|
29
|
+
if (passthroughProps.onModelVisibility)
|
|
30
|
+
modelViewer.addEventListener("model-visibility", passthroughProps.onModelVisibility);
|
|
31
|
+
if (passthroughProps.onProgress)
|
|
32
|
+
modelViewer.addEventListener("progress", passthroughProps.onProgress);
|
|
33
|
+
if (passthroughProps.onArStatus)
|
|
34
|
+
modelViewer.addEventListener("ar-status", passthroughProps.onArStatus);
|
|
35
|
+
if (passthroughProps.onArTracking)
|
|
36
|
+
modelViewer.addEventListener("ar-tracking", passthroughProps.onArTracking);
|
|
37
|
+
if (passthroughProps.onQuickLookButtonTapped)
|
|
38
|
+
modelViewer.addEventListener("quick-look-button-tapped", passthroughProps.onQuickLookButtonTapped);
|
|
39
|
+
if (passthroughProps.onCameraChange)
|
|
40
|
+
modelViewer.addEventListener("camera-change", passthroughProps.onCameraChange);
|
|
41
|
+
if (passthroughProps.onEnvironmentChange)
|
|
42
|
+
modelViewer.addEventListener("environment-change", passthroughProps.onEnvironmentChange);
|
|
43
|
+
if (passthroughProps.onPlay)
|
|
44
|
+
modelViewer.addEventListener("play", passthroughProps.onPlay);
|
|
45
|
+
if (passthroughProps.onPause)
|
|
46
|
+
modelViewer.addEventListener("ar-status", passthroughProps.onPause);
|
|
47
|
+
if (passthroughProps.onSceneGraphReady)
|
|
48
|
+
modelViewer.addEventListener("scene-graph-ready", passthroughProps.onSceneGraphReady);
|
|
49
|
+
return () => {
|
|
50
|
+
if (modelViewer == null) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (passthroughProps.onError)
|
|
54
|
+
modelViewer.removeEventListener("error", passthroughProps.onError);
|
|
55
|
+
if (passthroughProps.onLoad)
|
|
56
|
+
modelViewer.removeEventListener("load", passthroughProps.onLoad);
|
|
57
|
+
if (passthroughProps.onPreload)
|
|
58
|
+
modelViewer.removeEventListener("preload", passthroughProps.onPreload);
|
|
59
|
+
if (passthroughProps.onModelVisibility)
|
|
60
|
+
modelViewer.removeEventListener("model-visibility", passthroughProps.onModelVisibility);
|
|
61
|
+
if (passthroughProps.onProgress)
|
|
62
|
+
modelViewer.removeEventListener("progress", passthroughProps.onProgress);
|
|
63
|
+
if (passthroughProps.onArStatus)
|
|
64
|
+
modelViewer.removeEventListener("ar-status", passthroughProps.onArStatus);
|
|
65
|
+
if (passthroughProps.onArTracking)
|
|
66
|
+
modelViewer.removeEventListener("ar-tracking", passthroughProps.onArTracking);
|
|
67
|
+
if (passthroughProps.onQuickLookButtonTapped)
|
|
68
|
+
modelViewer.removeEventListener("quick-look-button-tapped", passthroughProps.onQuickLookButtonTapped);
|
|
69
|
+
if (passthroughProps.onCameraChange)
|
|
70
|
+
modelViewer.removeEventListener("camera-change", passthroughProps.onCameraChange);
|
|
71
|
+
if (passthroughProps.onEnvironmentChange)
|
|
72
|
+
modelViewer.removeEventListener("environment-change", passthroughProps.onEnvironmentChange);
|
|
73
|
+
if (passthroughProps.onPlay)
|
|
74
|
+
modelViewer.removeEventListener("play", passthroughProps.onPlay);
|
|
75
|
+
if (passthroughProps.onPause)
|
|
76
|
+
modelViewer.removeEventListener("ar-status", passthroughProps.onPause);
|
|
77
|
+
if (passthroughProps.onSceneGraphReady)
|
|
78
|
+
modelViewer.removeEventListener("scene-graph-ready", passthroughProps.onSceneGraphReady);
|
|
79
|
+
};
|
|
80
|
+
}, [modelViewer, passthroughProps.onArStatus, passthroughProps.onArTracking, passthroughProps.onCameraChange, passthroughProps.onEnvironmentChange, passthroughProps.onError, passthroughProps.onLoad, passthroughProps.onModelVisibility, passthroughProps.onPause, passthroughProps.onPlay, passthroughProps.onPreload, passthroughProps.onProgress, passthroughProps.onQuickLookButtonTapped, passthroughProps.onSceneGraphReady]);
|
|
81
|
+
if (modelViewerLoadedStatus !== "done") {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
if (!((_b = (_a = data.sources) == null ? void 0 : _a[0]) == null ? void 0 : _b.url)) {
|
|
85
|
+
const sourcesUrlError = `<ModelViewer/> requires 'data.sources' prop to be an array, with an object that has a property 'url' on it. Rendering 'null'`;
|
|
86
|
+
{
|
|
87
|
+
throw new Error(sourcesUrlError);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (!data.alt) {
|
|
91
|
+
console.warn(`<ModelViewer/> requires the 'data.alt' prop for accessibility`);
|
|
92
|
+
}
|
|
93
|
+
return /* @__PURE__ */ jsx("model-viewer", {
|
|
94
|
+
ref: callbackRef,
|
|
95
|
+
...passthroughProps,
|
|
96
|
+
className,
|
|
97
|
+
id: (_c = passthroughProps.id) != null ? _c : data.id,
|
|
98
|
+
src: data.sources[0].url,
|
|
99
|
+
alt: (_d = data.alt) != null ? _d : null,
|
|
100
|
+
"camera-controls": (_e = passthroughProps.cameraControls) != null ? _e : true,
|
|
101
|
+
poster: (_g = passthroughProps.poster || ((_f = data.previewImage) == null ? void 0 : _f.url)) != null ? _g : null,
|
|
102
|
+
autoplay: (_h = passthroughProps.autoplay) != null ? _h : true,
|
|
103
|
+
loading: passthroughProps.loading,
|
|
104
|
+
reveal: passthroughProps.reveal,
|
|
105
|
+
ar: passthroughProps.ar,
|
|
106
|
+
"ar-modes": passthroughProps.arModes,
|
|
107
|
+
"ar-scale": passthroughProps.arScale,
|
|
108
|
+
"ar-placement": passthroughProps.arPlacement,
|
|
109
|
+
"ios-src": passthroughProps.iosSrc,
|
|
110
|
+
"touch-action": passthroughProps.touchAction,
|
|
111
|
+
"disable-zoom": passthroughProps.disableZoom,
|
|
112
|
+
"orbit-sensitivity": passthroughProps.orbitSensitivity,
|
|
113
|
+
"auto-rotate": passthroughProps.autoRotate,
|
|
114
|
+
"auto-rotate-delay": passthroughProps.autoRotateDelay,
|
|
115
|
+
"rotation-per-second": passthroughProps.rotationPerSecond,
|
|
116
|
+
"interaction-policy": passthroughProps.interactionPolicy,
|
|
117
|
+
"interaction-prompt": passthroughProps.interactionPrompt,
|
|
118
|
+
"interaction-prompt-style": passthroughProps.interactionPromptStyle,
|
|
119
|
+
"interaction-prompt-threshold": passthroughProps.interactionPromptThreshold,
|
|
120
|
+
"camera-orbit": passthroughProps.cameraOrbit,
|
|
121
|
+
"camera-target": passthroughProps.cameraTarget,
|
|
122
|
+
"field-of-view": passthroughProps.fieldOfView,
|
|
123
|
+
"max-camera-orbit": passthroughProps.maxCameraOrbit,
|
|
124
|
+
"min-camera-orbit": passthroughProps.minCameraOrbit,
|
|
125
|
+
"max-field-of-view": passthroughProps.maxFieldOfView,
|
|
126
|
+
"min-field-of-view": passthroughProps.minFieldOfView,
|
|
127
|
+
bounds: passthroughProps.bounds,
|
|
128
|
+
"interpolation-decay": (_i = passthroughProps.interpolationDecay) != null ? _i : 100,
|
|
129
|
+
"skybox-image": passthroughProps.skyboxImage,
|
|
130
|
+
"environment-image": passthroughProps.environmentImage,
|
|
131
|
+
exposure: passthroughProps.exposure,
|
|
132
|
+
"shadow-intensity": (_j = passthroughProps.shadowIntensity) != null ? _j : 0,
|
|
133
|
+
"shadow-softness": (_k = passthroughProps.shadowSoftness) != null ? _k : 0,
|
|
134
|
+
"animation-name": passthroughProps.animationName,
|
|
135
|
+
"animation-crossfade-duration": passthroughProps.animationCrossfadeDuration,
|
|
136
|
+
"variant-name": passthroughProps.variantName,
|
|
137
|
+
orientation: passthroughProps.orientation,
|
|
138
|
+
scale: passthroughProps.scale,
|
|
139
|
+
children
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
export {
|
|
143
|
+
ModelViewer
|
|
144
|
+
};
|
|
145
|
+
//# sourceMappingURL=ModelViewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModelViewer.js","sources":["../../src/ModelViewer.tsx"],"sourcesContent":["import {useState, useEffect, useCallback} from 'react';\nimport {useLoadScript} from './load-script.js';\nimport type {Model3d} from './storefront-api-types.js';\nimport type {PartialDeep} from 'type-fest';\nimport type {ModelViewerElement} from '@google/model-viewer/lib/model-viewer.js';\n\ntype PropsWeControl = 'src';\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace JSX {\n interface IntrinsicElements {\n 'model-viewer': PartialDeep<\n ModelViewerElement,\n {recurseIntoArrays: true}\n >;\n }\n }\n}\n\ntype ModelViewerProps = Omit<\n PartialDeep<JSX.IntrinsicElements['model-viewer'], {recurseIntoArrays: true}>,\n PropsWeControl\n> & {\n /** An object with fields that correspond to the Storefront API's [Model3D object](https://shopify.dev/api/storefront/latest/objects/model3d). */\n data: PartialDeep<Model3d, {recurseIntoArrays: true}>;\n /** The callback to invoke when the 'error' event is triggered. Refer to [error in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-loading-events-error). */\n onError?: (event: Event) => void;\n /** The callback to invoke when the `load` event is triggered. Refer to [load in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-loading-events-load). */\n onLoad?: (event: Event) => void;\n /** The callback to invoke when the 'preload' event is triggered. Refer to [preload in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-loading-events-preload). */\n onPreload?: (event: Event) => void;\n /** The callback to invoke when the 'model-visibility' event is triggered. Refer to [model-visibility in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-loading-events-modelVisibility). */\n onModelVisibility?: (event: Event) => void;\n /** The callback to invoke when the 'progress' event is triggered. Refer to [progress in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-loading-events-progress). */\n onProgress?: (event: Event) => void;\n /** The callback to invoke when the 'ar-status' event is triggered. Refer to [ar-status in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-augmentedreality-events-arStatus). */\n onArStatus?: (event: Event) => void;\n /** The callback to invoke when the 'ar-tracking' event is triggered. Refer to [ar-tracking in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-augmentedreality-events-arTracking). */\n onArTracking?: (event: Event) => void;\n /** The callback to invoke when the 'quick-look-button-tapped' event is triggered. Refer to [quick-look-button-tapped in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-augmentedreality-events-quickLookButtonTapped). */\n onQuickLookButtonTapped?: (event: Event) => void;\n /** The callback to invoke when the 'camera-change' event is triggered. Refer to [camera-change in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-stagingandcameras-events-cameraChange). */\n onCameraChange?: (event: Event) => void;\n /** The callback to invoke when the 'environment-change' event is triggered. Refer to [environment-change in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-lightingandenv-events-environmentChange). */\n onEnvironmentChange?: (event: Event) => void;\n /** The callback to invoke when the 'play' event is triggered. Refer to [play in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-animation-events-play). */\n onPlay?: (event: Event) => void;\n /** The callback to invoke when the 'pause' event is triggered. Refer to [pause in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-animation-events-pause). */\n onPause?: (event: Event) => void;\n /** The callback to invoke when the 'scene-graph-ready' event is triggered. Refer to [scene-graph-ready in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-scenegraph-events-sceneGraphReady). */\n onSceneGraphReady?: (event: Event) => void;\n};\n\n/**\n * The `ModelViewer` component renders a 3D model (with the `model-viewer` custom element) for\n * the Storefront API's [Model3d object](https://shopify.dev/api/storefront/reference/products/model3d).\n *\n * The `model-viewer` custom element is lazily downloaded through a dynamically-injected `<script type=\"module\">` tag when the `<ModelViewer />` component is rendered\n *\n * ModelViewer is using version `1.21.1` of the `@google/model-viewer` library.\n */\nexport function ModelViewer(props: ModelViewerProps) {\n const [modelViewer, setModelViewer] = useState<undefined | HTMLElement>(\n undefined\n );\n const callbackRef = useCallback((node: HTMLElement) => {\n setModelViewer(node);\n }, []);\n const {data, children, className, ...passthroughProps} = props;\n\n const modelViewerLoadedStatus = useLoadScript(\n 'https://unpkg.com/@google/model-viewer@v1.12.1/dist/model-viewer.min.js',\n {\n module: true,\n }\n );\n\n useEffect(() => {\n if (!modelViewer) {\n return;\n }\n if (passthroughProps.onError)\n modelViewer.addEventListener('error', passthroughProps.onError);\n if (passthroughProps.onLoad)\n modelViewer.addEventListener('load', passthroughProps.onLoad);\n if (passthroughProps.onPreload)\n modelViewer.addEventListener('preload', passthroughProps.onPreload);\n if (passthroughProps.onModelVisibility)\n modelViewer.addEventListener(\n 'model-visibility',\n passthroughProps.onModelVisibility\n );\n if (passthroughProps.onProgress)\n modelViewer.addEventListener('progress', passthroughProps.onProgress);\n if (passthroughProps.onArStatus)\n modelViewer.addEventListener('ar-status', passthroughProps.onArStatus);\n if (passthroughProps.onArTracking)\n modelViewer.addEventListener(\n 'ar-tracking',\n passthroughProps.onArTracking\n );\n if (passthroughProps.onQuickLookButtonTapped)\n modelViewer.addEventListener(\n 'quick-look-button-tapped',\n passthroughProps.onQuickLookButtonTapped\n );\n if (passthroughProps.onCameraChange)\n modelViewer.addEventListener(\n 'camera-change',\n passthroughProps.onCameraChange\n );\n if (passthroughProps.onEnvironmentChange)\n modelViewer.addEventListener(\n 'environment-change',\n passthroughProps.onEnvironmentChange\n );\n if (passthroughProps.onPlay)\n modelViewer.addEventListener('play', passthroughProps.onPlay);\n if (passthroughProps.onPause)\n modelViewer.addEventListener('ar-status', passthroughProps.onPause);\n if (passthroughProps.onSceneGraphReady)\n modelViewer.addEventListener(\n 'scene-graph-ready',\n passthroughProps.onSceneGraphReady\n );\n\n return () => {\n if (modelViewer == null) {\n return;\n }\n if (passthroughProps.onError)\n modelViewer.removeEventListener('error', passthroughProps.onError);\n if (passthroughProps.onLoad)\n modelViewer.removeEventListener('load', passthroughProps.onLoad);\n if (passthroughProps.onPreload)\n modelViewer.removeEventListener('preload', passthroughProps.onPreload);\n if (passthroughProps.onModelVisibility)\n modelViewer.removeEventListener(\n 'model-visibility',\n passthroughProps.onModelVisibility\n );\n if (passthroughProps.onProgress)\n modelViewer.removeEventListener(\n 'progress',\n passthroughProps.onProgress\n );\n if (passthroughProps.onArStatus)\n modelViewer.removeEventListener(\n 'ar-status',\n passthroughProps.onArStatus\n );\n if (passthroughProps.onArTracking)\n modelViewer.removeEventListener(\n 'ar-tracking',\n passthroughProps.onArTracking\n );\n if (passthroughProps.onQuickLookButtonTapped)\n modelViewer.removeEventListener(\n 'quick-look-button-tapped',\n passthroughProps.onQuickLookButtonTapped\n );\n if (passthroughProps.onCameraChange)\n modelViewer.removeEventListener(\n 'camera-change',\n passthroughProps.onCameraChange\n );\n if (passthroughProps.onEnvironmentChange)\n modelViewer.removeEventListener(\n 'environment-change',\n passthroughProps.onEnvironmentChange\n );\n if (passthroughProps.onPlay)\n modelViewer.removeEventListener('play', passthroughProps.onPlay);\n if (passthroughProps.onPause)\n modelViewer.removeEventListener('ar-status', passthroughProps.onPause);\n if (passthroughProps.onSceneGraphReady)\n modelViewer.removeEventListener(\n 'scene-graph-ready',\n passthroughProps.onSceneGraphReady\n );\n };\n }, [\n modelViewer,\n passthroughProps.onArStatus,\n passthroughProps.onArTracking,\n passthroughProps.onCameraChange,\n passthroughProps.onEnvironmentChange,\n passthroughProps.onError,\n passthroughProps.onLoad,\n passthroughProps.onModelVisibility,\n passthroughProps.onPause,\n passthroughProps.onPlay,\n passthroughProps.onPreload,\n passthroughProps.onProgress,\n passthroughProps.onQuickLookButtonTapped,\n passthroughProps.onSceneGraphReady,\n ]);\n\n if (modelViewerLoadedStatus !== 'done') {\n // TODO: What do we want to display while the model-viewer library loads?\n return null;\n }\n\n if (!data.sources?.[0]?.url) {\n const sourcesUrlError = `<ModelViewer/> requires 'data.sources' prop to be an array, with an object that has a property 'url' on it. Rendering 'null'`;\n if (__HYDROGEN_DEV__) {\n throw new Error(sourcesUrlError);\n } else {\n console.error(sourcesUrlError);\n return null;\n }\n }\n\n if (__HYDROGEN_DEV__ && !data.alt) {\n console.warn(\n `<ModelViewer/> requires the 'data.alt' prop for accessibility`\n );\n }\n\n return (\n <model-viewer\n // @ts-expect-error ref should exist\n ref={callbackRef}\n {...passthroughProps}\n className={className}\n id={passthroughProps.id ?? data.id}\n src={data.sources[0].url}\n alt={data.alt ?? null}\n camera-controls={passthroughProps.cameraControls ?? true}\n poster={(passthroughProps.poster || data.previewImage?.url) ?? null}\n autoplay={passthroughProps.autoplay ?? true}\n loading={passthroughProps.loading}\n reveal={passthroughProps.reveal}\n ar={passthroughProps.ar}\n ar-modes={passthroughProps.arModes}\n ar-scale={passthroughProps.arScale}\n // @ts-expect-error arPlacement should exist as a type, not sure why it doesn't. https://modelviewer.dev/docs/index.html#entrydocs-augmentedreality-attributes-arPlacement\n ar-placement={passthroughProps.arPlacement}\n ios-src={passthroughProps.iosSrc}\n touch-action={passthroughProps.touchAction}\n disable-zoom={passthroughProps.disableZoom}\n orbit-sensitivity={passthroughProps.orbitSensitivity}\n auto-rotate={passthroughProps.autoRotate}\n auto-rotate-delay={passthroughProps.autoRotateDelay}\n // @ts-expect-error rotationPerSecond should exist as a type, not sure why it doesn't. https://modelviewer.dev/docs/index.html#entrydocs-stagingandcameras-attributes-rotationPerSecond\n rotation-per-second={passthroughProps.rotationPerSecond}\n interaction-policy={passthroughProps.interactionPolicy}\n interaction-prompt={passthroughProps.interactionPrompt}\n interaction-prompt-style={passthroughProps.interactionPromptStyle}\n interaction-prompt-threshold={passthroughProps.interactionPromptThreshold}\n camera-orbit={passthroughProps.cameraOrbit}\n camera-target={passthroughProps.cameraTarget}\n field-of-view={passthroughProps.fieldOfView}\n max-camera-orbit={passthroughProps.maxCameraOrbit}\n min-camera-orbit={passthroughProps.minCameraOrbit}\n max-field-of-view={passthroughProps.maxFieldOfView}\n min-field-of-view={passthroughProps.minFieldOfView}\n bounds={passthroughProps.bounds}\n interpolation-decay={passthroughProps.interpolationDecay ?? 100}\n skybox-image={passthroughProps.skyboxImage}\n environment-image={passthroughProps.environmentImage}\n exposure={passthroughProps.exposure}\n shadow-intensity={passthroughProps.shadowIntensity ?? 0}\n shadow-softness={passthroughProps.shadowSoftness ?? 0}\n animation-name={passthroughProps.animationName}\n animation-crossfade-duration={passthroughProps.animationCrossfadeDuration}\n variant-name={passthroughProps.variantName}\n orientation={passthroughProps.orientation}\n scale={passthroughProps.scale}\n >\n {children}\n </model-viewer>\n );\n}\n"],"names":["ModelViewer","props","modelViewer","setModelViewer","useState","undefined","callbackRef","useCallback","node","data","children","className","passthroughProps","modelViewerLoadedStatus","useLoadScript","module","useEffect","onError","addEventListener","onLoad","onPreload","onModelVisibility","onProgress","onArStatus","onArTracking","onQuickLookButtonTapped","onCameraChange","onEnvironmentChange","onPlay","onPause","onSceneGraphReady","removeEventListener","sources","url","sourcesUrlError","Error","__HYDROGEN_DEV__","alt","console","warn","id","cameraControls","poster","previewImage","autoplay","loading","reveal","ar","arModes","arScale","arPlacement","iosSrc","touchAction","disableZoom","orbitSensitivity","autoRotate","autoRotateDelay","rotationPerSecond","interactionPolicy","interactionPrompt","interactionPromptStyle","interactionPromptThreshold","cameraOrbit","cameraTarget","fieldOfView","maxCameraOrbit","minCameraOrbit","maxFieldOfView","minFieldOfView","bounds","interpolationDecay","skyboxImage","environmentImage","exposure","shadowIntensity","shadowSoftness","animationName","animationCrossfadeDuration","variantName","orientation","scale"],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
+
const useMoney = require("./useMoney.cjs");
|
|
4
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
5
|
+
function Money({
|
|
6
|
+
data,
|
|
7
|
+
as,
|
|
8
|
+
withoutCurrency,
|
|
9
|
+
withoutTrailingZeros,
|
|
10
|
+
measurement,
|
|
11
|
+
measurementSeparator = "/",
|
|
12
|
+
...passthroughProps
|
|
13
|
+
}) {
|
|
14
|
+
if (!isMoney(data)) {
|
|
15
|
+
throw new Error(`<Money/> needs a valid 'data' prop that has 'amount' and 'currencyCode'`);
|
|
16
|
+
}
|
|
17
|
+
const moneyObject = useMoney.useMoney(data);
|
|
18
|
+
const Wrapper = as != null ? as : "div";
|
|
19
|
+
let output = moneyObject.localizedString;
|
|
20
|
+
if (withoutCurrency || withoutTrailingZeros) {
|
|
21
|
+
if (withoutCurrency && !withoutTrailingZeros) {
|
|
22
|
+
output = moneyObject.amount;
|
|
23
|
+
} else if (!withoutCurrency && withoutTrailingZeros) {
|
|
24
|
+
output = moneyObject.withoutTrailingZeros;
|
|
25
|
+
} else {
|
|
26
|
+
output = moneyObject.withoutTrailingZerosAndCurrency;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Wrapper, {
|
|
30
|
+
...passthroughProps,
|
|
31
|
+
children: [output, measurement && measurement.referenceUnit && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
32
|
+
children: [measurementSeparator, measurement.referenceUnit]
|
|
33
|
+
})]
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
function isMoney(maybeMoney) {
|
|
37
|
+
return typeof maybeMoney.amount === "string" && !!maybeMoney.amount && typeof maybeMoney.currencyCode === "string" && !!maybeMoney.currencyCode;
|
|
38
|
+
}
|
|
39
|
+
exports.Money = Money;
|
|
40
|
+
//# sourceMappingURL=Money.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Money.cjs","sources":["../../src/Money.tsx"],"sourcesContent":["import React, {type ReactNode} from 'react';\nimport {useMoney} from './useMoney.js';\nimport type {MoneyV2, UnitPriceMeasurement} from './storefront-api-types.js';\nimport type {PartialDeep} from 'type-fest';\n\ninterface CustomProps<ComponentGeneric extends React.ElementType> {\n /** An HTML tag or React Component to be rendered as the base element wrapper. The default is `div`. */\n as?: ComponentGeneric;\n /** An object with fields that correspond to the Storefront API's [MoneyV2 object](https://shopify.dev/api/storefront/reference/common-objects/moneyv2). */\n data: PartialDeep<MoneyV2, {recurseIntoArrays: true}>;\n /** Whether to remove the currency symbol from the output. */\n withoutCurrency?: boolean;\n /** Whether to remove trailing zeros (fractional money) from the output. */\n withoutTrailingZeros?: boolean;\n /** A [UnitPriceMeasurement object](https://shopify.dev/api/storefront/latest/objects/unitpricemeasurement). */\n measurement?: PartialDeep<UnitPriceMeasurement, {recurseIntoArrays: true}>;\n /** Customizes the separator between the money output and the measurement output. Used with the `measurement` prop. Defaults to `'/'`. */\n measurementSeparator?: ReactNode;\n}\n\n// This article helps understand the typing here https://www.benmvp.com/blog/polymorphic-react-components-typescript/ Ben is the best :)\nexport type MoneyProps<ComponentGeneric extends React.ElementType> =\n CustomProps<ComponentGeneric> &\n Omit<\n React.ComponentPropsWithoutRef<ComponentGeneric>,\n keyof CustomProps<ComponentGeneric>\n >;\n\n/**\n * The `Money` component renders a string of the Storefront API's\n * [MoneyV2 object](https://shopify.dev/api/storefront/reference/common-objects/moneyv2) according to the\n * `locale` in the `ShopifyProvider` component.\n */\nexport function Money<ComponentGeneric extends React.ElementType>({\n data,\n as,\n withoutCurrency,\n withoutTrailingZeros,\n measurement,\n measurementSeparator = '/',\n ...passthroughProps\n}: MoneyProps<ComponentGeneric>) {\n if (!isMoney(data)) {\n throw new Error(\n `<Money/> needs a valid 'data' prop that has 'amount' and 'currencyCode'`\n );\n }\n const moneyObject = useMoney(data);\n const Wrapper = as ?? 'div';\n\n let output = moneyObject.localizedString;\n\n if (withoutCurrency || withoutTrailingZeros) {\n if (withoutCurrency && !withoutTrailingZeros) {\n output = moneyObject.amount;\n } else if (!withoutCurrency && withoutTrailingZeros) {\n output = moneyObject.withoutTrailingZeros;\n } else {\n // both\n output = moneyObject.withoutTrailingZerosAndCurrency;\n }\n }\n\n return (\n <Wrapper {...passthroughProps}>\n {output}\n {measurement && measurement.referenceUnit && (\n <>\n {measurementSeparator}\n {measurement.referenceUnit}\n </>\n )}\n </Wrapper>\n );\n}\n\n// required in order to narrow the money object down and make TS happy\nfunction isMoney(\n maybeMoney: PartialDeep<MoneyV2, {recurseIntoArrays: true}>\n): maybeMoney is MoneyV2 {\n return (\n typeof maybeMoney.amount === 'string' &&\n !!maybeMoney.amount &&\n typeof maybeMoney.currencyCode === 'string' &&\n !!maybeMoney.currencyCode\n );\n}\n"],"names":["Money","data","as","withoutCurrency","withoutTrailingZeros","measurement","measurementSeparator","passthroughProps","isMoney","Error","moneyObject","useMoney","Wrapper","output","localizedString","amount","withoutTrailingZerosAndCurrency","referenceUnit","_Fragment","maybeMoney","currencyCode"],"mappings":";;;;AAiCO,SAASA,MAAkD;AAAA,EAChEC;AAAAA,EACAC;AAAAA,EACAC;AAAAA,EACAC;AAAAA,EACAC;AAAAA,EACAC,uBAAuB;AAAA,KACpBC;AAP6D,GAQjC;AAC3B,MAAA,CAACC,QAAQP,IAAD,GAAQ;AACZ,UAAA,IAAIQ,MACP,yEADG;AAAA,EAGP;AACKC,QAAAA,cAAcC,kBAASV,IAAD;AAC5B,QAAMW,UAAUV,kBAAM;AAEtB,MAAIW,SAASH,YAAYI;AAEzB,MAAIX,mBAAmBC,sBAAsB;AACvCD,QAAAA,mBAAmB,CAACC,sBAAsB;AAC5CS,eAASH,YAAYK;AAAAA,IAAAA,WACZ,CAACZ,mBAAmBC,sBAAsB;AACnDS,eAASH,YAAYN;AAAAA,IAAAA,OAChB;AAELS,eAASH,YAAYM;AAAAA,IACtB;AAAA,EACF;AAED,yCACG,SAAD;AAAA,IAAA,GAAaT;AAAAA,IAAb,UAAA,CACGM,QACAR,eAAeA,YAAYY,iDAC1BC,qBAAA;AAAA,MAAA,UAAA,CACGZ,sBACAD,YAAYY,aAFf;AAAA,IAAA,CAHJ,CAAA;AAAA,EAAA,CADF;AAWD;AAGD,SAAST,QACPW,YACuB;AACvB,SACE,OAAOA,WAAWJ,WAAW,YAC7B,CAAC,CAACI,WAAWJ,UACb,OAAOI,WAAWC,iBAAiB,YACnC,CAAC,CAACD,WAAWC;AAEhB;;"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useMoney } from "./useMoney.js";
|
|
2
|
+
import { jsxs, Fragment } from "react/jsx-runtime";
|
|
3
|
+
function Money({
|
|
4
|
+
data,
|
|
5
|
+
as,
|
|
6
|
+
withoutCurrency,
|
|
7
|
+
withoutTrailingZeros,
|
|
8
|
+
measurement,
|
|
9
|
+
measurementSeparator = "/",
|
|
10
|
+
...passthroughProps
|
|
11
|
+
}) {
|
|
12
|
+
if (!isMoney(data)) {
|
|
13
|
+
throw new Error(`<Money/> needs a valid 'data' prop that has 'amount' and 'currencyCode'`);
|
|
14
|
+
}
|
|
15
|
+
const moneyObject = useMoney(data);
|
|
16
|
+
const Wrapper = as != null ? as : "div";
|
|
17
|
+
let output = moneyObject.localizedString;
|
|
18
|
+
if (withoutCurrency || withoutTrailingZeros) {
|
|
19
|
+
if (withoutCurrency && !withoutTrailingZeros) {
|
|
20
|
+
output = moneyObject.amount;
|
|
21
|
+
} else if (!withoutCurrency && withoutTrailingZeros) {
|
|
22
|
+
output = moneyObject.withoutTrailingZeros;
|
|
23
|
+
} else {
|
|
24
|
+
output = moneyObject.withoutTrailingZerosAndCurrency;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return /* @__PURE__ */ jsxs(Wrapper, {
|
|
28
|
+
...passthroughProps,
|
|
29
|
+
children: [output, measurement && measurement.referenceUnit && /* @__PURE__ */ jsxs(Fragment, {
|
|
30
|
+
children: [measurementSeparator, measurement.referenceUnit]
|
|
31
|
+
})]
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function isMoney(maybeMoney) {
|
|
35
|
+
return typeof maybeMoney.amount === "string" && !!maybeMoney.amount && typeof maybeMoney.currencyCode === "string" && !!maybeMoney.currencyCode;
|
|
36
|
+
}
|
|
37
|
+
export {
|
|
38
|
+
Money
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=Money.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Money.js","sources":["../../src/Money.tsx"],"sourcesContent":["import React, {type ReactNode} from 'react';\nimport {useMoney} from './useMoney.js';\nimport type {MoneyV2, UnitPriceMeasurement} from './storefront-api-types.js';\nimport type {PartialDeep} from 'type-fest';\n\ninterface CustomProps<ComponentGeneric extends React.ElementType> {\n /** An HTML tag or React Component to be rendered as the base element wrapper. The default is `div`. */\n as?: ComponentGeneric;\n /** An object with fields that correspond to the Storefront API's [MoneyV2 object](https://shopify.dev/api/storefront/reference/common-objects/moneyv2). */\n data: PartialDeep<MoneyV2, {recurseIntoArrays: true}>;\n /** Whether to remove the currency symbol from the output. */\n withoutCurrency?: boolean;\n /** Whether to remove trailing zeros (fractional money) from the output. */\n withoutTrailingZeros?: boolean;\n /** A [UnitPriceMeasurement object](https://shopify.dev/api/storefront/latest/objects/unitpricemeasurement). */\n measurement?: PartialDeep<UnitPriceMeasurement, {recurseIntoArrays: true}>;\n /** Customizes the separator between the money output and the measurement output. Used with the `measurement` prop. Defaults to `'/'`. */\n measurementSeparator?: ReactNode;\n}\n\n// This article helps understand the typing here https://www.benmvp.com/blog/polymorphic-react-components-typescript/ Ben is the best :)\nexport type MoneyProps<ComponentGeneric extends React.ElementType> =\n CustomProps<ComponentGeneric> &\n Omit<\n React.ComponentPropsWithoutRef<ComponentGeneric>,\n keyof CustomProps<ComponentGeneric>\n >;\n\n/**\n * The `Money` component renders a string of the Storefront API's\n * [MoneyV2 object](https://shopify.dev/api/storefront/reference/common-objects/moneyv2) according to the\n * `locale` in the `ShopifyProvider` component.\n */\nexport function Money<ComponentGeneric extends React.ElementType>({\n data,\n as,\n withoutCurrency,\n withoutTrailingZeros,\n measurement,\n measurementSeparator = '/',\n ...passthroughProps\n}: MoneyProps<ComponentGeneric>) {\n if (!isMoney(data)) {\n throw new Error(\n `<Money/> needs a valid 'data' prop that has 'amount' and 'currencyCode'`\n );\n }\n const moneyObject = useMoney(data);\n const Wrapper = as ?? 'div';\n\n let output = moneyObject.localizedString;\n\n if (withoutCurrency || withoutTrailingZeros) {\n if (withoutCurrency && !withoutTrailingZeros) {\n output = moneyObject.amount;\n } else if (!withoutCurrency && withoutTrailingZeros) {\n output = moneyObject.withoutTrailingZeros;\n } else {\n // both\n output = moneyObject.withoutTrailingZerosAndCurrency;\n }\n }\n\n return (\n <Wrapper {...passthroughProps}>\n {output}\n {measurement && measurement.referenceUnit && (\n <>\n {measurementSeparator}\n {measurement.referenceUnit}\n </>\n )}\n </Wrapper>\n );\n}\n\n// required in order to narrow the money object down and make TS happy\nfunction isMoney(\n maybeMoney: PartialDeep<MoneyV2, {recurseIntoArrays: true}>\n): maybeMoney is MoneyV2 {\n return (\n typeof maybeMoney.amount === 'string' &&\n !!maybeMoney.amount &&\n typeof maybeMoney.currencyCode === 'string' &&\n !!maybeMoney.currencyCode\n );\n}\n"],"names":["Money","data","as","withoutCurrency","withoutTrailingZeros","measurement","measurementSeparator","passthroughProps","isMoney","Error","moneyObject","useMoney","Wrapper","output","localizedString","amount","withoutTrailingZerosAndCurrency","referenceUnit","_Fragment","maybeMoney","currencyCode"],"mappings":";;AAiCO,SAASA,MAAkD;AAAA,EAChEC;AAAAA,EACAC;AAAAA,EACAC;AAAAA,EACAC;AAAAA,EACAC;AAAAA,EACAC,uBAAuB;AAAA,KACpBC;AAP6D,GAQjC;AAC3B,MAAA,CAACC,QAAQP,IAAD,GAAQ;AACZ,UAAA,IAAIQ,MACP,yEADG;AAAA,EAGP;AACKC,QAAAA,cAAcC,SAASV,IAAD;AAC5B,QAAMW,UAAUV,kBAAM;AAEtB,MAAIW,SAASH,YAAYI;AAEzB,MAAIX,mBAAmBC,sBAAsB;AACvCD,QAAAA,mBAAmB,CAACC,sBAAsB;AAC5CS,eAASH,YAAYK;AAAAA,IAAAA,WACZ,CAACZ,mBAAmBC,sBAAsB;AACnDS,eAASH,YAAYN;AAAAA,IAAAA,OAChB;AAELS,eAASH,YAAYM;AAAAA,IACtB;AAAA,EACF;AAED,8BACG,SAAD;AAAA,IAAA,GAAaT;AAAAA,IAAb,UAAA,CACGM,QACAR,eAAeA,YAAYY,sCAC1BC,UAAA;AAAA,MAAA,UAAA,CACGZ,sBACAD,YAAYY,aAFf;AAAA,IAAA,CAHJ,CAAA;AAAA,EAAA,CADF;AAWD;AAGD,SAAST,QACPW,YACuB;AACvB,SACE,OAAOA,WAAWJ,WAAW,YAC7B,CAAC,CAACI,WAAWJ,UACb,OAAOI,WAAWC,iBAAiB,YACnC,CAAC,CAACD,WAAWC;AAEhB;"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
+
const Money = require("./Money.cjs");
|
|
4
|
+
const flattenConnection = require("./flatten-connection.cjs");
|
|
5
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
6
|
+
function ProductPrice(props) {
|
|
7
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
8
|
+
const {
|
|
9
|
+
priceType = "regular",
|
|
10
|
+
variantId,
|
|
11
|
+
valueType = "min",
|
|
12
|
+
data: product,
|
|
13
|
+
...passthroughProps
|
|
14
|
+
} = props;
|
|
15
|
+
if (product == null) {
|
|
16
|
+
throw new Error(`<ProductPrice/> requires a product as the 'data' prop`);
|
|
17
|
+
}
|
|
18
|
+
let price;
|
|
19
|
+
let measurement;
|
|
20
|
+
const variant = variantId ? (_b = flattenConnection.flattenConnection((_a = product == null ? void 0 : product.variants) != null ? _a : {}).find((variant2) => (variant2 == null ? void 0 : variant2.id) === variantId)) != null ? _b : null : null;
|
|
21
|
+
if (priceType === "compareAt") {
|
|
22
|
+
if (variantId && variant) {
|
|
23
|
+
if (((_c = variant.compareAtPriceV2) == null ? void 0 : _c.amount) === ((_d = variant.priceV2) == null ? void 0 : _d.amount)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
price = variant.compareAtPriceV2;
|
|
27
|
+
} else if (valueType === "max") {
|
|
28
|
+
price = (_e = product == null ? void 0 : product.compareAtPriceRange) == null ? void 0 : _e.maxVariantPrice;
|
|
29
|
+
} else {
|
|
30
|
+
price = (_f = product == null ? void 0 : product.compareAtPriceRange) == null ? void 0 : _f.minVariantPrice;
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
if (variantId && variant) {
|
|
34
|
+
price = variant.priceV2;
|
|
35
|
+
if (valueType === "unit") {
|
|
36
|
+
price = variant.unitPrice;
|
|
37
|
+
measurement = variant.unitPriceMeasurement;
|
|
38
|
+
}
|
|
39
|
+
} else if (valueType === "max") {
|
|
40
|
+
price = (_g = product.priceRange) == null ? void 0 : _g.maxVariantPrice;
|
|
41
|
+
} else {
|
|
42
|
+
price = (_h = product.priceRange) == null ? void 0 : _h.minVariantPrice;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (!price) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
if (measurement) {
|
|
49
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Money.Money, {
|
|
50
|
+
...passthroughProps,
|
|
51
|
+
data: price,
|
|
52
|
+
measurement
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Money.Money, {
|
|
56
|
+
...passthroughProps,
|
|
57
|
+
data: price
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
exports.ProductPrice = ProductPrice;
|
|
61
|
+
//# sourceMappingURL=ProductPrice.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProductPrice.cjs","sources":["../../src/ProductPrice.tsx"],"sourcesContent":["import React from 'react';\nimport type {\n MoneyV2,\n UnitPriceMeasurement,\n Product,\n} from './storefront-api-types.js';\nimport {Money, type MoneyProps} from './Money.js';\nimport type {PartialDeep} from 'type-fest';\nimport {flattenConnection} from './flatten-connection.js';\n\ninterface ProductPriceProps {\n /** A [Product object](https://shopify.dev/api/storefront/reference/products/product). */\n data: PartialDeep<Product, {recurseIntoArrays: true}>;\n /** The type of price. Valid values: `regular` (default) or `compareAt`. */\n priceType?: 'regular' | 'compareAt';\n /** The type of value. Valid values: `min` (default), `max` or `unit`. */\n valueType?: 'max' | 'min' | 'unit';\n /** The ID of the variant. */\n variantId?: string;\n}\n\n/**\n * The `ProductPrice` component renders a `Money` component with the product\n * [`priceRange`](https://shopify.dev/api/storefront/reference/products/productpricerange)'s `maxVariantPrice` or `minVariantPrice`, for either the regular price or compare at price range.\n */\nexport function ProductPrice<ComponentGeneric extends React.ElementType>(\n props: ProductPriceProps &\n Omit<MoneyProps<ComponentGeneric>, 'data' | 'measurement'>\n) {\n const {\n priceType = 'regular',\n variantId,\n valueType = 'min',\n data: product,\n ...passthroughProps\n } = props;\n\n if (product == null) {\n throw new Error(`<ProductPrice/> requires a product as the 'data' prop`);\n }\n\n let price: Partial<MoneyV2> | undefined | null;\n let measurement: Partial<UnitPriceMeasurement> | undefined | null;\n\n const variant = variantId\n ? flattenConnection(product?.variants ?? {}).find(\n (variant) => variant?.id === variantId\n ) ?? null\n : null;\n\n if (priceType === 'compareAt') {\n if (variantId && variant) {\n if (variant.compareAtPriceV2?.amount === variant.priceV2?.amount) {\n return null;\n }\n price = variant.compareAtPriceV2;\n } else if (valueType === 'max') {\n price = product?.compareAtPriceRange?.maxVariantPrice;\n } else {\n price = product?.compareAtPriceRange?.minVariantPrice;\n }\n } else {\n if (variantId && variant) {\n price = variant.priceV2;\n if (valueType === 'unit') {\n price = variant.unitPrice;\n measurement = variant.unitPriceMeasurement;\n }\n } else if (valueType === 'max') {\n price = product.priceRange?.maxVariantPrice;\n } else {\n price = product.priceRange?.minVariantPrice;\n }\n }\n\n if (!price) {\n return null;\n }\n\n if (measurement) {\n return (\n <Money {...passthroughProps} data={price} measurement={measurement} />\n );\n }\n\n return <Money {...passthroughProps} data={price} />;\n}\n"],"names":["ProductPrice","props","priceType","variantId","valueType","data","product","passthroughProps","Error","price","measurement","variant","flattenConnection","variants","find","id","compareAtPriceV2","amount","priceV2","compareAtPriceRange","maxVariantPrice","minVariantPrice","unitPrice","unitPriceMeasurement","priceRange","Money"],"mappings":";;;;;AAyBO,SAASA,aACdC,OAEA;;AACM,QAAA;AAAA,IACJC,YAAY;AAAA,IACZC;AAAAA,IACAC,YAAY;AAAA,IACZC,MAAMC;AAAAA,OACHC;AAAAA,EACDN,IAAAA;AAEJ,MAAIK,WAAW,MAAM;AACb,UAAA,IAAIE,MAAO,uDAAX;AAAA,EACP;AAEGC,MAAAA;AACAC,MAAAA;AAEJ,QAAMC,UAAUR,aACZS,uBAAAA,mBAAkBN,wCAASO,aAATP,YAAqB,CAAA,CAAtB,EAA0BQ,KACxCH,CAAAA,cAAYA,qCAASI,QAAOZ,SAD/B,MAAAS,YAEK,OACL;AAEJ,MAAIV,cAAc,aAAa;AAC7B,QAAIC,aAAaQ,SAAS;AACxB,YAAIA,aAAQK,qBAARL,mBAA0BM,cAAWN,aAAQO,YAARP,mBAAiBM,SAAQ;AACzD,eAAA;AAAA,MACR;AACDR,cAAQE,QAAQK;AAAAA,IAAAA,WACPZ,cAAc,OAAO;AAC9BK,eAAQH,wCAASa,wBAATb,mBAA8Bc;AAAAA,IAAAA,OACjC;AACLX,eAAQH,wCAASa,wBAATb,mBAA8Be;AAAAA,IACvC;AAAA,EAAA,OACI;AACL,QAAIlB,aAAaQ,SAAS;AACxBF,cAAQE,QAAQO;AAChB,UAAId,cAAc,QAAQ;AACxBK,gBAAQE,QAAQW;AAChBZ,sBAAcC,QAAQY;AAAAA,MACvB;AAAA,IAAA,WACQnB,cAAc,OAAO;AAC9BK,eAAQH,aAAQkB,eAARlB,mBAAoBc;AAAAA,IAAAA,OACvB;AACLX,eAAQH,aAAQkB,eAARlB,mBAAoBe;AAAAA,IAC7B;AAAA,EACF;AAED,MAAI,CAACZ,OAAO;AACH,WAAA;AAAA,EACR;AAED,MAAIC,aAAa;AACf,0CACGe,MAAAA,OAAD;AAAA,MAAA,GAAWlB;AAAAA,MAAkB,MAAME;AAAAA,MAAO;AAAA,IAAA,CAD5C;AAAA,EAGD;AAED,wCAAQgB,MAAAA,OAAD;AAAA,IAAA,GAAWlB;AAAAA,IAAkB,MAAME;AAAAA,EAAAA,CAA1C;AACD;;"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Money } from "./Money.js";
|
|
2
|
+
import { flattenConnection } from "./flatten-connection.js";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
function ProductPrice(props) {
|
|
5
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
6
|
+
const {
|
|
7
|
+
priceType = "regular",
|
|
8
|
+
variantId,
|
|
9
|
+
valueType = "min",
|
|
10
|
+
data: product,
|
|
11
|
+
...passthroughProps
|
|
12
|
+
} = props;
|
|
13
|
+
if (product == null) {
|
|
14
|
+
throw new Error(`<ProductPrice/> requires a product as the 'data' prop`);
|
|
15
|
+
}
|
|
16
|
+
let price;
|
|
17
|
+
let measurement;
|
|
18
|
+
const variant = variantId ? (_b = flattenConnection((_a = product == null ? void 0 : product.variants) != null ? _a : {}).find((variant2) => (variant2 == null ? void 0 : variant2.id) === variantId)) != null ? _b : null : null;
|
|
19
|
+
if (priceType === "compareAt") {
|
|
20
|
+
if (variantId && variant) {
|
|
21
|
+
if (((_c = variant.compareAtPriceV2) == null ? void 0 : _c.amount) === ((_d = variant.priceV2) == null ? void 0 : _d.amount)) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
price = variant.compareAtPriceV2;
|
|
25
|
+
} else if (valueType === "max") {
|
|
26
|
+
price = (_e = product == null ? void 0 : product.compareAtPriceRange) == null ? void 0 : _e.maxVariantPrice;
|
|
27
|
+
} else {
|
|
28
|
+
price = (_f = product == null ? void 0 : product.compareAtPriceRange) == null ? void 0 : _f.minVariantPrice;
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
if (variantId && variant) {
|
|
32
|
+
price = variant.priceV2;
|
|
33
|
+
if (valueType === "unit") {
|
|
34
|
+
price = variant.unitPrice;
|
|
35
|
+
measurement = variant.unitPriceMeasurement;
|
|
36
|
+
}
|
|
37
|
+
} else if (valueType === "max") {
|
|
38
|
+
price = (_g = product.priceRange) == null ? void 0 : _g.maxVariantPrice;
|
|
39
|
+
} else {
|
|
40
|
+
price = (_h = product.priceRange) == null ? void 0 : _h.minVariantPrice;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (!price) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
if (measurement) {
|
|
47
|
+
return /* @__PURE__ */ jsx(Money, {
|
|
48
|
+
...passthroughProps,
|
|
49
|
+
data: price,
|
|
50
|
+
measurement
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return /* @__PURE__ */ jsx(Money, {
|
|
54
|
+
...passthroughProps,
|
|
55
|
+
data: price
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
export {
|
|
59
|
+
ProductPrice
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=ProductPrice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProductPrice.js","sources":["../../src/ProductPrice.tsx"],"sourcesContent":["import React from 'react';\nimport type {\n MoneyV2,\n UnitPriceMeasurement,\n Product,\n} from './storefront-api-types.js';\nimport {Money, type MoneyProps} from './Money.js';\nimport type {PartialDeep} from 'type-fest';\nimport {flattenConnection} from './flatten-connection.js';\n\ninterface ProductPriceProps {\n /** A [Product object](https://shopify.dev/api/storefront/reference/products/product). */\n data: PartialDeep<Product, {recurseIntoArrays: true}>;\n /** The type of price. Valid values: `regular` (default) or `compareAt`. */\n priceType?: 'regular' | 'compareAt';\n /** The type of value. Valid values: `min` (default), `max` or `unit`. */\n valueType?: 'max' | 'min' | 'unit';\n /** The ID of the variant. */\n variantId?: string;\n}\n\n/**\n * The `ProductPrice` component renders a `Money` component with the product\n * [`priceRange`](https://shopify.dev/api/storefront/reference/products/productpricerange)'s `maxVariantPrice` or `minVariantPrice`, for either the regular price or compare at price range.\n */\nexport function ProductPrice<ComponentGeneric extends React.ElementType>(\n props: ProductPriceProps &\n Omit<MoneyProps<ComponentGeneric>, 'data' | 'measurement'>\n) {\n const {\n priceType = 'regular',\n variantId,\n valueType = 'min',\n data: product,\n ...passthroughProps\n } = props;\n\n if (product == null) {\n throw new Error(`<ProductPrice/> requires a product as the 'data' prop`);\n }\n\n let price: Partial<MoneyV2> | undefined | null;\n let measurement: Partial<UnitPriceMeasurement> | undefined | null;\n\n const variant = variantId\n ? flattenConnection(product?.variants ?? {}).find(\n (variant) => variant?.id === variantId\n ) ?? null\n : null;\n\n if (priceType === 'compareAt') {\n if (variantId && variant) {\n if (variant.compareAtPriceV2?.amount === variant.priceV2?.amount) {\n return null;\n }\n price = variant.compareAtPriceV2;\n } else if (valueType === 'max') {\n price = product?.compareAtPriceRange?.maxVariantPrice;\n } else {\n price = product?.compareAtPriceRange?.minVariantPrice;\n }\n } else {\n if (variantId && variant) {\n price = variant.priceV2;\n if (valueType === 'unit') {\n price = variant.unitPrice;\n measurement = variant.unitPriceMeasurement;\n }\n } else if (valueType === 'max') {\n price = product.priceRange?.maxVariantPrice;\n } else {\n price = product.priceRange?.minVariantPrice;\n }\n }\n\n if (!price) {\n return null;\n }\n\n if (measurement) {\n return (\n <Money {...passthroughProps} data={price} measurement={measurement} />\n );\n }\n\n return <Money {...passthroughProps} data={price} />;\n}\n"],"names":["ProductPrice","props","priceType","variantId","valueType","data","product","passthroughProps","Error","price","measurement","variant","flattenConnection","variants","find","id","compareAtPriceV2","amount","priceV2","compareAtPriceRange","maxVariantPrice","minVariantPrice","unitPrice","unitPriceMeasurement","priceRange"],"mappings":";;;AAyBO,SAASA,aACdC,OAEA;;AACM,QAAA;AAAA,IACJC,YAAY;AAAA,IACZC;AAAAA,IACAC,YAAY;AAAA,IACZC,MAAMC;AAAAA,OACHC;AAAAA,EACDN,IAAAA;AAEJ,MAAIK,WAAW,MAAM;AACb,UAAA,IAAIE,MAAO,uDAAX;AAAA,EACP;AAEGC,MAAAA;AACAC,MAAAA;AAEJ,QAAMC,UAAUR,aACZS,wBAAkBN,wCAASO,aAATP,YAAqB,CAAA,CAAtB,EAA0BQ,KACxCH,CAAAA,cAAYA,qCAASI,QAAOZ,SAD/B,MAAAS,YAEK,OACL;AAEJ,MAAIV,cAAc,aAAa;AAC7B,QAAIC,aAAaQ,SAAS;AACxB,YAAIA,aAAQK,qBAARL,mBAA0BM,cAAWN,aAAQO,YAARP,mBAAiBM,SAAQ;AACzD,eAAA;AAAA,MACR;AACDR,cAAQE,QAAQK;AAAAA,IAAAA,WACPZ,cAAc,OAAO;AAC9BK,eAAQH,wCAASa,wBAATb,mBAA8Bc;AAAAA,IAAAA,OACjC;AACLX,eAAQH,wCAASa,wBAATb,mBAA8Be;AAAAA,IACvC;AAAA,EAAA,OACI;AACL,QAAIlB,aAAaQ,SAAS;AACxBF,cAAQE,QAAQO;AAChB,UAAId,cAAc,QAAQ;AACxBK,gBAAQE,QAAQW;AAChBZ,sBAAcC,QAAQY;AAAAA,MACvB;AAAA,IAAA,WACQnB,cAAc,OAAO;AAC9BK,eAAQH,aAAQkB,eAARlB,mBAAoBc;AAAAA,IAAAA,OACvB;AACLX,eAAQH,aAAQkB,eAARlB,mBAAoBe;AAAAA,IAC7B;AAAA,EACF;AAED,MAAI,CAACZ,OAAO;AACH,WAAA;AAAA,EACR;AAED,MAAIC,aAAa;AACf,+BACG,OAAD;AAAA,MAAA,GAAWH;AAAAA,MAAkB,MAAME;AAAAA,MAAO;AAAA,IAAA,CAD5C;AAAA,EAGD;AAED,6BAAQ,OAAD;AAAA,IAAA,GAAWF;AAAAA,IAAkB,MAAME;AAAAA,EAAAA,CAA1C;AACD;"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
+
const react = require("react");
|
|
4
|
+
const flattenConnection = require("./flatten-connection.cjs");
|
|
5
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
6
|
+
const ProductOptionsContext = react.createContext(null);
|
|
7
|
+
function ProductProvider({
|
|
8
|
+
children,
|
|
9
|
+
data: product,
|
|
10
|
+
initialVariantId: explicitVariantId
|
|
11
|
+
}) {
|
|
12
|
+
const variants = react.useMemo(() => {
|
|
13
|
+
var _a;
|
|
14
|
+
return flattenConnection.flattenConnection((_a = product.variants) != null ? _a : {});
|
|
15
|
+
}, [product.variants]);
|
|
16
|
+
if (!isProductVariantArray(variants)) {
|
|
17
|
+
throw new Error(`<ProductProvider/> requires 'product.variants.nodes' or 'product.variants.edges'`);
|
|
18
|
+
}
|
|
19
|
+
const options = react.useMemo(() => getOptions(variants), [variants]);
|
|
20
|
+
const [selectedVariant, setSelectedVariant] = react.useState(() => getVariantBasedOnIdProp(explicitVariantId, variants));
|
|
21
|
+
const [selectedOptions, setSelectedOptions] = react.useState(() => getSelectedOptions(selectedVariant));
|
|
22
|
+
react.useEffect(() => {
|
|
23
|
+
const newSelectedVariant = getVariantBasedOnIdProp(explicitVariantId, variants);
|
|
24
|
+
setSelectedVariant(newSelectedVariant);
|
|
25
|
+
setSelectedOptions(getSelectedOptions(newSelectedVariant));
|
|
26
|
+
}, [explicitVariantId, variants]);
|
|
27
|
+
const setSelectedOption = react.useCallback((name, value2) => {
|
|
28
|
+
setSelectedOptions((selectedOptions2) => {
|
|
29
|
+
const opts = {
|
|
30
|
+
...selectedOptions2,
|
|
31
|
+
[name]: value2
|
|
32
|
+
};
|
|
33
|
+
setSelectedVariant(getSelectedVariant(variants, opts));
|
|
34
|
+
return opts;
|
|
35
|
+
});
|
|
36
|
+
}, [setSelectedOptions, variants]);
|
|
37
|
+
const isOptionInStock = react.useCallback((option, value2) => {
|
|
38
|
+
var _a;
|
|
39
|
+
const proposedVariant = getSelectedVariant(variants, {
|
|
40
|
+
...selectedOptions,
|
|
41
|
+
...{
|
|
42
|
+
[option]: value2
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
return (_a = proposedVariant == null ? void 0 : proposedVariant.availableForSale) != null ? _a : true;
|
|
46
|
+
}, [selectedOptions, variants]);
|
|
47
|
+
const sellingPlanGroups = react.useMemo(() => {
|
|
48
|
+
var _a;
|
|
49
|
+
return flattenConnection.flattenConnection((_a = product.sellingPlanGroups) != null ? _a : {}).map((sellingPlanGroup) => {
|
|
50
|
+
var _a2;
|
|
51
|
+
return {
|
|
52
|
+
...sellingPlanGroup,
|
|
53
|
+
sellingPlans: flattenConnection.flattenConnection((_a2 = sellingPlanGroup == null ? void 0 : sellingPlanGroup.sellingPlans) != null ? _a2 : {})
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
}, [product.sellingPlanGroups]);
|
|
57
|
+
const [selectedSellingPlan, setSelectedSellingPlan] = react.useState(void 0);
|
|
58
|
+
const selectedSellingPlanAllocation = react.useMemo(() => {
|
|
59
|
+
var _a, _b;
|
|
60
|
+
if (!selectedVariant || !selectedSellingPlan) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (!((_a = selectedVariant.sellingPlanAllocations) == null ? void 0 : _a.nodes) && !((_b = selectedVariant.sellingPlanAllocations) == null ? void 0 : _b.edges)) {
|
|
64
|
+
throw new Error(`<ProductProvider/>: You must include 'sellingPlanAllocations.nodes' or 'sellingPlanAllocations.edges' in your variants in order to calculate selectedSellingPlanAllocation`);
|
|
65
|
+
}
|
|
66
|
+
return flattenConnection.flattenConnection(selectedVariant.sellingPlanAllocations).find((allocation) => {
|
|
67
|
+
var _a2;
|
|
68
|
+
return ((_a2 = allocation == null ? void 0 : allocation.sellingPlan) == null ? void 0 : _a2.id) === selectedSellingPlan.id;
|
|
69
|
+
});
|
|
70
|
+
}, [selectedVariant, selectedSellingPlan]);
|
|
71
|
+
const value = react.useMemo(() => ({
|
|
72
|
+
variants,
|
|
73
|
+
variantsConnection: product.variants,
|
|
74
|
+
options,
|
|
75
|
+
selectedVariant,
|
|
76
|
+
setSelectedVariant,
|
|
77
|
+
selectedOptions,
|
|
78
|
+
setSelectedOption,
|
|
79
|
+
setSelectedOptions,
|
|
80
|
+
isOptionInStock,
|
|
81
|
+
selectedSellingPlan,
|
|
82
|
+
setSelectedSellingPlan,
|
|
83
|
+
selectedSellingPlanAllocation,
|
|
84
|
+
sellingPlanGroups,
|
|
85
|
+
sellingPlanGroupsConnection: product.sellingPlanGroups
|
|
86
|
+
}), [isOptionInStock, options, product.sellingPlanGroups, product.variants, selectedOptions, selectedSellingPlan, selectedSellingPlanAllocation, selectedVariant, sellingPlanGroups, setSelectedOption, variants]);
|
|
87
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ProductOptionsContext.Provider, {
|
|
88
|
+
value,
|
|
89
|
+
children
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function useProduct() {
|
|
93
|
+
const context = react.useContext(ProductOptionsContext);
|
|
94
|
+
if (!context) {
|
|
95
|
+
throw new Error(`'useProduct' must be a child of <ProductProvider />`);
|
|
96
|
+
}
|
|
97
|
+
return context;
|
|
98
|
+
}
|
|
99
|
+
function getSelectedVariant(variants, choices) {
|
|
100
|
+
var _a, _b;
|
|
101
|
+
if (!variants.length || ((_b = (_a = variants == null ? void 0 : variants[0]) == null ? void 0 : _a.selectedOptions) == null ? void 0 : _b.length) !== Object.keys(choices).length) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
return variants == null ? void 0 : variants.find((variant) => {
|
|
105
|
+
return Object.entries(choices).every(([name, value]) => {
|
|
106
|
+
var _a2;
|
|
107
|
+
return (_a2 = variant == null ? void 0 : variant.selectedOptions) == null ? void 0 : _a2.some((option) => (option == null ? void 0 : option.name) === name && (option == null ? void 0 : option.value) === value);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
function getOptions(variants) {
|
|
112
|
+
const map = variants.reduce((memo, variant) => {
|
|
113
|
+
var _a;
|
|
114
|
+
if (!variant.selectedOptions) {
|
|
115
|
+
throw new Error(`'getOptions' requires 'variant.selectedOptions'`);
|
|
116
|
+
}
|
|
117
|
+
(_a = variant == null ? void 0 : variant.selectedOptions) == null ? void 0 : _a.forEach((opt) => {
|
|
118
|
+
var _a2, _b, _c, _d;
|
|
119
|
+
memo[(_a2 = opt == null ? void 0 : opt.name) != null ? _a2 : ""] = memo[(_b = opt == null ? void 0 : opt.name) != null ? _b : ""] || /* @__PURE__ */ new Set();
|
|
120
|
+
memo[(_c = opt == null ? void 0 : opt.name) != null ? _c : ""].add((_d = opt == null ? void 0 : opt.value) != null ? _d : "");
|
|
121
|
+
});
|
|
122
|
+
return memo;
|
|
123
|
+
}, {});
|
|
124
|
+
return Object.keys(map).map((option) => {
|
|
125
|
+
return {
|
|
126
|
+
name: option,
|
|
127
|
+
values: Array.from(map[option])
|
|
128
|
+
};
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
function getVariantBasedOnIdProp(explicitVariantId, variants) {
|
|
132
|
+
if (explicitVariantId) {
|
|
133
|
+
const foundVariant = variants.find((variant) => (variant == null ? void 0 : variant.id) === explicitVariantId);
|
|
134
|
+
if (!foundVariant) {
|
|
135
|
+
console.warn(`<ProductProvider/> received a 'initialVariantId' prop, but could not actually find a variant with that ID`);
|
|
136
|
+
}
|
|
137
|
+
return foundVariant;
|
|
138
|
+
}
|
|
139
|
+
if (explicitVariantId === null) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
if (explicitVariantId === void 0) {
|
|
143
|
+
return variants.find((variant) => variant == null ? void 0 : variant.availableForSale) || variants[0];
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function getSelectedOptions(selectedVariant) {
|
|
147
|
+
return (selectedVariant == null ? void 0 : selectedVariant.selectedOptions) ? selectedVariant.selectedOptions.reduce((memo, optionSet) => {
|
|
148
|
+
var _a, _b;
|
|
149
|
+
memo[(_a = optionSet == null ? void 0 : optionSet.name) != null ? _a : ""] = (_b = optionSet == null ? void 0 : optionSet.value) != null ? _b : "";
|
|
150
|
+
return memo;
|
|
151
|
+
}, {}) : {};
|
|
152
|
+
}
|
|
153
|
+
function isProductVariantArray(maybeVariantArray) {
|
|
154
|
+
if (!maybeVariantArray || !Array.isArray(maybeVariantArray)) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
exports.ProductProvider = ProductProvider;
|
|
160
|
+
exports.useProduct = useProduct;
|
|
161
|
+
//# sourceMappingURL=ProductProvider.cjs.map
|