@shopify/hydrogen-react 0.0.0-next-5e36d61 → 0.0.0-next-781568d

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/dist/browser-dev/AddToCartButton.mjs.map +1 -1
  2. package/dist/browser-dev/BaseButton.mjs.map +1 -1
  3. package/dist/browser-dev/BuyNowButton.mjs.map +1 -1
  4. package/dist/browser-dev/CartCheckoutButton.mjs.map +1 -1
  5. package/dist/browser-dev/CartCost.mjs.map +1 -1
  6. package/dist/browser-dev/CartLinePrice.mjs +3 -0
  7. package/dist/browser-dev/CartLinePrice.mjs.map +1 -1
  8. package/dist/browser-dev/CartLineProvider.mjs +4 -1
  9. package/dist/browser-dev/CartLineProvider.mjs.map +1 -1
  10. package/dist/browser-dev/CartProvider.mjs +3 -3
  11. package/dist/browser-dev/CartProvider.mjs.map +1 -1
  12. package/dist/browser-dev/ExternalVideo.mjs.map +1 -1
  13. package/dist/browser-dev/Image.mjs +1 -1
  14. package/dist/browser-dev/Image.mjs.map +1 -1
  15. package/dist/browser-dev/MediaFile.mjs.map +1 -1
  16. package/dist/browser-dev/ModelViewer.mjs.map +1 -1
  17. package/dist/browser-dev/Money.mjs.map +1 -1
  18. package/dist/browser-dev/ProductPrice.mjs.map +1 -1
  19. package/dist/browser-dev/ProductProvider.mjs.map +1 -1
  20. package/dist/browser-dev/ShopPayButton.mjs.map +1 -1
  21. package/dist/browser-dev/ShopifyProvider.mjs.map +1 -1
  22. package/dist/browser-dev/Video.mjs.map +1 -1
  23. package/dist/browser-dev/analytics.mjs.map +1 -1
  24. package/dist/browser-dev/cart-hooks.mjs +5 -2
  25. package/dist/browser-dev/cart-hooks.mjs.map +1 -1
  26. package/dist/browser-dev/cart-queries.mjs.map +1 -1
  27. package/dist/browser-dev/flatten-connection.mjs +1 -1
  28. package/dist/browser-dev/flatten-connection.mjs.map +1 -1
  29. package/dist/browser-dev/image-size.mjs.map +1 -1
  30. package/dist/browser-dev/load-script.mjs +3 -1
  31. package/dist/browser-dev/load-script.mjs.map +1 -1
  32. package/dist/browser-dev/parse-metafield.mjs.map +1 -1
  33. package/dist/browser-dev/storefront-client.mjs +8 -7
  34. package/dist/browser-dev/storefront-client.mjs.map +1 -1
  35. package/dist/browser-dev/useCartAPIStateMachine.mjs +9 -0
  36. package/dist/browser-dev/useCartAPIStateMachine.mjs.map +1 -1
  37. package/dist/browser-dev/useCartActions.mjs.map +1 -1
  38. package/dist/browser-dev/useMoney.mjs +1 -0
  39. package/dist/browser-dev/useMoney.mjs.map +1 -1
  40. package/dist/browser-prod/AddToCartButton.mjs.map +1 -1
  41. package/dist/browser-prod/BaseButton.mjs.map +1 -1
  42. package/dist/browser-prod/BuyNowButton.mjs.map +1 -1
  43. package/dist/browser-prod/CartCheckoutButton.mjs.map +1 -1
  44. package/dist/browser-prod/CartCost.mjs.map +1 -1
  45. package/dist/browser-prod/CartLinePrice.mjs.map +1 -1
  46. package/dist/browser-prod/CartLineProvider.mjs +4 -1
  47. package/dist/browser-prod/CartLineProvider.mjs.map +1 -1
  48. package/dist/browser-prod/CartProvider.mjs +3 -3
  49. package/dist/browser-prod/CartProvider.mjs.map +1 -1
  50. package/dist/browser-prod/ExternalVideo.mjs.map +1 -1
  51. package/dist/browser-prod/Image.mjs +1 -1
  52. package/dist/browser-prod/Image.mjs.map +1 -1
  53. package/dist/browser-prod/MediaFile.mjs.map +1 -1
  54. package/dist/browser-prod/ModelViewer.mjs.map +1 -1
  55. package/dist/browser-prod/Money.mjs.map +1 -1
  56. package/dist/browser-prod/ProductPrice.mjs.map +1 -1
  57. package/dist/browser-prod/ProductProvider.mjs.map +1 -1
  58. package/dist/browser-prod/ShopPayButton.mjs.map +1 -1
  59. package/dist/browser-prod/ShopifyProvider.mjs.map +1 -1
  60. package/dist/browser-prod/Video.mjs.map +1 -1
  61. package/dist/browser-prod/analytics.mjs.map +1 -1
  62. package/dist/browser-prod/cart-hooks.mjs +5 -2
  63. package/dist/browser-prod/cart-hooks.mjs.map +1 -1
  64. package/dist/browser-prod/cart-queries.mjs.map +1 -1
  65. package/dist/browser-prod/flatten-connection.mjs +1 -1
  66. package/dist/browser-prod/flatten-connection.mjs.map +1 -1
  67. package/dist/browser-prod/image-size.mjs.map +1 -1
  68. package/dist/browser-prod/load-script.mjs +3 -1
  69. package/dist/browser-prod/load-script.mjs.map +1 -1
  70. package/dist/browser-prod/parse-metafield.mjs.map +1 -1
  71. package/dist/browser-prod/storefront-client.mjs +8 -7
  72. package/dist/browser-prod/storefront-client.mjs.map +1 -1
  73. package/dist/browser-prod/useCartAPIStateMachine.mjs +9 -0
  74. package/dist/browser-prod/useCartAPIStateMachine.mjs.map +1 -1
  75. package/dist/browser-prod/useCartActions.mjs.map +1 -1
  76. package/dist/browser-prod/useMoney.mjs +1 -0
  77. package/dist/browser-prod/useMoney.mjs.map +1 -1
  78. package/dist/node-dev/AddToCartButton.js.map +1 -1
  79. package/dist/node-dev/AddToCartButton.mjs.map +1 -1
  80. package/dist/node-dev/BaseButton.js.map +1 -1
  81. package/dist/node-dev/BaseButton.mjs.map +1 -1
  82. package/dist/node-dev/BuyNowButton.js.map +1 -1
  83. package/dist/node-dev/BuyNowButton.mjs.map +1 -1
  84. package/dist/node-dev/CartCheckoutButton.js.map +1 -1
  85. package/dist/node-dev/CartCheckoutButton.mjs.map +1 -1
  86. package/dist/node-dev/CartCost.js.map +1 -1
  87. package/dist/node-dev/CartCost.mjs.map +1 -1
  88. package/dist/node-dev/CartLinePrice.js +3 -0
  89. package/dist/node-dev/CartLinePrice.js.map +1 -1
  90. package/dist/node-dev/CartLinePrice.mjs +3 -0
  91. package/dist/node-dev/CartLinePrice.mjs.map +1 -1
  92. package/dist/node-dev/CartLineProvider.js +4 -1
  93. package/dist/node-dev/CartLineProvider.js.map +1 -1
  94. package/dist/node-dev/CartLineProvider.mjs +4 -1
  95. package/dist/node-dev/CartLineProvider.mjs.map +1 -1
  96. package/dist/node-dev/CartProvider.js +3 -3
  97. package/dist/node-dev/CartProvider.js.map +1 -1
  98. package/dist/node-dev/CartProvider.mjs +3 -3
  99. package/dist/node-dev/CartProvider.mjs.map +1 -1
  100. package/dist/node-dev/ExternalVideo.js.map +1 -1
  101. package/dist/node-dev/ExternalVideo.mjs.map +1 -1
  102. package/dist/node-dev/Image.js +1 -1
  103. package/dist/node-dev/Image.js.map +1 -1
  104. package/dist/node-dev/Image.mjs +1 -1
  105. package/dist/node-dev/Image.mjs.map +1 -1
  106. package/dist/node-dev/MediaFile.js.map +1 -1
  107. package/dist/node-dev/MediaFile.mjs.map +1 -1
  108. package/dist/node-dev/ModelViewer.js.map +1 -1
  109. package/dist/node-dev/ModelViewer.mjs.map +1 -1
  110. package/dist/node-dev/Money.js.map +1 -1
  111. package/dist/node-dev/Money.mjs.map +1 -1
  112. package/dist/node-dev/ProductPrice.js.map +1 -1
  113. package/dist/node-dev/ProductPrice.mjs.map +1 -1
  114. package/dist/node-dev/ProductProvider.js.map +1 -1
  115. package/dist/node-dev/ProductProvider.mjs.map +1 -1
  116. package/dist/node-dev/ShopPayButton.js.map +1 -1
  117. package/dist/node-dev/ShopPayButton.mjs.map +1 -1
  118. package/dist/node-dev/ShopifyProvider.js.map +1 -1
  119. package/dist/node-dev/ShopifyProvider.mjs.map +1 -1
  120. package/dist/node-dev/Video.js.map +1 -1
  121. package/dist/node-dev/Video.mjs.map +1 -1
  122. package/dist/node-dev/analytics.js.map +1 -1
  123. package/dist/node-dev/analytics.mjs.map +1 -1
  124. package/dist/node-dev/cart-hooks.js +5 -2
  125. package/dist/node-dev/cart-hooks.js.map +1 -1
  126. package/dist/node-dev/cart-hooks.mjs +5 -2
  127. package/dist/node-dev/cart-hooks.mjs.map +1 -1
  128. package/dist/node-dev/cart-queries.js.map +1 -1
  129. package/dist/node-dev/cart-queries.mjs.map +1 -1
  130. package/dist/node-dev/flatten-connection.js +1 -1
  131. package/dist/node-dev/flatten-connection.js.map +1 -1
  132. package/dist/node-dev/flatten-connection.mjs +1 -1
  133. package/dist/node-dev/flatten-connection.mjs.map +1 -1
  134. package/dist/node-dev/image-size.js.map +1 -1
  135. package/dist/node-dev/image-size.mjs.map +1 -1
  136. package/dist/node-dev/load-script.js +3 -1
  137. package/dist/node-dev/load-script.js.map +1 -1
  138. package/dist/node-dev/load-script.mjs +3 -1
  139. package/dist/node-dev/load-script.mjs.map +1 -1
  140. package/dist/node-dev/parse-metafield.js.map +1 -1
  141. package/dist/node-dev/parse-metafield.mjs.map +1 -1
  142. package/dist/node-dev/storefront-client.js +8 -7
  143. package/dist/node-dev/storefront-client.js.map +1 -1
  144. package/dist/node-dev/storefront-client.mjs +8 -7
  145. package/dist/node-dev/storefront-client.mjs.map +1 -1
  146. package/dist/node-dev/useCartAPIStateMachine.js +9 -0
  147. package/dist/node-dev/useCartAPIStateMachine.js.map +1 -1
  148. package/dist/node-dev/useCartAPIStateMachine.mjs +9 -0
  149. package/dist/node-dev/useCartAPIStateMachine.mjs.map +1 -1
  150. package/dist/node-dev/useCartActions.js.map +1 -1
  151. package/dist/node-dev/useCartActions.mjs.map +1 -1
  152. package/dist/node-dev/useMoney.js +1 -0
  153. package/dist/node-dev/useMoney.js.map +1 -1
  154. package/dist/node-dev/useMoney.mjs +1 -0
  155. package/dist/node-dev/useMoney.mjs.map +1 -1
  156. package/dist/node-prod/AddToCartButton.js.map +1 -1
  157. package/dist/node-prod/AddToCartButton.mjs.map +1 -1
  158. package/dist/node-prod/BaseButton.js.map +1 -1
  159. package/dist/node-prod/BaseButton.mjs.map +1 -1
  160. package/dist/node-prod/BuyNowButton.js.map +1 -1
  161. package/dist/node-prod/BuyNowButton.mjs.map +1 -1
  162. package/dist/node-prod/CartCheckoutButton.js.map +1 -1
  163. package/dist/node-prod/CartCheckoutButton.mjs.map +1 -1
  164. package/dist/node-prod/CartCost.js.map +1 -1
  165. package/dist/node-prod/CartCost.mjs.map +1 -1
  166. package/dist/node-prod/CartLinePrice.js.map +1 -1
  167. package/dist/node-prod/CartLinePrice.mjs.map +1 -1
  168. package/dist/node-prod/CartLineProvider.js +4 -1
  169. package/dist/node-prod/CartLineProvider.js.map +1 -1
  170. package/dist/node-prod/CartLineProvider.mjs +4 -1
  171. package/dist/node-prod/CartLineProvider.mjs.map +1 -1
  172. package/dist/node-prod/CartProvider.js +3 -3
  173. package/dist/node-prod/CartProvider.js.map +1 -1
  174. package/dist/node-prod/CartProvider.mjs +3 -3
  175. package/dist/node-prod/CartProvider.mjs.map +1 -1
  176. package/dist/node-prod/ExternalVideo.js.map +1 -1
  177. package/dist/node-prod/ExternalVideo.mjs.map +1 -1
  178. package/dist/node-prod/Image.js +1 -1
  179. package/dist/node-prod/Image.js.map +1 -1
  180. package/dist/node-prod/Image.mjs +1 -1
  181. package/dist/node-prod/Image.mjs.map +1 -1
  182. package/dist/node-prod/MediaFile.js.map +1 -1
  183. package/dist/node-prod/MediaFile.mjs.map +1 -1
  184. package/dist/node-prod/ModelViewer.js.map +1 -1
  185. package/dist/node-prod/ModelViewer.mjs.map +1 -1
  186. package/dist/node-prod/Money.js.map +1 -1
  187. package/dist/node-prod/Money.mjs.map +1 -1
  188. package/dist/node-prod/ProductPrice.js.map +1 -1
  189. package/dist/node-prod/ProductPrice.mjs.map +1 -1
  190. package/dist/node-prod/ProductProvider.js.map +1 -1
  191. package/dist/node-prod/ProductProvider.mjs.map +1 -1
  192. package/dist/node-prod/ShopPayButton.js.map +1 -1
  193. package/dist/node-prod/ShopPayButton.mjs.map +1 -1
  194. package/dist/node-prod/ShopifyProvider.js.map +1 -1
  195. package/dist/node-prod/ShopifyProvider.mjs.map +1 -1
  196. package/dist/node-prod/Video.js.map +1 -1
  197. package/dist/node-prod/Video.mjs.map +1 -1
  198. package/dist/node-prod/analytics.js.map +1 -1
  199. package/dist/node-prod/analytics.mjs.map +1 -1
  200. package/dist/node-prod/cart-hooks.js +5 -2
  201. package/dist/node-prod/cart-hooks.js.map +1 -1
  202. package/dist/node-prod/cart-hooks.mjs +5 -2
  203. package/dist/node-prod/cart-hooks.mjs.map +1 -1
  204. package/dist/node-prod/cart-queries.js.map +1 -1
  205. package/dist/node-prod/cart-queries.mjs.map +1 -1
  206. package/dist/node-prod/flatten-connection.js +1 -1
  207. package/dist/node-prod/flatten-connection.js.map +1 -1
  208. package/dist/node-prod/flatten-connection.mjs +1 -1
  209. package/dist/node-prod/flatten-connection.mjs.map +1 -1
  210. package/dist/node-prod/image-size.js.map +1 -1
  211. package/dist/node-prod/image-size.mjs.map +1 -1
  212. package/dist/node-prod/load-script.js +3 -1
  213. package/dist/node-prod/load-script.js.map +1 -1
  214. package/dist/node-prod/load-script.mjs +3 -1
  215. package/dist/node-prod/load-script.mjs.map +1 -1
  216. package/dist/node-prod/parse-metafield.js.map +1 -1
  217. package/dist/node-prod/parse-metafield.mjs.map +1 -1
  218. package/dist/node-prod/storefront-client.js +8 -7
  219. package/dist/node-prod/storefront-client.js.map +1 -1
  220. package/dist/node-prod/storefront-client.mjs +8 -7
  221. package/dist/node-prod/storefront-client.mjs.map +1 -1
  222. package/dist/node-prod/useCartAPIStateMachine.js +9 -0
  223. package/dist/node-prod/useCartAPIStateMachine.js.map +1 -1
  224. package/dist/node-prod/useCartAPIStateMachine.mjs +9 -0
  225. package/dist/node-prod/useCartAPIStateMachine.mjs.map +1 -1
  226. package/dist/node-prod/useCartActions.js.map +1 -1
  227. package/dist/node-prod/useCartActions.mjs.map +1 -1
  228. package/dist/node-prod/useMoney.js +1 -0
  229. package/dist/node-prod/useMoney.js.map +1 -1
  230. package/dist/node-prod/useMoney.mjs +1 -0
  231. package/dist/node-prod/useMoney.mjs.map +1 -1
  232. package/dist/types/CartLinePrice.d.ts +12 -0
  233. package/dist/types/CartLineProvider.d.ts +1 -1
  234. package/dist/types/CartProvider.d.ts +1 -1
  235. package/dist/types/image-size.d.ts +1 -1
  236. package/dist/types/parse-metafield.d.ts +1 -1
  237. package/dist/types/storefront-client.d.ts +1 -1
  238. package/dist/umd/hydrogen-react.dev.js +38 -16
  239. package/dist/umd/hydrogen-react.dev.js.map +1 -1
  240. package/dist/umd/hydrogen-react.prod.js +7 -7
  241. package/dist/umd/hydrogen-react.prod.js.map +1 -1
  242. package/package.json +11 -1
@@ -1 +1 @@
1
- {"version":3,"file":"AddToCartButton.mjs","sources":["../../src/AddToCartButton.tsx"],"sourcesContent":["import {useCallback, useEffect, useState} from 'react';\nimport {useCart} from './CartProvider.js';\nimport {useProduct} from './ProductProvider.js';\nimport {\n BaseButton,\n type CustomBaseButtonProps,\n type BaseButtonProps,\n} from './BaseButton.js';\nimport * as React from 'react';\n\nexport interface AddToCartButtonPropsBase {\n /** An array of cart line attributes that belong to the item being added to the cart. */\n attributes?: {\n key: string;\n value: string;\n }[];\n /** The ID of the variant. */\n variantId?: string | null;\n /** The item quantity. */\n quantity?: number;\n /** The text that is announced by the screen reader when the item is being added to the cart. Used for accessibility purposes only and not displayed on the page. */\n accessibleAddingToCartLabel?: string;\n /** The selling plan ID of the subscription variant */\n sellingPlanId?: string;\n}\n\nexport type AddToCartButtonProps<AsType extends React.ElementType = 'button'> =\n AddToCartButtonPropsBase & BaseButtonProps<AsType>;\n\n/**\n * The `AddToCartButton` component renders a button that adds an item to the cart when pressed.\n * It must be a descendent of the `CartProvider` component.\n */\nexport function AddToCartButton<AsType extends React.ElementType = 'button'>(\n props: AddToCartButtonProps<AsType>\n) {\n const [addingItem, setAddingItem] = useState<boolean>(false);\n const {\n variantId: explicitVariantId,\n quantity = 1,\n attributes,\n sellingPlanId,\n onClick,\n children,\n accessibleAddingToCartLabel,\n ...passthroughProps\n } = props;\n const {status, linesAdd} = useCart();\n const {selectedVariant} = useProduct();\n const variantId = explicitVariantId ?? selectedVariant?.id ?? '';\n const disabled =\n explicitVariantId === null ||\n variantId === '' ||\n selectedVariant === null ||\n addingItem ||\n passthroughProps.disabled;\n\n useEffect(() => {\n if (addingItem && status === 'idle') {\n setAddingItem(false);\n }\n }, [status, addingItem]);\n\n const handleAddItem = useCallback(() => {\n setAddingItem(true);\n linesAdd([\n {\n quantity,\n merchandiseId: variantId || '',\n attributes,\n sellingPlanId,\n },\n ]);\n }, [linesAdd, quantity, variantId, attributes, sellingPlanId]);\n\n return (\n <>\n <BaseButton\n {...passthroughProps}\n disabled={disabled}\n onClick={onClick}\n defaultOnClick={handleAddItem}\n >\n {children}\n </BaseButton>\n {accessibleAddingToCartLabel ? (\n <p\n style={{\n position: 'absolute',\n width: '1px',\n height: '1px',\n padding: '0',\n margin: '-1px',\n overflow: 'hidden',\n clip: 'rect(0, 0, 0, 0)',\n whiteSpace: 'nowrap',\n borderWidth: '0',\n }}\n role=\"alert\"\n aria-live=\"assertive\"\n >\n {addingItem ? accessibleAddingToCartLabel : null}\n </p>\n ) : null}\n </>\n );\n}\n\n// This is only for documenation purposes, and it is not used in the code.\nexport interface AddToCartButtonPropsForDocs<\n AsType extends React.ElementType = 'button'\n> extends AddToCartButtonPropsBase,\n CustomBaseButtonProps<AsType> {}\n"],"names":[],"mappings":";;;;;AAiCO,SAAS,gBACd,OACA;AACA,QAAM,CAAC,YAAY,aAAa,IAAI,SAAkB,KAAK;AACrD,QAAA;AAAA,IACJ,WAAW;AAAA,IACX,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACD,IAAA;AACJ,QAAM,EAAC,QAAQ,SAAQ,IAAI,QAAQ;AAC7B,QAAA,EAAC,oBAAmB;AACpB,QAAA,YAAY,sBAAqB,mDAAiB,OAAM;AACxD,QAAA,WACJ,sBAAsB,QACtB,cAAc,MACd,oBAAoB,QACpB,cACA,iBAAiB;AAEnB,YAAU,MAAM;AACV,QAAA,cAAc,WAAW,QAAQ;AACnC,oBAAc,KAAK;AAAA,IACrB;AAAA,EAAA,GACC,CAAC,QAAQ,UAAU,CAAC;AAEjB,QAAA,gBAAgB,YAAY,MAAM;AACtC,kBAAc,IAAI;AACT,aAAA;AAAA,MACP;AAAA,QACE;AAAA,QACA,eAAe,aAAa;AAAA,QAC5B;AAAA,QACA;AAAA,MACF;AAAA,IAAA,CACD;AAAA,EAAA,GACA,CAAC,UAAU,UAAU,WAAW,YAAY,aAAa,CAAC;AAE7D,SAEI,qBAAA,UAAA,EAAA,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACE,GAAG;AAAA,QACJ;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,QAEf;AAAA,MAAA;AAAA,IACH;AAAA,IACC,8BACC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAO;AAAA,UACL,UAAU;AAAA,UACV,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,aAAa;AAAA,QACf;AAAA,QACA,MAAK;AAAA,QACL,aAAU;AAAA,QAET,uBAAa,8BAA8B;AAAA,MAAA;AAAA,IAAA,IAE5C;AAAA,EACN,EAAA,CAAA;AAEJ;"}
1
+ {"version":3,"file":"AddToCartButton.mjs","sources":["../../src/AddToCartButton.tsx"],"sourcesContent":["import {useCallback, useEffect, useState} from 'react';\nimport {useCart} from './CartProvider.js';\nimport {useProduct} from './ProductProvider.js';\nimport {\n BaseButton,\n type CustomBaseButtonProps,\n type BaseButtonProps,\n} from './BaseButton.js';\nimport * as React from 'react';\n\nexport interface AddToCartButtonPropsBase {\n /** An array of cart line attributes that belong to the item being added to the cart. */\n attributes?: {\n key: string;\n value: string;\n }[];\n /** The ID of the variant. */\n variantId?: string | null;\n /** The item quantity. */\n quantity?: number;\n /** The text that is announced by the screen reader when the item is being added to the cart. Used for accessibility purposes only and not displayed on the page. */\n accessibleAddingToCartLabel?: string;\n /** The selling plan ID of the subscription variant */\n sellingPlanId?: string;\n}\n\nexport type AddToCartButtonProps<AsType extends React.ElementType = 'button'> =\n AddToCartButtonPropsBase & BaseButtonProps<AsType>;\n\n/**\n * The `AddToCartButton` component renders a button that adds an item to the cart when pressed.\n * It must be a descendent of the `CartProvider` component.\n */\nexport function AddToCartButton<AsType extends React.ElementType = 'button'>(\n props: AddToCartButtonProps<AsType>\n): JSX.Element {\n const [addingItem, setAddingItem] = useState<boolean>(false);\n const {\n variantId: explicitVariantId,\n quantity = 1,\n attributes,\n sellingPlanId,\n onClick,\n children,\n accessibleAddingToCartLabel,\n ...passthroughProps\n } = props;\n const {status, linesAdd} = useCart();\n const {selectedVariant} = useProduct();\n const variantId = explicitVariantId ?? selectedVariant?.id ?? '';\n const disabled =\n explicitVariantId === null ||\n variantId === '' ||\n selectedVariant === null ||\n addingItem ||\n passthroughProps.disabled;\n\n useEffect(() => {\n if (addingItem && status === 'idle') {\n setAddingItem(false);\n }\n }, [status, addingItem]);\n\n const handleAddItem = useCallback(() => {\n setAddingItem(true);\n linesAdd([\n {\n quantity,\n merchandiseId: variantId || '',\n attributes,\n sellingPlanId,\n },\n ]);\n }, [linesAdd, quantity, variantId, attributes, sellingPlanId]);\n\n return (\n <>\n <BaseButton\n {...passthroughProps}\n disabled={disabled}\n onClick={onClick}\n defaultOnClick={handleAddItem}\n >\n {children}\n </BaseButton>\n {accessibleAddingToCartLabel ? (\n <p\n style={{\n position: 'absolute',\n width: '1px',\n height: '1px',\n padding: '0',\n margin: '-1px',\n overflow: 'hidden',\n clip: 'rect(0, 0, 0, 0)',\n whiteSpace: 'nowrap',\n borderWidth: '0',\n }}\n role=\"alert\"\n aria-live=\"assertive\"\n >\n {addingItem ? accessibleAddingToCartLabel : null}\n </p>\n ) : null}\n </>\n );\n}\n\n// This is only for documenation purposes, and it is not used in the code.\nexport interface AddToCartButtonPropsForDocs<\n AsType extends React.ElementType = 'button'\n> extends AddToCartButtonPropsBase,\n CustomBaseButtonProps<AsType> {}\n"],"names":[],"mappings":";;;;;AAiCO,SAAS,gBACd,OACa;AACb,QAAM,CAAC,YAAY,aAAa,IAAI,SAAkB,KAAK;AACrD,QAAA;AAAA,IACJ,WAAW;AAAA,IACX,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACD,IAAA;AACJ,QAAM,EAAC,QAAQ,SAAQ,IAAI,QAAQ;AAC7B,QAAA,EAAC,oBAAmB;AACpB,QAAA,YAAY,sBAAqB,mDAAiB,OAAM;AACxD,QAAA,WACJ,sBAAsB,QACtB,cAAc,MACd,oBAAoB,QACpB,cACA,iBAAiB;AAEnB,YAAU,MAAM;AACV,QAAA,cAAc,WAAW,QAAQ;AACnC,oBAAc,KAAK;AAAA,IACrB;AAAA,EAAA,GACC,CAAC,QAAQ,UAAU,CAAC;AAEjB,QAAA,gBAAgB,YAAY,MAAM;AACtC,kBAAc,IAAI;AACT,aAAA;AAAA,MACP;AAAA,QACE;AAAA,QACA,eAAe,aAAa;AAAA,QAC5B;AAAA,QACA;AAAA,MACF;AAAA,IAAA,CACD;AAAA,EAAA,GACA,CAAC,UAAU,UAAU,WAAW,YAAY,aAAa,CAAC;AAE7D,SAEI,qBAAA,UAAA,EAAA,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACE,GAAG;AAAA,QACJ;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,QAEf;AAAA,MAAA;AAAA,IACH;AAAA,IACC,8BACC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAO;AAAA,UACL,UAAU;AAAA,UACV,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,aAAa;AAAA,QACf;AAAA,QACA,MAAK;AAAA,QACL,aAAU;AAAA,QAET,uBAAa,8BAA8B;AAAA,MAAA;AAAA,IAAA,IAE5C;AAAA,EACN,EAAA,CAAA;AAEJ;"}
@@ -1 +1 @@
1
- {"version":3,"file":"BaseButton.mjs","sources":["../../src/BaseButton.tsx"],"sourcesContent":["import {ReactNode, Ref, useCallback} from 'react';\n\nexport interface CustomBaseButtonProps<AsType> {\n /** Provide a React element or component to render as the underlying button. Note: for accessibility compliance, almost always you should use a `button` element, or a component that renders an underlying button. */\n as?: AsType;\n /** Any ReactNode elements. */\n children: ReactNode;\n /** Click event handler. Default behaviour triggers unless prevented */\n onClick?: (\n event?: React.MouseEvent<HTMLButtonElement, MouseEvent>\n ) => void | boolean;\n /** A default `onClick` behavior */\n defaultOnClick?: (\n event?: React.MouseEvent<HTMLButtonElement, MouseEvent>\n ) => void | boolean;\n /** A `ref` to the underlying button */\n buttonRef?: Ref<HTMLButtonElement>;\n}\n\nexport type BaseButtonProps<AsType extends React.ElementType> =\n CustomBaseButtonProps<AsType> &\n Omit<\n React.ComponentPropsWithoutRef<AsType>,\n keyof CustomBaseButtonProps<AsType>\n >;\n\nexport function BaseButton<AsType extends React.ElementType = 'button'>(\n props: BaseButtonProps<AsType>\n) {\n const {\n as,\n onClick,\n defaultOnClick,\n children,\n buttonRef,\n ...passthroughProps\n } = props;\n\n const handleOnClick = useCallback(\n (event?: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {\n if (onClick) {\n const clickShouldContinue = onClick(event);\n if (\n (typeof clickShouldContinue === 'boolean' &&\n clickShouldContinue === false) ||\n event?.defaultPrevented\n )\n return;\n }\n\n defaultOnClick?.(event);\n },\n [defaultOnClick, onClick]\n );\n\n const Component = as || 'button';\n\n return (\n <Component ref={buttonRef} onClick={handleOnClick} {...passthroughProps}>\n {children}\n </Component>\n );\n}\n"],"names":[],"mappings":";;AA0BO,SAAS,WACd,OACA;AACM,QAAA;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACD,IAAA;AAEJ,QAAM,gBAAgB;AAAA,IACpB,CAAC,UAA4D;AAC3D,UAAI,SAAS;AACL,cAAA,sBAAsB,QAAQ,KAAK;AACzC,YACG,OAAO,wBAAwB,aAC9B,wBAAwB,UAC1B,+BAAO;AAEP;AAAA,MACJ;AAEA,uDAAiB;AAAA,IACnB;AAAA,IACA,CAAC,gBAAgB,OAAO;AAAA,EAAA;AAG1B,QAAM,YAAY,MAAM;AAGtB,SAAA,oBAAC,aAAU,KAAK,WAAW,SAAS,eAAgB,GAAG,kBACpD,SACH,CAAA;AAEJ;"}
1
+ {"version":3,"file":"BaseButton.mjs","sources":["../../src/BaseButton.tsx"],"sourcesContent":["import {ReactNode, Ref, useCallback} from 'react';\n\nexport interface CustomBaseButtonProps<AsType> {\n /** Provide a React element or component to render as the underlying button. Note: for accessibility compliance, almost always you should use a `button` element, or a component that renders an underlying button. */\n as?: AsType;\n /** Any ReactNode elements. */\n children: ReactNode;\n /** Click event handler. Default behaviour triggers unless prevented */\n onClick?: (\n event?: React.MouseEvent<HTMLButtonElement, MouseEvent>\n ) => void | boolean;\n /** A default `onClick` behavior */\n defaultOnClick?: (\n event?: React.MouseEvent<HTMLButtonElement, MouseEvent>\n ) => void | boolean;\n /** A `ref` to the underlying button */\n buttonRef?: Ref<HTMLButtonElement>;\n}\n\nexport type BaseButtonProps<AsType extends React.ElementType> =\n CustomBaseButtonProps<AsType> &\n Omit<\n React.ComponentPropsWithoutRef<AsType>,\n keyof CustomBaseButtonProps<AsType>\n >;\n\nexport function BaseButton<AsType extends React.ElementType = 'button'>(\n props: BaseButtonProps<AsType>\n): JSX.Element {\n const {\n as,\n onClick,\n defaultOnClick,\n children,\n buttonRef,\n ...passthroughProps\n } = props;\n\n const handleOnClick = useCallback(\n (event?: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {\n if (onClick) {\n const clickShouldContinue = onClick(event);\n if (\n (typeof clickShouldContinue === 'boolean' &&\n clickShouldContinue === false) ||\n event?.defaultPrevented\n )\n return;\n }\n\n defaultOnClick?.(event);\n },\n [defaultOnClick, onClick]\n );\n\n const Component = as || 'button';\n\n return (\n <Component ref={buttonRef} onClick={handleOnClick} {...passthroughProps}>\n {children}\n </Component>\n );\n}\n"],"names":[],"mappings":";;AA0BO,SAAS,WACd,OACa;AACP,QAAA;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACD,IAAA;AAEJ,QAAM,gBAAgB;AAAA,IACpB,CAAC,UAA4D;AAC3D,UAAI,SAAS;AACL,cAAA,sBAAsB,QAAQ,KAAK;AACzC,YACG,OAAO,wBAAwB,aAC9B,wBAAwB,UAC1B,+BAAO;AAEP;AAAA,MACJ;AAEA,uDAAiB;AAAA,IACnB;AAAA,IACA,CAAC,gBAAgB,OAAO;AAAA,EAAA;AAG1B,QAAM,YAAY,MAAM;AAGtB,SAAA,oBAAC,aAAU,KAAK,WAAW,SAAS,eAAgB,GAAG,kBACpD,SACH,CAAA;AAEJ;"}
@@ -1 +1 @@
1
- {"version":3,"file":"BuyNowButton.mjs","sources":["../../src/BuyNowButton.tsx"],"sourcesContent":["import {useEffect, useState, useCallback} from 'react';\nimport {useCart} from './CartProvider.js';\nimport {\n BaseButton,\n type BaseButtonProps,\n type CustomBaseButtonProps,\n} from './BaseButton.js';\n\ninterface BuyNowButtonPropsBase {\n /** The item quantity. Defaults to 1. */\n quantity?: number;\n /** The ID of the variant. */\n variantId: string;\n /** An array of cart line attributes that belong to the item being added to the cart. */\n attributes?: {\n key: string;\n value: string;\n }[];\n}\n\ntype BuyNowButtonProps<AsType extends React.ElementType = 'button'> =\n BuyNowButtonPropsBase & BaseButtonProps<AsType>;\n\n/**\n * The `BuyNowButton` component renders a button that adds an item to the cart and redirects the customer to checkout.\n * Must be a child of a `CartProvider` component.\n */\nexport function BuyNowButton<AsType extends React.ElementType = 'button'>(\n props: BuyNowButtonProps<AsType>\n) {\n const {cartCreate, checkoutUrl} = useCart();\n const [loading, setLoading] = useState<boolean>(false);\n\n const {\n quantity,\n variantId,\n onClick,\n attributes,\n children,\n ...passthroughProps\n } = props;\n\n useEffect(() => {\n if (checkoutUrl) {\n window.location.href = checkoutUrl;\n }\n }, [checkoutUrl]);\n\n const handleBuyNow = useCallback(() => {\n setLoading(true);\n cartCreate({\n lines: [\n {\n quantity: quantity ?? 1,\n merchandiseId: variantId,\n attributes,\n },\n ],\n });\n }, [cartCreate, quantity, variantId, attributes]);\n\n return (\n <BaseButton\n disabled={loading ?? passthroughProps.disabled}\n {...passthroughProps}\n onClick={onClick}\n defaultOnClick={handleBuyNow}\n >\n {children}\n </BaseButton>\n );\n}\n\n// This is only for documenation purposes, and it is not used in the code.\nexport interface BuyNowButtonPropsForDocs<\n AsType extends React.ElementType = 'button'\n> extends BuyNowButtonPropsBase,\n CustomBaseButtonProps<AsType> {}\n"],"names":[],"mappings":";;;;AA2BO,SAAS,aACd,OACA;AACA,QAAM,EAAC,YAAY,YAAW,IAAI,QAAQ;AAC1C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAkB,KAAK;AAE/C,QAAA;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACD,IAAA;AAEJ,YAAU,MAAM;AACd,QAAI,aAAa;AACf,aAAO,SAAS,OAAO;AAAA,IACzB;AAAA,EAAA,GACC,CAAC,WAAW,CAAC;AAEV,QAAA,eAAe,YAAY,MAAM;AACrC,eAAW,IAAI;AACJ,eAAA;AAAA,MACT,OAAO;AAAA,QACL;AAAA,UACE,UAAU,YAAY;AAAA,UACtB,eAAe;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IAAA,CACD;AAAA,KACA,CAAC,YAAY,UAAU,WAAW,UAAU,CAAC;AAG9C,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,UAAU,WAAW,iBAAiB;AAAA,MACrC,GAAG;AAAA,MACJ;AAAA,MACA,gBAAgB;AAAA,MAEf;AAAA,IAAA;AAAA,EAAA;AAGP;"}
1
+ {"version":3,"file":"BuyNowButton.mjs","sources":["../../src/BuyNowButton.tsx"],"sourcesContent":["import {useEffect, useState, useCallback} from 'react';\nimport {useCart} from './CartProvider.js';\nimport {\n BaseButton,\n type BaseButtonProps,\n type CustomBaseButtonProps,\n} from './BaseButton.js';\n\ninterface BuyNowButtonPropsBase {\n /** The item quantity. Defaults to 1. */\n quantity?: number;\n /** The ID of the variant. */\n variantId: string;\n /** An array of cart line attributes that belong to the item being added to the cart. */\n attributes?: {\n key: string;\n value: string;\n }[];\n}\n\ntype BuyNowButtonProps<AsType extends React.ElementType = 'button'> =\n BuyNowButtonPropsBase & BaseButtonProps<AsType>;\n\n/**\n * The `BuyNowButton` component renders a button that adds an item to the cart and redirects the customer to checkout.\n * Must be a child of a `CartProvider` component.\n */\nexport function BuyNowButton<AsType extends React.ElementType = 'button'>(\n props: BuyNowButtonProps<AsType>\n): JSX.Element {\n const {cartCreate, checkoutUrl} = useCart();\n const [loading, setLoading] = useState<boolean>(false);\n\n const {\n quantity,\n variantId,\n onClick,\n attributes,\n children,\n ...passthroughProps\n } = props;\n\n useEffect(() => {\n if (checkoutUrl) {\n window.location.href = checkoutUrl;\n }\n }, [checkoutUrl]);\n\n const handleBuyNow = useCallback(() => {\n setLoading(true);\n cartCreate({\n lines: [\n {\n quantity: quantity ?? 1,\n merchandiseId: variantId,\n attributes,\n },\n ],\n });\n }, [cartCreate, quantity, variantId, attributes]);\n\n return (\n <BaseButton\n disabled={loading ?? passthroughProps.disabled}\n {...passthroughProps}\n onClick={onClick}\n defaultOnClick={handleBuyNow}\n >\n {children}\n </BaseButton>\n );\n}\n\n// This is only for documenation purposes, and it is not used in the code.\nexport interface BuyNowButtonPropsForDocs<\n AsType extends React.ElementType = 'button'\n> extends BuyNowButtonPropsBase,\n CustomBaseButtonProps<AsType> {}\n"],"names":[],"mappings":";;;;AA2BO,SAAS,aACd,OACa;AACb,QAAM,EAAC,YAAY,YAAW,IAAI,QAAQ;AAC1C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAkB,KAAK;AAE/C,QAAA;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACD,IAAA;AAEJ,YAAU,MAAM;AACd,QAAI,aAAa;AACf,aAAO,SAAS,OAAO;AAAA,IACzB;AAAA,EAAA,GACC,CAAC,WAAW,CAAC;AAEV,QAAA,eAAe,YAAY,MAAM;AACrC,eAAW,IAAI;AACJ,eAAA;AAAA,MACT,OAAO;AAAA,QACL;AAAA,UACE,UAAU,YAAY;AAAA,UACtB,eAAe;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IAAA,CACD;AAAA,KACA,CAAC,YAAY,UAAU,WAAW,UAAU,CAAC;AAG9C,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,UAAU,WAAW,iBAAiB;AAAA,MACrC,GAAG;AAAA,MACJ;AAAA,MACA,gBAAgB;AAAA,MAEf;AAAA,IAAA;AAAA,EAAA;AAGP;"}
@@ -1 +1 @@
1
- {"version":3,"file":"CartCheckoutButton.mjs","sources":["../../src/CartCheckoutButton.tsx"],"sourcesContent":["import {ReactNode, useEffect, useState} from 'react';\nimport {useCart} from './CartProvider.js';\nimport {\n BaseButton,\n type BaseButtonProps,\n type CustomBaseButtonProps,\n} from './BaseButton.js';\n\ntype ChildrenProps = {\n /** A `ReactNode` element. */\n children: ReactNode;\n};\ntype CartCheckoutButtonProps = Omit<BaseButtonProps<'button'>, 'onClick'> &\n ChildrenProps;\n\n/**\n * The `CartCheckoutButton` component renders a button that redirects to the checkout URL for the cart.\n * It must be a descendent of a `CartProvider` component.\n */\nexport function CartCheckoutButton(props: CartCheckoutButtonProps) {\n const [requestedCheckout, setRequestedCheckout] = useState(false);\n const {status, checkoutUrl} = useCart();\n const {children, ...passthroughProps} = props;\n\n useEffect(() => {\n if (requestedCheckout && checkoutUrl && status === 'idle') {\n window.location.href = checkoutUrl;\n }\n }, [requestedCheckout, status, checkoutUrl]);\n\n return (\n <BaseButton\n {...passthroughProps}\n disabled={requestedCheckout || passthroughProps.disabled}\n onClick={() => setRequestedCheckout(true)}\n >\n {children}\n </BaseButton>\n );\n}\n\n// This is only for documentation purposes, and it is not used in the code.\n// we ignore this issue because it makes the documentation look better than the equivalent `type` that it wants us to convert to\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface CartCheckoutButtonPropsForDocs<\n AsType extends React.ElementType = 'button'\n> extends Omit<CustomBaseButtonProps<AsType>, 'onClick'> {}\n"],"names":[],"mappings":";;;;AAmBO,SAAS,mBAAmB,OAAgC;AACjE,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,SAAS,KAAK;AAChE,QAAM,EAAC,QAAQ,YAAW,IAAI,QAAQ;AACtC,QAAM,EAAC,UAAU,GAAG,iBAAA,IAAoB;AAExC,YAAU,MAAM;AACV,QAAA,qBAAqB,eAAe,WAAW,QAAQ;AACzD,aAAO,SAAS,OAAO;AAAA,IACzB;AAAA,EACC,GAAA,CAAC,mBAAmB,QAAQ,WAAW,CAAC;AAGzC,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACE,GAAG;AAAA,MACJ,UAAU,qBAAqB,iBAAiB;AAAA,MAChD,SAAS,MAAM,qBAAqB,IAAI;AAAA,MAEvC;AAAA,IAAA;AAAA,EAAA;AAGP;"}
1
+ {"version":3,"file":"CartCheckoutButton.mjs","sources":["../../src/CartCheckoutButton.tsx"],"sourcesContent":["import {ReactNode, useEffect, useState} from 'react';\nimport {useCart} from './CartProvider.js';\nimport {\n BaseButton,\n type BaseButtonProps,\n type CustomBaseButtonProps,\n} from './BaseButton.js';\n\ntype ChildrenProps = {\n /** A `ReactNode` element. */\n children: ReactNode;\n};\ntype CartCheckoutButtonProps = Omit<BaseButtonProps<'button'>, 'onClick'> &\n ChildrenProps;\n\n/**\n * The `CartCheckoutButton` component renders a button that redirects to the checkout URL for the cart.\n * It must be a descendent of a `CartProvider` component.\n */\nexport function CartCheckoutButton(\n props: CartCheckoutButtonProps\n): JSX.Element {\n const [requestedCheckout, setRequestedCheckout] = useState(false);\n const {status, checkoutUrl} = useCart();\n const {children, ...passthroughProps} = props;\n\n useEffect(() => {\n if (requestedCheckout && checkoutUrl && status === 'idle') {\n window.location.href = checkoutUrl;\n }\n }, [requestedCheckout, status, checkoutUrl]);\n\n return (\n <BaseButton\n {...passthroughProps}\n disabled={requestedCheckout || passthroughProps.disabled}\n onClick={(): void => setRequestedCheckout(true)}\n >\n {children}\n </BaseButton>\n );\n}\n\n// This is only for documentation purposes, and it is not used in the code.\n// we ignore this issue because it makes the documentation look better than the equivalent `type` that it wants us to convert to\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface CartCheckoutButtonPropsForDocs<\n AsType extends React.ElementType = 'button'\n> extends Omit<CustomBaseButtonProps<AsType>, 'onClick'> {}\n"],"names":[],"mappings":";;;;AAmBO,SAAS,mBACd,OACa;AACb,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,SAAS,KAAK;AAChE,QAAM,EAAC,QAAQ,YAAW,IAAI,QAAQ;AACtC,QAAM,EAAC,UAAU,GAAG,iBAAA,IAAoB;AAExC,YAAU,MAAM;AACV,QAAA,qBAAqB,eAAe,WAAW,QAAQ;AACzD,aAAO,SAAS,OAAO;AAAA,IACzB;AAAA,EACC,GAAA,CAAC,mBAAmB,QAAQ,WAAW,CAAC;AAGzC,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACE,GAAG;AAAA,MACJ,UAAU,qBAAqB,iBAAiB;AAAA,MAChD,SAAS,MAAY,qBAAqB,IAAI;AAAA,MAE7C;AAAA,IAAA;AAAA,EAAA;AAGP;"}
@@ -1 +1 @@
1
- {"version":3,"file":"CartCost.mjs","sources":["../../src/CartCost.tsx"],"sourcesContent":["import {Money, type MoneyPropsBase} from './Money.js';\nimport {useCart} from './CartProvider.js';\n\ninterface CartCostPropsBase {\n /** A string type that defines the type of cost needed. Valid values: `total`, `subtotal`, `tax`, or `duty`. */\n amountType?: 'total' | 'subtotal' | 'tax' | 'duty';\n /** Any `ReactNode` elements. */\n children?: React.ReactNode;\n}\n\ntype CartCostProps = Omit<React.ComponentProps<typeof Money>, 'data'> &\n CartCostPropsBase;\n\n/**\n * The `CartCost` component renders a `Money` component with the cost associated with the `amountType` prop.\n * If no `amountType` prop is specified, then it defaults to `totalAmount`.\n * Depends on `useCart()` and must be a child of `<CartProvider/>`\n */\nexport function CartCost(props: CartCostProps) {\n const {cost} = useCart();\n const {amountType = 'total', children, ...passthroughProps} = props;\n let amount;\n\n if (amountType == 'total') {\n amount = cost?.totalAmount;\n } else if (amountType == 'subtotal') {\n amount = cost?.subtotalAmount;\n } else if (amountType == 'tax') {\n amount = cost?.totalTaxAmount;\n } else if (amountType == 'duty') {\n amount = cost?.totalDutyAmount;\n }\n\n if (amount == null) {\n return null;\n }\n\n return (\n <Money {...passthroughProps} data={amount}>\n {children}\n </Money>\n );\n}\n\n// This is only for documenation purposes, and it is not used in the code.\nexport interface CartCostPropsForDocs<AsType extends React.ElementType = 'div'>\n extends Omit<MoneyPropsBase<AsType>, 'data'>,\n CartCostPropsBase {}\n"],"names":[],"mappings":";;;AAkBO,SAAS,SAAS,OAAsB;AACvC,QAAA,EAAC,SAAQ;AACf,QAAM,EAAC,aAAa,SAAS,UAAU,GAAG,iBAAoB,IAAA;AAC1D,MAAA;AAEJ,MAAI,cAAc,SAAS;AACzB,aAAS,6BAAM;AAAA,EAAA,WACN,cAAc,YAAY;AACnC,aAAS,6BAAM;AAAA,EAAA,WACN,cAAc,OAAO;AAC9B,aAAS,6BAAM;AAAA,EAAA,WACN,cAAc,QAAQ;AAC/B,aAAS,6BAAM;AAAA,EACjB;AAEA,MAAI,UAAU,MAAM;AACX,WAAA;AAAA,EACT;AAEA,6BACG,OAAO,EAAA,GAAG,kBAAkB,MAAM,QAChC,SACH,CAAA;AAEJ;"}
1
+ {"version":3,"file":"CartCost.mjs","sources":["../../src/CartCost.tsx"],"sourcesContent":["import {Money, type MoneyPropsBase} from './Money.js';\nimport {useCart} from './CartProvider.js';\n\ninterface CartCostPropsBase {\n /** A string type that defines the type of cost needed. Valid values: `total`, `subtotal`, `tax`, or `duty`. */\n amountType?: 'total' | 'subtotal' | 'tax' | 'duty';\n /** Any `ReactNode` elements. */\n children?: React.ReactNode;\n}\n\ntype CartCostProps = Omit<React.ComponentProps<typeof Money>, 'data'> &\n CartCostPropsBase;\n\n/**\n * The `CartCost` component renders a `Money` component with the cost associated with the `amountType` prop.\n * If no `amountType` prop is specified, then it defaults to `totalAmount`.\n * Depends on `useCart()` and must be a child of `<CartProvider/>`\n */\nexport function CartCost(props: CartCostProps): JSX.Element | null {\n const {cost} = useCart();\n const {amountType = 'total', children, ...passthroughProps} = props;\n let amount;\n\n if (amountType == 'total') {\n amount = cost?.totalAmount;\n } else if (amountType == 'subtotal') {\n amount = cost?.subtotalAmount;\n } else if (amountType == 'tax') {\n amount = cost?.totalTaxAmount;\n } else if (amountType == 'duty') {\n amount = cost?.totalDutyAmount;\n }\n\n if (amount == null) {\n return null;\n }\n\n return (\n <Money {...passthroughProps} data={amount}>\n {children}\n </Money>\n );\n}\n\n// This is only for documenation purposes, and it is not used in the code.\nexport interface CartCostPropsForDocs<AsType extends React.ElementType = 'div'>\n extends Omit<MoneyPropsBase<AsType>, 'data'>,\n CartCostPropsBase {}\n"],"names":[],"mappings":";;;AAkBO,SAAS,SAAS,OAA0C;AAC3D,QAAA,EAAC,SAAQ;AACf,QAAM,EAAC,aAAa,SAAS,UAAU,GAAG,iBAAoB,IAAA;AAC1D,MAAA;AAEJ,MAAI,cAAc,SAAS;AACzB,aAAS,6BAAM;AAAA,EAAA,WACN,cAAc,YAAY;AACnC,aAAS,6BAAM;AAAA,EAAA,WACN,cAAc,OAAO;AAC9B,aAAS,6BAAM;AAAA,EAAA,WACN,cAAc,QAAQ;AAC/B,aAAS,6BAAM;AAAA,EACjB;AAEA,MAAI,UAAU,MAAM;AACX,WAAA;AAAA,EACT;AAEA,6BACG,OAAO,EAAA,GAAG,kBAAkB,MAAM,QAChC,SACH,CAAA;AAEJ;"}
@@ -2,6 +2,9 @@ import { jsx } from "react/jsx-runtime";
2
2
  import { Money } from "./Money.mjs";
3
3
  function CartLinePrice(props) {
4
4
  var _a, _b;
5
+ {
6
+ console.warn(`<CartLinePrice/> is deprecated; use <Money/> instead.`);
7
+ }
5
8
  const { data: cartLine, priceType = "regular", ...passthroughProps } = props;
6
9
  if (cartLine == null) {
7
10
  throw new Error(`<CartLinePrice/> requires a cart line as the 'data' prop`);
@@ -1 +1 @@
1
- {"version":3,"file":"CartLinePrice.mjs","sources":["../../src/CartLinePrice.tsx"],"sourcesContent":["import {Money, type MoneyPropsBase} from './Money.js';\nimport {CartLine} from './storefront-api-types.js';\nimport {PartialDeep} from 'type-fest';\n\ninterface CartLinePricePropsBase {\n /** A [CartLine object](https://shopify.dev/api/storefront/reference/objects/CartLine). */\n data: PartialDeep<CartLine, {recurseIntoArrays: true}>;\n /** The type of price. Valid values:`regular` (default) or `compareAt`. */\n priceType?: 'regular' | 'compareAt';\n}\n\ntype CartLinePriceProps = Omit<React.ComponentProps<typeof Money>, 'data'> &\n CartLinePricePropsBase;\n\n/**\n * The `CartLinePrice` component renders a `Money` component for the cart line merchandise's price or compare at price.\n */\nexport function CartLinePrice(props: CartLinePriceProps) {\n const {data: cartLine, priceType = 'regular', ...passthroughProps} = props;\n\n if (cartLine == null) {\n throw new Error(`<CartLinePrice/> requires a cart line as the 'data' prop`);\n }\n\n const moneyV2 =\n priceType === 'regular'\n ? cartLine.cost?.totalAmount\n : cartLine.cost?.compareAtAmountPerQuantity;\n\n if (moneyV2 == null) {\n return null;\n }\n\n return <Money {...passthroughProps} data={moneyV2} />;\n}\n\n// This is only for documenation purposes, and it is not used in the code.\nexport interface CartLinePricePropsForDocs<\n AsType extends React.ElementType = 'div'\n> extends Omit<MoneyPropsBase<AsType>, 'data'>,\n CartLinePricePropsBase {}\n"],"names":[],"mappings":";;AAiBO,SAAS,cAAc,OAA2B;;AACvD,QAAM,EAAC,MAAM,UAAU,YAAY,WAAW,GAAG,iBAAoB,IAAA;AAErE,MAAI,YAAY,MAAM;AACd,UAAA,IAAI,MAAM,0DAA0D;AAAA,EAC5E;AAEA,QAAM,UACJ,cAAc,aACV,cAAS,SAAT,mBAAe,eACf,cAAS,SAAT,mBAAe;AAErB,MAAI,WAAW,MAAM;AACZ,WAAA;AAAA,EACT;AAEA,SAAQ,oBAAA,OAAA,EAAO,GAAG,kBAAkB,MAAM,QAAS,CAAA;AACrD;"}
1
+ {"version":3,"file":"CartLinePrice.mjs","sources":["../../src/CartLinePrice.tsx"],"sourcesContent":["import {Money, type MoneyPropsBase} from './Money.js';\nimport {CartLine} from './storefront-api-types.js';\nimport {PartialDeep} from 'type-fest';\n\ninterface CartLinePricePropsBase {\n /** A [CartLine object](https://shopify.dev/api/storefront/reference/objects/CartLine). */\n data: PartialDeep<CartLine, {recurseIntoArrays: true}>;\n /** The type of price. Valid values:`regular` (default) or `compareAt`. */\n priceType?: 'regular' | 'compareAt';\n}\n\ntype CartLinePriceProps = Omit<React.ComponentProps<typeof Money>, 'data'> &\n CartLinePricePropsBase;\n\n/**\n * @deprecated Use `Money` instead. To migrate, use the `priceType` prop that matches the corresponding property on the `CartLine` object:\n * - `regular`: `cartLine.cost.totalAmount`\n * - `compareAt`: `cartLine.cost.compareAtAmountPerQuantity`\n *\n * For example:\n * ```\n * // before\n * <CartLinePrice data={cartLine} priceType=\"regular\" />\n * // after\n * <Money data={cartLine.cost.totalAmount} />\n * ```\n *\n * The `CartLinePrice` component renders a `Money` component for the cart line merchandise's price or compare at price.\n */\nexport function CartLinePrice(props: CartLinePriceProps): JSX.Element | null {\n if (__HYDROGEN_DEV__) {\n console.warn(`<CartLinePrice/> is deprecated; use <Money/> instead.`);\n }\n\n const {data: cartLine, priceType = 'regular', ...passthroughProps} = props;\n\n if (cartLine == null) {\n throw new Error(`<CartLinePrice/> requires a cart line as the 'data' prop`);\n }\n\n const moneyV2 =\n priceType === 'regular'\n ? cartLine.cost?.totalAmount\n : cartLine.cost?.compareAtAmountPerQuantity;\n\n if (moneyV2 == null) {\n return null;\n }\n\n return <Money {...passthroughProps} data={moneyV2} />;\n}\n\n// This is only for documenation purposes, and it is not used in the code.\nexport interface CartLinePricePropsForDocs<\n AsType extends React.ElementType = 'div'\n> extends Omit<MoneyPropsBase<AsType>, 'data'>,\n CartLinePricePropsBase {}\n"],"names":[],"mappings":";;AA6BO,SAAS,cAAc,OAA+C;;AACrD;AACpB,YAAQ,KAAK,uDAAuD;AAAA,EACtE;AAEA,QAAM,EAAC,MAAM,UAAU,YAAY,WAAW,GAAG,iBAAoB,IAAA;AAErE,MAAI,YAAY,MAAM;AACd,UAAA,IAAI,MAAM,0DAA0D;AAAA,EAC5E;AAEA,QAAM,UACJ,cAAc,aACV,cAAS,SAAT,mBAAe,eACf,cAAS,SAAT,mBAAe;AAErB,MAAI,WAAW,MAAM;AACZ,WAAA;AAAA,EACT;AAEA,SAAQ,oBAAA,OAAA,EAAO,GAAG,kBAAkB,MAAM,QAAS,CAAA;AACrD;"}
@@ -8,7 +8,10 @@ function useCartLine() {
8
8
  }
9
9
  return context;
10
10
  }
11
- function CartLineProvider({ children, line }) {
11
+ function CartLineProvider({
12
+ children,
13
+ line
14
+ }) {
12
15
  return /* @__PURE__ */ jsx(CartLineContext.Provider, { value: line, children });
13
16
  }
14
17
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"CartLineProvider.mjs","sources":["../../src/CartLineProvider.tsx"],"sourcesContent":["import {useContext, createContext, type ReactNode} from 'react';\nimport type {CartLine} from './storefront-api-types.js';\n\nexport const CartLineContext = createContext<CartLine | null>(null);\n\n/**\n * The `useCartLine` hook provides access to the [CartLine object](https://shopify.dev/api/storefront/unstable/objects/cartline) from the Storefront API. It must be a descendent of a `CartProvider` component.\n */\nexport function useCartLine(): CartLine {\n const context = useContext(CartLineContext);\n\n if (context == null) {\n throw new Error('Expected a cart line context but none was found');\n }\n\n return context;\n}\n\ntype CartLineProviderProps = {\n /** Any `ReactNode` elements. */\n children: ReactNode;\n /** A cart line object. */\n line: CartLine;\n};\n\n/**\n * The `CartLineProvider` component creates a context for using a cart line.\n */\nexport function CartLineProvider({children, line}: CartLineProviderProps) {\n return (\n <CartLineContext.Provider value={line}>{children}</CartLineContext.Provider>\n );\n}\n"],"names":[],"mappings":";;AAGa,MAAA,kBAAkB,cAA+B,IAAI;AAK3D,SAAS,cAAwB;AAChC,QAAA,UAAU,WAAW,eAAe;AAE1C,MAAI,WAAW,MAAM;AACb,UAAA,IAAI,MAAM,iDAAiD;AAAA,EACnE;AAEO,SAAA;AACT;AAYO,SAAS,iBAAiB,EAAC,UAAU,QAA8B;AACxE,6BACG,gBAAgB,UAAhB,EAAyB,OAAO,MAAO,SAAS,CAAA;AAErD;"}
1
+ {"version":3,"file":"CartLineProvider.mjs","sources":["../../src/CartLineProvider.tsx"],"sourcesContent":["import {useContext, createContext, type ReactNode} from 'react';\nimport type {CartLine} from './storefront-api-types.js';\n\nexport const CartLineContext = createContext<CartLine | null>(null);\n\n/**\n * The `useCartLine` hook provides access to the [CartLine object](https://shopify.dev/api/storefront/unstable/objects/cartline) from the Storefront API. It must be a descendent of a `CartProvider` component.\n */\nexport function useCartLine(): CartLine {\n const context = useContext(CartLineContext);\n\n if (context == null) {\n throw new Error('Expected a cart line context but none was found');\n }\n\n return context;\n}\n\ntype CartLineProviderProps = {\n /** Any `ReactNode` elements. */\n children: ReactNode;\n /** A cart line object. */\n line: CartLine;\n};\n\n/**\n * The `CartLineProvider` component creates a context for using a cart line.\n */\nexport function CartLineProvider({\n children,\n line,\n}: CartLineProviderProps): JSX.Element {\n return (\n <CartLineContext.Provider value={line}>{children}</CartLineContext.Provider>\n );\n}\n"],"names":[],"mappings":";;AAGa,MAAA,kBAAkB,cAA+B,IAAI;AAK3D,SAAS,cAAwB;AAChC,QAAA,UAAU,WAAW,eAAe;AAE1C,MAAI,WAAW,MAAM;AACb,UAAA,IAAI,MAAM,iDAAiD;AAAA,EACnE;AAEO,SAAA;AACT;AAYO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AACF,GAAuC;AACrC,6BACG,gBAAgB,UAAhB,EAAyB,OAAO,MAAO,SAAS,CAAA;AAErD;"}
@@ -365,18 +365,18 @@ function storageAvailable(type) {
365
365
  storage.removeItem(x);
366
366
  return true;
367
367
  } catch (e) {
368
- return e instanceof DOMException && // everything except Firefox
368
+ return !!(e instanceof DOMException && // everything except Firefox
369
369
  (e.code === 22 || // Firefox
370
370
  e.code === 1014 || // test name field too, because code might not be present
371
371
  // everything except Firefox
372
372
  e.name === "QuotaExceededError" || // Firefox
373
373
  e.name === "NS_ERROR_DOM_QUOTA_REACHED") && // acknowledge QuotaExceededError only if there's something already stored
374
- storage && storage.length !== 0;
374
+ storage && storage.length !== 0);
375
375
  }
376
376
  }
377
377
  function countryCodeNotUpdated(context, event) {
378
378
  var _a, _b;
379
- return event.payload.buyerIdentity.countryCode && ((_b = (_a = context.cart) == null ? void 0 : _a.buyerIdentity) == null ? void 0 : _b.countryCode) !== event.payload.buyerIdentity.countryCode;
379
+ return !!(event.payload.buyerIdentity.countryCode && ((_b = (_a = context.cart) == null ? void 0 : _a.buyerIdentity) == null ? void 0 : _b.countryCode) !== event.payload.buyerIdentity.countryCode);
380
380
  }
381
381
  export {
382
382
  CartContext,
@@ -1 +1 @@
1
- {"version":3,"file":"CartProvider.mjs","sources":["../../src/CartProvider.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n useTransition,\n createContext,\n useContext,\n} from 'react';\nimport {\n AttributeInput,\n CartBuyerIdentityInput,\n CartInput,\n CartLineInput,\n CartLineUpdateInput,\n CountryCode,\n Cart as CartType,\n MutationCartNoteUpdateArgs,\n} from './storefront-api-types.js';\nimport {\n BuyerIdentityUpdateEvent,\n CartMachineContext,\n CartMachineEvent,\n CartMachineTypeState,\n CartWithActions,\n} from './cart-types.js';\nimport {useCartAPIStateMachine} from './useCartAPIStateMachine.js';\nimport {CART_ID_STORAGE_KEY} from './cart-constants.js';\nimport {PartialDeep} from 'type-fest';\nimport {defaultCartFragment} from './cart-queries.js';\n\nexport const CartContext = createContext<CartWithActions | null>(null);\n\n/**\n * The `useCart` hook provides access to the cart object. It must be a descendent of a `CartProvider` component.\n */\nexport function useCart(): CartWithActions {\n const context = useContext(CartContext);\n\n if (!context) {\n throw new Error('Expected a Cart Context, but no Cart Context was found');\n }\n\n return context;\n}\n\ntype CartProviderProps = {\n /** Any `ReactNode` elements. */\n children: React.ReactNode;\n /** Maximum number of cart lines to fetch. Defaults to 250 cart lines. */\n numCartLines?: number;\n /** A callback that is invoked when the process to create a cart begins, but before the cart is created in the Storefront API. */\n onCreate?: () => void;\n /** A callback that is invoked when the process to add a line item to the cart begins, but before the line item is added to the Storefront API. */\n onLineAdd?: () => void;\n /** A callback that is invoked when the process to remove a line item to the cart begins, but before the line item is removed from the Storefront API. */\n onLineRemove?: () => void;\n /** A callback that is invoked when the process to update a line item in the cart begins, but before the line item is updated in the Storefront API. */\n onLineUpdate?: () => void;\n /** A callback that is invoked when the process to add or update a note in the cart begins, but before the note is added or updated in the Storefront API. */\n onNoteUpdate?: () => void;\n /** A callback that is invoked when the process to update the buyer identity begins, but before the buyer identity is updated in the Storefront API. */\n onBuyerIdentityUpdate?: () => void;\n /** A callback that is invoked when the process to update the cart attributes begins, but before the attributes are updated in the Storefront API. */\n onAttributesUpdate?: () => void;\n /** A callback that is invoked when the process to update the cart discount codes begins, but before the discount codes are updated in the Storefront API. */\n onDiscountCodesUpdate?: () => void;\n /** A callback that is invoked when the process to create a cart completes */\n onCreateComplete?: () => void;\n /** A callback that is invoked when the process to add a line item to the cart completes */\n onLineAddComplete?: () => void;\n /** A callback that is invoked when the process to remove a line item to the cart completes */\n onLineRemoveComplete?: () => void;\n /** A callback that is invoked when the process to update a line item in the cart completes */\n onLineUpdateComplete?: () => void;\n /** A callback that is invoked when the process to add or update a note in the cart completes */\n onNoteUpdateComplete?: () => void;\n /** A callback that is invoked when the process to update the buyer identity completes */\n onBuyerIdentityUpdateComplete?: () => void;\n /** A callback that is invoked when the process to update the cart attributes completes */\n onAttributesUpdateComplete?: () => void;\n /** A callback that is invoked when the process to update the cart discount codes completes */\n onDiscountCodesUpdateComplete?: () => void;\n /** An object with fields that correspond to the Storefront API's [Cart object](https://shopify.dev/api/storefront/latest/objects/cart). */\n data?: PartialDeep<CartType, {recurseIntoArrays: true}>;\n /** A fragment used to query the Storefront API's [Cart object](https://shopify.dev/api/storefront/latest/objects/cart) for all queries and mutations. A default value is used if no argument is provided. */\n cartFragment?: string;\n /** A customer access token that's accessible on the server if there's a customer login. */\n customerAccessToken?: CartBuyerIdentityInput['customerAccessToken'];\n /** The ISO country code for i18n. */\n countryCode?: CountryCode;\n};\n\n/**\n * The `CartProvider` component synchronizes the state of the Storefront API Cart and a customer's cart,\n * and allows you to more easily manipulate the cart by adding, removing, and updating it.\n * It could be placed at the root of your app so that your whole app is able to use the `useCart()` hook anywhere.\n *\n * There are props that trigger when a call to the Storefront API is made, such as `onLineAdd={}` when a line is added to the cart.\n * There are also props that trigger when a call to the Storefront API is completed, such as `onLineAddComplete={}` when the fetch request for adding a line to the cart completes.\n */\nexport function CartProvider({\n children,\n numCartLines,\n onCreate,\n onLineAdd,\n onLineRemove,\n onLineUpdate,\n onNoteUpdate,\n onBuyerIdentityUpdate,\n onAttributesUpdate,\n onDiscountCodesUpdate,\n onCreateComplete,\n onLineAddComplete,\n onLineRemoveComplete,\n onLineUpdateComplete,\n onNoteUpdateComplete,\n onBuyerIdentityUpdateComplete,\n onAttributesUpdateComplete,\n onDiscountCodesUpdateComplete,\n data: cart,\n cartFragment = defaultCartFragment,\n customerAccessToken,\n countryCode = 'US',\n}: CartProviderProps) {\n if (countryCode) countryCode = countryCode.toUpperCase() as CountryCode;\n const [prevCountryCode, setPrevCountryCode] = useState(countryCode);\n const [prevCustomerAccessToken, setPrevCustomerAccessToken] =\n useState(customerAccessToken);\n const customerOverridesCountryCode = useRef(false);\n\n if (\n prevCountryCode !== countryCode ||\n prevCustomerAccessToken !== customerAccessToken\n ) {\n setPrevCountryCode(countryCode);\n setPrevCustomerAccessToken(customerAccessToken);\n customerOverridesCountryCode.current = false;\n }\n\n const [cartState, cartSend] = useCartAPIStateMachine({\n numCartLines,\n data: cart,\n cartFragment,\n countryCode,\n onCartActionEntry(_, event) {\n try {\n switch (event.type) {\n case 'CART_CREATE':\n return onCreate?.();\n case 'CARTLINE_ADD':\n return onLineAdd?.();\n case 'CARTLINE_REMOVE':\n return onLineRemove?.();\n case 'CARTLINE_UPDATE':\n return onLineUpdate?.();\n case 'NOTE_UPDATE':\n return onNoteUpdate?.();\n case 'BUYER_IDENTITY_UPDATE':\n return onBuyerIdentityUpdate?.();\n case 'CART_ATTRIBUTES_UPDATE':\n return onAttributesUpdate?.();\n case 'DISCOUNT_CODES_UPDATE':\n return onDiscountCodesUpdate?.();\n }\n } catch (error) {\n console.error('Cart entry action failed', error);\n }\n },\n onCartActionOptimisticUI(context, event) {\n if (!context.cart) return {...context};\n switch (event.type) {\n case 'CARTLINE_REMOVE':\n return {\n ...context,\n cart: {\n ...context.cart,\n lines: context?.cart?.lines?.filter(\n (line) => line?.id && !event.payload.lines.includes(line?.id)\n ),\n },\n };\n case 'CARTLINE_UPDATE':\n return {\n ...context,\n cart: {\n ...context.cart,\n lines: context?.cart?.lines?.map((line) => {\n const updatedLine = event.payload.lines.find(\n ({id}) => id === line?.id\n );\n\n if (updatedLine && updatedLine.quantity) {\n return {\n ...line,\n quantity: updatedLine.quantity,\n };\n }\n\n return line;\n }),\n },\n };\n }\n return {...context};\n },\n onCartActionComplete(context, event) {\n const cartActionEvent = event.payload.cartActionEvent;\n try {\n switch (event.type) {\n case 'RESOLVE':\n switch (cartActionEvent.type) {\n case 'CART_CREATE':\n return onCreateComplete?.();\n case 'CARTLINE_ADD':\n return onLineAddComplete?.();\n case 'CARTLINE_REMOVE':\n return onLineRemoveComplete?.();\n case 'CARTLINE_UPDATE':\n return onLineUpdateComplete?.();\n case 'NOTE_UPDATE':\n return onNoteUpdateComplete?.();\n case 'BUYER_IDENTITY_UPDATE':\n if (countryCodeNotUpdated(context, cartActionEvent)) {\n customerOverridesCountryCode.current = true;\n }\n return onBuyerIdentityUpdateComplete?.();\n case 'CART_ATTRIBUTES_UPDATE':\n return onAttributesUpdateComplete?.();\n case 'DISCOUNT_CODES_UPDATE':\n return onDiscountCodesUpdateComplete?.();\n }\n }\n } catch (error) {\n console.error('onCartActionComplete failed', error);\n }\n },\n });\n\n const cartReady = useRef(false);\n const cartCompleted = cartState.matches('cartCompleted');\n\n const countryChanged =\n (cartState.value === 'idle' ||\n cartState.value === 'error' ||\n cartState.value === 'cartCompleted') &&\n countryCode !== cartState?.context?.cart?.buyerIdentity?.countryCode &&\n !cartState.context.errors;\n\n const fetchingFromStorage = useRef(false);\n\n /**\n * Initializes cart with priority in this order:\n * 1. cart props\n * 2. localStorage cartId\n */\n useEffect(() => {\n if (!cartReady.current && !fetchingFromStorage.current) {\n if (!cart && storageAvailable('localStorage')) {\n fetchingFromStorage.current = true;\n try {\n const cartId = window.localStorage.getItem(CART_ID_STORAGE_KEY);\n if (cartId) {\n cartSend({type: 'CART_FETCH', payload: {cartId}});\n }\n } catch (error) {\n console.warn('error fetching cartId');\n console.warn(error);\n }\n }\n cartReady.current = true;\n }\n }, [cart, cartReady, cartSend]);\n\n // Update cart country code if cart and props countryCode's as different\n useEffect(() => {\n if (!countryChanged || customerOverridesCountryCode.current) return;\n cartSend({\n type: 'BUYER_IDENTITY_UPDATE',\n payload: {buyerIdentity: {countryCode, customerAccessToken}},\n });\n }, [\n countryCode,\n customerAccessToken,\n countryChanged,\n customerOverridesCountryCode,\n cartSend,\n ]);\n\n // send cart events when ready\n const onCartReadySend = useCallback(\n (cartEvent: CartMachineEvent) => {\n if (!cartReady.current) {\n return console.warn(\"Cart isn't ready yet\");\n }\n cartSend(cartEvent);\n },\n [cartSend]\n );\n\n // save cart id to local storage\n useEffect(() => {\n if (cartState?.context?.cart?.id && storageAvailable('localStorage')) {\n try {\n window.localStorage.setItem(\n CART_ID_STORAGE_KEY,\n cartState.context.cart?.id\n );\n } catch (error) {\n console.warn('Failed to save cartId to localStorage', error);\n }\n }\n }, [cartState?.context?.cart?.id]);\n\n // delete cart from local storage if cart fetched has been completed\n useEffect(() => {\n if (cartCompleted && storageAvailable('localStorage')) {\n try {\n window.localStorage.removeItem(CART_ID_STORAGE_KEY);\n } catch (error) {\n console.warn('Failed to delete cartId from localStorage', error);\n }\n }\n }, [cartCompleted]);\n\n const cartCreate = useCallback(\n (cartInput: CartInput) => {\n if (countryCode && !cartInput.buyerIdentity?.countryCode) {\n if (cartInput.buyerIdentity == null) {\n cartInput.buyerIdentity = {};\n }\n cartInput.buyerIdentity.countryCode = countryCode;\n }\n\n if (\n customerAccessToken &&\n !cartInput.buyerIdentity?.customerAccessToken\n ) {\n if (cartInput.buyerIdentity == null) {\n cartInput.buyerIdentity = {};\n }\n cartInput.buyerIdentity.customerAccessToken = customerAccessToken;\n }\n onCartReadySend({\n type: 'CART_CREATE',\n payload: cartInput,\n });\n },\n [countryCode, customerAccessToken, onCartReadySend]\n );\n\n // Delays the cart state in the context if the page is hydrating\n // preventing suspense boundary errors.\n const cartDisplayState = useDelayedStateUntilHydration(cartState);\n\n const cartContextValue = useMemo<CartWithActions>(() => {\n return {\n ...(cartDisplayState?.context?.cart ?? {lines: [], attributes: []}),\n status: transposeStatus(cartDisplayState.value),\n error: cartDisplayState?.context?.errors,\n totalQuantity: cartDisplayState?.context?.cart?.totalQuantity ?? 0,\n cartCreate,\n linesAdd(lines: CartLineInput[]) {\n if (cartDisplayState?.context?.cart?.id) {\n onCartReadySend({\n type: 'CARTLINE_ADD',\n payload: {lines},\n });\n } else {\n cartCreate({lines});\n }\n },\n linesRemove(lines: string[]) {\n onCartReadySend({\n type: 'CARTLINE_REMOVE',\n payload: {\n lines,\n },\n });\n },\n linesUpdate(lines: CartLineUpdateInput[]) {\n onCartReadySend({\n type: 'CARTLINE_UPDATE',\n payload: {\n lines,\n },\n });\n },\n noteUpdate(note: MutationCartNoteUpdateArgs['note']) {\n onCartReadySend({\n type: 'NOTE_UPDATE',\n payload: {\n note,\n },\n });\n },\n buyerIdentityUpdate(buyerIdentity: CartBuyerIdentityInput) {\n onCartReadySend({\n type: 'BUYER_IDENTITY_UPDATE',\n payload: {\n buyerIdentity,\n },\n });\n },\n cartAttributesUpdate(attributes: AttributeInput[]) {\n onCartReadySend({\n type: 'CART_ATTRIBUTES_UPDATE',\n payload: {\n attributes,\n },\n });\n },\n discountCodesUpdate(discountCodes: string[]) {\n onCartReadySend({\n type: 'DISCOUNT_CODES_UPDATE',\n payload: {\n discountCodes,\n },\n });\n },\n cartFragment,\n };\n }, [\n cartCreate,\n cartDisplayState?.context?.cart,\n cartDisplayState?.context?.errors,\n cartDisplayState.value,\n cartFragment,\n onCartReadySend,\n ]);\n\n return (\n <CartContext.Provider value={cartContextValue}>\n {children}\n </CartContext.Provider>\n );\n}\n\nfunction transposeStatus(\n status: CartMachineTypeState['value']\n): CartWithActions['status'] {\n switch (status) {\n case 'uninitialized':\n case 'initializationError':\n return 'uninitialized';\n case 'idle':\n case 'cartCompleted':\n case 'error':\n return 'idle';\n case 'cartFetching':\n return 'fetching';\n case 'cartCreating':\n return 'creating';\n case 'cartLineAdding':\n case 'cartLineRemoving':\n case 'cartLineUpdating':\n case 'noteUpdating':\n case 'buyerIdentityUpdating':\n case 'cartAttributesUpdating':\n case 'discountCodesUpdating':\n return 'updating';\n }\n}\n\n/**\n * Delays a state update until hydration finishes. Useful for preventing suspense boundaries errors when updating a context\n * @remarks this uses startTransition and waits for it to finish.\n */\nfunction useDelayedStateUntilHydration<T>(state: T) {\n const [isPending, startTransition] = useTransition();\n const [delayedState, setDelayedState] = useState(state);\n\n const firstTimePending = useRef(false);\n if (isPending) {\n firstTimePending.current = true;\n }\n\n const firstTimePendingFinished = useRef(false);\n if (!isPending && firstTimePending.current) {\n firstTimePendingFinished.current = true;\n }\n\n useEffect(() => {\n startTransition(() => {\n if (!firstTimePendingFinished.current) {\n setDelayedState(state);\n }\n });\n }, [state]);\n\n const displayState = firstTimePendingFinished.current ? state : delayedState;\n\n return displayState;\n}\n\n/** Check for storage availability funciton obtained from\n * https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API\n */\nexport function storageAvailable(type: 'localStorage' | 'sessionStorage') {\n let storage;\n try {\n storage = window[type];\n const x = '__storage_test__';\n storage.setItem(x, x);\n storage.removeItem(x);\n return true;\n } catch (e) {\n return (\n e instanceof DOMException &&\n // everything except Firefox\n (e.code === 22 ||\n // Firefox\n e.code === 1014 ||\n // test name field too, because code might not be present\n // everything except Firefox\n e.name === 'QuotaExceededError' ||\n // Firefox\n e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&\n // acknowledge QuotaExceededError only if there's something already stored\n storage &&\n storage.length !== 0\n );\n }\n}\n\nfunction countryCodeNotUpdated(\n context: CartMachineContext,\n event: BuyerIdentityUpdateEvent\n) {\n return (\n event.payload.buyerIdentity.countryCode &&\n context.cart?.buyerIdentity?.countryCode !==\n event.payload.buyerIdentity.countryCode\n );\n}\n"],"names":["_b","_a","_d","_c"],"mappings":"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"}
1
+ {"version":3,"file":"CartProvider.mjs","sources":["../../src/CartProvider.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n useTransition,\n createContext,\n useContext,\n} from 'react';\nimport {\n AttributeInput,\n CartBuyerIdentityInput,\n CartInput,\n CartLineInput,\n CartLineUpdateInput,\n CountryCode,\n Cart as CartType,\n MutationCartNoteUpdateArgs,\n} from './storefront-api-types.js';\nimport {\n BuyerIdentityUpdateEvent,\n CartMachineContext,\n CartMachineEvent,\n CartMachineTypeState,\n CartWithActions,\n} from './cart-types.js';\nimport {useCartAPIStateMachine} from './useCartAPIStateMachine.js';\nimport {CART_ID_STORAGE_KEY} from './cart-constants.js';\nimport {PartialDeep} from 'type-fest';\nimport {defaultCartFragment} from './cart-queries.js';\n\nexport const CartContext = createContext<CartWithActions | null>(null);\n\n/**\n * The `useCart` hook provides access to the cart object. It must be a descendent of a `CartProvider` component.\n */\nexport function useCart(): CartWithActions {\n const context = useContext(CartContext);\n\n if (!context) {\n throw new Error('Expected a Cart Context, but no Cart Context was found');\n }\n\n return context;\n}\n\ntype CartProviderProps = {\n /** Any `ReactNode` elements. */\n children: React.ReactNode;\n /** Maximum number of cart lines to fetch. Defaults to 250 cart lines. */\n numCartLines?: number;\n /** A callback that is invoked when the process to create a cart begins, but before the cart is created in the Storefront API. */\n onCreate?: () => void;\n /** A callback that is invoked when the process to add a line item to the cart begins, but before the line item is added to the Storefront API. */\n onLineAdd?: () => void;\n /** A callback that is invoked when the process to remove a line item to the cart begins, but before the line item is removed from the Storefront API. */\n onLineRemove?: () => void;\n /** A callback that is invoked when the process to update a line item in the cart begins, but before the line item is updated in the Storefront API. */\n onLineUpdate?: () => void;\n /** A callback that is invoked when the process to add or update a note in the cart begins, but before the note is added or updated in the Storefront API. */\n onNoteUpdate?: () => void;\n /** A callback that is invoked when the process to update the buyer identity begins, but before the buyer identity is updated in the Storefront API. */\n onBuyerIdentityUpdate?: () => void;\n /** A callback that is invoked when the process to update the cart attributes begins, but before the attributes are updated in the Storefront API. */\n onAttributesUpdate?: () => void;\n /** A callback that is invoked when the process to update the cart discount codes begins, but before the discount codes are updated in the Storefront API. */\n onDiscountCodesUpdate?: () => void;\n /** A callback that is invoked when the process to create a cart completes */\n onCreateComplete?: () => void;\n /** A callback that is invoked when the process to add a line item to the cart completes */\n onLineAddComplete?: () => void;\n /** A callback that is invoked when the process to remove a line item to the cart completes */\n onLineRemoveComplete?: () => void;\n /** A callback that is invoked when the process to update a line item in the cart completes */\n onLineUpdateComplete?: () => void;\n /** A callback that is invoked when the process to add or update a note in the cart completes */\n onNoteUpdateComplete?: () => void;\n /** A callback that is invoked when the process to update the buyer identity completes */\n onBuyerIdentityUpdateComplete?: () => void;\n /** A callback that is invoked when the process to update the cart attributes completes */\n onAttributesUpdateComplete?: () => void;\n /** A callback that is invoked when the process to update the cart discount codes completes */\n onDiscountCodesUpdateComplete?: () => void;\n /** An object with fields that correspond to the Storefront API's [Cart object](https://shopify.dev/api/storefront/latest/objects/cart). */\n data?: PartialDeep<CartType, {recurseIntoArrays: true}>;\n /** A fragment used to query the Storefront API's [Cart object](https://shopify.dev/api/storefront/latest/objects/cart) for all queries and mutations. A default value is used if no argument is provided. */\n cartFragment?: string;\n /** A customer access token that's accessible on the server if there's a customer login. */\n customerAccessToken?: CartBuyerIdentityInput['customerAccessToken'];\n /** The ISO country code for i18n. */\n countryCode?: CountryCode;\n};\n\n/**\n * The `CartProvider` component synchronizes the state of the Storefront API Cart and a customer's cart,\n * and allows you to more easily manipulate the cart by adding, removing, and updating it.\n * It could be placed at the root of your app so that your whole app is able to use the `useCart()` hook anywhere.\n *\n * There are props that trigger when a call to the Storefront API is made, such as `onLineAdd={}` when a line is added to the cart.\n * There are also props that trigger when a call to the Storefront API is completed, such as `onLineAddComplete={}` when the fetch request for adding a line to the cart completes.\n */\nexport function CartProvider({\n children,\n numCartLines,\n onCreate,\n onLineAdd,\n onLineRemove,\n onLineUpdate,\n onNoteUpdate,\n onBuyerIdentityUpdate,\n onAttributesUpdate,\n onDiscountCodesUpdate,\n onCreateComplete,\n onLineAddComplete,\n onLineRemoveComplete,\n onLineUpdateComplete,\n onNoteUpdateComplete,\n onBuyerIdentityUpdateComplete,\n onAttributesUpdateComplete,\n onDiscountCodesUpdateComplete,\n data: cart,\n cartFragment = defaultCartFragment,\n customerAccessToken,\n countryCode = 'US',\n}: CartProviderProps): JSX.Element {\n if (countryCode) countryCode = countryCode.toUpperCase() as CountryCode;\n const [prevCountryCode, setPrevCountryCode] = useState(countryCode);\n const [prevCustomerAccessToken, setPrevCustomerAccessToken] =\n useState(customerAccessToken);\n const customerOverridesCountryCode = useRef(false);\n\n if (\n prevCountryCode !== countryCode ||\n prevCustomerAccessToken !== customerAccessToken\n ) {\n setPrevCountryCode(countryCode);\n setPrevCustomerAccessToken(customerAccessToken);\n customerOverridesCountryCode.current = false;\n }\n\n const [cartState, cartSend] = useCartAPIStateMachine({\n numCartLines,\n data: cart,\n cartFragment,\n countryCode,\n onCartActionEntry(_, event) {\n try {\n switch (event.type) {\n case 'CART_CREATE':\n return onCreate?.();\n case 'CARTLINE_ADD':\n return onLineAdd?.();\n case 'CARTLINE_REMOVE':\n return onLineRemove?.();\n case 'CARTLINE_UPDATE':\n return onLineUpdate?.();\n case 'NOTE_UPDATE':\n return onNoteUpdate?.();\n case 'BUYER_IDENTITY_UPDATE':\n return onBuyerIdentityUpdate?.();\n case 'CART_ATTRIBUTES_UPDATE':\n return onAttributesUpdate?.();\n case 'DISCOUNT_CODES_UPDATE':\n return onDiscountCodesUpdate?.();\n }\n } catch (error) {\n console.error('Cart entry action failed', error);\n }\n },\n onCartActionOptimisticUI(context, event) {\n if (!context.cart) return {...context};\n switch (event.type) {\n case 'CARTLINE_REMOVE':\n return {\n ...context,\n cart: {\n ...context.cart,\n lines: context?.cart?.lines?.filter(\n (line) => line?.id && !event.payload.lines.includes(line?.id)\n ),\n },\n };\n case 'CARTLINE_UPDATE':\n return {\n ...context,\n cart: {\n ...context.cart,\n lines: context?.cart?.lines?.map((line) => {\n const updatedLine = event.payload.lines.find(\n ({id}) => id === line?.id\n );\n\n if (updatedLine && updatedLine.quantity) {\n return {\n ...line,\n quantity: updatedLine.quantity,\n };\n }\n\n return line;\n }),\n },\n };\n }\n return {...context};\n },\n onCartActionComplete(context, event) {\n const cartActionEvent = event.payload.cartActionEvent;\n try {\n switch (event.type) {\n case 'RESOLVE':\n switch (cartActionEvent.type) {\n case 'CART_CREATE':\n return onCreateComplete?.();\n case 'CARTLINE_ADD':\n return onLineAddComplete?.();\n case 'CARTLINE_REMOVE':\n return onLineRemoveComplete?.();\n case 'CARTLINE_UPDATE':\n return onLineUpdateComplete?.();\n case 'NOTE_UPDATE':\n return onNoteUpdateComplete?.();\n case 'BUYER_IDENTITY_UPDATE':\n if (countryCodeNotUpdated(context, cartActionEvent)) {\n customerOverridesCountryCode.current = true;\n }\n return onBuyerIdentityUpdateComplete?.();\n case 'CART_ATTRIBUTES_UPDATE':\n return onAttributesUpdateComplete?.();\n case 'DISCOUNT_CODES_UPDATE':\n return onDiscountCodesUpdateComplete?.();\n }\n }\n } catch (error) {\n console.error('onCartActionComplete failed', error);\n }\n },\n });\n\n const cartReady = useRef(false);\n const cartCompleted = cartState.matches('cartCompleted');\n\n const countryChanged =\n (cartState.value === 'idle' ||\n cartState.value === 'error' ||\n cartState.value === 'cartCompleted') &&\n countryCode !== cartState?.context?.cart?.buyerIdentity?.countryCode &&\n !cartState.context.errors;\n\n const fetchingFromStorage = useRef(false);\n\n /**\n * Initializes cart with priority in this order:\n * 1. cart props\n * 2. localStorage cartId\n */\n useEffect(() => {\n if (!cartReady.current && !fetchingFromStorage.current) {\n if (!cart && storageAvailable('localStorage')) {\n fetchingFromStorage.current = true;\n try {\n const cartId = window.localStorage.getItem(CART_ID_STORAGE_KEY);\n if (cartId) {\n cartSend({type: 'CART_FETCH', payload: {cartId}});\n }\n } catch (error) {\n console.warn('error fetching cartId');\n console.warn(error);\n }\n }\n cartReady.current = true;\n }\n }, [cart, cartReady, cartSend]);\n\n // Update cart country code if cart and props countryCode's as different\n useEffect(() => {\n if (!countryChanged || customerOverridesCountryCode.current) return;\n cartSend({\n type: 'BUYER_IDENTITY_UPDATE',\n payload: {buyerIdentity: {countryCode, customerAccessToken}},\n });\n }, [\n countryCode,\n customerAccessToken,\n countryChanged,\n customerOverridesCountryCode,\n cartSend,\n ]);\n\n // send cart events when ready\n const onCartReadySend = useCallback(\n (cartEvent: CartMachineEvent) => {\n if (!cartReady.current) {\n return console.warn(\"Cart isn't ready yet\");\n }\n cartSend(cartEvent);\n },\n [cartSend]\n );\n\n // save cart id to local storage\n useEffect(() => {\n if (cartState?.context?.cart?.id && storageAvailable('localStorage')) {\n try {\n window.localStorage.setItem(\n CART_ID_STORAGE_KEY,\n cartState.context.cart?.id\n );\n } catch (error) {\n console.warn('Failed to save cartId to localStorage', error);\n }\n }\n }, [cartState?.context?.cart?.id]);\n\n // delete cart from local storage if cart fetched has been completed\n useEffect(() => {\n if (cartCompleted && storageAvailable('localStorage')) {\n try {\n window.localStorage.removeItem(CART_ID_STORAGE_KEY);\n } catch (error) {\n console.warn('Failed to delete cartId from localStorage', error);\n }\n }\n }, [cartCompleted]);\n\n const cartCreate = useCallback(\n (cartInput: CartInput) => {\n if (countryCode && !cartInput.buyerIdentity?.countryCode) {\n if (cartInput.buyerIdentity == null) {\n cartInput.buyerIdentity = {};\n }\n cartInput.buyerIdentity.countryCode = countryCode;\n }\n\n if (\n customerAccessToken &&\n !cartInput.buyerIdentity?.customerAccessToken\n ) {\n if (cartInput.buyerIdentity == null) {\n cartInput.buyerIdentity = {};\n }\n cartInput.buyerIdentity.customerAccessToken = customerAccessToken;\n }\n onCartReadySend({\n type: 'CART_CREATE',\n payload: cartInput,\n });\n },\n [countryCode, customerAccessToken, onCartReadySend]\n );\n\n // Delays the cart state in the context if the page is hydrating\n // preventing suspense boundary errors.\n const cartDisplayState = useDelayedStateUntilHydration(cartState);\n\n const cartContextValue = useMemo<CartWithActions>(() => {\n return {\n ...(cartDisplayState?.context?.cart ?? {lines: [], attributes: []}),\n status: transposeStatus(cartDisplayState.value),\n error: cartDisplayState?.context?.errors,\n totalQuantity: cartDisplayState?.context?.cart?.totalQuantity ?? 0,\n cartCreate,\n linesAdd(lines: CartLineInput[]): void {\n if (cartDisplayState?.context?.cart?.id) {\n onCartReadySend({\n type: 'CARTLINE_ADD',\n payload: {lines},\n });\n } else {\n cartCreate({lines});\n }\n },\n linesRemove(lines: string[]): void {\n onCartReadySend({\n type: 'CARTLINE_REMOVE',\n payload: {\n lines,\n },\n });\n },\n linesUpdate(lines: CartLineUpdateInput[]): void {\n onCartReadySend({\n type: 'CARTLINE_UPDATE',\n payload: {\n lines,\n },\n });\n },\n noteUpdate(note: MutationCartNoteUpdateArgs['note']): void {\n onCartReadySend({\n type: 'NOTE_UPDATE',\n payload: {\n note,\n },\n });\n },\n buyerIdentityUpdate(buyerIdentity: CartBuyerIdentityInput): void {\n onCartReadySend({\n type: 'BUYER_IDENTITY_UPDATE',\n payload: {\n buyerIdentity,\n },\n });\n },\n cartAttributesUpdate(attributes: AttributeInput[]): void {\n onCartReadySend({\n type: 'CART_ATTRIBUTES_UPDATE',\n payload: {\n attributes,\n },\n });\n },\n discountCodesUpdate(discountCodes: string[]): void {\n onCartReadySend({\n type: 'DISCOUNT_CODES_UPDATE',\n payload: {\n discountCodes,\n },\n });\n },\n cartFragment,\n };\n }, [\n cartCreate,\n cartDisplayState?.context?.cart,\n cartDisplayState?.context?.errors,\n cartDisplayState.value,\n cartFragment,\n onCartReadySend,\n ]);\n\n return (\n <CartContext.Provider value={cartContextValue}>\n {children}\n </CartContext.Provider>\n );\n}\n\nfunction transposeStatus(\n status: CartMachineTypeState['value']\n): CartWithActions['status'] {\n switch (status) {\n case 'uninitialized':\n case 'initializationError':\n return 'uninitialized';\n case 'idle':\n case 'cartCompleted':\n case 'error':\n return 'idle';\n case 'cartFetching':\n return 'fetching';\n case 'cartCreating':\n return 'creating';\n case 'cartLineAdding':\n case 'cartLineRemoving':\n case 'cartLineUpdating':\n case 'noteUpdating':\n case 'buyerIdentityUpdating':\n case 'cartAttributesUpdating':\n case 'discountCodesUpdating':\n return 'updating';\n }\n}\n\n/**\n * Delays a state update until hydration finishes. Useful for preventing suspense boundaries errors when updating a context\n * @remarks this uses startTransition and waits for it to finish.\n */\nfunction useDelayedStateUntilHydration<T>(state: T): T {\n const [isPending, startTransition] = useTransition();\n const [delayedState, setDelayedState] = useState(state);\n\n const firstTimePending = useRef(false);\n if (isPending) {\n firstTimePending.current = true;\n }\n\n const firstTimePendingFinished = useRef(false);\n if (!isPending && firstTimePending.current) {\n firstTimePendingFinished.current = true;\n }\n\n useEffect(() => {\n startTransition(() => {\n if (!firstTimePendingFinished.current) {\n setDelayedState(state);\n }\n });\n }, [state]);\n\n const displayState = firstTimePendingFinished.current ? state : delayedState;\n\n return displayState;\n}\n\n/** Check for storage availability funciton obtained from\n * https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API\n */\nexport function storageAvailable(\n type: 'localStorage' | 'sessionStorage'\n): boolean {\n let storage;\n try {\n storage = window[type];\n const x = '__storage_test__';\n storage.setItem(x, x);\n storage.removeItem(x);\n return true;\n } catch (e) {\n return !!(\n e instanceof DOMException &&\n // everything except Firefox\n (e.code === 22 ||\n // Firefox\n e.code === 1014 ||\n // test name field too, because code might not be present\n // everything except Firefox\n e.name === 'QuotaExceededError' ||\n // Firefox\n e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&\n // acknowledge QuotaExceededError only if there's something already stored\n storage &&\n storage.length !== 0\n );\n }\n}\n\nfunction countryCodeNotUpdated(\n context: CartMachineContext,\n event: BuyerIdentityUpdateEvent\n): boolean {\n return !!(\n event.payload.buyerIdentity.countryCode &&\n context.cart?.buyerIdentity?.countryCode !==\n event.payload.buyerIdentity.countryCode\n );\n}\n"],"names":["_b","_a","_d","_c"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ExternalVideo.mjs","sources":["../../src/ExternalVideo.tsx"],"sourcesContent":["import type {ExternalVideo as ExternalVideoType} from './storefront-api-types.js';\nimport type {PartialDeep} from 'type-fest';\n\ninterface ExternalVideoBaseProps {\n /**\n * An object with fields that correspond to the Storefront API's [ExternalVideo object](https://shopify.dev/api/storefront/reference/products/externalvideo).\n */\n data: PartialDeep<ExternalVideoType, {recurseIntoArrays: true}>;\n /** An object containing the options available for either\n * [YouTube](https://developers.google.com/youtube/player_parameters#Parameters) or\n * [Vimeo](https://vimeo.zendesk.com/hc/en-us/articles/360001494447-Using-Player-Parameters).\n */\n options?: YouTube | Vimeo;\n}\n\nexport type ExternalVideoProps = Omit<JSX.IntrinsicElements['iframe'], 'src'> &\n ExternalVideoBaseProps;\n\n/**\n * The `ExternalVideo` component renders an embedded video for the Storefront\n * API's [ExternalVideo object](https://shopify.dev/api/storefront/reference/products/externalvideo).\n */\nexport function ExternalVideo(props: ExternalVideoProps) {\n const {\n data,\n options,\n id = data.id,\n frameBorder = '0',\n allow = 'accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture',\n allowFullScreen = true,\n loading = 'lazy',\n ...passthroughProps\n } = props;\n\n if (!data.embedUrl) {\n throw new Error(`<ExternalVideo/> requires the 'embedUrl' property`);\n }\n\n let finalUrl: string = data.embedUrl;\n\n if (options) {\n const urlObject = new URL(data.embedUrl);\n for (const key of Object.keys(options)) {\n // @ts-expect-error https://github.com/microsoft/TypeScript/issues/32951\n urlObject.searchParams.set(key, options[key]);\n }\n finalUrl = urlObject.toString();\n }\n\n return (\n <iframe\n {...passthroughProps}\n id={id ?? data.embedUrl}\n title={data.alt ?? data.id ?? 'external video'}\n frameBorder={frameBorder}\n allow={allow}\n allowFullScreen={allowFullScreen}\n src={finalUrl}\n loading={loading}\n ></iframe>\n );\n}\n\ninterface YouTube {\n autoplay?: 0 | 1;\n cc_lang_pref?: string;\n cc_load_policy?: 1;\n color?: 'red' | 'white';\n controls?: 0 | 1;\n disablekb?: 0 | 1;\n enablejsapi?: 0 | 1;\n end?: number;\n fs?: 0 | 1;\n hl?: string;\n iv_load_policy?: 1 | 3;\n list?: string;\n list_type?: 'playlist' | 'user_uploads';\n loop?: 0 | 1;\n modest_branding?: 1;\n origin?: string;\n playlist?: string;\n plays_inline?: 0 | 1;\n rel?: 0 | 1;\n start?: number;\n widget_referrer?: string;\n}\n\ntype VimeoBoolean = 0 | 1 | boolean;\n\ninterface Vimeo {\n autopause?: VimeoBoolean;\n autoplay?: VimeoBoolean;\n background?: VimeoBoolean;\n byline?: VimeoBoolean;\n color?: string;\n controls?: VimeoBoolean;\n dnt?: VimeoBoolean;\n loop?: VimeoBoolean;\n muted?: VimeoBoolean;\n pip?: VimeoBoolean;\n playsinline?: VimeoBoolean;\n portrait?: VimeoBoolean;\n quality?: '240p' | '360p' | '540p' | '720p' | '1080p' | '2k' | '4k';\n speed?: VimeoBoolean;\n '#t'?: string;\n texttrack?: string;\n title?: VimeoBoolean;\n transparent?: VimeoBoolean;\n}\n"],"names":[],"mappings":";AAsBO,SAAS,cAAc,OAA2B;AACjD,QAAA;AAAA,IACJ;AAAA,IACA;AAAA,IACA,KAAK,KAAK;AAAA,IACV,cAAc;AAAA,IACd,QAAQ;AAAA,IACR,kBAAkB;AAAA,IAClB,UAAU;AAAA,IACV,GAAG;AAAA,EACD,IAAA;AAEA,MAAA,CAAC,KAAK,UAAU;AACZ,UAAA,IAAI,MAAM,mDAAmD;AAAA,EACrE;AAEA,MAAI,WAAmB,KAAK;AAE5B,MAAI,SAAS;AACX,UAAM,YAAY,IAAI,IAAI,KAAK,QAAQ;AACvC,eAAW,OAAO,OAAO,KAAK,OAAO,GAAG;AAEtC,gBAAU,aAAa,IAAI,KAAK,QAAQ,GAAG,CAAC;AAAA,IAC9C;AACA,eAAW,UAAU;EACvB;AAGE,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACE,GAAG;AAAA,MACJ,IAAI,MAAM,KAAK;AAAA,MACf,OAAO,KAAK,OAAO,KAAK,MAAM;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IAAA;AAAA,EAAA;AAGN;"}
1
+ {"version":3,"file":"ExternalVideo.mjs","sources":["../../src/ExternalVideo.tsx"],"sourcesContent":["import type {ExternalVideo as ExternalVideoType} from './storefront-api-types.js';\nimport type {PartialDeep} from 'type-fest';\n\ninterface ExternalVideoBaseProps {\n /**\n * An object with fields that correspond to the Storefront API's [ExternalVideo object](https://shopify.dev/api/storefront/reference/products/externalvideo).\n */\n data: PartialDeep<ExternalVideoType, {recurseIntoArrays: true}>;\n /** An object containing the options available for either\n * [YouTube](https://developers.google.com/youtube/player_parameters#Parameters) or\n * [Vimeo](https://vimeo.zendesk.com/hc/en-us/articles/360001494447-Using-Player-Parameters).\n */\n options?: YouTube | Vimeo;\n}\n\nexport type ExternalVideoProps = Omit<JSX.IntrinsicElements['iframe'], 'src'> &\n ExternalVideoBaseProps;\n\n/**\n * The `ExternalVideo` component renders an embedded video for the Storefront\n * API's [ExternalVideo object](https://shopify.dev/api/storefront/reference/products/externalvideo).\n */\nexport function ExternalVideo(props: ExternalVideoProps): JSX.Element {\n const {\n data,\n options,\n id = data.id,\n frameBorder = '0',\n allow = 'accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture',\n allowFullScreen = true,\n loading = 'lazy',\n ...passthroughProps\n } = props;\n\n if (!data.embedUrl) {\n throw new Error(`<ExternalVideo/> requires the 'embedUrl' property`);\n }\n\n let finalUrl: string = data.embedUrl;\n\n if (options) {\n const urlObject = new URL(data.embedUrl);\n for (const key of Object.keys(options) as (keyof typeof options)[]) {\n // @ts-expect-error https://github.com/microsoft/TypeScript/issues/32951\n urlObject.searchParams.set(key, options[key]);\n }\n finalUrl = urlObject.toString();\n }\n\n return (\n <iframe\n {...passthroughProps}\n id={id ?? data.embedUrl}\n title={data.alt ?? data.id ?? 'external video'}\n frameBorder={frameBorder}\n allow={allow}\n allowFullScreen={allowFullScreen}\n src={finalUrl}\n loading={loading}\n ></iframe>\n );\n}\n\ninterface YouTube {\n autoplay?: 0 | 1;\n cc_lang_pref?: string;\n cc_load_policy?: 1;\n color?: 'red' | 'white';\n controls?: 0 | 1;\n disablekb?: 0 | 1;\n enablejsapi?: 0 | 1;\n end?: number;\n fs?: 0 | 1;\n hl?: string;\n iv_load_policy?: 1 | 3;\n list?: string;\n list_type?: 'playlist' | 'user_uploads';\n loop?: 0 | 1;\n modest_branding?: 1;\n origin?: string;\n playlist?: string;\n plays_inline?: 0 | 1;\n rel?: 0 | 1;\n start?: number;\n widget_referrer?: string;\n}\n\ntype VimeoBoolean = 0 | 1 | boolean;\n\ninterface Vimeo {\n autopause?: VimeoBoolean;\n autoplay?: VimeoBoolean;\n background?: VimeoBoolean;\n byline?: VimeoBoolean;\n color?: string;\n controls?: VimeoBoolean;\n dnt?: VimeoBoolean;\n loop?: VimeoBoolean;\n muted?: VimeoBoolean;\n pip?: VimeoBoolean;\n playsinline?: VimeoBoolean;\n portrait?: VimeoBoolean;\n quality?: '240p' | '360p' | '540p' | '720p' | '1080p' | '2k' | '4k';\n speed?: VimeoBoolean;\n '#t'?: string;\n texttrack?: string;\n title?: VimeoBoolean;\n transparent?: VimeoBoolean;\n}\n"],"names":[],"mappings":";AAsBO,SAAS,cAAc,OAAwC;AAC9D,QAAA;AAAA,IACJ;AAAA,IACA;AAAA,IACA,KAAK,KAAK;AAAA,IACV,cAAc;AAAA,IACd,QAAQ;AAAA,IACR,kBAAkB;AAAA,IAClB,UAAU;AAAA,IACV,GAAG;AAAA,EACD,IAAA;AAEA,MAAA,CAAC,KAAK,UAAU;AACZ,UAAA,IAAI,MAAM,mDAAmD;AAAA,EACrE;AAEA,MAAI,WAAmB,KAAK;AAE5B,MAAI,SAAS;AACX,UAAM,YAAY,IAAI,IAAI,KAAK,QAAQ;AACvC,eAAW,OAAO,OAAO,KAAK,OAAO,GAA+B;AAElE,gBAAU,aAAa,IAAI,KAAK,QAAQ,GAAG,CAAC;AAAA,IAC9C;AACA,eAAW,UAAU;EACvB;AAGE,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACE,GAAG;AAAA,MACJ,IAAI,MAAM,KAAK;AAAA,MACf,OAAO,KAAK,OAAO,KAAK,MAAM;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IAAA;AAAA,EAAA;AAGN;"}
@@ -106,7 +106,7 @@ function internalImageSrcSet({
106
106
  height: crop ? Number(size) * aspectRatio : void 0,
107
107
  crop,
108
108
  scale
109
- })} ${size}w`
109
+ })} ${size ?? ""}w`
110
110
  ).join(", ");
111
111
  }
112
112
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"Image.mjs","sources":["../../src/Image.tsx"],"sourcesContent":["import * as React from 'react';\nimport {\n getShopifyImageDimensions,\n shopifyImageLoader,\n addImageSizeParametersToUrl,\n IMG_SRC_SET_SIZES,\n} from './image-size.js';\nimport type {Image as ImageType} from './storefront-api-types.js';\nimport type {PartialDeep, Simplify} from 'type-fest';\n\ntype HtmlImageProps = React.ImgHTMLAttributes<HTMLImageElement>;\n\nexport type ShopifyLoaderOptions = {\n crop?: 'top' | 'bottom' | 'left' | 'right' | 'center';\n scale?: 2 | 3;\n width?: HtmlImageProps['width'] | ImageType['width'];\n height?: HtmlImageProps['height'] | ImageType['height'];\n};\nexport type ShopifyLoaderParams = Simplify<ShopifyLoaderOptions & ImageSrc>;\n\ntype ImageSrc = {\n src: ImageType['url'];\n};\n\nexport type ShopifyImageProps = Omit<HtmlImageProps, 'src'> &\n ShopifyImageBaseProps;\n\ntype ShopifyImageBaseProps = {\n /** An object with fields that correspond to the Storefront API's\n * [Image object](https://shopify.dev/api/storefront/reference/common-objects/image).\n * The `data` prop is required.\n */\n data: PartialDeep<ImageType, {recurseIntoArrays: true}>;\n /** A custom function that generates the image URL. Parameters passed in\n * are `ShopifyLoaderParams`\n */\n loader?: (params: ShopifyLoaderParams) => string;\n /** An object of `loader` function options. For example, if the `loader` function\n * requires a `scale` option, then the value can be a property of the\n * `loaderOptions` object (for example, `{scale: 2}`). The object shape is `ShopifyLoaderOptions`.\n */\n loaderOptions?: ShopifyLoaderOptions;\n /**\n * `src` isn't used, and should instead be passed as part of the `data` object\n */\n src?: never;\n /**\n * An array of pixel widths to overwrite the default generated srcset. For example, `[300, 600, 800]`.\n */\n widths?: (HtmlImageProps['width'] | ImageType['width'])[];\n};\n\n/**\n * The `Image` component renders an image for the Storefront API's\n * [Image object](https://shopify.dev/api/storefront/reference/common-objects/image) by using the `data` prop. You can [customize this component](https://shopify.dev/api/hydrogen/components#customizing-hydrogen-components) using passthrough props.\n *\n * An image's width and height are determined using the following priority list:\n * 1. The width and height values for the `loaderOptions` prop\n * 2. The width and height values for bare props\n * 3. The width and height values for the `data` prop\n *\n * If only one of `width` or `height` are defined, then the other will attempt to be calculated based on the image's aspect ratio,\n * provided that both `data.width` and `data.height` are available. If `data.width` and `data.height` aren't available, then the aspect ratio cannot be determined and the missing\n * value will remain as `null`\n */\nexport function Image({\n data,\n width,\n height,\n loading,\n loader = shopifyImageLoader,\n loaderOptions,\n widths,\n decoding = 'async',\n ...rest\n}: ShopifyImageProps) {\n if (!data.url) {\n const missingUrlError = `<Image/>: the 'data' prop requires the 'url' property. Image: ${\n data.id ?? 'no ID provided'\n }`;\n\n if (__HYDROGEN_DEV__) {\n throw new Error(missingUrlError);\n } else {\n console.error(missingUrlError);\n }\n\n return null;\n }\n\n if (__HYDROGEN_DEV__ && !data.altText && !rest.alt) {\n console.warn(\n `<Image/>: the 'data' prop should have the 'altText' property, or the 'alt' prop, and one of them should not be empty. Image: ${\n data.id ?? data.url\n }`\n );\n }\n\n const {width: imgElementWidth, height: imgElementHeight} =\n getShopifyImageDimensions({\n data,\n loaderOptions,\n elementProps: {\n width,\n height,\n },\n });\n\n if (__HYDROGEN_DEV__ && (!imgElementWidth || !imgElementHeight)) {\n console.warn(\n `<Image/>: the 'data' prop requires either 'width' or 'data.width', and 'height' or 'data.height' properties. Image: ${\n data.id ?? data.url\n }`\n );\n }\n\n let finalSrc = data.url;\n\n if (loader) {\n finalSrc = loader({\n ...loaderOptions,\n src: data.url,\n width: imgElementWidth,\n height: imgElementHeight,\n });\n if (typeof finalSrc !== 'string' || !finalSrc) {\n throw new Error(\n `<Image/>: 'loader' did not return a valid string. Image: ${\n data.id ?? data.url\n }`\n );\n }\n }\n\n // determining what the intended width of the image is. For example, if the width is specified and lower than the image width, then that is the maximum image width\n // to prevent generating a srcset with widths bigger than needed or to generate images that would distort because of being larger than original\n const maxWidth =\n width && imgElementWidth && width < imgElementWidth\n ? width\n : imgElementWidth;\n const finalSrcset =\n rest.srcSet ??\n internalImageSrcSet({\n ...loaderOptions,\n widths,\n src: data.url,\n width: maxWidth,\n height: imgElementHeight,\n loader,\n });\n\n /* eslint-disable hydrogen/prefer-image-component */\n return (\n <img\n id={data.id ?? ''}\n alt={data.altText ?? rest.alt ?? ''}\n loading={loading ?? 'lazy'}\n {...rest}\n src={finalSrc}\n width={imgElementWidth ?? undefined}\n height={imgElementHeight ?? undefined}\n srcSet={finalSrcset}\n decoding={decoding}\n />\n );\n /* eslint-enable hydrogen/prefer-image-component */\n}\n\ntype InternalShopifySrcSetGeneratorsParams = Simplify<\n ShopifyLoaderOptions & {\n src: ImageType['url'];\n widths?: (HtmlImageProps['width'] | ImageType['width'])[];\n loader?: (params: ShopifyLoaderParams) => string;\n }\n>;\nfunction internalImageSrcSet({\n src,\n width,\n crop,\n scale,\n widths,\n loader,\n height,\n}: InternalShopifySrcSetGeneratorsParams) {\n const hasCustomWidths = widths && Array.isArray(widths);\n if (hasCustomWidths && widths.some((size) => isNaN(size as number))) {\n throw new Error(\n `<Image/>: the 'widths' must be an array of numbers. Image: ${src}`\n );\n }\n\n let aspectRatio = 1;\n if (width && height) {\n aspectRatio = Number(height) / Number(width);\n }\n\n let setSizes = hasCustomWidths ? widths : IMG_SRC_SET_SIZES;\n if (\n !hasCustomWidths &&\n width &&\n width < IMG_SRC_SET_SIZES[IMG_SRC_SET_SIZES.length - 1]\n ) {\n setSizes = IMG_SRC_SET_SIZES.filter((size) => size <= width);\n }\n const srcGenerator = loader ? loader : addImageSizeParametersToUrl;\n return setSizes\n .map(\n (size) =>\n `${srcGenerator({\n src,\n width: size,\n // height is not applied if there is no crop\n // if there is crop, then height is applied as a ratio of the original width + height aspect ratio * size\n height: crop ? Number(size) * aspectRatio : undefined,\n crop,\n scale,\n })} ${size}w`\n )\n .join(', ');\n}\n"],"names":[],"mappings":";;AAiEO,SAAS,MAAM;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,GAAG;AACL,GAAsB;AAChB,MAAA,CAAC,KAAK,KAAK;AACP,UAAA,kBAAkB,iEACtB,KAAK,MAAM;AAGS;AACd,YAAA,IAAI,MAAM,eAAe;AAAA,IAGjC;AAAA,EAGF;AAEA,MAAwB,CAAC,KAAK,WAAW,CAAC,KAAK,KAAK;AAC1C,YAAA;AAAA,MACN,gIACE,KAAK,MAAM,KAAK;AAAA,IAAA;AAAA,EAGtB;AAEA,QAAM,EAAC,OAAO,iBAAiB,QAAQ,iBAAA,IACrC,0BAA0B;AAAA,IACxB;AAAA,IACA;AAAA,IACA,cAAc;AAAA,MACZ;AAAA,MACA;AAAA,IACF;AAAA,EAAA,CACD;AAEH,MAAyB,CAAC,mBAAmB,CAAC,kBAAmB;AACvD,YAAA;AAAA,MACN,uHACE,KAAK,MAAM,KAAK;AAAA,IAAA;AAAA,EAGtB;AAEA,MAAI,WAAW,KAAK;AAEpB,MAAI,QAAQ;AACV,eAAW,OAAO;AAAA,MAChB,GAAG;AAAA,MACH,KAAK,KAAK;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,IAAA,CACT;AACD,QAAI,OAAO,aAAa,YAAY,CAAC,UAAU;AAC7C,YAAM,IAAI;AAAA,QACR,4DACE,KAAK,MAAM,KAAK;AAAA,MAAA;AAAA,IAGtB;AAAA,EACF;AAIA,QAAM,WACJ,SAAS,mBAAmB,QAAQ,kBAChC,QACA;AACA,QAAA,cACJ,KAAK,UACL,oBAAoB;AAAA,IAClB,GAAG;AAAA,IACH;AAAA,IACA,KAAK,KAAK;AAAA,IACV,OAAO;AAAA,IACP,QAAQ;AAAA,IACR;AAAA,EAAA,CACD;AAID,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,IAAI,KAAK,MAAM;AAAA,MACf,KAAK,KAAK,WAAW,KAAK,OAAO;AAAA,MACjC,SAAS,WAAW;AAAA,MACnB,GAAG;AAAA,MACJ,KAAK;AAAA,MACL,OAAO,mBAAmB;AAAA,MAC1B,QAAQ,oBAAoB;AAAA,MAC5B,QAAQ;AAAA,MACR;AAAA,IAAA;AAAA,EAAA;AAIN;AASA,SAAS,oBAAoB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0C;AACxC,QAAM,kBAAkB,UAAU,MAAM,QAAQ,MAAM;AAClD,MAAA,mBAAmB,OAAO,KAAK,CAAC,SAAS,MAAM,IAAc,CAAC,GAAG;AACnE,UAAM,IAAI;AAAA,MACR,8DAA8D;AAAA,IAAA;AAAA,EAElE;AAEA,MAAI,cAAc;AAClB,MAAI,SAAS,QAAQ;AACnB,kBAAc,OAAO,MAAM,IAAI,OAAO,KAAK;AAAA,EAC7C;AAEI,MAAA,WAAW,kBAAkB,SAAS;AAExC,MAAA,CAAC,mBACD,SACA,QAAQ,kBAAkB,kBAAkB,SAAS,CAAC,GACtD;AACA,eAAW,kBAAkB,OAAO,CAAC,SAAS,QAAQ,KAAK;AAAA,EAC7D;AACM,QAAA,eAAe,SAAS,SAAS;AACvC,SAAO,SACJ;AAAA,IACC,CAAC,SACC,GAAG,aAAa;AAAA,MACd;AAAA,MACA,OAAO;AAAA;AAAA;AAAA,MAGP,QAAQ,OAAO,OAAO,IAAI,IAAI,cAAc;AAAA,MAC5C;AAAA,MACA;AAAA,IAAA,CACD,KAAK;AAAA,EAAA,EAET,KAAK,IAAI;AACd;"}
1
+ {"version":3,"file":"Image.mjs","sources":["../../src/Image.tsx"],"sourcesContent":["import * as React from 'react';\nimport {\n getShopifyImageDimensions,\n shopifyImageLoader,\n addImageSizeParametersToUrl,\n IMG_SRC_SET_SIZES,\n} from './image-size.js';\nimport type {Image as ImageType} from './storefront-api-types.js';\nimport type {PartialDeep, Simplify} from 'type-fest';\n\ntype HtmlImageProps = React.ImgHTMLAttributes<HTMLImageElement>;\n\nexport type ShopifyLoaderOptions = {\n crop?: 'top' | 'bottom' | 'left' | 'right' | 'center';\n scale?: 2 | 3;\n width?: HtmlImageProps['width'] | ImageType['width'];\n height?: HtmlImageProps['height'] | ImageType['height'];\n};\nexport type ShopifyLoaderParams = Simplify<ShopifyLoaderOptions & ImageSrc>;\n\ntype ImageSrc = {\n src: ImageType['url'];\n};\n\nexport type ShopifyImageProps = Omit<HtmlImageProps, 'src'> &\n ShopifyImageBaseProps;\n\ntype ShopifyImageBaseProps = {\n /** An object with fields that correspond to the Storefront API's\n * [Image object](https://shopify.dev/api/storefront/reference/common-objects/image).\n * The `data` prop is required.\n */\n data: PartialDeep<ImageType, {recurseIntoArrays: true}>;\n /** A custom function that generates the image URL. Parameters passed in\n * are `ShopifyLoaderParams`\n */\n loader?: (params: ShopifyLoaderParams) => string;\n /** An object of `loader` function options. For example, if the `loader` function\n * requires a `scale` option, then the value can be a property of the\n * `loaderOptions` object (for example, `{scale: 2}`). The object shape is `ShopifyLoaderOptions`.\n */\n loaderOptions?: ShopifyLoaderOptions;\n /**\n * `src` isn't used, and should instead be passed as part of the `data` object\n */\n src?: never;\n /**\n * An array of pixel widths to overwrite the default generated srcset. For example, `[300, 600, 800]`.\n */\n widths?: (HtmlImageProps['width'] | ImageType['width'])[];\n};\n\n/**\n * The `Image` component renders an image for the Storefront API's\n * [Image object](https://shopify.dev/api/storefront/reference/common-objects/image) by using the `data` prop. You can [customize this component](https://shopify.dev/api/hydrogen/components#customizing-hydrogen-components) using passthrough props.\n *\n * An image's width and height are determined using the following priority list:\n * 1. The width and height values for the `loaderOptions` prop\n * 2. The width and height values for bare props\n * 3. The width and height values for the `data` prop\n *\n * If only one of `width` or `height` are defined, then the other will attempt to be calculated based on the image's aspect ratio,\n * provided that both `data.width` and `data.height` are available. If `data.width` and `data.height` aren't available, then the aspect ratio cannot be determined and the missing\n * value will remain as `null`\n */\nexport function Image({\n data,\n width,\n height,\n loading,\n loader = shopifyImageLoader,\n loaderOptions,\n widths,\n decoding = 'async',\n ...rest\n}: ShopifyImageProps): JSX.Element | null {\n if (!data.url) {\n const missingUrlError = `<Image/>: the 'data' prop requires the 'url' property. Image: ${\n data.id ?? 'no ID provided'\n }`;\n\n if (__HYDROGEN_DEV__) {\n throw new Error(missingUrlError);\n } else {\n console.error(missingUrlError);\n }\n\n return null;\n }\n\n if (__HYDROGEN_DEV__ && !data.altText && !rest.alt) {\n console.warn(\n `<Image/>: the 'data' prop should have the 'altText' property, or the 'alt' prop, and one of them should not be empty. Image: ${\n data.id ?? data.url\n }`\n );\n }\n\n const {width: imgElementWidth, height: imgElementHeight} =\n getShopifyImageDimensions({\n data,\n loaderOptions,\n elementProps: {\n width,\n height,\n },\n });\n\n if (__HYDROGEN_DEV__ && (!imgElementWidth || !imgElementHeight)) {\n console.warn(\n `<Image/>: the 'data' prop requires either 'width' or 'data.width', and 'height' or 'data.height' properties. Image: ${\n data.id ?? data.url\n }`\n );\n }\n\n let finalSrc = data.url;\n\n if (loader) {\n finalSrc = loader({\n ...loaderOptions,\n src: data.url,\n width: imgElementWidth,\n height: imgElementHeight,\n });\n if (typeof finalSrc !== 'string' || !finalSrc) {\n throw new Error(\n `<Image/>: 'loader' did not return a valid string. Image: ${\n data.id ?? data.url\n }`\n );\n }\n }\n\n // determining what the intended width of the image is. For example, if the width is specified and lower than the image width, then that is the maximum image width\n // to prevent generating a srcset with widths bigger than needed or to generate images that would distort because of being larger than original\n const maxWidth =\n width && imgElementWidth && width < imgElementWidth\n ? width\n : imgElementWidth;\n const finalSrcset =\n rest.srcSet ??\n internalImageSrcSet({\n ...loaderOptions,\n widths,\n src: data.url,\n width: maxWidth,\n height: imgElementHeight,\n loader,\n });\n\n /* eslint-disable hydrogen/prefer-image-component */\n return (\n <img\n id={data.id ?? ''}\n alt={data.altText ?? rest.alt ?? ''}\n loading={loading ?? 'lazy'}\n {...rest}\n src={finalSrc}\n width={imgElementWidth ?? undefined}\n height={imgElementHeight ?? undefined}\n srcSet={finalSrcset}\n decoding={decoding}\n />\n );\n /* eslint-enable hydrogen/prefer-image-component */\n}\n\ntype InternalShopifySrcSetGeneratorsParams = Simplify<\n ShopifyLoaderOptions & {\n src: ImageType['url'];\n widths?: (HtmlImageProps['width'] | ImageType['width'])[];\n loader?: (params: ShopifyLoaderParams) => string;\n }\n>;\nfunction internalImageSrcSet({\n src,\n width,\n crop,\n scale,\n widths,\n loader,\n height,\n}: InternalShopifySrcSetGeneratorsParams): string {\n const hasCustomWidths = widths && Array.isArray(widths);\n if (hasCustomWidths && widths.some((size) => isNaN(size as number))) {\n throw new Error(\n `<Image/>: the 'widths' must be an array of numbers. Image: ${src}`\n );\n }\n\n let aspectRatio = 1;\n if (width && height) {\n aspectRatio = Number(height) / Number(width);\n }\n\n let setSizes = hasCustomWidths ? widths : IMG_SRC_SET_SIZES;\n if (\n !hasCustomWidths &&\n width &&\n width < IMG_SRC_SET_SIZES[IMG_SRC_SET_SIZES.length - 1]\n ) {\n setSizes = IMG_SRC_SET_SIZES.filter((size) => size <= width);\n }\n const srcGenerator = loader ? loader : addImageSizeParametersToUrl;\n return setSizes\n .map(\n (size) =>\n `${srcGenerator({\n src,\n width: size,\n // height is not applied if there is no crop\n // if there is crop, then height is applied as a ratio of the original width + height aspect ratio * size\n height: crop ? Number(size) * aspectRatio : undefined,\n crop,\n scale,\n })} ${size ?? ''}w`\n )\n .join(', ');\n}\n"],"names":[],"mappings":";;AAiEO,SAAS,MAAM;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,GAAG;AACL,GAA0C;AACpC,MAAA,CAAC,KAAK,KAAK;AACP,UAAA,kBAAkB,iEACtB,KAAK,MAAM;AAGS;AACd,YAAA,IAAI,MAAM,eAAe;AAAA,IAGjC;AAAA,EAGF;AAEA,MAAwB,CAAC,KAAK,WAAW,CAAC,KAAK,KAAK;AAC1C,YAAA;AAAA,MACN,gIACE,KAAK,MAAM,KAAK;AAAA,IAAA;AAAA,EAGtB;AAEA,QAAM,EAAC,OAAO,iBAAiB,QAAQ,iBAAA,IACrC,0BAA0B;AAAA,IACxB;AAAA,IACA;AAAA,IACA,cAAc;AAAA,MACZ;AAAA,MACA;AAAA,IACF;AAAA,EAAA,CACD;AAEH,MAAyB,CAAC,mBAAmB,CAAC,kBAAmB;AACvD,YAAA;AAAA,MACN,uHACE,KAAK,MAAM,KAAK;AAAA,IAAA;AAAA,EAGtB;AAEA,MAAI,WAAW,KAAK;AAEpB,MAAI,QAAQ;AACV,eAAW,OAAO;AAAA,MAChB,GAAG;AAAA,MACH,KAAK,KAAK;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,IAAA,CACT;AACD,QAAI,OAAO,aAAa,YAAY,CAAC,UAAU;AAC7C,YAAM,IAAI;AAAA,QACR,4DACE,KAAK,MAAM,KAAK;AAAA,MAAA;AAAA,IAGtB;AAAA,EACF;AAIA,QAAM,WACJ,SAAS,mBAAmB,QAAQ,kBAChC,QACA;AACA,QAAA,cACJ,KAAK,UACL,oBAAoB;AAAA,IAClB,GAAG;AAAA,IACH;AAAA,IACA,KAAK,KAAK;AAAA,IACV,OAAO;AAAA,IACP,QAAQ;AAAA,IACR;AAAA,EAAA,CACD;AAID,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,IAAI,KAAK,MAAM;AAAA,MACf,KAAK,KAAK,WAAW,KAAK,OAAO;AAAA,MACjC,SAAS,WAAW;AAAA,MACnB,GAAG;AAAA,MACJ,KAAK;AAAA,MACL,OAAO,mBAAmB;AAAA,MAC1B,QAAQ,oBAAoB;AAAA,MAC5B,QAAQ;AAAA,MACR;AAAA,IAAA;AAAA,EAAA;AAIN;AASA,SAAS,oBAAoB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAkD;AAChD,QAAM,kBAAkB,UAAU,MAAM,QAAQ,MAAM;AAClD,MAAA,mBAAmB,OAAO,KAAK,CAAC,SAAS,MAAM,IAAc,CAAC,GAAG;AACnE,UAAM,IAAI;AAAA,MACR,8DAA8D;AAAA,IAAA;AAAA,EAElE;AAEA,MAAI,cAAc;AAClB,MAAI,SAAS,QAAQ;AACnB,kBAAc,OAAO,MAAM,IAAI,OAAO,KAAK;AAAA,EAC7C;AAEI,MAAA,WAAW,kBAAkB,SAAS;AAExC,MAAA,CAAC,mBACD,SACA,QAAQ,kBAAkB,kBAAkB,SAAS,CAAC,GACtD;AACA,eAAW,kBAAkB,OAAO,CAAC,SAAS,QAAQ,KAAK;AAAA,EAC7D;AACM,QAAA,eAAe,SAAS,SAAS;AACvC,SAAO,SACJ;AAAA,IACC,CAAC,SACC,GAAG,aAAa;AAAA,MACd;AAAA,MACA,OAAO;AAAA;AAAA;AAAA,MAGP,QAAQ,OAAO,OAAO,IAAI,IAAI,cAAc;AAAA,MAC5C;AAAA,MACA;AAAA,IACD,CAAA,KAAK,QAAQ;AAAA,EAAA,EAEjB,KAAK,IAAI;AACd;"}
@@ -1 +1 @@
1
- {"version":3,"file":"MediaFile.mjs","sources":["../../src/MediaFile.tsx"],"sourcesContent":["import {Image, type ShopifyImageProps} from './Image.js';\nimport {Video} from './Video.js';\nimport {ExternalVideo} from './ExternalVideo.js';\nimport {ModelViewer} from './ModelViewer.js';\nimport type {MediaEdge as MediaEdgeType} from './storefront-api-types.js';\nimport type {PartialDeep} from 'type-fest';\nimport type {ModelViewerElement} from '@google/model-viewer/lib/model-viewer.js';\n\ntype BaseProps = React.HTMLAttributes<\n HTMLImageElement | HTMLVideoElement | HTMLIFrameElement | ModelViewerElement\n>;\nexport interface MediaFileProps extends BaseProps {\n /** An object with fields that correspond to the Storefront API's [Media object](https://shopify.dev/api/storefront/reference/products/media). */\n data: PartialDeep<MediaEdgeType['node'], {recurseIntoArrays: true}>;\n /** The options for the `Image`, `Video`, `ExternalVideo`, or `ModelViewer` components. */\n mediaOptions?: MediaOptions;\n}\n\ntype MediaOptions = {\n /** Props that will only apply when an `<Image />` is rendered */\n image?: Omit<ShopifyImageProps, 'data'>;\n /** Props that will only apply when a `<Video />` is rendered */\n video?: Omit<React.ComponentProps<typeof Video>, 'data'>;\n /** Props that will only apply when an `<ExternalVideo />` is rendered */\n externalVideo?: Omit<\n React.ComponentProps<typeof ExternalVideo>['options'],\n 'data'\n >;\n /** Props that will only apply when a `<ModelViewer />` is rendered */\n modelViewer?: Omit<typeof ModelViewer, 'data'>;\n};\n\n/**\n * The `MediaFile` component renders the media for the Storefront API's\n * [Media object](https://shopify.dev/api/storefront/reference/products/media). It renders an `Image`, a\n * `Video`, an `ExternalVideo`, or a `ModelViewer` depending on the `__typename` of the `data` prop.\n */\nexport function MediaFile({\n data,\n mediaOptions,\n ...passthroughProps\n}: MediaFileProps) {\n switch (data.__typename) {\n case 'MediaImage': {\n if (!data.image) {\n const noDataImage = `<MediaFile/>: 'data.image' does not exist for __typename of 'MediaImage'; rendering 'null' by default.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(noDataImage);\n } else {\n console.warn(noDataImage);\n return null;\n }\n }\n\n return (\n <Image\n {...passthroughProps}\n {...mediaOptions?.image}\n data={data.image}\n />\n );\n }\n case 'Video': {\n return (\n <Video {...passthroughProps} {...mediaOptions?.video} data={data} />\n );\n }\n case 'ExternalVideo': {\n return (\n <ExternalVideo\n {...passthroughProps}\n {...mediaOptions?.externalVideo}\n data={data}\n />\n );\n }\n case 'Model3d': {\n return (\n // @ts-expect-error There are issues with the inferred HTML attribute types here for ModelViewer (and contentEditable), but I think that's a little bit beyond me at the moment\n <ModelViewer\n {...passthroughProps}\n {...mediaOptions?.modelViewer}\n data={data}\n />\n );\n }\n default: {\n const typenameMissingMessage = `<MediaFile /> requires the '__typename' property to exist on the 'data' prop in order to render the matching sub-component for this type of media.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(typenameMissingMessage);\n } else {\n console.error(`${typenameMissingMessage} Rendering 'null' by default`);\n return null;\n }\n }\n }\n}\n"],"names":[],"mappings":";;;;;AAqCO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAmB;AACjB,UAAQ,KAAK,YAAY;AAAA,IACvB,KAAK,cAAc;AACb,UAAA,CAAC,KAAK,OAAO;AACf,cAAM,cAAc;AACE;AACd,gBAAA,IAAI,MAAM,WAAW;AAAA,QAI7B;AAAA,MACF;AAGE,aAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACE,GAAG;AAAA,UACH,GAAG,6CAAc;AAAA,UAClB,MAAM,KAAK;AAAA,QAAA;AAAA,MAAA;AAAA,IAGjB;AAAA,IACA,KAAK,SAAS;AACZ,iCACG,OAAO,EAAA,GAAG,kBAAmB,GAAG,6CAAc,OAAO,KAAY,CAAA;AAAA,IAEtE;AAAA,IACA,KAAK,iBAAiB;AAElB,aAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACE,GAAG;AAAA,UACH,GAAG,6CAAc;AAAA,UAClB;AAAA,QAAA;AAAA,MAAA;AAAA,IAGN;AAAA,IACA,KAAK,WAAW;AACd;AAAA;AAAA,QAEE;AAAA,UAAC;AAAA,UAAA;AAAA,YACE,GAAG;AAAA,YACH,GAAG,6CAAc;AAAA,YAClB;AAAA,UAAA;AAAA,QACF;AAAA;AAAA,IAEJ;AAAA,IACA,SAAS;AACP,YAAM,yBAAyB;AACT;AACd,cAAA,IAAI,MAAM,sBAAsB;AAAA,MAIxC;AAAA,IACF;AAAA,EACF;AACF;"}
1
+ {"version":3,"file":"MediaFile.mjs","sources":["../../src/MediaFile.tsx"],"sourcesContent":["import {Image, type ShopifyImageProps} from './Image.js';\nimport {Video} from './Video.js';\nimport {ExternalVideo} from './ExternalVideo.js';\nimport {ModelViewer} from './ModelViewer.js';\nimport type {MediaEdge as MediaEdgeType} from './storefront-api-types.js';\nimport type {PartialDeep} from 'type-fest';\nimport type {ModelViewerElement} from '@google/model-viewer/lib/model-viewer.js';\n\ntype BaseProps = React.HTMLAttributes<\n HTMLImageElement | HTMLVideoElement | HTMLIFrameElement | ModelViewerElement\n>;\nexport interface MediaFileProps extends BaseProps {\n /** An object with fields that correspond to the Storefront API's [Media object](https://shopify.dev/api/storefront/reference/products/media). */\n data: PartialDeep<MediaEdgeType['node'], {recurseIntoArrays: true}>;\n /** The options for the `Image`, `Video`, `ExternalVideo`, or `ModelViewer` components. */\n mediaOptions?: MediaOptions;\n}\n\ntype MediaOptions = {\n /** Props that will only apply when an `<Image />` is rendered */\n image?: Omit<ShopifyImageProps, 'data'>;\n /** Props that will only apply when a `<Video />` is rendered */\n video?: Omit<React.ComponentProps<typeof Video>, 'data'>;\n /** Props that will only apply when an `<ExternalVideo />` is rendered */\n externalVideo?: Omit<\n React.ComponentProps<typeof ExternalVideo>['options'],\n 'data'\n >;\n /** Props that will only apply when a `<ModelViewer />` is rendered */\n modelViewer?: Omit<typeof ModelViewer, 'data'>;\n};\n\n/**\n * The `MediaFile` component renders the media for the Storefront API's\n * [Media object](https://shopify.dev/api/storefront/reference/products/media). It renders an `Image`, a\n * `Video`, an `ExternalVideo`, or a `ModelViewer` depending on the `__typename` of the `data` prop.\n */\nexport function MediaFile({\n data,\n mediaOptions,\n ...passthroughProps\n}: MediaFileProps): JSX.Element | null {\n switch (data.__typename) {\n case 'MediaImage': {\n if (!data.image) {\n const noDataImage = `<MediaFile/>: 'data.image' does not exist for __typename of 'MediaImage'; rendering 'null' by default.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(noDataImage);\n } else {\n console.warn(noDataImage);\n return null;\n }\n }\n\n return (\n <Image\n {...passthroughProps}\n {...mediaOptions?.image}\n data={data.image}\n />\n );\n }\n case 'Video': {\n return (\n <Video {...passthroughProps} {...mediaOptions?.video} data={data} />\n );\n }\n case 'ExternalVideo': {\n return (\n <ExternalVideo\n {...passthroughProps}\n {...mediaOptions?.externalVideo}\n data={data}\n />\n );\n }\n case 'Model3d': {\n return (\n // @ts-expect-error There are issues with the inferred HTML attribute types here for ModelViewer (and contentEditable), but I think that's a little bit beyond me at the moment\n <ModelViewer\n {...passthroughProps}\n {...mediaOptions?.modelViewer}\n data={data}\n />\n );\n }\n default: {\n const typenameMissingMessage = `<MediaFile /> requires the '__typename' property to exist on the 'data' prop in order to render the matching sub-component for this type of media.`;\n if (__HYDROGEN_DEV__) {\n throw new Error(typenameMissingMessage);\n } else {\n console.error(`${typenameMissingMessage} Rendering 'null' by default`);\n return null;\n }\n }\n }\n}\n"],"names":[],"mappings":";;;;;AAqCO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAuC;AACrC,UAAQ,KAAK,YAAY;AAAA,IACvB,KAAK,cAAc;AACb,UAAA,CAAC,KAAK,OAAO;AACf,cAAM,cAAc;AACE;AACd,gBAAA,IAAI,MAAM,WAAW;AAAA,QAI7B;AAAA,MACF;AAGE,aAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACE,GAAG;AAAA,UACH,GAAG,6CAAc;AAAA,UAClB,MAAM,KAAK;AAAA,QAAA;AAAA,MAAA;AAAA,IAGjB;AAAA,IACA,KAAK,SAAS;AACZ,iCACG,OAAO,EAAA,GAAG,kBAAmB,GAAG,6CAAc,OAAO,KAAY,CAAA;AAAA,IAEtE;AAAA,IACA,KAAK,iBAAiB;AAElB,aAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACE,GAAG;AAAA,UACH,GAAG,6CAAc;AAAA,UAClB;AAAA,QAAA;AAAA,MAAA;AAAA,IAGN;AAAA,IACA,KAAK,WAAW;AACd;AAAA;AAAA,QAEE;AAAA,UAAC;AAAA,UAAA;AAAA,YACE,GAAG;AAAA,YACH,GAAG,6CAAc;AAAA,YAClB;AAAA,UAAA;AAAA,QACF;AAAA;AAAA,IAEJ;AAAA,IACA,SAAS;AACP,YAAM,yBAAyB;AACT;AACd,cAAA,IAAI,MAAM,sBAAsB;AAAA,MAIxC;AAAA,IACF;AAAA,EACF;AACF;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ModelViewer.mjs","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\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 'src'\n> &\n ModelViewerBaseProps;\n\ntype ModelViewerBaseProps = {\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":[],"mappings":"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"}
1
+ {"version":3,"file":"ModelViewer.mjs","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\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 'src'\n> &\n ModelViewerBaseProps;\n\ntype ModelViewerBaseProps = {\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): JSX.Element | null {\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 // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\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 // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\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":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Money.mjs","sources":["../../src/Money.tsx"],"sourcesContent":["import {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\nexport interface MoneyPropsBase<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 MoneyPropsBase<ComponentGeneric> &\n Omit<\n React.ComponentPropsWithoutRef<ComponentGeneric>,\n keyof MoneyPropsBase<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 = 'div'>({\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":[],"mappings":";;AAiCO,SAAS,MAA0D;AAAA,EACxE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,uBAAuB;AAAA,EACvB,GAAG;AACL,GAAiC;AAC3B,MAAA,CAAC,QAAQ,IAAI,GAAG;AAClB,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AACM,QAAA,cAAc,SAAS,IAAI;AACjC,QAAM,UAAU,MAAM;AAEtB,MAAI,SAAS,YAAY;AAEzB,MAAI,mBAAmB,sBAAsB;AACvC,QAAA,mBAAmB,CAAC,sBAAsB;AAC5C,eAAS,YAAY;AAAA,IAAA,WACZ,CAAC,mBAAmB,sBAAsB;AACnD,eAAS,YAAY;AAAA,IAAA,OAChB;AAEL,eAAS,YAAY;AAAA,IACvB;AAAA,EACF;AAGE,SAAA,qBAAC,SAAS,EAAA,GAAG,kBACV,UAAA;AAAA,IAAA;AAAA,IACA,eAAe,YAAY,iBAEvB,qBAAA,UAAA,EAAA,UAAA;AAAA,MAAA;AAAA,MACA,YAAY;AAAA,IAAA,GACf;AAAA,EAEJ,EAAA,CAAA;AAEJ;AAGA,SAAS,QACP,YACuB;AACvB,SACE,OAAO,WAAW,WAAW,YAC7B,CAAC,CAAC,WAAW,UACb,OAAO,WAAW,iBAAiB,YACnC,CAAC,CAAC,WAAW;AAEjB;"}
1
+ {"version":3,"file":"Money.mjs","sources":["../../src/Money.tsx"],"sourcesContent":["import {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\nexport interface MoneyPropsBase<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 MoneyPropsBase<ComponentGeneric> &\n Omit<\n React.ComponentPropsWithoutRef<ComponentGeneric>,\n keyof MoneyPropsBase<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 = 'div'>({\n data,\n as,\n withoutCurrency,\n withoutTrailingZeros,\n measurement,\n measurementSeparator = '/',\n ...passthroughProps\n}: MoneyProps<ComponentGeneric>): JSX.Element {\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":[],"mappings":";;AAiCO,SAAS,MAA0D;AAAA,EACxE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,uBAAuB;AAAA,EACvB,GAAG;AACL,GAA8C;AACxC,MAAA,CAAC,QAAQ,IAAI,GAAG;AAClB,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AACM,QAAA,cAAc,SAAS,IAAI;AACjC,QAAM,UAAU,MAAM;AAEtB,MAAI,SAAS,YAAY;AAEzB,MAAI,mBAAmB,sBAAsB;AACvC,QAAA,mBAAmB,CAAC,sBAAsB;AAC5C,eAAS,YAAY;AAAA,IAAA,WACZ,CAAC,mBAAmB,sBAAsB;AACnD,eAAS,YAAY;AAAA,IAAA,OAChB;AAEL,eAAS,YAAY;AAAA,IACvB;AAAA,EACF;AAGE,SAAA,qBAAC,SAAS,EAAA,GAAG,kBACV,UAAA;AAAA,IAAA;AAAA,IACA,eAAe,YAAY,iBAEvB,qBAAA,UAAA,EAAA,UAAA;AAAA,MAAA;AAAA,MACA,YAAY;AAAA,IAAA,GACf;AAAA,EAEJ,EAAA,CAAA;AAEJ;AAGA,SAAS,QACP,YACuB;AACvB,SACE,OAAO,WAAW,WAAW,YAC7B,CAAC,CAAC,WAAW,UACb,OAAO,WAAW,iBAAiB,YACnC,CAAC,CAAC,WAAW;AAEjB;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProductPrice.mjs","sources":["../../src/ProductPrice.tsx"],"sourcesContent":["import type {\n MoneyV2,\n UnitPriceMeasurement,\n Product,\n} from './storefront-api-types.js';\nimport {Money, type MoneyProps, type MoneyPropsBase} from './Money.js';\nimport type {PartialDeep} from 'type-fest';\nimport {flattenConnection} from './flatten-connection.js';\n\nexport interface ProductPriceProps {\n /** A Storefront API [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\n// This is only for documenation purposes, and it is not used in the code.\nexport interface ProductPricePropsForDocs<\n AsType extends React.ElementType = 'div'\n> extends Omit<MoneyPropsBase<AsType>, 'data' | 'measurement'>,\n ProductPriceProps {}\n"],"names":["variant"],"mappings":";;;AAwBO,SAAS,aACd,OAEA;;AACM,QAAA;AAAA,IACJ,YAAY;AAAA,IACZ;AAAA,IACA,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,GAAG;AAAA,EACD,IAAA;AAEJ,MAAI,WAAW,MAAM;AACb,UAAA,IAAI,MAAM,uDAAuD;AAAA,EACzE;AAEI,MAAA;AACA,MAAA;AAEJ,QAAM,UAAU,YACZ,mBAAkB,mCAAS,aAAY,CAAE,CAAA,EAAE;AAAA,IACzC,CAACA,cAAYA,qCAAS,QAAO;AAAA,EAAA,KAC1B,OACL;AAEJ,MAAI,cAAc,aAAa;AAC7B,QAAI,aAAa,SAAS;AACxB,YAAI,aAAQ,qBAAR,mBAA0B,cAAW,aAAQ,YAAR,mBAAiB,SAAQ;AACzD,eAAA;AAAA,MACT;AACA,cAAQ,QAAQ;AAAA,IAAA,WACP,cAAc,OAAO;AAC9B,eAAQ,wCAAS,wBAAT,mBAA8B;AAAA,IAAA,OACjC;AACL,eAAQ,wCAAS,wBAAT,mBAA8B;AAAA,IACxC;AAAA,EAAA,OACK;AACL,QAAI,aAAa,SAAS;AACxB,cAAQ,QAAQ;AAChB,UAAI,cAAc,QAAQ;AACxB,gBAAQ,QAAQ;AAChB,sBAAc,QAAQ;AAAA,MACxB;AAAA,IAAA,WACS,cAAc,OAAO;AAC9B,eAAQ,aAAQ,eAAR,mBAAoB;AAAA,IAAA,OACvB;AACL,eAAQ,aAAQ,eAAR,mBAAoB;AAAA,IAC9B;AAAA,EACF;AAEA,MAAI,CAAC,OAAO;AACH,WAAA;AAAA,EACT;AAEA,MAAI,aAAa;AACf,+BACG,OAAO,EAAA,GAAG,kBAAkB,MAAM,OAAO,YAA0B,CAAA;AAAA,EAExE;AAEA,SAAQ,oBAAA,OAAA,EAAO,GAAG,kBAAkB,MAAM,MAAO,CAAA;AACnD;"}
1
+ {"version":3,"file":"ProductPrice.mjs","sources":["../../src/ProductPrice.tsx"],"sourcesContent":["import type {\n MoneyV2,\n UnitPriceMeasurement,\n Product,\n} from './storefront-api-types.js';\nimport {Money, type MoneyProps, type MoneyPropsBase} from './Money.js';\nimport type {PartialDeep} from 'type-fest';\nimport {flattenConnection} from './flatten-connection.js';\n\nexport interface ProductPriceProps {\n /** A Storefront API [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): JSX.Element | null {\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\n// This is only for documenation purposes, and it is not used in the code.\nexport interface ProductPricePropsForDocs<\n AsType extends React.ElementType = 'div'\n> extends Omit<MoneyPropsBase<AsType>, 'data' | 'measurement'>,\n ProductPriceProps {}\n"],"names":["variant"],"mappings":";;;AAwBO,SAAS,aACd,OAEoB;;AACd,QAAA;AAAA,IACJ,YAAY;AAAA,IACZ;AAAA,IACA,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,GAAG;AAAA,EACD,IAAA;AAEJ,MAAI,WAAW,MAAM;AACb,UAAA,IAAI,MAAM,uDAAuD;AAAA,EACzE;AAEI,MAAA;AACA,MAAA;AAEJ,QAAM,UAAU,YACZ,mBAAkB,mCAAS,aAAY,CAAE,CAAA,EAAE;AAAA,IACzC,CAACA,cAAYA,qCAAS,QAAO;AAAA,EAAA,KAC1B,OACL;AAEJ,MAAI,cAAc,aAAa;AAC7B,QAAI,aAAa,SAAS;AACxB,YAAI,aAAQ,qBAAR,mBAA0B,cAAW,aAAQ,YAAR,mBAAiB,SAAQ;AACzD,eAAA;AAAA,MACT;AACA,cAAQ,QAAQ;AAAA,IAAA,WACP,cAAc,OAAO;AAC9B,eAAQ,wCAAS,wBAAT,mBAA8B;AAAA,IAAA,OACjC;AACL,eAAQ,wCAAS,wBAAT,mBAA8B;AAAA,IACxC;AAAA,EAAA,OACK;AACL,QAAI,aAAa,SAAS;AACxB,cAAQ,QAAQ;AAChB,UAAI,cAAc,QAAQ;AACxB,gBAAQ,QAAQ;AAChB,sBAAc,QAAQ;AAAA,MACxB;AAAA,IAAA,WACS,cAAc,OAAO;AAC9B,eAAQ,aAAQ,eAAR,mBAAoB;AAAA,IAAA,OACvB;AACL,eAAQ,aAAQ,eAAR,mBAAoB;AAAA,IAC9B;AAAA,EACF;AAEA,MAAI,CAAC,OAAO;AACH,WAAA;AAAA,EACT;AAEA,MAAI,aAAa;AACf,+BACG,OAAO,EAAA,GAAG,kBAAkB,MAAM,OAAO,YAA0B,CAAA;AAAA,EAExE;AAEA,SAAQ,oBAAA,OAAA,EAAO,GAAG,kBAAkB,MAAM,MAAO,CAAA;AACnD;"}