@anker-in/campaign-ui 0.2.11-beta.2 → 0.2.11-beta.21
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/cjs/components/LiveChatWidget/LiveChatWidget.d.ts +43 -0
- package/dist/cjs/components/LiveChatWidget/LiveChatWidget.js +2 -0
- package/dist/cjs/components/LiveChatWidget/LiveChatWidget.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/api/chat.d.ts +25 -0
- package/dist/cjs/components/LiveChatWidget/api/chat.js +3 -0
- package/dist/cjs/components/LiveChatWidget/api/chat.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/ChatBubble.d.ts +68 -0
- package/dist/cjs/components/LiveChatWidget/components/ChatBubble.js +2 -0
- package/dist/cjs/components/LiveChatWidget/components/ChatBubble.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/ChatHeader.d.ts +57 -0
- package/dist/cjs/components/LiveChatWidget/components/ChatHeader.js +2 -0
- package/dist/cjs/components/LiveChatWidget/components/ChatHeader.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/ChatInput.d.ts +70 -0
- package/dist/cjs/components/LiveChatWidget/components/ChatInput.js +2 -0
- package/dist/cjs/components/LiveChatWidget/components/ChatInput.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/ChatMessage.d.ts +59 -0
- package/dist/cjs/components/LiveChatWidget/components/ChatMessage.js +5 -0
- package/dist/cjs/components/LiveChatWidget/components/ChatMessage.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/ChatWindow.d.ts +127 -0
- package/dist/cjs/components/LiveChatWidget/components/ChatWindow.js +2 -0
- package/dist/cjs/components/LiveChatWidget/components/ChatWindow.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/CartCard.d.ts +54 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/CartCard.js +2 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/CartCard.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ErrorBlock.d.ts +33 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ErrorBlock.js +2 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ErrorBlock.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/FAQList.d.ts +16 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/FAQList.js +2 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/FAQList.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/PolicyBlock.d.ts +45 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/PolicyBlock.js +5 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/PolicyBlock.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductCard.d.ts +48 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductCard.js +5 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductCard.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductComparison.d.ts +70 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductComparison.js +2 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductComparison.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductList.d.ts +47 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductList.js +2 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductList.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/PromotionList.d.ts +78 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/PromotionList.js +2 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/PromotionList.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/QuickReplies.d.ts +54 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/QuickReplies.js +2 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/QuickReplies.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/TextBlock.d.ts +31 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/TextBlock.js +2 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/TextBlock.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ThinkingBlock.d.ts +31 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ThinkingBlock.js +2 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ThinkingBlock.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/index.d.ts +15 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/index.js +2 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/index.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent.d.ts +63 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent.js +2 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageContent.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageList.d.ts +74 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageList.js +5 -0
- package/dist/cjs/components/LiveChatWidget/components/MessageList.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/components/ScrollAnchor.d.ts +44 -0
- package/dist/cjs/components/LiveChatWidget/components/ScrollAnchor.js +2 -0
- package/dist/cjs/components/LiveChatWidget/components/ScrollAnchor.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/constants.d.ts +8 -0
- package/dist/cjs/components/LiveChatWidget/constants.js +2 -0
- package/dist/cjs/components/LiveChatWidget/constants.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/hooks/useChatAPI.d.ts +51 -0
- package/dist/cjs/components/LiveChatWidget/hooks/useChatAPI.js +2 -0
- package/dist/cjs/components/LiveChatWidget/hooks/useChatAPI.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/hooks/useChatState.d.ts +120 -0
- package/dist/cjs/components/LiveChatWidget/hooks/useChatState.js +2 -0
- package/dist/cjs/components/LiveChatWidget/hooks/useChatState.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/hooks/useSession.d.ts +37 -0
- package/dist/cjs/components/LiveChatWidget/hooks/useSession.js +2 -0
- package/dist/cjs/components/LiveChatWidget/hooks/useSession.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/index.d.ts +12 -0
- package/dist/cjs/components/LiveChatWidget/index.js +2 -0
- package/dist/cjs/components/LiveChatWidget/index.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/types.d.ts +609 -0
- package/dist/cjs/components/LiveChatWidget/types.js +2 -0
- package/dist/cjs/components/LiveChatWidget/types.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/utils/cartTransformers.d.ts +25 -0
- package/dist/cjs/components/LiveChatWidget/utils/cartTransformers.js +2 -0
- package/dist/cjs/components/LiveChatWidget/utils/cartTransformers.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/utils/messageRenderers.d.ts +64 -0
- package/dist/cjs/components/LiveChatWidget/utils/messageRenderers.js +2 -0
- package/dist/cjs/components/LiveChatWidget/utils/messageRenderers.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/utils/productTransformers.d.ts +43 -0
- package/dist/cjs/components/LiveChatWidget/utils/productTransformers.js +2 -0
- package/dist/cjs/components/LiveChatWidget/utils/productTransformers.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/utils/userId.d.ts +18 -0
- package/dist/cjs/components/LiveChatWidget/utils/userId.js +2 -0
- package/dist/cjs/components/LiveChatWidget/utils/userId.js.map +7 -0
- package/dist/cjs/components/LiveChatWidget/utils/validation.d.ts +37 -0
- package/dist/cjs/components/LiveChatWidget/utils/validation.js +2 -0
- package/dist/cjs/components/LiveChatWidget/utils/validation.js.map +7 -0
- package/dist/cjs/components/chat/markdown.js +1 -1
- package/dist/cjs/components/chat/markdown.js.map +2 -2
- package/dist/cjs/components/credits/context/hooks/useFunctionMemberPrice.d.ts +2 -2
- package/dist/cjs/components/credits/context/hooks/useFunctionMemberPrice.js +1 -1
- package/dist/cjs/components/credits/context/hooks/useFunctionMemberPrice.js.map +2 -2
- package/dist/cjs/components/credits/context/hooks/useRedeemableList.js +1 -1
- package/dist/cjs/components/credits/context/hooks/useRedeemableList.js.map +2 -2
- package/dist/cjs/components/credits/context/memberPriceConst.d.ts +0 -5
- package/dist/cjs/components/credits/context/memberPriceConst.js +1 -1
- package/dist/cjs/components/credits/context/memberPriceConst.js.map +3 -3
- package/dist/cjs/components/credits/context/memberPriceTypes.d.ts +1 -22
- package/dist/cjs/components/credits/context/memberPriceTypes.js +1 -1
- package/dist/cjs/components/credits/context/memberPriceTypes.js.map +1 -1
- package/dist/cjs/components/credits/context/provider.d.ts +16 -1
- package/dist/cjs/components/credits/context/provider.js +1 -1
- package/dist/cjs/components/credits/context/provider.js.map +3 -3
- package/dist/cjs/components/credits/context/utils/getFunctionMemberPrice.d.ts +2 -2
- package/dist/cjs/components/credits/context/utils/getFunctionMemberPrice.js +1 -1
- package/dist/cjs/components/credits/context/utils/getFunctionMemberPrice.js.map +1 -1
- package/dist/cjs/components/credits/context/utils/getFunctionMemberPriceDiscountConfig.d.ts +2 -2
- package/dist/cjs/components/credits/context/utils/getFunctionMemberPriceDiscountConfig.js +1 -1
- package/dist/cjs/components/credits/context/utils/getFunctionMemberPriceDiscountConfig.js.map +1 -1
- package/dist/cjs/components/credits/context/utils/variantGetCoupon.d.ts +2 -2
- package/dist/cjs/components/credits/context/utils/variantGetCoupon.js +1 -1
- package/dist/cjs/components/credits/context/utils/variantGetCoupon.js.map +1 -1
- package/dist/cjs/components/credits/context/utils.d.ts +4 -0
- package/dist/cjs/components/credits/context/utils.js +1 -1
- package/dist/cjs/components/credits/context/utils.js.map +3 -3
- package/dist/cjs/components/credits/creditsAnkersolixTask/CreditsAnkersolixTask.js +1 -1
- package/dist/cjs/components/credits/creditsAnkersolixTask/CreditsAnkersolixTask.js.map +3 -3
- package/dist/cjs/components/credits/creditsBanner/index.d.ts +2 -0
- package/dist/cjs/components/credits/creditsBanner/index.js +12 -1
- package/dist/cjs/components/credits/creditsBanner/index.js.map +3 -3
- package/dist/cjs/components/credits/creditsBenefits/BenefitItem.js +1 -1
- package/dist/cjs/components/credits/creditsBenefits/BenefitItem.js.map +3 -3
- package/dist/cjs/components/credits/creditsBenefits/IconInfo.js +1 -1
- package/dist/cjs/components/credits/creditsBenefits/IconInfo.js.map +1 -1
- package/dist/cjs/components/credits/creditsBenefits/index.js +3 -3
- package/dist/cjs/components/credits/creditsBenefits/index.js.map +2 -2
- package/dist/cjs/components/credits/creditsCash/CreditsCash.js +1 -1
- package/dist/cjs/components/credits/creditsCash/CreditsCash.js.map +3 -3
- package/dist/cjs/components/credits/creditsCash/RedeemableItem.js +1 -1
- package/dist/cjs/components/credits/creditsCash/RedeemableItem.js.map +3 -3
- package/dist/cjs/components/credits/creditsCash/type.d.ts +1 -0
- package/dist/cjs/components/credits/creditsCash/type.js +1 -1
- package/dist/cjs/components/credits/creditsCash/type.js.map +1 -1
- package/dist/cjs/components/credits/creditsFaq/faqItem/FaqItem.js +1 -1
- package/dist/cjs/components/credits/creditsFaq/faqItem/FaqItem.js.map +3 -3
- package/dist/cjs/components/credits/creditsFaq/index.js +1 -1
- package/dist/cjs/components/credits/creditsFaq/index.js.map +3 -3
- package/dist/cjs/components/credits/creditsInfoCard/index.js +1 -1
- package/dist/cjs/components/credits/creditsInfoCard/index.js.map +3 -3
- package/dist/cjs/components/credits/creditsMemberPrice/CreditsMemberPrice.js +1 -1
- package/dist/cjs/components/credits/creditsMemberPrice/CreditsMemberPrice.js.map +3 -3
- package/dist/cjs/components/credits/creditsMemberPrice/MemberPriceItem.js +1 -1
- package/dist/cjs/components/credits/creditsMemberPrice/MemberPriceItem.js.map +3 -3
- package/dist/cjs/components/credits/creditsMemberPrice/Pagination.d.ts +7 -0
- package/dist/cjs/components/credits/creditsMemberPrice/Pagination.js +2 -0
- package/dist/cjs/components/credits/creditsMemberPrice/Pagination.js.map +7 -0
- package/dist/cjs/components/credits/creditsMemberPrice/type.d.ts +3 -5
- package/dist/cjs/components/credits/creditsMemberPrice/type.js +1 -1
- package/dist/cjs/components/credits/creditsMemberPrice/type.js.map +1 -1
- package/dist/cjs/components/credits/creditsNavigation/CreditsNavigation.js +1 -1
- package/dist/cjs/components/credits/creditsNavigation/CreditsNavigation.js.map +2 -2
- package/dist/cjs/components/credits/creditsRedeemList/AddressForm/CountrySelect.js +1 -1
- package/dist/cjs/components/credits/creditsRedeemList/AddressForm/CountrySelect.js.map +3 -3
- package/dist/cjs/components/credits/creditsRedeemList/AddressForm/StateSelect.js +1 -1
- package/dist/cjs/components/credits/creditsRedeemList/AddressForm/StateSelect.js.map +3 -3
- package/dist/cjs/components/credits/creditsRedeemList/AddressForm/index.js +1 -1
- package/dist/cjs/components/credits/creditsRedeemList/AddressForm/index.js.map +3 -3
- package/dist/cjs/components/credits/creditsRedeemList/CreditsRedeemList.js +1 -1
- package/dist/cjs/components/credits/creditsRedeemList/CreditsRedeemList.js.map +3 -3
- package/dist/cjs/components/credits/creditsRedeemList/RedeemProductModal/Address.js +1 -1
- package/dist/cjs/components/credits/creditsRedeemList/RedeemProductModal/Address.js.map +3 -3
- package/dist/cjs/components/credits/creditsRedeemList/RedeemProductModal/ProductInfo.js +1 -1
- package/dist/cjs/components/credits/creditsRedeemList/RedeemProductModal/ProductInfo.js.map +2 -2
- package/dist/cjs/components/credits/creditsRedeemList/RedeemProductModal/Success.js +1 -1
- package/dist/cjs/components/credits/creditsRedeemList/RedeemProductModal/Success.js.map +3 -3
- package/dist/cjs/components/credits/creditsRedeemList/RedeemableItem.js +1 -1
- package/dist/cjs/components/credits/creditsRedeemList/RedeemableItem.js.map +3 -3
- package/dist/cjs/components/credits/creditsWaysToGetCredits/CreditsWaysToGetCredits.js +1 -1
- package/dist/cjs/components/credits/creditsWaysToGetCredits/CreditsWaysToGetCredits.js.map +3 -3
- package/dist/cjs/components/credits/modal/MyRewardsModal.js +1 -1
- package/dist/cjs/components/credits/modal/MyRewardsModal.js.map +3 -3
- package/dist/cjs/components/credits/modal/activitiesModal.js +1 -1
- package/dist/cjs/components/credits/modal/activitiesModal.js.map +3 -3
- package/dist/cjs/components/credits/modal/creditsUploadReceiptModal.js +1 -1
- package/dist/cjs/components/credits/modal/creditsUploadReceiptModal.js.map +3 -3
- package/dist/cjs/components/credits/modal/modalContainer.js +1 -1
- package/dist/cjs/components/credits/modal/modalContainer.js.map +3 -3
- package/dist/cjs/components/credits/modal/subscribeModal.js +1 -1
- package/dist/cjs/components/credits/modal/subscribeModal.js.map +3 -3
- package/dist/cjs/components/credits/modal/tip.js +1 -1
- package/dist/cjs/components/credits/modal/tip.js.map +3 -3
- package/dist/cjs/components/index.d.ts +3 -1
- package/dist/cjs/components/index.js +1 -1
- package/dist/cjs/components/index.js.map +3 -3
- package/dist/cjs/components/registration/authCodeActivate/index.js +1 -1
- package/dist/cjs/components/registration/authCodeActivate/index.js.map +3 -3
- package/dist/cjs/components/registration/modalContainer.js +1 -1
- package/dist/cjs/components/registration/modalContainer.js.map +3 -3
- package/dist/cjs/constants.d.ts +1 -0
- package/dist/cjs/constants.js +2 -0
- package/dist/cjs/constants.js.map +7 -0
- package/dist/cjs/index.d.ts +3 -2
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/stories/CartCard.stories.d.ts +33 -0
- package/dist/cjs/stories/CartCard.stories.js +21 -0
- package/dist/cjs/stories/CartCard.stories.js.map +7 -0
- package/dist/cjs/stories/LiveChatWidget.stories.d.ts +92 -0
- package/dist/cjs/stories/LiveChatWidget.stories.js +98 -0
- package/dist/cjs/stories/LiveChatWidget.stories.js.map +7 -0
- package/dist/cjs/templates/Credits.d.ts +15 -1
- package/dist/cjs/templates/Credits.js +1 -1
- package/dist/cjs/templates/Credits.js.map +3 -3
- package/dist/esm/components/LiveChatWidget/LiveChatWidget.d.ts +43 -0
- package/dist/esm/components/LiveChatWidget/LiveChatWidget.js +2 -0
- package/dist/esm/components/LiveChatWidget/LiveChatWidget.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/api/chat.d.ts +25 -0
- package/dist/esm/components/LiveChatWidget/api/chat.js +3 -0
- package/dist/esm/components/LiveChatWidget/api/chat.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/ChatBubble.d.ts +68 -0
- package/dist/esm/components/LiveChatWidget/components/ChatBubble.js +2 -0
- package/dist/esm/components/LiveChatWidget/components/ChatBubble.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/ChatHeader.d.ts +57 -0
- package/dist/esm/components/LiveChatWidget/components/ChatHeader.js +2 -0
- package/dist/esm/components/LiveChatWidget/components/ChatHeader.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/ChatInput.d.ts +70 -0
- package/dist/esm/components/LiveChatWidget/components/ChatInput.js +2 -0
- package/dist/esm/components/LiveChatWidget/components/ChatInput.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/ChatMessage.d.ts +59 -0
- package/dist/esm/components/LiveChatWidget/components/ChatMessage.js +5 -0
- package/dist/esm/components/LiveChatWidget/components/ChatMessage.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/ChatWindow.d.ts +127 -0
- package/dist/esm/components/LiveChatWidget/components/ChatWindow.js +2 -0
- package/dist/esm/components/LiveChatWidget/components/ChatWindow.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/CartCard.d.ts +54 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/CartCard.js +2 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/CartCard.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ErrorBlock.d.ts +33 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ErrorBlock.js +2 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ErrorBlock.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/FAQList.d.ts +16 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/FAQList.js +2 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/FAQList.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/PolicyBlock.d.ts +45 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/PolicyBlock.js +5 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/PolicyBlock.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductCard.d.ts +48 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductCard.js +5 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductCard.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductComparison.d.ts +70 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductComparison.js +2 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductComparison.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductList.d.ts +47 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductList.js +2 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductList.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/PromotionList.d.ts +78 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/PromotionList.js +2 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/PromotionList.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/QuickReplies.d.ts +54 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/QuickReplies.js +2 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/QuickReplies.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/TextBlock.d.ts +31 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/TextBlock.js +2 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/TextBlock.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ThinkingBlock.d.ts +31 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ThinkingBlock.js +2 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ThinkingBlock.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/index.d.ts +15 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/index.js +2 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent/index.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent.d.ts +63 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent.js +2 -0
- package/dist/esm/components/LiveChatWidget/components/MessageContent.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/MessageList.d.ts +74 -0
- package/dist/esm/components/LiveChatWidget/components/MessageList.js +5 -0
- package/dist/esm/components/LiveChatWidget/components/MessageList.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/components/ScrollAnchor.d.ts +44 -0
- package/dist/esm/components/LiveChatWidget/components/ScrollAnchor.js +2 -0
- package/dist/esm/components/LiveChatWidget/components/ScrollAnchor.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/constants.d.ts +8 -0
- package/dist/esm/components/LiveChatWidget/constants.js +2 -0
- package/dist/esm/components/LiveChatWidget/constants.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/hooks/useChatAPI.d.ts +51 -0
- package/dist/esm/components/LiveChatWidget/hooks/useChatAPI.js +2 -0
- package/dist/esm/components/LiveChatWidget/hooks/useChatAPI.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/hooks/useChatState.d.ts +120 -0
- package/dist/esm/components/LiveChatWidget/hooks/useChatState.js +2 -0
- package/dist/esm/components/LiveChatWidget/hooks/useChatState.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/hooks/useSession.d.ts +37 -0
- package/dist/esm/components/LiveChatWidget/hooks/useSession.js +2 -0
- package/dist/esm/components/LiveChatWidget/hooks/useSession.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/index.d.ts +12 -0
- package/dist/esm/components/LiveChatWidget/index.js +2 -0
- package/dist/esm/components/LiveChatWidget/index.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/types.d.ts +609 -0
- package/dist/esm/components/LiveChatWidget/types.js +1 -0
- package/dist/esm/components/LiveChatWidget/types.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/utils/cartTransformers.d.ts +25 -0
- package/dist/esm/components/LiveChatWidget/utils/cartTransformers.js +2 -0
- package/dist/esm/components/LiveChatWidget/utils/cartTransformers.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/utils/messageRenderers.d.ts +64 -0
- package/dist/esm/components/LiveChatWidget/utils/messageRenderers.js +2 -0
- package/dist/esm/components/LiveChatWidget/utils/messageRenderers.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/utils/productTransformers.d.ts +43 -0
- package/dist/esm/components/LiveChatWidget/utils/productTransformers.js +2 -0
- package/dist/esm/components/LiveChatWidget/utils/productTransformers.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/utils/userId.d.ts +18 -0
- package/dist/esm/components/LiveChatWidget/utils/userId.js +2 -0
- package/dist/esm/components/LiveChatWidget/utils/userId.js.map +7 -0
- package/dist/esm/components/LiveChatWidget/utils/validation.d.ts +37 -0
- package/dist/esm/components/LiveChatWidget/utils/validation.js +2 -0
- package/dist/esm/components/LiveChatWidget/utils/validation.js.map +7 -0
- package/dist/esm/components/chat/markdown.js +1 -1
- package/dist/esm/components/chat/markdown.js.map +2 -2
- package/dist/esm/components/credits/context/hooks/useFunctionMemberPrice.d.ts +2 -2
- package/dist/esm/components/credits/context/hooks/useFunctionMemberPrice.js +1 -1
- package/dist/esm/components/credits/context/hooks/useFunctionMemberPrice.js.map +2 -2
- package/dist/esm/components/credits/context/hooks/useRedeemableList.js +1 -1
- package/dist/esm/components/credits/context/hooks/useRedeemableList.js.map +2 -2
- package/dist/esm/components/credits/context/memberPriceConst.d.ts +0 -5
- package/dist/esm/components/credits/context/memberPriceConst.js +1 -1
- package/dist/esm/components/credits/context/memberPriceConst.js.map +3 -3
- package/dist/esm/components/credits/context/memberPriceTypes.d.ts +1 -22
- package/dist/esm/components/credits/context/provider.d.ts +16 -1
- package/dist/esm/components/credits/context/provider.js +1 -1
- package/dist/esm/components/credits/context/provider.js.map +3 -3
- package/dist/esm/components/credits/context/utils/getFunctionMemberPrice.d.ts +2 -2
- package/dist/esm/components/credits/context/utils/getFunctionMemberPrice.js +1 -1
- package/dist/esm/components/credits/context/utils/getFunctionMemberPrice.js.map +1 -1
- package/dist/esm/components/credits/context/utils/getFunctionMemberPriceDiscountConfig.d.ts +2 -2
- package/dist/esm/components/credits/context/utils/getFunctionMemberPriceDiscountConfig.js +1 -1
- package/dist/esm/components/credits/context/utils/getFunctionMemberPriceDiscountConfig.js.map +1 -1
- package/dist/esm/components/credits/context/utils/variantGetCoupon.d.ts +2 -2
- package/dist/esm/components/credits/context/utils/variantGetCoupon.js +1 -1
- package/dist/esm/components/credits/context/utils/variantGetCoupon.js.map +1 -1
- package/dist/esm/components/credits/context/utils.d.ts +4 -0
- package/dist/esm/components/credits/context/utils.js +1 -1
- package/dist/esm/components/credits/context/utils.js.map +3 -3
- package/dist/esm/components/credits/creditsAnkersolixTask/CreditsAnkersolixTask.js +1 -1
- package/dist/esm/components/credits/creditsAnkersolixTask/CreditsAnkersolixTask.js.map +3 -3
- package/dist/esm/components/credits/creditsBanner/index.d.ts +2 -0
- package/dist/esm/components/credits/creditsBanner/index.js +12 -1
- package/dist/esm/components/credits/creditsBanner/index.js.map +3 -3
- package/dist/esm/components/credits/creditsBenefits/BenefitItem.js +1 -1
- package/dist/esm/components/credits/creditsBenefits/BenefitItem.js.map +3 -3
- package/dist/esm/components/credits/creditsBenefits/IconInfo.js +1 -1
- package/dist/esm/components/credits/creditsBenefits/IconInfo.js.map +1 -1
- package/dist/esm/components/credits/creditsBenefits/index.js +3 -3
- package/dist/esm/components/credits/creditsBenefits/index.js.map +2 -2
- package/dist/esm/components/credits/creditsCash/CreditsCash.js +1 -1
- package/dist/esm/components/credits/creditsCash/CreditsCash.js.map +3 -3
- package/dist/esm/components/credits/creditsCash/RedeemableItem.js +1 -1
- package/dist/esm/components/credits/creditsCash/RedeemableItem.js.map +3 -3
- package/dist/esm/components/credits/creditsCash/type.d.ts +1 -0
- package/dist/esm/components/credits/creditsFaq/faqItem/FaqItem.js +1 -1
- package/dist/esm/components/credits/creditsFaq/faqItem/FaqItem.js.map +3 -3
- package/dist/esm/components/credits/creditsFaq/index.js +1 -1
- package/dist/esm/components/credits/creditsFaq/index.js.map +3 -3
- package/dist/esm/components/credits/creditsInfoCard/index.js +1 -1
- package/dist/esm/components/credits/creditsInfoCard/index.js.map +2 -2
- package/dist/esm/components/credits/creditsMemberPrice/CreditsMemberPrice.js +1 -1
- package/dist/esm/components/credits/creditsMemberPrice/CreditsMemberPrice.js.map +3 -3
- package/dist/esm/components/credits/creditsMemberPrice/MemberPriceItem.js +1 -1
- package/dist/esm/components/credits/creditsMemberPrice/MemberPriceItem.js.map +3 -3
- package/dist/esm/components/credits/creditsMemberPrice/Pagination.d.ts +7 -0
- package/dist/esm/components/credits/creditsMemberPrice/Pagination.js +2 -0
- package/dist/esm/components/credits/creditsMemberPrice/Pagination.js.map +7 -0
- package/dist/esm/components/credits/creditsMemberPrice/type.d.ts +3 -5
- package/dist/esm/components/credits/creditsNavigation/CreditsNavigation.js +1 -1
- package/dist/esm/components/credits/creditsNavigation/CreditsNavigation.js.map +2 -2
- package/dist/esm/components/credits/creditsRedeemList/AddressForm/CountrySelect.js +1 -1
- package/dist/esm/components/credits/creditsRedeemList/AddressForm/CountrySelect.js.map +2 -2
- package/dist/esm/components/credits/creditsRedeemList/AddressForm/StateSelect.js +1 -1
- package/dist/esm/components/credits/creditsRedeemList/AddressForm/StateSelect.js.map +2 -2
- package/dist/esm/components/credits/creditsRedeemList/AddressForm/index.js +1 -1
- package/dist/esm/components/credits/creditsRedeemList/AddressForm/index.js.map +2 -2
- package/dist/esm/components/credits/creditsRedeemList/CreditsRedeemList.js +1 -1
- package/dist/esm/components/credits/creditsRedeemList/CreditsRedeemList.js.map +3 -3
- package/dist/esm/components/credits/creditsRedeemList/RedeemProductModal/Address.js +1 -1
- package/dist/esm/components/credits/creditsRedeemList/RedeemProductModal/Address.js.map +3 -3
- package/dist/esm/components/credits/creditsRedeemList/RedeemProductModal/ProductInfo.js +1 -1
- package/dist/esm/components/credits/creditsRedeemList/RedeemProductModal/ProductInfo.js.map +2 -2
- package/dist/esm/components/credits/creditsRedeemList/RedeemProductModal/Success.js +1 -1
- package/dist/esm/components/credits/creditsRedeemList/RedeemProductModal/Success.js.map +2 -2
- package/dist/esm/components/credits/creditsRedeemList/RedeemableItem.js +1 -1
- package/dist/esm/components/credits/creditsRedeemList/RedeemableItem.js.map +3 -3
- package/dist/esm/components/credits/creditsWaysToGetCredits/CreditsWaysToGetCredits.js +1 -1
- package/dist/esm/components/credits/creditsWaysToGetCredits/CreditsWaysToGetCredits.js.map +3 -3
- package/dist/esm/components/credits/modal/MyRewardsModal.js +1 -1
- package/dist/esm/components/credits/modal/MyRewardsModal.js.map +2 -2
- package/dist/esm/components/credits/modal/activitiesModal.js +1 -1
- package/dist/esm/components/credits/modal/activitiesModal.js.map +3 -3
- package/dist/esm/components/credits/modal/creditsUploadReceiptModal.js +1 -1
- package/dist/esm/components/credits/modal/creditsUploadReceiptModal.js.map +3 -3
- package/dist/esm/components/credits/modal/modalContainer.js +1 -1
- package/dist/esm/components/credits/modal/modalContainer.js.map +3 -3
- package/dist/esm/components/credits/modal/subscribeModal.js +1 -1
- package/dist/esm/components/credits/modal/subscribeModal.js.map +3 -3
- package/dist/esm/components/credits/modal/tip.js +1 -1
- package/dist/esm/components/credits/modal/tip.js.map +3 -3
- package/dist/esm/components/index.d.ts +3 -1
- package/dist/esm/components/index.js +1 -1
- package/dist/esm/components/index.js.map +3 -3
- package/dist/esm/components/registration/authCodeActivate/index.js +1 -1
- package/dist/esm/components/registration/authCodeActivate/index.js.map +3 -3
- package/dist/esm/components/registration/modalContainer.js +1 -1
- package/dist/esm/components/registration/modalContainer.js.map +3 -3
- package/dist/esm/constants.d.ts +1 -0
- package/dist/esm/constants.js +2 -0
- package/dist/esm/constants.js.map +7 -0
- package/dist/esm/index.d.ts +3 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +2 -2
- package/dist/esm/stories/CartCard.stories.d.ts +33 -0
- package/dist/esm/stories/CartCard.stories.js +21 -0
- package/dist/esm/stories/CartCard.stories.js.map +7 -0
- package/dist/esm/stories/LiveChatWidget.stories.d.ts +92 -0
- package/dist/esm/stories/LiveChatWidget.stories.js +98 -0
- package/dist/esm/stories/LiveChatWidget.stories.js.map +7 -0
- package/dist/esm/templates/Credits.d.ts +15 -1
- package/dist/esm/templates/Credits.js +1 -1
- package/dist/esm/templates/Credits.js.map +3 -3
- package/package.json +7 -3
- package/src/components/LiveChatWidget/LiveChatWidget.tsx +599 -0
- package/src/components/LiveChatWidget/api/chat.ts +136 -0
- package/src/components/LiveChatWidget/components/ChatBubble.tsx +152 -0
- package/src/components/LiveChatWidget/components/ChatHeader.tsx +151 -0
- package/src/components/LiveChatWidget/components/ChatInput.tsx +216 -0
- package/src/components/LiveChatWidget/components/ChatMessage.tsx +182 -0
- package/src/components/LiveChatWidget/components/ChatWindow.tsx +304 -0
- package/src/components/LiveChatWidget/components/MessageContent/CartCard.tsx +198 -0
- package/src/components/LiveChatWidget/components/MessageContent/ErrorBlock.tsx +75 -0
- package/src/components/LiveChatWidget/components/MessageContent/FAQList.tsx +127 -0
- package/src/components/LiveChatWidget/components/MessageContent/PolicyBlock.tsx +150 -0
- package/src/components/LiveChatWidget/components/MessageContent/ProductCard.tsx +139 -0
- package/src/components/LiveChatWidget/components/MessageContent/ProductComparison.tsx +348 -0
- package/src/components/LiveChatWidget/components/MessageContent/ProductList.tsx +275 -0
- package/src/components/LiveChatWidget/components/MessageContent/PromotionList.tsx +207 -0
- package/src/components/LiveChatWidget/components/MessageContent/QuickReplies.tsx +91 -0
- package/src/components/LiveChatWidget/components/MessageContent/TextBlock.tsx +89 -0
- package/src/components/LiveChatWidget/components/MessageContent/ThinkingBlock.tsx +53 -0
- package/src/components/LiveChatWidget/components/MessageContent/index.ts +16 -0
- package/src/components/LiveChatWidget/components/MessageContent.tsx +110 -0
- package/src/components/LiveChatWidget/components/MessageList.tsx +261 -0
- package/src/components/LiveChatWidget/components/ScrollAnchor.tsx +75 -0
- package/src/components/LiveChatWidget/constants.ts +15 -0
- package/src/components/LiveChatWidget/hooks/useChatAPI.ts +136 -0
- package/src/components/LiveChatWidget/hooks/useChatState.ts +542 -0
- package/src/components/LiveChatWidget/hooks/useSession.ts +123 -0
- package/src/components/LiveChatWidget/index.tsx +62 -0
- package/src/components/LiveChatWidget/types.ts +769 -0
- package/src/components/LiveChatWidget/utils/cartTransformers.ts +72 -0
- package/src/components/LiveChatWidget/utils/messageRenderers.ts +120 -0
- package/src/components/LiveChatWidget/utils/productTransformers.ts +149 -0
- package/src/components/LiveChatWidget/utils/userId.ts +140 -0
- package/src/components/LiveChatWidget/utils/validation.ts +99 -0
- package/src/components/chat/markdown.tsx +1 -1
- package/src/components/credits/context/hooks/useRedeemableList.ts +1 -1
- package/src/components/credits/context/memberPriceConst.ts +0 -7
- package/src/components/credits/context/memberPriceTypes.ts +1 -26
- package/src/components/credits/context/provider.tsx +16 -0
- package/src/components/credits/context/utils.ts +9 -0
- package/src/components/credits/creditsAnkersolixTask/CreditsAnkersolixTask.tsx +44 -41
- package/src/components/credits/creditsBanner/index.tsx +31 -3
- package/src/components/credits/creditsBenefits/BenefitItem.tsx +13 -5
- package/src/components/credits/creditsBenefits/IconInfo.tsx +1 -1
- package/src/components/credits/creditsBenefits/index.tsx +1 -1
- package/src/components/credits/creditsCash/CreditsCash.tsx +6 -3
- package/src/components/credits/creditsCash/RedeemableItem.tsx +29 -11
- package/src/components/credits/creditsCash/type.ts +1 -0
- package/src/components/credits/creditsFaq/faqItem/FaqItem.tsx +25 -23
- package/src/components/credits/creditsFaq/index.tsx +2 -1
- package/src/components/credits/creditsInfoCard/index.tsx +10 -3
- package/src/components/credits/creditsMemberPrice/CreditsMemberPrice.tsx +160 -136
- package/src/components/credits/creditsMemberPrice/MemberPriceItem.tsx +134 -29
- package/src/components/credits/creditsMemberPrice/Pagination.tsx +113 -0
- package/src/components/credits/creditsMemberPrice/type.ts +3 -5
- package/src/components/credits/creditsNavigation/CreditsNavigation.tsx +3 -3
- package/src/components/credits/creditsRedeemList/AddressForm/CountrySelect.tsx +2 -1
- package/src/components/credits/creditsRedeemList/AddressForm/StateSelect.tsx +2 -1
- package/src/components/credits/creditsRedeemList/AddressForm/index.tsx +2 -1
- package/src/components/credits/creditsRedeemList/CreditsRedeemList.tsx +32 -18
- package/src/components/credits/creditsRedeemList/RedeemProductModal/Address.tsx +2 -1
- package/src/components/credits/creditsRedeemList/RedeemProductModal/ProductInfo.tsx +6 -4
- package/src/components/credits/creditsRedeemList/RedeemProductModal/Success.tsx +2 -1
- package/src/components/credits/creditsRedeemList/RedeemableItem.tsx +21 -7
- package/src/components/credits/creditsWaysToGetCredits/CreditsWaysToGetCredits.tsx +34 -20
- package/src/components/credits/modal/MyRewardsModal.tsx +2 -1
- package/src/components/credits/modal/activitiesModal.tsx +2 -1
- package/src/components/credits/modal/creditsUploadReceiptModal.tsx +2 -1
- package/src/components/credits/modal/modalContainer.tsx +2 -1
- package/src/components/credits/modal/subscribeModal.tsx +2 -1
- package/src/components/credits/modal/tip.tsx +2 -1
- package/src/components/index.ts +23 -1
- package/src/components/registration/authCodeActivate/index.tsx +3 -1
- package/src/components/registration/modalContainer.tsx +2 -1
- package/src/constants.ts +1 -0
- package/src/index.ts +3 -2
- package/src/stories/CartCard.stories.tsx +459 -0
- package/src/stories/LiveChatWidget.stories.tsx +461 -0
- package/src/styles/livechat.css +263 -0
- package/src/templates/Credits.tsx +26 -9
- package/src/components/credits/context/hooks/useFunctionMemberPrice.ts +0 -33
- package/src/components/credits/context/utils/atobID.ts +0 -8
- package/src/components/credits/context/utils/functionDiscountCalculate.ts +0 -57
- package/src/components/credits/context/utils/getFunctionMemberPrice.ts +0 -135
- package/src/components/credits/context/utils/getFunctionMemberPriceDiscountConfig.ts +0 -51
- package/src/components/credits/context/utils/variantGetCoupon.ts +0 -34
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 产品对比组件
|
|
3
|
+
* 显示多个产品的对比信息,采用表格布局展示各维度差异
|
|
4
|
+
* 基于参考设计:顶部产品展示 + 底部对比表格
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React, { useState } from 'react'
|
|
8
|
+
import type { Product, MessageRenderer } from '../../types'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 对比维度数据结构
|
|
12
|
+
*/
|
|
13
|
+
interface ComparisonDimension {
|
|
14
|
+
label: string
|
|
15
|
+
values: Array<{
|
|
16
|
+
product_id: string
|
|
17
|
+
[key: string]: any
|
|
18
|
+
}>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 产品对比数据结构
|
|
23
|
+
*/
|
|
24
|
+
export interface ProductComparisonData {
|
|
25
|
+
products: Product[]
|
|
26
|
+
dimensions: {
|
|
27
|
+
price?: ComparisonDimension
|
|
28
|
+
variants?: ComparisonDimension
|
|
29
|
+
member_price?: ComparisonDimension
|
|
30
|
+
discount?: ComparisonDimension
|
|
31
|
+
[key: string]: ComparisonDimension | undefined
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ProductComparisonProps {
|
|
36
|
+
/**
|
|
37
|
+
* 产品对比数据
|
|
38
|
+
*/
|
|
39
|
+
data: ProductComparisonData
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 是否为用户消息
|
|
43
|
+
*/
|
|
44
|
+
isUser?: boolean
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 是否为系统消息
|
|
48
|
+
*/
|
|
49
|
+
isSystem?: boolean
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 添加到购物车回调
|
|
53
|
+
*/
|
|
54
|
+
onAddToCart?: (product: Product) => void
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* 格式化价格显示
|
|
59
|
+
*/
|
|
60
|
+
const formatPrice = (amount: number, currency: string = 'USD'): string => {
|
|
61
|
+
const symbol = currency === 'USD' ? '$' : currency
|
|
62
|
+
return `${symbol}${amount.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 产品对比组件
|
|
67
|
+
*
|
|
68
|
+
* 布局:
|
|
69
|
+
* ```
|
|
70
|
+
* ┌─────────────────────────────────────┐
|
|
71
|
+
* │ [产品1图片] [产品2图片] │
|
|
72
|
+
* │ 价格1 价格2 │
|
|
73
|
+
* │ 颜色选项 颜色选项 │
|
|
74
|
+
* ├─────────────────────────────────────┤
|
|
75
|
+
* │ 维度1 │ 值1-1 │ 值1-2 │
|
|
76
|
+
* │ 维度2 │ 值2-1 │ 值2-2 │
|
|
77
|
+
* │ 维度3 │ 值3-1 │ 值3-2 │
|
|
78
|
+
* └─────────────────────────────────────┘
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export const ProductComparison: React.FC<ProductComparisonProps> = ({ data, onAddToCart }) => {
|
|
82
|
+
const { products: rawProducts, dimensions } = data
|
|
83
|
+
|
|
84
|
+
// 过滤掉 null 或无效的产品
|
|
85
|
+
const allProducts = rawProducts?.filter(p => p && p.shopifyId) || []
|
|
86
|
+
|
|
87
|
+
// 对比列数(固定为2列)
|
|
88
|
+
const COMPARISON_COLUMNS = 2
|
|
89
|
+
|
|
90
|
+
// 初始化每个对比位置的选中产品(默认取前两个产品)
|
|
91
|
+
const initialSelectedProducts = allProducts.slice(0, COMPARISON_COLUMNS)
|
|
92
|
+
const [selectedProducts, setSelectedProducts] = useState<Product[]>(initialSelectedProducts)
|
|
93
|
+
|
|
94
|
+
// Early return 必须在所有 hooks 之后
|
|
95
|
+
if (allProducts.length === 0) {
|
|
96
|
+
return null
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 处理产品选择变更
|
|
100
|
+
const handleProductChange = (index: number, productId: string) => {
|
|
101
|
+
const newProduct = allProducts.find(p => p.shopifyId === productId)
|
|
102
|
+
if (newProduct) {
|
|
103
|
+
const newSelectedProducts = [...selectedProducts]
|
|
104
|
+
newSelectedProducts[index] = newProduct
|
|
105
|
+
setSelectedProducts(newSelectedProducts)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// 当前显示的产品(确保只显示指定列数)
|
|
110
|
+
const products = selectedProducts.slice(0, COMPARISON_COLUMNS)
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* 获取指定产品在某个维度的值
|
|
114
|
+
*/
|
|
115
|
+
const getDimensionValue = (dimension: ComparisonDimension, productId: string): any => {
|
|
116
|
+
if (!dimension || !dimension.values || !Array.isArray(dimension.values)) {
|
|
117
|
+
return null
|
|
118
|
+
}
|
|
119
|
+
return dimension.values.find(v => v && v.product_id === productId)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* 渲染通用对比行
|
|
124
|
+
*/
|
|
125
|
+
const renderComparisonRow = (label: string, dimension: ComparisonDimension | undefined) => {
|
|
126
|
+
if (!dimension) return null
|
|
127
|
+
|
|
128
|
+
return (
|
|
129
|
+
<div className="border-b border-[#DADCE0] pb-2">
|
|
130
|
+
{/* 维度标签(标题) */}
|
|
131
|
+
<div className="mb-3">
|
|
132
|
+
<span className="text-sm font-bold leading-[1.4] tracking-[-0.02em] text-[#86868C]">{label}</span>
|
|
133
|
+
</div>
|
|
134
|
+
|
|
135
|
+
{/* 产品值列表(横向排列) */}
|
|
136
|
+
<div className="flex gap-4" style={{ gap: '36px' }}>
|
|
137
|
+
{products.map((product, index) => {
|
|
138
|
+
if (!product || !product.shopifyId) return null
|
|
139
|
+
const value = getDimensionValue(dimension, product.shopifyId)
|
|
140
|
+
|
|
141
|
+
return (
|
|
142
|
+
<div key={`comparison-${index}`} className="flex-1">
|
|
143
|
+
{renderDimensionValue(value, dimension.label)}
|
|
144
|
+
</div>
|
|
145
|
+
)
|
|
146
|
+
})}
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* 渲染维度值
|
|
154
|
+
*/
|
|
155
|
+
const renderDimensionValue = (value: any, dimensionLabel: string) => {
|
|
156
|
+
if (!value) {
|
|
157
|
+
return <span className="text-sm font-bold leading-[1.4] tracking-[-0.02em] text-[#1D1D1F]">-</span>
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// 根据不同维度类型渲染不同格式
|
|
161
|
+
if (dimensionLabel.toLowerCase().includes('price')) {
|
|
162
|
+
// 价格维度
|
|
163
|
+
const priceDisplay =
|
|
164
|
+
value.min === value.max
|
|
165
|
+
? formatPrice(value.min, value.currency)
|
|
166
|
+
: `${formatPrice(value.min, value.currency)} - ${formatPrice(value.max, value.currency)}`
|
|
167
|
+
return <span className="text-sm font-bold leading-[1.4] tracking-[-0.02em] text-[#1D1D1F]">{priceDisplay}</span>
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (dimensionLabel.toLowerCase().includes('variant')) {
|
|
171
|
+
// 变体数量
|
|
172
|
+
return (
|
|
173
|
+
<span className="text-sm font-bold leading-[1.4] tracking-[-0.02em] text-[#1D1D1F]">
|
|
174
|
+
{value.count || 0} {value.count === 1 ? 'variant' : 'variants'}
|
|
175
|
+
</span>
|
|
176
|
+
)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// 默认显示
|
|
180
|
+
return (
|
|
181
|
+
<span className="text-sm font-bold leading-[1.4] tracking-[-0.02em] text-[#1D1D1F]">
|
|
182
|
+
{value.display || value.value || '-'}
|
|
183
|
+
</span>
|
|
184
|
+
)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return (
|
|
188
|
+
<div className="w-full overflow-hidden rounded-2xl bg-[#F5F6F7]">
|
|
189
|
+
{/* 顶部产品展示区域 */}
|
|
190
|
+
<div className="flex p-4" style={{ gap: '36px', paddingBottom: '0px' }}>
|
|
191
|
+
{products.map((product, index) => {
|
|
192
|
+
if (!product || !product.shopifyId) return null
|
|
193
|
+
|
|
194
|
+
// 获取价格信息
|
|
195
|
+
const priceInfo = dimensions.price ? getDimensionValue(dimensions.price, product.shopifyId) : null
|
|
196
|
+
|
|
197
|
+
// 获取折扣信息
|
|
198
|
+
const firstVariant = product.variants?.[0]
|
|
199
|
+
const hasDiscount = firstVariant?.discount?.has_discount
|
|
200
|
+
const discountPrice = hasDiscount ? firstVariant?.discount?.discount_price : null
|
|
201
|
+
|
|
202
|
+
// 当前显示价格:有折扣时显示折扣价,否则显示原价
|
|
203
|
+
const currentPrice = discountPrice || priceInfo?.min || product.price.amount
|
|
204
|
+
const originalPrice = product.price.amount
|
|
205
|
+
|
|
206
|
+
// Add to Cart 按钮点击处理
|
|
207
|
+
const handleAddToCart = (e: React.MouseEvent) => {
|
|
208
|
+
e.preventDefault()
|
|
209
|
+
e.stopPropagation()
|
|
210
|
+
if (onAddToCart) {
|
|
211
|
+
onAddToCart(product)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return (
|
|
216
|
+
<div key={`product-column-${index}`} className="flex flex-1 flex-col items-center">
|
|
217
|
+
{/* 产品选择下拉框 */}
|
|
218
|
+
<div className="mb-4 w-full">
|
|
219
|
+
<select
|
|
220
|
+
value={product.shopifyId}
|
|
221
|
+
onChange={e => handleProductChange(index, e.target.value)}
|
|
222
|
+
className="w-full rounded-lg border border-[#DADCE0] bg-[#F5F6F7] px-3 py-2 text-sm font-bold leading-[1.4] tracking-[-0.02em] text-[#1D1D1F]"
|
|
223
|
+
style={{
|
|
224
|
+
appearance: 'none',
|
|
225
|
+
backgroundImage:
|
|
226
|
+
"url(\"data:image/svg+xml,%3Csvg width='12' height='8' viewBox='0 0 12 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%231D1D1F' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\")",
|
|
227
|
+
backgroundRepeat: 'no-repeat',
|
|
228
|
+
backgroundPosition: 'right 12px center',
|
|
229
|
+
paddingRight: '32px',
|
|
230
|
+
}}
|
|
231
|
+
>
|
|
232
|
+
{allProducts.map(p => (
|
|
233
|
+
<option key={p.shopifyId} value={p.shopifyId}>
|
|
234
|
+
{p.title.length > 30 ? `${p.title.slice(0, 30)}...` : p.title}
|
|
235
|
+
</option>
|
|
236
|
+
))}
|
|
237
|
+
</select>
|
|
238
|
+
</div>
|
|
239
|
+
|
|
240
|
+
{/* 产品图片 */}
|
|
241
|
+
<a
|
|
242
|
+
href={product.productUrl}
|
|
243
|
+
target="_blank"
|
|
244
|
+
rel="noopener noreferrer"
|
|
245
|
+
className="mb-4 block w-full max-w-[160px]"
|
|
246
|
+
>
|
|
247
|
+
<div className="aspect-square w-full overflow-hidden rounded-lg">
|
|
248
|
+
{product.imageUrl ? (
|
|
249
|
+
<img
|
|
250
|
+
src={product.imageUrl}
|
|
251
|
+
alt={product.title}
|
|
252
|
+
className="size-full object-contain"
|
|
253
|
+
loading="lazy"
|
|
254
|
+
/>
|
|
255
|
+
) : (
|
|
256
|
+
<div className="flex size-full items-center justify-center text-gray-400">
|
|
257
|
+
<svg className="size-12" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
258
|
+
<path
|
|
259
|
+
strokeLinecap="round"
|
|
260
|
+
strokeLinejoin="round"
|
|
261
|
+
strokeWidth={2}
|
|
262
|
+
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
|
|
263
|
+
/>
|
|
264
|
+
</svg>
|
|
265
|
+
</div>
|
|
266
|
+
)}
|
|
267
|
+
</div>
|
|
268
|
+
</a>
|
|
269
|
+
|
|
270
|
+
{/* 价格展示(带划线价) */}
|
|
271
|
+
<div className="mb-4 flex flex-col items-center gap-1">
|
|
272
|
+
<div className="flex items-center gap-2">
|
|
273
|
+
{/* 当前价格(折扣价或原价) */}
|
|
274
|
+
<span className="text-base font-bold leading-[1.2] tracking-[-0.02em] text-[#1D1D1F]">
|
|
275
|
+
{formatPrice(currentPrice, priceInfo?.currency || product.price.currency)}
|
|
276
|
+
</span>
|
|
277
|
+
{/* 划线价 - 仅在有折扣时显示 */}
|
|
278
|
+
{hasDiscount && discountPrice && (
|
|
279
|
+
<span className="text-base font-bold leading-[1.2] tracking-[-0.02em] text-[#4A4C56] line-through">
|
|
280
|
+
{formatPrice(originalPrice, product.price.currency)}
|
|
281
|
+
</span>
|
|
282
|
+
)}
|
|
283
|
+
</div>
|
|
284
|
+
</div>
|
|
285
|
+
|
|
286
|
+
{/* Add to Cart 按钮 */}
|
|
287
|
+
{onAddToCart && (
|
|
288
|
+
<button
|
|
289
|
+
type="button"
|
|
290
|
+
onClick={handleAddToCart}
|
|
291
|
+
className="mb-3 w-fit rounded-full px-[20px] py-[10px] text-center text-sm font-bold leading-[1.2] tracking-[-0.04em] text-white"
|
|
292
|
+
style={{ backgroundColor: '#1D1D1F' }}
|
|
293
|
+
>
|
|
294
|
+
Add to Cart
|
|
295
|
+
</button>
|
|
296
|
+
)}
|
|
297
|
+
|
|
298
|
+
{/* 颜色选项(如果有variants) */}
|
|
299
|
+
{product.variants && product.variants.length > 1 && (
|
|
300
|
+
<div className="flex gap-2">
|
|
301
|
+
{product.variants.slice(0, 3).map((variant, idx) => (
|
|
302
|
+
<div
|
|
303
|
+
key={variant.id || idx}
|
|
304
|
+
className="size-6 rounded-full border-2 border-[#DADCE0]"
|
|
305
|
+
style={{ backgroundColor: variant.color || '#000' }}
|
|
306
|
+
title={variant.title}
|
|
307
|
+
/>
|
|
308
|
+
))}
|
|
309
|
+
</div>
|
|
310
|
+
)}
|
|
311
|
+
</div>
|
|
312
|
+
)
|
|
313
|
+
})}
|
|
314
|
+
</div>
|
|
315
|
+
|
|
316
|
+
{/* 对比表格区域 */}
|
|
317
|
+
<div className="flex flex-col gap-4 p-4">
|
|
318
|
+
{/* 遍历所有维度并渲染 */}
|
|
319
|
+
{Object.entries(dimensions).map(([key, dimension]) => {
|
|
320
|
+
if (!dimension || key === 'price') return null // price 已在顶部显示
|
|
321
|
+
return <div key={key}>{renderComparisonRow(dimension.label, dimension)}</div>
|
|
322
|
+
})}
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
)
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* 创建产品对比渲染器
|
|
330
|
+
*/
|
|
331
|
+
export const ProductComparisonRenderer: MessageRenderer = {
|
|
332
|
+
render: (content, isUser, isSystem) => {
|
|
333
|
+
if (content.type !== 'product_comparison' || !content.data) {
|
|
334
|
+
return null
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const comparisonData = content.data as ProductComparisonData & { onAddToCart?: (product: Product) => void }
|
|
338
|
+
|
|
339
|
+
return (
|
|
340
|
+
<ProductComparison
|
|
341
|
+
data={comparisonData}
|
|
342
|
+
isUser={isUser}
|
|
343
|
+
isSystem={isSystem}
|
|
344
|
+
onAddToCart={comparisonData.onAddToCart}
|
|
345
|
+
/>
|
|
346
|
+
)
|
|
347
|
+
},
|
|
348
|
+
}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 商品列表渲染器
|
|
3
|
+
* 显示多个商品的纵向列表,支持展开/收起
|
|
4
|
+
* 基于 specs/livechat-widget/data-model.md 的商品数据模型
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React, { useState } from 'react'
|
|
8
|
+
import type { MessageRenderer, ProductListContent, Product } from '../../types'
|
|
9
|
+
import { CURRENCY_SYMBOLS } from '../../constants.js'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 格式化价格
|
|
13
|
+
*/
|
|
14
|
+
function formatPrice(price: Product['price']): string {
|
|
15
|
+
const { amount, currency } = price
|
|
16
|
+
|
|
17
|
+
const symbol = CURRENCY_SYMBOLS[currency] || currency
|
|
18
|
+
return `${symbol}${amount.toFixed(2)}`
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 格式化折扣标签文本
|
|
23
|
+
* @param discount 折扣对象
|
|
24
|
+
* @param currency 货币代码
|
|
25
|
+
* @returns 格式化后的折扣文本(如 "$10 OFF" 或 "20% OFF")
|
|
26
|
+
*/
|
|
27
|
+
function formatDiscountLabel(
|
|
28
|
+
discount: { discount_type?: string; discount_value?: string | number },
|
|
29
|
+
currency: string
|
|
30
|
+
): string {
|
|
31
|
+
if (!discount.discount_type || discount.discount_value === undefined) {
|
|
32
|
+
return ''
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// 将 discount_value 转换为数字
|
|
36
|
+
const value =
|
|
37
|
+
typeof discount.discount_value === 'string' ? parseFloat(discount.discount_value) : discount.discount_value
|
|
38
|
+
|
|
39
|
+
if (isNaN(value)) {
|
|
40
|
+
return ''
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (discount.discount_type === 'percentage') {
|
|
44
|
+
return `${Math.round(value)}% OFF`
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (discount.discount_type === 'fixed_amount') {
|
|
48
|
+
const symbol = CURRENCY_SYMBOLS[currency] || currency
|
|
49
|
+
return `${symbol}${Math.round(value)} OFF`
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return ''
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 紧凑型商品卡片(用于纵向列表)
|
|
57
|
+
*/
|
|
58
|
+
const CompactProductCard: React.FC<{
|
|
59
|
+
product: Product
|
|
60
|
+
onAddToCart?: (product: Product) => void
|
|
61
|
+
}> = ({ product, onAddToCart }) => {
|
|
62
|
+
const { title, description, price, imageUrl, productUrl, stockStatus, averageRating, variants } = product
|
|
63
|
+
|
|
64
|
+
const isOutOfStock = stockStatus === 'out_of_stock'
|
|
65
|
+
|
|
66
|
+
// 获取第一个变体的折扣信息
|
|
67
|
+
const firstVariant = variants?.[0]
|
|
68
|
+
const hasDiscount = firstVariant?.discount?.has_discount
|
|
69
|
+
const discountPrice = hasDiscount ? firstVariant?.discount?.discount_price : null
|
|
70
|
+
const discount = firstVariant?.discount
|
|
71
|
+
|
|
72
|
+
// 当前显示价格:有折扣时显示折扣价,否则显示原价
|
|
73
|
+
const currentPrice = discountPrice ? { amount: discountPrice, currency: price.currency } : price
|
|
74
|
+
|
|
75
|
+
// 格式化折扣标签
|
|
76
|
+
const discountLabel = discount && hasDiscount ? formatDiscountLabel(discount, price.currency) : ''
|
|
77
|
+
|
|
78
|
+
const handleAddToCart = (e: React.MouseEvent) => {
|
|
79
|
+
e.preventDefault()
|
|
80
|
+
e.stopPropagation()
|
|
81
|
+
if (onAddToCart) {
|
|
82
|
+
onAddToCart(product)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<div className="block w-full overflow-hidden rounded-2xl bg-[#F5F6F7] transition-shadow hover:shadow-md">
|
|
88
|
+
<a href={productUrl} target="_blank" rel="noopener noreferrer" className="block">
|
|
89
|
+
<div className="flex gap-2 p-4">
|
|
90
|
+
{/* 商品图片 */}
|
|
91
|
+
<div className=" flex shrink-0 items-center overflow-hidden rounded-md " style={{ width: '40%' }}>
|
|
92
|
+
<img
|
|
93
|
+
src={imageUrl}
|
|
94
|
+
alt={title}
|
|
95
|
+
className={`h-auto w-full object-cover ${isOutOfStock ? 'opacity-50' : ''}`}
|
|
96
|
+
loading="lazy"
|
|
97
|
+
/>
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
{/* 商品信息 */}
|
|
101
|
+
<div className="flex flex-1 flex-col justify-center gap-0.5">
|
|
102
|
+
{/* 折扣标签 */}
|
|
103
|
+
{discountLabel && (
|
|
104
|
+
<div
|
|
105
|
+
className="mb-1 w-fit rounded-full px-2 text-sm font-bold leading-none tracking-[-0.04em] text-white"
|
|
106
|
+
style={{ backgroundColor: '#005D8E', paddingTop: '6px', paddingBottom: '4px' }}
|
|
107
|
+
>
|
|
108
|
+
{discountLabel}
|
|
109
|
+
</div>
|
|
110
|
+
)}
|
|
111
|
+
|
|
112
|
+
{/* 标题 */}
|
|
113
|
+
<h4 className="line-clamp-2 text-base font-bold leading-[1.4] tracking-[-0.02em] text-[#080A0F]">
|
|
114
|
+
{title}
|
|
115
|
+
</h4>
|
|
116
|
+
|
|
117
|
+
{/* 描述(可选) */}
|
|
118
|
+
{description && (
|
|
119
|
+
<p className="line-clamp-2 text-sm font-bold leading-[1.4] tracking-[-0.02em] text-[#1D1D1F]">
|
|
120
|
+
{description}
|
|
121
|
+
</p>
|
|
122
|
+
)}
|
|
123
|
+
|
|
124
|
+
{/* 价格和评分 */}
|
|
125
|
+
<div className="mt-4 flex items-center gap-2">
|
|
126
|
+
<div className="flex items-center gap-1">
|
|
127
|
+
{/* 当前价格(有折扣时显示折扣价,否则显示原价) */}
|
|
128
|
+
<span className="text-base font-bold leading-[1.4] tracking-[-0.02em] text-[#1D1D1F]">
|
|
129
|
+
{formatPrice(currentPrice)}
|
|
130
|
+
</span>
|
|
131
|
+
{/* 原价(划线价)- 仅在有折扣时显示 */}
|
|
132
|
+
{hasDiscount && (
|
|
133
|
+
<span className="text-base font-bold leading-[1.4] tracking-[-0.02em] text-[#6D6D6F] line-through">
|
|
134
|
+
{formatPrice(price)}
|
|
135
|
+
</span>
|
|
136
|
+
)}
|
|
137
|
+
</div>
|
|
138
|
+
{/* 评分(可选) */}
|
|
139
|
+
{averageRating !== undefined && (
|
|
140
|
+
<div className="flex items-center gap-0.5 text-xs text-gray-600">
|
|
141
|
+
<span className="text-yellow-500">⭐</span>
|
|
142
|
+
<span>{averageRating.toFixed(1)}</span>
|
|
143
|
+
</div>
|
|
144
|
+
)}
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
{/* Add to Cart 按钮 - 在价格下方 */}
|
|
148
|
+
<button
|
|
149
|
+
type="button"
|
|
150
|
+
onClick={handleAddToCart}
|
|
151
|
+
className="mt-2 w-fit rounded-full px-[20px] py-[10px] text-center text-sm font-bold leading-[1.2] tracking-[-0.04em] text-white"
|
|
152
|
+
style={{ backgroundColor: '#1D1D1F' }}
|
|
153
|
+
>
|
|
154
|
+
Add to Cart
|
|
155
|
+
</button>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
</a>
|
|
159
|
+
</div>
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* 商品列表内部组件(支持展开/收起)
|
|
165
|
+
*/
|
|
166
|
+
const ProductListComponent: React.FC<{
|
|
167
|
+
products: Product[]
|
|
168
|
+
title?: string
|
|
169
|
+
onAddToCart?: (product: Product) => void
|
|
170
|
+
}> = ({ products, title, onAddToCart }) => {
|
|
171
|
+
const [isExpanded, setIsExpanded] = useState(false)
|
|
172
|
+
|
|
173
|
+
// 过滤掉 null 或无效的产品
|
|
174
|
+
const validProducts = products.filter(p => p && p.shopifyId)
|
|
175
|
+
|
|
176
|
+
// 默认显示前3个产品
|
|
177
|
+
const INITIAL_DISPLAY_COUNT = 3
|
|
178
|
+
const hasMore = validProducts.length > INITIAL_DISPLAY_COUNT
|
|
179
|
+
const displayedProducts = isExpanded ? validProducts : validProducts.slice(0, INITIAL_DISPLAY_COUNT)
|
|
180
|
+
|
|
181
|
+
return (
|
|
182
|
+
<div className="flex w-full flex-col gap-2">
|
|
183
|
+
{/* 列表标题(可选) */}
|
|
184
|
+
{title && <h3 className="text-sm font-semibold text-gray-900">{title}</h3>}
|
|
185
|
+
|
|
186
|
+
{/* 纵向排列的商品列表 */}
|
|
187
|
+
<div className="flex flex-col gap-1.5">
|
|
188
|
+
{displayedProducts.map((product, index) => {
|
|
189
|
+
if (!product || !product.shopifyId) return null
|
|
190
|
+
return <CompactProductCard key={product.shopifyId} product={product} onAddToCart={onAddToCart} />
|
|
191
|
+
})}
|
|
192
|
+
</div>
|
|
193
|
+
|
|
194
|
+
{/* Learn More 按钮 */}
|
|
195
|
+
{hasMore && (
|
|
196
|
+
<button
|
|
197
|
+
type="button"
|
|
198
|
+
onClick={() => setIsExpanded(!isExpanded)}
|
|
199
|
+
className="flex items-center justify-center gap-1.5 px-3 py-2 text-[14px] font-bold leading-[1.2] tracking-tighter text-[#080A0F]"
|
|
200
|
+
>
|
|
201
|
+
<span>{isExpanded ? 'Show Less' : 'Learn More'}</span>
|
|
202
|
+
<svg
|
|
203
|
+
width="14"
|
|
204
|
+
height="14"
|
|
205
|
+
viewBox="0 0 24 24"
|
|
206
|
+
fill="none"
|
|
207
|
+
stroke="currentColor"
|
|
208
|
+
strokeWidth="2"
|
|
209
|
+
strokeLinecap="round"
|
|
210
|
+
strokeLinejoin="round"
|
|
211
|
+
className={`transition-transform ${isExpanded ? 'rotate-180' : ''}`}
|
|
212
|
+
>
|
|
213
|
+
<polyline points="6 9 12 15 18 9" />
|
|
214
|
+
</svg>
|
|
215
|
+
</button>
|
|
216
|
+
)}
|
|
217
|
+
</div>
|
|
218
|
+
)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* 商品列表渲染器
|
|
223
|
+
*
|
|
224
|
+
* 功能:
|
|
225
|
+
* - 纵向展示多个商品
|
|
226
|
+
* - 默认显示前3个产品
|
|
227
|
+
* - 支持展开/收起查看全部
|
|
228
|
+
* - 紧凑型卡片设计
|
|
229
|
+
* - 可选标题
|
|
230
|
+
*
|
|
231
|
+
* 布局:
|
|
232
|
+
* ```
|
|
233
|
+
* 标题(可选)
|
|
234
|
+
* ┌─────────────────┐
|
|
235
|
+
* │ [图] 商品标题 │
|
|
236
|
+
* │ $29.99 │
|
|
237
|
+
* └─────────────────┘
|
|
238
|
+
* ┌─────────────────┐
|
|
239
|
+
* │ [图] 商品标题 │
|
|
240
|
+
* │ $39.99 │
|
|
241
|
+
* └─────────────────┘
|
|
242
|
+
* ┌─────────────────┐
|
|
243
|
+
* │ [图] 商品标题 │
|
|
244
|
+
* │ $49.99 │
|
|
245
|
+
* └─────────────────┘
|
|
246
|
+
* [ Learn More ↓ ]
|
|
247
|
+
* ```
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```tsx
|
|
251
|
+
* const content: ProductListContent = {
|
|
252
|
+
* type: 'product_list',
|
|
253
|
+
* data: {
|
|
254
|
+
* title: '相关商品推荐',
|
|
255
|
+
* products: [product1, product2, product3, product4, product5]
|
|
256
|
+
* }
|
|
257
|
+
* }
|
|
258
|
+
* <ProductList.render(content, false, false) />
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
export const ProductList: MessageRenderer = {
|
|
262
|
+
render: content => {
|
|
263
|
+
const productListContent = content as ProductListContent
|
|
264
|
+
const { products, title, onAddToCart } = productListContent.data
|
|
265
|
+
|
|
266
|
+
// 过滤掉 null 或无效的产品
|
|
267
|
+
const validProducts = products?.filter(p => p && p.shopifyId) || []
|
|
268
|
+
|
|
269
|
+
if (validProducts.length === 0) {
|
|
270
|
+
return null
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return <ProductListComponent products={validProducts} title={title} onAddToCart={onAddToCart} />
|
|
274
|
+
},
|
|
275
|
+
}
|