@anker-in/campaign-ui 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/cjs/components/LiveChatWidget/components/ChatInput.js +1 -1
  2. package/dist/cjs/components/LiveChatWidget/components/ChatInput.js.map +2 -2
  3. package/dist/cjs/components/LiveChatWidget/components/ChatMessage.js +1 -1
  4. package/dist/cjs/components/LiveChatWidget/components/ChatMessage.js.map +2 -2
  5. package/dist/cjs/components/LiveChatWidget/components/MessageContent/CartCard.js +1 -1
  6. package/dist/cjs/components/LiveChatWidget/components/MessageContent/CartCard.js.map +2 -2
  7. package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductCard.js +1 -1
  8. package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductCard.js.map +2 -2
  9. package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductComparison.js +1 -1
  10. package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductComparison.js.map +2 -2
  11. package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductList.js +1 -1
  12. package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductList.js.map +2 -2
  13. package/dist/cjs/components/LiveChatWidget/components/MessageContent/TextBlock.js +1 -1
  14. package/dist/cjs/components/LiveChatWidget/components/MessageContent/TextBlock.js.map +2 -2
  15. package/dist/cjs/components/LiveChatWidget/components/MessageContent/ThinkingBlock.js +1 -1
  16. package/dist/cjs/components/LiveChatWidget/components/MessageContent/ThinkingBlock.js.map +2 -2
  17. package/dist/cjs/stories/CartCard.stories.d.ts +33 -0
  18. package/dist/cjs/stories/CartCard.stories.js +21 -0
  19. package/dist/cjs/stories/CartCard.stories.js.map +7 -0
  20. package/dist/cjs/stories/LiveChatWidget.stories.js +2 -2
  21. package/dist/cjs/stories/LiveChatWidget.stories.js.map +2 -2
  22. package/dist/esm/components/LiveChatWidget/components/ChatInput.js +1 -1
  23. package/dist/esm/components/LiveChatWidget/components/ChatInput.js.map +2 -2
  24. package/dist/esm/components/LiveChatWidget/components/ChatMessage.js +2 -2
  25. package/dist/esm/components/LiveChatWidget/components/ChatMessage.js.map +2 -2
  26. package/dist/esm/components/LiveChatWidget/components/MessageContent/CartCard.js +1 -1
  27. package/dist/esm/components/LiveChatWidget/components/MessageContent/CartCard.js.map +2 -2
  28. package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductCard.js +1 -1
  29. package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductCard.js.map +2 -2
  30. package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductComparison.js +1 -1
  31. package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductComparison.js.map +2 -2
  32. package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductList.js +1 -1
  33. package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductList.js.map +2 -2
  34. package/dist/esm/components/LiveChatWidget/components/MessageContent/TextBlock.js +1 -1
  35. package/dist/esm/components/LiveChatWidget/components/MessageContent/TextBlock.js.map +2 -2
  36. package/dist/esm/components/LiveChatWidget/components/MessageContent/ThinkingBlock.js +1 -1
  37. package/dist/esm/components/LiveChatWidget/components/MessageContent/ThinkingBlock.js.map +2 -2
  38. package/dist/esm/stories/CartCard.stories.d.ts +33 -0
  39. package/dist/esm/stories/CartCard.stories.js +21 -0
  40. package/dist/esm/stories/CartCard.stories.js.map +7 -0
  41. package/dist/esm/stories/LiveChatWidget.stories.js +1 -1
  42. package/dist/esm/stories/LiveChatWidget.stories.js.map +2 -2
  43. package/package.json +1 -1
  44. package/src/components/LiveChatWidget/components/ChatInput.tsx +2 -2
  45. package/src/components/LiveChatWidget/components/ChatMessage.tsx +1 -1
  46. package/src/components/LiveChatWidget/components/MessageContent/CartCard.tsx +7 -7
  47. package/src/components/LiveChatWidget/components/MessageContent/ProductCard.tsx +2 -2
  48. package/src/components/LiveChatWidget/components/MessageContent/ProductComparison.tsx +1 -1
  49. package/src/components/LiveChatWidget/components/MessageContent/ProductList.tsx +2 -2
  50. package/src/components/LiveChatWidget/components/MessageContent/TextBlock.tsx +2 -2
  51. package/src/components/LiveChatWidget/components/MessageContent/ThinkingBlock.tsx +3 -3
  52. package/src/stories/LiveChatWidget.stories.tsx +2 -2
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/components/LiveChatWidget/components/MessageContent/ProductList.tsx"],
4
- "sourcesContent": ["/**\n * \u5546\u54C1\u5217\u8868\u6E32\u67D3\u5668\n * \u663E\u793A\u591A\u4E2A\u5546\u54C1\u7684\u7EB5\u5411\u5217\u8868\uFF0C\u652F\u6301\u5C55\u5F00/\u6536\u8D77\n * \u57FA\u4E8E specs/livechat-widget/data-model.md \u7684\u5546\u54C1\u6570\u636E\u6A21\u578B\n */\n\nimport React, { useState } from 'react'\nimport type { MessageRenderer, ProductListContent, Product, CommonText } from '../../types'\nimport { CURRENCY_SYMBOLS, DEFAULT_COMMON_TEXT } from '../../constants.js'\n\n/**\n * \u683C\u5F0F\u5316\u4EF7\u683C\n */\nfunction formatPrice(price: Product['price']): string {\n const { amount, currency } = price\n\n const symbol = CURRENCY_SYMBOLS[currency] || currency\n return `${symbol}${amount.toFixed(2)}`\n}\n\n/**\n * \u683C\u5F0F\u5316\u6298\u6263\u6807\u7B7E\u6587\u672C\n * @param discount \u6298\u6263\u5BF9\u8C61\n * @param currency \u8D27\u5E01\u4EE3\u7801\n * @param offText \"OFF\" \u6587\u6848\n * @returns \u683C\u5F0F\u5316\u540E\u7684\u6298\u6263\u6587\u672C\uFF08\u5982 \"$10 OFF\" \u6216 \"20% OFF\"\uFF09\n */\nfunction formatDiscountLabel(\n discount: { discount_type?: string; discount_value?: string | number },\n currency: string,\n offText: string = DEFAULT_COMMON_TEXT.off\n): string {\n if (!discount.discount_type || discount.discount_value === undefined) {\n return ''\n }\n\n // \u5C06 discount_value \u8F6C\u6362\u4E3A\u6570\u5B57\n const value =\n typeof discount.discount_value === 'string' ? parseFloat(discount.discount_value) : discount.discount_value\n\n if (isNaN(value)) {\n return ''\n }\n\n if (discount.discount_type === 'percentage') {\n return `${Math.round(value)}% ${offText}`\n }\n\n if (discount.discount_type === 'fixed_amount') {\n const symbol = CURRENCY_SYMBOLS[currency] || currency\n return `${symbol}${Math.round(value)} ${offText}`\n }\n\n return ''\n}\n\n/**\n * \u7D27\u51D1\u578B\u5546\u54C1\u5361\u7247\uFF08\u7528\u4E8E\u7EB5\u5411\u5217\u8868\uFF09\n */\nconst CompactProductCard: React.FC<{\n product: Product\n onAddToCart?: (product: Product) => void\n addToCartText?: string\n offText?: string\n}> = ({ product, onAddToCart, addToCartText = DEFAULT_COMMON_TEXT.addToCart, offText = DEFAULT_COMMON_TEXT.off }) => {\n const { title, description, price, imageUrl, stockStatus, averageRating, variants } = product\n\n const isOutOfStock = stockStatus === 'out_of_stock'\n\n // \u83B7\u53D6\u7B2C\u4E00\u4E2A\u53D8\u4F53\u7684\u6298\u6263\u4FE1\u606F\n const firstVariant = variants?.[0]\n const hasDiscount = firstVariant?.discount?.has_discount\n const discountPrice = hasDiscount ? firstVariant?.discount?.discount_price : null\n const discount = firstVariant?.discount\n\n // \u5F53\u524D\u663E\u793A\u4EF7\u683C\uFF1A\u6709\u6298\u6263\u65F6\u663E\u793A\u6298\u6263\u4EF7\uFF0C\u5426\u5219\u663E\u793A\u539F\u4EF7\n const currentPrice = discountPrice ? { amount: discountPrice, currency: price.currency } : price\n\n // \u683C\u5F0F\u5316\u6298\u6263\u6807\u7B7E\n const discountLabel = discount && hasDiscount ? formatDiscountLabel(discount, price.currency, offText) : ''\n\n const handleAddToCart = (e: React.MouseEvent) => {\n e.preventDefault()\n e.stopPropagation()\n if (onAddToCart) {\n onAddToCart(product)\n }\n }\n\n return (\n <div className=\"block w-full overflow-hidden rounded-2xl bg-[#F5F6F7] transition-shadow\">\n <div className=\"block\">\n <div className=\"flex gap-2 p-4\">\n {/* \u5546\u54C1\u56FE\u7247 */}\n <div className=\" flex shrink-0 items-center overflow-hidden rounded-md \" style={{ width: '40%' }}>\n <img\n src={imageUrl}\n alt={title}\n className={`h-auto w-full object-cover ${isOutOfStock ? 'opacity-50' : ''}`}\n loading=\"lazy\"\n />\n </div>\n\n {/* \u5546\u54C1\u4FE1\u606F */}\n <div className=\"flex flex-1 flex-col justify-center\">\n {/* \u6298\u6263\u6807\u7B7E */}\n {discountLabel && (\n <div\n className=\"mb-1 w-fit rounded-full px-2 text-sm font-bold leading-none tracking-[-0.04em] text-white\"\n style={{ backgroundColor: '#005D8E', paddingTop: '6px', paddingBottom: '4px' }}\n >\n {discountLabel}\n </div>\n )}\n\n {/* \u6807\u9898 */}\n <h4 className=\"line-clamp-2 text-base font-bold leading-[1.4] tracking-[-0.02em] text-[#080A0F]\">\n {title}\n </h4>\n\n {/* \u63CF\u8FF0\uFF08\u53EF\u9009\uFF09 */}\n {description && (\n <p className=\"line-clamp-2 text-sm font-bold leading-[1.4] tracking-[-0.02em] text-[#1D1D1F]\">\n {description}\n </p>\n )}\n\n {/* \u4EF7\u683C\u548C\u8BC4\u5206 */}\n <div className=\"mt-4 flex items-center gap-2\">\n <div className=\"flex items-center gap-1\">\n {/* \u5F53\u524D\u4EF7\u683C\uFF08\u6709\u6298\u6263\u65F6\u663E\u793A\u6298\u6263\u4EF7\uFF0C\u5426\u5219\u663E\u793A\u539F\u4EF7\uFF09 */}\n <span className=\"text-base font-bold leading-[1.4] tracking-[-0.02em] text-[#1D1D1F]\">\n {formatPrice(currentPrice)}\n </span>\n {/* \u539F\u4EF7\uFF08\u5212\u7EBF\u4EF7\uFF09- \u4EC5\u5728\u6709\u6298\u6263\u65F6\u663E\u793A */}\n {hasDiscount && (\n <span className=\"text-base font-bold leading-[1.4] tracking-[-0.02em] text-[#6D6D6F] line-through\">\n {formatPrice(price)}\n </span>\n )}\n </div>\n {/* \u8BC4\u5206\uFF08\u53EF\u9009\uFF09 */}\n {averageRating !== undefined && (\n <div className=\"flex items-center gap-0.5 text-xs text-gray-600\">\n <span className=\"text-yellow-500\">\u2B50</span>\n <span>{averageRating.toFixed(1)}</span>\n </div>\n )}\n </div>\n\n {/* Add to Cart \u6309\u94AE - \u5728\u4EF7\u683C\u4E0B\u65B9 */}\n <button\n type=\"button\"\n onClick={handleAddToCart}\n className=\"mt-2 w-fit rounded-full px-[20px] py-[10px] text-center text-sm font-bold leading-[1.2] tracking-[-0.04em] text-white\"\n style={{ backgroundColor: '#1D1D1F' }}\n >\n {addToCartText}\n </button>\n </div>\n </div>\n </div>\n </div>\n )\n}\n\n/**\n * \u5546\u54C1\u5217\u8868\u5185\u90E8\u7EC4\u4EF6\uFF08\u652F\u6301\u5C55\u5F00/\u6536\u8D77\uFF09\n */\nconst ProductListComponent: React.FC<{\n products: Product[]\n title?: string\n onAddToCart?: (product: Product) => void\n commonText?: CommonText\n}> = ({ products, title, onAddToCart, commonText }) => {\n const [isExpanded, setIsExpanded] = useState(false)\n\n // \u5408\u5E76\u9ED8\u8BA4\u6587\u6848\u548C\u81EA\u5B9A\u4E49\u6587\u6848\n const mergedText = { ...DEFAULT_COMMON_TEXT, ...commonText }\n\n // \u8FC7\u6EE4\u6389 null \u6216\u65E0\u6548\u7684\u4EA7\u54C1\n const validProducts = products.filter(p => p && p.shopifyId)\n\n // \u9ED8\u8BA4\u663E\u793A\u524D3\u4E2A\u4EA7\u54C1\n const INITIAL_DISPLAY_COUNT = 3\n const hasMore = validProducts.length > INITIAL_DISPLAY_COUNT\n const displayedProducts = isExpanded ? validProducts : validProducts.slice(0, INITIAL_DISPLAY_COUNT)\n\n return (\n <div className=\"flex w-full flex-col gap-2\">\n {/* \u5217\u8868\u6807\u9898\uFF08\u53EF\u9009\uFF09 */}\n {title && <h3 className=\"text-sm font-semibold text-gray-900\">{title}</h3>}\n\n {/* \u7EB5\u5411\u6392\u5217\u7684\u5546\u54C1\u5217\u8868 */}\n <div className=\"flex flex-col gap-1.5\">\n {displayedProducts.map(product => {\n if (!product || !product.shopifyId) return null\n return (\n <CompactProductCard\n key={product.shopifyId}\n product={product}\n onAddToCart={onAddToCart}\n addToCartText={mergedText.addToCart}\n offText={mergedText.off}\n />\n )\n })}\n </div>\n\n {/* Learn More \u6309\u94AE */}\n {hasMore && (\n <button\n type=\"button\"\n onClick={() => setIsExpanded(!isExpanded)}\n className=\"flex items-center justify-center gap-1.5 px-3 py-2 text-[14px] font-bold leading-[1.2] tracking-tighter text-[#080A0F]\"\n >\n <span>{isExpanded ? mergedText.showLess : mergedText.learnMore}</span>\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={`transition-transform ${isExpanded ? 'rotate-180' : ''}`}\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n )}\n </div>\n )\n}\n\n/**\n * \u5546\u54C1\u5217\u8868\u6E32\u67D3\u5668\n *\n * \u529F\u80FD\uFF1A\n * - \u7EB5\u5411\u5C55\u793A\u591A\u4E2A\u5546\u54C1\n * - \u9ED8\u8BA4\u663E\u793A\u524D3\u4E2A\u4EA7\u54C1\n * - \u652F\u6301\u5C55\u5F00/\u6536\u8D77\u67E5\u770B\u5168\u90E8\n * - \u7D27\u51D1\u578B\u5361\u7247\u8BBE\u8BA1\n * - \u53EF\u9009\u6807\u9898\n *\n * \u5E03\u5C40\uFF1A\n * ```\n * \u6807\u9898\uFF08\u53EF\u9009\uFF09\n * \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n * \u2502 [\u56FE] \u5546\u54C1\u6807\u9898 \u2502\n * \u2502 $29.99 \u2502\n * \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n * \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n * \u2502 [\u56FE] \u5546\u54C1\u6807\u9898 \u2502\n * \u2502 $39.99 \u2502\n * \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n * \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n * \u2502 [\u56FE] \u5546\u54C1\u6807\u9898 \u2502\n * \u2502 $49.99 \u2502\n * \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n * [ Learn More \u2193 ]\n * ```\n *\n * @example\n * ```tsx\n * const content: ProductListContent = {\n * type: 'product_list',\n * data: {\n * title: '\u76F8\u5173\u5546\u54C1\u63A8\u8350',\n * products: [product1, product2, product3, product4, product5]\n * }\n * }\n * <ProductList.render(content, false, false) />\n * ```\n */\nexport const ProductList: MessageRenderer = {\n render: content => {\n const productListContent = content as ProductListContent\n const { products, title, onAddToCart, commonText } = productListContent.data\n\n // \u8FC7\u6EE4\u6389 null \u6216\u65E0\u6548\u7684\u4EA7\u54C1\n const validProducts = products?.filter(p => p && p.shopifyId) || []\n\n if (validProducts.length === 0) {\n return null\n }\n\n return (\n <ProductListComponent products={validProducts} title={title} onAddToCart={onAddToCart} commonText={commonText} />\n )\n },\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * \u5546\u54C1\u5217\u8868\u6E32\u67D3\u5668\n * \u663E\u793A\u591A\u4E2A\u5546\u54C1\u7684\u7EB5\u5411\u5217\u8868\uFF0C\u652F\u6301\u5C55\u5F00/\u6536\u8D77\n * \u57FA\u4E8E specs/livechat-widget/data-model.md \u7684\u5546\u54C1\u6570\u636E\u6A21\u578B\n */\n\nimport React, { useState } from 'react'\nimport type { MessageRenderer, ProductListContent, Product, CommonText } from '../../types'\nimport { CURRENCY_SYMBOLS, DEFAULT_COMMON_TEXT } from '../../constants.js'\n\n/**\n * \u683C\u5F0F\u5316\u4EF7\u683C\n */\nfunction formatPrice(price: Product['price']): string {\n const { amount, currency } = price\n\n const symbol = CURRENCY_SYMBOLS[currency] || currency\n return `${symbol}${amount.toFixed(2)}`\n}\n\n/**\n * \u683C\u5F0F\u5316\u6298\u6263\u6807\u7B7E\u6587\u672C\n * @param discount \u6298\u6263\u5BF9\u8C61\n * @param currency \u8D27\u5E01\u4EE3\u7801\n * @param offText \"OFF\" \u6587\u6848\n * @returns \u683C\u5F0F\u5316\u540E\u7684\u6298\u6263\u6587\u672C\uFF08\u5982 \"$10 OFF\" \u6216 \"20% OFF\"\uFF09\n */\nfunction formatDiscountLabel(\n discount: { discount_type?: string; discount_value?: string | number },\n currency: string,\n offText: string = DEFAULT_COMMON_TEXT.off\n): string {\n if (!discount.discount_type || discount.discount_value === undefined) {\n return ''\n }\n\n // \u5C06 discount_value \u8F6C\u6362\u4E3A\u6570\u5B57\n const value =\n typeof discount.discount_value === 'string' ? parseFloat(discount.discount_value) : discount.discount_value\n\n if (isNaN(value)) {\n return ''\n }\n\n if (discount.discount_type === 'percentage') {\n return `${Math.round(value)}% ${offText}`\n }\n\n if (discount.discount_type === 'fixed_amount') {\n const symbol = CURRENCY_SYMBOLS[currency] || currency\n return `${symbol}${Math.round(value)} ${offText}`\n }\n\n return ''\n}\n\n/**\n * \u7D27\u51D1\u578B\u5546\u54C1\u5361\u7247\uFF08\u7528\u4E8E\u7EB5\u5411\u5217\u8868\uFF09\n */\nconst CompactProductCard: React.FC<{\n product: Product\n onAddToCart?: (product: Product) => void\n addToCartText?: string\n offText?: string\n}> = ({ product, onAddToCart, addToCartText = DEFAULT_COMMON_TEXT.addToCart, offText = DEFAULT_COMMON_TEXT.off }) => {\n const { title, description, price, imageUrl, stockStatus, averageRating, variants } = product\n\n const isOutOfStock = stockStatus === 'out_of_stock'\n\n // \u83B7\u53D6\u7B2C\u4E00\u4E2A\u53D8\u4F53\u7684\u6298\u6263\u4FE1\u606F\n const firstVariant = variants?.[0]\n const hasDiscount = firstVariant?.discount?.has_discount\n const discountPrice = hasDiscount ? firstVariant?.discount?.discount_price : null\n const discount = firstVariant?.discount\n\n // \u5F53\u524D\u663E\u793A\u4EF7\u683C\uFF1A\u6709\u6298\u6263\u65F6\u663E\u793A\u6298\u6263\u4EF7\uFF0C\u5426\u5219\u663E\u793A\u539F\u4EF7\n const currentPrice = discountPrice ? { amount: discountPrice, currency: price.currency } : price\n\n // \u683C\u5F0F\u5316\u6298\u6263\u6807\u7B7E\n const discountLabel = discount && hasDiscount ? formatDiscountLabel(discount, price.currency, offText) : ''\n\n const handleAddToCart = (e: React.MouseEvent) => {\n e.preventDefault()\n e.stopPropagation()\n if (onAddToCart) {\n onAddToCart(product)\n }\n }\n\n return (\n <div className=\"block w-full overflow-hidden rounded-2xl bg-[#F5F6F7] transition-shadow\">\n <div className=\"block\">\n <div className=\"flex gap-2 p-4\">\n {/* \u5546\u54C1\u56FE\u7247 */}\n <div className=\" flex shrink-0 items-center overflow-hidden rounded-md \" style={{ width: '40%' }}>\n <img\n src={imageUrl}\n alt={title}\n className={`h-auto w-full object-cover ${isOutOfStock ? 'opacity-50' : ''}`}\n loading=\"lazy\"\n />\n </div>\n\n {/* \u5546\u54C1\u4FE1\u606F */}\n <div className=\"flex flex-1 flex-col justify-center\">\n {/* \u6298\u6263\u6807\u7B7E */}\n {discountLabel && (\n <div\n className=\"livechat-tag-product mb-1 w-fit rounded-full px-2 text-sm font-bold leading-none tracking-[-0.04em] text-white\"\n style={{ backgroundColor: '#005D8E', paddingTop: '6px', paddingBottom: '4px' }}\n >\n {discountLabel}\n </div>\n )}\n\n {/* \u6807\u9898 */}\n <h4 className=\"line-clamp-2 text-base font-bold leading-[1.4] tracking-[-0.02em] text-[#080A0F]\">\n {title}\n </h4>\n\n {/* \u63CF\u8FF0\uFF08\u53EF\u9009\uFF09 */}\n {description && (\n <p className=\"line-clamp-2 text-sm font-bold leading-[1.4] tracking-[-0.02em] text-[#1D1D1F]\">\n {description}\n </p>\n )}\n\n {/* \u4EF7\u683C\u548C\u8BC4\u5206 */}\n <div className=\"mt-4 flex items-center gap-2\">\n <div className=\"flex items-center gap-1\">\n {/* \u5F53\u524D\u4EF7\u683C\uFF08\u6709\u6298\u6263\u65F6\u663E\u793A\u6298\u6263\u4EF7\uFF0C\u5426\u5219\u663E\u793A\u539F\u4EF7\uFF09 */}\n <span className=\"text-base font-bold leading-[1.4] tracking-[-0.02em] text-[#1D1D1F]\">\n {formatPrice(currentPrice)}\n </span>\n {/* \u539F\u4EF7\uFF08\u5212\u7EBF\u4EF7\uFF09- \u4EC5\u5728\u6709\u6298\u6263\u65F6\u663E\u793A */}\n {hasDiscount && (\n <span className=\"text-base font-bold leading-[1.4] tracking-[-0.02em] text-[#6D6D6F] line-through\">\n {formatPrice(price)}\n </span>\n )}\n </div>\n {/* \u8BC4\u5206\uFF08\u53EF\u9009\uFF09 */}\n {averageRating !== undefined && (\n <div className=\"flex items-center gap-0.5 text-xs text-gray-600\">\n <span className=\"text-yellow-500\">\u2B50</span>\n <span>{averageRating.toFixed(1)}</span>\n </div>\n )}\n </div>\n\n {/* Add to Cart \u6309\u94AE - \u5728\u4EF7\u683C\u4E0B\u65B9 */}\n <button\n type=\"button\"\n onClick={handleAddToCart}\n className=\"livechat-btn-primary mt-2 w-fit rounded-full px-[20px] py-[10px] text-center text-sm font-bold leading-[1.2] tracking-[-0.04em] text-white\"\n style={{ backgroundColor: '#1D1D1F' }}\n >\n {addToCartText}\n </button>\n </div>\n </div>\n </div>\n </div>\n )\n}\n\n/**\n * \u5546\u54C1\u5217\u8868\u5185\u90E8\u7EC4\u4EF6\uFF08\u652F\u6301\u5C55\u5F00/\u6536\u8D77\uFF09\n */\nconst ProductListComponent: React.FC<{\n products: Product[]\n title?: string\n onAddToCart?: (product: Product) => void\n commonText?: CommonText\n}> = ({ products, title, onAddToCart, commonText }) => {\n const [isExpanded, setIsExpanded] = useState(false)\n\n // \u5408\u5E76\u9ED8\u8BA4\u6587\u6848\u548C\u81EA\u5B9A\u4E49\u6587\u6848\n const mergedText = { ...DEFAULT_COMMON_TEXT, ...commonText }\n\n // \u8FC7\u6EE4\u6389 null \u6216\u65E0\u6548\u7684\u4EA7\u54C1\n const validProducts = products.filter(p => p && p.shopifyId)\n\n // \u9ED8\u8BA4\u663E\u793A\u524D3\u4E2A\u4EA7\u54C1\n const INITIAL_DISPLAY_COUNT = 3\n const hasMore = validProducts.length > INITIAL_DISPLAY_COUNT\n const displayedProducts = isExpanded ? validProducts : validProducts.slice(0, INITIAL_DISPLAY_COUNT)\n\n return (\n <div className=\"flex w-full flex-col gap-2\">\n {/* \u5217\u8868\u6807\u9898\uFF08\u53EF\u9009\uFF09 */}\n {title && <h3 className=\"text-sm font-semibold text-gray-900\">{title}</h3>}\n\n {/* \u7EB5\u5411\u6392\u5217\u7684\u5546\u54C1\u5217\u8868 */}\n <div className=\"flex flex-col gap-1.5\">\n {displayedProducts.map(product => {\n if (!product || !product.shopifyId) return null\n return (\n <CompactProductCard\n key={product.shopifyId}\n product={product}\n onAddToCart={onAddToCart}\n addToCartText={mergedText.addToCart}\n offText={mergedText.off}\n />\n )\n })}\n </div>\n\n {/* Learn More \u6309\u94AE */}\n {hasMore && (\n <button\n type=\"button\"\n onClick={() => setIsExpanded(!isExpanded)}\n className=\"flex items-center justify-center gap-1.5 px-3 py-2 text-[14px] font-bold leading-[1.2] tracking-tighter text-[#080A0F]\"\n >\n <span>{isExpanded ? mergedText.showLess : mergedText.learnMore}</span>\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={`transition-transform ${isExpanded ? 'rotate-180' : ''}`}\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n )}\n </div>\n )\n}\n\n/**\n * \u5546\u54C1\u5217\u8868\u6E32\u67D3\u5668\n *\n * \u529F\u80FD\uFF1A\n * - \u7EB5\u5411\u5C55\u793A\u591A\u4E2A\u5546\u54C1\n * - \u9ED8\u8BA4\u663E\u793A\u524D3\u4E2A\u4EA7\u54C1\n * - \u652F\u6301\u5C55\u5F00/\u6536\u8D77\u67E5\u770B\u5168\u90E8\n * - \u7D27\u51D1\u578B\u5361\u7247\u8BBE\u8BA1\n * - \u53EF\u9009\u6807\u9898\n *\n * \u5E03\u5C40\uFF1A\n * ```\n * \u6807\u9898\uFF08\u53EF\u9009\uFF09\n * \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n * \u2502 [\u56FE] \u5546\u54C1\u6807\u9898 \u2502\n * \u2502 $29.99 \u2502\n * \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n * \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n * \u2502 [\u56FE] \u5546\u54C1\u6807\u9898 \u2502\n * \u2502 $39.99 \u2502\n * \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n * \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n * \u2502 [\u56FE] \u5546\u54C1\u6807\u9898 \u2502\n * \u2502 $49.99 \u2502\n * \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n * [ Learn More \u2193 ]\n * ```\n *\n * @example\n * ```tsx\n * const content: ProductListContent = {\n * type: 'product_list',\n * data: {\n * title: '\u76F8\u5173\u5546\u54C1\u63A8\u8350',\n * products: [product1, product2, product3, product4, product5]\n * }\n * }\n * <ProductList.render(content, false, false) />\n * ```\n */\nexport const ProductList: MessageRenderer = {\n render: content => {\n const productListContent = content as ProductListContent\n const { products, title, onAddToCart, commonText } = productListContent.data\n\n // \u8FC7\u6EE4\u6389 null \u6216\u65E0\u6548\u7684\u4EA7\u54C1\n const validProducts = products?.filter(p => p && p.shopifyId) || []\n\n if (validProducts.length === 0) {\n return null\n }\n\n return (\n <ProductListComponent products={validProducts} title={title} onAddToCart={onAddToCart} commonText={commonText} />\n )\n },\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["ProductList_exports", "__export", "ProductList", "__toCommonJS", "import_jsx_runtime", "import_react", "import_constants", "formatPrice", "price", "amount", "currency", "formatDiscountLabel", "discount", "offText", "value", "CompactProductCard", "product", "onAddToCart", "addToCartText", "title", "description", "imageUrl", "stockStatus", "averageRating", "variants", "isOutOfStock", "firstVariant", "hasDiscount", "discountPrice", "currentPrice", "discountLabel", "handleAddToCart", "e", "ProductListComponent", "products", "commonText", "isExpanded", "setIsExpanded", "mergedText", "validProducts", "p", "INITIAL_DISPLAY_COUNT", "hasMore", "displayedProducts", "content", "productListContent"]
7
7
  }
@@ -1,2 +1,2 @@
1
- "use strict";var x=Object.create;var n=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var y=Object.getPrototypeOf,N=Object.prototype.hasOwnProperty;var f=(a,r)=>{for(var l in r)n(a,l,{get:r[l],enumerable:!0})},s=(a,r,l,d)=>{if(r&&typeof r=="object"||typeof r=="function")for(let t of g(r))!N.call(a,t)&&t!==l&&n(a,t,{get:()=>r[t],enumerable:!(d=i(r,t))||d.enumerable});return a};var m=(a,r,l)=>(l=a!=null?x(y(a)):{},s(r||!a||!a.__esModule?n(l,"default",{value:a,enumerable:!0}):l,a)),p=a=>s(n({},"__esModule",{value:!0}),a);var u={};f(u,{TextBlock:()=>h});module.exports=p(u);var o=require("react/jsx-runtime"),b=m(require("react-markdown")),c=m(require("remark-gfm"));const h={render:(a,r,l)=>{const d=a;return d.text?(0,o.jsx)("div",{className:"livechat-markdown text-base md:text-sm",children:(0,o.jsx)(b.default,{remarkPlugins:[c.default],components:{a:({node:t,...e})=>(0,o.jsx)("a",{...e,className:`underline ${r?"text-blue-200 hover:text-blue-100":"text-blue-600 hover:text-blue-700"}`,target:"_blank",rel:"noopener noreferrer"}),code:({node:t,...e})=>e.inline?(0,o.jsx)("code",{...e,className:`rounded px-1.5 py-0.5 font-mono text-xs ${r?"bg-[#004A6E] text-white":"bg-gray-200 text-gray-800"}`}):(0,o.jsx)("code",{...e,className:`block overflow-x-auto rounded px-3 py-2 font-mono text-xs ${r?"bg-[#004A6E] text-white":"bg-gray-200 text-gray-800"}`}),p:({node:t,...e})=>(0,o.jsx)("p",{...e,className:"last:mb-0"}),ul:({node:t,...e})=>(0,o.jsx)("ul",{...e,className:"ml-4 list-disc"}),ol:({node:t,...e})=>(0,o.jsx)("ol",{...e,className:"mb-2 ml-4 list-decimal"}),li:({node:t,...e})=>(0,o.jsx)("li",{...e,className:"mb-1"}),h1:({node:t,...e})=>(0,o.jsx)("h1",{...e,className:"mb-2 font-bold"}),h2:({node:t,...e})=>(0,o.jsx)("h2",{...e,className:"mb-2 font-bold"}),h3:({node:t,...e})=>(0,o.jsx)("h3",{...e,className:"mb-1 font-bold"}),strong:({node:t,...e})=>(0,o.jsx)("strong",{...e,className:"font-bold"}),em:({node:t,...e})=>(0,o.jsx)("em",{...e,className:"italic"}),table:({node:t,...e})=>(0,o.jsx)("div",{className:"my-2 overflow-x-auto",children:(0,o.jsx)("table",{...e,className:"min-w-full border-collapse border border-gray-300 text-base md:text-sm"})}),thead:({node:t,...e})=>(0,o.jsx)("thead",{...e,className:"bg-gray-100"}),tbody:({node:t,...e})=>(0,o.jsx)("tbody",{...e}),tr:({node:t,...e})=>(0,o.jsx)("tr",{...e,className:"border-b border-gray-300"}),th:({node:t,...e})=>(0,o.jsx)("th",{...e,className:"border border-gray-300 px-3 py-2 text-left font-semibold"}),td:({node:t,...e})=>(0,o.jsx)("td",{...e,className:"border border-gray-300 px-3 py-2"})},children:d.text})}):null}};
1
+ "use strict";var x=Object.create;var n=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var y=Object.getPrototypeOf,N=Object.prototype.hasOwnProperty;var f=(a,r)=>{for(var l in r)n(a,l,{get:r[l],enumerable:!0})},s=(a,r,l,d)=>{if(r&&typeof r=="object"||typeof r=="function")for(let t of g(r))!N.call(a,t)&&t!==l&&n(a,t,{get:()=>r[t],enumerable:!(d=i(r,t))||d.enumerable});return a};var m=(a,r,l)=>(l=a!=null?x(y(a)):{},s(r||!a||!a.__esModule?n(l,"default",{value:a,enumerable:!0}):l,a)),h=a=>s(n({},"__esModule",{value:!0}),a);var p={};f(p,{TextBlock:()=>u});module.exports=h(p);var o=require("react/jsx-runtime"),b=m(require("react-markdown")),c=m(require("remark-gfm"));const u={render:(a,r,l)=>{const d=a;return d.text?(0,o.jsx)("div",{className:"livechat-markdown text-base md:text-sm",children:(0,o.jsx)(b.default,{remarkPlugins:[c.default],components:{a:({node:t,...e})=>(0,o.jsx)("a",{...e,className:`underline ${r?"text-blue-200 hover:text-blue-100":"text-blue-600 hover:text-blue-700"}`,target:"_blank",rel:"noopener noreferrer"}),code:({node:t,...e})=>e.inline?(0,o.jsx)("code",{...e,className:`rounded px-1.5 py-0.5 font-mono text-xs ${r?"livechat-code-user bg-[#004A6E] text-white":"bg-gray-200 text-gray-800"}`}):(0,o.jsx)("code",{...e,className:`block overflow-x-auto rounded px-3 py-2 font-mono text-xs ${r?"livechat-code-user bg-[#004A6E] text-white":"bg-gray-200 text-gray-800"}`}),p:({node:t,...e})=>(0,o.jsx)("p",{...e,className:"last:mb-0"}),ul:({node:t,...e})=>(0,o.jsx)("ul",{...e,className:"ml-4 list-disc"}),ol:({node:t,...e})=>(0,o.jsx)("ol",{...e,className:"mb-2 ml-4 list-decimal"}),li:({node:t,...e})=>(0,o.jsx)("li",{...e,className:"mb-1"}),h1:({node:t,...e})=>(0,o.jsx)("h1",{...e,className:"mb-2 font-bold"}),h2:({node:t,...e})=>(0,o.jsx)("h2",{...e,className:"mb-2 font-bold"}),h3:({node:t,...e})=>(0,o.jsx)("h3",{...e,className:"mb-1 font-bold"}),strong:({node:t,...e})=>(0,o.jsx)("strong",{...e,className:"font-bold"}),em:({node:t,...e})=>(0,o.jsx)("em",{...e,className:"italic"}),table:({node:t,...e})=>(0,o.jsx)("div",{className:"my-2 overflow-x-auto",children:(0,o.jsx)("table",{...e,className:"min-w-full border-collapse border border-gray-300 text-base md:text-sm"})}),thead:({node:t,...e})=>(0,o.jsx)("thead",{...e,className:"bg-gray-100"}),tbody:({node:t,...e})=>(0,o.jsx)("tbody",{...e}),tr:({node:t,...e})=>(0,o.jsx)("tr",{...e,className:"border-b border-gray-300"}),th:({node:t,...e})=>(0,o.jsx)("th",{...e,className:"border border-gray-300 px-3 py-2 text-left font-semibold"}),td:({node:t,...e})=>(0,o.jsx)("td",{...e,className:"border border-gray-300 px-3 py-2"})},children:d.text})}):null}};
2
2
  //# sourceMappingURL=TextBlock.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/components/LiveChatWidget/components/MessageContent/TextBlock.tsx"],
4
- "sourcesContent": ["/**\n * \u6587\u672C\u6D88\u606F\u5185\u5BB9\u6E32\u67D3\u5668\n * \u652F\u6301 Markdown \u683C\u5F0F\n * \u57FA\u4E8E specs/livechat-widget/plan.md \u7684\u6587\u672C\u6D88\u606F\u8BBE\u8BA1\n */\n\nimport React from 'react'\nimport ReactMarkdown from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\nimport type { MessageRenderer, TextContent } from '../../types'\n\n/**\n * \u6587\u672C\u6D88\u606F\u6E32\u67D3\u5668\n *\n * \u529F\u80FD\uFF1A\n * - \u652F\u6301 Markdown \u8BED\u6CD5\uFF08\u7C97\u4F53\u3001\u659C\u4F53\u3001\u94FE\u63A5\u3001\u5217\u8868\u7B49\uFF09\n * - \u5B89\u5168\u6E32\u67D3\uFF08React Markdown \u81EA\u52A8\u9632\u62A4 XSS\uFF09\n * - \u54CD\u5E94\u5F0F\u6587\u672C\u6837\u5F0F\n *\n * Markdown \u652F\u6301\uFF1A\n * - \u7C97\u4F53\uFF1A**text** \u6216 __text__\n * - \u659C\u4F53\uFF1A*text* \u6216 _text_\n * - \u94FE\u63A5\uFF1A[text](url)\n * - \u5217\u8868\uFF1A- item \u6216 1. item\n * - \u4EE3\u7801\uFF1A`code` \u6216 ```code block```\n *\n * @example\n * ```tsx\n * const content: TextContent = {\n * type: 'text',\n * text: '\u60A8\u597D\uFF01**\u8FD9\u662F\u7C97\u4F53**\uFF0C*\u8FD9\u662F\u659C\u4F53*\u3002'\n * }\n * <TextBlock.render(content, false, false) />\n * ```\n */\nexport const TextBlock: MessageRenderer = {\n render: (content, isUser, isSystem) => {\n const textContent = content as TextContent\n\n if (!textContent.text) {\n return null\n }\n\n return (\n <div className=\"livechat-markdown text-base md:text-sm\">\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n components={{\n // \u81EA\u5B9A\u4E49\u94FE\u63A5\u6837\u5F0F\n a: ({ node, ...props }) => (\n <a\n {...props}\n className={`underline ${isUser ? 'text-blue-200 hover:text-blue-100' : 'text-blue-600 hover:text-blue-700'}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n />\n ),\n // \u81EA\u5B9A\u4E49\u4EE3\u7801\u5757\u6837\u5F0F\n code: ({ node, ...props }: any) =>\n props.inline ? (\n <code\n {...props}\n className={`rounded px-1.5 py-0.5 font-mono text-xs ${isUser ? 'bg-[#004A6E] text-white' : 'bg-gray-200 text-gray-800'}`}\n />\n ) : (\n <code\n {...props}\n className={`block overflow-x-auto rounded px-3 py-2 font-mono text-xs ${isUser ? 'bg-[#004A6E] text-white' : 'bg-gray-200 text-gray-800'}`}\n />\n ),\n // \u81EA\u5B9A\u4E49\u6BB5\u843D\u6837\u5F0F\n p: ({ node, ...props }) => <p {...props} className=\"last:mb-0\" />,\n // \u81EA\u5B9A\u4E49\u5217\u8868\u6837\u5F0F\n ul: ({ node, ...props }) => <ul {...props} className=\"ml-4 list-disc\" />,\n ol: ({ node, ...props }) => <ol {...props} className=\"mb-2 ml-4 list-decimal\" />,\n li: ({ node, ...props }) => <li {...props} className=\"mb-1\" />,\n // \u81EA\u5B9A\u4E49\u6807\u9898\u6837\u5F0F\n h1: ({ node, ...props }) => <h1 {...props} className=\"mb-2 font-bold\" />,\n h2: ({ node, ...props }) => <h2 {...props} className=\"mb-2 font-bold\" />,\n h3: ({ node, ...props }) => <h3 {...props} className=\"mb-1 font-bold\" />,\n // \u81EA\u5B9A\u4E49\u5F3A\u8C03\u6837\u5F0F\n strong: ({ node, ...props }) => <strong {...props} className=\"font-bold\" />,\n em: ({ node, ...props }) => <em {...props} className=\"italic\" />,\n // \u8868\u683C\u6837\u5F0F\n table: ({ node, ...props }) => (\n <div className=\"my-2 overflow-x-auto\">\n <table {...props} className=\"min-w-full border-collapse border border-gray-300 text-base md:text-sm\" />\n </div>\n ),\n thead: ({ node, ...props }) => (\n <thead {...props} className=\"bg-gray-100\" />\n ),\n tbody: ({ node, ...props }) => <tbody {...props} />,\n tr: ({ node, ...props }) => (\n <tr {...props} className=\"border-b border-gray-300\" />\n ),\n th: ({ node, ...props }) => (\n <th {...props} className=\"border border-gray-300 px-3 py-2 text-left font-semibold\" />\n ),\n td: ({ node, ...props }) => (\n <td {...props} className=\"border border-gray-300 px-3 py-2\" />\n ),\n }}\n >\n {textContent.text}\n </ReactMarkdown>\n </div>\n )\n },\n}\n"],
5
- "mappings": "0jBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,eAAAE,IAAA,eAAAC,EAAAH,GAkDc,IAAAI,EAAA,6BA3CdC,EAA0B,6BAC1BC,EAAsB,yBA2Bf,MAAMJ,EAA6B,CACxC,OAAQ,CAACK,EAASC,EAAQC,IAAa,CACrC,MAAMC,EAAcH,EAEpB,OAAKG,EAAY,QAKf,OAAC,OAAI,UAAU,yCACb,mBAAC,EAAAC,QAAA,CACC,cAAe,CAAC,EAAAC,OAAS,EACzB,WAAY,CAEV,EAAG,CAAC,CAAE,KAAAC,EAAM,GAAGC,CAAM,OACnB,OAAC,KACE,GAAGA,EACJ,UAAW,aAAaN,EAAS,oCAAsC,mCAAmC,GAC1G,OAAO,SACP,IAAI,sBACN,EAGF,KAAM,CAAC,CAAE,KAAAK,EAAM,GAAGC,CAAM,IACtBA,EAAM,UACJ,OAAC,QACE,GAAGA,EACJ,UAAW,2CAA2CN,EAAS,0BAA4B,2BAA2B,GACxH,KAEA,OAAC,QACE,GAAGM,EACJ,UAAW,6DAA6DN,EAAS,0BAA4B,2BAA2B,GAC1I,EAGJ,EAAG,CAAC,CAAE,KAAAK,EAAM,GAAGC,CAAM,OAAM,OAAC,KAAG,GAAGA,EAAO,UAAU,YAAY,EAE/D,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OAAM,OAAC,MAAI,GAAGA,EAAO,UAAU,iBAAiB,EACtE,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OAAM,OAAC,MAAI,GAAGA,EAAO,UAAU,yBAAyB,EAC9E,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OAAM,OAAC,MAAI,GAAGA,EAAO,UAAU,OAAO,EAE5D,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OAAM,OAAC,MAAI,GAAGA,EAAO,UAAU,iBAAiB,EACtE,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OAAM,OAAC,MAAI,GAAGA,EAAO,UAAU,iBAAiB,EACtE,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OAAM,OAAC,MAAI,GAAGA,EAAO,UAAU,iBAAiB,EAEtE,OAAQ,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OAAM,OAAC,UAAQ,GAAGA,EAAO,UAAU,YAAY,EACzE,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OAAM,OAAC,MAAI,GAAGA,EAAO,UAAU,SAAS,EAE9D,MAAO,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OACvB,OAAC,OAAI,UAAU,uBACb,mBAAC,SAAO,GAAGA,EAAO,UAAU,yEAAyE,EACvG,EAEF,MAAO,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OACvB,OAAC,SAAO,GAAGA,EAAO,UAAU,cAAc,EAE5C,MAAO,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OAAM,OAAC,SAAO,GAAGA,EAAO,EACjD,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OACpB,OAAC,MAAI,GAAGA,EAAO,UAAU,2BAA2B,EAEtD,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OACpB,OAAC,MAAI,GAAGA,EAAO,UAAU,2DAA2D,EAEtF,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OACpB,OAAC,MAAI,GAAGA,EAAO,UAAU,mCAAmC,CAEhE,EAEC,SAAAJ,EAAY,KACf,EACF,EAlEO,IAoEX,CACF",
4
+ "sourcesContent": ["/**\n * \u6587\u672C\u6D88\u606F\u5185\u5BB9\u6E32\u67D3\u5668\n * \u652F\u6301 Markdown \u683C\u5F0F\n * \u57FA\u4E8E specs/livechat-widget/plan.md \u7684\u6587\u672C\u6D88\u606F\u8BBE\u8BA1\n */\n\nimport React from 'react'\nimport ReactMarkdown from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\nimport type { MessageRenderer, TextContent } from '../../types'\n\n/**\n * \u6587\u672C\u6D88\u606F\u6E32\u67D3\u5668\n *\n * \u529F\u80FD\uFF1A\n * - \u652F\u6301 Markdown \u8BED\u6CD5\uFF08\u7C97\u4F53\u3001\u659C\u4F53\u3001\u94FE\u63A5\u3001\u5217\u8868\u7B49\uFF09\n * - \u5B89\u5168\u6E32\u67D3\uFF08React Markdown \u81EA\u52A8\u9632\u62A4 XSS\uFF09\n * - \u54CD\u5E94\u5F0F\u6587\u672C\u6837\u5F0F\n *\n * Markdown \u652F\u6301\uFF1A\n * - \u7C97\u4F53\uFF1A**text** \u6216 __text__\n * - \u659C\u4F53\uFF1A*text* \u6216 _text_\n * - \u94FE\u63A5\uFF1A[text](url)\n * - \u5217\u8868\uFF1A- item \u6216 1. item\n * - \u4EE3\u7801\uFF1A`code` \u6216 ```code block```\n *\n * @example\n * ```tsx\n * const content: TextContent = {\n * type: 'text',\n * text: '\u60A8\u597D\uFF01**\u8FD9\u662F\u7C97\u4F53**\uFF0C*\u8FD9\u662F\u659C\u4F53*\u3002'\n * }\n * <TextBlock.render(content, false, false) />\n * ```\n */\nexport const TextBlock: MessageRenderer = {\n render: (content, isUser, isSystem) => {\n const textContent = content as TextContent\n\n if (!textContent.text) {\n return null\n }\n\n return (\n <div className=\"livechat-markdown text-base md:text-sm\">\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n components={{\n // \u81EA\u5B9A\u4E49\u94FE\u63A5\u6837\u5F0F\n a: ({ node, ...props }) => (\n <a\n {...props}\n className={`underline ${isUser ? 'text-blue-200 hover:text-blue-100' : 'text-blue-600 hover:text-blue-700'}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n />\n ),\n // \u81EA\u5B9A\u4E49\u4EE3\u7801\u5757\u6837\u5F0F\n code: ({ node, ...props }: any) =>\n props.inline ? (\n <code\n {...props}\n className={`rounded px-1.5 py-0.5 font-mono text-xs ${isUser ? 'livechat-code-user bg-[#004A6E] text-white' : 'bg-gray-200 text-gray-800'}`}\n />\n ) : (\n <code\n {...props}\n className={`block overflow-x-auto rounded px-3 py-2 font-mono text-xs ${isUser ? 'livechat-code-user bg-[#004A6E] text-white' : 'bg-gray-200 text-gray-800'}`}\n />\n ),\n // \u81EA\u5B9A\u4E49\u6BB5\u843D\u6837\u5F0F\n p: ({ node, ...props }) => <p {...props} className=\"last:mb-0\" />,\n // \u81EA\u5B9A\u4E49\u5217\u8868\u6837\u5F0F\n ul: ({ node, ...props }) => <ul {...props} className=\"ml-4 list-disc\" />,\n ol: ({ node, ...props }) => <ol {...props} className=\"mb-2 ml-4 list-decimal\" />,\n li: ({ node, ...props }) => <li {...props} className=\"mb-1\" />,\n // \u81EA\u5B9A\u4E49\u6807\u9898\u6837\u5F0F\n h1: ({ node, ...props }) => <h1 {...props} className=\"mb-2 font-bold\" />,\n h2: ({ node, ...props }) => <h2 {...props} className=\"mb-2 font-bold\" />,\n h3: ({ node, ...props }) => <h3 {...props} className=\"mb-1 font-bold\" />,\n // \u81EA\u5B9A\u4E49\u5F3A\u8C03\u6837\u5F0F\n strong: ({ node, ...props }) => <strong {...props} className=\"font-bold\" />,\n em: ({ node, ...props }) => <em {...props} className=\"italic\" />,\n // \u8868\u683C\u6837\u5F0F\n table: ({ node, ...props }) => (\n <div className=\"my-2 overflow-x-auto\">\n <table {...props} className=\"min-w-full border-collapse border border-gray-300 text-base md:text-sm\" />\n </div>\n ),\n thead: ({ node, ...props }) => (\n <thead {...props} className=\"bg-gray-100\" />\n ),\n tbody: ({ node, ...props }) => <tbody {...props} />,\n tr: ({ node, ...props }) => (\n <tr {...props} className=\"border-b border-gray-300\" />\n ),\n th: ({ node, ...props }) => (\n <th {...props} className=\"border border-gray-300 px-3 py-2 text-left font-semibold\" />\n ),\n td: ({ node, ...props }) => (\n <td {...props} className=\"border border-gray-300 px-3 py-2\" />\n ),\n }}\n >\n {textContent.text}\n </ReactMarkdown>\n </div>\n )\n },\n}\n"],
5
+ "mappings": "0jBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,eAAAE,IAAA,eAAAC,EAAAH,GAkDc,IAAAI,EAAA,6BA3CdC,EAA0B,6BAC1BC,EAAsB,yBA2Bf,MAAMJ,EAA6B,CACxC,OAAQ,CAACK,EAASC,EAAQC,IAAa,CACrC,MAAMC,EAAcH,EAEpB,OAAKG,EAAY,QAKf,OAAC,OAAI,UAAU,yCACb,mBAAC,EAAAC,QAAA,CACC,cAAe,CAAC,EAAAC,OAAS,EACzB,WAAY,CAEV,EAAG,CAAC,CAAE,KAAAC,EAAM,GAAGC,CAAM,OACnB,OAAC,KACE,GAAGA,EACJ,UAAW,aAAaN,EAAS,oCAAsC,mCAAmC,GAC1G,OAAO,SACP,IAAI,sBACN,EAGF,KAAM,CAAC,CAAE,KAAAK,EAAM,GAAGC,CAAM,IACtBA,EAAM,UACJ,OAAC,QACE,GAAGA,EACJ,UAAW,2CAA2CN,EAAS,6CAA+C,2BAA2B,GAC3I,KAEA,OAAC,QACE,GAAGM,EACJ,UAAW,6DAA6DN,EAAS,6CAA+C,2BAA2B,GAC7J,EAGJ,EAAG,CAAC,CAAE,KAAAK,EAAM,GAAGC,CAAM,OAAM,OAAC,KAAG,GAAGA,EAAO,UAAU,YAAY,EAE/D,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OAAM,OAAC,MAAI,GAAGA,EAAO,UAAU,iBAAiB,EACtE,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OAAM,OAAC,MAAI,GAAGA,EAAO,UAAU,yBAAyB,EAC9E,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OAAM,OAAC,MAAI,GAAGA,EAAO,UAAU,OAAO,EAE5D,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OAAM,OAAC,MAAI,GAAGA,EAAO,UAAU,iBAAiB,EACtE,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OAAM,OAAC,MAAI,GAAGA,EAAO,UAAU,iBAAiB,EACtE,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OAAM,OAAC,MAAI,GAAGA,EAAO,UAAU,iBAAiB,EAEtE,OAAQ,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OAAM,OAAC,UAAQ,GAAGA,EAAO,UAAU,YAAY,EACzE,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OAAM,OAAC,MAAI,GAAGA,EAAO,UAAU,SAAS,EAE9D,MAAO,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OACvB,OAAC,OAAI,UAAU,uBACb,mBAAC,SAAO,GAAGA,EAAO,UAAU,yEAAyE,EACvG,EAEF,MAAO,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OACvB,OAAC,SAAO,GAAGA,EAAO,UAAU,cAAc,EAE5C,MAAO,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OAAM,OAAC,SAAO,GAAGA,EAAO,EACjD,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OACpB,OAAC,MAAI,GAAGA,EAAO,UAAU,2BAA2B,EAEtD,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OACpB,OAAC,MAAI,GAAGA,EAAO,UAAU,2DAA2D,EAEtF,GAAI,CAAC,CAAE,KAAAD,EAAM,GAAGC,CAAM,OACpB,OAAC,MAAI,GAAGA,EAAO,UAAU,mCAAmC,CAEhE,EAEC,SAAAJ,EAAY,KACf,EACF,EAlEO,IAoEX,CACF",
6
6
  "names": ["TextBlock_exports", "__export", "TextBlock", "__toCommonJS", "import_jsx_runtime", "import_react_markdown", "import_remark_gfm", "content", "isUser", "isSystem", "textContent", "ReactMarkdown", "remarkGfm", "node", "props"]
7
7
  }
@@ -1,2 +1,2 @@
1
- "use strict";var r=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var g=(s,e)=>{for(var a in e)r(s,a,{get:e[a],enumerable:!0})},c=(s,e,a,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of l(e))!d.call(s,t)&&t!==a&&r(s,t,{get:()=>e[t],enumerable:!(o=i(e,t))||o.enumerable});return s};var p=s=>c(r({},"__esModule",{value:!0}),s);var k={};g(k,{ThinkingBlock:()=>u});module.exports=p(k);var n=require("react/jsx-runtime");const u={render:(s,e,a)=>{const t=s.data.status||"";return(0,n.jsx)("div",{className:"flex items-center gap-2 py-1",children:(0,n.jsxs)("div",{className:"livechat-thinking-dots flex gap-1",children:[(0,n.jsx)("span",{className:"size-2 rounded-full",style:{backgroundColor:"rgba(0, 93, 142, 1)"}}),(0,n.jsx)("span",{className:"size-2 rounded-full",style:{backgroundColor:"rgba(0, 93, 142, 0.6)"}}),(0,n.jsx)("span",{className:"size-2 rounded-full",style:{backgroundColor:"rgba(0, 93, 142, 0.2)"}})]})})}};
1
+ "use strict";var i=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var r=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var g=(n,e)=>{for(var a in e)i(n,a,{get:e[a],enumerable:!0})},c=(n,e,a,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of r(e))!d.call(n,s)&&s!==a&&i(n,s,{get:()=>e[s],enumerable:!(o=l(e,s))||o.enumerable});return n};var p=n=>c(i({},"__esModule",{value:!0}),n);var h={};g(h,{ThinkingBlock:()=>u});module.exports=p(h);var t=require("react/jsx-runtime");const u={render:(n,e,a)=>{const s=n.data.status||"";return(0,t.jsx)("div",{className:"flex items-center gap-2 py-1",children:(0,t.jsxs)("div",{className:"livechat-thinking-dots flex gap-1",children:[(0,t.jsx)("span",{className:"livechat-loading-dot size-2 rounded-full",style:{backgroundColor:"rgba(0, 93, 142, 1)"}}),(0,t.jsx)("span",{className:"livechat-loading-dot size-2 rounded-full",style:{backgroundColor:"rgba(0, 93, 142, 0.6)"}}),(0,t.jsx)("span",{className:"livechat-loading-dot size-2 rounded-full",style:{backgroundColor:"rgba(0, 93, 142, 0.2)"}})]})})}};
2
2
  //# sourceMappingURL=ThinkingBlock.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/components/LiveChatWidget/components/MessageContent/ThinkingBlock.tsx"],
4
- "sourcesContent": ["/**\n * \u601D\u8003\u72B6\u6001\u6D88\u606F\u6E32\u67D3\u5668\n * \u663E\u793A AI \u52A9\u624B\u6B63\u5728\u601D\u8003\u7684\u52A8\u753B\n * \u57FA\u4E8E specs/livechat-widget/plan.md \u7684\u601D\u8003\u72B6\u6001\u8BBE\u8BA1\n */\n\nimport React from 'react'\nimport type { MessageRenderer, ThinkingContent } from '../../types'\n\n/**\n * \u601D\u8003\u72B6\u6001\u6E32\u67D3\u5668\n *\n * \u529F\u80FD\uFF1A\n * - \u663E\u793A\"\u6B63\u5728\u601D\u8003...\"\u52A8\u753B\n * - \u4E09\u4E2A\u8DF3\u52A8\u7684\u5706\u70B9\n * - \u9EC4\u8272\u80CC\u666F\u63D0\u793A\n *\n * \u52A8\u753B\u6548\u679C\uFF1A\n * - \u4F7F\u7528 CSS \u52A8\u753B\uFF08livechat.css \u4E2D\u5B9A\u4E49\uFF09\n * - \u4E09\u4E2A\u5706\u70B9\u4F9D\u6B21\u8DF3\u52A8\n * - \u5FAA\u73AF\u64AD\u653E\n *\n * @example\n * ```tsx\n * const content: ThinkingContent = {\n * type: 'thinking',\n * data: {\n * status: '\u6B63\u5728\u67E5\u8BE2\u5546\u54C1\u4FE1\u606F...'\n * }\n * }\n * <ThinkingBlock.render(content, false, false) />\n * ```\n */\nexport const ThinkingBlock: MessageRenderer = {\n render: (content, isUser, isSystem) => {\n const thinkingContent = content as ThinkingContent\n const status = thinkingContent.data.status || ''\n\n return (\n <div className=\"flex items-center gap-2 py-1\">\n {/* \u601D\u8003\u52A8\u753B - \u4E09\u4E2A\u8DF3\u52A8\u7684\u70B9 */}\n <div className=\"livechat-thinking-dots flex gap-1\">\n <span className=\"size-2 rounded-full\" style={{ backgroundColor: 'rgba(0, 93, 142, 1)' }} />\n <span className=\"size-2 rounded-full\" style={{ backgroundColor: 'rgba(0, 93, 142, 0.6)' }} />\n <span className=\"size-2 rounded-full\" style={{ backgroundColor: 'rgba(0, 93, 142, 0.2)' }} />\n </div>\n\n {/* \u72B6\u6001\u6587\u672C\uFF08\u53EF\u9009\uFF09 */}\n {/* {status && <span className=\"text-sm text-gray-500\">{status}</span>} */}\n </div>\n )\n },\n}\n"],
5
- "mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,mBAAAE,IAAA,eAAAC,EAAAH,GAyCQ,IAAAI,EAAA,6BARD,MAAMF,EAAiC,CAC5C,OAAQ,CAACG,EAASC,EAAQC,IAAa,CAErC,MAAMC,EADkBH,EACO,KAAK,QAAU,GAE9C,SACE,OAAC,OAAI,UAAU,+BAEb,oBAAC,OAAI,UAAU,oCACb,oBAAC,QAAK,UAAU,sBAAsB,MAAO,CAAE,gBAAiB,qBAAsB,EAAG,KACzF,OAAC,QAAK,UAAU,sBAAsB,MAAO,CAAE,gBAAiB,uBAAwB,EAAG,KAC3F,OAAC,QAAK,UAAU,sBAAsB,MAAO,CAAE,gBAAiB,uBAAwB,EAAG,GAC7F,EAIF,CAEJ,CACF",
4
+ "sourcesContent": ["/**\n * \u601D\u8003\u72B6\u6001\u6D88\u606F\u6E32\u67D3\u5668\n * \u663E\u793A AI \u52A9\u624B\u6B63\u5728\u601D\u8003\u7684\u52A8\u753B\n * \u57FA\u4E8E specs/livechat-widget/plan.md \u7684\u601D\u8003\u72B6\u6001\u8BBE\u8BA1\n */\n\nimport React from 'react'\nimport type { MessageRenderer, ThinkingContent } from '../../types'\n\n/**\n * \u601D\u8003\u72B6\u6001\u6E32\u67D3\u5668\n *\n * \u529F\u80FD\uFF1A\n * - \u663E\u793A\"\u6B63\u5728\u601D\u8003...\"\u52A8\u753B\n * - \u4E09\u4E2A\u8DF3\u52A8\u7684\u5706\u70B9\n * - \u9EC4\u8272\u80CC\u666F\u63D0\u793A\n *\n * \u52A8\u753B\u6548\u679C\uFF1A\n * - \u4F7F\u7528 CSS \u52A8\u753B\uFF08livechat.css \u4E2D\u5B9A\u4E49\uFF09\n * - \u4E09\u4E2A\u5706\u70B9\u4F9D\u6B21\u8DF3\u52A8\n * - \u5FAA\u73AF\u64AD\u653E\n *\n * @example\n * ```tsx\n * const content: ThinkingContent = {\n * type: 'thinking',\n * data: {\n * status: '\u6B63\u5728\u67E5\u8BE2\u5546\u54C1\u4FE1\u606F...'\n * }\n * }\n * <ThinkingBlock.render(content, false, false) />\n * ```\n */\nexport const ThinkingBlock: MessageRenderer = {\n render: (content, isUser, isSystem) => {\n const thinkingContent = content as ThinkingContent\n const status = thinkingContent.data.status || ''\n\n return (\n <div className=\"flex items-center gap-2 py-1\">\n {/* \u601D\u8003\u52A8\u753B - \u4E09\u4E2A\u8DF3\u52A8\u7684\u70B9 */}\n <div className=\"livechat-thinking-dots flex gap-1\">\n <span className=\"livechat-loading-dot size-2 rounded-full\" style={{ backgroundColor: 'rgba(0, 93, 142, 1)' }} />\n <span className=\"livechat-loading-dot size-2 rounded-full\" style={{ backgroundColor: 'rgba(0, 93, 142, 0.6)' }} />\n <span className=\"livechat-loading-dot size-2 rounded-full\" style={{ backgroundColor: 'rgba(0, 93, 142, 0.2)' }} />\n </div>\n\n {/* \u72B6\u6001\u6587\u672C\uFF08\u53EF\u9009\uFF09 */}\n {/* {status && <span className=\"text-sm text-gray-500\">{status}</span>} */}\n </div>\n )\n },\n}\n"],
5
+ "mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,mBAAAE,IAAA,eAAAC,EAAAH,GAyCQ,IAAAI,EAAA,6BARD,MAAMF,EAAiC,CAC5C,OAAQ,CAACG,EAASC,EAAQC,IAAa,CAErC,MAAMC,EADkBH,EACO,KAAK,QAAU,GAE9C,SACE,OAAC,OAAI,UAAU,+BAEb,oBAAC,OAAI,UAAU,oCACb,oBAAC,QAAK,UAAU,2CAA2C,MAAO,CAAE,gBAAiB,qBAAsB,EAAG,KAC9G,OAAC,QAAK,UAAU,2CAA2C,MAAO,CAAE,gBAAiB,uBAAwB,EAAG,KAChH,OAAC,QAAK,UAAU,2CAA2C,MAAO,CAAE,gBAAiB,uBAAwB,EAAG,GAClH,EAIF,CAEJ,CACF",
6
6
  "names": ["ThinkingBlock_exports", "__export", "ThinkingBlock", "__toCommonJS", "import_jsx_runtime", "content", "isUser", "isSystem", "status"]
7
7
  }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * CartCard Storybook Stories
3
+ * 展示购物车卡片组件的各种状态
4
+ */
5
+ import type { Meta, StoryObj } from '@storybook/react';
6
+ import React from 'react';
7
+ import type { CartContent } from '../components/LiveChatWidget/types';
8
+ declare const CartCardWrapper: React.FC<{
9
+ content: CartContent;
10
+ }>;
11
+ declare const meta: Meta<typeof CartCardWrapper>;
12
+ export default meta;
13
+ type Story = StoryObj<typeof CartCardWrapper>;
14
+ /**
15
+ * 空购物车状态
16
+ */
17
+ export declare const Empty: Story;
18
+ /**
19
+ * 单件商品
20
+ */
21
+ export declare const SingleItem: Story;
22
+ /**
23
+ * 多件商品
24
+ */
25
+ export declare const MultipleItems: Story;
26
+ /**
27
+ * 有折扣码的购物车
28
+ */
29
+ export declare const WithDiscount: Story;
30
+ /**
31
+ * 多个折扣码(部分失效)
32
+ */
33
+ export declare const WithMultipleDiscounts: Story;
@@ -0,0 +1,21 @@
1
+ "use strict";var c=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var s=Object.prototype.hasOwnProperty;var p=(t,e)=>{for(var a in e)c(t,a,{get:e[a],enumerable:!0})},m=(t,e,a,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of d(e))!s.call(t,o)&&o!==a&&c(t,o,{get:()=>e[o],enumerable:!(n=i(e,o))||n.enumerable});return t};var y=t=>m(c({},"__esModule",{value:!0}),t);var A={};p(A,{Empty:()=>S,MultipleItems:()=>g,SingleItem:()=>f,WithDiscount:()=>U,WithMultipleDiscounts:()=>D,default:()=>C});module.exports=y(A);var r=require("react/jsx-runtime"),u=require("../components/LiveChatWidget/components/MessageContent/CartCard.js");const l=({content:t})=>(0,r.jsx)("div",{className:"flex min-h-screen items-center justify-center bg-gray-100 p-4",children:(0,r.jsx)("div",{className:"w-full max-w-md",children:u.CartCard.render(t,!1,!1)})}),h={title:"Campaign/LiveChatWidget/MessageContent/CartCard",component:l,parameters:{layout:"fullscreen",docs:{description:{component:`
2
+ # \u8D2D\u7269\u8F66\u5361\u7247\u7EC4\u4EF6
3
+
4
+ \u663E\u793A\u7528\u6237\u8D2D\u7269\u8F66\u5185\u5BB9\uFF0C\u5305\u62EC\u5546\u54C1\u5217\u8868\u3001\u4EF7\u683C\u6C47\u603B\u548C\u7ED3\u8D26\u6309\u94AE\u3002
5
+
6
+ ## \u529F\u80FD\u7279\u6027
7
+
8
+ - \u{1F4E6} **\u5546\u54C1\u5217\u8868**: \u5C55\u793A\u8D2D\u7269\u8F66\u4E2D\u7684\u6240\u6709\u5546\u54C1
9
+ - \u{1F4B0} **\u4EF7\u683C\u6C47\u603B**: \u663E\u793A\u5C0F\u8BA1\u3001\u6298\u6263\u548C\u603B\u8BA1
10
+ - \u{1F39F}\uFE0F **\u6298\u6263\u7801**: \u663E\u793A\u5DF2\u5E94\u7528\u7684\u6298\u6263\u7801\u53CA\u5176\u72B6\u6001
11
+ - \u{1F6D2} **\u7ED3\u8D26\u6309\u94AE**: \u4E00\u952E\u8DF3\u8F6C\u5230 Shopify \u7ED3\u8D26\u9875\u9762
12
+ - \u{1F233} **\u7A7A\u72B6\u6001**: \u4F18\u96C5\u7684\u7A7A\u8D2D\u7269\u8F66\u63D0\u793A
13
+
14
+ ## \u4F7F\u7528\u573A\u666F
15
+
16
+ - \u7528\u6237\u6DFB\u52A0\u5546\u54C1\u5230\u8D2D\u7269\u8F66\u540E (add_to_cart)
17
+ - \u7528\u6237\u67E5\u8BE2\u8D2D\u7269\u8F66\u5185\u5BB9 (get_cart)
18
+ - \u7528\u6237\u4FEE\u6539\u8D2D\u7269\u8F66\u6570\u91CF (update_cart_item)
19
+ - \u7528\u6237\u5E94\u7528\u6298\u6263\u7801 (update_discount_codes)
20
+ `}}},tags:["autodocs"]};var C=h;const S={args:{content:{type:"cart",data:{isEmpty:!0,cartId:"gid://shopify/Cart/empty",totalQuantity:0,lines:[],cost:{totalAmount:{amount:"0.00",currencyCode:"USD"},subtotalAmount:{amount:"0.00",currencyCode:"USD"}}}}}},f={args:{content:{type:"cart",data:{isEmpty:!1,cartId:"gid://shopify/Cart/Z2NwLXVzLWVhc3QxOjAxSkZHRjA4VkFRQkhON1dBMTNLREZEVEZH",totalQuantity:1,lines:[{id:"gid://shopify/CartLine/12345",quantity:1,cost:{totalAmount:{amount:"99.99",currencyCode:"USD"},amountPerQuantity:{amount:"99.99",currencyCode:"USD"},subtotalAmount:{amount:"99.99",currencyCode:"USD"}},merchandise:{id:"gid://shopify/ProductVariant/43234567890",title:"Black",price:{amount:"99.99",currencyCode:"USD"},image:{url:"https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=400&h=400&fit=crop",altText:"Soundcore Space One"},product:{id:"gid://shopify/Product/8179159826618",title:"Soundcore Space One",handle:"soundcore-space-one"}}}],cost:{totalAmount:{amount:"99.99",currencyCode:"USD"},subtotalAmount:{amount:"99.99",currencyCode:"USD"}},checkoutUrl:"https://checkout.shopify.com/example"}}}},g={args:{content:{type:"cart",data:{isEmpty:!1,cartId:"gid://shopify/Cart/Z2NwLXVzLWVhc3QxOjAxSkZHRjA4VkFRQkhON1dBMTNLREZEVEZH",totalQuantity:5,lines:[{id:"gid://shopify/CartLine/12345",quantity:2,cost:{totalAmount:{amount:"199.98",currencyCode:"USD"},amountPerQuantity:{amount:"99.99",currencyCode:"USD"},subtotalAmount:{amount:"199.98",currencyCode:"USD"}},merchandise:{id:"gid://shopify/ProductVariant/43234567890",title:"Black",price:{amount:"99.99",currencyCode:"USD"},image:{url:"https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=400&h=400&fit=crop",altText:"Soundcore Space One"},product:{id:"gid://shopify/Product/8179159826618",title:"Soundcore Space One",handle:"soundcore-space-one"}}},{id:"gid://shopify/CartLine/12346",quantity:1,cost:{totalAmount:{amount:"129.99",currencyCode:"USD"},amountPerQuantity:{amount:"129.99",currencyCode:"USD"},subtotalAmount:{amount:"129.99",currencyCode:"USD"}},merchandise:{id:"gid://shopify/ProductVariant/43234567891",title:"White",price:{amount:"129.99",currencyCode:"USD"},image:{url:"https://images.unsplash.com/photo-1484704849700-f032a568e944?w=400&h=400&fit=crop",altText:"eufy Security Camera"},product:{id:"gid://shopify/Product/8179159826619",title:"eufy Security Camera",handle:"eufy-security-camera"}}},{id:"gid://shopify/CartLine/12347",quantity:2,cost:{totalAmount:{amount:"79.98",currencyCode:"USD"},amountPerQuantity:{amount:"39.99",currencyCode:"USD"},subtotalAmount:{amount:"79.98",currencyCode:"USD"}},merchandise:{id:"gid://shopify/ProductVariant/43234567892",title:"USB-C Cable",price:{amount:"39.99",currencyCode:"USD"},image:{url:"https://images.unsplash.com/photo-1583863788434-e58a36330cf0?w=400&h=400&fit=crop",altText:"Anker USB-C Cable"},product:{id:"gid://shopify/Product/8179159826620",title:"Anker USB-C Cable 6ft",handle:"anker-usb-c-cable"}}}],cost:{totalAmount:{amount:"409.95",currencyCode:"USD"},subtotalAmount:{amount:"409.95",currencyCode:"USD"}},checkoutUrl:"https://checkout.shopify.com/example"}}}},U={args:{content:{type:"cart",data:{isEmpty:!1,cartId:"gid://shopify/Cart/Z2NwLXVzLWVhc3QxOjAxSkZHRjA4VkFRQkhON1dBMTNLREZEVEZH",totalQuantity:3,lines:[{id:"gid://shopify/CartLine/12345",quantity:2,cost:{totalAmount:{amount:"199.98",currencyCode:"USD"},amountPerQuantity:{amount:"99.99",currencyCode:"USD"},subtotalAmount:{amount:"199.98",currencyCode:"USD"}},merchandise:{id:"gid://shopify/ProductVariant/43234567890",title:"Black",price:{amount:"99.99",currencyCode:"USD"},image:{url:"https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=400&h=400&fit=crop",altText:"Soundcore Space One"},product:{id:"gid://shopify/Product/8179159826618",title:"Soundcore Space One",handle:"soundcore-space-one"}}},{id:"gid://shopify/CartLine/12346",quantity:1,cost:{totalAmount:{amount:"129.99",currencyCode:"USD"},amountPerQuantity:{amount:"129.99",currencyCode:"USD"},subtotalAmount:{amount:"129.99",currencyCode:"USD"}},merchandise:{id:"gid://shopify/ProductVariant/43234567891",title:"White",price:{amount:"129.99",currencyCode:"USD"},image:{url:"https://images.unsplash.com/photo-1484704849700-f032a568e944?w=400&h=400&fit=crop",altText:"eufy Security Camera"},product:{id:"gid://shopify/Product/8179159826619",title:"eufy Security Camera",handle:"eufy-security-camera"}}}],cost:{totalAmount:{amount:"296.97",currencyCode:"USD"},subtotalAmount:{amount:"329.97",currencyCode:"USD"}},discountCodes:[{code:"SPRING20",applicable:!0}],checkoutUrl:"https://checkout.shopify.com/example"}}}},D={args:{content:{type:"cart",data:{isEmpty:!1,cartId:"gid://shopify/Cart/Z2NwLXVzLWVhc3QxOjAxSkZHRjA4VkFRQkhON1dBMTNLREZEVEZH",totalQuantity:2,lines:[{id:"gid://shopify/CartLine/12345",quantity:2,cost:{totalAmount:{amount:"199.98",currencyCode:"USD"},amountPerQuantity:{amount:"99.99",currencyCode:"USD"},subtotalAmount:{amount:"199.98",currencyCode:"USD"}},merchandise:{id:"gid://shopify/ProductVariant/43234567890",title:"Black",price:{amount:"99.99",currencyCode:"USD"},image:{url:"https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=400&h=400&fit=crop",altText:"Soundcore Space One"},product:{id:"gid://shopify/Product/8179159826618",title:"Soundcore Space One",handle:"soundcore-space-one"}}}],cost:{totalAmount:{amount:"179.98",currencyCode:"USD"},subtotalAmount:{amount:"199.98",currencyCode:"USD"}},discountCodes:[{code:"WELCOME10",applicable:!0},{code:"EXPIRED20",applicable:!1}],checkoutUrl:"https://checkout.shopify.com/example"}}}};
21
+ //# sourceMappingURL=CartCard.stories.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/stories/CartCard.stories.tsx"],
4
+ "sourcesContent": ["/**\n * CartCard Storybook Stories\n * \u5C55\u793A\u8D2D\u7269\u8F66\u5361\u7247\u7EC4\u4EF6\u7684\u5404\u79CD\u72B6\u6001\n */\n\nimport type { Meta, StoryObj } from '@storybook/react'\nimport React from 'react'\nimport { CartCard } from '../components/LiveChatWidget/components/MessageContent/CartCard.js'\nimport type { CartContent } from '../components/LiveChatWidget/types'\n\n// Story \u5305\u88C5\u7EC4\u4EF6\nconst CartCardWrapper: React.FC<{ content: CartContent }> = ({ content }) => {\n return (\n <div className=\"flex min-h-screen items-center justify-center bg-gray-100 p-4\">\n <div className=\"w-full max-w-md\">{CartCard.render(content, false, false)}</div>\n </div>\n )\n}\n\nconst meta: Meta<typeof CartCardWrapper> = {\n title: 'Campaign/LiveChatWidget/MessageContent/CartCard',\n component: CartCardWrapper,\n parameters: {\n layout: 'fullscreen',\n docs: {\n description: {\n component: `\n# \u8D2D\u7269\u8F66\u5361\u7247\u7EC4\u4EF6\n\n\u663E\u793A\u7528\u6237\u8D2D\u7269\u8F66\u5185\u5BB9\uFF0C\u5305\u62EC\u5546\u54C1\u5217\u8868\u3001\u4EF7\u683C\u6C47\u603B\u548C\u7ED3\u8D26\u6309\u94AE\u3002\n\n## \u529F\u80FD\u7279\u6027\n\n- \uD83D\uDCE6 **\u5546\u54C1\u5217\u8868**: \u5C55\u793A\u8D2D\u7269\u8F66\u4E2D\u7684\u6240\u6709\u5546\u54C1\n- \uD83D\uDCB0 **\u4EF7\u683C\u6C47\u603B**: \u663E\u793A\u5C0F\u8BA1\u3001\u6298\u6263\u548C\u603B\u8BA1\n- \uD83C\uDF9F\uFE0F **\u6298\u6263\u7801**: \u663E\u793A\u5DF2\u5E94\u7528\u7684\u6298\u6263\u7801\u53CA\u5176\u72B6\u6001\n- \uD83D\uDED2 **\u7ED3\u8D26\u6309\u94AE**: \u4E00\u952E\u8DF3\u8F6C\u5230 Shopify \u7ED3\u8D26\u9875\u9762\n- \uD83C\uDE33 **\u7A7A\u72B6\u6001**: \u4F18\u96C5\u7684\u7A7A\u8D2D\u7269\u8F66\u63D0\u793A\n\n## \u4F7F\u7528\u573A\u666F\n\n- \u7528\u6237\u6DFB\u52A0\u5546\u54C1\u5230\u8D2D\u7269\u8F66\u540E (add_to_cart)\n- \u7528\u6237\u67E5\u8BE2\u8D2D\u7269\u8F66\u5185\u5BB9 (get_cart)\n- \u7528\u6237\u4FEE\u6539\u8D2D\u7269\u8F66\u6570\u91CF (update_cart_item)\n- \u7528\u6237\u5E94\u7528\u6298\u6263\u7801 (update_discount_codes)\n `,\n },\n },\n },\n tags: ['autodocs'],\n}\n\nexport default meta\n\ntype Story = StoryObj<typeof CartCardWrapper>\n\n/**\n * \u7A7A\u8D2D\u7269\u8F66\u72B6\u6001\n */\nexport const Empty: Story = {\n args: {\n content: {\n type: 'cart',\n data: {\n isEmpty: true,\n cartId: 'gid://shopify/Cart/empty',\n totalQuantity: 0,\n lines: [],\n cost: {\n totalAmount: {\n amount: '0.00',\n currencyCode: 'USD',\n },\n subtotalAmount: {\n amount: '0.00',\n currencyCode: 'USD',\n },\n },\n },\n },\n },\n}\n\n/**\n * \u5355\u4EF6\u5546\u54C1\n */\nexport const SingleItem: Story = {\n args: {\n content: {\n type: 'cart',\n data: {\n isEmpty: false,\n cartId: 'gid://shopify/Cart/Z2NwLXVzLWVhc3QxOjAxSkZHRjA4VkFRQkhON1dBMTNLREZEVEZH',\n totalQuantity: 1,\n lines: [\n {\n id: 'gid://shopify/CartLine/12345',\n quantity: 1,\n cost: {\n totalAmount: {\n amount: '99.99',\n currencyCode: 'USD',\n },\n amountPerQuantity: {\n amount: '99.99',\n currencyCode: 'USD',\n },\n subtotalAmount: {\n amount: '99.99',\n currencyCode: 'USD',\n },\n },\n merchandise: {\n id: 'gid://shopify/ProductVariant/43234567890',\n title: 'Black',\n price: {\n amount: '99.99',\n currencyCode: 'USD',\n },\n image: {\n url: 'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=400&h=400&fit=crop',\n altText: 'Soundcore Space One',\n },\n product: {\n id: 'gid://shopify/Product/8179159826618',\n title: 'Soundcore Space One',\n handle: 'soundcore-space-one',\n },\n },\n },\n ],\n cost: {\n totalAmount: {\n amount: '99.99',\n currencyCode: 'USD',\n },\n subtotalAmount: {\n amount: '99.99',\n currencyCode: 'USD',\n },\n },\n checkoutUrl: 'https://checkout.shopify.com/example',\n },\n },\n },\n}\n\n/**\n * \u591A\u4EF6\u5546\u54C1\n */\nexport const MultipleItems: Story = {\n args: {\n content: {\n type: 'cart',\n data: {\n isEmpty: false,\n cartId: 'gid://shopify/Cart/Z2NwLXVzLWVhc3QxOjAxSkZHRjA4VkFRQkhON1dBMTNLREZEVEZH',\n totalQuantity: 5,\n lines: [\n {\n id: 'gid://shopify/CartLine/12345',\n quantity: 2,\n cost: {\n totalAmount: {\n amount: '199.98',\n currencyCode: 'USD',\n },\n amountPerQuantity: {\n amount: '99.99',\n currencyCode: 'USD',\n },\n subtotalAmount: {\n amount: '199.98',\n currencyCode: 'USD',\n },\n },\n merchandise: {\n id: 'gid://shopify/ProductVariant/43234567890',\n title: 'Black',\n price: {\n amount: '99.99',\n currencyCode: 'USD',\n },\n image: {\n url: 'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=400&h=400&fit=crop',\n altText: 'Soundcore Space One',\n },\n product: {\n id: 'gid://shopify/Product/8179159826618',\n title: 'Soundcore Space One',\n handle: 'soundcore-space-one',\n },\n },\n },\n {\n id: 'gid://shopify/CartLine/12346',\n quantity: 1,\n cost: {\n totalAmount: {\n amount: '129.99',\n currencyCode: 'USD',\n },\n amountPerQuantity: {\n amount: '129.99',\n currencyCode: 'USD',\n },\n subtotalAmount: {\n amount: '129.99',\n currencyCode: 'USD',\n },\n },\n merchandise: {\n id: 'gid://shopify/ProductVariant/43234567891',\n title: 'White',\n price: {\n amount: '129.99',\n currencyCode: 'USD',\n },\n image: {\n url: 'https://images.unsplash.com/photo-1484704849700-f032a568e944?w=400&h=400&fit=crop',\n altText: 'eufy Security Camera',\n },\n product: {\n id: 'gid://shopify/Product/8179159826619',\n title: 'eufy Security Camera',\n handle: 'eufy-security-camera',\n },\n },\n },\n {\n id: 'gid://shopify/CartLine/12347',\n quantity: 2,\n cost: {\n totalAmount: {\n amount: '79.98',\n currencyCode: 'USD',\n },\n amountPerQuantity: {\n amount: '39.99',\n currencyCode: 'USD',\n },\n subtotalAmount: {\n amount: '79.98',\n currencyCode: 'USD',\n },\n },\n merchandise: {\n id: 'gid://shopify/ProductVariant/43234567892',\n title: 'USB-C Cable',\n price: {\n amount: '39.99',\n currencyCode: 'USD',\n },\n image: {\n url: 'https://images.unsplash.com/photo-1583863788434-e58a36330cf0?w=400&h=400&fit=crop',\n altText: 'Anker USB-C Cable',\n },\n product: {\n id: 'gid://shopify/Product/8179159826620',\n title: 'Anker USB-C Cable 6ft',\n handle: 'anker-usb-c-cable',\n },\n },\n },\n ],\n cost: {\n totalAmount: {\n amount: '409.95',\n currencyCode: 'USD',\n },\n subtotalAmount: {\n amount: '409.95',\n currencyCode: 'USD',\n },\n },\n checkoutUrl: 'https://checkout.shopify.com/example',\n },\n },\n },\n}\n\n/**\n * \u6709\u6298\u6263\u7801\u7684\u8D2D\u7269\u8F66\n */\nexport const WithDiscount: Story = {\n args: {\n content: {\n type: 'cart',\n data: {\n isEmpty: false,\n cartId: 'gid://shopify/Cart/Z2NwLXVzLWVhc3QxOjAxSkZHRjA4VkFRQkhON1dBMTNLREZEVEZH',\n totalQuantity: 3,\n lines: [\n {\n id: 'gid://shopify/CartLine/12345',\n quantity: 2,\n cost: {\n totalAmount: {\n amount: '199.98',\n currencyCode: 'USD',\n },\n amountPerQuantity: {\n amount: '99.99',\n currencyCode: 'USD',\n },\n subtotalAmount: {\n amount: '199.98',\n currencyCode: 'USD',\n },\n },\n merchandise: {\n id: 'gid://shopify/ProductVariant/43234567890',\n title: 'Black',\n price: {\n amount: '99.99',\n currencyCode: 'USD',\n },\n image: {\n url: 'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=400&h=400&fit=crop',\n altText: 'Soundcore Space One',\n },\n product: {\n id: 'gid://shopify/Product/8179159826618',\n title: 'Soundcore Space One',\n handle: 'soundcore-space-one',\n },\n },\n },\n {\n id: 'gid://shopify/CartLine/12346',\n quantity: 1,\n cost: {\n totalAmount: {\n amount: '129.99',\n currencyCode: 'USD',\n },\n amountPerQuantity: {\n amount: '129.99',\n currencyCode: 'USD',\n },\n subtotalAmount: {\n amount: '129.99',\n currencyCode: 'USD',\n },\n },\n merchandise: {\n id: 'gid://shopify/ProductVariant/43234567891',\n title: 'White',\n price: {\n amount: '129.99',\n currencyCode: 'USD',\n },\n image: {\n url: 'https://images.unsplash.com/photo-1484704849700-f032a568e944?w=400&h=400&fit=crop',\n altText: 'eufy Security Camera',\n },\n product: {\n id: 'gid://shopify/Product/8179159826619',\n title: 'eufy Security Camera',\n handle: 'eufy-security-camera',\n },\n },\n },\n ],\n cost: {\n totalAmount: {\n amount: '296.97',\n currencyCode: 'USD',\n },\n subtotalAmount: {\n amount: '329.97',\n currencyCode: 'USD',\n },\n },\n discountCodes: [\n {\n code: 'SPRING20',\n applicable: true,\n },\n ],\n checkoutUrl: 'https://checkout.shopify.com/example',\n },\n },\n },\n}\n\n/**\n * \u591A\u4E2A\u6298\u6263\u7801\uFF08\u90E8\u5206\u5931\u6548\uFF09\n */\nexport const WithMultipleDiscounts: Story = {\n args: {\n content: {\n type: 'cart',\n data: {\n isEmpty: false,\n cartId: 'gid://shopify/Cart/Z2NwLXVzLWVhc3QxOjAxSkZHRjA4VkFRQkhON1dBMTNLREZEVEZH',\n totalQuantity: 2,\n lines: [\n {\n id: 'gid://shopify/CartLine/12345',\n quantity: 2,\n cost: {\n totalAmount: {\n amount: '199.98',\n currencyCode: 'USD',\n },\n amountPerQuantity: {\n amount: '99.99',\n currencyCode: 'USD',\n },\n subtotalAmount: {\n amount: '199.98',\n currencyCode: 'USD',\n },\n },\n merchandise: {\n id: 'gid://shopify/ProductVariant/43234567890',\n title: 'Black',\n price: {\n amount: '99.99',\n currencyCode: 'USD',\n },\n image: {\n url: 'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=400&h=400&fit=crop',\n altText: 'Soundcore Space One',\n },\n product: {\n id: 'gid://shopify/Product/8179159826618',\n title: 'Soundcore Space One',\n handle: 'soundcore-space-one',\n },\n },\n },\n ],\n cost: {\n totalAmount: {\n amount: '179.98',\n currencyCode: 'USD',\n },\n subtotalAmount: {\n amount: '199.98',\n currencyCode: 'USD',\n },\n },\n discountCodes: [\n {\n code: 'WELCOME10',\n applicable: true,\n },\n {\n code: 'EXPIRED20',\n applicable: false,\n },\n ],\n checkoutUrl: 'https://checkout.shopify.com/example',\n },\n },\n },\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["CartCard_stories_exports", "__export", "Empty", "MultipleItems", "SingleItem", "WithDiscount", "WithMultipleDiscounts", "CartCard_stories_default", "__toCommonJS", "import_jsx_runtime", "import_CartCard", "CartCardWrapper", "content", "meta"]
7
+ }
@@ -1,4 +1,4 @@
1
- "use strict";var n=Object.defineProperty;var c=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var g=(t,e)=>{for(var a in e)n(t,a,{get:e[a],enumerable:!0})},m=(t,e,a,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of d(e))!p.call(t,r)&&r!==a&&n(t,r,{get:()=>e[r],enumerable:!(i=c(e,r))||i.enumerable});return t};var u=t=>m(n({},"__esModule",{value:!0}),t);var f={};g(f,{Default:()=>y,default:()=>h});module.exports=u(f);var o=require("react/jsx-runtime"),s=require("../components/LiveChatWidget"),b=require("../styles/livechat.css");const v={title:"Campaign/LiveChatWidget",component:s.LiveChatWidget,parameters:{layout:"fullscreen",docs:{story:{inline:!1,iframeHeight:500},description:{component:`
1
+ "use strict";var n=Object.defineProperty;var c=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var g=(t,e)=>{for(var a in e)n(t,a,{get:e[a],enumerable:!0})},m=(t,e,a,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of d(e))!p.call(t,r)&&r!==a&&n(t,r,{get:()=>e[r],enumerable:!(i=c(e,r))||i.enumerable});return t};var u=t=>m(n({},"__esModule",{value:!0}),t);var f={};g(f,{Default:()=>h,default:()=>y});module.exports=u(f);var o=require("react/jsx-runtime"),s=require("../components/LiveChatWidget"),C=require("../styles/livechat.css");const v={title:"Campaign/LiveChatWidget",component:s.LiveChatWidget,parameters:{layout:"fullscreen",docs:{story:{inline:!1,iframeHeight:500},description:{component:`
2
2
  # LiveChat \u804A\u5929\u7EC4\u4EF6
3
3
 
4
4
  \u53EF\u590D\u7528\u7684\u6C14\u6CE1\u5F39\u7A97\u804A\u5929\u7EC4\u4EF6\uFF0C\u652F\u6301 SSE \u6D41\u5F0F\u6D88\u606F\u3001\u81EA\u5B9A\u4E49\u6E32\u67D3\u5668\u548C\u591A\u79CD\u6D88\u606F\u7C7B\u578B\u3002
@@ -48,5 +48,5 @@ const customRenderers = {
48
48
  customRenderers={customRenderers}
49
49
  />
50
50
  \`\`\`
51
- `}}},tags:["autodocs"],argTypes:{apiBaseUrl:{control:"text",description:"API \u57FA\u7840 URL"},headers:{control:"object",description:"\u81EA\u5B9A\u4E49\u8BF7\u6C42\u5934\uFF0C\u5C06\u5728\u6240\u6709 API \u8BF7\u6C42\u4E2D\u6DFB\u52A0",table:{defaultValue:{summary:"undefined"}}},recaptchaSitekey:{control:"text",description:"Google reCAPTCHA v3 site key\uFF0C\u63D0\u4F9B\u6B64\u53C2\u6570\u5C06\u81EA\u52A8\u542F\u7528 reCAPTCHA v3 \u9A8C\u8BC1",table:{defaultValue:{summary:"undefined"}}},recaptchaAction:{control:"text",description:"reCAPTCHA action \u540D\u79F0\uFF0C\u7528\u4E8E\u533A\u5206\u4E0D\u540C\u7684\u9A8C\u8BC1\u573A\u666F",table:{defaultValue:{summary:'"activity"'}}},site:{control:"text",description:"Shopify \u5E97\u94FA URL"},channelCode:{control:"text",description:"\u6E20\u9053\u7F16\u7801\uFF0C\u7528\u4E8E\u6807\u8BC6\u6765\u6E90\u6E20\u9053",table:{defaultValue:{summary:"undefined"}}},welcomeMessage:{control:"text",description:"\u6B22\u8FCE\u6D88\u606F",table:{defaultValue:{summary:"\u4F60\u597D\uFF01\u6211\u662F AI \u52A9\u624B\uFF0C\u6709\u4EC0\u4E48\u53EF\u4EE5\u5E2E\u52A9\u4F60\u7684\u5417\uFF1F"}}},logoUrl:{control:"text",description:"Logo URL"},position:{control:"object",description:"\u6C14\u6CE1\u6309\u94AE\u4F4D\u7F6E\u5BF9\u8C61",table:{defaultValue:{summary:'{ bottom: "1.5rem", right: "1.5rem" }'}}}},args:{apiBaseUrl:"http://172.16.38.183:3003",site:"www.eufy.com",loginUserId:"test_test",welcomeMessage:"\u4F60\u597D\uFF01\u6211\u662F AI \u52A9\u624B\uFF0C\u6709\u4EC0\u4E48\u53EF\u4EE5\u5E2E\u52A9\u4F60\u7684\u5417\uFF1F"}};var h=v;const y={args:{loginUserId:"test_test1",apiBaseUrl:"https://beta-api-v2-livechat.anker.com",site:"beta.eufy.com",channelCode:"dtc",title:"eufy AI Assistant",cartId:"gid://shopify/Cart/hWN7wB3Pa12gh78d8hPOAUBI?key=0e73db1d3fb5ac21da19099c45033253",accessToken:"47b1aa2c0797043f9baba39388029d70",position:{bottom:"24px",right:"30px"},welcomeMessage:"",quickReplies:[{id:"1",label:"Product Info",value:"Tell me about your products",icon:"\u{1F4E6}"},{id:"2",label:"Track Order",value:"I want to track my order",icon:"\u{1F69A}"},{id:"3",label:"Support",value:"I need help with my device",icon:"\u{1F527}"},{id:"4",label:"Recommendations",value:"Recommend products for me",icon:"\u2B50"}],complianceConfig:{title:"Hi! I'm your eufy AI assistant.",content:"AI-generated responses can be inaccurate. Please verify important info. Do not input sensitive personal data.",checkboxText:`By starting to use "Live Chat", you agree to Anker's <a href="https://www.anker.com/pages/privacy-policy" target="_blank" rel="noopener noreferrer" style="text-decoration: underline;">LIVE CHAT PRIVACY NOTICE</a>.`,agreeButtonText:"Agree"},recaptchaAction:"livechat",showNewSessionButton:!0,commonText:{learnMore:"Learn More",total:"Total"},customRenderers:{video:{render:t=>{const e=t;return(0,o.jsxs)("div",{className:"w-full",children:[(0,o.jsx)("video",{src:e.url,controls:!0,className:"w-full rounded-lg",poster:e.poster,children:"Your browser does not support video playback"}),e.title&&(0,o.jsx)("p",{className:"mt-2 text-sm text-gray-600",children:e.title})]})}},image_gallery:{render:t=>{const a=t.images||[];return(0,o.jsx)("div",{className:"grid grid-cols-2 gap-2",children:a.map((i,r)=>(0,o.jsx)("div",{className:"relative aspect-square",children:(0,o.jsx)("img",{src:i.url,alt:i.alt||`Image ${r+1}`,className:"size-full rounded-lg object-cover"})},r))})}}},productCardRender:(t,e)=>{if(!t)return(0,o.jsx)("div",{style:{padding:"16px",border:"1px dashed #ccc",borderRadius:"8px",textAlign:"center"},children:(0,o.jsxs)("p",{children:["Product loading... (handle: ",e,")"]})});const a=t?.featured_image||"",i=t?.title||"",r=t?.description||"",l=t?.average_rating;return(0,o.jsx)("div",{style:{border:"2px solid #4CAF50",borderRadius:"16px",padding:"16px",margin:"12px 0",backgroundColor:"#f0f9ff",boxShadow:"0 4px 12px rgba(76, 175, 80, 0.15)"},children:(0,o.jsxs)("div",{style:{display:"flex",gap:"12px",alignItems:"center"},children:[a&&(0,o.jsx)("img",{src:a,alt:i,style:{width:"60px",height:"60px",borderRadius:"8px",objectFit:"cover"}}),(0,o.jsxs)("div",{style:{flex:1},children:[(0,o.jsx)("h4",{style:{margin:"0 0 4px 0",fontSize:"16px",fontWeight:"bold"},children:i}),r&&(0,o.jsxs)("p",{style:{margin:0,fontSize:"12px",color:"#666",lineHeight:1.4},children:[r.slice(0,80),"..."]}),l&&(0,o.jsxs)("span",{style:{fontSize:"12px",color:"#FFB800"},children:["Rating: ",l.toFixed(1)]})]}),(0,o.jsx)("button",{style:{padding:"8px 16px",backgroundColor:"#4CAF50",color:"white",borderRadius:"8px",border:"none",cursor:"pointer"},onClick:()=>console.log("View product:",e,t),children:"View"})]})})}},render:t=>(0,o.jsx)(s.LiveChatWidget,{...t,onOpen:()=>console.log("[LiveChat] Chat opened"),onClose:()=>console.log("[LiveChat] Chat closed"),onMessageSend:e=>console.log("[LiveChat] Message sent:",e),onError:e=>console.error("[LiveChat] Error:",e),onTextMessage:()=>console.log("[LiveChat] AI text message received"),onProductList:()=>console.log("[LiveChat] Product list received"),onPromotionList:()=>console.log("[LiveChat] Promotion list received"),onAddToCart:e=>{console.log("[LiveChat] Add to cart:",e),alert(`Added "${e.title}" to cart!`)},onCart:(e,a)=>{console.log("[LiveChat] Cart clicked:",{cartId:e,checkoutUrl:a}),alert(`Cart ID: ${e}`)}})};
51
+ `}}},tags:["autodocs"],argTypes:{apiBaseUrl:{control:"text",description:"API \u57FA\u7840 URL"},headers:{control:"object",description:"\u81EA\u5B9A\u4E49\u8BF7\u6C42\u5934\uFF0C\u5C06\u5728\u6240\u6709 API \u8BF7\u6C42\u4E2D\u6DFB\u52A0",table:{defaultValue:{summary:"undefined"}}},recaptchaSitekey:{control:"text",description:"Google reCAPTCHA v3 site key\uFF0C\u63D0\u4F9B\u6B64\u53C2\u6570\u5C06\u81EA\u52A8\u542F\u7528 reCAPTCHA v3 \u9A8C\u8BC1",table:{defaultValue:{summary:"undefined"}}},recaptchaAction:{control:"text",description:"reCAPTCHA action \u540D\u79F0\uFF0C\u7528\u4E8E\u533A\u5206\u4E0D\u540C\u7684\u9A8C\u8BC1\u573A\u666F",table:{defaultValue:{summary:'"activity"'}}},site:{control:"text",description:"Shopify \u5E97\u94FA URL"},channelCode:{control:"text",description:"\u6E20\u9053\u7F16\u7801\uFF0C\u7528\u4E8E\u6807\u8BC6\u6765\u6E90\u6E20\u9053",table:{defaultValue:{summary:"undefined"}}},welcomeMessage:{control:"text",description:"\u6B22\u8FCE\u6D88\u606F",table:{defaultValue:{summary:"\u4F60\u597D\uFF01\u6211\u662F AI \u52A9\u624B\uFF0C\u6709\u4EC0\u4E48\u53EF\u4EE5\u5E2E\u52A9\u4F60\u7684\u5417\uFF1F"}}},logoUrl:{control:"text",description:"Logo URL"},position:{control:"object",description:"\u6C14\u6CE1\u6309\u94AE\u4F4D\u7F6E\u5BF9\u8C61",table:{defaultValue:{summary:'{ bottom: "1.5rem", right: "1.5rem" }'}}}},args:{apiBaseUrl:"http://172.16.38.183:3003",site:"www.eufy.com",loginUserId:"test_test",welcomeMessage:"\u4F60\u597D\uFF01\u6211\u662F AI \u52A9\u624B\uFF0C\u6709\u4EC0\u4E48\u53EF\u4EE5\u5E2E\u52A9\u4F60\u7684\u5417\uFF1F"}};var y=v;const h={args:{loginUserId:"test_test1",apiBaseUrl:"https://beta-api-v2-livechat.anker.com",site:"beta.soundcore.com",channelCode:"dtc",title:"eufy AI Assistant",cartId:"gid://shopify/Cart/hWNAAJweS9IkeRKib4LRy9PY?key=ff1f9b24e74b3f11f5574539e7cbbb2f",accessToken:"47b1aa2c0797043f9baba39388029d70",position:{bottom:"24px",right:"30px"},welcomeMessage:"",quickReplies:[{id:"1",label:"Product Info",value:"Tell me about your products",icon:"\u{1F4E6}"},{id:"2",label:"Track Order",value:"I want to track my order",icon:"\u{1F69A}"},{id:"3",label:"Support",value:"I need help with my device",icon:"\u{1F527}"},{id:"4",label:"Recommendations",value:"Recommend products for me",icon:"\u2B50"}],complianceConfig:{title:"Hi! I'm your eufy AI assistant.",content:"AI-generated responses can be inaccurate. Please verify important info. Do not input sensitive personal data.",checkboxText:`By starting to use "Live Chat", you agree to Anker's <a href="https://www.anker.com/pages/privacy-policy" target="_blank" rel="noopener noreferrer" style="text-decoration: underline;">LIVE CHAT PRIVACY NOTICE</a>.`,agreeButtonText:"Agree"},recaptchaAction:"livechat",showNewSessionButton:!0,commonText:{learnMore:"Learn More",total:"Total"},customRenderers:{video:{render:t=>{const e=t;return(0,o.jsxs)("div",{className:"w-full",children:[(0,o.jsx)("video",{src:e.url,controls:!0,className:"w-full rounded-lg",poster:e.poster,children:"Your browser does not support video playback"}),e.title&&(0,o.jsx)("p",{className:"mt-2 text-sm text-gray-600",children:e.title})]})}},image_gallery:{render:t=>{const a=t.images||[];return(0,o.jsx)("div",{className:"grid grid-cols-2 gap-2",children:a.map((i,r)=>(0,o.jsx)("div",{className:"relative aspect-square",children:(0,o.jsx)("img",{src:i.url,alt:i.alt||`Image ${r+1}`,className:"size-full rounded-lg object-cover"})},r))})}}},productCardRender:(t,e)=>{if(!t)return(0,o.jsx)("div",{style:{padding:"16px",border:"1px dashed #ccc",borderRadius:"8px",textAlign:"center"},children:(0,o.jsxs)("p",{children:["Product loading... (handle: ",e,")"]})});const a=t?.featured_image||"",i=t?.title||"",r=t?.description||"",l=t?.average_rating;return(0,o.jsx)("div",{style:{border:"2px solid #4CAF50",borderRadius:"16px",padding:"16px",margin:"12px 0",backgroundColor:"#f0f9ff",boxShadow:"0 4px 12px rgba(76, 175, 80, 0.15)"},children:(0,o.jsxs)("div",{style:{display:"flex",gap:"12px",alignItems:"center"},children:[a&&(0,o.jsx)("img",{src:a,alt:i,style:{width:"60px",height:"60px",borderRadius:"8px",objectFit:"cover"}}),(0,o.jsxs)("div",{style:{flex:1},children:[(0,o.jsx)("h4",{style:{margin:"0 0 4px 0",fontSize:"16px",fontWeight:"bold"},children:i}),r&&(0,o.jsxs)("p",{style:{margin:0,fontSize:"12px",color:"#666",lineHeight:1.4},children:[r.slice(0,80),"..."]}),l&&(0,o.jsxs)("span",{style:{fontSize:"12px",color:"#FFB800"},children:["Rating: ",l.toFixed(1)]})]}),(0,o.jsx)("button",{style:{padding:"8px 16px",backgroundColor:"#4CAF50",color:"white",borderRadius:"8px",border:"none",cursor:"pointer"},onClick:()=>console.log("View product:",e,t),children:"View"})]})})}},render:t=>(0,o.jsx)(s.LiveChatWidget,{...t,onOpen:()=>console.log("[LiveChat] Chat opened"),onClose:()=>console.log("[LiveChat] Chat closed"),onMessageSend:e=>console.log("[LiveChat] Message sent:",e),onError:e=>console.error("[LiveChat] Error:",e),onTextMessage:()=>console.log("[LiveChat] AI text message received"),onProductList:()=>console.log("[LiveChat] Product list received"),onPromotionList:()=>console.log("[LiveChat] Promotion list received"),onAddToCart:e=>{console.log("[LiveChat] Add to cart:",e),alert(`Added "${e.title}" to cart!`)},onCart:(e,a)=>{console.log("[LiveChat] Cart clicked:",{cartId:e,checkoutUrl:a}),alert(`Cart ID: ${e}`)}})};
52
52
  //# sourceMappingURL=LiveChatWidget.stories.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/stories/LiveChatWidget.stories.tsx"],
4
- "sourcesContent": ["/**\n * LiveChatWidget Storybook Stories\n * \u5C55\u793A LiveChat \u7EC4\u4EF6\u7684\u5404\u79CD\u4F7F\u7528\u573A\u666F\u548C\u914D\u7F6E\n */\n\nimport type { Meta, StoryObj } from '@storybook/react'\nimport { LiveChatWidget } from '../components/LiveChatWidget'\nimport type { MessageRenderer, MessageContent } from '../components/LiveChatWidget'\nimport '../styles/livechat.css'\n\nconst meta: Meta<typeof LiveChatWidget> = {\n title: 'Campaign/LiveChatWidget',\n component: LiveChatWidget,\n parameters: {\n layout: 'fullscreen',\n docs: {\n story: {\n inline: false,\n iframeHeight: 500,\n },\n description: {\n component: `\n# LiveChat \u804A\u5929\u7EC4\u4EF6\n\n\u53EF\u590D\u7528\u7684\u6C14\u6CE1\u5F39\u7A97\u804A\u5929\u7EC4\u4EF6\uFF0C\u652F\u6301 SSE \u6D41\u5F0F\u6D88\u606F\u3001\u81EA\u5B9A\u4E49\u6E32\u67D3\u5668\u548C\u591A\u79CD\u6D88\u606F\u7C7B\u578B\u3002\n\n## \u529F\u80FD\u7279\u6027\n\n- \uD83C\uDF88 **\u6C14\u6CE1\u5F39\u7A97**: \u53EF\u81EA\u5B9A\u4E49\u4F4D\u7F6E\u7684\u60AC\u6D6E\u6C14\u6CE1\u6309\u94AE\n- \uD83D\uDCAC **\u6D41\u5F0F\u6D88\u606F**: \u57FA\u4E8E SSE \u7684\u5B9E\u65F6\u6D41\u5F0F\u54CD\u5E94\n- \uD83D\uDCE6 **\u591A\u79CD\u6D88\u606F\u7C7B\u578B**: \u6587\u672C\u3001\u5546\u54C1\u5361\u7247\u3001\u5546\u54C1\u5217\u8868\u3001\u653F\u7B56\u3001\u5FEB\u6377\u56DE\u590D\u7B49\n- \uD83C\uDFA8 **\u53EF\u5B9A\u5236**: \u652F\u6301\u81EA\u5B9A\u4E49\u54C1\u724C\u989C\u8272\u3001Logo\u3001\u6E32\u67D3\u5668\n- \uD83D\uDCF1 **\u54CD\u5E94\u5F0F**: \u79FB\u52A8\u7AEF\u5168\u5C4F\uFF0C\u684C\u9762\u7AEF\u56FA\u5B9A\u5C3A\u5BF8\n- \uD83D\uDCBE **\u4F1A\u8BDD\u7BA1\u7406**: \u81EA\u52A8\u7BA1\u7406 userId \u548C sessionId\n- \uD83D\uDD12 **\u5B89\u5168\u9632\u62A4**: \u5185\u7F6E XSS \u9632\u62A4\u548C\u8F93\u5165\u9A8C\u8BC1\n\n## \u57FA\u7840\u7528\u6CD5\n\n\\`\\`\\`tsx\nimport { LiveChatWidget } from '@anker-in/campaign-ui'\nimport '@anker-in/campaign-ui/livechat.css'\n\nfunction App() {\n return (\n <LiveChatWidget\n apiBaseUrl=\"https://beta-api-livechat.anker.com\"\n site=\"www.eufy.com\"\n channel_code=\"web_homepage\"\n welcomeMessage=\"\u4F60\u597D\uFF01\u6211\u662F AI \u52A9\u624B\"\n />\n )\n}\n\\`\\`\\`\n\n## \u81EA\u5B9A\u4E49\u6E32\u67D3\u5668\n\n\\`\\`\\`tsx\nconst customRenderers = {\n video: {\n render: (content) => (\n <video src={content.url} controls className=\"w-full rounded\" />\n )\n }\n}\n\n<LiveChatWidget\n apiBaseUrl=\"...\"\n site=\"...\"\n customRenderers={customRenderers}\n/>\n\\`\\`\\`\n `,\n },\n },\n },\n tags: ['autodocs'],\n argTypes: {\n apiBaseUrl: {\n control: 'text',\n description: 'API \u57FA\u7840 URL',\n },\n headers: {\n control: 'object',\n description: '\u81EA\u5B9A\u4E49\u8BF7\u6C42\u5934\uFF0C\u5C06\u5728\u6240\u6709 API \u8BF7\u6C42\u4E2D\u6DFB\u52A0',\n table: {\n defaultValue: { summary: 'undefined' },\n },\n },\n recaptchaSitekey: {\n control: 'text',\n description: 'Google reCAPTCHA v3 site key\uFF0C\u63D0\u4F9B\u6B64\u53C2\u6570\u5C06\u81EA\u52A8\u542F\u7528 reCAPTCHA v3 \u9A8C\u8BC1',\n table: {\n defaultValue: { summary: 'undefined' },\n },\n },\n recaptchaAction: {\n control: 'text',\n description: 'reCAPTCHA action \u540D\u79F0\uFF0C\u7528\u4E8E\u533A\u5206\u4E0D\u540C\u7684\u9A8C\u8BC1\u573A\u666F',\n table: {\n defaultValue: { summary: '\"activity\"' },\n },\n },\n site: {\n control: 'text',\n description: 'Shopify \u5E97\u94FA URL',\n },\n channelCode: {\n control: 'text',\n description: '\u6E20\u9053\u7F16\u7801\uFF0C\u7528\u4E8E\u6807\u8BC6\u6765\u6E90\u6E20\u9053',\n table: {\n defaultValue: { summary: 'undefined' },\n },\n },\n welcomeMessage: {\n control: 'text',\n description: '\u6B22\u8FCE\u6D88\u606F',\n table: {\n defaultValue: { summary: '\u4F60\u597D\uFF01\u6211\u662F AI \u52A9\u624B\uFF0C\u6709\u4EC0\u4E48\u53EF\u4EE5\u5E2E\u52A9\u4F60\u7684\u5417\uFF1F' },\n },\n },\n logoUrl: {\n control: 'text',\n description: 'Logo URL',\n },\n position: {\n control: 'object',\n description: '\u6C14\u6CE1\u6309\u94AE\u4F4D\u7F6E\u5BF9\u8C61',\n table: {\n defaultValue: { summary: '{ bottom: \"1.5rem\", right: \"1.5rem\" }' },\n },\n },\n },\n args: {\n apiBaseUrl: 'http://172.16.38.183:3003',\n site: 'www.eufy.com',\n loginUserId: 'test_test',\n welcomeMessage: '\u4F60\u597D\uFF01\u6211\u662F AI \u52A9\u624B\uFF0C\u6709\u4EC0\u4E48\u53EF\u4EE5\u5E2E\u52A9\u4F60\u7684\u5417\uFF1F',\n },\n}\n\nexport default meta\ntype Story = StoryObj<typeof LiveChatWidget>\n\n/**\n * \u9ED8\u8BA4\u914D\u7F6E - \u5C55\u793A\u6240\u6709\u529F\u80FD\n */\nexport const Default: Story = {\n args: {\n // \u57FA\u7840\u914D\u7F6E\n loginUserId: 'test_test1',\n apiBaseUrl: 'https://beta-api-v2-livechat.anker.com',\n site: 'beta.eufy.com',\n channelCode: 'dtc',\n title: 'eufy AI Assistant',\n cartId: 'gid://shopify/Cart/hWN7wB3Pa12gh78d8hPOAUBI?key=0e73db1d3fb5ac21da19099c45033253',\n accessToken: '47b1aa2c0797043f9baba39388029d70',\n\n // \u81EA\u5B9A\u4E49\u4F4D\u7F6E\n position: { bottom: '24px', right: '30px' },\n\n // \u6B22\u8FCE\u6D88\u606F\n welcomeMessage: '',\n\n // \u5FEB\u6377\u56DE\u590D\n quickReplies: [\n { id: '1', label: 'Product Info', value: 'Tell me about your products', icon: '\uD83D\uDCE6' },\n { id: '2', label: 'Track Order', value: 'I want to track my order', icon: '\uD83D\uDE9A' },\n { id: '3', label: 'Support', value: 'I need help with my device', icon: '\uD83D\uDD27' },\n { id: '4', label: 'Recommendations', value: 'Recommend products for me', icon: '\u2B50' },\n ],\n\n // \u6CD5\u89C4\u534F\u8BAE\u5F39\u7A97\n complianceConfig: {\n title: \"Hi! I'm your eufy AI assistant.\",\n content:\n 'AI-generated responses can be inaccurate. Please verify important info. Do not input sensitive personal data.',\n checkboxText:\n 'By starting to use \"Live Chat\", you agree to Anker\\'s <a href=\"https://www.anker.com/pages/privacy-policy\" target=\"_blank\" rel=\"noopener noreferrer\" style=\"text-decoration: underline;\">LIVE CHAT PRIVACY NOTICE</a>.',\n agreeButtonText: 'Agree',\n },\n\n // reCAPTCHA \u914D\u7F6E\uFF08\u53D6\u6D88\u6CE8\u91CA\u4EE5\u542F\u7528\uFF09\n // recaptchaSitekey: '6LfS4J4pAAAAACX1e_WrxutmxxzCK7FU4WzVqL14',\n recaptchaAction: 'livechat',\n\n // \u663E\u793A\u65B0\u4F1A\u8BDD\u6309\u94AE\n showNewSessionButton: true,\n\n // \u81EA\u5B9A\u4E49\u6587\u6848\n commonText: {\n learnMore: 'Learn More',\n total: 'Total',\n },\n\n // \u81EA\u5B9A\u4E49\u6D88\u606F\u6E32\u67D3\u5668\n customRenderers: {\n video: {\n render: (content: MessageContent) => {\n const videoContent = content as any\n return (\n <div className=\"w-full\">\n <video src={videoContent.url} controls className=\"w-full rounded-lg\" poster={videoContent.poster}>\n Your browser does not support video playback\n </video>\n {videoContent.title && <p className=\"mt-2 text-sm text-gray-600\">{videoContent.title}</p>}\n </div>\n )\n },\n } as MessageRenderer,\n image_gallery: {\n render: (content: MessageContent) => {\n const galleryContent = content as any\n const images = galleryContent.images || []\n return (\n <div className=\"grid grid-cols-2 gap-2\">\n {images.map((image: any, index: number) => (\n <div key={index} className=\"relative aspect-square\">\n <img\n src={image.url}\n alt={image.alt || `Image ${index + 1}`}\n className=\"size-full rounded-lg object-cover\"\n />\n </div>\n ))}\n </div>\n )\n },\n } as MessageRenderer,\n },\n\n // \u81EA\u5B9A\u4E49\u4EA7\u54C1\u5361\u7247\u6E32\u67D3\n productCardRender: (product, productHandle) => {\n // product \u53EF\u80FD\u4E3A undefined\uFF0C\u6B64\u65F6\u53EF\u7528 productHandle \u67E5\u8BE2\n if (!product) {\n return (\n <div style={{ padding: '16px', border: '1px dashed #ccc', borderRadius: '8px', textAlign: 'center' }}>\n <p>Product loading... (handle: {productHandle})</p>\n </div>\n )\n }\n\n const imageUrl = product?.featured_image || ''\n const title = product?.title || ''\n const description = product?.description || ''\n const averageRating = product?.average_rating\n\n return (\n <div\n style={{\n border: '2px solid #4CAF50',\n borderRadius: '16px',\n padding: '16px',\n margin: '12px 0',\n backgroundColor: '#f0f9ff',\n boxShadow: '0 4px 12px rgba(76, 175, 80, 0.15)',\n }}\n >\n <div style={{ display: 'flex', gap: '12px', alignItems: 'center' }}>\n {imageUrl && (\n <img\n src={imageUrl}\n alt={title}\n style={{ width: '60px', height: '60px', borderRadius: '8px', objectFit: 'cover' }}\n />\n )}\n <div style={{ flex: 1 }}>\n <h4 style={{ margin: '0 0 4px 0', fontSize: '16px', fontWeight: 'bold' }}>{title}</h4>\n {description && (\n <p style={{ margin: 0, fontSize: '12px', color: '#666', lineHeight: 1.4 }}>\n {description.slice(0, 80)}...\n </p>\n )}\n {averageRating && (\n <span style={{ fontSize: '12px', color: '#FFB800' }}>Rating: {averageRating.toFixed(1)}</span>\n )}\n </div>\n <button\n style={{\n padding: '8px 16px',\n backgroundColor: '#4CAF50',\n color: 'white',\n borderRadius: '8px',\n border: 'none',\n cursor: 'pointer',\n }}\n onClick={() => console.log('View product:', productHandle, product)}\n >\n View\n </button>\n </div>\n </div>\n )\n },\n },\n\n render: args => (\n <LiveChatWidget\n {...args}\n // \u6240\u6709\u4E8B\u4EF6\u56DE\u8C03\n onOpen={() => console.log('[LiveChat] Chat opened')}\n onClose={() => console.log('[LiveChat] Chat closed')}\n onMessageSend={(message: string) => console.log('[LiveChat] Message sent:', message)}\n onError={(error: Error) => console.error('[LiveChat] Error:', error)}\n onTextMessage={() => console.log('[LiveChat] AI text message received')}\n onProductList={() => console.log('[LiveChat] Product list received')}\n onPromotionList={() => console.log('[LiveChat] Promotion list received')}\n onAddToCart={(product: any) => {\n console.log('[LiveChat] Add to cart:', product)\n alert(`Added \"${product.title}\" to cart!`)\n }}\n onCart={(cartId: string, checkoutUrl?: string) => {\n console.log('[LiveChat] Cart clicked:', { cartId, checkoutUrl })\n alert(`Cart ID: ${cartId}`)\n }}\n />\n ),\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * LiveChatWidget Storybook Stories\n * \u5C55\u793A LiveChat \u7EC4\u4EF6\u7684\u5404\u79CD\u4F7F\u7528\u573A\u666F\u548C\u914D\u7F6E\n */\n\nimport type { Meta, StoryObj } from '@storybook/react'\nimport { LiveChatWidget } from '../components/LiveChatWidget'\nimport type { MessageRenderer, MessageContent } from '../components/LiveChatWidget'\nimport '../styles/livechat.css'\n\nconst meta: Meta<typeof LiveChatWidget> = {\n title: 'Campaign/LiveChatWidget',\n component: LiveChatWidget,\n parameters: {\n layout: 'fullscreen',\n docs: {\n story: {\n inline: false,\n iframeHeight: 500,\n },\n description: {\n component: `\n# LiveChat \u804A\u5929\u7EC4\u4EF6\n\n\u53EF\u590D\u7528\u7684\u6C14\u6CE1\u5F39\u7A97\u804A\u5929\u7EC4\u4EF6\uFF0C\u652F\u6301 SSE \u6D41\u5F0F\u6D88\u606F\u3001\u81EA\u5B9A\u4E49\u6E32\u67D3\u5668\u548C\u591A\u79CD\u6D88\u606F\u7C7B\u578B\u3002\n\n## \u529F\u80FD\u7279\u6027\n\n- \uD83C\uDF88 **\u6C14\u6CE1\u5F39\u7A97**: \u53EF\u81EA\u5B9A\u4E49\u4F4D\u7F6E\u7684\u60AC\u6D6E\u6C14\u6CE1\u6309\u94AE\n- \uD83D\uDCAC **\u6D41\u5F0F\u6D88\u606F**: \u57FA\u4E8E SSE \u7684\u5B9E\u65F6\u6D41\u5F0F\u54CD\u5E94\n- \uD83D\uDCE6 **\u591A\u79CD\u6D88\u606F\u7C7B\u578B**: \u6587\u672C\u3001\u5546\u54C1\u5361\u7247\u3001\u5546\u54C1\u5217\u8868\u3001\u653F\u7B56\u3001\u5FEB\u6377\u56DE\u590D\u7B49\n- \uD83C\uDFA8 **\u53EF\u5B9A\u5236**: \u652F\u6301\u81EA\u5B9A\u4E49\u54C1\u724C\u989C\u8272\u3001Logo\u3001\u6E32\u67D3\u5668\n- \uD83D\uDCF1 **\u54CD\u5E94\u5F0F**: \u79FB\u52A8\u7AEF\u5168\u5C4F\uFF0C\u684C\u9762\u7AEF\u56FA\u5B9A\u5C3A\u5BF8\n- \uD83D\uDCBE **\u4F1A\u8BDD\u7BA1\u7406**: \u81EA\u52A8\u7BA1\u7406 userId \u548C sessionId\n- \uD83D\uDD12 **\u5B89\u5168\u9632\u62A4**: \u5185\u7F6E XSS \u9632\u62A4\u548C\u8F93\u5165\u9A8C\u8BC1\n\n## \u57FA\u7840\u7528\u6CD5\n\n\\`\\`\\`tsx\nimport { LiveChatWidget } from '@anker-in/campaign-ui'\nimport '@anker-in/campaign-ui/livechat.css'\n\nfunction App() {\n return (\n <LiveChatWidget\n apiBaseUrl=\"https://beta-api-livechat.anker.com\"\n site=\"www.eufy.com\"\n channel_code=\"web_homepage\"\n welcomeMessage=\"\u4F60\u597D\uFF01\u6211\u662F AI \u52A9\u624B\"\n />\n )\n}\n\\`\\`\\`\n\n## \u81EA\u5B9A\u4E49\u6E32\u67D3\u5668\n\n\\`\\`\\`tsx\nconst customRenderers = {\n video: {\n render: (content) => (\n <video src={content.url} controls className=\"w-full rounded\" />\n )\n }\n}\n\n<LiveChatWidget\n apiBaseUrl=\"...\"\n site=\"...\"\n customRenderers={customRenderers}\n/>\n\\`\\`\\`\n `,\n },\n },\n },\n tags: ['autodocs'],\n argTypes: {\n apiBaseUrl: {\n control: 'text',\n description: 'API \u57FA\u7840 URL',\n },\n headers: {\n control: 'object',\n description: '\u81EA\u5B9A\u4E49\u8BF7\u6C42\u5934\uFF0C\u5C06\u5728\u6240\u6709 API \u8BF7\u6C42\u4E2D\u6DFB\u52A0',\n table: {\n defaultValue: { summary: 'undefined' },\n },\n },\n recaptchaSitekey: {\n control: 'text',\n description: 'Google reCAPTCHA v3 site key\uFF0C\u63D0\u4F9B\u6B64\u53C2\u6570\u5C06\u81EA\u52A8\u542F\u7528 reCAPTCHA v3 \u9A8C\u8BC1',\n table: {\n defaultValue: { summary: 'undefined' },\n },\n },\n recaptchaAction: {\n control: 'text',\n description: 'reCAPTCHA action \u540D\u79F0\uFF0C\u7528\u4E8E\u533A\u5206\u4E0D\u540C\u7684\u9A8C\u8BC1\u573A\u666F',\n table: {\n defaultValue: { summary: '\"activity\"' },\n },\n },\n site: {\n control: 'text',\n description: 'Shopify \u5E97\u94FA URL',\n },\n channelCode: {\n control: 'text',\n description: '\u6E20\u9053\u7F16\u7801\uFF0C\u7528\u4E8E\u6807\u8BC6\u6765\u6E90\u6E20\u9053',\n table: {\n defaultValue: { summary: 'undefined' },\n },\n },\n welcomeMessage: {\n control: 'text',\n description: '\u6B22\u8FCE\u6D88\u606F',\n table: {\n defaultValue: { summary: '\u4F60\u597D\uFF01\u6211\u662F AI \u52A9\u624B\uFF0C\u6709\u4EC0\u4E48\u53EF\u4EE5\u5E2E\u52A9\u4F60\u7684\u5417\uFF1F' },\n },\n },\n logoUrl: {\n control: 'text',\n description: 'Logo URL',\n },\n position: {\n control: 'object',\n description: '\u6C14\u6CE1\u6309\u94AE\u4F4D\u7F6E\u5BF9\u8C61',\n table: {\n defaultValue: { summary: '{ bottom: \"1.5rem\", right: \"1.5rem\" }' },\n },\n },\n },\n args: {\n apiBaseUrl: 'http://172.16.38.183:3003',\n site: 'www.eufy.com',\n loginUserId: 'test_test',\n welcomeMessage: '\u4F60\u597D\uFF01\u6211\u662F AI \u52A9\u624B\uFF0C\u6709\u4EC0\u4E48\u53EF\u4EE5\u5E2E\u52A9\u4F60\u7684\u5417\uFF1F',\n },\n}\n\nexport default meta\ntype Story = StoryObj<typeof LiveChatWidget>\n\n/**\n * \u9ED8\u8BA4\u914D\u7F6E - \u5C55\u793A\u6240\u6709\u529F\u80FD\n */\nexport const Default: Story = {\n args: {\n // \u57FA\u7840\u914D\u7F6E\n loginUserId: 'test_test1',\n apiBaseUrl: 'https://beta-api-v2-livechat.anker.com',\n site: 'beta.soundcore.com',\n channelCode: 'dtc',\n title: 'eufy AI Assistant',\n cartId: 'gid://shopify/Cart/hWNAAJweS9IkeRKib4LRy9PY?key=ff1f9b24e74b3f11f5574539e7cbbb2f',\n accessToken: '47b1aa2c0797043f9baba39388029d70',\n\n // \u81EA\u5B9A\u4E49\u4F4D\u7F6E\n position: { bottom: '24px', right: '30px' },\n\n // \u6B22\u8FCE\u6D88\u606F\n welcomeMessage: '',\n\n // \u5FEB\u6377\u56DE\u590D\n quickReplies: [\n { id: '1', label: 'Product Info', value: 'Tell me about your products', icon: '\uD83D\uDCE6' },\n { id: '2', label: 'Track Order', value: 'I want to track my order', icon: '\uD83D\uDE9A' },\n { id: '3', label: 'Support', value: 'I need help with my device', icon: '\uD83D\uDD27' },\n { id: '4', label: 'Recommendations', value: 'Recommend products for me', icon: '\u2B50' },\n ],\n\n // \u6CD5\u89C4\u534F\u8BAE\u5F39\u7A97\n complianceConfig: {\n title: \"Hi! I'm your eufy AI assistant.\",\n content:\n 'AI-generated responses can be inaccurate. Please verify important info. Do not input sensitive personal data.',\n checkboxText:\n 'By starting to use \"Live Chat\", you agree to Anker\\'s <a href=\"https://www.anker.com/pages/privacy-policy\" target=\"_blank\" rel=\"noopener noreferrer\" style=\"text-decoration: underline;\">LIVE CHAT PRIVACY NOTICE</a>.',\n agreeButtonText: 'Agree',\n },\n\n // reCAPTCHA \u914D\u7F6E\uFF08\u53D6\u6D88\u6CE8\u91CA\u4EE5\u542F\u7528\uFF09\n // recaptchaSitekey: '6LfS4J4pAAAAACX1e_WrxutmxxzCK7FU4WzVqL14',\n recaptchaAction: 'livechat',\n\n // \u663E\u793A\u65B0\u4F1A\u8BDD\u6309\u94AE\n showNewSessionButton: true,\n\n // \u81EA\u5B9A\u4E49\u6587\u6848\n commonText: {\n learnMore: 'Learn More',\n total: 'Total',\n },\n\n // \u81EA\u5B9A\u4E49\u6D88\u606F\u6E32\u67D3\u5668\n customRenderers: {\n video: {\n render: (content: MessageContent) => {\n const videoContent = content as any\n return (\n <div className=\"w-full\">\n <video src={videoContent.url} controls className=\"w-full rounded-lg\" poster={videoContent.poster}>\n Your browser does not support video playback\n </video>\n {videoContent.title && <p className=\"mt-2 text-sm text-gray-600\">{videoContent.title}</p>}\n </div>\n )\n },\n } as MessageRenderer,\n image_gallery: {\n render: (content: MessageContent) => {\n const galleryContent = content as any\n const images = galleryContent.images || []\n return (\n <div className=\"grid grid-cols-2 gap-2\">\n {images.map((image: any, index: number) => (\n <div key={index} className=\"relative aspect-square\">\n <img\n src={image.url}\n alt={image.alt || `Image ${index + 1}`}\n className=\"size-full rounded-lg object-cover\"\n />\n </div>\n ))}\n </div>\n )\n },\n } as MessageRenderer,\n },\n\n // \u81EA\u5B9A\u4E49\u4EA7\u54C1\u5361\u7247\u6E32\u67D3\n productCardRender: (product, productHandle) => {\n // product \u53EF\u80FD\u4E3A undefined\uFF0C\u6B64\u65F6\u53EF\u7528 productHandle \u67E5\u8BE2\n if (!product) {\n return (\n <div style={{ padding: '16px', border: '1px dashed #ccc', borderRadius: '8px', textAlign: 'center' }}>\n <p>Product loading... (handle: {productHandle})</p>\n </div>\n )\n }\n\n const imageUrl = product?.featured_image || ''\n const title = product?.title || ''\n const description = product?.description || ''\n const averageRating = product?.average_rating\n\n return (\n <div\n style={{\n border: '2px solid #4CAF50',\n borderRadius: '16px',\n padding: '16px',\n margin: '12px 0',\n backgroundColor: '#f0f9ff',\n boxShadow: '0 4px 12px rgba(76, 175, 80, 0.15)',\n }}\n >\n <div style={{ display: 'flex', gap: '12px', alignItems: 'center' }}>\n {imageUrl && (\n <img\n src={imageUrl}\n alt={title}\n style={{ width: '60px', height: '60px', borderRadius: '8px', objectFit: 'cover' }}\n />\n )}\n <div style={{ flex: 1 }}>\n <h4 style={{ margin: '0 0 4px 0', fontSize: '16px', fontWeight: 'bold' }}>{title}</h4>\n {description && (\n <p style={{ margin: 0, fontSize: '12px', color: '#666', lineHeight: 1.4 }}>\n {description.slice(0, 80)}...\n </p>\n )}\n {averageRating && (\n <span style={{ fontSize: '12px', color: '#FFB800' }}>Rating: {averageRating.toFixed(1)}</span>\n )}\n </div>\n <button\n style={{\n padding: '8px 16px',\n backgroundColor: '#4CAF50',\n color: 'white',\n borderRadius: '8px',\n border: 'none',\n cursor: 'pointer',\n }}\n onClick={() => console.log('View product:', productHandle, product)}\n >\n View\n </button>\n </div>\n </div>\n )\n },\n },\n\n render: args => (\n <LiveChatWidget\n {...args}\n // \u6240\u6709\u4E8B\u4EF6\u56DE\u8C03\n onOpen={() => console.log('[LiveChat] Chat opened')}\n onClose={() => console.log('[LiveChat] Chat closed')}\n onMessageSend={(message: string) => console.log('[LiveChat] Message sent:', message)}\n onError={(error: Error) => console.error('[LiveChat] Error:', error)}\n onTextMessage={() => console.log('[LiveChat] AI text message received')}\n onProductList={() => console.log('[LiveChat] Product list received')}\n onPromotionList={() => console.log('[LiveChat] Promotion list received')}\n onAddToCart={(product: any) => {\n console.log('[LiveChat] Add to cart:', product)\n alert(`Added \"${product.title}\" to cart!`)\n }}\n onCart={(cartId: string, checkoutUrl?: string) => {\n console.log('[LiveChat] Cart clicked:', { cartId, checkoutUrl })\n alert(`Cart ID: ${cartId}`)\n }}\n />\n ),\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["LiveChatWidget_stories_exports", "__export", "Default", "LiveChatWidget_stories_default", "__toCommonJS", "import_jsx_runtime", "import_LiveChatWidget", "import_livechat", "meta", "content", "videoContent", "images", "image", "index", "product", "productHandle", "imageUrl", "title", "description", "averageRating", "args", "message", "error", "cartId", "checkoutUrl"]
7
7
  }
@@ -1,2 +1,2 @@
1
- import{jsx as n,jsxs as a}from"react/jsx-runtime";import{useRef as h,useEffect as E}from"react";const v=()=>a("svg",{width:"20",height:"20",viewBox:"0 0 20 20",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[n("path",{d:"M10.2069 15.6997V4.69971",stroke:"white","stroke-width":"2","stroke-linecap":"round"}),n("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"})]}),N=({value:t,onChange:p,onSend:c,placeholder:u="",disabled:o=!1,autoFocus:x=!1,maxLength:s=5e3,bottomTips:d,className:f=""})=>{const g=h(null),r=h(!1);E(()=>{const e=g.current;if(!e)return;e.style.height="auto";const k=Math.min(e.scrollHeight,120);e.style.height=`${k}px`},[t]);const m=()=>{r.current=!0},b=()=>{r.current=!1},w=e=>{if(e.key==="Enter"&&!e.shiftKey){if(r.current)return;e.preventDefault(),t.trim()&&!o&&c()}},C=e=>{const l=e.target.value;l.length<=s&&p(l)},y=()=>{t.trim()&&!o&&c()},i=t.trim().length>0&&!o;return a("div",{className:`flex flex-col gap-2 bg-white px-4 py-4 ${f}`,children:[n("div",{className:"flex items-center gap-2 rounded-2xl",style:{background:"linear-gradient(to right, #7687F3, #7687F3, #4DA8F5, #A3DFCE)",padding:"2px"},children:a("div",{className:"flex flex-1 items-center gap-2 bg-white px-3 py-2",style:{borderRadius:"14px"},children:[n("textarea",{ref:g,value:t,onChange:C,onKeyDown:w,onCompositionStart:m,onCompositionEnd:b,placeholder:u,disabled:o,autoFocus:x,rows:1,className:"flex-1 resize-none bg-transparent font-bold text-sm text-gray-900 outline-none placeholder:text-gray-400 disabled:cursor-not-allowed disabled:opacity-50",style:{resize:"none"}}),t.length>s*.8&&a("span",{className:"text-xs text-gray-400",children:[t.length,"/",s]}),n("button",{type:"button",onClick:y,disabled:!i,className:`shrink-0 rounded-full p-2 transition-all ${i?" active:scale-95":"cursor-not-allowed "}`,style:i?{background:"linear-gradient(to bottom, #A3DFCE, #4DA8F5, #7687F3)"}:{background:"#BEBEBE"},"aria-label":"Send message",children:n(v,{})})]})}),d&&n("p",{className:"px-3 font-bold text-[12px] text-[#767880] tracking-tight leading-[1.4]",children:d})]})};export{N as ChatInput};
1
+ import{jsx as n,jsxs as a}from"react/jsx-runtime";import{useRef as p,useEffect as v}from"react";const E=()=>a("svg",{width:"20",height:"20",viewBox:"0 0 20 20",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[n("path",{d:"M10.2069 15.6997V4.69971",stroke:"white","stroke-width":"2","stroke-linecap":"round"}),n("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"})]}),N=({value:t,onChange:g,onSend:c,placeholder:u="",disabled:o=!1,autoFocus:x=!1,maxLength:s=5e3,bottomTips:d,className:f=""})=>{const h=p(null),r=p(!1);v(()=>{const e=h.current;if(!e)return;e.style.height="auto";const k=Math.min(e.scrollHeight,120);e.style.height=`${k}px`},[t]);const m=()=>{r.current=!0},b=()=>{r.current=!1},w=e=>{if(e.key==="Enter"&&!e.shiftKey){if(r.current)return;e.preventDefault(),t.trim()&&!o&&c()}},C=e=>{const l=e.target.value;l.length<=s&&g(l)},y=()=>{t.trim()&&!o&&c()},i=t.trim().length>0&&!o;return a("div",{className:`flex flex-col gap-2 bg-white px-4 py-4 ${f}`,children:[n("div",{className:"livechat-input-border flex items-center gap-2 rounded-2xl",style:{background:"linear-gradient(to right, #7687F3, #7687F3, #4DA8F5, #A3DFCE)",padding:"2px"},children:a("div",{className:"flex flex-1 items-center gap-2 bg-white px-3 py-2",style:{borderRadius:"14px"},children:[n("textarea",{ref:h,value:t,onChange:C,onKeyDown:w,onCompositionStart:m,onCompositionEnd:b,placeholder:u,disabled:o,autoFocus:x,rows:1,className:"flex-1 resize-none bg-transparent font-bold text-sm text-gray-900 outline-none placeholder:text-gray-400 disabled:cursor-not-allowed disabled:opacity-50",style:{resize:"none"}}),t.length>s*.8&&a("span",{className:"text-xs text-gray-400",children:[t.length,"/",s]}),n("button",{type:"button",onClick:y,disabled:!i,className:`shrink-0 rounded-full p-2 transition-all ${i?"livechat-input-send active:scale-95":"livechat-input-send--disabled cursor-not-allowed "}`,style:i?{background:"linear-gradient(to bottom, #A3DFCE, #4DA8F5, #7687F3)"}:{background:"#BEBEBE"},"aria-label":"Send message",children:n(E,{})})]})}),d&&n("p",{className:"px-3 font-bold text-[12px] text-[#767880] tracking-tight leading-[1.4]",children:d})]})};export{N as ChatInput};
2
2
  //# sourceMappingURL=ChatInput.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
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 * \u5E95\u90E8\u63D0\u793A\u6587\u672C\n * \u4E0D\u4F20\u5165\u5219\u4E0D\u663E\u793A\n */\n bottomTips?: 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 bottomTips,\n className = '',\n}) => {\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n // \u8DDF\u8E2A\u8F93\u5165\u6CD5\u72B6\u6001\uFF08\u662F\u5426\u6B63\u5728\u4F7F\u7528\u62FC\u97F3\u8F93\u5165\u7B49\uFF09\n const isComposingRef = useRef(false)\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\u8F93\u5165\u6CD5\u5F00\u59CB\n */\n const handleCompositionStart = () => {\n isComposingRef.current = true\n }\n\n /**\n * \u5904\u7406\u8F93\u5165\u6CD5\u7ED3\u675F\n */\n const handleCompositionEnd = () => {\n isComposingRef.current = false\n }\n\n /**\n * \u5904\u7406\u952E\u76D8\u4E8B\u4EF6\n * Enter \u53D1\u9001\uFF0CShift+Enter \u6362\u884C\n * \u6CE8\u610F\uFF1A\u8F93\u5165\u6CD5\u6FC0\u6D3B\u65F6\uFF08\u5982\u62FC\u97F3\u8F93\u5165\u4E2D\uFF09\uFF0C\u56DE\u8F66\u952E\u4E0D\u5E94\u53D1\u9001\u6D88\u606F\n */\n const handleKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key === 'Enter' && !event.shiftKey) {\n // \u5982\u679C\u6B63\u5728\u4F7F\u7528\u8F93\u5165\u6CD5\uFF08\u5982\u62FC\u97F3\u8F93\u5165\uFF09\uFF0C\u5219\u4E0D\u53D1\u9001\u6D88\u606F\n // \u8BA9\u8F93\u5165\u6CD5\u5148\u5B8C\u6210\u5B57\u7B26\u9009\u62E9\n if (isComposingRef.current) {\n return\n }\n\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 flex-col gap-2 bg-white px-4 py-4 ${className}`}>\n {/* \u8F93\u5165\u6846\u5BB9\u5668 - \u5E26\u6E10\u53D8\u8FB9\u6846 */}\n <div\n className=\"flex 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 onCompositionStart={handleCompositionStart}\n onCompositionEnd={handleCompositionEnd}\n placeholder={placeholder}\n disabled={disabled}\n autoFocus={autoFocus}\n rows={1}\n className=\"flex-1 resize-none bg-transparent font-bold 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=\"Send message\"\n >\n <SendIcon />\n </button>\n </div>\n </div>\n {bottomTips && (\n <p className=\"px-3 font-bold text-[12px] text-[#767880] tracking-tight leading-[1.4]\">\n {bottomTips}\n </p>\n )}\n </div>\n )\n}\n"],
5
- "mappings": "AAgEE,OACE,OAAAA,EADF,QAAAC,MAAA,oBA1DF,OAAgB,UAAAC,EAAQ,aAAAC,MAAiB,QAyDzC,MAAMC,EAAqB,IACzBH,EAAC,OAAI,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,MAAM,6BAChE,UAAAD,EAAC,QAAK,EAAE,2BAA2B,OAAO,QAAQ,eAAa,IAAI,iBAAe,QAAQ,EAC1FA,EAAC,QACC,EAAE,gGACF,OAAO,QACP,eAAa,IACb,iBAAe,QACf,kBAAgB,QAClB,GACF,EA4BWK,EAAsC,CAAC,CAClD,MAAAC,EACA,SAAAC,EACA,OAAAC,EACA,YAAAC,EAAc,GACd,SAAAC,EAAW,GACX,UAAAC,EAAY,GACZ,UAAAC,EAAY,IACZ,WAAAC,EACA,UAAAC,EAAY,EACd,IAAM,CACJ,MAAMC,EAAcb,EAA4B,IAAI,EAE9Cc,EAAiBd,EAAO,EAAK,EAKnCC,EAAU,IAAM,CACd,MAAMc,EAAWF,EAAY,QAC7B,GAAI,CAACE,EAAU,OAGfA,EAAS,MAAM,OAAS,OAIxB,MAAMC,EAAY,KAAK,IAAID,EAAS,aADlB,GACyC,EAC3DA,EAAS,MAAM,OAAS,GAAGC,CAAS,IACtC,EAAG,CAACZ,CAAK,CAAC,EAKV,MAAMa,EAAyB,IAAM,CACnCH,EAAe,QAAU,EAC3B,EAKMI,EAAuB,IAAM,CACjCJ,EAAe,QAAU,EAC3B,EAOMK,EAAiBC,GAAoD,CACzE,GAAIA,EAAM,MAAQ,SAAW,CAACA,EAAM,SAAU,CAG5C,GAAIN,EAAe,QACjB,OAGFM,EAAM,eAAe,EACjBhB,EAAM,KAAK,GAAK,CAACI,GACnBF,EAAO,CAEX,CACF,EAKMe,EAAgBD,GAAkD,CACtE,MAAME,EAAWF,EAAM,OAAO,MAG1BE,EAAS,QAAUZ,GACrBL,EAASiB,CAAQ,CAErB,EAKMC,EAAkB,IAAM,CACxBnB,EAAM,KAAK,GAAK,CAACI,GACnBF,EAAO,CAEX,EAEMkB,EAAUpB,EAAM,KAAK,EAAE,OAAS,GAAK,CAACI,EAE5C,OACET,EAAC,OAAI,UAAW,0CAA0Ca,CAAS,GAEjE,UAAAd,EAAC,OACC,UAAU,sCACV,MAAO,CACL,WAAY,gEACZ,QAAS,KACX,EAGA,SAAAC,EAAC,OAAI,UAAU,oDAAoD,MAAO,CAAE,aAAc,MAAO,EAE/F,UAAAD,EAAC,YACC,IAAKe,EACL,MAAOT,EACP,SAAUiB,EACV,UAAWF,EACX,mBAAoBF,EACpB,iBAAkBC,EAClB,YAAaX,EACb,SAAUC,EACV,UAAWC,EACX,KAAM,EACN,UAAU,2JACV,MAAO,CACL,OAAQ,MACV,EACF,EAGCL,EAAM,OAASM,EAAY,IAC1BX,EAAC,QAAK,UAAU,wBACb,UAAAK,EAAM,OAAO,IAAEM,GAClB,EAIFZ,EAAC,UACC,KAAK,SACL,QAASyB,EACT,SAAU,CAACC,EACX,UAAW,4CAA4CA,EAAU,mBAAqB,qBAAqB,GAC3G,MACEA,EACI,CACE,WAAY,uDACd,EACA,CAAE,WAAY,SAAU,EAE9B,aAAW,eAEX,SAAA1B,EAACI,EAAA,EAAS,EACZ,GACF,EACF,EACCS,GACCb,EAAC,KAAE,UAAU,yEACV,SAAAa,EACH,GAEJ,CAEJ",
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 * \u5E95\u90E8\u63D0\u793A\u6587\u672C\n * \u4E0D\u4F20\u5165\u5219\u4E0D\u663E\u793A\n */\n bottomTips?: 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 bottomTips,\n className = '',\n}) => {\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n // \u8DDF\u8E2A\u8F93\u5165\u6CD5\u72B6\u6001\uFF08\u662F\u5426\u6B63\u5728\u4F7F\u7528\u62FC\u97F3\u8F93\u5165\u7B49\uFF09\n const isComposingRef = useRef(false)\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\u8F93\u5165\u6CD5\u5F00\u59CB\n */\n const handleCompositionStart = () => {\n isComposingRef.current = true\n }\n\n /**\n * \u5904\u7406\u8F93\u5165\u6CD5\u7ED3\u675F\n */\n const handleCompositionEnd = () => {\n isComposingRef.current = false\n }\n\n /**\n * \u5904\u7406\u952E\u76D8\u4E8B\u4EF6\n * Enter \u53D1\u9001\uFF0CShift+Enter \u6362\u884C\n * \u6CE8\u610F\uFF1A\u8F93\u5165\u6CD5\u6FC0\u6D3B\u65F6\uFF08\u5982\u62FC\u97F3\u8F93\u5165\u4E2D\uFF09\uFF0C\u56DE\u8F66\u952E\u4E0D\u5E94\u53D1\u9001\u6D88\u606F\n */\n const handleKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key === 'Enter' && !event.shiftKey) {\n // \u5982\u679C\u6B63\u5728\u4F7F\u7528\u8F93\u5165\u6CD5\uFF08\u5982\u62FC\u97F3\u8F93\u5165\uFF09\uFF0C\u5219\u4E0D\u53D1\u9001\u6D88\u606F\n // \u8BA9\u8F93\u5165\u6CD5\u5148\u5B8C\u6210\u5B57\u7B26\u9009\u62E9\n if (isComposingRef.current) {\n return\n }\n\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 flex-col gap-2 bg-white px-4 py-4 ${className}`}>\n {/* \u8F93\u5165\u6846\u5BB9\u5668 - \u5E26\u6E10\u53D8\u8FB9\u6846 */}\n <div\n className=\"livechat-input-border flex 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 onCompositionStart={handleCompositionStart}\n onCompositionEnd={handleCompositionEnd}\n placeholder={placeholder}\n disabled={disabled}\n autoFocus={autoFocus}\n rows={1}\n className=\"flex-1 resize-none bg-transparent font-bold 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 ? 'livechat-input-send active:scale-95' : 'livechat-input-send--disabled 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=\"Send message\"\n >\n <SendIcon />\n </button>\n </div>\n </div>\n {bottomTips && (\n <p className=\"px-3 font-bold text-[12px] text-[#767880] tracking-tight leading-[1.4]\">\n {bottomTips}\n </p>\n )}\n </div>\n )\n}\n"],
5
+ "mappings": "AAgEE,OACE,OAAAA,EADF,QAAAC,MAAA,oBA1DF,OAAgB,UAAAC,EAAQ,aAAAC,MAAiB,QAyDzC,MAAMC,EAAqB,IACzBH,EAAC,OAAI,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,MAAM,6BAChE,UAAAD,EAAC,QAAK,EAAE,2BAA2B,OAAO,QAAQ,eAAa,IAAI,iBAAe,QAAQ,EAC1FA,EAAC,QACC,EAAE,gGACF,OAAO,QACP,eAAa,IACb,iBAAe,QACf,kBAAgB,QAClB,GACF,EA4BWK,EAAsC,CAAC,CAClD,MAAAC,EACA,SAAAC,EACA,OAAAC,EACA,YAAAC,EAAc,GACd,SAAAC,EAAW,GACX,UAAAC,EAAY,GACZ,UAAAC,EAAY,IACZ,WAAAC,EACA,UAAAC,EAAY,EACd,IAAM,CACJ,MAAMC,EAAcb,EAA4B,IAAI,EAE9Cc,EAAiBd,EAAO,EAAK,EAKnCC,EAAU,IAAM,CACd,MAAMc,EAAWF,EAAY,QAC7B,GAAI,CAACE,EAAU,OAGfA,EAAS,MAAM,OAAS,OAIxB,MAAMC,EAAY,KAAK,IAAID,EAAS,aADlB,GACyC,EAC3DA,EAAS,MAAM,OAAS,GAAGC,CAAS,IACtC,EAAG,CAACZ,CAAK,CAAC,EAKV,MAAMa,EAAyB,IAAM,CACnCH,EAAe,QAAU,EAC3B,EAKMI,EAAuB,IAAM,CACjCJ,EAAe,QAAU,EAC3B,EAOMK,EAAiBC,GAAoD,CACzE,GAAIA,EAAM,MAAQ,SAAW,CAACA,EAAM,SAAU,CAG5C,GAAIN,EAAe,QACjB,OAGFM,EAAM,eAAe,EACjBhB,EAAM,KAAK,GAAK,CAACI,GACnBF,EAAO,CAEX,CACF,EAKMe,EAAgBD,GAAkD,CACtE,MAAME,EAAWF,EAAM,OAAO,MAG1BE,EAAS,QAAUZ,GACrBL,EAASiB,CAAQ,CAErB,EAKMC,EAAkB,IAAM,CACxBnB,EAAM,KAAK,GAAK,CAACI,GACnBF,EAAO,CAEX,EAEMkB,EAAUpB,EAAM,KAAK,EAAE,OAAS,GAAK,CAACI,EAE5C,OACET,EAAC,OAAI,UAAW,0CAA0Ca,CAAS,GAEjE,UAAAd,EAAC,OACC,UAAU,4DACV,MAAO,CACL,WAAY,gEACZ,QAAS,KACX,EAGA,SAAAC,EAAC,OAAI,UAAU,oDAAoD,MAAO,CAAE,aAAc,MAAO,EAE/F,UAAAD,EAAC,YACC,IAAKe,EACL,MAAOT,EACP,SAAUiB,EACV,UAAWF,EACX,mBAAoBF,EACpB,iBAAkBC,EAClB,YAAaX,EACb,SAAUC,EACV,UAAWC,EACX,KAAM,EACN,UAAU,2JACV,MAAO,CACL,OAAQ,MACV,EACF,EAGCL,EAAM,OAASM,EAAY,IAC1BX,EAAC,QAAK,UAAU,wBACb,UAAAK,EAAM,OAAO,IAAEM,GAClB,EAIFZ,EAAC,UACC,KAAK,SACL,QAASyB,EACT,SAAU,CAACC,EACX,UAAW,4CAA4CA,EAAU,sCAAwC,mDAAmD,GAC5J,MACEA,EACI,CACE,WAAY,uDACd,EACA,CAAE,WAAY,SAAU,EAE9B,aAAW,eAEX,SAAA1B,EAACI,EAAA,EAAS,EACZ,GACF,EACF,EACCS,GACCb,EAAC,KAAE,UAAU,yEACV,SAAAa,EACH,GAEJ,CAEJ",
6
6
  "names": ["jsx", "jsxs", "useRef", "useEffect", "SendIcon", "ChatInput", "value", "onChange", "onSend", "placeholder", "disabled", "autoFocus", "maxLength", "bottomTips", "className", "textareaRef", "isComposingRef", "textarea", "newHeight", "handleCompositionStart", "handleCompositionEnd", "handleKeyDown", "event", "handleChange", "newValue", "handleSendClick", "canSend"]
7
7
  }
@@ -1,5 +1,5 @@
1
- import{jsx as s,jsxs as C}from"react/jsx-runtime";import{MessageContent as d}from"./MessageContent";import u from"classnames";function v(t){const r=new Date(t),o=r.getHours().toString().padStart(2,"0"),i=r.getMinutes().toString().padStart(2,"0");return`${o}:${i}`}const $=({message:t,rendererRegistry:r,defaultRenderer:o,showTimestamp:i=!0,className:c="",onAddToCart:p})=>{const n=t.role==="user",R=t.role==="assistant",y=t.role==="system",g=t.role==="tool";if(y)return s("div",{className:`flex justify-center py-2 ${c}`,children:s("div",{className:"",children:t.content.map((e,a)=>s(d,{content:e,isUser:!1,isSystem:!0,rendererRegistry:r,defaultRenderer:o},a))})});if(g)return null;const f=["product_list","product_comparison","faq_list","promotion_list","cart"],l=t.content.filter(e=>!f.includes(e.type)),x=t.content.filter(e=>f.includes(e.type)),m=l.some(e=>e.type==="product_card");return s("div",{className:`flex ${n?"justify-end":"justify-start"} py-2 ${c}`,children:C("div",{className:"flex w-fit max-w-full flex-col gap-2",children:[l.length>0&&s("div",{className:u("w-fit min-w-0 overflow-hidden rounded-2xl ",n?"text-white":"text-[#1D1D1F]",m?"p-4":"p-3"),style:{backgroundColor:n?"#005D8E":"#F5F6F7"},children:s("div",{className:u("flex w-full min-w-0 flex-col",m?"gap-0":"gap-2"),children:l.map((e,a)=>s(d,{content:e,isUser:n,isSystem:!1,rendererRegistry:r,defaultRenderer:o,onAddToCart:p},a))})}),x.map((e,a)=>s("div",{className:"w-full",children:s(d,{content:e,isUser:n,isSystem:!1,rendererRegistry:r,defaultRenderer:o,onAddToCart:p})},`standalone-${a}`)),i&&s("span",{className:`
1
+ import{jsx as s,jsxs as b}from"react/jsx-runtime";import{MessageContent as d}from"./MessageContent";import m from"classnames";function x(t){const r=new Date(t),o=r.getHours().toString().padStart(2,"0"),i=r.getMinutes().toString().padStart(2,"0");return`${o}:${i}`}const $=({message:t,rendererRegistry:r,defaultRenderer:o,showTimestamp:i=!0,className:c="",onAddToCart:p})=>{const n=t.role==="user",C=t.role==="assistant",y=t.role==="system",g=t.role==="tool";if(y)return s("div",{className:`flex justify-center py-2 ${c}`,children:s("div",{className:"",children:t.content.map((e,a)=>s(d,{content:e,isUser:!1,isSystem:!0,rendererRegistry:r,defaultRenderer:o},a))})});if(g)return null;const u=["product_list","product_comparison","faq_list","promotion_list","cart"],l=t.content.filter(e=>!u.includes(e.type)),v=t.content.filter(e=>u.includes(e.type)),f=l.some(e=>e.type==="product_card");return s("div",{className:`flex ${n?"justify-end":"justify-start"} py-2 ${c}`,children:b("div",{className:"flex w-fit max-w-full flex-col gap-2",children:[l.length>0&&s("div",{className:m("w-fit min-w-0 overflow-hidden rounded-2xl ",n?"livechat-bubble-user text-white":"livechat-bubble-bot text-[#1D1D1F]",f?"p-4":"p-3"),style:{backgroundColor:n?"#005D8E":"#F5F6F7"},children:s("div",{className:m("flex w-full min-w-0 flex-col",f?"gap-0":"gap-2"),children:l.map((e,a)=>s(d,{content:e,isUser:n,isSystem:!1,rendererRegistry:r,defaultRenderer:o,onAddToCart:p},a))})}),v.map((e,a)=>s("div",{className:"w-full",children:s(d,{content:e,isUser:n,isSystem:!1,rendererRegistry:r,defaultRenderer:o,onAddToCart:p})},`standalone-${a}`)),i&&s("span",{className:`
2
2
  px-2 text-xs text-gray-400
3
3
  ${n?"text-right":"text-left"}
4
- `,children:v(t.timestamp)})]})})};export{$ as ChatMessage};
4
+ `,children:x(t.timestamp)})]})})};export{$ as ChatMessage};
5
5
  //# sourceMappingURL=ChatMessage.js.map