@shopify/hydrogen-react 2026.4.1 → 2026.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser-dev/AddToCartButton.mjs +60 -71
- package/dist/browser-dev/AddToCartButton.mjs.map +1 -1
- package/dist/browser-dev/BaseButton.mjs +20 -26
- package/dist/browser-dev/BaseButton.mjs.map +1 -1
- package/dist/browser-dev/BuyNowButton.mjs +40 -45
- package/dist/browser-dev/BuyNowButton.mjs.map +1 -1
- package/dist/browser-dev/CartCheckoutButton.mjs +28 -23
- package/dist/browser-dev/CartCheckoutButton.mjs.map +1 -1
- package/dist/browser-dev/CartCost.mjs +26 -22
- package/dist/browser-dev/CartCost.mjs.map +1 -1
- package/dist/browser-dev/CartLineProvider.mjs +23 -18
- package/dist/browser-dev/CartLineProvider.mjs.map +1 -1
- package/dist/browser-dev/CartLineQuantity.mjs +18 -9
- package/dist/browser-dev/CartLineQuantity.mjs.map +1 -1
- package/dist/browser-dev/CartLineQuantityAdjustButton.mjs +48 -45
- package/dist/browser-dev/CartLineQuantityAdjustButton.mjs.map +1 -1
- package/dist/browser-dev/CartProvider.mjs +315 -385
- package/dist/browser-dev/CartProvider.mjs.map +1 -1
- package/dist/browser-dev/ExternalVideo.mjs +35 -47
- package/dist/browser-dev/ExternalVideo.mjs.map +1 -1
- package/dist/browser-dev/Image.mjs +335 -340
- package/dist/browser-dev/Image.mjs.map +1 -1
- package/dist/browser-dev/MediaFile.mjs +39 -61
- package/dist/browser-dev/MediaFile.mjs.map +1 -1
- package/dist/browser-dev/ModelViewer.mjs +115 -139
- package/dist/browser-dev/ModelViewer.mjs.map +1 -1
- package/dist/browser-dev/Money.mjs +53 -39
- package/dist/browser-dev/Money.mjs.map +1 -1
- package/dist/browser-dev/ProductPrice.mjs +44 -61
- package/dist/browser-dev/ProductPrice.mjs.map +1 -1
- package/dist/browser-dev/ProductProvider.mjs +147 -179
- package/dist/browser-dev/ProductProvider.mjs.map +1 -1
- package/dist/browser-dev/RichText.components.mjs +36 -46
- package/dist/browser-dev/RichText.components.mjs.map +1 -1
- package/dist/browser-dev/RichText.mjs +111 -154
- package/dist/browser-dev/RichText.mjs.map +1 -1
- package/dist/browser-dev/ShopPayButton.mjs +53 -81
- package/dist/browser-dev/ShopPayButton.mjs.map +1 -1
- package/dist/browser-dev/ShopifyProvider.mjs +71 -84
- package/dist/browser-dev/ShopifyProvider.mjs.map +1 -1
- package/dist/browser-dev/Video.mjs +35 -52
- package/dist/browser-dev/Video.mjs.map +1 -1
- package/dist/browser-dev/analytics-constants.mjs +41 -43
- package/dist/browser-dev/analytics-constants.mjs.map +1 -1
- package/dist/browser-dev/analytics-schema-custom-storefront-customer-tracking.mjs +127 -214
- package/dist/browser-dev/analytics-schema-custom-storefront-customer-tracking.mjs.map +1 -1
- package/dist/browser-dev/analytics-schema-trekkie-storefront-page-view.mjs +39 -50
- package/dist/browser-dev/analytics-schema-trekkie-storefront-page-view.mjs.map +1 -1
- package/dist/browser-dev/analytics-utils.mjs +78 -56
- package/dist/browser-dev/analytics-utils.mjs.map +1 -1
- package/dist/browser-dev/analytics.mjs +112 -155
- package/dist/browser-dev/analytics.mjs.map +1 -1
- package/dist/browser-dev/cart-constants.mjs +11 -15
- package/dist/browser-dev/cart-constants.mjs.map +1 -1
- package/dist/browser-dev/cart-hooks.mjs +42 -57
- package/dist/browser-dev/cart-hooks.mjs.map +1 -1
- package/dist/browser-dev/cart-queries.mjs +28 -66
- package/dist/browser-dev/cart-queries.mjs.map +1 -1
- package/dist/browser-dev/codegen.helpers.mjs +31 -20
- package/dist/browser-dev/codegen.helpers.mjs.map +1 -1
- package/dist/browser-dev/cookies-utils.mjs +44 -42
- package/dist/browser-dev/cookies-utils.mjs.map +1 -1
- package/dist/browser-dev/flatten-connection.mjs +23 -29
- package/dist/browser-dev/flatten-connection.mjs.map +1 -1
- package/dist/browser-dev/getProductOptions.mjs +248 -226
- package/dist/browser-dev/getProductOptions.mjs.map +1 -1
- package/dist/browser-dev/index.mjs +15 -70
- package/dist/browser-dev/load-script.mjs +38 -49
- package/dist/browser-dev/load-script.mjs.map +1 -1
- package/dist/browser-dev/node_modules/.pnpm/@xstate_fsm@2.0.0/node_modules/@xstate/fsm/es/index.mjs +175 -123
- package/dist/browser-dev/node_modules/.pnpm/@xstate_fsm@2.0.0/node_modules/@xstate/fsm/es/index.mjs.map +1 -1
- package/dist/browser-dev/optionValueDecoder.mjs +104 -86
- package/dist/browser-dev/optionValueDecoder.mjs.map +1 -1
- package/dist/browser-dev/packages/hydrogen-react/package.mjs +6 -0
- package/dist/browser-dev/packages/hydrogen-react/package.mjs.map +1 -0
- package/dist/browser-dev/parse-metafield.mjs +122 -134
- package/dist/browser-dev/parse-metafield.mjs.map +1 -1
- package/dist/browser-dev/storefront-api-constants.mjs +6 -5
- package/dist/browser-dev/storefront-api-constants.mjs.map +1 -1
- package/dist/browser-dev/storefront-client.mjs +62 -102
- package/dist/browser-dev/storefront-client.mjs.map +1 -1
- package/dist/browser-dev/tracking-utils.mjs +68 -88
- package/dist/browser-dev/tracking-utils.mjs.map +1 -1
- package/dist/browser-dev/useCartAPIStateMachine.mjs +188 -346
- package/dist/browser-dev/useCartAPIStateMachine.mjs.map +1 -1
- package/dist/browser-dev/useCartActions.mjs +197 -172
- package/dist/browser-dev/useCartActions.mjs.map +1 -1
- package/dist/browser-dev/useMachine.mjs +50 -62
- package/dist/browser-dev/useMachine.mjs.map +1 -1
- package/dist/browser-dev/useMoney.mjs +176 -154
- package/dist/browser-dev/useMoney.mjs.map +1 -1
- package/dist/browser-dev/useSelectedOptionInUrlParam.mjs +17 -27
- package/dist/browser-dev/useSelectedOptionInUrlParam.mjs.map +1 -1
- package/dist/browser-dev/useShopifyCookies.mjs +123 -138
- package/dist/browser-dev/useShopifyCookies.mjs.map +1 -1
- package/dist/browser-prod/AddToCartButton.mjs +60 -71
- package/dist/browser-prod/AddToCartButton.mjs.map +1 -1
- package/dist/browser-prod/BaseButton.mjs +20 -26
- package/dist/browser-prod/BaseButton.mjs.map +1 -1
- package/dist/browser-prod/BuyNowButton.mjs +40 -45
- package/dist/browser-prod/BuyNowButton.mjs.map +1 -1
- package/dist/browser-prod/CartCheckoutButton.mjs +28 -23
- package/dist/browser-prod/CartCheckoutButton.mjs.map +1 -1
- package/dist/browser-prod/CartCost.mjs +26 -22
- package/dist/browser-prod/CartCost.mjs.map +1 -1
- package/dist/browser-prod/CartLineProvider.mjs +23 -18
- package/dist/browser-prod/CartLineProvider.mjs.map +1 -1
- package/dist/browser-prod/CartLineQuantity.mjs +18 -9
- package/dist/browser-prod/CartLineQuantity.mjs.map +1 -1
- package/dist/browser-prod/CartLineQuantityAdjustButton.mjs +48 -45
- package/dist/browser-prod/CartLineQuantityAdjustButton.mjs.map +1 -1
- package/dist/browser-prod/CartProvider.mjs +315 -385
- package/dist/browser-prod/CartProvider.mjs.map +1 -1
- package/dist/browser-prod/ExternalVideo.mjs +35 -47
- package/dist/browser-prod/ExternalVideo.mjs.map +1 -1
- package/dist/browser-prod/Image.mjs +326 -325
- package/dist/browser-prod/Image.mjs.map +1 -1
- package/dist/browser-prod/MediaFile.mjs +44 -63
- package/dist/browser-prod/MediaFile.mjs.map +1 -1
- package/dist/browser-prod/ModelViewer.mjs +117 -135
- package/dist/browser-prod/ModelViewer.mjs.map +1 -1
- package/dist/browser-prod/Money.mjs +53 -39
- package/dist/browser-prod/Money.mjs.map +1 -1
- package/dist/browser-prod/ProductPrice.mjs +44 -61
- package/dist/browser-prod/ProductPrice.mjs.map +1 -1
- package/dist/browser-prod/ProductProvider.mjs +147 -179
- package/dist/browser-prod/ProductProvider.mjs.map +1 -1
- package/dist/browser-prod/RichText.components.mjs +36 -46
- package/dist/browser-prod/RichText.components.mjs.map +1 -1
- package/dist/browser-prod/RichText.mjs +111 -154
- package/dist/browser-prod/RichText.mjs.map +1 -1
- package/dist/browser-prod/ShopPayButton.mjs +53 -81
- package/dist/browser-prod/ShopPayButton.mjs.map +1 -1
- package/dist/browser-prod/ShopifyProvider.mjs +71 -84
- package/dist/browser-prod/ShopifyProvider.mjs.map +1 -1
- package/dist/browser-prod/Video.mjs +35 -52
- package/dist/browser-prod/Video.mjs.map +1 -1
- package/dist/browser-prod/analytics-constants.mjs +41 -43
- package/dist/browser-prod/analytics-constants.mjs.map +1 -1
- package/dist/browser-prod/analytics-schema-custom-storefront-customer-tracking.mjs +127 -214
- package/dist/browser-prod/analytics-schema-custom-storefront-customer-tracking.mjs.map +1 -1
- package/dist/browser-prod/analytics-schema-trekkie-storefront-page-view.mjs +39 -50
- package/dist/browser-prod/analytics-schema-trekkie-storefront-page-view.mjs.map +1 -1
- package/dist/browser-prod/analytics-utils.mjs +78 -56
- package/dist/browser-prod/analytics-utils.mjs.map +1 -1
- package/dist/browser-prod/analytics.mjs +111 -153
- package/dist/browser-prod/analytics.mjs.map +1 -1
- package/dist/browser-prod/cart-constants.mjs +11 -15
- package/dist/browser-prod/cart-constants.mjs.map +1 -1
- package/dist/browser-prod/cart-hooks.mjs +42 -57
- package/dist/browser-prod/cart-hooks.mjs.map +1 -1
- package/dist/browser-prod/cart-queries.mjs +28 -66
- package/dist/browser-prod/cart-queries.mjs.map +1 -1
- package/dist/browser-prod/codegen.helpers.mjs +31 -20
- package/dist/browser-prod/codegen.helpers.mjs.map +1 -1
- package/dist/browser-prod/cookies-utils.mjs +44 -42
- package/dist/browser-prod/cookies-utils.mjs.map +1 -1
- package/dist/browser-prod/flatten-connection.mjs +23 -25
- package/dist/browser-prod/flatten-connection.mjs.map +1 -1
- package/dist/browser-prod/getProductOptions.mjs +248 -226
- package/dist/browser-prod/getProductOptions.mjs.map +1 -1
- package/dist/browser-prod/index.mjs +15 -70
- package/dist/browser-prod/load-script.mjs +38 -49
- package/dist/browser-prod/load-script.mjs.map +1 -1
- package/dist/browser-prod/node_modules/.pnpm/@xstate_fsm@2.0.0/node_modules/@xstate/fsm/es/index.mjs +175 -123
- package/dist/browser-prod/node_modules/.pnpm/@xstate_fsm@2.0.0/node_modules/@xstate/fsm/es/index.mjs.map +1 -1
- package/dist/browser-prod/optionValueDecoder.mjs +104 -86
- package/dist/browser-prod/optionValueDecoder.mjs.map +1 -1
- package/dist/browser-prod/packages/hydrogen-react/package.mjs +6 -0
- package/dist/browser-prod/packages/hydrogen-react/package.mjs.map +1 -0
- package/dist/browser-prod/parse-metafield.mjs +134 -146
- package/dist/browser-prod/parse-metafield.mjs.map +1 -1
- package/dist/browser-prod/storefront-api-constants.mjs +6 -5
- package/dist/browser-prod/storefront-api-constants.mjs.map +1 -1
- package/dist/browser-prod/storefront-client.mjs +56 -84
- package/dist/browser-prod/storefront-client.mjs.map +1 -1
- package/dist/browser-prod/tracking-utils.mjs +68 -88
- package/dist/browser-prod/tracking-utils.mjs.map +1 -1
- package/dist/browser-prod/useCartAPIStateMachine.mjs +188 -346
- package/dist/browser-prod/useCartAPIStateMachine.mjs.map +1 -1
- package/dist/browser-prod/useCartActions.mjs +197 -172
- package/dist/browser-prod/useCartActions.mjs.map +1 -1
- package/dist/browser-prod/useMachine.mjs +50 -62
- package/dist/browser-prod/useMachine.mjs.map +1 -1
- package/dist/browser-prod/useMoney.mjs +176 -154
- package/dist/browser-prod/useMoney.mjs.map +1 -1
- package/dist/browser-prod/useSelectedOptionInUrlParam.mjs +17 -27
- package/dist/browser-prod/useSelectedOptionInUrlParam.mjs.map +1 -1
- package/dist/browser-prod/useShopifyCookies.mjs +123 -138
- package/dist/browser-prod/useShopifyCookies.mjs.map +1 -1
- package/dist/node-dev/AddToCartButton.js +64 -73
- package/dist/node-dev/AddToCartButton.js.map +1 -1
- package/dist/node-dev/AddToCartButton.mjs +60 -71
- package/dist/node-dev/AddToCartButton.mjs.map +1 -1
- package/dist/node-dev/BaseButton.js +21 -26
- package/dist/node-dev/BaseButton.js.map +1 -1
- package/dist/node-dev/BaseButton.mjs +20 -26
- package/dist/node-dev/BaseButton.mjs.map +1 -1
- package/dist/node-dev/BuyNowButton.js +42 -46
- package/dist/node-dev/BuyNowButton.js.map +1 -1
- package/dist/node-dev/BuyNowButton.mjs +40 -45
- package/dist/node-dev/BuyNowButton.mjs.map +1 -1
- package/dist/node-dev/CartCheckoutButton.js +30 -24
- package/dist/node-dev/CartCheckoutButton.js.map +1 -1
- package/dist/node-dev/CartCheckoutButton.mjs +28 -23
- package/dist/node-dev/CartCheckoutButton.mjs.map +1 -1
- package/dist/node-dev/CartCost.js +27 -22
- package/dist/node-dev/CartCost.js.map +1 -1
- package/dist/node-dev/CartCost.mjs +26 -22
- package/dist/node-dev/CartCost.mjs.map +1 -1
- package/dist/node-dev/CartLineProvider.js +24 -17
- package/dist/node-dev/CartLineProvider.js.map +1 -1
- package/dist/node-dev/CartLineProvider.mjs +23 -18
- package/dist/node-dev/CartLineProvider.mjs.map +1 -1
- package/dist/node-dev/CartLineQuantity.js +19 -9
- package/dist/node-dev/CartLineQuantity.js.map +1 -1
- package/dist/node-dev/CartLineQuantity.mjs +18 -9
- package/dist/node-dev/CartLineQuantity.mjs.map +1 -1
- package/dist/node-dev/CartLineQuantityAdjustButton.js +50 -46
- package/dist/node-dev/CartLineQuantityAdjustButton.js.map +1 -1
- package/dist/node-dev/CartLineQuantityAdjustButton.mjs +48 -45
- package/dist/node-dev/CartLineQuantityAdjustButton.mjs.map +1 -1
- package/dist/node-dev/CartProvider.js +317 -385
- package/dist/node-dev/CartProvider.js.map +1 -1
- package/dist/node-dev/CartProvider.mjs +315 -385
- package/dist/node-dev/CartProvider.mjs.map +1 -1
- package/dist/node-dev/ExternalVideo.js +36 -47
- package/dist/node-dev/ExternalVideo.js.map +1 -1
- package/dist/node-dev/ExternalVideo.mjs +35 -47
- package/dist/node-dev/ExternalVideo.mjs.map +1 -1
- package/dist/node-dev/Image.js +337 -355
- package/dist/node-dev/Image.js.map +1 -1
- package/dist/node-dev/Image.mjs +335 -340
- package/dist/node-dev/Image.mjs.map +1 -1
- package/dist/node-dev/MediaFile.js +42 -63
- package/dist/node-dev/MediaFile.js.map +1 -1
- package/dist/node-dev/MediaFile.mjs +39 -61
- package/dist/node-dev/MediaFile.mjs.map +1 -1
- package/dist/node-dev/ModelViewer.js +116 -139
- package/dist/node-dev/ModelViewer.js.map +1 -1
- package/dist/node-dev/ModelViewer.mjs +115 -139
- package/dist/node-dev/ModelViewer.mjs.map +1 -1
- package/dist/node-dev/Money.js +54 -39
- package/dist/node-dev/Money.js.map +1 -1
- package/dist/node-dev/Money.mjs +53 -39
- package/dist/node-dev/Money.mjs.map +1 -1
- package/dist/node-dev/ProductPrice.js +45 -61
- package/dist/node-dev/ProductPrice.js.map +1 -1
- package/dist/node-dev/ProductPrice.mjs +44 -61
- package/dist/node-dev/ProductPrice.mjs.map +1 -1
- package/dist/node-dev/ProductProvider.js +148 -178
- package/dist/node-dev/ProductProvider.js.map +1 -1
- package/dist/node-dev/ProductProvider.mjs +147 -179
- package/dist/node-dev/ProductProvider.mjs.map +1 -1
- package/dist/node-dev/RichText.components.js +37 -46
- package/dist/node-dev/RichText.components.js.map +1 -1
- package/dist/node-dev/RichText.components.mjs +36 -46
- package/dist/node-dev/RichText.components.mjs.map +1 -1
- package/dist/node-dev/RichText.js +112 -154
- package/dist/node-dev/RichText.js.map +1 -1
- package/dist/node-dev/RichText.mjs +111 -154
- package/dist/node-dev/RichText.mjs.map +1 -1
- package/dist/node-dev/ShopPayButton.js +54 -81
- package/dist/node-dev/ShopPayButton.js.map +1 -1
- package/dist/node-dev/ShopPayButton.mjs +53 -81
- package/dist/node-dev/ShopPayButton.mjs.map +1 -1
- package/dist/node-dev/ShopifyProvider.js +73 -83
- package/dist/node-dev/ShopifyProvider.js.map +1 -1
- package/dist/node-dev/ShopifyProvider.mjs +71 -84
- package/dist/node-dev/ShopifyProvider.mjs.map +1 -1
- package/dist/node-dev/Video.js +36 -52
- package/dist/node-dev/Video.js.map +1 -1
- package/dist/node-dev/Video.mjs +35 -52
- package/dist/node-dev/Video.mjs.map +1 -1
- package/dist/node-dev/_virtual/_rolldown/runtime.js +23 -0
- package/dist/node-dev/analytics-constants.js +40 -39
- package/dist/node-dev/analytics-constants.js.map +1 -1
- package/dist/node-dev/analytics-constants.mjs +41 -43
- package/dist/node-dev/analytics-constants.mjs.map +1 -1
- package/dist/node-dev/analytics-schema-custom-storefront-customer-tracking.js +128 -210
- package/dist/node-dev/analytics-schema-custom-storefront-customer-tracking.js.map +1 -1
- package/dist/node-dev/analytics-schema-custom-storefront-customer-tracking.mjs +127 -214
- package/dist/node-dev/analytics-schema-custom-storefront-customer-tracking.mjs.map +1 -1
- package/dist/node-dev/analytics-schema-trekkie-storefront-page-view.js +40 -51
- package/dist/node-dev/analytics-schema-trekkie-storefront-page-view.js.map +1 -1
- package/dist/node-dev/analytics-schema-trekkie-storefront-page-view.mjs +39 -50
- package/dist/node-dev/analytics-schema-trekkie-storefront-page-view.mjs.map +1 -1
- package/dist/node-dev/analytics-utils.js +77 -52
- package/dist/node-dev/analytics-utils.js.map +1 -1
- package/dist/node-dev/analytics-utils.mjs +78 -56
- package/dist/node-dev/analytics-utils.mjs.map +1 -1
- package/dist/node-dev/analytics.js +114 -156
- package/dist/node-dev/analytics.js.map +1 -1
- package/dist/node-dev/analytics.mjs +112 -155
- package/dist/node-dev/analytics.mjs.map +1 -1
- package/dist/node-dev/cart-constants.js +10 -9
- package/dist/node-dev/cart-constants.js.map +1 -1
- package/dist/node-dev/cart-constants.mjs +11 -15
- package/dist/node-dev/cart-constants.mjs.map +1 -1
- package/dist/node-dev/cart-hooks.js +43 -57
- package/dist/node-dev/cart-hooks.js.map +1 -1
- package/dist/node-dev/cart-hooks.mjs +42 -57
- package/dist/node-dev/cart-hooks.mjs.map +1 -1
- package/dist/node-dev/cart-queries.js +27 -56
- package/dist/node-dev/cart-queries.js.map +1 -1
- package/dist/node-dev/cart-queries.mjs +28 -66
- package/dist/node-dev/cart-queries.mjs.map +1 -1
- package/dist/node-dev/codegen.helpers.js +30 -18
- package/dist/node-dev/codegen.helpers.js.map +1 -1
- package/dist/node-dev/codegen.helpers.mjs +31 -20
- package/dist/node-dev/codegen.helpers.mjs.map +1 -1
- package/dist/node-dev/cookies-utils.js +45 -42
- package/dist/node-dev/cookies-utils.js.map +1 -1
- package/dist/node-dev/cookies-utils.mjs +44 -42
- package/dist/node-dev/cookies-utils.mjs.map +1 -1
- package/dist/node-dev/flatten-connection.js +22 -28
- package/dist/node-dev/flatten-connection.js.map +1 -1
- package/dist/node-dev/flatten-connection.mjs +23 -29
- package/dist/node-dev/flatten-connection.mjs.map +1 -1
- package/dist/node-dev/getProductOptions.js +248 -224
- package/dist/node-dev/getProductOptions.js.map +1 -1
- package/dist/node-dev/getProductOptions.mjs +248 -226
- package/dist/node-dev/getProductOptions.mjs.map +1 -1
- package/dist/node-dev/index.js +88 -90
- package/dist/node-dev/index.mjs +15 -70
- package/dist/node-dev/load-script.js +38 -48
- package/dist/node-dev/load-script.js.map +1 -1
- package/dist/node-dev/load-script.mjs +38 -49
- package/dist/node-dev/load-script.mjs.map +1 -1
- package/dist/node-dev/node_modules/.pnpm/@xstate_fsm@2.0.0/node_modules/@xstate/fsm/es/index.js +185 -124
- package/dist/node-dev/node_modules/.pnpm/@xstate_fsm@2.0.0/node_modules/@xstate/fsm/es/index.js.map +1 -1
- package/dist/node-dev/node_modules/.pnpm/@xstate_fsm@2.0.0/node_modules/@xstate/fsm/es/index.mjs +175 -123
- package/dist/node-dev/node_modules/.pnpm/@xstate_fsm@2.0.0/node_modules/@xstate/fsm/es/index.mjs.map +1 -1
- package/dist/node-dev/optionValueDecoder.js +103 -84
- package/dist/node-dev/optionValueDecoder.js.map +1 -1
- package/dist/node-dev/optionValueDecoder.mjs +104 -86
- package/dist/node-dev/optionValueDecoder.mjs.map +1 -1
- package/dist/node-dev/packages/hydrogen-react/package.js +6 -0
- package/dist/node-dev/packages/hydrogen-react/package.js.map +1 -0
- package/dist/node-dev/packages/hydrogen-react/package.mjs +6 -0
- package/dist/node-dev/packages/hydrogen-react/package.mjs.map +1 -0
- package/dist/node-dev/parse-metafield.js +122 -134
- package/dist/node-dev/parse-metafield.js.map +1 -1
- package/dist/node-dev/parse-metafield.mjs +122 -134
- package/dist/node-dev/parse-metafield.mjs.map +1 -1
- package/dist/node-dev/storefront-api-constants.js +5 -4
- package/dist/node-dev/storefront-api-constants.js.map +1 -1
- package/dist/node-dev/storefront-api-constants.mjs +6 -5
- package/dist/node-dev/storefront-api-constants.mjs.map +1 -1
- package/dist/node-dev/storefront-client.js +62 -101
- package/dist/node-dev/storefront-client.js.map +1 -1
- package/dist/node-dev/storefront-client.mjs +62 -102
- package/dist/node-dev/storefront-client.mjs.map +1 -1
- package/dist/node-dev/tracking-utils.js +67 -85
- package/dist/node-dev/tracking-utils.js.map +1 -1
- package/dist/node-dev/tracking-utils.mjs +68 -88
- package/dist/node-dev/tracking-utils.mjs.map +1 -1
- package/dist/node-dev/useCartAPIStateMachine.js +192 -349
- package/dist/node-dev/useCartAPIStateMachine.js.map +1 -1
- package/dist/node-dev/useCartAPIStateMachine.mjs +188 -346
- package/dist/node-dev/useCartAPIStateMachine.mjs.map +1 -1
- package/dist/node-dev/useCartActions.js +198 -172
- package/dist/node-dev/useCartActions.js.map +1 -1
- package/dist/node-dev/useCartActions.mjs +197 -172
- package/dist/node-dev/useCartActions.mjs.map +1 -1
- package/dist/node-dev/useMachine.js +50 -61
- package/dist/node-dev/useMachine.js.map +1 -1
- package/dist/node-dev/useMachine.mjs +50 -62
- package/dist/node-dev/useMachine.mjs.map +1 -1
- package/dist/node-dev/useMoney.js +177 -154
- package/dist/node-dev/useMoney.js.map +1 -1
- package/dist/node-dev/useMoney.mjs +176 -154
- package/dist/node-dev/useMoney.mjs.map +1 -1
- package/dist/node-dev/useSelectedOptionInUrlParam.js +18 -27
- package/dist/node-dev/useSelectedOptionInUrlParam.js.map +1 -1
- package/dist/node-dev/useSelectedOptionInUrlParam.mjs +17 -27
- package/dist/node-dev/useSelectedOptionInUrlParam.mjs.map +1 -1
- package/dist/node-dev/useShopifyCookies.js +124 -138
- package/dist/node-dev/useShopifyCookies.js.map +1 -1
- package/dist/node-dev/useShopifyCookies.mjs +123 -138
- package/dist/node-dev/useShopifyCookies.mjs.map +1 -1
- package/dist/node-prod/AddToCartButton.js +64 -73
- package/dist/node-prod/AddToCartButton.js.map +1 -1
- package/dist/node-prod/AddToCartButton.mjs +60 -71
- package/dist/node-prod/AddToCartButton.mjs.map +1 -1
- package/dist/node-prod/BaseButton.js +21 -26
- package/dist/node-prod/BaseButton.js.map +1 -1
- package/dist/node-prod/BaseButton.mjs +20 -26
- package/dist/node-prod/BaseButton.mjs.map +1 -1
- package/dist/node-prod/BuyNowButton.js +42 -46
- package/dist/node-prod/BuyNowButton.js.map +1 -1
- package/dist/node-prod/BuyNowButton.mjs +40 -45
- package/dist/node-prod/BuyNowButton.mjs.map +1 -1
- package/dist/node-prod/CartCheckoutButton.js +30 -24
- package/dist/node-prod/CartCheckoutButton.js.map +1 -1
- package/dist/node-prod/CartCheckoutButton.mjs +28 -23
- package/dist/node-prod/CartCheckoutButton.mjs.map +1 -1
- package/dist/node-prod/CartCost.js +27 -22
- package/dist/node-prod/CartCost.js.map +1 -1
- package/dist/node-prod/CartCost.mjs +26 -22
- package/dist/node-prod/CartCost.mjs.map +1 -1
- package/dist/node-prod/CartLineProvider.js +24 -17
- package/dist/node-prod/CartLineProvider.js.map +1 -1
- package/dist/node-prod/CartLineProvider.mjs +23 -18
- package/dist/node-prod/CartLineProvider.mjs.map +1 -1
- package/dist/node-prod/CartLineQuantity.js +19 -9
- package/dist/node-prod/CartLineQuantity.js.map +1 -1
- package/dist/node-prod/CartLineQuantity.mjs +18 -9
- package/dist/node-prod/CartLineQuantity.mjs.map +1 -1
- package/dist/node-prod/CartLineQuantityAdjustButton.js +50 -46
- package/dist/node-prod/CartLineQuantityAdjustButton.js.map +1 -1
- package/dist/node-prod/CartLineQuantityAdjustButton.mjs +48 -45
- package/dist/node-prod/CartLineQuantityAdjustButton.mjs.map +1 -1
- package/dist/node-prod/CartProvider.js +317 -385
- package/dist/node-prod/CartProvider.js.map +1 -1
- package/dist/node-prod/CartProvider.mjs +315 -385
- package/dist/node-prod/CartProvider.mjs.map +1 -1
- package/dist/node-prod/ExternalVideo.js +36 -47
- package/dist/node-prod/ExternalVideo.js.map +1 -1
- package/dist/node-prod/ExternalVideo.mjs +35 -47
- package/dist/node-prod/ExternalVideo.mjs.map +1 -1
- package/dist/node-prod/Image.js +328 -340
- package/dist/node-prod/Image.js.map +1 -1
- package/dist/node-prod/Image.mjs +326 -325
- package/dist/node-prod/Image.mjs.map +1 -1
- package/dist/node-prod/MediaFile.js +47 -65
- package/dist/node-prod/MediaFile.js.map +1 -1
- package/dist/node-prod/MediaFile.mjs +44 -63
- package/dist/node-prod/MediaFile.mjs.map +1 -1
- package/dist/node-prod/ModelViewer.js +118 -135
- package/dist/node-prod/ModelViewer.js.map +1 -1
- package/dist/node-prod/ModelViewer.mjs +117 -135
- package/dist/node-prod/ModelViewer.mjs.map +1 -1
- package/dist/node-prod/Money.js +54 -39
- package/dist/node-prod/Money.js.map +1 -1
- package/dist/node-prod/Money.mjs +53 -39
- package/dist/node-prod/Money.mjs.map +1 -1
- package/dist/node-prod/ProductPrice.js +45 -61
- package/dist/node-prod/ProductPrice.js.map +1 -1
- package/dist/node-prod/ProductPrice.mjs +44 -61
- package/dist/node-prod/ProductPrice.mjs.map +1 -1
- package/dist/node-prod/ProductProvider.js +148 -178
- package/dist/node-prod/ProductProvider.js.map +1 -1
- package/dist/node-prod/ProductProvider.mjs +147 -179
- package/dist/node-prod/ProductProvider.mjs.map +1 -1
- package/dist/node-prod/RichText.components.js +37 -46
- package/dist/node-prod/RichText.components.js.map +1 -1
- package/dist/node-prod/RichText.components.mjs +36 -46
- package/dist/node-prod/RichText.components.mjs.map +1 -1
- package/dist/node-prod/RichText.js +112 -154
- package/dist/node-prod/RichText.js.map +1 -1
- package/dist/node-prod/RichText.mjs +111 -154
- package/dist/node-prod/RichText.mjs.map +1 -1
- package/dist/node-prod/ShopPayButton.js +54 -81
- package/dist/node-prod/ShopPayButton.js.map +1 -1
- package/dist/node-prod/ShopPayButton.mjs +53 -81
- package/dist/node-prod/ShopPayButton.mjs.map +1 -1
- package/dist/node-prod/ShopifyProvider.js +73 -83
- package/dist/node-prod/ShopifyProvider.js.map +1 -1
- package/dist/node-prod/ShopifyProvider.mjs +71 -84
- package/dist/node-prod/ShopifyProvider.mjs.map +1 -1
- package/dist/node-prod/Video.js +36 -52
- package/dist/node-prod/Video.js.map +1 -1
- package/dist/node-prod/Video.mjs +35 -52
- package/dist/node-prod/Video.mjs.map +1 -1
- package/dist/node-prod/_virtual/_rolldown/runtime.js +23 -0
- package/dist/node-prod/analytics-constants.js +40 -39
- package/dist/node-prod/analytics-constants.js.map +1 -1
- package/dist/node-prod/analytics-constants.mjs +41 -43
- package/dist/node-prod/analytics-constants.mjs.map +1 -1
- package/dist/node-prod/analytics-schema-custom-storefront-customer-tracking.js +128 -210
- package/dist/node-prod/analytics-schema-custom-storefront-customer-tracking.js.map +1 -1
- package/dist/node-prod/analytics-schema-custom-storefront-customer-tracking.mjs +127 -214
- package/dist/node-prod/analytics-schema-custom-storefront-customer-tracking.mjs.map +1 -1
- package/dist/node-prod/analytics-schema-trekkie-storefront-page-view.js +40 -51
- package/dist/node-prod/analytics-schema-trekkie-storefront-page-view.js.map +1 -1
- package/dist/node-prod/analytics-schema-trekkie-storefront-page-view.mjs +39 -50
- package/dist/node-prod/analytics-schema-trekkie-storefront-page-view.mjs.map +1 -1
- package/dist/node-prod/analytics-utils.js +77 -52
- package/dist/node-prod/analytics-utils.js.map +1 -1
- package/dist/node-prod/analytics-utils.mjs +78 -56
- package/dist/node-prod/analytics-utils.mjs.map +1 -1
- package/dist/node-prod/analytics.js +113 -154
- package/dist/node-prod/analytics.js.map +1 -1
- package/dist/node-prod/analytics.mjs +111 -153
- package/dist/node-prod/analytics.mjs.map +1 -1
- package/dist/node-prod/cart-constants.js +10 -9
- package/dist/node-prod/cart-constants.js.map +1 -1
- package/dist/node-prod/cart-constants.mjs +11 -15
- package/dist/node-prod/cart-constants.mjs.map +1 -1
- package/dist/node-prod/cart-hooks.js +43 -57
- package/dist/node-prod/cart-hooks.js.map +1 -1
- package/dist/node-prod/cart-hooks.mjs +42 -57
- package/dist/node-prod/cart-hooks.mjs.map +1 -1
- package/dist/node-prod/cart-queries.js +27 -56
- package/dist/node-prod/cart-queries.js.map +1 -1
- package/dist/node-prod/cart-queries.mjs +28 -66
- package/dist/node-prod/cart-queries.mjs.map +1 -1
- package/dist/node-prod/codegen.helpers.js +30 -18
- package/dist/node-prod/codegen.helpers.js.map +1 -1
- package/dist/node-prod/codegen.helpers.mjs +31 -20
- package/dist/node-prod/codegen.helpers.mjs.map +1 -1
- package/dist/node-prod/cookies-utils.js +45 -42
- package/dist/node-prod/cookies-utils.js.map +1 -1
- package/dist/node-prod/cookies-utils.mjs +44 -42
- package/dist/node-prod/cookies-utils.mjs.map +1 -1
- package/dist/node-prod/flatten-connection.js +22 -24
- package/dist/node-prod/flatten-connection.js.map +1 -1
- package/dist/node-prod/flatten-connection.mjs +23 -25
- package/dist/node-prod/flatten-connection.mjs.map +1 -1
- package/dist/node-prod/getProductOptions.js +248 -224
- package/dist/node-prod/getProductOptions.js.map +1 -1
- package/dist/node-prod/getProductOptions.mjs +248 -226
- package/dist/node-prod/getProductOptions.mjs.map +1 -1
- package/dist/node-prod/index.js +88 -90
- package/dist/node-prod/index.mjs +15 -70
- package/dist/node-prod/load-script.js +38 -48
- package/dist/node-prod/load-script.js.map +1 -1
- package/dist/node-prod/load-script.mjs +38 -49
- package/dist/node-prod/load-script.mjs.map +1 -1
- package/dist/node-prod/node_modules/.pnpm/@xstate_fsm@2.0.0/node_modules/@xstate/fsm/es/index.js +185 -124
- package/dist/node-prod/node_modules/.pnpm/@xstate_fsm@2.0.0/node_modules/@xstate/fsm/es/index.js.map +1 -1
- package/dist/node-prod/node_modules/.pnpm/@xstate_fsm@2.0.0/node_modules/@xstate/fsm/es/index.mjs +175 -123
- package/dist/node-prod/node_modules/.pnpm/@xstate_fsm@2.0.0/node_modules/@xstate/fsm/es/index.mjs.map +1 -1
- package/dist/node-prod/optionValueDecoder.js +103 -84
- package/dist/node-prod/optionValueDecoder.js.map +1 -1
- package/dist/node-prod/optionValueDecoder.mjs +104 -86
- package/dist/node-prod/optionValueDecoder.mjs.map +1 -1
- package/dist/node-prod/packages/hydrogen-react/package.js +6 -0
- package/dist/node-prod/packages/hydrogen-react/package.js.map +1 -0
- package/dist/node-prod/packages/hydrogen-react/package.mjs +6 -0
- package/dist/node-prod/packages/hydrogen-react/package.mjs.map +1 -0
- package/dist/node-prod/parse-metafield.js +134 -146
- package/dist/node-prod/parse-metafield.js.map +1 -1
- package/dist/node-prod/parse-metafield.mjs +134 -146
- package/dist/node-prod/parse-metafield.mjs.map +1 -1
- package/dist/node-prod/storefront-api-constants.js +5 -4
- package/dist/node-prod/storefront-api-constants.js.map +1 -1
- package/dist/node-prod/storefront-api-constants.mjs +6 -5
- package/dist/node-prod/storefront-api-constants.mjs.map +1 -1
- package/dist/node-prod/storefront-client.js +56 -83
- package/dist/node-prod/storefront-client.js.map +1 -1
- package/dist/node-prod/storefront-client.mjs +56 -84
- package/dist/node-prod/storefront-client.mjs.map +1 -1
- package/dist/node-prod/tracking-utils.js +67 -85
- package/dist/node-prod/tracking-utils.js.map +1 -1
- package/dist/node-prod/tracking-utils.mjs +68 -88
- package/dist/node-prod/tracking-utils.mjs.map +1 -1
- package/dist/node-prod/useCartAPIStateMachine.js +192 -349
- package/dist/node-prod/useCartAPIStateMachine.js.map +1 -1
- package/dist/node-prod/useCartAPIStateMachine.mjs +188 -346
- package/dist/node-prod/useCartAPIStateMachine.mjs.map +1 -1
- package/dist/node-prod/useCartActions.js +198 -172
- package/dist/node-prod/useCartActions.js.map +1 -1
- package/dist/node-prod/useCartActions.mjs +197 -172
- package/dist/node-prod/useCartActions.mjs.map +1 -1
- package/dist/node-prod/useMachine.js +50 -61
- package/dist/node-prod/useMachine.js.map +1 -1
- package/dist/node-prod/useMachine.mjs +50 -62
- package/dist/node-prod/useMachine.mjs.map +1 -1
- package/dist/node-prod/useMoney.js +177 -154
- package/dist/node-prod/useMoney.js.map +1 -1
- package/dist/node-prod/useMoney.mjs +176 -154
- package/dist/node-prod/useMoney.mjs.map +1 -1
- package/dist/node-prod/useSelectedOptionInUrlParam.js +18 -27
- package/dist/node-prod/useSelectedOptionInUrlParam.js.map +1 -1
- package/dist/node-prod/useSelectedOptionInUrlParam.mjs +17 -27
- package/dist/node-prod/useSelectedOptionInUrlParam.mjs.map +1 -1
- package/dist/node-prod/useShopifyCookies.js +124 -138
- package/dist/node-prod/useShopifyCookies.js.map +1 -1
- package/dist/node-prod/useShopifyCookies.mjs +123 -138
- package/dist/node-prod/useShopifyCookies.mjs.map +1 -1
- package/dist/umd/hydrogen-react.dev.js +3930 -4418
- package/dist/umd/hydrogen-react.dev.js.map +1 -1
- package/dist/umd/hydrogen-react.prod.js +35 -49
- package/dist/umd/hydrogen-react.prod.js.map +1 -1
- package/package.json +5 -5
- package/dist/browser-dev/index.mjs.map +0 -1
- package/dist/browser-dev/packages/hydrogen-react/package.json.mjs +0 -5
- package/dist/browser-dev/packages/hydrogen-react/package.json.mjs.map +0 -1
- package/dist/browser-prod/index.mjs.map +0 -1
- package/dist/browser-prod/packages/hydrogen-react/package.json.mjs +0 -5
- package/dist/browser-prod/packages/hydrogen-react/package.json.mjs.map +0 -1
- package/dist/node-dev/index.js.map +0 -1
- package/dist/node-dev/index.mjs.map +0 -1
- package/dist/node-dev/packages/hydrogen-react/package.json.js +0 -5
- package/dist/node-dev/packages/hydrogen-react/package.json.js.map +0 -1
- package/dist/node-dev/packages/hydrogen-react/package.json.mjs +0 -5
- package/dist/node-dev/packages/hydrogen-react/package.json.mjs.map +0 -1
- package/dist/node-prod/index.js.map +0 -1
- package/dist/node-prod/index.mjs.map +0 -1
- package/dist/node-prod/packages/hydrogen-react/package.json.js +0 -5
- package/dist/node-prod/packages/hydrogen-react/package.json.js.map +0 -1
- package/dist/node-prod/packages/hydrogen-react/package.json.mjs +0 -5
- package/dist/node-prod/packages/hydrogen-react/package.json.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProductProvider.mjs","sources":["../../src/ProductProvider.tsx"],"sourcesContent":["import {\n useMemo,\n useState,\n useEffect,\n useCallback,\n createContext,\n useContext,\n} from 'react';\nimport type {\n SelectedOption as SelectedOptionType,\n SellingPlan,\n SellingPlanAllocation,\n Product,\n ProductVariant as ProductVariantType,\n ProductVariantConnection,\n SellingPlan as SellingPlanType,\n SellingPlanAllocation as SellingPlanAllocationType,\n SellingPlanGroup as SellingPlanGroupType,\n SellingPlanGroupConnection,\n} from './storefront-api-types.js';\nimport type {PartialDeep} from 'type-fest';\nimport {flattenConnection} from './flatten-connection.js';\n\nconst ProductOptionsContext = createContext<ProductHookValue | null>(null);\n\ntype InitialVariantId = ProductVariantType['id'] | null;\n\ninterface ProductProviderProps {\n /** A Storefront API [Product object](https://shopify.dev/api/storefront/reference/products/product). */\n data: PartialDeep<Product, {recurseIntoArrays: true}>;\n /** A `ReactNode` element. */\n children: React.ReactNode;\n /**\n * The initially selected variant.\n * The following logic applies to `initialVariantId`:\n * 1. If `initialVariantId` is provided, then it's used even if it's out of stock.\n * 2. If `initialVariantId` is provided but is `null`, then no variant is used.\n * 3. If nothing is passed to `initialVariantId` then the first available / in-stock variant is used.\n * 4. If nothing is passed to `initialVariantId` and no variants are in stock, then the first variant is used.\n */\n initialVariantId?: InitialVariantId;\n}\n\n/**\n * `<ProductProvider />` is a context provider that enables use of the `useProduct()` hook.\n *\n * It helps manage selected options and variants for a product.\n * @publicDocs\n */\nexport function ProductProvider({\n children,\n data: product,\n initialVariantId: explicitVariantId,\n}: ProductProviderProps): JSX.Element {\n // The flattened variants\n const variants = useMemo(\n () => flattenConnection(product.variants ?? {}),\n [product.variants],\n );\n\n if (!isProductVariantArray(variants)) {\n throw new Error(\n `<ProductProvider/> requires 'product.variants.nodes' or 'product.variants.edges'`,\n );\n }\n\n // All the options available for a product, based on all the variants\n const options = useMemo(() => getOptions(variants), [variants]);\n\n /**\n * Track the selectedVariant within the provider.\n */\n const [selectedVariant, setSelectedVariant] = useState<\n | PartialDeep<ProductVariantType, {recurseIntoArrays: true}>\n | undefined\n | null\n >(() => getVariantBasedOnIdProp(explicitVariantId, variants));\n\n /**\n * Track the selectedOptions within the provider. If a `initialVariantId`\n * is passed, use that to select initial options.\n */\n const [selectedOptions, setSelectedOptions] = useState<SelectedOptions>(() =>\n getSelectedOptions(selectedVariant),\n );\n\n /**\n * When the initialVariantId changes, we need to make sure we\n * update the selected variant and selected options. If not,\n * then the selected variant and options will reference incorrect\n * values.\n */\n useEffect(() => {\n const newSelectedVariant = getVariantBasedOnIdProp(\n explicitVariantId,\n variants,\n );\n setSelectedVariant(newSelectedVariant);\n setSelectedOptions(getSelectedOptions(newSelectedVariant));\n }, [explicitVariantId, variants]);\n\n /**\n * Allow the developer to select an option.\n */\n const setSelectedOption = useCallback(\n (name: string, value: string) => {\n setSelectedOptions((selectedOptions) => {\n const opts = {...selectedOptions, [name]: value};\n setSelectedVariant(getSelectedVariant(variants, opts));\n return opts;\n });\n },\n [setSelectedOptions, variants],\n );\n\n const isOptionInStock = useCallback(\n (option: string, value: string) => {\n const proposedVariant = getSelectedVariant(variants, {\n ...selectedOptions,\n ...{[option]: value},\n });\n\n return proposedVariant?.availableForSale ?? true;\n },\n [selectedOptions, variants],\n );\n\n const sellingPlanGroups = useMemo(\n () =>\n flattenConnection(product.sellingPlanGroups ?? {}).map(\n (sellingPlanGroup) => ({\n ...sellingPlanGroup,\n sellingPlans: flattenConnection(sellingPlanGroup?.sellingPlans ?? {}),\n }),\n ),\n [product.sellingPlanGroups],\n );\n\n /**\n * Track the selectedSellingPlan within the hook. If `initialSellingPlanId`\n * is passed, use that as an initial value. Look it up from the `selectedVariant`, since\n * that is also a requirement.\n */\n const [selectedSellingPlan, setSelectedSellingPlan] = useState<\n PartialDeep<SellingPlan, {recurseIntoArrays: true}> | undefined\n >(undefined);\n\n const selectedSellingPlanAllocation = useMemo<\n PartialDeep<SellingPlanAllocation, {recurseIntoArrays: true}> | undefined\n >(() => {\n if (!selectedVariant || !selectedSellingPlan) {\n return;\n }\n\n if (\n !selectedVariant.sellingPlanAllocations?.nodes &&\n !selectedVariant.sellingPlanAllocations?.edges\n ) {\n throw new Error(\n `<ProductProvider/>: You must include 'sellingPlanAllocations.nodes' or 'sellingPlanAllocations.edges' in your variants in order to calculate selectedSellingPlanAllocation`,\n );\n }\n\n return flattenConnection(selectedVariant.sellingPlanAllocations).find(\n (allocation) => allocation?.sellingPlan?.id === selectedSellingPlan.id,\n );\n }, [selectedVariant, selectedSellingPlan]);\n\n const value = useMemo<ProductHookValue>(\n () => ({\n product,\n variants,\n variantsConnection: product.variants,\n options,\n selectedVariant,\n setSelectedVariant,\n selectedOptions,\n setSelectedOption,\n setSelectedOptions,\n isOptionInStock,\n selectedSellingPlan,\n setSelectedSellingPlan,\n selectedSellingPlanAllocation,\n sellingPlanGroups,\n sellingPlanGroupsConnection: product.sellingPlanGroups,\n }),\n [\n product,\n isOptionInStock,\n options,\n selectedOptions,\n selectedSellingPlan,\n selectedSellingPlanAllocation,\n selectedVariant,\n sellingPlanGroups,\n setSelectedOption,\n variants,\n ],\n );\n\n return (\n <ProductOptionsContext.Provider value={value}>\n {children}\n </ProductOptionsContext.Provider>\n );\n}\n\n/**\n * Provides access to the context value provided by `<ProductProvider />`. Must be a descendent of `<ProductProvider />`.\n * @publicDocs\n */\nexport function useProduct(): ProductHookValue {\n const context = useContext(ProductOptionsContext);\n\n if (!context) {\n throw new Error(`'useProduct' must be a child of <ProductProvider />`);\n }\n\n return context;\n}\n\nfunction getSelectedVariant(\n variants: PartialDeep<ProductVariantType, {recurseIntoArrays: true}>[],\n choices: SelectedOptions,\n): PartialDeep<ProductVariantType, {recurseIntoArrays: true}> | undefined {\n /**\n * Ensure the user has selected all the required options, not just some.\n */\n if (\n !variants.length ||\n variants?.[0]?.selectedOptions?.length !== Object.keys(choices).length\n ) {\n return;\n }\n\n return variants?.find((variant) => {\n return Object.entries(choices).every(([name, value]) => {\n return variant?.selectedOptions?.some(\n (option) => option?.name === name && option?.value === value,\n );\n });\n });\n}\n\nfunction getOptions(\n variants: PartialDeep<ProductVariantType, {recurseIntoArrays: true}>[],\n): OptionWithValues[] {\n const map = variants.reduce(\n (memo, variant) => {\n if (!variant.selectedOptions) {\n throw new Error(`'getOptions' requires 'variant.selectedOptions'`);\n }\n variant?.selectedOptions?.forEach((opt) => {\n memo[opt?.name ?? ''] = memo[opt?.name ?? ''] || new Set();\n memo[opt?.name ?? ''].add(opt?.value ?? '');\n });\n\n return memo;\n },\n {} as Record<string, Set<string>>,\n );\n\n return Object.keys(map).map((option) => {\n return {\n name: option,\n values: Array.from(map[option]),\n };\n });\n}\n\nfunction getVariantBasedOnIdProp(\n explicitVariantId: InitialVariantId | undefined,\n variants: Array<\n PartialDeep<ProductVariantType, {recurseIntoArrays: true}> | undefined\n >,\n):\n | PartialDeep<ProductVariantType, {recurseIntoArrays: true}>\n | undefined\n | null {\n // get the initial variant based on the logic outlined in the comments for 'initialVariantId' above\n // * 1. If `initialVariantId` is provided, then it's used even if it's out of stock.\n if (explicitVariantId) {\n const foundVariant = variants.find(\n (variant) => variant?.id === explicitVariantId,\n );\n if (!foundVariant) {\n console.warn(\n `<ProductProvider/> received a 'initialVariantId' prop, but could not actually find a variant with that ID`,\n );\n }\n return foundVariant;\n }\n // * 2. If `initialVariantId` is provided but is `null`, then no variant is used.\n if (explicitVariantId === null) {\n return null;\n }\n // * 3. If nothing is passed to `initialVariantId` then the first available / in-stock variant is used.\n // * 4. If nothing is passed to `initialVariantId` and no variants are in stock, then the first variant is used.\n if (explicitVariantId === undefined) {\n return variants.find((variant) => variant?.availableForSale) || variants[0];\n }\n}\n\nfunction getSelectedOptions(\n selectedVariant:\n | PartialDeep<ProductVariantType, {recurseIntoArrays: true}>\n | undefined\n | null,\n): SelectedOptions {\n return selectedVariant?.selectedOptions\n ? selectedVariant.selectedOptions.reduce<SelectedOptions>(\n (memo, optionSet) => {\n memo[optionSet?.name ?? ''] = optionSet?.value ?? '';\n return memo;\n },\n {},\n )\n : {};\n}\n\nfunction isProductVariantArray(\n maybeVariantArray:\n | (PartialDeep<ProductVariantType, {recurseIntoArrays: true}> | undefined)[]\n | undefined,\n): maybeVariantArray is PartialDeep<\n ProductVariantType,\n {recurseIntoArrays: true}\n>[] {\n if (!maybeVariantArray || !Array.isArray(maybeVariantArray)) {\n return false;\n }\n\n return true;\n}\n\nexport interface OptionWithValues {\n name: SelectedOptionType['name'];\n values: SelectedOptionType['value'][];\n}\n\ntype UseProductObjects = {\n /** The raw product from the Storefront API */\n product: Product;\n /** An array of the variant `nodes` from the `VariantConnection`. */\n variants: ProductVariantType[];\n variantsConnection?: ProductVariantConnection;\n /** An array of the product's options and values. */\n options: OptionWithValues[];\n /** The selected variant. */\n selectedVariant?: ProductVariantType | null;\n selectedOptions: SelectedOptions;\n /** The selected selling plan. */\n selectedSellingPlan?: SellingPlanType;\n /** The selected selling plan allocation. */\n selectedSellingPlanAllocation?: SellingPlanAllocationType;\n /** The selling plan groups. */\n sellingPlanGroups?: (Omit<SellingPlanGroupType, 'sellingPlans'> & {\n sellingPlans: SellingPlanType[];\n })[];\n sellingPlanGroupsConnection?: SellingPlanGroupConnection;\n};\n\ntype UseProductFunctions = {\n /** A callback to set the selected variant to the variant passed as an argument. */\n setSelectedVariant: (\n variant: PartialDeep<ProductVariantType, {recurseIntoArrays: true}> | null,\n ) => void;\n /** A callback to set the selected option. */\n setSelectedOption: (\n name: SelectedOptionType['name'],\n value: SelectedOptionType['value'],\n ) => void;\n /** A callback to set multiple selected options at once. */\n setSelectedOptions: (options: SelectedOptions) => void;\n /** A callback to set the selected selling plan to the one passed as an argument. */\n setSelectedSellingPlan: (\n sellingPlan: PartialDeep<SellingPlanType, {recurseIntoArrays: true}>,\n ) => void;\n /** A callback that returns a boolean indicating if the option is in stock. */\n isOptionInStock: (\n name: SelectedOptionType['name'],\n value: SelectedOptionType['value'],\n ) => boolean;\n};\n\ntype ProductHookValue = PartialDeep<\n UseProductObjects,\n {recurseIntoArrays: true}\n> &\n UseProductFunctions;\n\nexport type SelectedOptions = {\n [key: string]: string;\n};\n"],"names":["value","selectedOptions","_a"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ProductProvider.mjs","names":[],"sources":["../../src/ProductProvider.tsx"],"sourcesContent":["import {\n useMemo,\n useState,\n useEffect,\n useCallback,\n createContext,\n useContext,\n} from 'react';\nimport type {\n SelectedOption as SelectedOptionType,\n SellingPlan,\n SellingPlanAllocation,\n Product,\n ProductVariant as ProductVariantType,\n ProductVariantConnection,\n SellingPlan as SellingPlanType,\n SellingPlanAllocation as SellingPlanAllocationType,\n SellingPlanGroup as SellingPlanGroupType,\n SellingPlanGroupConnection,\n} from './storefront-api-types.js';\nimport type {PartialDeep} from 'type-fest';\nimport {flattenConnection} from './flatten-connection.js';\n\nconst ProductOptionsContext = createContext<ProductHookValue | null>(null);\n\ntype InitialVariantId = ProductVariantType['id'] | null;\n\ninterface ProductProviderProps {\n /** A Storefront API [Product object](https://shopify.dev/api/storefront/reference/products/product). */\n data: PartialDeep<Product, {recurseIntoArrays: true}>;\n /** A `ReactNode` element. */\n children: React.ReactNode;\n /**\n * The initially selected variant.\n * The following logic applies to `initialVariantId`:\n * 1. If `initialVariantId` is provided, then it's used even if it's out of stock.\n * 2. If `initialVariantId` is provided but is `null`, then no variant is used.\n * 3. If nothing is passed to `initialVariantId` then the first available / in-stock variant is used.\n * 4. If nothing is passed to `initialVariantId` and no variants are in stock, then the first variant is used.\n */\n initialVariantId?: InitialVariantId;\n}\n\n/**\n * `<ProductProvider />` is a context provider that enables use of the `useProduct()` hook.\n *\n * It helps manage selected options and variants for a product.\n * @publicDocs\n */\nexport function ProductProvider({\n children,\n data: product,\n initialVariantId: explicitVariantId,\n}: ProductProviderProps): JSX.Element {\n // The flattened variants\n const variants = useMemo(\n () => flattenConnection(product.variants ?? {}),\n [product.variants],\n );\n\n if (!isProductVariantArray(variants)) {\n throw new Error(\n `<ProductProvider/> requires 'product.variants.nodes' or 'product.variants.edges'`,\n );\n }\n\n // All the options available for a product, based on all the variants\n const options = useMemo(() => getOptions(variants), [variants]);\n\n /**\n * Track the selectedVariant within the provider.\n */\n const [selectedVariant, setSelectedVariant] = useState<\n | PartialDeep<ProductVariantType, {recurseIntoArrays: true}>\n | undefined\n | null\n >(() => getVariantBasedOnIdProp(explicitVariantId, variants));\n\n /**\n * Track the selectedOptions within the provider. If a `initialVariantId`\n * is passed, use that to select initial options.\n */\n const [selectedOptions, setSelectedOptions] = useState<SelectedOptions>(() =>\n getSelectedOptions(selectedVariant),\n );\n\n /**\n * When the initialVariantId changes, we need to make sure we\n * update the selected variant and selected options. If not,\n * then the selected variant and options will reference incorrect\n * values.\n */\n useEffect(() => {\n const newSelectedVariant = getVariantBasedOnIdProp(\n explicitVariantId,\n variants,\n );\n setSelectedVariant(newSelectedVariant);\n setSelectedOptions(getSelectedOptions(newSelectedVariant));\n }, [explicitVariantId, variants]);\n\n /**\n * Allow the developer to select an option.\n */\n const setSelectedOption = useCallback(\n (name: string, value: string) => {\n setSelectedOptions((selectedOptions) => {\n const opts = {...selectedOptions, [name]: value};\n setSelectedVariant(getSelectedVariant(variants, opts));\n return opts;\n });\n },\n [setSelectedOptions, variants],\n );\n\n const isOptionInStock = useCallback(\n (option: string, value: string) => {\n const proposedVariant = getSelectedVariant(variants, {\n ...selectedOptions,\n ...{[option]: value},\n });\n\n return proposedVariant?.availableForSale ?? true;\n },\n [selectedOptions, variants],\n );\n\n const sellingPlanGroups = useMemo(\n () =>\n flattenConnection(product.sellingPlanGroups ?? {}).map(\n (sellingPlanGroup) => ({\n ...sellingPlanGroup,\n sellingPlans: flattenConnection(sellingPlanGroup?.sellingPlans ?? {}),\n }),\n ),\n [product.sellingPlanGroups],\n );\n\n /**\n * Track the selectedSellingPlan within the hook. If `initialSellingPlanId`\n * is passed, use that as an initial value. Look it up from the `selectedVariant`, since\n * that is also a requirement.\n */\n const [selectedSellingPlan, setSelectedSellingPlan] = useState<\n PartialDeep<SellingPlan, {recurseIntoArrays: true}> | undefined\n >(undefined);\n\n const selectedSellingPlanAllocation = useMemo<\n PartialDeep<SellingPlanAllocation, {recurseIntoArrays: true}> | undefined\n >(() => {\n if (!selectedVariant || !selectedSellingPlan) {\n return;\n }\n\n if (\n !selectedVariant.sellingPlanAllocations?.nodes &&\n !selectedVariant.sellingPlanAllocations?.edges\n ) {\n throw new Error(\n `<ProductProvider/>: You must include 'sellingPlanAllocations.nodes' or 'sellingPlanAllocations.edges' in your variants in order to calculate selectedSellingPlanAllocation`,\n );\n }\n\n return flattenConnection(selectedVariant.sellingPlanAllocations).find(\n (allocation) => allocation?.sellingPlan?.id === selectedSellingPlan.id,\n );\n }, [selectedVariant, selectedSellingPlan]);\n\n const value = useMemo<ProductHookValue>(\n () => ({\n product,\n variants,\n variantsConnection: product.variants,\n options,\n selectedVariant,\n setSelectedVariant,\n selectedOptions,\n setSelectedOption,\n setSelectedOptions,\n isOptionInStock,\n selectedSellingPlan,\n setSelectedSellingPlan,\n selectedSellingPlanAllocation,\n sellingPlanGroups,\n sellingPlanGroupsConnection: product.sellingPlanGroups,\n }),\n [\n product,\n isOptionInStock,\n options,\n selectedOptions,\n selectedSellingPlan,\n selectedSellingPlanAllocation,\n selectedVariant,\n sellingPlanGroups,\n setSelectedOption,\n variants,\n ],\n );\n\n return (\n <ProductOptionsContext.Provider value={value}>\n {children}\n </ProductOptionsContext.Provider>\n );\n}\n\n/**\n * Provides access to the context value provided by `<ProductProvider />`. Must be a descendent of `<ProductProvider />`.\n * @publicDocs\n */\nexport function useProduct(): ProductHookValue {\n const context = useContext(ProductOptionsContext);\n\n if (!context) {\n throw new Error(`'useProduct' must be a child of <ProductProvider />`);\n }\n\n return context;\n}\n\nfunction getSelectedVariant(\n variants: PartialDeep<ProductVariantType, {recurseIntoArrays: true}>[],\n choices: SelectedOptions,\n): PartialDeep<ProductVariantType, {recurseIntoArrays: true}> | undefined {\n /**\n * Ensure the user has selected all the required options, not just some.\n */\n if (\n !variants.length ||\n variants?.[0]?.selectedOptions?.length !== Object.keys(choices).length\n ) {\n return;\n }\n\n return variants?.find((variant) => {\n return Object.entries(choices).every(([name, value]) => {\n return variant?.selectedOptions?.some(\n (option) => option?.name === name && option?.value === value,\n );\n });\n });\n}\n\nfunction getOptions(\n variants: PartialDeep<ProductVariantType, {recurseIntoArrays: true}>[],\n): OptionWithValues[] {\n const map = variants.reduce(\n (memo, variant) => {\n if (!variant.selectedOptions) {\n throw new Error(`'getOptions' requires 'variant.selectedOptions'`);\n }\n variant?.selectedOptions?.forEach((opt) => {\n memo[opt?.name ?? ''] = memo[opt?.name ?? ''] || new Set();\n memo[opt?.name ?? ''].add(opt?.value ?? '');\n });\n\n return memo;\n },\n {} as Record<string, Set<string>>,\n );\n\n return Object.keys(map).map((option) => {\n return {\n name: option,\n values: Array.from(map[option]),\n };\n });\n}\n\nfunction getVariantBasedOnIdProp(\n explicitVariantId: InitialVariantId | undefined,\n variants: Array<\n PartialDeep<ProductVariantType, {recurseIntoArrays: true}> | undefined\n >,\n):\n | PartialDeep<ProductVariantType, {recurseIntoArrays: true}>\n | undefined\n | null {\n // get the initial variant based on the logic outlined in the comments for 'initialVariantId' above\n // * 1. If `initialVariantId` is provided, then it's used even if it's out of stock.\n if (explicitVariantId) {\n const foundVariant = variants.find(\n (variant) => variant?.id === explicitVariantId,\n );\n if (!foundVariant) {\n console.warn(\n `<ProductProvider/> received a 'initialVariantId' prop, but could not actually find a variant with that ID`,\n );\n }\n return foundVariant;\n }\n // * 2. If `initialVariantId` is provided but is `null`, then no variant is used.\n if (explicitVariantId === null) {\n return null;\n }\n // * 3. If nothing is passed to `initialVariantId` then the first available / in-stock variant is used.\n // * 4. If nothing is passed to `initialVariantId` and no variants are in stock, then the first variant is used.\n if (explicitVariantId === undefined) {\n return variants.find((variant) => variant?.availableForSale) || variants[0];\n }\n}\n\nfunction getSelectedOptions(\n selectedVariant:\n | PartialDeep<ProductVariantType, {recurseIntoArrays: true}>\n | undefined\n | null,\n): SelectedOptions {\n return selectedVariant?.selectedOptions\n ? selectedVariant.selectedOptions.reduce<SelectedOptions>(\n (memo, optionSet) => {\n memo[optionSet?.name ?? ''] = optionSet?.value ?? '';\n return memo;\n },\n {},\n )\n : {};\n}\n\nfunction isProductVariantArray(\n maybeVariantArray:\n | (PartialDeep<ProductVariantType, {recurseIntoArrays: true}> | undefined)[]\n | undefined,\n): maybeVariantArray is PartialDeep<\n ProductVariantType,\n {recurseIntoArrays: true}\n>[] {\n if (!maybeVariantArray || !Array.isArray(maybeVariantArray)) {\n return false;\n }\n\n return true;\n}\n\nexport interface OptionWithValues {\n name: SelectedOptionType['name'];\n values: SelectedOptionType['value'][];\n}\n\ntype UseProductObjects = {\n /** The raw product from the Storefront API */\n product: Product;\n /** An array of the variant `nodes` from the `VariantConnection`. */\n variants: ProductVariantType[];\n variantsConnection?: ProductVariantConnection;\n /** An array of the product's options and values. */\n options: OptionWithValues[];\n /** The selected variant. */\n selectedVariant?: ProductVariantType | null;\n selectedOptions: SelectedOptions;\n /** The selected selling plan. */\n selectedSellingPlan?: SellingPlanType;\n /** The selected selling plan allocation. */\n selectedSellingPlanAllocation?: SellingPlanAllocationType;\n /** The selling plan groups. */\n sellingPlanGroups?: (Omit<SellingPlanGroupType, 'sellingPlans'> & {\n sellingPlans: SellingPlanType[];\n })[];\n sellingPlanGroupsConnection?: SellingPlanGroupConnection;\n};\n\ntype UseProductFunctions = {\n /** A callback to set the selected variant to the variant passed as an argument. */\n setSelectedVariant: (\n variant: PartialDeep<ProductVariantType, {recurseIntoArrays: true}> | null,\n ) => void;\n /** A callback to set the selected option. */\n setSelectedOption: (\n name: SelectedOptionType['name'],\n value: SelectedOptionType['value'],\n ) => void;\n /** A callback to set multiple selected options at once. */\n setSelectedOptions: (options: SelectedOptions) => void;\n /** A callback to set the selected selling plan to the one passed as an argument. */\n setSelectedSellingPlan: (\n sellingPlan: PartialDeep<SellingPlanType, {recurseIntoArrays: true}>,\n ) => void;\n /** A callback that returns a boolean indicating if the option is in stock. */\n isOptionInStock: (\n name: SelectedOptionType['name'],\n value: SelectedOptionType['value'],\n ) => boolean;\n};\n\ntype ProductHookValue = PartialDeep<\n UseProductObjects,\n {recurseIntoArrays: true}\n> &\n UseProductFunctions;\n\nexport type SelectedOptions = {\n [key: string]: string;\n};\n"],"mappings":"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"}
|
|
@@ -1,55 +1,45 @@
|
|
|
1
|
-
import { jsx } from "react/jsx-runtime";
|
|
2
1
|
import { createElement } from "react";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
//#region src/RichText.components.tsx
|
|
4
|
+
var RichTextComponents = {
|
|
5
|
+
root: Root,
|
|
6
|
+
heading: Heading,
|
|
7
|
+
paragraph: Paragraph,
|
|
8
|
+
text: Text,
|
|
9
|
+
link: RichTextLink,
|
|
10
|
+
list: List,
|
|
11
|
+
"list-item": ListItem
|
|
11
12
|
};
|
|
12
|
-
function Root({
|
|
13
|
-
|
|
14
|
-
}) {
|
|
15
|
-
return /* @__PURE__ */ jsx("div", { children: node.children });
|
|
13
|
+
function Root({ node }) {
|
|
14
|
+
return /* @__PURE__ */ jsx("div", { children: node.children });
|
|
16
15
|
}
|
|
17
|
-
function Heading({
|
|
18
|
-
|
|
19
|
-
}) {
|
|
20
|
-
return createElement(`h${node.level ?? "1"}`, null, node.children);
|
|
16
|
+
function Heading({ node }) {
|
|
17
|
+
return createElement(`h${node.level ?? "1"}`, null, node.children);
|
|
21
18
|
}
|
|
22
|
-
function Paragraph({
|
|
23
|
-
|
|
24
|
-
}) {
|
|
25
|
-
return /* @__PURE__ */ jsx("p", { children: node.children });
|
|
19
|
+
function Paragraph({ node }) {
|
|
20
|
+
return /* @__PURE__ */ jsx("p", { children: node.children });
|
|
26
21
|
}
|
|
27
|
-
function Text({
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (node.bold) return /* @__PURE__ */ jsx("strong", { children: node.value });
|
|
33
|
-
if (node.italic) return /* @__PURE__ */ jsx("em", { children: node.value });
|
|
34
|
-
return node.value;
|
|
22
|
+
function Text({ node }) {
|
|
23
|
+
if (node.bold && node.italic) return /* @__PURE__ */ jsx("em", { children: /* @__PURE__ */ jsx("strong", { children: node.value }) });
|
|
24
|
+
if (node.bold) return /* @__PURE__ */ jsx("strong", { children: node.value });
|
|
25
|
+
if (node.italic) return /* @__PURE__ */ jsx("em", { children: node.value });
|
|
26
|
+
return node.value;
|
|
35
27
|
}
|
|
36
|
-
function RichTextLink({
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
function RichTextLink({ node }) {
|
|
29
|
+
return /* @__PURE__ */ jsx("a", {
|
|
30
|
+
href: node.url,
|
|
31
|
+
title: node.title,
|
|
32
|
+
target: node.target,
|
|
33
|
+
children: node.children
|
|
34
|
+
});
|
|
40
35
|
}
|
|
41
|
-
function List({
|
|
42
|
-
|
|
43
|
-
}) {
|
|
44
|
-
const List2 = node.listType === "unordered" ? "ul" : "ol";
|
|
45
|
-
return /* @__PURE__ */ jsx(List2, { children: node.children });
|
|
36
|
+
function List({ node }) {
|
|
37
|
+
return /* @__PURE__ */ jsx(node.listType === "unordered" ? "ul" : "ol", { children: node.children });
|
|
46
38
|
}
|
|
47
|
-
function ListItem({
|
|
48
|
-
|
|
49
|
-
}) {
|
|
50
|
-
return /* @__PURE__ */ jsx("li", { children: node.children });
|
|
39
|
+
function ListItem({ node }) {
|
|
40
|
+
return /* @__PURE__ */ jsx("li", { children: node.children });
|
|
51
41
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
//# sourceMappingURL=RichText.components.mjs.map
|
|
42
|
+
//#endregion
|
|
43
|
+
export { RichTextComponents };
|
|
44
|
+
|
|
45
|
+
//# sourceMappingURL=RichText.components.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RichText.components.mjs","sources":["../../src/RichText.components.tsx"],"sourcesContent":["import {createElement, type ReactNode} from 'react';\n\nexport type CustomComponents = {\n /** The root node of the rich text. Defaults to `<div>` */\n root?: typeof Root;\n /** Customize the headings. Each heading has a `level` property from 1-6. Defaults to `<h1>` to `<h6>` */\n heading?: typeof Heading;\n /** Customize paragraphs. Defaults to `<p>` */\n paragraph?: typeof Paragraph;\n /** Customize how text nodes. They can either be bold or italic. Defaults to `<em>`, `<strong>` or text. */\n text?: typeof Text;\n /** Customize links. Defaults to a React Router `<Link>` component in Hydrogen and a `<a>` in Hydrogen React. */\n link?: typeof RichTextLink;\n /** Customize lists. They can be either ordered or unordered. Defaults to `<ol>` or `<ul>` */\n list?: typeof List;\n /** Customize list items. Defaults to `<li>`. */\n listItem?: typeof ListItem;\n};\n\nexport const RichTextComponents = {\n root: Root,\n heading: Heading,\n paragraph: Paragraph,\n text: Text,\n link: RichTextLink,\n list: List,\n 'list-item': ListItem,\n};\n\nfunction Root({\n node,\n}: {\n node: {\n type: 'root';\n children?: ReactNode[];\n };\n}): ReactNode {\n return <div>{node.children}</div>;\n}\n\nfunction Heading({\n node,\n}: {\n node: {\n type: 'heading';\n level: number;\n children?: ReactNode[];\n };\n}): ReactNode {\n return createElement(`h${node.level ?? '1'}`, null, node.children);\n}\n\nfunction Paragraph({\n node,\n}: {\n node: {\n type: 'paragraph';\n children?: ReactNode[];\n };\n}): ReactNode {\n return <p>{node.children}</p>;\n}\n\nfunction Text({\n node,\n}: {\n node: {\n type: 'text';\n italic?: boolean;\n bold?: boolean;\n value?: string;\n };\n}): ReactNode {\n if (node.bold && node.italic)\n return (\n <em>\n <strong>{node.value}</strong>\n </em>\n );\n\n if (node.bold) return <strong>{node.value}</strong>;\n if (node.italic) return <em>{node.value}</em>;\n\n return node.value;\n}\n\nfunction RichTextLink({\n node,\n}: {\n node: {\n type: 'link';\n url: string;\n title?: string;\n target?: string;\n children?: ReactNode[];\n };\n}): ReactNode {\n return (\n <a href={node.url} title={node.title} target={node.target}>\n {node.children}\n </a>\n );\n}\n\nfunction List({\n node,\n}: {\n node: {\n type: 'list';\n listType: 'unordered' | 'ordered';\n children?: ReactNode[];\n };\n}): ReactNode {\n const List = node.listType === 'unordered' ? 'ul' : 'ol';\n return <List>{node.children}</List>;\n}\n\nfunction ListItem({\n node,\n}: {\n node: {\n type: 'list-item';\n children?: ReactNode[];\n };\n}): ReactNode {\n return <li>{node.children}</li>;\n}\n"],"
|
|
1
|
+
{"version":3,"file":"RichText.components.mjs","names":[],"sources":["../../src/RichText.components.tsx"],"sourcesContent":["import {createElement, type ReactNode} from 'react';\n\nexport type CustomComponents = {\n /** The root node of the rich text. Defaults to `<div>` */\n root?: typeof Root;\n /** Customize the headings. Each heading has a `level` property from 1-6. Defaults to `<h1>` to `<h6>` */\n heading?: typeof Heading;\n /** Customize paragraphs. Defaults to `<p>` */\n paragraph?: typeof Paragraph;\n /** Customize how text nodes. They can either be bold or italic. Defaults to `<em>`, `<strong>` or text. */\n text?: typeof Text;\n /** Customize links. Defaults to a React Router `<Link>` component in Hydrogen and a `<a>` in Hydrogen React. */\n link?: typeof RichTextLink;\n /** Customize lists. They can be either ordered or unordered. Defaults to `<ol>` or `<ul>` */\n list?: typeof List;\n /** Customize list items. Defaults to `<li>`. */\n listItem?: typeof ListItem;\n};\n\nexport const RichTextComponents = {\n root: Root,\n heading: Heading,\n paragraph: Paragraph,\n text: Text,\n link: RichTextLink,\n list: List,\n 'list-item': ListItem,\n};\n\nfunction Root({\n node,\n}: {\n node: {\n type: 'root';\n children?: ReactNode[];\n };\n}): ReactNode {\n return <div>{node.children}</div>;\n}\n\nfunction Heading({\n node,\n}: {\n node: {\n type: 'heading';\n level: number;\n children?: ReactNode[];\n };\n}): ReactNode {\n return createElement(`h${node.level ?? '1'}`, null, node.children);\n}\n\nfunction Paragraph({\n node,\n}: {\n node: {\n type: 'paragraph';\n children?: ReactNode[];\n };\n}): ReactNode {\n return <p>{node.children}</p>;\n}\n\nfunction Text({\n node,\n}: {\n node: {\n type: 'text';\n italic?: boolean;\n bold?: boolean;\n value?: string;\n };\n}): ReactNode {\n if (node.bold && node.italic)\n return (\n <em>\n <strong>{node.value}</strong>\n </em>\n );\n\n if (node.bold) return <strong>{node.value}</strong>;\n if (node.italic) return <em>{node.value}</em>;\n\n return node.value;\n}\n\nfunction RichTextLink({\n node,\n}: {\n node: {\n type: 'link';\n url: string;\n title?: string;\n target?: string;\n children?: ReactNode[];\n };\n}): ReactNode {\n return (\n <a href={node.url} title={node.title} target={node.target}>\n {node.children}\n </a>\n );\n}\n\nfunction List({\n node,\n}: {\n node: {\n type: 'list';\n listType: 'unordered' | 'ordered';\n children?: ReactNode[];\n };\n}): ReactNode {\n const List = node.listType === 'unordered' ? 'ul' : 'ol';\n return <List>{node.children}</List>;\n}\n\nfunction ListItem({\n node,\n}: {\n node: {\n type: 'list-item';\n children?: ReactNode[];\n };\n}): ReactNode {\n return <li>{node.children}</li>;\n}\n"],"mappings":";;;AAmBA,IAAa,qBAAqB;CAChC,MAAM;CACN,SAAS;CACT,WAAW;CACX,MAAM;CACN,MAAM;CACN,MAAM;CACN,aAAa;CACd;AAED,SAAS,KAAK,EACZ,QAMY;AACZ,QAAO,oBAAC,OAAD,EAAA,UAAM,KAAK,UAAe,CAAA;;AAGnC,SAAS,QAAQ,EACf,QAOY;AACZ,QAAO,cAAc,IAAI,KAAK,SAAS,OAAO,MAAM,KAAK,SAAS;;AAGpE,SAAS,UAAU,EACjB,QAMY;AACZ,QAAO,oBAAC,KAAD,EAAA,UAAI,KAAK,UAAa,CAAA;;AAG/B,SAAS,KAAK,EACZ,QAQY;AACZ,KAAI,KAAK,QAAQ,KAAK,OACpB,QACE,oBAAC,MAAD,EAAA,UACE,oBAAC,UAAD,EAAA,UAAS,KAAK,OAAe,CAAA,EAC1B,CAAA;AAGT,KAAI,KAAK,KAAM,QAAO,oBAAC,UAAD,EAAA,UAAS,KAAK,OAAe,CAAA;AACnD,KAAI,KAAK,OAAQ,QAAO,oBAAC,MAAD,EAAA,UAAK,KAAK,OAAW,CAAA;AAE7C,QAAO,KAAK;;AAGd,SAAS,aAAa,EACpB,QASY;AACZ,QACE,oBAAC,KAAD;EAAG,MAAM,KAAK;EAAK,OAAO,KAAK;EAAO,QAAQ,KAAK;YAChD,KAAK;EACJ,CAAA;;AAIR,SAAS,KAAK,EACZ,QAOY;AAEZ,QAAO,oBADM,KAAK,aAAa,cAAc,OAAO,MAC7C,EAAA,UAAO,KAAK,UAAgB,CAAA;;AAGrC,SAAS,SAAS,EAChB,QAMY;AACZ,QAAO,oBAAC,MAAD,EAAA,UAAK,KAAK,UAAc,CAAA"}
|
|
@@ -1,160 +1,117 @@
|
|
|
1
|
-
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useMemo, createElement, Fragment } from "react";
|
|
3
1
|
import { RichTextComponents } from "./RichText.components.mjs";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
throw new Error(
|
|
20
|
-
"[h2:error:RichText] Parsing error. Make sure to pass a JSON string of rich text metafield",
|
|
21
|
-
{
|
|
22
|
-
cause: e
|
|
23
|
-
}
|
|
24
|
-
);
|
|
25
|
-
}
|
|
2
|
+
import { Fragment, createElement, useMemo } from "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
//#region src/RichText.tsx
|
|
5
|
+
/** @publicDocs */
|
|
6
|
+
function RichText({ as, data, plain, components, ...passthroughProps }) {
|
|
7
|
+
try {
|
|
8
|
+
const Wrapper = as ?? "div";
|
|
9
|
+
const parsedData = useMemo(() => JSON.parse(data), [data]);
|
|
10
|
+
return /* @__PURE__ */ jsx(Wrapper, {
|
|
11
|
+
...passthroughProps,
|
|
12
|
+
children: plain ? richTextToString(parsedData) : serializeRichTextASTNode(components, parsedData)
|
|
13
|
+
});
|
|
14
|
+
} catch (e) {
|
|
15
|
+
throw new Error("[h2:error:RichText] Parsing error. Make sure to pass a JSON string of rich text metafield", { cause: e });
|
|
16
|
+
}
|
|
26
17
|
}
|
|
27
18
|
function serializeRichTextASTNode(components = {}, node, index = 0) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
url: node.url,
|
|
97
|
-
title: node.title,
|
|
98
|
-
target: node.target,
|
|
99
|
-
children
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
);
|
|
103
|
-
case "list":
|
|
104
|
-
return createElement(
|
|
105
|
-
Component,
|
|
106
|
-
{
|
|
107
|
-
key: index,
|
|
108
|
-
node: {
|
|
109
|
-
type: "list",
|
|
110
|
-
listType: node.listType,
|
|
111
|
-
children
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
);
|
|
115
|
-
case "list-item":
|
|
116
|
-
return createElement(
|
|
117
|
-
Component,
|
|
118
|
-
{
|
|
119
|
-
key: index,
|
|
120
|
-
node: {
|
|
121
|
-
type: "list-item",
|
|
122
|
-
children
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
);
|
|
126
|
-
}
|
|
19
|
+
let children;
|
|
20
|
+
if ("children" in node) children = node.children.map((child, childIndex) => serializeRichTextASTNode(components, child, childIndex));
|
|
21
|
+
const Component = components[node.type === "list-item" ? "listItem" : node.type] ?? RichTextComponents[node.type];
|
|
22
|
+
switch (node.type) {
|
|
23
|
+
case "root": return createElement(Component, {
|
|
24
|
+
key: index,
|
|
25
|
+
node: {
|
|
26
|
+
type: "root",
|
|
27
|
+
children
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
case "heading": return createElement(Component, {
|
|
31
|
+
key: index,
|
|
32
|
+
node: {
|
|
33
|
+
type: "heading",
|
|
34
|
+
level: node.level,
|
|
35
|
+
children
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
case "paragraph": return createElement(Component, {
|
|
39
|
+
key: index,
|
|
40
|
+
node: {
|
|
41
|
+
type: "paragraph",
|
|
42
|
+
children
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
case "text": {
|
|
46
|
+
const elements = (node.value ?? "").split("\n").flatMap((value, subindex) => {
|
|
47
|
+
const key = `${index}-${value}-${subindex}`;
|
|
48
|
+
const textElement = createElement(Component, {
|
|
49
|
+
key,
|
|
50
|
+
node: {
|
|
51
|
+
type: "text",
|
|
52
|
+
italic: node.italic,
|
|
53
|
+
bold: node.bold,
|
|
54
|
+
value
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return subindex === 0 ? textElement : [createElement("br", { key: `${key}-br` }), textElement];
|
|
58
|
+
});
|
|
59
|
+
return elements.length > 1 ? createElement(Fragment, { key: index }, elements) : elements[0];
|
|
60
|
+
}
|
|
61
|
+
case "link": return createElement(Component, {
|
|
62
|
+
key: index,
|
|
63
|
+
node: {
|
|
64
|
+
type: "link",
|
|
65
|
+
url: node.url,
|
|
66
|
+
title: node.title,
|
|
67
|
+
target: node.target,
|
|
68
|
+
children
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
case "list": return createElement(Component, {
|
|
72
|
+
key: index,
|
|
73
|
+
node: {
|
|
74
|
+
type: "list",
|
|
75
|
+
listType: node.listType,
|
|
76
|
+
children
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
case "list-item": return createElement(Component, {
|
|
80
|
+
key: index,
|
|
81
|
+
node: {
|
|
82
|
+
type: "list-item",
|
|
83
|
+
children
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
127
87
|
}
|
|
128
88
|
function richTextToString(node, result = []) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
throw new Error(`Unknown node encountered ${node.type}`);
|
|
154
|
-
}
|
|
155
|
-
return result.join("").trim();
|
|
89
|
+
switch (node.type) {
|
|
90
|
+
case "root":
|
|
91
|
+
node.children.forEach((child) => richTextToString(child, result));
|
|
92
|
+
break;
|
|
93
|
+
case "heading":
|
|
94
|
+
case "paragraph":
|
|
95
|
+
node.children.forEach((child) => richTextToString(child, result));
|
|
96
|
+
result.push(" ");
|
|
97
|
+
break;
|
|
98
|
+
case "text":
|
|
99
|
+
result.push(node.value || "");
|
|
100
|
+
break;
|
|
101
|
+
case "link":
|
|
102
|
+
node.children.forEach((child) => richTextToString(child, result));
|
|
103
|
+
break;
|
|
104
|
+
case "list":
|
|
105
|
+
node.children.forEach((item) => {
|
|
106
|
+
if (item.children) item.children.forEach((child) => richTextToString(child, result));
|
|
107
|
+
result.push(" ");
|
|
108
|
+
});
|
|
109
|
+
break;
|
|
110
|
+
default: throw new Error(`Unknown node encountered ${node.type}`);
|
|
111
|
+
}
|
|
112
|
+
return result.join("").trim();
|
|
156
113
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
//# sourceMappingURL=RichText.mjs.map
|
|
114
|
+
//#endregion
|
|
115
|
+
export { RichText };
|
|
116
|
+
|
|
117
|
+
//# sourceMappingURL=RichText.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RichText.mjs","sources":["../../src/RichText.tsx"],"sourcesContent":["import {createElement, Fragment, type ReactNode, useMemo} from 'react';\nimport type {RichTextASTNode} from './RichText.types.js';\nimport {\n type CustomComponents,\n RichTextComponents,\n} from './RichText.components.js';\n\nexport interface RichTextPropsBase<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 /** The JSON string that correspond to the Storefront API's [RichText format](https://shopify.dev/docs/apps/custom-data/metafields/types#rich-text-formatting). */\n data: string;\n /** Customize how rich text components are rendered */\n components?: CustomComponents;\n /** Remove rich text formatting and render plain text */\n plain?: boolean;\n}\n\n/** @publicDocs */\nexport function RichText<ComponentGeneric extends React.ElementType = 'div'>({\n as,\n data,\n plain,\n components,\n ...passthroughProps\n}: RichTextProps<ComponentGeneric>): JSX.Element {\n try {\n const Wrapper = as ?? 'div';\n const parsedData = useMemo(\n () => JSON.parse(data) as RichTextASTNode,\n [data],\n );\n\n return (\n <Wrapper {...passthroughProps}>\n {plain\n ? richTextToString(parsedData)\n : serializeRichTextASTNode(components, parsedData)}\n </Wrapper>\n );\n } catch (e) {\n throw new Error(\n '[h2:error:RichText] Parsing error. Make sure to pass a JSON string of rich text metafield',\n {\n cause: e,\n },\n );\n }\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 RichTextProps<ComponentGeneric extends React.ElementType> =\n RichTextPropsBase<ComponentGeneric> &\n Omit<\n React.ComponentPropsWithoutRef<ComponentGeneric>,\n keyof RichTextPropsBase<ComponentGeneric>\n >;\n\nfunction serializeRichTextASTNode(\n components: CustomComponents = {},\n node: RichTextASTNode,\n index = 0,\n): ReactNode {\n let children;\n if ('children' in node) {\n children = node.children.map((child, childIndex) =>\n serializeRichTextASTNode(components, child, childIndex),\n );\n }\n\n const Component =\n components[node.type === 'list-item' ? 'listItem' : node.type] ??\n RichTextComponents[node.type];\n\n switch (node.type) {\n case 'root':\n return createElement(\n Component as Exclude<CustomComponents['root'], undefined>,\n {\n key: index,\n node: {\n type: 'root',\n children,\n },\n },\n );\n case 'heading':\n return createElement(\n Component as Exclude<CustomComponents['heading'], undefined>,\n {\n key: index,\n node: {\n type: 'heading',\n level: node.level,\n children,\n },\n },\n );\n case 'paragraph':\n return createElement(\n Component as Exclude<CustomComponents['paragraph'], undefined>,\n {\n key: index,\n node: {\n type: 'paragraph',\n children,\n },\n },\n );\n case 'text': {\n const elements = (node.value ?? '')\n .split('\\n')\n .flatMap((value, subindex) => {\n const key = `${index}-${value}-${subindex}`;\n const textElement = createElement(\n Component as Exclude<CustomComponents['text'], undefined>,\n {\n key,\n node: {\n type: 'text',\n italic: node.italic,\n bold: node.bold,\n value,\n },\n },\n );\n\n // Add a `<br>` before each substring except the first one\n return subindex === 0\n ? textElement\n : [createElement('br', {key: `${key}-br`}), textElement];\n });\n\n return elements.length > 1\n ? createElement(Fragment, {key: index}, elements)\n : elements[0];\n }\n case 'link':\n return createElement(\n Component as Exclude<CustomComponents['link'], undefined>,\n {\n key: index,\n node: {\n type: 'link',\n url: node.url,\n title: node.title,\n target: node.target,\n children,\n },\n },\n );\n case 'list':\n return createElement(\n Component as Exclude<CustomComponents['list'], undefined>,\n {\n key: index,\n node: {\n type: 'list',\n listType: node.listType,\n children,\n },\n },\n );\n case 'list-item':\n return createElement(\n Component as Exclude<CustomComponents['listItem'], undefined>,\n {\n key: index,\n node: {\n type: 'list-item',\n children,\n },\n },\n );\n }\n}\n\nfunction richTextToString(\n node: RichTextASTNode,\n result: string[] = [],\n): string {\n switch (node.type) {\n case 'root':\n node.children.forEach((child) => richTextToString(child, result));\n break;\n case 'heading':\n case 'paragraph':\n node.children.forEach((child) => richTextToString(child, result));\n result.push(' ');\n break;\n case 'text':\n result.push(node.value || '');\n break;\n case 'link':\n node.children.forEach((child) => richTextToString(child, result));\n break;\n case 'list':\n node.children.forEach((item) => {\n if (item.children) {\n item.children.forEach((child) => richTextToString(child, result));\n }\n result.push(' ');\n });\n break;\n default:\n throw new Error(`Unknown node encountered ${node.type}`);\n }\n\n return result.join('').trim();\n}\n\n// This is only for documentation purposes, and it is not used in the code.\n/** @publicDocs */\nexport type RichTextPropsForDocs<AsType extends React.ElementType = 'div'> =\n RichTextPropsBase<AsType>;\n"],"
|
|
1
|
+
{"version":3,"file":"RichText.mjs","names":[],"sources":["../../src/RichText.tsx"],"sourcesContent":["import {createElement, Fragment, type ReactNode, useMemo} from 'react';\nimport type {RichTextASTNode} from './RichText.types.js';\nimport {\n type CustomComponents,\n RichTextComponents,\n} from './RichText.components.js';\n\nexport interface RichTextPropsBase<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 /** The JSON string that correspond to the Storefront API's [RichText format](https://shopify.dev/docs/apps/custom-data/metafields/types#rich-text-formatting). */\n data: string;\n /** Customize how rich text components are rendered */\n components?: CustomComponents;\n /** Remove rich text formatting and render plain text */\n plain?: boolean;\n}\n\n/** @publicDocs */\nexport function RichText<ComponentGeneric extends React.ElementType = 'div'>({\n as,\n data,\n plain,\n components,\n ...passthroughProps\n}: RichTextProps<ComponentGeneric>): JSX.Element {\n try {\n const Wrapper = as ?? 'div';\n const parsedData = useMemo(\n () => JSON.parse(data) as RichTextASTNode,\n [data],\n );\n\n return (\n <Wrapper {...passthroughProps}>\n {plain\n ? richTextToString(parsedData)\n : serializeRichTextASTNode(components, parsedData)}\n </Wrapper>\n );\n } catch (e) {\n throw new Error(\n '[h2:error:RichText] Parsing error. Make sure to pass a JSON string of rich text metafield',\n {\n cause: e,\n },\n );\n }\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 RichTextProps<ComponentGeneric extends React.ElementType> =\n RichTextPropsBase<ComponentGeneric> &\n Omit<\n React.ComponentPropsWithoutRef<ComponentGeneric>,\n keyof RichTextPropsBase<ComponentGeneric>\n >;\n\nfunction serializeRichTextASTNode(\n components: CustomComponents = {},\n node: RichTextASTNode,\n index = 0,\n): ReactNode {\n let children;\n if ('children' in node) {\n children = node.children.map((child, childIndex) =>\n serializeRichTextASTNode(components, child, childIndex),\n );\n }\n\n const Component =\n components[node.type === 'list-item' ? 'listItem' : node.type] ??\n RichTextComponents[node.type];\n\n switch (node.type) {\n case 'root':\n return createElement(\n Component as Exclude<CustomComponents['root'], undefined>,\n {\n key: index,\n node: {\n type: 'root',\n children,\n },\n },\n );\n case 'heading':\n return createElement(\n Component as Exclude<CustomComponents['heading'], undefined>,\n {\n key: index,\n node: {\n type: 'heading',\n level: node.level,\n children,\n },\n },\n );\n case 'paragraph':\n return createElement(\n Component as Exclude<CustomComponents['paragraph'], undefined>,\n {\n key: index,\n node: {\n type: 'paragraph',\n children,\n },\n },\n );\n case 'text': {\n const elements = (node.value ?? '')\n .split('\\n')\n .flatMap((value, subindex) => {\n const key = `${index}-${value}-${subindex}`;\n const textElement = createElement(\n Component as Exclude<CustomComponents['text'], undefined>,\n {\n key,\n node: {\n type: 'text',\n italic: node.italic,\n bold: node.bold,\n value,\n },\n },\n );\n\n // Add a `<br>` before each substring except the first one\n return subindex === 0\n ? textElement\n : [createElement('br', {key: `${key}-br`}), textElement];\n });\n\n return elements.length > 1\n ? createElement(Fragment, {key: index}, elements)\n : elements[0];\n }\n case 'link':\n return createElement(\n Component as Exclude<CustomComponents['link'], undefined>,\n {\n key: index,\n node: {\n type: 'link',\n url: node.url,\n title: node.title,\n target: node.target,\n children,\n },\n },\n );\n case 'list':\n return createElement(\n Component as Exclude<CustomComponents['list'], undefined>,\n {\n key: index,\n node: {\n type: 'list',\n listType: node.listType,\n children,\n },\n },\n );\n case 'list-item':\n return createElement(\n Component as Exclude<CustomComponents['listItem'], undefined>,\n {\n key: index,\n node: {\n type: 'list-item',\n children,\n },\n },\n );\n }\n}\n\nfunction richTextToString(\n node: RichTextASTNode,\n result: string[] = [],\n): string {\n switch (node.type) {\n case 'root':\n node.children.forEach((child) => richTextToString(child, result));\n break;\n case 'heading':\n case 'paragraph':\n node.children.forEach((child) => richTextToString(child, result));\n result.push(' ');\n break;\n case 'text':\n result.push(node.value || '');\n break;\n case 'link':\n node.children.forEach((child) => richTextToString(child, result));\n break;\n case 'list':\n node.children.forEach((item) => {\n if (item.children) {\n item.children.forEach((child) => richTextToString(child, result));\n }\n result.push(' ');\n });\n break;\n default:\n throw new Error(`Unknown node encountered ${node.type}`);\n }\n\n return result.join('').trim();\n}\n\n// This is only for documentation purposes, and it is not used in the code.\n/** @publicDocs */\nexport type RichTextPropsForDocs<AsType extends React.ElementType = 'div'> =\n RichTextPropsBase<AsType>;\n"],"mappings":";;;;;AAmBA,SAAgB,SAA6D,EAC3E,IACA,MACA,OACA,YACA,GAAG,oBAC4C;AAC/C,KAAI;EACF,MAAM,UAAU,MAAM;EACtB,MAAM,aAAa,cACX,KAAK,MAAM,KAAK,EACtB,CAAC,KAAK,CACP;AAED,SACE,oBAAC,SAAD;GAAS,GAAI;aACV,QACG,iBAAiB,WAAW,GAC5B,yBAAyB,YAAY,WAAW;GAC5C,CAAA;UAEL,GAAG;AACV,QAAM,IAAI,MACR,6FACA,EACE,OAAO,GACR,CACF;;;AAYL,SAAS,yBACP,aAA+B,EAAE,EACjC,MACA,QAAQ,GACG;CACX,IAAI;AACJ,KAAI,cAAc,KAChB,YAAW,KAAK,SAAS,KAAK,OAAO,eACnC,yBAAyB,YAAY,OAAO,WAAW,CACxD;CAGH,MAAM,YACJ,WAAW,KAAK,SAAS,cAAc,aAAa,KAAK,SACzD,mBAAmB,KAAK;AAE1B,SAAQ,KAAK,MAAb;EACE,KAAK,OACH,QAAO,cACL,WACA;GACE,KAAK;GACL,MAAM;IACJ,MAAM;IACN;IACD;GACF,CACF;EACH,KAAK,UACH,QAAO,cACL,WACA;GACE,KAAK;GACL,MAAM;IACJ,MAAM;IACN,OAAO,KAAK;IACZ;IACD;GACF,CACF;EACH,KAAK,YACH,QAAO,cACL,WACA;GACE,KAAK;GACL,MAAM;IACJ,MAAM;IACN;IACD;GACF,CACF;EACH,KAAK,QAAQ;GACX,MAAM,YAAY,KAAK,SAAS,IAC7B,MAAM,KAAK,CACX,SAAS,OAAO,aAAa;IAC5B,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG;IACjC,MAAM,cAAc,cAClB,WACA;KACE;KACA,MAAM;MACJ,MAAM;MACN,QAAQ,KAAK;MACb,MAAM,KAAK;MACX;MACD;KACF,CACF;AAGD,WAAO,aAAa,IAChB,cACA,CAAC,cAAc,MAAM,EAAC,KAAK,GAAG,IAAI,MAAK,CAAC,EAAE,YAAY;KAC1D;AAEJ,UAAO,SAAS,SAAS,IACrB,cAAc,UAAU,EAAC,KAAK,OAAM,EAAE,SAAS,GAC/C,SAAS;;EAEf,KAAK,OACH,QAAO,cACL,WACA;GACE,KAAK;GACL,MAAM;IACJ,MAAM;IACN,KAAK,KAAK;IACV,OAAO,KAAK;IACZ,QAAQ,KAAK;IACb;IACD;GACF,CACF;EACH,KAAK,OACH,QAAO,cACL,WACA;GACE,KAAK;GACL,MAAM;IACJ,MAAM;IACN,UAAU,KAAK;IACf;IACD;GACF,CACF;EACH,KAAK,YACH,QAAO,cACL,WACA;GACE,KAAK;GACL,MAAM;IACJ,MAAM;IACN;IACD;GACF,CACF;;;AAIP,SAAS,iBACP,MACA,SAAmB,EAAE,EACb;AACR,SAAQ,KAAK,MAAb;EACE,KAAK;AACH,QAAK,SAAS,SAAS,UAAU,iBAAiB,OAAO,OAAO,CAAC;AACjE;EACF,KAAK;EACL,KAAK;AACH,QAAK,SAAS,SAAS,UAAU,iBAAiB,OAAO,OAAO,CAAC;AACjE,UAAO,KAAK,IAAI;AAChB;EACF,KAAK;AACH,UAAO,KAAK,KAAK,SAAS,GAAG;AAC7B;EACF,KAAK;AACH,QAAK,SAAS,SAAS,UAAU,iBAAiB,OAAO,OAAO,CAAC;AACjE;EACF,KAAK;AACH,QAAK,SAAS,SAAS,SAAS;AAC9B,QAAI,KAAK,SACP,MAAK,SAAS,SAAS,UAAU,iBAAiB,OAAO,OAAO,CAAC;AAEnE,WAAO,KAAK,IAAI;KAChB;AACF;EACF,QACE,OAAM,IAAI,MAAM,4BAA4B,KAAK,OAAO;;AAG5D,QAAO,OAAO,KAAK,GAAG,CAAC,MAAM"}
|