@anker-in/campaign-ui 0.2.11-beta.9 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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/credits/context/provider.d.ts +1 -0
- package/dist/cjs/components/credits/context/provider.js +1 -1
- package/dist/cjs/components/credits/context/provider.js.map +2 -2
- package/dist/cjs/components/credits/creditsAnkersolixTask/CreditsAnkersolixTask.js +1 -1
- package/dist/cjs/components/credits/creditsAnkersolixTask/CreditsAnkersolixTask.js.map +2 -2
- package/dist/cjs/components/credits/creditsBanner/index.js +1 -1
- package/dist/cjs/components/credits/creditsBanner/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/creditsInfoCard/index.js +1 -1
- package/dist/cjs/components/credits/creditsInfoCard/index.js.map +2 -2
- 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/creditsRedeemList/CreditsRedeemList.js +1 -1
- package/dist/cjs/components/credits/creditsRedeemList/CreditsRedeemList.js.map +2 -2
- 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/RedeemableItem.js +1 -1
- package/dist/cjs/components/credits/creditsRedeemList/RedeemableItem.js.map +3 -3
- package/dist/cjs/components/registration/authCodeActivate/index.js +1 -1
- package/dist/cjs/components/registration/authCodeActivate/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 +1 -0
- package/dist/cjs/templates/Credits.js.map +2 -2
- 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/credits/context/provider.d.ts +1 -0
- package/dist/esm/components/credits/context/provider.js +1 -1
- package/dist/esm/components/credits/context/provider.js.map +2 -2
- package/dist/esm/components/credits/creditsAnkersolixTask/CreditsAnkersolixTask.js +1 -1
- package/dist/esm/components/credits/creditsAnkersolixTask/CreditsAnkersolixTask.js.map +2 -2
- package/dist/esm/components/credits/creditsBanner/index.js +1 -1
- package/dist/esm/components/credits/creditsBanner/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/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/creditsRedeemList/CreditsRedeemList.js +1 -1
- package/dist/esm/components/credits/creditsRedeemList/CreditsRedeemList.js.map +2 -2
- 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/RedeemableItem.js +1 -1
- package/dist/esm/components/credits/creditsRedeemList/RedeemableItem.js.map +3 -3
- package/dist/esm/components/registration/authCodeActivate/index.js +1 -1
- package/dist/esm/components/registration/authCodeActivate/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 +1 -0
- package/dist/esm/templates/Credits.js.map +2 -2
- package/package.json +19 -19
- package/src/components/credits/context/provider.tsx +2 -0
- package/src/components/credits/creditsAnkersolixTask/CreditsAnkersolixTask.tsx +1 -1
- package/src/components/credits/creditsBanner/index.tsx +1 -2
- package/src/components/credits/creditsCash/CreditsCash.tsx +5 -2
- package/src/components/credits/creditsCash/RedeemableItem.tsx +8 -8
- package/src/components/credits/creditsInfoCard/index.tsx +8 -2
- package/src/components/credits/creditsMemberPrice/CreditsMemberPrice.tsx +70 -19
- package/src/components/credits/creditsMemberPrice/MemberPriceItem.tsx +13 -8
- package/src/components/credits/creditsRedeemList/CreditsRedeemList.tsx +5 -5
- package/src/components/credits/creditsRedeemList/RedeemProductModal/ProductInfo.tsx +6 -4
- package/src/components/credits/creditsRedeemList/RedeemableItem.tsx +18 -5
- package/src/components/registration/authCodeActivate/index.tsx +2 -0
- package/src/templates/Credits.tsx +1 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LiveChat 主组件
|
|
3
|
+
* 集成所有子组件,提供完整的聊天功能
|
|
4
|
+
* 基于 specs/livechat-widget/plan.md 的三层架构设计
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import type { LiveChatWidgetProps } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* LiveChat 聊天组件
|
|
10
|
+
*
|
|
11
|
+
* 功能:
|
|
12
|
+
* - 气泡弹窗聊天界面
|
|
13
|
+
* - SSE 流式消息接收
|
|
14
|
+
* - 会话管理(userId, sessionId)
|
|
15
|
+
* - 历史消息加载
|
|
16
|
+
* - 多种消息类型渲染
|
|
17
|
+
* - 自定义扩展机制
|
|
18
|
+
*
|
|
19
|
+
* 架构:
|
|
20
|
+
* - UI Layer: ChatBubble, ChatWindow, MessageList, etc.
|
|
21
|
+
* - Logic Layer: useChatState, useChatAPI, useSession
|
|
22
|
+
* - Core Layer: MessageRendererRegistry, 自定义渲染器
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```tsx
|
|
26
|
+
* // 使用默认位置(右下角)
|
|
27
|
+
* <LiveChatWidget
|
|
28
|
+
* apiBaseUrl="https://beta-api-livechat.anker.com"
|
|
29
|
+
* site="www.eufy.com"
|
|
30
|
+
* welcomeMessage="你好!我是 AI 助手"
|
|
31
|
+
* onMessageSend={(msg) => console.log('Sent:', msg)}
|
|
32
|
+
* />
|
|
33
|
+
*
|
|
34
|
+
* // 使用自定义位置
|
|
35
|
+
* <LiveChatWidget
|
|
36
|
+
* apiBaseUrl="https://beta-api-livechat.anker.com"
|
|
37
|
+
* site="www.eufy.com"
|
|
38
|
+
* position={{ bottom: "20px", right: "30px" }}
|
|
39
|
+
* onMessageSend={(msg) => console.log('Sent:', msg)}
|
|
40
|
+
* />
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare const LiveChatWidget: React.FC<LiveChatWidgetProps>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var le=Object.create;var q=Object.defineProperty;var me=Object.getOwnPropertyDescriptor;var fe=Object.getOwnPropertyNames;var ge=Object.getPrototypeOf,ye=Object.prototype.hasOwnProperty;var he=(n,r)=>{for(var o in r)q(n,o,{get:r[o],enumerable:!0})},H=(n,r,o,_)=>{if(r&&typeof r=="object"||typeof r=="function")for(let m of fe(r))!ye.call(n,m)&&m!==o&&q(n,m,{get:()=>r[m],enumerable:!(_=me(r,m))||_.enumerable});return n};var J=(n,r,o)=>(o=n!=null?le(ge(n)):{},H(r||!n||!n.__esModule?q(o,"default",{value:n,enumerable:!0}):o,n)),_e=n=>H(q({},"__esModule",{value:!0}),n);var we={};he(we,{LiveChatWidget:()=>Ce});module.exports=_e(we);var l=require("react/jsx-runtime"),p=J(require("react")),Q=J(require("@radix-ui/react-dialog")),K=require("./components/ChatBubble"),X=require("./components/ChatWindow"),Y=require("./hooks/useChatState"),Z=require("./hooks/useChatAPI"),j=require("./utils/messageRenderers"),k=require("./utils/validation"),z=require("./utils/productTransformers.js"),U=require("./utils/cartTransformers.js"),a=require("./components/MessageContent/index.js");const Ce=({apiBaseUrl:n,site:r,loginUserId:o,cartId:_,accessToken:m,position:b,welcomeMessage:C,quickReplies:f,customRenderers:v,logoUrl:ee,title:te,chatBubbleIcon:se,onOpen:re,onClose:ae,onMessageSend:B,onError:g,onAddToCart:M,onCart:L,showNewSessionButton:ie})=>{const ne=(0,Y.useChatState)({welcomeMessage:C,site:r,onOpen:re,onClose:ae,onMessageSend:B,onError:g,onAddToCart:M,onCart:L}),{messages:oe,isOpen:D,userId:u,sessionId:F,inputValue:A,isStreaming:de,openChat:$,closeChat:E,setInputValue:W,addMessage:y,setMessages:N,clearMessages:P,handleSSEEvent:T,saveSession:R,clearSession:w}=ne,{sendMessageStream:V,createSession:h}=(0,Z.useChatAPI)({apiBaseUrl:n,onError:g}),O=p.default.useRef(async e=>{}),ce=p.default.useMemo(()=>{const e=new j.MessageRendererRegistry;e.register("text",a.TextBlock),e.register("product_card",a.ProductCard),e.register("product_list",a.ProductList),e.register("product_comparison",a.ProductComparisonRenderer),e.register("policy",a.PolicyBlock),e.register("thinking",a.ThinkingBlock),e.register("error",a.ErrorBlock),e.register("faq_list",a.FAQListRenderer),e.register("promotion_list",a.PromotionListRenderer),e.register("cart",a.CartCard);const s=(0,a.createQuickRepliesRenderer)(i=>{O.current(i.value)});return e.register("quick_replies",s),v&&e.registerMany(v),e},[v]);(0,p.useEffect)(()=>{if(!D||!u)return;const e=F;e?pe(e):S()},[D,u]);const G=(0,p.useCallback)(e=>{if(Array.isArray(e.content))return e;const s=[];typeof e.content=="string"&&e.content.trim()&&s.push({type:"text",text:e.content});const i=e.structuredContent||e.structured_content;return Array.isArray(i)&&i.forEach(t=>{if(t.type==="product_list"&&Array.isArray(t.data))s.push({type:"product_list",data:{products:(0,z.transformProducts)(t.data,r),title:void 0}});else if(t.type==="quick_replies"&&t.data?.replies)s.push({type:"quick_replies",data:{replies:t.data.replies}});else if(t.type==="policy"&&t.data?.title&&t.data?.content)s.push({type:"policy",data:{title:t.data.title,content:t.data.content}});else if(t.type==="product_comparison"&&t.data?.products&&t.data?.dimensions)s.push({type:"product_comparison",data:{products:(0,z.transformProducts)(t.data.products,r),dimensions:t.data.dimensions,onAddToCart:M}});else if(t.type==="faq_list"&&t.data?.found!==void 0)s.push({type:"faq_list",data:t.data});else if(t.type==="promotion_list"&&t.data?.found!==void 0)s.push({type:"promotion_list",data:t.data});else if(t.type==="cart"&&t.data?.id!==void 0){const d=(0,U.transformCartData)(t.data);s.push({type:"cart",data:{...d,onCart:L}})}else s.push(t)}),s.length===0&&s.push({type:"text",text:""}),{...e,content:s}},[r,L,M]),S=(0,p.useCallback)(async()=>{if(u)try{const e=await h({user_id:u,site:r,real_user_id:o});if(e.success){R(e.sessionId),P();const s=e.welcomeMessage||C;if(s){const i=[{type:"text",text:s}],t=e.quickQuestions;if(t&&t.length>0){const d=t.map((x,c)=>({id:`quick-${c}`,label:x,value:x}));i.push({type:"quick_replies",data:{replies:d}})}else f&&f.length>0&&i.push({type:"quick_replies",data:{replies:f}});y({id:`welcome-${Date.now()}`,role:"assistant",content:i,timestamp:Date.now()})}}}catch(e){console.error("[LiveChatWidget] Failed to create new session:",e),g?.(e)}},[u,r,o,h,R,P,C,f,y,g]),pe=(0,p.useCallback)(async e=>{try{const s=await h({user_id:u,session_id:e,site:r,real_user_id:o});if(s.success&&s.resumed)if(s.messages&&s.messages.length>0){const i=s.messages.map(G);N(i)}else{P();const i=s.welcomeMessage||C;if(i){const t=[{type:"text",text:i}],d=s.quickQuestions;if(d&&d.length>0){const x=d.map((c,ue)=>({id:`quick-${ue}`,label:c,value:c}));t.push({type:"quick_replies",data:{replies:x}})}else f&&f.length>0&&t.push({type:"quick_replies",data:{replies:f}});y({id:`welcome-${Date.now()}`,role:"assistant",content:t,timestamp:Date.now()})}}else s.resumed||(w(),S())}catch(s){console.error("[LiveChatWidget] Failed to resume session:",s),w(),S()}},[u,r,o,h,N,w,P,G,S,C,f,y]),I=(0,p.useCallback)(async e=>{const s=e||A.trim();if(!s)return;e||W("");const i=(0,k.sanitizeInput)(s);if(!i){g?.(new Error("\u65E0\u6548\u7684\u6D88\u606F\u5185\u5BB9"));return}const t={id:`user-${Date.now()}`,role:"user",content:[{type:"text",text:i}],timestamp:Date.now()};y(t),B?.(i);try{let d=F;if(!d){const c=await h({user_id:u,site:r,real_user_id:o});if(c.success)d=c.sessionId,R(d);else throw new Error("Failed to create session")}await V({message:i,user_id:u,session_id:d,context:{cartId:_,accessToken:m,real_user_id:o}},c=>{T(c),c.event==="status"&&c.data.type==="session_expired"&&w()})}catch(d){console.error("[LiveChatWidget] Failed to send message:",d),g?.(d)}},[A,u,F,r,o,_,m,W,y,h,V,T,R,w,B,g]);return p.default.useEffect(()=>{O.current=I},[I]),(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(K.ChatBubble,{position:b,onClick:$,visible:!D,iconImageUrl:se}),(0,l.jsx)(Q.Root,{open:D,onOpenChange:e=>e?$():E(),children:(0,l.jsx)(Q.Portal,{children:(0,l.jsx)(Q.Content,{className:"livechat-window-enter",style:{position:"fixed",zIndex:9998},children:(0,l.jsx)(X.ChatWindow,{messages:oe,inputValue:A,onInputChange:W,onSend:()=>I(),onClose:E,onNewSession:S,title:te,logoUrl:ee,isSending:de,rendererRegistry:ce,inputPlaceholder:"",onAddToCart:M,showNewSessionButton:ie})})})})]})};
|
|
2
|
+
//# sourceMappingURL=LiveChatWidget.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/components/LiveChatWidget/LiveChatWidget.tsx"],
|
|
4
|
+
"sourcesContent": ["/**\n * LiveChat \u4E3B\u7EC4\u4EF6\n * \u96C6\u6210\u6240\u6709\u5B50\u7EC4\u4EF6\uFF0C\u63D0\u4F9B\u5B8C\u6574\u7684\u804A\u5929\u529F\u80FD\n * \u57FA\u4E8E specs/livechat-widget/plan.md \u7684\u4E09\u5C42\u67B6\u6784\u8BBE\u8BA1\n */\n\nimport React, { useEffect, useCallback } from 'react'\nimport * as Dialog from '@radix-ui/react-dialog'\nimport type {\n LiveChatWidgetProps,\n QuickReply,\n Message,\n MessageContent,\n ChatStreamRequest,\n BackendCartData,\n} from './types'\nimport { ChatBubble } from './components/ChatBubble'\nimport { ChatWindow } from './components/ChatWindow'\nimport { useChatState } from './hooks/useChatState'\nimport { useChatAPI } from './hooks/useChatAPI'\nimport { MessageRendererRegistry } from './utils/messageRenderers'\nimport { sanitizeInput } from './utils/validation'\nimport { transformProducts } from './utils/productTransformers.js'\nimport { transformCartData } from './utils/cartTransformers.js'\nimport {\n TextBlock,\n ProductCard,\n ProductList,\n ProductComparisonRenderer,\n PolicyBlock,\n createQuickRepliesRenderer,\n ThinkingBlock,\n ErrorBlock,\n FAQListRenderer,\n PromotionListRenderer,\n CartCard,\n} from './components/MessageContent/index.js'\n\n/**\n * LiveChat \u804A\u5929\u7EC4\u4EF6\n *\n * \u529F\u80FD\uFF1A\n * - \u6C14\u6CE1\u5F39\u7A97\u804A\u5929\u754C\u9762\n * - SSE \u6D41\u5F0F\u6D88\u606F\u63A5\u6536\n * - \u4F1A\u8BDD\u7BA1\u7406\uFF08userId, sessionId\uFF09\n * - \u5386\u53F2\u6D88\u606F\u52A0\u8F7D\n * - \u591A\u79CD\u6D88\u606F\u7C7B\u578B\u6E32\u67D3\n * - \u81EA\u5B9A\u4E49\u6269\u5C55\u673A\u5236\n *\n * \u67B6\u6784\uFF1A\n * - UI Layer: ChatBubble, ChatWindow, MessageList, etc.\n * - Logic Layer: useChatState, useChatAPI, useSession\n * - Core Layer: MessageRendererRegistry, \u81EA\u5B9A\u4E49\u6E32\u67D3\u5668\n *\n * @example\n * ```tsx\n * // \u4F7F\u7528\u9ED8\u8BA4\u4F4D\u7F6E\uFF08\u53F3\u4E0B\u89D2\uFF09\n * <LiveChatWidget\n * apiBaseUrl=\"https://beta-api-livechat.anker.com\"\n * site=\"www.eufy.com\"\n * welcomeMessage=\"\u4F60\u597D\uFF01\u6211\u662F AI \u52A9\u624B\"\n * onMessageSend={(msg) => console.log('Sent:', msg)}\n * />\n *\n * // \u4F7F\u7528\u81EA\u5B9A\u4E49\u4F4D\u7F6E\n * <LiveChatWidget\n * apiBaseUrl=\"https://beta-api-livechat.anker.com\"\n * site=\"www.eufy.com\"\n * position={{ bottom: \"20px\", right: \"30px\" }}\n * onMessageSend={(msg) => console.log('Sent:', msg)}\n * />\n * ```\n */\nexport const LiveChatWidget: React.FC<LiveChatWidgetProps> = ({\n apiBaseUrl,\n site,\n loginUserId,\n cartId,\n accessToken,\n position,\n welcomeMessage,\n quickReplies,\n customRenderers,\n logoUrl,\n title,\n chatBubbleIcon,\n onOpen,\n onClose,\n onMessageSend,\n onError,\n onAddToCart,\n onCart,\n showNewSessionButton,\n}) => {\n // \u72B6\u6001\u7BA1\u7406\n const chatState = useChatState({\n welcomeMessage,\n site,\n onOpen,\n onClose,\n onMessageSend,\n onError,\n onAddToCart,\n onCart,\n })\n\n const {\n messages,\n isOpen,\n userId,\n sessionId,\n inputValue,\n isStreaming,\n openChat,\n closeChat,\n setInputValue,\n addMessage,\n setMessages,\n clearMessages,\n handleSSEEvent,\n saveSession,\n clearSession,\n } = chatState\n\n // API \u8C03\u7528\n const { sendMessageStream, createSession } = useChatAPI({\n apiBaseUrl,\n onError,\n })\n\n // \u4F7F\u7528 ref \u5B58\u50A8\u6700\u65B0\u7684 handleSendMessage\uFF0C\u907F\u514D\u5FAA\u73AF\u4F9D\u8D56\n const handleSendMessageRef = React.useRef<(_message?: string) => Promise<void>>(async (_message?: string) => {})\n\n // \u6D88\u606F\u6E32\u67D3\u5668\u6CE8\u518C\u8868\n const rendererRegistry = React.useMemo(() => {\n const registry = new MessageRendererRegistry()\n\n // \u6CE8\u518C\u9ED8\u8BA4\u6E32\u67D3\u5668\n registry.register('text', TextBlock)\n registry.register('product_card', ProductCard)\n registry.register('product_list', ProductList)\n registry.register('product_comparison', ProductComparisonRenderer)\n registry.register('policy', PolicyBlock)\n registry.register('thinking', ThinkingBlock)\n registry.register('error', ErrorBlock)\n registry.register('faq_list', FAQListRenderer)\n registry.register('promotion_list', PromotionListRenderer)\n registry.register('cart', CartCard)\n\n // \u6CE8\u518C\u5FEB\u6377\u56DE\u590D\u6E32\u67D3\u5668\uFF08\u5E26\u56DE\u8C03\uFF09\n const quickRepliesRenderer = createQuickRepliesRenderer((reply: QuickReply) => {\n // \u4F7F\u7528 ref \u8C03\u7528\u6700\u65B0\u7684 handleSendMessage\n handleSendMessageRef.current(reply.value)\n })\n registry.register('quick_replies', quickRepliesRenderer)\n\n // \u6CE8\u518C\u81EA\u5B9A\u4E49\u6E32\u67D3\u5668\n if (customRenderers) {\n registry.registerMany(customRenderers)\n }\n\n return registry\n }, [customRenderers])\n\n /**\n * T043: \u6253\u5F00\u804A\u5929\u7A97\u53E3\u65F6\u521D\u59CB\u5316\u4F1A\u8BDD\n * \u4F7F\u7528 API v2.0.0 \u7684\u7EDF\u4E00\u63A5\u53E3\uFF1A\n * - \u5982\u679C\u6CA1\u6709 sessionId\uFF0C\u521B\u5EFA\u65B0\u4F1A\u8BDD\n * - \u5982\u679C\u6709 sessionId\uFF0C\u6062\u590D\u4F1A\u8BDD\u5E76\u52A0\u8F7D\u5386\u53F2\u6D88\u606F\n */\n useEffect(() => {\n if (!isOpen || !userId) return\n\n const currentSessionId = sessionId\n\n if (!currentSessionId) {\n // \u6CA1\u6709\u4F1A\u8BDD\uFF0C\u521B\u5EFA\u65B0\u4F1A\u8BDD\n handleCreateNewSession()\n } else {\n // \u6709\u4F1A\u8BDD\uFF0C\u5C1D\u8BD5\u6062\u590D\u4F1A\u8BDD\u548C\u5386\u53F2\u6D88\u606F\n handleResumeSession(currentSessionId)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isOpen, userId])\n\n /**\n * \u89C4\u8303\u5316\u6D88\u606F\u683C\u5F0F\uFF08\u786E\u4FDD content \u662F\u6570\u7EC4\uFF09\n * \u540E\u7AEF\u8FD4\u56DE\u683C\u5F0F\uFF1A\n * - content: \u5B57\u7B26\u4E32\uFF08\u6587\u672C\u5185\u5BB9\uFF09\n * - structuredContent: \u6570\u7EC4\uFF08\u7ED3\u6784\u5316\u5185\u5BB9\uFF0C\u5982\u4EA7\u54C1\u5217\u8868\u3001\u653F\u7B56\u7B49\uFF09\n * \u9700\u8981\u5408\u5E76\u4E3A\u7EDF\u4E00\u7684 content \u6570\u7EC4\u683C\u5F0F\n */\n const normalizeMessage = useCallback(\n (message: any): Message => {\n // \u5982\u679C content \u5DF2\u7ECF\u662F\u6570\u7EC4\uFF0C\u76F4\u63A5\u8FD4\u56DE\n if (Array.isArray(message.content)) {\n return message as Message\n }\n\n const contentBlocks: MessageContent[] = []\n\n // \u5904\u7406\u6587\u672C\u5185\u5BB9\n if (typeof message.content === 'string' && message.content.trim()) {\n contentBlocks.push({\n type: 'text',\n text: message.content,\n })\n }\n\n // \u5904\u7406\u7ED3\u6784\u5316\u5185\u5BB9\n // \u5386\u53F2\u6D88\u606F\u683C\u5F0F: structured_content: [{type, data}]\n const structuredData = message.structuredContent || message.structured_content\n\n if (Array.isArray(structuredData)) {\n structuredData.forEach((block: any) => {\n if (block.type === 'product_list' && Array.isArray(block.data)) {\n // \u8F6C\u6362\u4EA7\u54C1\u5217\u8868\u6570\u636E\u7ED3\u6784 - data \u76F4\u63A5\u662F\u4EA7\u54C1\u6570\u7EC4\n contentBlocks.push({\n type: 'product_list',\n data: {\n products: transformProducts(block.data, site),\n title: undefined, // \u5386\u53F2\u6D88\u606F\u4E0D\u5305\u542B title\n },\n })\n } else if (block.type === 'quick_replies' && block.data?.replies) {\n contentBlocks.push({\n type: 'quick_replies',\n data: {\n replies: block.data.replies,\n },\n })\n } else if (block.type === 'policy' && block.data?.title && block.data?.content) {\n contentBlocks.push({\n type: 'policy',\n data: {\n title: block.data.title,\n content: block.data.content,\n },\n })\n } else if (block.type === 'product_comparison' && block.data?.products && block.data?.dimensions) {\n // \u8F6C\u6362\u4EA7\u54C1\u5BF9\u6BD4\u6570\u636E\u7ED3\u6784\u5E76\u6CE8\u5165 onAddToCart \u56DE\u8C03\n contentBlocks.push({\n type: 'product_comparison',\n data: {\n products: transformProducts(block.data.products, site),\n dimensions: block.data.dimensions,\n onAddToCart: onAddToCart,\n },\n })\n } else if (block.type === 'faq_list' && block.data?.found !== undefined) {\n // FAQ \u5217\u8868\u5361\u7247 - \u76F4\u63A5\u4F7F\u7528\u540E\u7AEF\u6570\u636E\n contentBlocks.push({\n type: 'faq_list',\n data: block.data,\n })\n } else if (block.type === 'promotion_list' && block.data?.found !== undefined) {\n // \u4FC3\u9500\u6D3B\u52A8\u5217\u8868\u5361\u7247 - \u76F4\u63A5\u4F7F\u7528\u540E\u7AEF\u6570\u636E\n contentBlocks.push({\n type: 'promotion_list',\n data: block.data,\n })\n } else if (block.type === 'cart' && block.data?.id !== undefined) {\n // \u8D2D\u7269\u8F66\u5361\u7247 - \u8F6C\u6362\u540E\u7AEF\u6570\u636E\u683C\u5F0F\u5E76\u6CE8\u5165 onCart \u56DE\u8C03\n const transformedData = transformCartData(block.data as BackendCartData)\n contentBlocks.push({\n type: 'cart',\n data: {\n ...transformedData,\n onCart: onCart,\n },\n })\n } else {\n // \u5176\u4ED6\u7C7B\u578B\u76F4\u63A5\u6DFB\u52A0\n contentBlocks.push(block)\n }\n })\n }\n\n // \u5982\u679C\u6CA1\u6709\u4EFB\u4F55\u5185\u5BB9\u5757\uFF0C\u8FD4\u56DE\u7A7A\u6587\u672C\u5757\n if (contentBlocks.length === 0) {\n contentBlocks.push({\n type: 'text',\n text: '',\n })\n }\n\n return {\n ...message,\n content: contentBlocks,\n } as Message\n },\n [site, onCart, onAddToCart]\n )\n\n /**\n * \u521B\u5EFA\u65B0\u4F1A\u8BDD\n */\n const handleCreateNewSession = useCallback(async () => {\n if (!userId) return\n\n try {\n const response = await createSession({\n user_id: userId,\n site: site,\n real_user_id: loginUserId,\n })\n\n if (response.success) {\n // \u4FDD\u5B58\u65B0\u4F1A\u8BDD ID\n saveSession(response.sessionId)\n\n // \u6E05\u7A7A\u6D88\u606F\u5217\u8868\n clearMessages()\n\n // \u4F7F\u7528\u540E\u7AEF\u8FD4\u56DE\u7684\u6B22\u8FCE\u6D88\u606F\uFF0C\u5982\u679C\u6CA1\u6709\u5219\u4F7F\u7528 props \u4E2D\u7684\u9ED8\u8BA4\u503C\n const messageText = response.welcomeMessage || welcomeMessage\n\n if (messageText) {\n const welcomeContent: MessageContent[] = [{ type: 'text', text: messageText }]\n\n // \u4F7F\u7528\u540E\u7AEF\u8FD4\u56DE\u7684\u5FEB\u6377\u95EE\u9898\uFF0C\u5982\u679C\u6CA1\u6709\u5219\u4F7F\u7528 props \u4E2D\u7684\u5FEB\u6377\u56DE\u590D\n const questions = response.quickQuestions\n if (questions && questions.length > 0) {\n // \u5C06\u540E\u7AEF\u7684 quickQuestions (\u5B57\u7B26\u4E32\u6570\u7EC4) \u8F6C\u6362\u4E3A QuickReply \u683C\u5F0F\n const quickRepliesFromBackend = questions.map((question, index) => ({\n id: `quick-${index}`,\n label: question,\n value: question,\n }))\n\n welcomeContent.push({\n type: 'quick_replies',\n data: {\n replies: quickRepliesFromBackend,\n },\n })\n } else if (quickReplies && quickReplies.length > 0) {\n // \u5982\u679C\u540E\u7AEF\u6CA1\u6709\u8FD4\u56DE\uFF0C\u4F7F\u7528 props \u4E2D\u7684\u5FEB\u6377\u56DE\u590D\n welcomeContent.push({\n type: 'quick_replies',\n data: {\n replies: quickReplies,\n },\n })\n }\n\n addMessage({\n id: `welcome-${Date.now()}`,\n role: 'assistant',\n content: welcomeContent,\n timestamp: Date.now(),\n })\n }\n }\n } catch (error) {\n console.error('[LiveChatWidget] Failed to create new session:', error)\n onError?.(error as Error)\n }\n }, [\n userId,\n site,\n loginUserId,\n createSession,\n saveSession,\n clearMessages,\n welcomeMessage,\n quickReplies,\n addMessage,\n onError,\n ])\n\n /**\n * \u6062\u590D\u4F1A\u8BDD\u548C\u5386\u53F2\u6D88\u606F\uFF08\u4F7F\u7528\u65B0\u7684 API v2.0.0\uFF09\n */\n const handleResumeSession = useCallback(\n async (existingSessionId: string) => {\n try {\n const response = await createSession({\n user_id: userId,\n session_id: existingSessionId,\n site: site,\n real_user_id: loginUserId,\n })\n\n if (response.success && response.resumed) {\n // \u4F1A\u8BDD\u6062\u590D\u6210\u529F\n if (response.messages && response.messages.length > 0) {\n // \u6709\u5386\u53F2\u6D88\u606F\uFF0C\u89C4\u8303\u5316\u5E76\u52A0\u8F7D\n const normalizedMessages = response.messages.map(normalizeMessage)\n setMessages(normalizedMessages)\n } else {\n // \u6CA1\u6709\u5386\u53F2\u6D88\u606F\uFF0C\u663E\u793A\u6B22\u8FCE\u6D88\u606F\n clearMessages()\n\n // \u4F7F\u7528\u540E\u7AEF\u8FD4\u56DE\u7684\u6B22\u8FCE\u6D88\u606F\uFF0C\u5982\u679C\u6CA1\u6709\u5219\u4F7F\u7528 props \u4E2D\u7684\u9ED8\u8BA4\u503C\n const messageText = response.welcomeMessage || welcomeMessage\n\n if (messageText) {\n const welcomeContent: MessageContent[] = [{ type: 'text', text: messageText }]\n\n // \u4F7F\u7528\u540E\u7AEF\u8FD4\u56DE\u7684\u5FEB\u6377\u95EE\u9898\n const questions = response.quickQuestions\n if (questions && questions.length > 0) {\n const quickRepliesFromBackend = questions.map((question, index) => ({\n id: `quick-${index}`,\n label: question,\n value: question,\n }))\n\n welcomeContent.push({\n type: 'quick_replies',\n data: {\n replies: quickRepliesFromBackend,\n },\n })\n } else if (quickReplies && quickReplies.length > 0) {\n welcomeContent.push({\n type: 'quick_replies',\n data: {\n replies: quickReplies,\n },\n })\n }\n\n addMessage({\n id: `welcome-${Date.now()}`,\n role: 'assistant',\n content: welcomeContent,\n timestamp: Date.now(),\n })\n }\n }\n } else if (!response.resumed) {\n // \u4F1A\u8BDD\u65E0\u6548\u6216\u8FC7\u671F\uFF0C\u521B\u5EFA\u65B0\u4F1A\u8BDD\n clearSession()\n handleCreateNewSession()\n }\n } catch (error) {\n console.error('[LiveChatWidget] Failed to resume session:', error)\n // \u6062\u590D\u5931\u8D25\uFF0C\u6E05\u7A7A\u4F1A\u8BDD\u5E76\u521B\u5EFA\u65B0\u7684\n clearSession()\n handleCreateNewSession()\n }\n },\n [\n userId,\n site,\n loginUserId,\n createSession,\n setMessages,\n clearSession,\n clearMessages,\n normalizeMessage,\n handleCreateNewSession,\n welcomeMessage,\n quickReplies,\n addMessage,\n ]\n )\n\n /**\n * \u53D1\u9001\u6D88\u606F\n */\n const handleSendMessage = useCallback(\n async (message?: string) => {\n const textToSend = message || inputValue.trim()\n\n if (!textToSend) return\n\n // \u6E05\u7A7A\u8F93\u5165\u6846\n if (!message) {\n setInputValue('')\n }\n\n // \u8F93\u5165\u9A8C\u8BC1\n const sanitized = sanitizeInput(textToSend)\n if (!sanitized) {\n onError?.(new Error('\u65E0\u6548\u7684\u6D88\u606F\u5185\u5BB9'))\n return\n }\n\n // \u6DFB\u52A0\u7528\u6237\u6D88\u606F\u5230\u754C\u9762\n const userMessage = {\n id: `user-${Date.now()}`,\n role: 'user' as const,\n content: [{ type: 'text' as const, text: sanitized }],\n timestamp: Date.now(),\n }\n addMessage(userMessage)\n\n // \u89E6\u53D1\u6D88\u606F\u53D1\u9001\u56DE\u8C03\n onMessageSend?.(sanitized)\n\n try {\n // \u786E\u4FDD\u6709 sessionId\uFF0C\u5982\u679C\u6CA1\u6709\u5219\u5148\u521B\u5EFA\u4F1A\u8BDD\n let currentSessionId = sessionId\n if (!currentSessionId) {\n // \u6CA1\u6709\u4F1A\u8BDD\uFF0C\u521B\u5EFA\u65B0\u4F1A\u8BDD\n const response = await createSession({\n user_id: userId,\n site: site,\n real_user_id: loginUserId,\n })\n if (response.success) {\n currentSessionId = response.sessionId\n saveSession(currentSessionId)\n } else {\n throw new Error('Failed to create session')\n }\n }\n\n // \u6784\u5EFA\u8BF7\u6C42\u53C2\u6570\uFF08session_id \u73B0\u5728\u662F\u5FC5\u586B\u7684\uFF09\n const requestPayload: ChatStreamRequest = {\n message: sanitized,\n user_id: userId,\n session_id: currentSessionId,\n context: {\n cartId: cartId,\n accessToken: accessToken,\n real_user_id: loginUserId,\n },\n }\n\n // \u53D1\u9001\u6D88\u606F\u5230\u540E\u7AEF\n await sendMessageStream(requestPayload, event => {\n // \u5904\u7406 SSE \u4E8B\u4EF6\n handleSSEEvent(event)\n\n // \u7279\u6B8A\u5904\u7406\uFF1A\u4F1A\u8BDD\u8FC7\u671F\n if (event.event === 'status' && event.data.type === 'session_expired') {\n clearSession()\n }\n })\n } catch (error) {\n console.error('[LiveChatWidget] Failed to send message:', error)\n onError?.(error as Error)\n }\n },\n [\n inputValue,\n userId,\n sessionId,\n site,\n loginUserId,\n cartId,\n accessToken,\n setInputValue,\n addMessage,\n createSession,\n sendMessageStream,\n handleSSEEvent,\n saveSession,\n clearSession,\n onMessageSend,\n onError,\n ]\n )\n\n // \u66F4\u65B0 ref \u4EE5\u4FDD\u6301\u6700\u65B0\u7684 handleSendMessage\n React.useEffect(() => {\n handleSendMessageRef.current = handleSendMessage\n }, [handleSendMessage])\n\n return (\n <>\n {/* \u6C14\u6CE1\u6309\u94AE */}\n <ChatBubble position={position} onClick={openChat} visible={!isOpen} iconImageUrl={chatBubbleIcon} />\n\n {/* \u804A\u5929\u7A97\u53E3\uFF08\u4F7F\u7528 Radix UI Dialog\uFF09 */}\n <Dialog.Root open={isOpen} onOpenChange={open => (open ? openChat() : closeChat())}>\n <Dialog.Portal>\n <Dialog.Content\n className=\"livechat-window-enter\"\n style={{\n position: 'fixed',\n zIndex: 9998,\n }}\n >\n <ChatWindow\n messages={messages}\n inputValue={inputValue}\n onInputChange={setInputValue}\n onSend={() => handleSendMessage()}\n onClose={closeChat}\n onNewSession={handleCreateNewSession}\n title={title}\n logoUrl={logoUrl}\n isSending={isStreaming}\n rendererRegistry={rendererRegistry}\n inputPlaceholder=\"\"\n onAddToCart={onAddToCart}\n showNewSessionButton={showNewSessionButton}\n />\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n </>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["LiveChatWidget_exports", "__export", "LiveChatWidget", "__toCommonJS", "import_jsx_runtime", "import_react", "Dialog", "import_ChatBubble", "import_ChatWindow", "import_useChatState", "import_useChatAPI", "import_messageRenderers", "import_validation", "import_productTransformers", "import_cartTransformers", "import_MessageContent", "apiBaseUrl", "site", "loginUserId", "cartId", "accessToken", "position", "welcomeMessage", "quickReplies", "customRenderers", "logoUrl", "title", "chatBubbleIcon", "onOpen", "onClose", "onMessageSend", "onError", "onAddToCart", "onCart", "showNewSessionButton", "chatState", "messages", "isOpen", "userId", "sessionId", "inputValue", "isStreaming", "openChat", "closeChat", "setInputValue", "addMessage", "setMessages", "clearMessages", "handleSSEEvent", "saveSession", "clearSession", "sendMessageStream", "createSession", "handleSendMessageRef", "React", "_message", "rendererRegistry", "registry", "quickRepliesRenderer", "reply", "currentSessionId", "handleResumeSession", "handleCreateNewSession", "normalizeMessage", "message", "contentBlocks", "structuredData", "block", "transformedData", "response", "messageText", "welcomeContent", "questions", "quickRepliesFromBackend", "question", "index", "error", "existingSessionId", "normalizedMessages", "handleSendMessage", "textToSend", "sanitized", "userMessage", "event", "open"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LiveChat API 层
|
|
3
|
+
* 处理 SSE 流式通信和 HTTP 请求
|
|
4
|
+
* 基于 specs/livechat-widget/contracts/*.yaml
|
|
5
|
+
*/
|
|
6
|
+
import type { ChatStreamRequest, SSEEvent, NewSessionRequest, NewSessionResponse } from '../types';
|
|
7
|
+
/**
|
|
8
|
+
* 发送消息并接收 SSE 流式响应
|
|
9
|
+
* @param apiBaseUrl API 基础 URL
|
|
10
|
+
* @param request 请求参数
|
|
11
|
+
* @param onEvent SSE 事件回调
|
|
12
|
+
*/
|
|
13
|
+
export declare function sendMessage(apiBaseUrl: string, request: ChatStreamRequest, onEvent: (event: SSEEvent) => void): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* 创建新会话或恢复现有会话
|
|
16
|
+
*
|
|
17
|
+
* 使用场景:
|
|
18
|
+
* 1. 创建新会话:不传 session_id,返回新的 sessionId
|
|
19
|
+
* 2. 恢复会话:传入 session_id,验证会话有效性并返回历史消息(resumed: true, messages: [...])
|
|
20
|
+
*
|
|
21
|
+
* @param apiBaseUrl API 基础 URL
|
|
22
|
+
* @param request 请求参数
|
|
23
|
+
* @returns 会话信息,可能包含历史消息
|
|
24
|
+
*/
|
|
25
|
+
export declare function createNewSession(apiBaseUrl: string, request: NewSessionRequest): Promise<NewSessionResponse>;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";var p=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var R=Object.prototype.hasOwnProperty;var y=(s,e)=>{for(var t in e)p(s,t,{get:e[t],enumerable:!0})},E=(s,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of w(e))!R.call(s,o)&&o!==t&&p(s,o,{get:()=>e[o],enumerable:!(r=m(e,o))||r.enumerable});return s};var T=s=>E(p({},"__esModule",{value:!0}),s);var P={};y(P,{createNewSession:()=>g,sendMessage:()=>v});module.exports=T(P);async function v(s,e,t){const r=await fetch(`${s}/api/chat/stream`,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream"},body:JSON.stringify(e)});if(!r.ok)throw new Error(`HTTP ${r.status}: ${r.statusText}`);const o=r.body?.getReader();if(!o)throw new Error("Response body is not readable");const u=new TextDecoder;let i="",c=null;try{for(;;){const{done:n,value:h}=await o.read();if(n)break;i+=u.decode(h,{stream:!0});const l=i.split(`
|
|
2
|
+
`);i=l.pop()||"";for(const f of l){const a=f.trim();if(a===""){c=null;continue}if(a.startsWith("event:"))c=a.substring(6).trim();else if(a.startsWith("data:")){const S=a.substring(5).trim();try{const d=JSON.parse(S);t({event:c||"message",data:d})}catch(d){console.error("[LiveChat API] Failed to parse SSE data:",S,d),t({event:"error",data:{message:"Failed to parse SSE data",code:"PARSE_ERROR"}})}}}}}catch(n){throw console.error("[LiveChat API] SSE stream error:",n),n}finally{o.releaseLock()}}async function g(s,e){const t=await fetch(`${s}/api/chat/new-session`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!t.ok){const r=await t.json().catch(()=>({success:!1,error:`HTTP ${t.status}: ${t.statusText}`,code:"HTTP_ERROR"}));throw new Error(r.error||"Failed to create session")}return t.json()}
|
|
3
|
+
//# sourceMappingURL=chat.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/components/LiveChatWidget/api/chat.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * LiveChat API \u5C42\n * \u5904\u7406 SSE \u6D41\u5F0F\u901A\u4FE1\u548C HTTP \u8BF7\u6C42\n * \u57FA\u4E8E specs/livechat-widget/contracts/*.yaml\n */\n\nimport type { ChatStreamRequest, SSEEvent, NewSessionRequest, NewSessionResponse, ErrorResponse } from '../types'\n\n// ============================================================================\n// SSE \u6D41\u5F0F\u6D88\u606F\u5904\u7406 (T006)\n// ============================================================================\n\n/**\n * \u53D1\u9001\u6D88\u606F\u5E76\u63A5\u6536 SSE \u6D41\u5F0F\u54CD\u5E94\n * @param apiBaseUrl API \u57FA\u7840 URL\n * @param request \u8BF7\u6C42\u53C2\u6570\n * @param onEvent SSE \u4E8B\u4EF6\u56DE\u8C03\n */\nexport async function sendMessage(\n apiBaseUrl: string,\n request: ChatStreamRequest,\n onEvent: (event: SSEEvent) => void\n): Promise<void> {\n const response = await fetch(`${apiBaseUrl}/api/chat/stream`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'text/event-stream',\n },\n body: JSON.stringify(request),\n })\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`)\n }\n\n const reader = response.body?.getReader()\n if (!reader) {\n throw new Error('Response body is not readable')\n }\n\n const decoder = new TextDecoder()\n let buffer = ''\n let currentEvent: string | null = null\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n // \u89E3\u7801\u5E76\u8FFD\u52A0\u5230\u7F13\u51B2\u533A\n buffer += decoder.decode(value, { stream: true })\n\n // \u6309\u884C\u5206\u5272\n const lines = buffer.split('\\n')\n\n // \u4FDD\u7559\u6700\u540E\u4E00\u4E2A\u4E0D\u5B8C\u6574\u7684\u884C\n buffer = lines.pop() || ''\n\n for (const line of lines) {\n const trimmed = line.trim()\n\n if (trimmed === '') {\n // \u7A7A\u884C\u8868\u793A\u4E8B\u4EF6\u8FB9\u754C\uFF0C\u91CD\u7F6E\u5F53\u524D\u4E8B\u4EF6\u7C7B\u578B\n currentEvent = null\n continue\n }\n\n if (trimmed.startsWith('event:')) {\n // \u63D0\u53D6\u4E8B\u4EF6\u7C7B\u578B\n currentEvent = trimmed.substring(6).trim()\n } else if (trimmed.startsWith('data:')) {\n // \u63D0\u53D6\u6570\u636E\u5E76\u89E3\u6790 JSON\n const dataStr = trimmed.substring(5).trim()\n try {\n const data = JSON.parse(dataStr)\n onEvent({\n event: (currentEvent as any) || 'message',\n data,\n })\n } catch (err) {\n console.error('[LiveChat API] Failed to parse SSE data:', dataStr, err)\n onEvent({\n event: 'error',\n data: {\n message: 'Failed to parse SSE data',\n code: 'PARSE_ERROR',\n },\n })\n }\n }\n }\n }\n } catch (error) {\n console.error('[LiveChat API] SSE stream error:', error)\n throw error\n } finally {\n reader.releaseLock()\n }\n}\n\n// ============================================================================\n// \u521B\u5EFA/\u6062\u590D\u4F1A\u8BDD (T009)\n// ============================================================================\n\n/**\n * \u521B\u5EFA\u65B0\u4F1A\u8BDD\u6216\u6062\u590D\u73B0\u6709\u4F1A\u8BDD\n *\n * \u4F7F\u7528\u573A\u666F\uFF1A\n * 1. \u521B\u5EFA\u65B0\u4F1A\u8BDD\uFF1A\u4E0D\u4F20 session_id\uFF0C\u8FD4\u56DE\u65B0\u7684 sessionId\n * 2. \u6062\u590D\u4F1A\u8BDD\uFF1A\u4F20\u5165 session_id\uFF0C\u9A8C\u8BC1\u4F1A\u8BDD\u6709\u6548\u6027\u5E76\u8FD4\u56DE\u5386\u53F2\u6D88\u606F\uFF08resumed: true, messages: [...]\uFF09\n *\n * @param apiBaseUrl API \u57FA\u7840 URL\n * @param request \u8BF7\u6C42\u53C2\u6570\n * @returns \u4F1A\u8BDD\u4FE1\u606F\uFF0C\u53EF\u80FD\u5305\u542B\u5386\u53F2\u6D88\u606F\n */\nexport async function createNewSession(apiBaseUrl: string, request: NewSessionRequest): Promise<NewSessionResponse> {\n const response = await fetch(`${apiBaseUrl}/api/chat/new-session`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n })\n\n if (!response.ok) {\n const errorData: ErrorResponse = await response.json().catch(() => ({\n success: false,\n error: `HTTP ${response.status}: ${response.statusText}`,\n code: 'HTTP_ERROR',\n }))\n throw new Error(errorData.error || 'Failed to create session')\n }\n\n return response.json()\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,sBAAAE,EAAA,gBAAAC,IAAA,eAAAC,EAAAJ,GAkBA,eAAsBG,EACpBE,EACAC,EACAC,EACe,CACf,MAAMC,EAAW,MAAM,MAAM,GAAGH,CAAU,mBAAoB,CAC5D,OAAQ,OACR,QAAS,CACP,eAAgB,mBAChB,OAAQ,mBACV,EACA,KAAM,KAAK,UAAUC,CAAO,CAC9B,CAAC,EAED,GAAI,CAACE,EAAS,GACZ,MAAM,IAAI,MAAM,QAAQA,EAAS,MAAM,KAAKA,EAAS,UAAU,EAAE,EAGnE,MAAMC,EAASD,EAAS,MAAM,UAAU,EACxC,GAAI,CAACC,EACH,MAAM,IAAI,MAAM,+BAA+B,EAGjD,MAAMC,EAAU,IAAI,YACpB,IAAIC,EAAS,GACTC,EAA8B,KAElC,GAAI,CACF,OAAa,CACX,KAAM,CAAE,KAAAC,EAAM,MAAAC,CAAM,EAAI,MAAML,EAAO,KAAK,EAC1C,GAAII,EAAM,MAGVF,GAAUD,EAAQ,OAAOI,EAAO,CAAE,OAAQ,EAAK,CAAC,EAGhD,MAAMC,EAAQJ,EAAO,MAAM;AAAA,CAAI,EAG/BA,EAASI,EAAM,IAAI,GAAK,GAExB,UAAWC,KAAQD,EAAO,CACxB,MAAME,EAAUD,EAAK,KAAK,EAE1B,GAAIC,IAAY,GAAI,CAElBL,EAAe,KACf,QACF,CAEA,GAAIK,EAAQ,WAAW,QAAQ,EAE7BL,EAAeK,EAAQ,UAAU,CAAC,EAAE,KAAK,UAChCA,EAAQ,WAAW,OAAO,EAAG,CAEtC,MAAMC,EAAUD,EAAQ,UAAU,CAAC,EAAE,KAAK,EAC1C,GAAI,CACF,MAAME,EAAO,KAAK,MAAMD,CAAO,EAC/BX,EAAQ,CACN,MAAQK,GAAwB,UAChC,KAAAO,CACF,CAAC,CACH,OAASC,EAAK,CACZ,QAAQ,MAAM,2CAA4CF,EAASE,CAAG,EACtEb,EAAQ,CACN,MAAO,QACP,KAAM,CACJ,QAAS,2BACT,KAAM,aACR,CACF,CAAC,CACH,CACF,CACF,CACF,CACF,OAASc,EAAO,CACd,cAAQ,MAAM,mCAAoCA,CAAK,EACjDA,CACR,QAAE,CACAZ,EAAO,YAAY,CACrB,CACF,CAiBA,eAAsBP,EAAiBG,EAAoBC,EAAyD,CAClH,MAAME,EAAW,MAAM,MAAM,GAAGH,CAAU,wBAAyB,CACjE,OAAQ,OACR,QAAS,CACP,eAAgB,kBAClB,EACA,KAAM,KAAK,UAAUC,CAAO,CAC9B,CAAC,EAED,GAAI,CAACE,EAAS,GAAI,CAChB,MAAMc,EAA2B,MAAMd,EAAS,KAAK,EAAE,MAAM,KAAO,CAClE,QAAS,GACT,MAAO,QAAQA,EAAS,MAAM,KAAKA,EAAS,UAAU,GACtD,KAAM,YACR,EAAE,EACF,MAAM,IAAI,MAAMc,EAAU,OAAS,0BAA0B,CAC/D,CAEA,OAAOd,EAAS,KAAK,CACvB",
|
|
6
|
+
"names": ["chat_exports", "__export", "createNewSession", "sendMessage", "__toCommonJS", "apiBaseUrl", "request", "onEvent", "response", "reader", "decoder", "buffer", "currentEvent", "done", "value", "lines", "line", "trimmed", "dataStr", "data", "err", "error", "errorData"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 聊天悬浮按钮组件
|
|
3
|
+
* 显示在页面角落的气泡按钮,点击后打开聊天窗口
|
|
4
|
+
* 基于 specs/livechat-widget/plan.md 的气泡按钮设计
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import type { BubblePosition } from '../types';
|
|
8
|
+
export interface ChatBubbleProps {
|
|
9
|
+
/**
|
|
10
|
+
* 气泡按钮位置
|
|
11
|
+
* @default { bottom: "1.5rem", right: "1.5rem" }
|
|
12
|
+
*/
|
|
13
|
+
position?: BubblePosition;
|
|
14
|
+
/**
|
|
15
|
+
* 点击按钮的回调
|
|
16
|
+
*/
|
|
17
|
+
onClick?: () => void;
|
|
18
|
+
/**
|
|
19
|
+
* 自定义图标
|
|
20
|
+
*/
|
|
21
|
+
icon?: React.ReactNode;
|
|
22
|
+
/**
|
|
23
|
+
* 自定义图标图片 URL
|
|
24
|
+
* 如果提供,将使用图片替代默认的 SVG 图标
|
|
25
|
+
*/
|
|
26
|
+
iconImageUrl?: string;
|
|
27
|
+
/**
|
|
28
|
+
* 是否显示气泡
|
|
29
|
+
* @default true
|
|
30
|
+
*/
|
|
31
|
+
visible?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* 自定义样式类名
|
|
34
|
+
*/
|
|
35
|
+
className?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 聊天悬浮按钮组件
|
|
39
|
+
*
|
|
40
|
+
* 功能:
|
|
41
|
+
* - 可配置位置(预设或自定义)
|
|
42
|
+
* - 支持自定义图标(React 节点或图片 URL)
|
|
43
|
+
* - 悬停和点击动画效果
|
|
44
|
+
*
|
|
45
|
+
* 样式:
|
|
46
|
+
* - 使用 livechat.css 中定义的 CSS 变量
|
|
47
|
+
* - 悬停时放大 1.05 倍
|
|
48
|
+
* - 点击时缩小 0.95 倍
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```tsx
|
|
52
|
+
* // 使用默认图标
|
|
53
|
+
* <ChatBubble onClick={() => setIsOpen(true)} />
|
|
54
|
+
*
|
|
55
|
+
* // 使用自定义位置
|
|
56
|
+
* <ChatBubble
|
|
57
|
+
* position={{ bottom: "20px", right: "30px" }}
|
|
58
|
+
* onClick={() => setIsOpen(true)}
|
|
59
|
+
* />
|
|
60
|
+
*
|
|
61
|
+
* // 使用图片作为图标
|
|
62
|
+
* <ChatBubble
|
|
63
|
+
* iconImageUrl="https://example.com/icon.png"
|
|
64
|
+
* onClick={() => setIsOpen(true)}
|
|
65
|
+
* />
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare const ChatBubble: React.FC<ChatBubbleProps>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var n=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var d=(t,e)=>{for(var o in e)n(t,o,{get:e[o],enumerable:!0})},f=(t,e,o,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of b(e))!p.call(t,r)&&r!==o&&n(t,r,{get:()=>e[r],enumerable:!(s=u(e,r))||s.enumerable});return t};var h=t=>f(n({},"__esModule",{value:!0}),t);var v={};d(v,{ChatBubble:()=>P});module.exports=h(v);var i=require("react/jsx-runtime");function C(t){return t||{bottom:"1.5rem",right:"1.5rem"}}const m=()=>(0,i.jsx)("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:(0,i.jsx)("path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"})}),P=({position:t,onClick:e,icon:o,iconImageUrl:s,visible:r=!0,className:a=""})=>{if(!r)return null;const l=C(t),c=()=>s?(0,i.jsx)("img",{src:s,alt:"Chat",className:"size-full object-cover",style:{borderRadius:"inherit"}}):o||(0,i.jsx)(m,{});return(0,i.jsx)("button",{type:"button",className:`livechat-bubble ${a}`,style:{...l,...s&&{background:"transparent"}},onClick:e,"aria-label":"\u6253\u5F00\u804A\u5929\u7A97\u53E3",children:(0,i.jsx)("div",{className:"flex size-full items-center justify-center",children:c()})})};
|
|
2
|
+
//# sourceMappingURL=ChatBubble.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/components/LiveChatWidget/components/ChatBubble.tsx"],
|
|
4
|
+
"sourcesContent": ["/**\n * \u804A\u5929\u60AC\u6D6E\u6309\u94AE\u7EC4\u4EF6\n * \u663E\u793A\u5728\u9875\u9762\u89D2\u843D\u7684\u6C14\u6CE1\u6309\u94AE\uFF0C\u70B9\u51FB\u540E\u6253\u5F00\u804A\u5929\u7A97\u53E3\n * \u57FA\u4E8E specs/livechat-widget/plan.md \u7684\u6C14\u6CE1\u6309\u94AE\u8BBE\u8BA1\n */\n\nimport React from 'react'\nimport type { BubblePosition } from '../types'\n\nexport interface ChatBubbleProps {\n /**\n * \u6C14\u6CE1\u6309\u94AE\u4F4D\u7F6E\n * @default { bottom: \"1.5rem\", right: \"1.5rem\" }\n */\n position?: BubblePosition\n\n /**\n * \u70B9\u51FB\u6309\u94AE\u7684\u56DE\u8C03\n */\n onClick?: () => void\n\n /**\n * \u81EA\u5B9A\u4E49\u56FE\u6807\n */\n icon?: React.ReactNode\n\n /**\n * \u81EA\u5B9A\u4E49\u56FE\u6807\u56FE\u7247 URL\n * \u5982\u679C\u63D0\u4F9B\uFF0C\u5C06\u4F7F\u7528\u56FE\u7247\u66FF\u4EE3\u9ED8\u8BA4\u7684 SVG \u56FE\u6807\n */\n iconImageUrl?: string\n\n /**\n * \u662F\u5426\u663E\u793A\u6C14\u6CE1\n * @default true\n */\n visible?: boolean\n\n /**\n * \u81EA\u5B9A\u4E49\u6837\u5F0F\u7C7B\u540D\n */\n className?: string\n}\n\n/**\n * \u83B7\u53D6\u6C14\u6CE1\u6309\u94AE\u7684\u4F4D\u7F6E\u6837\u5F0F\n * \u5982\u679C\u6CA1\u6709\u4F20\u5165 position\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u4F4D\u7F6E\uFF08\u53F3\u4E0B\u89D2\uFF09\n */\nfunction getPositionStyles(position?: BubblePosition): React.CSSProperties {\n // \u9ED8\u8BA4\u4F4D\u7F6E\uFF1A\u53F3\u4E0B\u89D2\n const defaultPosition: React.CSSProperties = {\n bottom: '1.5rem',\n right: '1.5rem',\n }\n\n // \u5982\u679C\u4F20\u5165\u4E86\u81EA\u5B9A\u4E49\u4F4D\u7F6E\uFF0C\u4F7F\u7528\u81EA\u5B9A\u4E49\u4F4D\u7F6E\n return position ? (position as React.CSSProperties) : defaultPosition\n}\n\n/**\n * \u9ED8\u8BA4\u804A\u5929\u56FE\u6807 (\u7B80\u5355\u7684\u6D88\u606F\u6C14\u6CE1 SVG)\n */\nconst DefaultChatIcon: React.FC = () => (\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n)\n\n/**\n * \u804A\u5929\u60AC\u6D6E\u6309\u94AE\u7EC4\u4EF6\n *\n * \u529F\u80FD\uFF1A\n * - \u53EF\u914D\u7F6E\u4F4D\u7F6E\uFF08\u9884\u8BBE\u6216\u81EA\u5B9A\u4E49\uFF09\n * - \u652F\u6301\u81EA\u5B9A\u4E49\u56FE\u6807\uFF08React \u8282\u70B9\u6216\u56FE\u7247 URL\uFF09\n * - \u60AC\u505C\u548C\u70B9\u51FB\u52A8\u753B\u6548\u679C\n *\n * \u6837\u5F0F\uFF1A\n * - \u4F7F\u7528 livechat.css \u4E2D\u5B9A\u4E49\u7684 CSS \u53D8\u91CF\n * - \u60AC\u505C\u65F6\u653E\u5927 1.05 \u500D\n * - \u70B9\u51FB\u65F6\u7F29\u5C0F 0.95 \u500D\n *\n * @example\n * ```tsx\n * // \u4F7F\u7528\u9ED8\u8BA4\u56FE\u6807\n * <ChatBubble onClick={() => setIsOpen(true)} />\n *\n * // \u4F7F\u7528\u81EA\u5B9A\u4E49\u4F4D\u7F6E\n * <ChatBubble\n * position={{ bottom: \"20px\", right: \"30px\" }}\n * onClick={() => setIsOpen(true)}\n * />\n *\n * // \u4F7F\u7528\u56FE\u7247\u4F5C\u4E3A\u56FE\u6807\n * <ChatBubble\n * iconImageUrl=\"https://example.com/icon.png\"\n * onClick={() => setIsOpen(true)}\n * />\n * ```\n */\nexport const ChatBubble: React.FC<ChatBubbleProps> = ({\n position,\n onClick,\n icon,\n iconImageUrl,\n visible = true,\n className = '',\n}) => {\n if (!visible) return null\n\n const positionStyles = getPositionStyles(position)\n\n // \u6E32\u67D3\u56FE\u6807\u5185\u5BB9\n const renderIcon = () => {\n // \u4F18\u5148\u4F7F\u7528\u56FE\u7247 URL\n if (iconImageUrl) {\n return (\n <img src={iconImageUrl} alt=\"Chat\" className=\"size-full object-cover\" style={{ borderRadius: 'inherit' }} />\n )\n }\n // \u5176\u6B21\u4F7F\u7528\u81EA\u5B9A\u4E49\u56FE\u6807\n if (icon) {\n return icon\n }\n // \u6700\u540E\u4F7F\u7528\u9ED8\u8BA4\u56FE\u6807\n return <DefaultChatIcon />\n }\n\n return (\n <button\n type=\"button\"\n className={`livechat-bubble ${className}`}\n style={{\n ...positionStyles,\n // \u5982\u679C\u4F20\u5165\u4E86\u56FE\u7247\uFF0C\u79FB\u9664\u9ED8\u8BA4\u80CC\u666F\u8272\n ...(iconImageUrl && { background: 'transparent' }),\n }}\n onClick={onClick}\n aria-label=\"\u6253\u5F00\u804A\u5929\u7A97\u53E3\"\n >\n <div className=\"flex size-full items-center justify-center\">{renderIcon()}</div>\n </button>\n )\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,gBAAAE,IAAA,eAAAC,EAAAH,GAyEI,IAAAI,EAAA,6BAzBJ,SAASC,EAAkBC,EAAgD,CAQzE,OAAOA,GANsC,CAC3C,OAAQ,SACR,MAAO,QACT,CAIF,CAKA,MAAMC,EAA4B,OAChC,OAAC,OACC,MAAM,KACN,OAAO,KACP,QAAQ,YACR,KAAK,OACL,OAAO,eACP,YAAY,IACZ,cAAc,QACd,eAAe,QAEf,mBAAC,QAAK,EAAE,gEAAgE,EAC1E,EAkCWL,EAAwC,CAAC,CACpD,SAAAI,EACA,QAAAE,EACA,KAAAC,EACA,aAAAC,EACA,QAAAC,EAAU,GACV,UAAAC,EAAY,EACd,IAAM,CACJ,GAAI,CAACD,EAAS,OAAO,KAErB,MAAME,EAAiBR,EAAkBC,CAAQ,EAG3CQ,EAAa,IAEbJ,KAEA,OAAC,OAAI,IAAKA,EAAc,IAAI,OAAO,UAAU,yBAAyB,MAAO,CAAE,aAAc,SAAU,EAAG,EAI1GD,MAIG,OAACF,EAAA,EAAgB,EAG1B,SACE,OAAC,UACC,KAAK,SACL,UAAW,mBAAmBK,CAAS,GACvC,MAAO,CACL,GAAGC,EAEH,GAAIH,GAAgB,CAAE,WAAY,aAAc,CAClD,EACA,QAASF,EACT,aAAW,uCAEX,mBAAC,OAAI,UAAU,6CAA8C,SAAAM,EAAW,EAAE,EAC5E,CAEJ",
|
|
6
|
+
"names": ["ChatBubble_exports", "__export", "ChatBubble", "__toCommonJS", "import_jsx_runtime", "getPositionStyles", "position", "DefaultChatIcon", "onClick", "icon", "iconImageUrl", "visible", "className", "positionStyles", "renderIcon"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 聊天窗口头部组件
|
|
3
|
+
* 显示标题、Logo、关闭按钮和新会话按钮
|
|
4
|
+
* 基于 specs/livechat-widget/plan.md 的头部设计
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
export interface ChatHeaderProps {
|
|
8
|
+
/**
|
|
9
|
+
* 头部标题
|
|
10
|
+
*/
|
|
11
|
+
title?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Logo URL
|
|
14
|
+
*/
|
|
15
|
+
logoUrl?: string;
|
|
16
|
+
/**
|
|
17
|
+
* 关闭按钮点击回调
|
|
18
|
+
*/
|
|
19
|
+
onClose?: () => void;
|
|
20
|
+
/**
|
|
21
|
+
* 新会话按钮点击回调
|
|
22
|
+
*/
|
|
23
|
+
onNewSession?: () => void;
|
|
24
|
+
/**
|
|
25
|
+
* 是否显示新会话按钮
|
|
26
|
+
* @default true
|
|
27
|
+
*/
|
|
28
|
+
showNewSessionButton?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* 自定义样式类名
|
|
31
|
+
*/
|
|
32
|
+
className?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 聊天窗口头部组件
|
|
36
|
+
*
|
|
37
|
+
* 功能:
|
|
38
|
+
* - 显示标题和 Logo
|
|
39
|
+
* - 关闭按钮(移动端隐藏,桌面端显示)
|
|
40
|
+
* - 新会话按钮(清空当前对话)
|
|
41
|
+
*
|
|
42
|
+
* 布局:
|
|
43
|
+
* - Logo (可选) + 标题 | 新会话按钮 + 关闭按钮
|
|
44
|
+
* - 固定高度 64px
|
|
45
|
+
* - 边框分隔下方内容
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```tsx
|
|
49
|
+
* <ChatHeader
|
|
50
|
+
* title="AI 助手"
|
|
51
|
+
* logoUrl="/logo.png"
|
|
52
|
+
* onClose={() => setIsOpen(false)}
|
|
53
|
+
* onNewSession={() => createNewSession()}
|
|
54
|
+
* />
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare const ChatHeader: React.FC<ChatHeaderProps>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var s=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var g=(o,t)=>{for(var i in t)s(o,i,{get:t[i],enumerable:!0})},x=(o,t,i,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of c(t))!d.call(o,n)&&n!==i&&s(o,n,{get:()=>t[n],enumerable:!(r=l(t,n))||r.enumerable});return o};var u=o=>x(s({},"__esModule",{value:!0}),o);var m={};g(m,{ChatHeader:()=>y});module.exports=u(m);var e=require("react/jsx-runtime");const b=()=>(0,e.jsxs)("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,e.jsx)("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),(0,e.jsx)("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]}),h=()=>(0,e.jsxs)("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,e.jsx)("line",{x1:"12",y1:"5",x2:"12",y2:"19"}),(0,e.jsx)("line",{x1:"5",y1:"12",x2:"19",y2:"12"})]}),y=({title:o="AI \u52A9\u624B",logoUrl:t,onClose:i,onNewSession:r,showNewSessionButton:n=!0,className:a=""})=>(0,e.jsxs)("div",{className:`flex items-center justify-between border-b border-[#DADCE0] bg-white px-4 py-3 ${a}`,style:{minHeight:"48px"},children:[(0,e.jsxs)("div",{className:"flex items-center gap-3",children:[t&&(0,e.jsx)("img",{src:t,alt:"Logo",className:"size-8 rounded-full object-cover"}),(0,e.jsx)("h2",{className:"text-lg font-semibold text-gray-900",children:o})]}),(0,e.jsxs)("div",{className:"flex items-center gap-2",children:[n&&r&&(0,e.jsx)("button",{type:"button",onClick:r,className:"rounded-lg p-2 text-gray-600","aria-label":"\u5F00\u59CB\u65B0\u4F1A\u8BDD",title:"\u5F00\u59CB\u65B0\u4F1A\u8BDD",children:(0,e.jsx)(h,{})}),i&&(0,e.jsx)("button",{type:"button",onClick:i,className:"tablet:block rounded-lg text-gray-600","aria-label":"\u5173\u95ED\u804A\u5929\u7A97\u53E3",children:(0,e.jsx)(b,{})})]})]});
|
|
2
|
+
//# sourceMappingURL=ChatHeader.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/components/LiveChatWidget/components/ChatHeader.tsx"],
|
|
4
|
+
"sourcesContent": ["/**\n * \u804A\u5929\u7A97\u53E3\u5934\u90E8\u7EC4\u4EF6\n * \u663E\u793A\u6807\u9898\u3001Logo\u3001\u5173\u95ED\u6309\u94AE\u548C\u65B0\u4F1A\u8BDD\u6309\u94AE\n * \u57FA\u4E8E specs/livechat-widget/plan.md \u7684\u5934\u90E8\u8BBE\u8BA1\n */\n\nimport React from 'react'\n\nexport interface ChatHeaderProps {\n /**\n * \u5934\u90E8\u6807\u9898\n */\n title?: string\n\n /**\n * Logo URL\n */\n logoUrl?: string\n\n /**\n * \u5173\u95ED\u6309\u94AE\u70B9\u51FB\u56DE\u8C03\n */\n onClose?: () => void\n\n /**\n * \u65B0\u4F1A\u8BDD\u6309\u94AE\u70B9\u51FB\u56DE\u8C03\n */\n onNewSession?: () => void\n\n /**\n * \u662F\u5426\u663E\u793A\u65B0\u4F1A\u8BDD\u6309\u94AE\n * @default true\n */\n showNewSessionButton?: boolean\n\n /**\n * \u81EA\u5B9A\u4E49\u6837\u5F0F\u7C7B\u540D\n */\n className?: string\n}\n\n/**\n * \u9ED8\u8BA4\u5173\u95ED\u56FE\u6807 (X)\n */\nconst CloseIcon: React.FC = () => (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n)\n\n/**\n * \u65B0\u4F1A\u8BDD\u56FE\u6807 (\u52A0\u53F7)\n */\nconst NewSessionIcon: React.FC = () => (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n)\n\n/**\n * \u804A\u5929\u7A97\u53E3\u5934\u90E8\u7EC4\u4EF6\n *\n * \u529F\u80FD\uFF1A\n * - \u663E\u793A\u6807\u9898\u548C Logo\n * - \u5173\u95ED\u6309\u94AE\uFF08\u79FB\u52A8\u7AEF\u9690\u85CF\uFF0C\u684C\u9762\u7AEF\u663E\u793A\uFF09\n * - \u65B0\u4F1A\u8BDD\u6309\u94AE\uFF08\u6E05\u7A7A\u5F53\u524D\u5BF9\u8BDD\uFF09\n *\n * \u5E03\u5C40\uFF1A\n * - Logo (\u53EF\u9009) + \u6807\u9898 | \u65B0\u4F1A\u8BDD\u6309\u94AE + \u5173\u95ED\u6309\u94AE\n * - \u56FA\u5B9A\u9AD8\u5EA6 64px\n * - \u8FB9\u6846\u5206\u9694\u4E0B\u65B9\u5185\u5BB9\n *\n * @example\n * ```tsx\n * <ChatHeader\n * title=\"AI \u52A9\u624B\"\n * logoUrl=\"/logo.png\"\n * onClose={() => setIsOpen(false)}\n * onNewSession={() => createNewSession()}\n * />\n * ```\n */\nexport const ChatHeader: React.FC<ChatHeaderProps> = ({\n title = 'AI \u52A9\u624B',\n logoUrl,\n onClose,\n onNewSession,\n showNewSessionButton = true,\n className = '',\n}) => {\n return (\n <div\n className={`flex items-center justify-between border-b border-[#DADCE0] bg-white px-4 py-3 ${className}`}\n style={{ minHeight: '48px' }}\n >\n {/* \u5DE6\u4FA7\uFF1ALogo + \u6807\u9898 */}\n <div className=\"flex items-center gap-3\">\n {logoUrl && <img src={logoUrl} alt=\"Logo\" className=\"size-8 rounded-full object-cover\" />}\n <h2 className=\"text-lg font-semibold text-gray-900\">{title}</h2>\n </div>\n\n {/* \u53F3\u4FA7\uFF1A\u65B0\u4F1A\u8BDD\u6309\u94AE + \u5173\u95ED\u6309\u94AE */}\n <div className=\"flex items-center gap-2\">\n {/* \u65B0\u4F1A\u8BDD\u6309\u94AE */}\n {showNewSessionButton && onNewSession && (\n <button\n type=\"button\"\n onClick={onNewSession}\n className=\"rounded-lg p-2 text-gray-600\"\n aria-label=\"\u5F00\u59CB\u65B0\u4F1A\u8BDD\"\n title=\"\u5F00\u59CB\u65B0\u4F1A\u8BDD\"\n >\n <NewSessionIcon />\n </button>\n )}\n\n {/* \u5173\u95ED\u6309\u94AE */}\n {onClose && (\n <button\n type=\"button\"\n onClick={onClose}\n className=\"tablet:block rounded-lg text-gray-600\"\n aria-label=\"\u5173\u95ED\u804A\u5929\u7A97\u53E3\"\n >\n <CloseIcon />\n </button>\n )}\n </div>\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,gBAAAE,IAAA,eAAAC,EAAAH,GA6CE,IAAAI,EAAA,6BADF,MAAMC,EAAsB,OAC1B,QAAC,OACC,MAAM,KACN,OAAO,KACP,QAAQ,YACR,KAAK,OACL,OAAO,eACP,YAAY,IACZ,cAAc,QACd,eAAe,QAEf,oBAAC,QAAK,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,KACpC,OAAC,QAAK,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,GACtC,EAMIC,EAA2B,OAC/B,QAAC,OACC,MAAM,KACN,OAAO,KACP,QAAQ,YACR,KAAK,OACL,OAAO,eACP,YAAY,IACZ,cAAc,QACd,eAAe,QAEf,oBAAC,QAAK,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,KACrC,OAAC,QAAK,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GACvC,EA0BWJ,EAAwC,CAAC,CACpD,MAAAK,EAAQ,kBACR,QAAAC,EACA,QAAAC,EACA,aAAAC,EACA,qBAAAC,EAAuB,GACvB,UAAAC,EAAY,EACd,OAEI,QAAC,OACC,UAAW,kFAAkFA,CAAS,GACtG,MAAO,CAAE,UAAW,MAAO,EAG3B,qBAAC,OAAI,UAAU,0BACZ,UAAAJ,MAAW,OAAC,OAAI,IAAKA,EAAS,IAAI,OAAO,UAAU,mCAAmC,KACvF,OAAC,MAAG,UAAU,sCAAuC,SAAAD,EAAM,GAC7D,KAGA,QAAC,OAAI,UAAU,0BAEZ,UAAAI,GAAwBD,MACvB,OAAC,UACC,KAAK,SACL,QAASA,EACT,UAAU,+BACV,aAAW,iCACX,MAAM,iCAEN,mBAACJ,EAAA,EAAe,EAClB,EAIDG,MACC,OAAC,UACC,KAAK,SACL,QAASA,EACT,UAAU,yCACV,aAAW,uCAEX,mBAACJ,EAAA,EAAU,EACb,GAEJ,GACF",
|
|
6
|
+
"names": ["ChatHeader_exports", "__export", "ChatHeader", "__toCommonJS", "import_jsx_runtime", "CloseIcon", "NewSessionIcon", "title", "logoUrl", "onClose", "onNewSession", "showNewSessionButton", "className"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 聊天输入框组件
|
|
3
|
+
* 提供文本输入和发送按钮
|
|
4
|
+
* 基于 specs/livechat-widget/plan.md 的输入框设计
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
export interface ChatInputProps {
|
|
8
|
+
/**
|
|
9
|
+
* 输入框当前值
|
|
10
|
+
*/
|
|
11
|
+
value: string;
|
|
12
|
+
/**
|
|
13
|
+
* 值变化回调
|
|
14
|
+
*/
|
|
15
|
+
onChange: (value: string) => void;
|
|
16
|
+
/**
|
|
17
|
+
* 发送消息回调
|
|
18
|
+
*/
|
|
19
|
+
onSend: () => void;
|
|
20
|
+
/**
|
|
21
|
+
* 占位符文本
|
|
22
|
+
* @default "输入消息..."
|
|
23
|
+
*/
|
|
24
|
+
placeholder?: string;
|
|
25
|
+
/**
|
|
26
|
+
* 是否禁用输入
|
|
27
|
+
* @default false
|
|
28
|
+
*/
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* 是否自动聚焦
|
|
32
|
+
* @default false
|
|
33
|
+
*/
|
|
34
|
+
autoFocus?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* 最大字符数
|
|
37
|
+
* @default 5000
|
|
38
|
+
*/
|
|
39
|
+
maxLength?: number;
|
|
40
|
+
/**
|
|
41
|
+
* 自定义样式类名
|
|
42
|
+
*/
|
|
43
|
+
className?: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 聊天输入框组件
|
|
47
|
+
*
|
|
48
|
+
* 功能:
|
|
49
|
+
* - 多行文本输入(自动增长)
|
|
50
|
+
* - Enter 发送,Shift+Enter 换行
|
|
51
|
+
* - 字符数限制(5000)
|
|
52
|
+
* - 禁用状态(发送中)
|
|
53
|
+
* - 发送按钮(空内容时禁用)
|
|
54
|
+
*
|
|
55
|
+
* 样式:
|
|
56
|
+
* - 固定底部
|
|
57
|
+
* - 边框分隔上方内容
|
|
58
|
+
* - 自适应高度(1-5 行)
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```tsx
|
|
62
|
+
* <ChatInput
|
|
63
|
+
* value={inputValue}
|
|
64
|
+
* onChange={setInputValue}
|
|
65
|
+
* onSend={handleSend}
|
|
66
|
+
* disabled={isStreaming}
|
|
67
|
+
* />
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare const ChatInput: React.FC<ChatInputProps>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var h=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var k=Object.prototype.hasOwnProperty;var C=(e,n)=>{for(var r in n)h(e,r,{get:n[r],enumerable:!0})},v=(e,n,r,s)=>{if(n&&typeof n=="object"||typeof n=="function")for(let a of y(n))!k.call(e,a)&&a!==r&&h(e,a,{get:()=>n[a],enumerable:!(s=b(n,a))||s.enumerable});return e};var E=e=>v(h({},"__esModule",{value:!0}),e);var A={};C(A,{ChatInput:()=>R});module.exports=E(A);var t=require("react/jsx-runtime"),l=require("react");const F=()=>(0,t.jsxs)("svg",{width:"20",height:"20",viewBox:"0 0 20 20",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[(0,t.jsx)("path",{d:"M10.2069 15.6997V4.69971",stroke:"white","stroke-width":"2","stroke-linecap":"round"}),(0,t.jsx)("path",{d:"M15.3995 8.50341L10.9506 4.05446C10.534 3.6379 9.85866 3.63791 9.4421 4.05446L5.00005 8.49651",stroke:"white","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"})]}),R=({value:e,onChange:n,onSend:r,placeholder:s="",disabled:a=!1,autoFocus:p=!1,maxLength:i=5e3,className:u=""})=>{const g=(0,l.useRef)(null);(0,l.useEffect)(()=>{const o=g.current;if(!o)return;o.style.height="auto";const w=Math.min(o.scrollHeight,120);o.style.height=`${w}px`},[e]);const x=o=>{o.key==="Enter"&&!o.shiftKey&&(o.preventDefault(),e.trim()&&!a&&r())},f=o=>{const d=o.target.value;d.length<=i&&n(d)},m=()=>{e.trim()&&!a&&r()},c=e.trim().length>0&&!a;return(0,t.jsx)("div",{className:`flex items-end gap-2 bg-white px-4 py-3 ${u}`,children:(0,t.jsx)("div",{className:"flex flex-1 items-center gap-2 rounded-2xl",style:{background:"linear-gradient(to right, #7687F3, #7687F3, #4DA8F5, #A3DFCE)",padding:"2px"},children:(0,t.jsxs)("div",{className:"flex flex-1 items-center gap-2 bg-white px-3 py-2",style:{borderRadius:"14px"},children:[(0,t.jsx)("textarea",{ref:g,value:e,onChange:f,onKeyDown:x,placeholder:s,disabled:a,autoFocus:p,rows:1,className:"flex-1 resize-none bg-transparent text-sm text-gray-900 outline-none placeholder:text-gray-400 disabled:cursor-not-allowed disabled:opacity-50",style:{resize:"none"}}),e.length>i*.8&&(0,t.jsxs)("span",{className:"text-xs text-gray-400",children:[e.length,"/",i]}),(0,t.jsx)("button",{type:"button",onClick:m,disabled:!c,className:`shrink-0 rounded-full p-2 transition-all ${c?" active:scale-95":"cursor-not-allowed "}`,style:c?{background:"linear-gradient(to bottom, #A3DFCE, #4DA8F5, #7687F3)"}:{background:"#BEBEBE"},"aria-label":"\u53D1\u9001\u6D88\u606F",children:(0,t.jsx)(F,{})})]})})})};
|
|
2
|
+
//# sourceMappingURL=ChatInput.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/components/LiveChatWidget/components/ChatInput.tsx"],
|
|
4
|
+
"sourcesContent": ["/**\n * \u804A\u5929\u8F93\u5165\u6846\u7EC4\u4EF6\n * \u63D0\u4F9B\u6587\u672C\u8F93\u5165\u548C\u53D1\u9001\u6309\u94AE\n * \u57FA\u4E8E specs/livechat-widget/plan.md \u7684\u8F93\u5165\u6846\u8BBE\u8BA1\n */\n\nimport React, { useRef, useEffect } from 'react'\n\nexport interface ChatInputProps {\n /**\n * \u8F93\u5165\u6846\u5F53\u524D\u503C\n */\n value: string\n\n /**\n * \u503C\u53D8\u5316\u56DE\u8C03\n */\n onChange: (value: string) => void\n\n /**\n * \u53D1\u9001\u6D88\u606F\u56DE\u8C03\n */\n onSend: () => void\n\n /**\n * \u5360\u4F4D\u7B26\u6587\u672C\n * @default \"\u8F93\u5165\u6D88\u606F...\"\n */\n placeholder?: string\n\n /**\n * \u662F\u5426\u7981\u7528\u8F93\u5165\n * @default false\n */\n disabled?: boolean\n\n /**\n * \u662F\u5426\u81EA\u52A8\u805A\u7126\n * @default false\n */\n autoFocus?: boolean\n\n /**\n * \u6700\u5927\u5B57\u7B26\u6570\n * @default 5000\n */\n maxLength?: number\n\n /**\n * \u81EA\u5B9A\u4E49\u6837\u5F0F\u7C7B\u540D\n */\n className?: string\n}\n\n/**\n * \u53D1\u9001\u56FE\u6807 (\u5411\u4E0A\u7BAD\u5934)\n */\nconst SendIcon: React.FC = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10.2069 15.6997V4.69971\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" />\n <path\n d=\"M15.3995 8.50341L10.9506 4.05446C10.534 3.6379 9.85866 3.63791 9.4421 4.05446L5.00005 8.49651\"\n stroke=\"white\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n)\n\n/**\n * \u804A\u5929\u8F93\u5165\u6846\u7EC4\u4EF6\n *\n * \u529F\u80FD\uFF1A\n * - \u591A\u884C\u6587\u672C\u8F93\u5165\uFF08\u81EA\u52A8\u589E\u957F\uFF09\n * - Enter \u53D1\u9001\uFF0CShift+Enter \u6362\u884C\n * - \u5B57\u7B26\u6570\u9650\u5236\uFF085000\uFF09\n * - \u7981\u7528\u72B6\u6001\uFF08\u53D1\u9001\u4E2D\uFF09\n * - \u53D1\u9001\u6309\u94AE\uFF08\u7A7A\u5185\u5BB9\u65F6\u7981\u7528\uFF09\n *\n * \u6837\u5F0F\uFF1A\n * - \u56FA\u5B9A\u5E95\u90E8\n * - \u8FB9\u6846\u5206\u9694\u4E0A\u65B9\u5185\u5BB9\n * - \u81EA\u9002\u5E94\u9AD8\u5EA6\uFF081-5 \u884C\uFF09\n *\n * @example\n * ```tsx\n * <ChatInput\n * value={inputValue}\n * onChange={setInputValue}\n * onSend={handleSend}\n * disabled={isStreaming}\n * />\n * ```\n */\nexport const ChatInput: React.FC<ChatInputProps> = ({\n value,\n onChange,\n onSend,\n placeholder = '',\n disabled = false,\n autoFocus = false,\n maxLength = 5000,\n className = '',\n}) => {\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n\n /**\n * \u81EA\u52A8\u8C03\u6574 textarea \u9AD8\u5EA6\n */\n useEffect(() => {\n const textarea = textareaRef.current\n if (!textarea) return\n\n // \u91CD\u7F6E\u9AD8\u5EA6\u4EE5\u83B7\u53D6\u6B63\u786E\u7684 scrollHeight\n textarea.style.height = 'auto'\n\n // \u8BBE\u7F6E\u9AD8\u5EA6\uFF0C\u6700\u5927 5 \u884C\uFF08\u7EA6 120px\uFF09\n const maxHeight = 120\n const newHeight = Math.min(textarea.scrollHeight, maxHeight)\n textarea.style.height = `${newHeight}px`\n }, [value])\n\n /**\n * \u5904\u7406\u952E\u76D8\u4E8B\u4EF6\n * Enter \u53D1\u9001\uFF0CShift+Enter \u6362\u884C\n */\n const handleKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault()\n if (value.trim() && !disabled) {\n onSend()\n }\n }\n }\n\n /**\n * \u5904\u7406\u8F93\u5165\u53D8\u5316\n */\n const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n const newValue = event.target.value\n\n // \u5B57\u7B26\u6570\u9650\u5236\n if (newValue.length <= maxLength) {\n onChange(newValue)\n }\n }\n\n /**\n * \u5904\u7406\u53D1\u9001\u6309\u94AE\u70B9\u51FB\n */\n const handleSendClick = () => {\n if (value.trim() && !disabled) {\n onSend()\n }\n }\n\n const canSend = value.trim().length > 0 && !disabled\n\n return (\n <div className={`flex items-end gap-2 bg-white px-4 py-3 ${className}`}>\n {/* \u8F93\u5165\u6846\u5BB9\u5668 - \u5E26\u6E10\u53D8\u8FB9\u6846 */}\n <div\n className=\"flex flex-1 items-center gap-2 rounded-2xl\"\n style={{\n background: 'linear-gradient(to right, #7687F3, #7687F3, #4DA8F5, #A3DFCE)',\n padding: '2px',\n }}\n >\n {/* \u5185\u90E8\u767D\u8272\u80CC\u666F */}\n <div className=\"flex flex-1 items-center gap-2 bg-white px-3 py-2\" style={{ borderRadius: '14px' }}>\n {/* \u6587\u672C\u8F93\u5165\u6846 */}\n <textarea\n ref={textareaRef}\n value={value}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={disabled}\n autoFocus={autoFocus}\n rows={1}\n className=\"flex-1 resize-none bg-transparent text-sm text-gray-900 outline-none placeholder:text-gray-400 disabled:cursor-not-allowed disabled:opacity-50\"\n style={{\n resize: 'none',\n }}\n />\n\n {/* \u5B57\u7B26\u6570\u63D0\u793A (\u63A5\u8FD1\u4E0A\u9650\u65F6\u663E\u793A) */}\n {value.length > maxLength * 0.8 && (\n <span className=\"text-xs text-gray-400\">\n {value.length}/{maxLength}\n </span>\n )}\n\n {/* \u53D1\u9001\u6309\u94AE */}\n <button\n type=\"button\"\n onClick={handleSendClick}\n disabled={!canSend}\n className={`shrink-0 rounded-full p-2 transition-all ${canSend ? ' active:scale-95' : 'cursor-not-allowed '}`}\n style={\n canSend\n ? {\n background: 'linear-gradient(to bottom, #A3DFCE, #4DA8F5, #7687F3)',\n }\n : { background: '#BEBEBE' }\n }\n aria-label=\"\u53D1\u9001\u6D88\u606F\"\n >\n <SendIcon />\n </button>\n </div>\n </div>\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,eAAAE,IAAA,eAAAC,EAAAH,GA0DE,IAAAI,EAAA,6BApDFC,EAAyC,iBAmDzC,MAAMC,EAAqB,OACzB,QAAC,OAAI,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,MAAM,6BAChE,oBAAC,QAAK,EAAE,2BAA2B,OAAO,QAAQ,eAAa,IAAI,iBAAe,QAAQ,KAC1F,OAAC,QACC,EAAE,gGACF,OAAO,QACP,eAAa,IACb,iBAAe,QACf,kBAAgB,QAClB,GACF,EA4BWJ,EAAsC,CAAC,CAClD,MAAAK,EACA,SAAAC,EACA,OAAAC,EACA,YAAAC,EAAc,GACd,SAAAC,EAAW,GACX,UAAAC,EAAY,GACZ,UAAAC,EAAY,IACZ,UAAAC,EAAY,EACd,IAAM,CACJ,MAAMC,KAAc,UAA4B,IAAI,KAKpD,aAAU,IAAM,CACd,MAAMC,EAAWD,EAAY,QAC7B,GAAI,CAACC,EAAU,OAGfA,EAAS,MAAM,OAAS,OAIxB,MAAMC,EAAY,KAAK,IAAID,EAAS,aADlB,GACyC,EAC3DA,EAAS,MAAM,OAAS,GAAGC,CAAS,IACtC,EAAG,CAACV,CAAK,CAAC,EAMV,MAAMW,EAAiBC,GAAoD,CACrEA,EAAM,MAAQ,SAAW,CAACA,EAAM,WAClCA,EAAM,eAAe,EACjBZ,EAAM,KAAK,GAAK,CAACI,GACnBF,EAAO,EAGb,EAKMW,EAAgBD,GAAkD,CACtE,MAAME,EAAWF,EAAM,OAAO,MAG1BE,EAAS,QAAUR,GACrBL,EAASa,CAAQ,CAErB,EAKMC,EAAkB,IAAM,CACxBf,EAAM,KAAK,GAAK,CAACI,GACnBF,EAAO,CAEX,EAEMc,EAAUhB,EAAM,KAAK,EAAE,OAAS,GAAK,CAACI,EAE5C,SACE,OAAC,OAAI,UAAW,2CAA2CG,CAAS,GAElE,mBAAC,OACC,UAAU,6CACV,MAAO,CACL,WAAY,gEACZ,QAAS,KACX,EAGA,oBAAC,OAAI,UAAU,oDAAoD,MAAO,CAAE,aAAc,MAAO,EAE/F,oBAAC,YACC,IAAKC,EACL,MAAOR,EACP,SAAUa,EACV,UAAWF,EACX,YAAaR,EACb,SAAUC,EACV,UAAWC,EACX,KAAM,EACN,UAAU,iJACV,MAAO,CACL,OAAQ,MACV,EACF,EAGCL,EAAM,OAASM,EAAY,OAC1B,QAAC,QAAK,UAAU,wBACb,UAAAN,EAAM,OAAO,IAAEM,GAClB,KAIF,OAAC,UACC,KAAK,SACL,QAASS,EACT,SAAU,CAACC,EACX,UAAW,4CAA4CA,EAAU,mBAAqB,qBAAqB,GAC3G,MACEA,EACI,CACE,WAAY,uDACd,EACA,CAAE,WAAY,SAAU,EAE9B,aAAW,2BAEX,mBAACjB,EAAA,EAAS,EACZ,GACF,EACF,EACF,CAEJ",
|
|
6
|
+
"names": ["ChatInput_exports", "__export", "ChatInput", "__toCommonJS", "import_jsx_runtime", "import_react", "SendIcon", "value", "onChange", "onSend", "placeholder", "disabled", "autoFocus", "maxLength", "className", "textareaRef", "textarea", "newHeight", "handleKeyDown", "event", "handleChange", "newValue", "handleSendClick", "canSend"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 单条聊天消息组件
|
|
3
|
+
* 显示消息气泡、发送者、时间戳
|
|
4
|
+
* 基于 specs/livechat-widget/plan.md 的消息展示设计
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import type { Message, MessageRenderer } from '../types';
|
|
8
|
+
import { MessageRendererRegistry } from '../utils/messageRenderers';
|
|
9
|
+
export interface ChatMessageProps {
|
|
10
|
+
/**
|
|
11
|
+
* 消息数据
|
|
12
|
+
*/
|
|
13
|
+
message: Message;
|
|
14
|
+
/**
|
|
15
|
+
* 自定义渲染器注册表
|
|
16
|
+
*/
|
|
17
|
+
rendererRegistry?: MessageRendererRegistry;
|
|
18
|
+
/**
|
|
19
|
+
* 默认渲染器
|
|
20
|
+
*/
|
|
21
|
+
defaultRenderer?: MessageRenderer;
|
|
22
|
+
/**
|
|
23
|
+
* 是否显示时间戳
|
|
24
|
+
* @default true
|
|
25
|
+
*/
|
|
26
|
+
showTimestamp?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* 自定义样式类名
|
|
29
|
+
*/
|
|
30
|
+
className?: string;
|
|
31
|
+
/**
|
|
32
|
+
* 商品添加到购物车回调
|
|
33
|
+
*/
|
|
34
|
+
onAddToCart?: (product: any) => void;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 单条聊天消息组件
|
|
38
|
+
*
|
|
39
|
+
* 功能:
|
|
40
|
+
* - 显示消息气泡(用户 vs AI 助手不同样式)
|
|
41
|
+
* - 支持多个 content 块(一条消息可包含多种内容类型)
|
|
42
|
+
* - 显示时间戳
|
|
43
|
+
* - 系统消息居中显示
|
|
44
|
+
*
|
|
45
|
+
* 样式规则:
|
|
46
|
+
* - 用户消息:右对齐,灰色背景
|
|
47
|
+
* - AI 助手消息:左对齐,白色背景
|
|
48
|
+
* - 系统消息:居中,黄色背景
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```tsx
|
|
52
|
+
* <ChatMessage
|
|
53
|
+
* message={message}
|
|
54
|
+
* rendererRegistry={customRegistry}
|
|
55
|
+
* showTimestamp={true}
|
|
56
|
+
* />
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare const ChatMessage: React.FC<ChatMessageProps>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";var c=Object.defineProperty;var x=Object.getOwnPropertyDescriptor;var v=Object.getOwnPropertyNames;var w=Object.prototype.hasOwnProperty;var R=(e,t)=>{for(var r in t)c(e,r,{get:t[r],enumerable:!0})},b=(e,t,r,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of v(t))!w.call(e,o)&&o!==r&&c(e,o,{get:()=>t[o],enumerable:!(a=x(t,o))||a.enumerable});return e};var C=e=>b(c({},"__esModule",{value:!0}),e);var N={};R(N,{ChatMessage:()=>h});module.exports=C(N);var s=require("react/jsx-runtime"),d=require("./MessageContent");function M(e){const t=new Date(e),r=t.getHours().toString().padStart(2,"0"),a=t.getMinutes().toString().padStart(2,"0");return`${r}:${a}`}const h=({message:e,rendererRegistry:t,defaultRenderer:r,showTimestamp:a=!0,className:o="",onAddToCart:p})=>{const i=e.role==="user",S=e.role==="assistant",f=e.role==="system",y=e.role==="tool";if(f)return(0,s.jsx)("div",{className:`flex justify-center py-2 ${o}`,children:(0,s.jsx)("div",{className:"max-w-xs rounded-lg border border-yellow-200 bg-yellow-50 px-4 py-2",children:e.content.map((n,l)=>(0,s.jsx)(d.MessageContent,{content:n,isUser:!1,isSystem:!0,rendererRegistry:t,defaultRenderer:r},l))})});if(y)return null;const u=["product_list","product_comparison","faq_list","promotion_list","cart"],m=e.content.filter(n=>!u.includes(n.type)),g=e.content.filter(n=>u.includes(n.type));return(0,s.jsx)("div",{className:`flex ${i?"justify-end":"justify-start"} py-2 ${o}`,children:(0,s.jsxs)("div",{className:"flex w-fit max-w-full flex-col gap-2",children:[m.length>0&&(0,s.jsx)("div",{className:`w-full min-w-0 overflow-hidden rounded-2xl px-4 py-2 ${i?"rounded-br-sm text-white":"rounded-bl-sm text-[#1D1D1F]"}`,style:{backgroundColor:i?"#005D8E":"#F5F6F7"},children:(0,s.jsx)("div",{className:"flex w-full min-w-0 flex-col gap-2",children:m.map((n,l)=>(0,s.jsx)(d.MessageContent,{content:n,isUser:i,isSystem:!1,rendererRegistry:t,defaultRenderer:r,onAddToCart:p},l))})}),g.map((n,l)=>(0,s.jsx)("div",{className:"w-full",children:(0,s.jsx)(d.MessageContent,{content:n,isUser:i,isSystem:!1,rendererRegistry:t,defaultRenderer:r,onAddToCart:p})},`standalone-${l}`)),a&&(0,s.jsx)("span",{className:`
|
|
2
|
+
px-2 text-xs text-gray-400
|
|
3
|
+
${i?"text-right":"text-left"}
|
|
4
|
+
`,children:M(e.timestamp)})]})})};
|
|
5
|
+
//# sourceMappingURL=ChatMessage.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/components/LiveChatWidget/components/ChatMessage.tsx"],
|
|
4
|
+
"sourcesContent": ["/**\n * \u5355\u6761\u804A\u5929\u6D88\u606F\u7EC4\u4EF6\n * \u663E\u793A\u6D88\u606F\u6C14\u6CE1\u3001\u53D1\u9001\u8005\u3001\u65F6\u95F4\u6233\n * \u57FA\u4E8E specs/livechat-widget/plan.md \u7684\u6D88\u606F\u5C55\u793A\u8BBE\u8BA1\n */\n\nimport React from 'react'\nimport type { Message, MessageRenderer } from '../types'\nimport { MessageContent } from './MessageContent'\nimport { MessageRendererRegistry } from '../utils/messageRenderers'\n\nexport interface ChatMessageProps {\n /**\n * \u6D88\u606F\u6570\u636E\n */\n message: Message\n\n /**\n * \u81EA\u5B9A\u4E49\u6E32\u67D3\u5668\u6CE8\u518C\u8868\n */\n rendererRegistry?: MessageRendererRegistry\n\n /**\n * \u9ED8\u8BA4\u6E32\u67D3\u5668\n */\n defaultRenderer?: MessageRenderer\n\n /**\n * \u662F\u5426\u663E\u793A\u65F6\u95F4\u6233\n * @default true\n */\n showTimestamp?: boolean\n\n /**\n * \u81EA\u5B9A\u4E49\u6837\u5F0F\u7C7B\u540D\n */\n className?: string\n\n /**\n * \u5546\u54C1\u6DFB\u52A0\u5230\u8D2D\u7269\u8F66\u56DE\u8C03\n */\n onAddToCart?: (product: any) => void\n}\n\n/**\n * \u683C\u5F0F\u5316\u65F6\u95F4\u6233\u4E3A\u53EF\u8BFB\u683C\u5F0F\n * @param timestamp Unix \u65F6\u95F4\u6233\uFF08\u6BEB\u79D2\uFF09\n * @returns \u683C\u5F0F\u5316\u540E\u7684\u65F6\u95F4\u5B57\u7B26\u4E32 (\u5982 \"14:30\")\n */\nfunction formatTimestamp(timestamp: number): string {\n const date = new Date(timestamp)\n const hours = date.getHours().toString().padStart(2, '0')\n const minutes = date.getMinutes().toString().padStart(2, '0')\n return `${hours}:${minutes}`\n}\n\n/**\n * \u5355\u6761\u804A\u5929\u6D88\u606F\u7EC4\u4EF6\n *\n * \u529F\u80FD\uFF1A\n * - \u663E\u793A\u6D88\u606F\u6C14\u6CE1\uFF08\u7528\u6237 vs AI \u52A9\u624B\u4E0D\u540C\u6837\u5F0F\uFF09\n * - \u652F\u6301\u591A\u4E2A content \u5757\uFF08\u4E00\u6761\u6D88\u606F\u53EF\u5305\u542B\u591A\u79CD\u5185\u5BB9\u7C7B\u578B\uFF09\n * - \u663E\u793A\u65F6\u95F4\u6233\n * - \u7CFB\u7EDF\u6D88\u606F\u5C45\u4E2D\u663E\u793A\n *\n * \u6837\u5F0F\u89C4\u5219\uFF1A\n * - \u7528\u6237\u6D88\u606F\uFF1A\u53F3\u5BF9\u9F50\uFF0C\u7070\u8272\u80CC\u666F\n * - AI \u52A9\u624B\u6D88\u606F\uFF1A\u5DE6\u5BF9\u9F50\uFF0C\u767D\u8272\u80CC\u666F\n * - \u7CFB\u7EDF\u6D88\u606F\uFF1A\u5C45\u4E2D\uFF0C\u9EC4\u8272\u80CC\u666F\n *\n * @example\n * ```tsx\n * <ChatMessage\n * message={message}\n * rendererRegistry={customRegistry}\n * showTimestamp={true}\n * />\n * ```\n */\nexport const ChatMessage: React.FC<ChatMessageProps> = ({\n message,\n rendererRegistry,\n defaultRenderer,\n showTimestamp = true,\n className = '',\n onAddToCart,\n}) => {\n const isUser = message.role === 'user'\n const isAssistant = message.role === 'assistant'\n const isSystem = message.role === 'system'\n const isTool = message.role === 'tool'\n\n // \u7CFB\u7EDF\u6D88\u606F\u7279\u6B8A\u5904\u7406\uFF08\u5C45\u4E2D\u663E\u793A\uFF09\n if (isSystem) {\n return (\n <div className={`flex justify-center py-2 ${className}`}>\n <div className=\"max-w-xs rounded-lg border border-yellow-200 bg-yellow-50 px-4 py-2\">\n {message.content.map((content, index) => (\n <MessageContent\n key={index}\n content={content}\n isUser={false}\n isSystem={true}\n rendererRegistry={rendererRegistry}\n defaultRenderer={defaultRenderer}\n />\n ))}\n </div>\n </div>\n )\n }\n\n // \u5DE5\u5177\u6D88\u606F\uFF08\u901A\u5E38\u4E0D\u663E\u793A\uFF0C\u6216\u663E\u793A\u4E3A\u7CFB\u7EDF\u6D88\u606F\uFF09\n if (isTool) {\n return null\n }\n\n // \u5206\u79BB\u5185\u5BB9\u7C7B\u578B\uFF1A\u9700\u8981\u72EC\u7ACB\u6E32\u67D3\u7684\u7ED3\u6784\u5316\u5185\u5BB9\n const structuredContentTypes = ['product_list', 'product_comparison', 'faq_list', 'promotion_list', 'cart']\n\n // \u5C06\u5185\u5BB9\u5206\u4E3A\u4E24\u7EC4\uFF1A\u6C14\u6CE1\u5185\u5BB9 \u548C \u72EC\u7ACB\u5185\u5BB9\n const bubbleContent = message.content.filter(c => !structuredContentTypes.includes(c.type))\n const standaloneContent = message.content.filter(c => structuredContentTypes.includes(c.type))\n\n // \u7528\u6237/\u52A9\u624B\u6D88\u606F\n return (\n <div className={`flex ${isUser ? 'justify-end' : 'justify-start'} py-2 ${className}`}>\n <div className=\"flex w-fit max-w-full flex-col gap-2\">\n {/* \u6D88\u606F\u6C14\u6CE1\uFF08\u4EC5\u5305\u542B\u6587\u672C\u548C\u5FEB\u6377\u56DE\u590D\u7B49\uFF09 */}\n {bubbleContent.length > 0 && (\n <div\n className={`w-full min-w-0 overflow-hidden rounded-2xl px-4 py-2 ${isUser ? 'rounded-br-sm text-white' : 'rounded-bl-sm text-[#1D1D1F]'}`}\n style={{\n backgroundColor: isUser ? '#005D8E' : '#F5F6F7',\n }}\n >\n {/* \u6E32\u67D3\u6C14\u6CE1\u5185\u7684\u5185\u5BB9\u5757 */}\n <div className=\"flex w-full min-w-0 flex-col gap-2\">\n {bubbleContent.map((content, index) => (\n <MessageContent\n key={index}\n content={content}\n isUser={isUser}\n isSystem={false}\n rendererRegistry={rendererRegistry}\n defaultRenderer={defaultRenderer}\n onAddToCart={onAddToCart}\n />\n ))}\n </div>\n </div>\n )}\n\n {/* \u72EC\u7ACB\u6E32\u67D3\u7684\u7ED3\u6784\u5316\u5185\u5BB9\uFF08\u4E0D\u5728\u6C14\u6CE1\u5185\uFF09 */}\n {standaloneContent.map((content, index) => (\n <div key={`standalone-${index}`} className=\"w-full\">\n <MessageContent\n content={content}\n isUser={isUser}\n isSystem={false}\n rendererRegistry={rendererRegistry}\n defaultRenderer={defaultRenderer}\n onAddToCart={onAddToCart}\n />\n </div>\n ))}\n\n {/* \u65F6\u95F4\u6233 */}\n {showTimestamp && (\n <span\n className={`\n px-2 text-xs text-gray-400\n ${isUser ? 'text-right' : 'text-left'}\n `}\n >\n {formatTimestamp(message.timestamp)}\n </span>\n )}\n </div>\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,iBAAAE,IAAA,eAAAC,EAAAH,GAkGY,IAAAI,EAAA,6BA1FZC,EAA+B,4BAyC/B,SAASC,EAAgBC,EAA2B,CAClD,MAAMC,EAAO,IAAI,KAAKD,CAAS,EACzBE,EAAQD,EAAK,SAAS,EAAE,SAAS,EAAE,SAAS,EAAG,GAAG,EAClDE,EAAUF,EAAK,WAAW,EAAE,SAAS,EAAE,SAAS,EAAG,GAAG,EAC5D,MAAO,GAAGC,CAAK,IAAIC,CAAO,EAC5B,CAyBO,MAAMR,EAA0C,CAAC,CACtD,QAAAS,EACA,iBAAAC,EACA,gBAAAC,EACA,cAAAC,EAAgB,GAChB,UAAAC,EAAY,GACZ,YAAAC,CACF,IAAM,CACJ,MAAMC,EAASN,EAAQ,OAAS,OAC1BO,EAAcP,EAAQ,OAAS,YAC/BQ,EAAWR,EAAQ,OAAS,SAC5BS,EAAST,EAAQ,OAAS,OAGhC,GAAIQ,EACF,SACE,OAAC,OAAI,UAAW,4BAA4BJ,CAAS,GACnD,mBAAC,OAAI,UAAU,sEACZ,SAAAJ,EAAQ,QAAQ,IAAI,CAACU,EAASC,OAC7B,OAAC,kBAEC,QAASD,EACT,OAAQ,GACR,SAAU,GACV,iBAAkBT,EAClB,gBAAiBC,GALZS,CAMP,CACD,EACH,EACF,EAKJ,GAAIF,EACF,OAAO,KAIT,MAAMG,EAAyB,CAAC,eAAgB,qBAAsB,WAAY,iBAAkB,MAAM,EAGpGC,EAAgBb,EAAQ,QAAQ,OAAOc,GAAK,CAACF,EAAuB,SAASE,EAAE,IAAI,CAAC,EACpFC,EAAoBf,EAAQ,QAAQ,OAAOc,GAAKF,EAAuB,SAASE,EAAE,IAAI,CAAC,EAG7F,SACE,OAAC,OAAI,UAAW,QAAQR,EAAS,cAAgB,eAAe,SAASF,CAAS,GAChF,oBAAC,OAAI,UAAU,uCAEZ,UAAAS,EAAc,OAAS,MACtB,OAAC,OACC,UAAW,wDAAwDP,EAAS,2BAA6B,+BAA+B,GACxI,MAAO,CACL,gBAAiBA,EAAS,UAAY,SACxC,EAGA,mBAAC,OAAI,UAAU,qCACZ,SAAAO,EAAc,IAAI,CAACH,EAASC,OAC3B,OAAC,kBAEC,QAASD,EACT,OAAQJ,EACR,SAAU,GACV,iBAAkBL,EAClB,gBAAiBC,EACjB,YAAaG,GANRM,CAOP,CACD,EACH,EACF,EAIDI,EAAkB,IAAI,CAACL,EAASC,OAC/B,OAAC,OAAgC,UAAU,SACzC,mBAAC,kBACC,QAASD,EACT,OAAQJ,EACR,SAAU,GACV,iBAAkBL,EAClB,gBAAiBC,EACjB,YAAaG,EACf,GARQ,cAAcM,CAAK,EAS7B,CACD,EAGAR,MACC,OAAC,QACC,UAAW;AAAA;AAAA,gBAEPG,EAAS,aAAe,WAAW;AAAA,cAGtC,SAAAX,EAAgBK,EAAQ,SAAS,EACpC,GAEJ,EACF,CAEJ",
|
|
6
|
+
"names": ["ChatMessage_exports", "__export", "ChatMessage", "__toCommonJS", "import_jsx_runtime", "import_MessageContent", "formatTimestamp", "timestamp", "date", "hours", "minutes", "message", "rendererRegistry", "defaultRenderer", "showTimestamp", "className", "onAddToCart", "isUser", "isAssistant", "isSystem", "isTool", "content", "index", "structuredContentTypes", "bubbleContent", "c", "standaloneContent"]
|
|
7
|
+
}
|