@anker-in/headless-ui 1.1.56 → 1.1.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/biz-components/ActiveShelf/ProductCard.d.ts +1 -1
- package/dist/cjs/biz-components/ActiveShelf/ProductCard.js +1 -1
- package/dist/cjs/biz-components/ActiveShelf/ProductCard.js.map +2 -2
- package/dist/cjs/biz-components/ActiveShelf/index.js +1 -1
- package/dist/cjs/biz-components/ActiveShelf/index.js.map +2 -2
- package/dist/cjs/biz-components/BuyOneGetOneShelf/FreeGiftItem.js +1 -1
- package/dist/cjs/biz-components/BuyOneGetOneShelf/FreeGiftItem.js.map +2 -2
- package/dist/cjs/biz-components/BuyOneGetOneShelf/ProductCard.js +1 -1
- package/dist/cjs/biz-components/BuyOneGetOneShelf/ProductCard.js.map +2 -2
- package/dist/cjs/biz-components/BuyOneGetOneShelf/index.js +1 -1
- package/dist/cjs/biz-components/BuyOneGetOneShelf/index.js.map +2 -2
- package/dist/cjs/biz-components/Category/SwiperCategory.d.ts +2 -0
- package/dist/cjs/biz-components/Category/SwiperCategory.js +1 -1
- package/dist/cjs/biz-components/Category/SwiperCategory.js.map +3 -3
- package/dist/cjs/biz-components/Category/index.js +1 -1
- package/dist/cjs/biz-components/Category/index.js.map +3 -3
- package/dist/cjs/biz-components/CreditsShelf/ProductCard.d.ts +41 -0
- package/dist/cjs/biz-components/CreditsShelf/ProductCard.js +2 -0
- package/dist/cjs/biz-components/CreditsShelf/ProductCard.js.map +7 -0
- package/dist/cjs/biz-components/CreditsShelf/ProductsList.d.ts +20 -0
- package/dist/cjs/biz-components/CreditsShelf/ProductsList.js +2 -0
- package/dist/cjs/biz-components/CreditsShelf/ProductsList.js.map +7 -0
- package/dist/cjs/biz-components/CreditsShelf/Root.d.ts +43 -0
- package/dist/cjs/biz-components/CreditsShelf/Root.js +2 -0
- package/dist/cjs/biz-components/CreditsShelf/Root.js.map +7 -0
- package/dist/cjs/biz-components/CreditsShelf/context.d.ts +40 -0
- package/dist/cjs/biz-components/CreditsShelf/context.js +2 -0
- package/dist/cjs/biz-components/CreditsShelf/context.js.map +7 -0
- package/dist/cjs/biz-components/CreditsShelf/index.d.ts +15 -0
- package/dist/cjs/biz-components/CreditsShelf/index.js +2 -0
- package/dist/cjs/biz-components/CreditsShelf/index.js.map +7 -0
- package/dist/cjs/biz-components/CreditsShelf/types.d.ts +73 -0
- package/dist/cjs/biz-components/CreditsShelf/types.js +2 -0
- package/dist/cjs/biz-components/CreditsShelf/types.js.map +7 -0
- package/dist/cjs/biz-components/ImageOverlayShelf/ProductCard.js +1 -1
- package/dist/cjs/biz-components/ImageOverlayShelf/ProductCard.js.map +2 -2
- package/dist/cjs/biz-components/MediaPlayerBase/index.js +1 -1
- package/dist/cjs/biz-components/MediaPlayerBase/index.js.map +2 -2
- package/dist/cjs/biz-components/MediaShelf/ProductCard.js +1 -1
- package/dist/cjs/biz-components/MediaShelf/ProductCard.js.map +2 -2
- package/dist/cjs/biz-components/MiniCart/CircleProgress.d.ts +38 -0
- package/dist/cjs/biz-components/MiniCart/CircleProgress.js +2 -0
- package/dist/cjs/biz-components/MiniCart/CircleProgress.js.map +7 -0
- package/dist/cjs/biz-components/MiniCart/MiniCartDialog.js +1 -1
- package/dist/cjs/biz-components/MiniCart/MiniCartDialog.js.map +1 -1
- package/dist/cjs/biz-components/MiniCart/index.d.ts +31 -1
- package/dist/cjs/biz-components/MiniCart/index.js +1 -1
- package/dist/cjs/biz-components/MiniCart/index.js.map +3 -3
- package/dist/cjs/biz-components/SceneShelf/Footer.d.ts +21 -0
- package/dist/cjs/biz-components/SceneShelf/Footer.js +2 -0
- package/dist/cjs/biz-components/SceneShelf/Footer.js.map +7 -0
- package/dist/cjs/biz-components/SceneShelf/ProductCard.d.ts +23 -0
- package/dist/cjs/biz-components/SceneShelf/ProductCard.js +2 -0
- package/dist/cjs/biz-components/SceneShelf/ProductCard.js.map +7 -0
- package/dist/cjs/biz-components/SceneShelf/ProductsPanel.d.ts +26 -0
- package/dist/cjs/biz-components/SceneShelf/ProductsPanel.js +2 -0
- package/dist/cjs/biz-components/SceneShelf/ProductsPanel.js.map +7 -0
- package/dist/cjs/biz-components/SceneShelf/Root.d.ts +20 -0
- package/dist/cjs/biz-components/SceneShelf/Root.js +2 -0
- package/dist/cjs/biz-components/SceneShelf/Root.js.map +7 -0
- package/dist/cjs/biz-components/SceneShelf/Scene.d.ts +38 -0
- package/dist/cjs/biz-components/SceneShelf/Scene.js +2 -0
- package/dist/cjs/biz-components/SceneShelf/Scene.js.map +7 -0
- package/dist/cjs/biz-components/SceneShelf/SceneImage.d.ts +14 -0
- package/dist/cjs/biz-components/SceneShelf/SceneImage.js +2 -0
- package/dist/cjs/biz-components/SceneShelf/SceneImage.js.map +7 -0
- package/dist/cjs/biz-components/SceneShelf/context.d.ts +40 -0
- package/dist/cjs/biz-components/SceneShelf/context.js +2 -0
- package/dist/cjs/biz-components/SceneShelf/context.js.map +7 -0
- package/dist/cjs/biz-components/SceneShelf/index.d.ts +21 -0
- package/dist/cjs/biz-components/SceneShelf/index.js +2 -0
- package/dist/cjs/biz-components/SceneShelf/index.js.map +7 -0
- package/dist/cjs/biz-components/SceneShelf/types.d.ts +51 -0
- package/dist/cjs/biz-components/SceneShelf/types.js +2 -0
- package/dist/cjs/biz-components/SceneShelf/types.js.map +7 -0
- package/dist/cjs/biz-components/SecondaryBanner/index.d.ts +25 -0
- package/dist/cjs/biz-components/SecondaryBanner/index.js +1 -1
- package/dist/cjs/biz-components/SecondaryBanner/index.js.map +3 -3
- package/dist/cjs/biz-components/index.d.ts +7 -1
- package/dist/cjs/biz-components/index.js +1 -1
- package/dist/cjs/biz-components/index.js.map +3 -3
- package/dist/cjs/components/Countdown.js +1 -1
- package/dist/cjs/components/Countdown.js.map +2 -2
- package/dist/cjs/components/button.js +1 -1
- package/dist/cjs/components/button.js.map +2 -2
- package/dist/cjs/components/checkbox.js +1 -1
- package/dist/cjs/components/checkbox.js.map +2 -2
- package/dist/cjs/components/text.js +1 -1
- package/dist/cjs/components/text.js.map +2 -2
- package/dist/esm/biz-components/ActiveShelf/ProductCard.d.ts +1 -1
- package/dist/esm/biz-components/ActiveShelf/ProductCard.js +1 -1
- package/dist/esm/biz-components/ActiveShelf/ProductCard.js.map +2 -2
- package/dist/esm/biz-components/ActiveShelf/index.js +1 -1
- package/dist/esm/biz-components/ActiveShelf/index.js.map +2 -2
- package/dist/esm/biz-components/BuyOneGetOneShelf/FreeGiftItem.js +1 -1
- package/dist/esm/biz-components/BuyOneGetOneShelf/FreeGiftItem.js.map +2 -2
- package/dist/esm/biz-components/BuyOneGetOneShelf/ProductCard.js +1 -1
- package/dist/esm/biz-components/BuyOneGetOneShelf/ProductCard.js.map +2 -2
- package/dist/esm/biz-components/BuyOneGetOneShelf/index.js +1 -1
- package/dist/esm/biz-components/BuyOneGetOneShelf/index.js.map +2 -2
- package/dist/esm/biz-components/Category/SwiperCategory.d.ts +2 -0
- package/dist/esm/biz-components/Category/SwiperCategory.js +1 -1
- package/dist/esm/biz-components/Category/SwiperCategory.js.map +3 -3
- package/dist/esm/biz-components/Category/index.js +1 -1
- package/dist/esm/biz-components/Category/index.js.map +3 -3
- package/dist/esm/biz-components/CreditsShelf/ProductCard.d.ts +41 -0
- package/dist/esm/biz-components/CreditsShelf/ProductCard.js +2 -0
- package/dist/esm/biz-components/CreditsShelf/ProductCard.js.map +7 -0
- package/dist/esm/biz-components/CreditsShelf/ProductsList.d.ts +20 -0
- package/dist/esm/biz-components/CreditsShelf/ProductsList.js +2 -0
- package/dist/esm/biz-components/CreditsShelf/ProductsList.js.map +7 -0
- package/dist/esm/biz-components/CreditsShelf/Root.d.ts +43 -0
- package/dist/esm/biz-components/CreditsShelf/Root.js +2 -0
- package/dist/esm/biz-components/CreditsShelf/Root.js.map +7 -0
- package/dist/esm/biz-components/CreditsShelf/context.d.ts +40 -0
- package/dist/esm/biz-components/CreditsShelf/context.js +2 -0
- package/dist/esm/biz-components/CreditsShelf/context.js.map +7 -0
- package/dist/esm/biz-components/CreditsShelf/index.d.ts +15 -0
- package/dist/esm/biz-components/CreditsShelf/index.js +2 -0
- package/dist/esm/biz-components/CreditsShelf/index.js.map +7 -0
- package/dist/esm/biz-components/CreditsShelf/types.d.ts +73 -0
- package/dist/esm/biz-components/CreditsShelf/types.js +2 -0
- package/dist/esm/biz-components/CreditsShelf/types.js.map +7 -0
- package/dist/esm/biz-components/ImageOverlayShelf/ProductCard.js +1 -1
- package/dist/esm/biz-components/ImageOverlayShelf/ProductCard.js.map +2 -2
- package/dist/esm/biz-components/MediaPlayerBase/index.js +1 -1
- package/dist/esm/biz-components/MediaPlayerBase/index.js.map +2 -2
- package/dist/esm/biz-components/MediaShelf/ProductCard.js +1 -1
- package/dist/esm/biz-components/MediaShelf/ProductCard.js.map +2 -2
- package/dist/esm/biz-components/MiniCart/CircleProgress.d.ts +38 -0
- package/dist/esm/biz-components/MiniCart/CircleProgress.js +2 -0
- package/dist/esm/biz-components/MiniCart/CircleProgress.js.map +7 -0
- package/dist/esm/biz-components/MiniCart/MiniCartDialog.js +1 -1
- package/dist/esm/biz-components/MiniCart/MiniCartDialog.js.map +1 -1
- package/dist/esm/biz-components/MiniCart/index.d.ts +31 -1
- package/dist/esm/biz-components/MiniCart/index.js +1 -1
- package/dist/esm/biz-components/MiniCart/index.js.map +3 -3
- package/dist/esm/biz-components/SceneShelf/Footer.d.ts +21 -0
- package/dist/esm/biz-components/SceneShelf/Footer.js +2 -0
- package/dist/esm/biz-components/SceneShelf/Footer.js.map +7 -0
- package/dist/esm/biz-components/SceneShelf/ProductCard.d.ts +23 -0
- package/dist/esm/biz-components/SceneShelf/ProductCard.js +2 -0
- package/dist/esm/biz-components/SceneShelf/ProductCard.js.map +7 -0
- package/dist/esm/biz-components/SceneShelf/ProductsPanel.d.ts +26 -0
- package/dist/esm/biz-components/SceneShelf/ProductsPanel.js +2 -0
- package/dist/esm/biz-components/SceneShelf/ProductsPanel.js.map +7 -0
- package/dist/esm/biz-components/SceneShelf/Root.d.ts +20 -0
- package/dist/esm/biz-components/SceneShelf/Root.js +2 -0
- package/dist/esm/biz-components/SceneShelf/Root.js.map +7 -0
- package/dist/esm/biz-components/SceneShelf/Scene.d.ts +38 -0
- package/dist/esm/biz-components/SceneShelf/Scene.js +2 -0
- package/dist/esm/biz-components/SceneShelf/Scene.js.map +7 -0
- package/dist/esm/biz-components/SceneShelf/SceneImage.d.ts +14 -0
- package/dist/esm/biz-components/SceneShelf/SceneImage.js +2 -0
- package/dist/esm/biz-components/SceneShelf/SceneImage.js.map +7 -0
- package/dist/esm/biz-components/SceneShelf/context.d.ts +40 -0
- package/dist/esm/biz-components/SceneShelf/context.js +2 -0
- package/dist/esm/biz-components/SceneShelf/context.js.map +7 -0
- package/dist/esm/biz-components/SceneShelf/index.d.ts +21 -0
- package/dist/esm/biz-components/SceneShelf/index.js +2 -0
- package/dist/esm/biz-components/SceneShelf/index.js.map +7 -0
- package/dist/esm/biz-components/SceneShelf/types.d.ts +51 -0
- package/dist/esm/biz-components/SceneShelf/types.js +2 -0
- package/dist/esm/biz-components/SceneShelf/types.js.map +7 -0
- package/dist/esm/biz-components/SecondaryBanner/index.d.ts +25 -0
- package/dist/esm/biz-components/SecondaryBanner/index.js +1 -1
- package/dist/esm/biz-components/SecondaryBanner/index.js.map +3 -3
- package/dist/esm/biz-components/index.d.ts +7 -1
- package/dist/esm/biz-components/index.js +1 -1
- package/dist/esm/biz-components/index.js.map +3 -3
- package/dist/esm/components/Countdown.js +1 -1
- package/dist/esm/components/Countdown.js.map +2 -2
- package/dist/esm/components/button.js +1 -1
- package/dist/esm/components/button.js.map +2 -2
- package/dist/esm/components/checkbox.js +1 -1
- package/dist/esm/components/checkbox.js.map +2 -2
- package/dist/esm/components/text.js +1 -1
- package/dist/esm/components/text.js.map +2 -2
- package/dist/tokens/anker.css +1 -0
- package/dist/tokens/base.css +1 -0
- package/dist/tokens/eufy.css +1 -0
- package/dist/tokens/eufyMake.css +1 -0
- package/dist/tokens/solix.css +1 -0
- package/dist/tokens/soundcore.css +1 -0
- package/package.json +1 -1
- package/style.css +20 -3
- package/tailwind.config.js +1 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/biz-components/MiniCart/CircleProgress.tsx"],
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport type { Img } from '../../types/props.js'\nimport { Picture, Text } from '../../components/index.js'\nimport { cn } from '../../helpers/index.js'\n\nexport interface CircleProgressProps {\n /** \u603B\u9636\u6BB5\u6570 (1-4) */\n totalSteps?: 1 | 2 | 3 | 4\n /** \u5F53\u524D\u5B8C\u6210\u7684\u9636\u6BB5 (0 \u5230 totalSteps) */\n currentStep?: number\n /** \u4E2D\u95F4\u663E\u793A\u7684\u56FE\u7247 */\n image?: Img\n /** \u5E95\u90E8\u663E\u793A\u7684\u6587\u6848 */\n label?: string\n /** \u8FDB\u5EA6\u6761\u989C\u8272\uFF0C\u9ED8\u8BA4\u4E3A\u54C1\u724C\u8272 */\n progressColor?: string\n /** \u5E95\u90E8\u6587\u6848\u80CC\u666F\u8272\uFF0C\u9ED8\u8BA4\u4E3A\u54C1\u724C\u8425\u9500\u8272 */\n labelColor?: string\n /** \u672A\u5B8C\u6210\u9636\u6BB5\u7684\u989C\u8272 */\n trackColor?: string\n /** \u80CC\u666F\u989C\u8272\uFF0C\u9ED8\u8BA4\u4E3A\u5BB9\u5668\u80CC\u666F\u8272 */\n backgroundColor?: string\n /** \u79FB\u52A8\u7AEF\u7EC4\u4EF6\u5C3A\u5BF8\uFF0C\u9ED8\u8BA4 64 */\n size?: number\n /** laptop \u4EE5\u4E0A\u7EC4\u4EF6\u5C3A\u5BF8\uFF0C\u9ED8\u8BA4 80 */\n laptopSize?: number\n /** \u6BB5\u4E4B\u95F4\u7684\u95F4\u9699\uFF08\u50CF\u7D20\uFF09\uFF0C\u9ED8\u8BA4 3 */\n gap?: number\n /** \u81EA\u5B9A\u4E49\u7C7B\u540D */\n className?: string\n}\n\n/**\n * \u5206\u6BB5\u5F0F\u5706\u5F62\u8FDB\u5EA6\u6761\u7EC4\u4EF6\n * \u7528\u4E8E MiniCart \u5DE6\u4FA7\u663E\u793A\u9636\u6BB5\u6027\u8FDB\u5EA6\uFF0C\u652F\u6301 1-4 \u4E2A\u9636\u6BB5\u914D\u7F6E\n * \u6BCF\u4E2A\u9636\u6BB5\u662F\u72EC\u7ACB\u7684\u5F27\u6BB5\uFF0C\u4E2D\u95F4\u6709\u95F4\u9699\n * \u79FB\u52A8\u7AEF\u9ED8\u8BA4 64px\uFF0Claptop \u4EE5\u4E0A\u9ED8\u8BA4 80px\n */\nconst CircleProgress = ({\n totalSteps = 4,\n currentStep = 0,\n image,\n label,\n progressColor = 'var(--brand-color-0)',\n labelColor = 'var(--marketing-color-1)',\n trackColor = '#DADCE0',\n backgroundColor = '#EAEAEC',\n size = 64,\n laptopSize = 96,\n gap = 3,\n className,\n}: CircleProgressProps) => {\n // \u4F7F\u7528\u8F83\u5927\u5C3A\u5BF8\u8BA1\u7B97 SVG \u53C2\u6570\uFF0C\u786E\u4FDD\u5728\u6240\u6709\u5C3A\u5BF8\u4E0B\u90FD\u6E05\u6670\n const maxSize = Math.max(size, laptopSize) // \u5982\u679C\u6709\u6807\u7B7E\uFF0C\u9884\u7559\u5E95\u90E8\u7A7A\u95F4\n const strokeWidth = 6\n const radius = (maxSize - strokeWidth) / 2\n const center = maxSize / 2\n\n // \u751F\u6210\u6240\u6709\u5206\u6BB5\n const segments = React.useMemo(() => {\n // \u89C6\u89C9\u95F4\u9699\u9700\u8981\u52A0\u4E0A\u4E24\u7AEF\u5706\u89D2\u5E3D\u5B50\u7684\u5BBD\u5EA6\uFF08strokeLinecap=\"round\" \u4F1A\u5EF6\u4F38 strokeWidth/2\uFF09\n const actualGap = gap + strokeWidth\n // \u5C06\u50CF\u7D20\u95F4\u9699\u8F6C\u6362\u4E3A\u89D2\u5EA6\uFF08\u5F27\u5EA6 = \u5F27\u957F / \u534A\u5F84\uFF0C\u518D\u8F6C\u4E3A\u5EA6\uFF09\n const gapAngle = (actualGap / radius) * (180 / Math.PI)\n const totalGapAngle = gapAngle * totalSteps\n const availableAngle = 360 - totalGapAngle\n const segmentAngle = availableAngle / totalSteps\n\n // \u5C06\u89D2\u5EA6\u8F6C\u6362\u4E3A\u5F27\u5EA6\n const toRadians = (degrees: number) => (degrees * Math.PI) / 180\n\n // \u8BA1\u7B97\u5F27\u6BB5\u7684\u8D77\u70B9\u548C\u7EC8\u70B9\u5750\u6807\n const getArcPath = (startAngle: number, endAngle: number) => {\n // \u4ECE\u9876\u90E8\u5F00\u59CB\uFF08-90\u5EA6\uFF09\uFF0C\u987A\u65F6\u9488\u65B9\u5411\n const adjustedStart = startAngle - 90\n const adjustedEnd = endAngle - 90\n\n const startX = center + radius * Math.cos(toRadians(adjustedStart))\n const startY = center + radius * Math.sin(toRadians(adjustedStart))\n const endX = center + radius * Math.cos(toRadians(adjustedEnd))\n const endY = center + radius * Math.sin(toRadians(adjustedEnd))\n\n // \u5224\u65AD\u662F\u5426\u4E3A\u5927\u5F27\uFF08\u8D85\u8FC7180\u5EA6\uFF09\n const largeArcFlag = endAngle - startAngle > 180 ? 1 : 0\n\n return `M ${startX} ${startY} A ${radius} ${radius} 0 ${largeArcFlag} 1 ${endX} ${endY}`\n }\n\n const result = []\n // totalSteps = 2 \u65F6\uFF0C\u8D77\u59CB\u4F4D\u7F6E\u9006\u65F6\u9488\u504F\u79FB 45 \u5EA6\uFF0C\u8BA9\u65AD\u5F00\u4F4D\u7F6E\u5728\u5DE6\u4E0A\u548C\u53F3\u4E0B\n const startOffset = totalSteps === 2 ? -45 : 0\n let currentAngle = startOffset\n\n for (let i = 0; i < totalSteps; i++) {\n const startAngle = currentAngle + gapAngle / 2\n const endAngle = startAngle + segmentAngle\n const isCompleted = i < currentStep\n\n result.push({\n path: getArcPath(startAngle, endAngle),\n isCompleted,\n index: i,\n })\n\n currentAngle = endAngle + gapAngle / 2\n }\n\n return result\n }, [totalSteps, currentStep, gap, radius, center])\n\n return (\n <div\n className={cn(\n 'relative inline-flex shrink-0 flex-col items-center',\n 'laptop:w-[--circle-laptop-size] w-[--circle-size]',\n 'laptop:h-[--circle-laptop-height] h-[--circle-height]',\n className\n )}\n style={\n {\n '--circle-size': `${size}px`,\n '--circle-laptop-size': `${laptopSize}px`,\n '--circle-height': `${label ? size + 8 : size}px`,\n '--circle-laptop-height': `${label ? laptopSize + 8 : laptopSize}px`,\n } as React.CSSProperties\n }\n >\n {/* \u8FDB\u5EA6\u6761\u5706\u73AF */}\n <div className=\"laptop:size-[--circle-laptop-size] relative size-[--circle-size]\">\n <svg\n viewBox={`0 0 ${maxSize} ${maxSize}`}\n className={cn('absolute inset-0 size-full', label ? 'translate-y-[-8px]' : '')}\n >\n {/* \u80CC\u666F\u5706\u5F62 */}\n <circle cx={center} cy={center} r={radius} fill={backgroundColor} stroke=\"none\" />\n\n {/* \u5206\u6BB5\u5F27 */}\n {segments.map(segment => (\n <path\n key={segment.index}\n d={segment.path}\n fill=\"none\"\n stroke={segment.isCompleted ? progressColor : trackColor}\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n style={{\n transition: 'stroke 0.3s ease-in-out',\n }}\n />\n ))}\n </svg>\n\n {/* \u4E2D\u95F4\u5185\u5BB9\u533A\u57DF */}\n <div\n className={cn('absolute inset-[10px] flex items-center justify-center', label ? 'translate-y-[-8px]' : '')}\n >\n <div\n className=\"flex size-full items-center justify-center overflow-hidden rounded-full\"\n style={{ backgroundColor }}\n >\n {image?.url && (\n <Picture className=\"size-full\" imgClassName=\"object-contain\" source={image.url} alt={image.alt || ''} />\n )}\n </div>\n </div>\n </div>\n\n {/* \u5E95\u90E8\u6587\u6848 - \u548C\u5706\u5F62\u5E95\u90E8\u91CD\u53E0 */}\n {label && (\n <div\n className=\"absolute bottom-0 left-1/2 flex -translate-x-1/2 items-center justify-center rounded-full px-2 py-0.5\"\n style={{ backgroundColor: labelColor }}\n >\n <Text className=\"text-xs font-medium text-white\" html={label} />\n </div>\n )}\n </div>\n )\n}\n\nCircleProgress.displayName = 'CircleProgress'\n\nexport default CircleProgress\n"],
|
|
5
|
+
"mappings": "aAmIQ,OAKE,OAAAA,EALF,QAAAC,MAAA,oBAjIR,UAAYC,MAAW,QAEvB,OAAS,WAAAC,EAAS,QAAAC,MAAY,4BAC9B,OAAS,MAAAC,MAAU,yBAmCnB,MAAMC,EAAiB,CAAC,CACtB,WAAAC,EAAa,EACb,YAAAC,EAAc,EACd,MAAAC,EACA,MAAAC,EACA,cAAAC,EAAgB,uBAChB,WAAAC,EAAa,2BACb,WAAAC,EAAa,UACb,gBAAAC,EAAkB,UAClB,KAAAC,EAAO,GACP,WAAAC,EAAa,GACb,IAAAC,EAAM,EACN,UAAAC,CACF,IAA2B,CAEzB,MAAMC,EAAU,KAAK,IAAIJ,EAAMC,CAAU,EACnCI,EAAc,EACdC,GAAUF,EAAUC,GAAe,EACnCE,EAASH,EAAU,EAGnBI,EAAWrB,EAAM,QAAQ,IAAM,CAInC,MAAMsB,GAFYP,EAAMG,GAEMC,GAAW,IAAM,KAAK,IAG9CI,GADiB,IADDD,EAAWjB,GAEKA,EAGhCmB,EAAaC,GAAqBA,EAAU,KAAK,GAAM,IAGvDC,EAAa,CAACC,EAAoBC,IAAqB,CAE3D,MAAMC,EAAgBF,EAAa,GAC7BG,EAAcF,EAAW,GAEzBG,EAASX,EAASD,EAAS,KAAK,IAAIK,EAAUK,CAAa,CAAC,EAC5DG,EAASZ,EAASD,EAAS,KAAK,IAAIK,EAAUK,CAAa,CAAC,EAC5DI,EAAOb,EAASD,EAAS,KAAK,IAAIK,EAAUM,CAAW,CAAC,EACxDI,EAAOd,EAASD,EAAS,KAAK,IAAIK,EAAUM,CAAW,CAAC,EAGxDK,EAAeP,EAAWD,EAAa,IAAM,EAAI,EAEvD,MAAO,KAAKI,CAAM,IAAIC,CAAM,MAAMb,CAAM,IAAIA,CAAM,MAAMgB,CAAY,MAAMF,CAAI,IAAIC,CAAI,EACxF,EAEME,EAAS,CAAC,EAGhB,IAAIC,EADgBhC,IAAe,EAAI,IAAM,EAG7C,QAASiC,EAAI,EAAGA,EAAIjC,EAAYiC,IAAK,CACnC,MAAMX,EAAaU,EAAef,EAAW,EACvCM,EAAWD,EAAaJ,EACxBgB,EAAcD,EAAIhC,EAExB8B,EAAO,KAAK,CACV,KAAMV,EAAWC,EAAYC,CAAQ,EACrC,YAAAW,EACA,MAAOD,CACT,CAAC,EAEDD,EAAeT,EAAWN,EAAW,CACvC,CAEA,OAAOc,CACT,EAAG,CAAC/B,EAAYC,EAAaS,EAAKI,EAAQC,CAAM,CAAC,EAEjD,OACErB,EAAC,OACC,UAAWI,EACT,sDACA,oDACA,wDACAa,CACF,EACA,MACE,CACE,gBAAiB,GAAGH,CAAI,KACxB,uBAAwB,GAAGC,CAAU,KACrC,kBAAmB,GAAGN,EAAQK,EAAO,EAAIA,CAAI,KAC7C,yBAA0B,GAAGL,EAAQM,EAAa,EAAIA,CAAU,IAClE,EAIF,UAAAf,EAAC,OAAI,UAAU,mEACb,UAAAA,EAAC,OACC,QAAS,OAAOkB,CAAO,IAAIA,CAAO,GAClC,UAAWd,EAAG,6BAA8BK,EAAQ,qBAAuB,EAAE,EAG7E,UAAAV,EAAC,UAAO,GAAIsB,EAAQ,GAAIA,EAAQ,EAAGD,EAAQ,KAAMP,EAAiB,OAAO,OAAO,EAG/ES,EAAS,IAAImB,GACZ1C,EAAC,QAEC,EAAG0C,EAAQ,KACX,KAAK,OACL,OAAQA,EAAQ,YAAc/B,EAAgBE,EAC9C,YAAaO,EACb,cAAc,QACd,MAAO,CACL,WAAY,yBACd,GARKsB,EAAQ,KASf,CACD,GACH,EAGA1C,EAAC,OACC,UAAWK,EAAG,yDAA0DK,EAAQ,qBAAuB,EAAE,EAEzG,SAAAV,EAAC,OACC,UAAU,0EACV,MAAO,CAAE,gBAAAc,CAAgB,EAExB,SAAAL,GAAO,KACNT,EAACG,EAAA,CAAQ,UAAU,YAAY,aAAa,iBAAiB,OAAQM,EAAM,IAAK,IAAKA,EAAM,KAAO,GAAI,EAE1G,EACF,GACF,EAGCC,GACCV,EAAC,OACC,UAAU,wGACV,MAAO,CAAE,gBAAiBY,CAAW,EAErC,SAAAZ,EAACI,EAAA,CAAK,UAAU,iCAAiC,KAAMM,EAAO,EAChE,GAEJ,CAEJ,EAEAJ,EAAe,YAAc,iBAE7B,IAAOqC,EAAQrC",
|
|
6
|
+
"names": ["jsx", "jsxs", "React", "Picture", "Text", "cn", "CircleProgress", "totalSteps", "currentStep", "image", "label", "progressColor", "labelColor", "trackColor", "backgroundColor", "size", "laptopSize", "gap", "className", "maxSize", "strokeWidth", "radius", "center", "segments", "gapAngle", "segmentAngle", "toRadians", "degrees", "getArcPath", "startAngle", "endAngle", "adjustedStart", "adjustedEnd", "startX", "startY", "endX", "endY", "largeArcFlag", "result", "currentAngle", "i", "isCompleted", "segment", "CircleProgress_default"]
|
|
7
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{jsx as t,jsxs as p}from"react/jsx-runtime";import{cn as e}from"../../helpers/index.js";import{Heading as w,Text as f,Dialog as D,DialogContent as I,DialogHeader as N,DialogTitle as z}from"../../components/index.js";const P=({className:r})=>t("svg",{className:r,width:"12",height:"12",viewBox:"0 0 12 12",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M2 6H10",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})}),T=({className:r})=>t("svg",{className:r,width:"12",height:"12",viewBox:"0 0 12 12",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M6 2V10M2 6H10",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})}),k=({item:r,classNames:a,onIncrease:d,onDecrease:x})=>{const{merchandise:o,quantity:u,cost:y}=r,{image:l,title:b}=o,{totalAmount:c,subtotalAmount:s}=y,m=b||o.sku||"Product",g=c?.formattedPrice||"",v=s&&c&&parseFloat(s.amount)>parseFloat(c.amount);return p("div",{className:e("bg-container-primary rounded-box flex items-center gap-2 px-2 py-4","laptop:bg-container-primary laptop:gap-4 laptop:p-4",a?.item),children:[t("div",{className:e("rounded-box relative size-16 shrink-0 overflow-hidden","laptop:size-20",a?.itemImage),children:l?.url&&t("img",{src:l.url,alt:l.altText||m,className:"size-full object-cover"})}),p("div",{className:e("laptop:gap-4 flex flex-1 flex-col gap-2",a?.itemInfo),children:[t(f,{as:"p",size:3,className:e("text-info-primary laptop:text-[16px] line-clamp-2 text-[14px]",a?.itemTitle),children:m}),p("div",{className:"laptop:flex-row laptop:items-center laptop:justify-between flex flex-col items-start gap-1",children:[p("div",{className:e("flex items-center gap-1",a?.itemPrice),children:[g&&t(f,{size:4,className:e("text-info-primary laptop:text-[18px] text-[16px]",a?.itemCurrentPrice),children:g}),v&&s?.formattedPrice&&t(f,{size:4,className:e("text-info-tertiary laptop:text-[18px] text-[16px] line-through",a?.itemOriginalPrice),children:s.formattedPrice})]}),p("div",{className:e("flex items-center",a?.quantityControl),children:[t("button",{type:"button",onClick:x,disabled:u<=0,className:e("border-lines flex size-8 items-center justify-center border","laptop:size-10","text-info-primary hover:bg-container-secondary-0 transition-colors","disabled:cursor-not-allowed disabled:opacity-50",a?.quantityButton),"aria-label":"Decrease quantity",children:t(P,{className:"laptop:size-3 size-[10.67px]"})}),t("div",{className:e("border-lines text-info-primary flex size-8 items-center justify-center border-y text-center text-sm font-semibold","laptop:size-10 laptop:text-base",a?.quantityValue),children:u}),t("button",{type:"button",onClick:d,className:e("border-lines flex size-8 items-center justify-center border","laptop:size-10","text-info-primary hover:bg-container-secondary-0 transition-colors",a?.quantityButton),"aria-label":"Increase quantity",children:t(T,{className:"laptop:size-3 size-[10.67px]"})})]})]})]})]})},h=({open:r,onOpenChange:a,cart:d,copy:x,classNames:o={},onIncreaseQuantity:u,onDecreaseQuantity:y,onQuantityChange:l})=>{const b=x?.title||"Selected ({count})",c=x?.emptyText||"Your cart is empty",s=d?.lineItems?.reduce((i,n)=>i+(n?.quantity||0),0)||0,m=d?.lineItems||[],g=m.length===0,v=(i,n)=>{u?.(i,n),l?.(i,n+1)},C=(i,n)=>{n>
|
|
1
|
+
"use client";import{jsx as t,jsxs as p}from"react/jsx-runtime";import{cn as e}from"../../helpers/index.js";import{Heading as w,Text as f,Dialog as D,DialogContent as I,DialogHeader as N,DialogTitle as z}from"../../components/index.js";const P=({className:r})=>t("svg",{className:r,width:"12",height:"12",viewBox:"0 0 12 12",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M2 6H10",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})}),T=({className:r})=>t("svg",{className:r,width:"12",height:"12",viewBox:"0 0 12 12",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M6 2V10M2 6H10",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})}),k=({item:r,classNames:a,onIncrease:d,onDecrease:x})=>{const{merchandise:o,quantity:u,cost:y}=r,{image:l,title:b}=o,{totalAmount:c,subtotalAmount:s}=y,m=b||o.sku||"Product",g=c?.formattedPrice||"",v=s&&c&&parseFloat(s.amount)>parseFloat(c.amount);return p("div",{className:e("bg-container-primary rounded-box flex items-center gap-2 px-2 py-4","laptop:bg-container-primary laptop:gap-4 laptop:p-4",a?.item),children:[t("div",{className:e("rounded-box relative size-16 shrink-0 overflow-hidden","laptop:size-20",a?.itemImage),children:l?.url&&t("img",{src:l.url,alt:l.altText||m,className:"size-full object-cover"})}),p("div",{className:e("laptop:gap-4 flex flex-1 flex-col gap-2",a?.itemInfo),children:[t(f,{as:"p",size:3,className:e("text-info-primary laptop:text-[16px] line-clamp-2 text-[14px]",a?.itemTitle),children:m}),p("div",{className:"laptop:flex-row laptop:items-center laptop:justify-between flex flex-col items-start gap-1",children:[p("div",{className:e("flex items-center gap-1",a?.itemPrice),children:[g&&t(f,{size:4,className:e("text-info-primary laptop:text-[18px] text-[16px]",a?.itemCurrentPrice),children:g}),v&&s?.formattedPrice&&t(f,{size:4,className:e("text-info-tertiary laptop:text-[18px] text-[16px] line-through",a?.itemOriginalPrice),children:s.formattedPrice})]}),p("div",{className:e("flex items-center",a?.quantityControl),children:[t("button",{type:"button",onClick:x,disabled:u<=0,className:e("border-lines flex size-8 items-center justify-center border","laptop:size-10","text-info-primary hover:bg-container-secondary-0 transition-colors","disabled:cursor-not-allowed disabled:opacity-50",a?.quantityButton),"aria-label":"Decrease quantity",children:t(P,{className:"laptop:size-3 size-[10.67px]"})}),t("div",{className:e("border-lines text-info-primary flex size-8 items-center justify-center border-y text-center text-sm font-semibold","laptop:size-10 laptop:text-base",a?.quantityValue),children:u}),t("button",{type:"button",onClick:d,className:e("border-lines flex size-8 items-center justify-center border","laptop:size-10","text-info-primary hover:bg-container-secondary-0 transition-colors",a?.quantityButton),"aria-label":"Increase quantity",children:t(T,{className:"laptop:size-3 size-[10.67px]"})})]})]})]})]})},h=({open:r,onOpenChange:a,cart:d,copy:x,classNames:o={},onIncreaseQuantity:u,onDecreaseQuantity:y,onQuantityChange:l})=>{const b=x?.title||"Selected ({count})",c=x?.emptyText||"Your cart is empty",s=d?.lineItems?.reduce((i,n)=>i+(n?.quantity||0),0)||0,m=d?.lineItems||[],g=m.length===0,v=(i,n)=>{u?.(i,n),l?.(i,n+1)},C=(i,n)=>{n>0&&(y?.(i,n),l?.(i,n-1))};return t(D,{open:r,onOpenChange:a,children:p(I,{className:e("bg-container-secondary-0 fixed left-1/2 top-1/2 flex -translate-x-1/2 -translate-y-1/2 flex-col gap-0 overflow-hidden p-0","rounded-box max-h-[80vh] w-[calc(100%-64px)] min-w-[326px]","laptop:w-full laptop:max-w-[560px] laptop:rounded-box",o?.root),children:[t(N,{className:e("bg-container-secondary-0 flex flex-row items-start justify-between gap-4 px-4 pb-2 pt-4",o?.header),children:t(z,{asChild:!0,children:t(w,{as:"h3",size:2,className:e("text-info-primary font-bold",o?.title),children:b.replace("{count}",s.toString())})})}),t("div",{className:e("bg-container-secondary-0 h- flex flex-col gap-2 overflow-y-auto px-4 py-2",o?.content),children:g?t("div",{className:"flex items-center justify-center py-8",children:t(f,{size:2,className:"text-info-tertiary",children:c})}):t("div",{className:e("flex flex-col gap-2",o?.itemList),children:m.map(i=>t(k,{item:i,classNames:o,onIncrease:()=>v(i.id,i.quantity),onDecrease:()=>C(i.id,i.quantity)},i.id))})}),t("div",{className:"bg-container-secondary-0 h-8 w-full"})]})})};h.displayName="MiniCartDialog";var L=h;export{h as MiniCartDialog,L as default};
|
|
2
2
|
//# sourceMappingURL=MiniCartDialog.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/biz-components/MiniCart/MiniCartDialog.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport { cn } from '../../helpers/index.js'\nimport { Heading, Text, Dialog, DialogContent, DialogHeader, DialogTitle } from '../../components/index.js'\nimport type { CartLineItem, Cart } from './index.js'\n\n/**\n * \u8D2D\u7269\u8F66\u6570\u636E\u7C7B\u578B - \u590D\u7528 MiniCart \u7684\u7C7B\u578B\u5B9A\u4E49\n */\nexport interface CartData {\n id: string\n checkoutUrl: string\n lineItems: CartLineItem[]\n}\n\n// \u91CD\u65B0\u5BFC\u51FA\u7C7B\u578B\u4F9B\u5916\u90E8\u4F7F\u7528\nexport type { CartLineItem, Cart }\n\n/**\n * \u6587\u6848\u914D\u7F6E\n */\nexport interface MiniCartDialogCopy {\n /** \u6807\u9898\u6587\u6848\uFF0C{count} \u4F1A\u88AB\u66FF\u6362\u4E3A\u5546\u54C1\u6570\u91CF */\n title?: string\n /** \u7A7A\u8D2D\u7269\u8F66\u63D0\u793A */\n emptyText?: string\n}\n\nexport type MiniCartDialogSemanticName =\n | 'root'\n | 'header'\n | 'title'\n | 'content'\n | 'itemList'\n | 'item'\n | 'itemImage'\n | 'itemInfo'\n | 'itemTitle'\n | 'itemPrice'\n | 'itemCurrentPrice'\n | 'itemOriginalPrice'\n | 'quantityControl'\n | 'quantityButton'\n | 'quantityValue'\n\nexport interface MiniCartDialogProps {\n /** \u662F\u5426\u6253\u5F00\u5F39\u7A97 */\n open: boolean\n /** \u5173\u95ED\u5F39\u7A97\u56DE\u8C03 */\n onOpenChange: (open: boolean) => void\n /** \u8D2D\u7269\u8F66\u6570\u636E */\n cart: CartData\n /** \u6587\u6848\u914D\u7F6E */\n copy?: MiniCartDialogCopy\n /** \u5404\u90E8\u5206\u7684\u81EA\u5B9A\u4E49\u6837\u5F0F\u7C7B\u540D */\n classNames?: Partial<Record<MiniCartDialogSemanticName, string>>\n /**\n * \u589E\u52A0\u5546\u54C1\u6570\u91CF\u56DE\u8C03\n * @param lineItemId \u5546\u54C1\u884CID\n * @param currentQuantity \u5F53\u524D\u6570\u91CF\n */\n onIncreaseQuantity?: (lineItemId: string, currentQuantity: number) => void\n /**\n * \u51CF\u5C11\u5546\u54C1\u6570\u91CF\u56DE\u8C03\n * @param lineItemId \u5546\u54C1\u884CID\n * @param currentQuantity \u5F53\u524D\u6570\u91CF\n */\n onDecreaseQuantity?: (lineItemId: string, currentQuantity: number) => void\n /**\n * \u6570\u91CF\u53D8\u66F4\u56DE\u8C03\n * @param lineItemId \u5546\u54C1\u884CID\n * @param quantity \u65B0\u6570\u91CF\n */\n onQuantityChange?: (lineItemId: string, quantity: number) => void\n}\n\n/**\n * MinusIcon - \u51CF\u53F7\u56FE\u6807\n */\nconst MinusIcon = ({ className }: { className?: string }) => (\n <svg className={className} width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M2 6H10\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n)\n\n/**\n * PlusIcon - \u52A0\u53F7\u56FE\u6807\n */\nconst PlusIcon = ({ className }: { className?: string }) => (\n <svg className={className} width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 2V10M2 6H10\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n)\n\n/**\n * CartItem - \u8D2D\u7269\u8F66\u5546\u54C1\u9879\u7EC4\u4EF6\n */\ninterface CartItemProps {\n item: CartLineItem\n classNames?: Partial<Record<MiniCartDialogSemanticName, string>>\n onIncrease?: () => void\n onDecrease?: () => void\n}\n\nconst CartItem = ({ item, classNames, onIncrease, onDecrease }: CartItemProps) => {\n const { merchandise, quantity, cost } = item\n const { image, title } = merchandise\n const { totalAmount, subtotalAmount } = cost\n\n // \u663E\u793A\u6807\u9898\uFF08\u56DE\u9000\u5230 SKU\uFF09\n const displayTitle = title || merchandise.sku || 'Product'\n // \u663E\u793A\u4EF7\u683C\uFF08\u73B0\u4EF7 = totalAmount\uFF09\n const displayPrice = totalAmount?.formattedPrice || ''\n // \u662F\u5426\u6709\u6298\u6263\uFF08\u539F\u4EF7 subtotalAmount \u5927\u4E8E\u73B0\u4EF7 totalAmount\uFF09\n const hasDiscount =\n subtotalAmount && totalAmount && parseFloat(subtotalAmount.amount) > parseFloat(totalAmount.amount)\n\n return (\n <div\n className={cn(\n // \u79FB\u52A8\u7AEF\uFF1A\u7070\u8272\u80CC\u666F\uFF0C\u8F83\u5C0F\u95F4\u8DDD\n 'bg-container-primary rounded-box flex items-center gap-2 px-2 py-4',\n // \u684C\u9762\u7AEF\uFF1A\u767D\u8272\u80CC\u666F\uFF0C\u8F83\u5927\u95F4\u8DDD\n 'laptop:bg-container-primary laptop:gap-4 laptop:p-4',\n classNames?.item\n )}\n >\n {/* \u5546\u54C1\u56FE\u7247 - \u79FB\u52A8\u7AEF 64px\uFF0C\u684C\u9762\u7AEF 80px */}\n <div\n className={cn('rounded-box relative size-16 shrink-0 overflow-hidden', 'laptop:size-20', classNames?.itemImage)}\n >\n {image?.url && <img src={image.url} alt={image.altText || displayTitle} className=\"size-full object-cover\" />}\n </div>\n\n {/* \u5546\u54C1\u4FE1\u606F */}\n <div className={cn('laptop:gap-4 flex flex-1 flex-col gap-2', classNames?.itemInfo)}>\n {/* \u5546\u54C1\u540D\u79F0 - \u79FB\u52A8\u7AEF\u8F83\u5C0F\u5B57\u4F53 */}\n <Text\n as=\"p\"\n size={3}\n className={cn('text-info-primary laptop:text-[16px] line-clamp-2 text-[14px]', classNames?.itemTitle)}\n >\n {displayTitle}\n </Text>\n\n {/* \u4EF7\u683C\u548C\u6570\u91CF\u63A7\u5236 - \u79FB\u52A8\u7AEF\u5782\u76F4\u6392\u5217\uFF0C\u684C\u9762\u7AEF\u6C34\u5E73\u6392\u5217 */}\n <div className=\"laptop:flex-row laptop:items-center laptop:justify-between flex flex-col items-start gap-1\">\n {/* \u4EF7\u683C\u533A\u57DF */}\n <div className={cn('flex items-center gap-1', classNames?.itemPrice)}>\n {displayPrice && (\n <Text\n size={4}\n className={cn('text-info-primary laptop:text-[18px] text-[16px]', classNames?.itemCurrentPrice)}\n >\n {displayPrice}\n </Text>\n )}\n {hasDiscount && subtotalAmount?.formattedPrice && (\n <Text\n size={4}\n className={cn(\n 'text-info-tertiary laptop:text-[18px] text-[16px] line-through',\n classNames?.itemOriginalPrice\n )}\n >\n {subtotalAmount.formattedPrice}\n </Text>\n )}\n </div>\n\n {/* \u6570\u91CF\u63A7\u5236 - \u79FB\u52A8\u7AEF 32px \u6309\u94AE\uFF0C\u684C\u9762\u7AEF 40px \u6309\u94AE */}\n <div className={cn('flex items-center', classNames?.quantityControl)}>\n {/* \u51CF\u5C11\u6309\u94AE */}\n <button\n type=\"button\"\n onClick={onDecrease}\n disabled={quantity <= 0}\n className={cn(\n 'border-lines flex size-8 items-center justify-center border',\n 'laptop:size-10',\n 'text-info-primary hover:bg-container-secondary-0 transition-colors',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n classNames?.quantityButton\n )}\n aria-label=\"Decrease quantity\"\n >\n <MinusIcon className=\"laptop:size-3 size-[10.67px]\" />\n </button>\n\n {/* \u6570\u91CF\u663E\u793A */}\n <div\n className={cn(\n 'border-lines text-info-primary flex size-8 items-center justify-center border-y text-center text-sm font-semibold',\n 'laptop:size-10 laptop:text-base',\n classNames?.quantityValue\n )}\n >\n {quantity}\n </div>\n\n {/* \u589E\u52A0\u6309\u94AE */}\n <button\n type=\"button\"\n onClick={onIncrease}\n className={cn(\n 'border-lines flex size-8 items-center justify-center border',\n 'laptop:size-10',\n 'text-info-primary hover:bg-container-secondary-0 transition-colors',\n classNames?.quantityButton\n )}\n aria-label=\"Increase quantity\"\n >\n <PlusIcon className=\"laptop:size-3 size-[10.67px]\" />\n </button>\n </div>\n </div>\n </div>\n </div>\n )\n}\n\n/**\n * MiniCartDialog - \u8FF7\u4F60\u8D2D\u7269\u8F66\u5F39\u7A97\u7EC4\u4EF6\n *\n * @description \u7528\u4E8E\u5C55\u793A\u8D2D\u7269\u8F66\u5546\u54C1\u5217\u8868\uFF0C\u652F\u6301\u8C03\u6574\u5546\u54C1\u6570\u91CF\n */\nconst MiniCartDialog = ({\n open,\n onOpenChange,\n cart,\n copy,\n classNames = {},\n onIncreaseQuantity,\n onDecreaseQuantity,\n onQuantityChange,\n}: MiniCartDialogProps) => {\n // \u6587\u6848\u914D\u7F6E\n const titleText = copy?.title || 'Selected ({count})'\n const emptyText = copy?.emptyText || 'Your cart is empty'\n\n // \u8BA1\u7B97\u5546\u54C1\u603B\u6570\u91CF\n const totalQuantity = cart?.lineItems?.reduce((total, item) => total + (item?.quantity || 0), 0) || 0\n\n const items = cart?.lineItems || []\n const isEmpty = items.length === 0\n\n // \u5904\u7406\u6570\u91CF\u589E\u52A0\n const handleIncrease = (lineItemId: string, currentQuantity: number) => {\n onIncreaseQuantity?.(lineItemId, currentQuantity)\n onQuantityChange?.(lineItemId, currentQuantity + 1)\n }\n\n // \u5904\u7406\u6570\u91CF\u51CF\u5C11\n const handleDecrease = (lineItemId: string, currentQuantity: number) => {\n if (currentQuantity > 1) {\n onDecreaseQuantity?.(lineItemId, currentQuantity)\n onQuantityChange?.(lineItemId, currentQuantity - 1)\n }\n }\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent\n className={cn(\n // \u57FA\u7840\u6837\u5F0F + \u5C45\u4E2D\u5B9A\u4F4D\n 'bg-container-secondary-0 fixed left-1/2 top-1/2 flex -translate-x-1/2 -translate-y-1/2 flex-col gap-0 overflow-hidden p-0',\n // \u79FB\u52A8\u7AEF\uFF1A\u5C45\u4E2D\u5F39\u7A97\uFF0C\u6700\u5C0F\u5BBD\u5EA6326px\uFF0C\u5DE6\u53F3\u8DDD\u5C4F\u5E55\u8FB9\u7F1832px\n 'rounded-box max-h-[80vh] w-[calc(100%-64px)] min-w-[326px]',\n // \u684C\u9762\u7AEF\uFF1A\u6700\u5927\u5BBD\u5EA6560px\n 'laptop:w-full laptop:max-w-[560px] laptop:rounded-box',\n classNames?.root\n )}\n >\n {/* \u5934\u90E8 */}\n <DialogHeader\n className={cn(\n 'bg-container-secondary-0 flex flex-row items-start justify-between gap-4 px-4 pb-2 pt-4',\n classNames?.header\n )}\n >\n <DialogTitle asChild>\n <Heading as=\"h3\" size={2} className={cn('text-info-primary font-bold', classNames?.title)}>\n {titleText.replace('{count}', totalQuantity.toString())}\n </Heading>\n </DialogTitle>\n </DialogHeader>\n\n {/* \u5546\u54C1\u5217\u8868 */}\n <div\n className={cn(\n 'bg-container-secondary-0 h- flex flex-col gap-2 overflow-y-auto px-4 py-2',\n classNames?.content\n )}\n >\n {isEmpty ? (\n <div className=\"flex items-center justify-center py-8\">\n <Text size={2} className=\"text-info-tertiary\">\n {emptyText}\n </Text>\n </div>\n ) : (\n <div className={cn('flex flex-col gap-2', classNames?.itemList)}>\n {items.map(item => (\n <CartItem\n key={item.id}\n item={item}\n classNames={classNames}\n onIncrease={() => handleIncrease(item.id, item.quantity)}\n onDecrease={() => handleDecrease(item.id, item.quantity)}\n />\n ))}\n </div>\n )}\n </div>\n\n {/* \u5E95\u90E8\u5B89\u5168\u533A\u57DF */}\n <div className=\"bg-container-secondary-0 h-8 w-full\" />\n </DialogContent>\n </Dialog>\n )\n}\n\nMiniCartDialog.displayName = 'MiniCartDialog'\n\nexport default MiniCartDialog\nexport { MiniCartDialog }\n"],
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport { cn } from '../../helpers/index.js'\nimport { Heading, Text, Dialog, DialogContent, DialogHeader, DialogTitle } from '../../components/index.js'\nimport type { CartLineItem, Cart } from './index.js'\n\n/**\n * \u8D2D\u7269\u8F66\u6570\u636E\u7C7B\u578B - \u590D\u7528 MiniCart \u7684\u7C7B\u578B\u5B9A\u4E49\n */\nexport interface CartData {\n id: string\n checkoutUrl: string\n lineItems: CartLineItem[]\n}\n\n// \u91CD\u65B0\u5BFC\u51FA\u7C7B\u578B\u4F9B\u5916\u90E8\u4F7F\u7528\nexport type { CartLineItem, Cart }\n\n/**\n * \u6587\u6848\u914D\u7F6E\n */\nexport interface MiniCartDialogCopy {\n /** \u6807\u9898\u6587\u6848\uFF0C{count} \u4F1A\u88AB\u66FF\u6362\u4E3A\u5546\u54C1\u6570\u91CF */\n title?: string\n /** \u7A7A\u8D2D\u7269\u8F66\u63D0\u793A */\n emptyText?: string\n}\n\nexport type MiniCartDialogSemanticName =\n | 'root'\n | 'header'\n | 'title'\n | 'content'\n | 'itemList'\n | 'item'\n | 'itemImage'\n | 'itemInfo'\n | 'itemTitle'\n | 'itemPrice'\n | 'itemCurrentPrice'\n | 'itemOriginalPrice'\n | 'quantityControl'\n | 'quantityButton'\n | 'quantityValue'\n\nexport interface MiniCartDialogProps {\n /** \u662F\u5426\u6253\u5F00\u5F39\u7A97 */\n open: boolean\n /** \u5173\u95ED\u5F39\u7A97\u56DE\u8C03 */\n onOpenChange: (open: boolean) => void\n /** \u8D2D\u7269\u8F66\u6570\u636E */\n cart: CartData\n /** \u6587\u6848\u914D\u7F6E */\n copy?: MiniCartDialogCopy\n /** \u5404\u90E8\u5206\u7684\u81EA\u5B9A\u4E49\u6837\u5F0F\u7C7B\u540D */\n classNames?: Partial<Record<MiniCartDialogSemanticName, string>>\n /**\n * \u589E\u52A0\u5546\u54C1\u6570\u91CF\u56DE\u8C03\n * @param lineItemId \u5546\u54C1\u884CID\n * @param currentQuantity \u5F53\u524D\u6570\u91CF\n */\n onIncreaseQuantity?: (lineItemId: string, currentQuantity: number) => void\n /**\n * \u51CF\u5C11\u5546\u54C1\u6570\u91CF\u56DE\u8C03\n * @param lineItemId \u5546\u54C1\u884CID\n * @param currentQuantity \u5F53\u524D\u6570\u91CF\n */\n onDecreaseQuantity?: (lineItemId: string, currentQuantity: number) => void\n /**\n * \u6570\u91CF\u53D8\u66F4\u56DE\u8C03\n * @param lineItemId \u5546\u54C1\u884CID\n * @param quantity \u65B0\u6570\u91CF\n */\n onQuantityChange?: (lineItemId: string, quantity: number) => void\n}\n\n/**\n * MinusIcon - \u51CF\u53F7\u56FE\u6807\n */\nconst MinusIcon = ({ className }: { className?: string }) => (\n <svg className={className} width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M2 6H10\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n)\n\n/**\n * PlusIcon - \u52A0\u53F7\u56FE\u6807\n */\nconst PlusIcon = ({ className }: { className?: string }) => (\n <svg className={className} width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 2V10M2 6H10\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n)\n\n/**\n * CartItem - \u8D2D\u7269\u8F66\u5546\u54C1\u9879\u7EC4\u4EF6\n */\ninterface CartItemProps {\n item: CartLineItem\n classNames?: Partial<Record<MiniCartDialogSemanticName, string>>\n onIncrease?: () => void\n onDecrease?: () => void\n}\n\nconst CartItem = ({ item, classNames, onIncrease, onDecrease }: CartItemProps) => {\n const { merchandise, quantity, cost } = item\n const { image, title } = merchandise\n const { totalAmount, subtotalAmount } = cost\n\n // \u663E\u793A\u6807\u9898\uFF08\u56DE\u9000\u5230 SKU\uFF09\n const displayTitle = title || merchandise.sku || 'Product'\n // \u663E\u793A\u4EF7\u683C\uFF08\u73B0\u4EF7 = totalAmount\uFF09\n const displayPrice = totalAmount?.formattedPrice || ''\n // \u662F\u5426\u6709\u6298\u6263\uFF08\u539F\u4EF7 subtotalAmount \u5927\u4E8E\u73B0\u4EF7 totalAmount\uFF09\n const hasDiscount =\n subtotalAmount && totalAmount && parseFloat(subtotalAmount.amount) > parseFloat(totalAmount.amount)\n\n return (\n <div\n className={cn(\n // \u79FB\u52A8\u7AEF\uFF1A\u7070\u8272\u80CC\u666F\uFF0C\u8F83\u5C0F\u95F4\u8DDD\n 'bg-container-primary rounded-box flex items-center gap-2 px-2 py-4',\n // \u684C\u9762\u7AEF\uFF1A\u767D\u8272\u80CC\u666F\uFF0C\u8F83\u5927\u95F4\u8DDD\n 'laptop:bg-container-primary laptop:gap-4 laptop:p-4',\n classNames?.item\n )}\n >\n {/* \u5546\u54C1\u56FE\u7247 - \u79FB\u52A8\u7AEF 64px\uFF0C\u684C\u9762\u7AEF 80px */}\n <div\n className={cn('rounded-box relative size-16 shrink-0 overflow-hidden', 'laptop:size-20', classNames?.itemImage)}\n >\n {image?.url && <img src={image.url} alt={image.altText || displayTitle} className=\"size-full object-cover\" />}\n </div>\n\n {/* \u5546\u54C1\u4FE1\u606F */}\n <div className={cn('laptop:gap-4 flex flex-1 flex-col gap-2', classNames?.itemInfo)}>\n {/* \u5546\u54C1\u540D\u79F0 - \u79FB\u52A8\u7AEF\u8F83\u5C0F\u5B57\u4F53 */}\n <Text\n as=\"p\"\n size={3}\n className={cn('text-info-primary laptop:text-[16px] line-clamp-2 text-[14px]', classNames?.itemTitle)}\n >\n {displayTitle}\n </Text>\n\n {/* \u4EF7\u683C\u548C\u6570\u91CF\u63A7\u5236 - \u79FB\u52A8\u7AEF\u5782\u76F4\u6392\u5217\uFF0C\u684C\u9762\u7AEF\u6C34\u5E73\u6392\u5217 */}\n <div className=\"laptop:flex-row laptop:items-center laptop:justify-between flex flex-col items-start gap-1\">\n {/* \u4EF7\u683C\u533A\u57DF */}\n <div className={cn('flex items-center gap-1', classNames?.itemPrice)}>\n {displayPrice && (\n <Text\n size={4}\n className={cn('text-info-primary laptop:text-[18px] text-[16px]', classNames?.itemCurrentPrice)}\n >\n {displayPrice}\n </Text>\n )}\n {hasDiscount && subtotalAmount?.formattedPrice && (\n <Text\n size={4}\n className={cn(\n 'text-info-tertiary laptop:text-[18px] text-[16px] line-through',\n classNames?.itemOriginalPrice\n )}\n >\n {subtotalAmount.formattedPrice}\n </Text>\n )}\n </div>\n\n {/* \u6570\u91CF\u63A7\u5236 - \u79FB\u52A8\u7AEF 32px \u6309\u94AE\uFF0C\u684C\u9762\u7AEF 40px \u6309\u94AE */}\n <div className={cn('flex items-center', classNames?.quantityControl)}>\n {/* \u51CF\u5C11\u6309\u94AE */}\n <button\n type=\"button\"\n onClick={onDecrease}\n disabled={quantity <= 0}\n className={cn(\n 'border-lines flex size-8 items-center justify-center border',\n 'laptop:size-10',\n 'text-info-primary hover:bg-container-secondary-0 transition-colors',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n classNames?.quantityButton\n )}\n aria-label=\"Decrease quantity\"\n >\n <MinusIcon className=\"laptop:size-3 size-[10.67px]\" />\n </button>\n\n {/* \u6570\u91CF\u663E\u793A */}\n <div\n className={cn(\n 'border-lines text-info-primary flex size-8 items-center justify-center border-y text-center text-sm font-semibold',\n 'laptop:size-10 laptop:text-base',\n classNames?.quantityValue\n )}\n >\n {quantity}\n </div>\n\n {/* \u589E\u52A0\u6309\u94AE */}\n <button\n type=\"button\"\n onClick={onIncrease}\n className={cn(\n 'border-lines flex size-8 items-center justify-center border',\n 'laptop:size-10',\n 'text-info-primary hover:bg-container-secondary-0 transition-colors',\n classNames?.quantityButton\n )}\n aria-label=\"Increase quantity\"\n >\n <PlusIcon className=\"laptop:size-3 size-[10.67px]\" />\n </button>\n </div>\n </div>\n </div>\n </div>\n )\n}\n\n/**\n * MiniCartDialog - \u8FF7\u4F60\u8D2D\u7269\u8F66\u5F39\u7A97\u7EC4\u4EF6\n *\n * @description \u7528\u4E8E\u5C55\u793A\u8D2D\u7269\u8F66\u5546\u54C1\u5217\u8868\uFF0C\u652F\u6301\u8C03\u6574\u5546\u54C1\u6570\u91CF\n */\nconst MiniCartDialog = ({\n open,\n onOpenChange,\n cart,\n copy,\n classNames = {},\n onIncreaseQuantity,\n onDecreaseQuantity,\n onQuantityChange,\n}: MiniCartDialogProps) => {\n // \u6587\u6848\u914D\u7F6E\n const titleText = copy?.title || 'Selected ({count})'\n const emptyText = copy?.emptyText || 'Your cart is empty'\n\n // \u8BA1\u7B97\u5546\u54C1\u603B\u6570\u91CF\n const totalQuantity = cart?.lineItems?.reduce((total, item) => total + (item?.quantity || 0), 0) || 0\n\n const items = cart?.lineItems || []\n const isEmpty = items.length === 0\n\n // \u5904\u7406\u6570\u91CF\u589E\u52A0\n const handleIncrease = (lineItemId: string, currentQuantity: number) => {\n onIncreaseQuantity?.(lineItemId, currentQuantity)\n onQuantityChange?.(lineItemId, currentQuantity + 1)\n }\n\n // \u5904\u7406\u6570\u91CF\u51CF\u5C11\n const handleDecrease = (lineItemId: string, currentQuantity: number) => {\n if (currentQuantity > 0) {\n onDecreaseQuantity?.(lineItemId, currentQuantity)\n onQuantityChange?.(lineItemId, currentQuantity - 1)\n }\n }\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent\n className={cn(\n // \u57FA\u7840\u6837\u5F0F + \u5C45\u4E2D\u5B9A\u4F4D\n 'bg-container-secondary-0 fixed left-1/2 top-1/2 flex -translate-x-1/2 -translate-y-1/2 flex-col gap-0 overflow-hidden p-0',\n // \u79FB\u52A8\u7AEF\uFF1A\u5C45\u4E2D\u5F39\u7A97\uFF0C\u6700\u5C0F\u5BBD\u5EA6326px\uFF0C\u5DE6\u53F3\u8DDD\u5C4F\u5E55\u8FB9\u7F1832px\n 'rounded-box max-h-[80vh] w-[calc(100%-64px)] min-w-[326px]',\n // \u684C\u9762\u7AEF\uFF1A\u6700\u5927\u5BBD\u5EA6560px\n 'laptop:w-full laptop:max-w-[560px] laptop:rounded-box',\n classNames?.root\n )}\n >\n {/* \u5934\u90E8 */}\n <DialogHeader\n className={cn(\n 'bg-container-secondary-0 flex flex-row items-start justify-between gap-4 px-4 pb-2 pt-4',\n classNames?.header\n )}\n >\n <DialogTitle asChild>\n <Heading as=\"h3\" size={2} className={cn('text-info-primary font-bold', classNames?.title)}>\n {titleText.replace('{count}', totalQuantity.toString())}\n </Heading>\n </DialogTitle>\n </DialogHeader>\n\n {/* \u5546\u54C1\u5217\u8868 */}\n <div\n className={cn(\n 'bg-container-secondary-0 h- flex flex-col gap-2 overflow-y-auto px-4 py-2',\n classNames?.content\n )}\n >\n {isEmpty ? (\n <div className=\"flex items-center justify-center py-8\">\n <Text size={2} className=\"text-info-tertiary\">\n {emptyText}\n </Text>\n </div>\n ) : (\n <div className={cn('flex flex-col gap-2', classNames?.itemList)}>\n {items.map(item => (\n <CartItem\n key={item.id}\n item={item}\n classNames={classNames}\n onIncrease={() => handleIncrease(item.id, item.quantity)}\n onDecrease={() => handleDecrease(item.id, item.quantity)}\n />\n ))}\n </div>\n )}\n </div>\n\n {/* \u5E95\u90E8\u5B89\u5168\u533A\u57DF */}\n <div className=\"bg-container-secondary-0 h-8 w-full\" />\n </DialogContent>\n </Dialog>\n )\n}\n\nMiniCartDialog.displayName = 'MiniCartDialog'\n\nexport default MiniCartDialog\nexport { MiniCartDialog }\n"],
|
|
5
5
|
"mappings": "aAiFI,cAAAA,EAmEM,QAAAC,MAnEN,oBA/EJ,OAAS,MAAAC,MAAU,yBACnB,OAAS,WAAAC,EAAS,QAAAC,EAAM,UAAAC,EAAQ,iBAAAC,EAAe,gBAAAC,EAAc,eAAAC,MAAmB,4BA4EhF,MAAMC,EAAY,CAAC,CAAE,UAAAC,CAAU,IAC7BV,EAAC,OAAI,UAAWU,EAAW,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,MAAM,6BACtF,SAAAV,EAAC,QAAK,EAAE,UAAU,OAAO,eAAe,YAAY,MAAM,cAAc,QAAQ,eAAe,QAAQ,EACzG,EAMIW,EAAW,CAAC,CAAE,UAAAD,CAAU,IAC5BV,EAAC,OAAI,UAAWU,EAAW,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,MAAM,6BACtF,SAAAV,EAAC,QAAK,EAAE,iBAAiB,OAAO,eAAe,YAAY,MAAM,cAAc,QAAQ,eAAe,QAAQ,EAChH,EAaIY,EAAW,CAAC,CAAE,KAAAC,EAAM,WAAAC,EAAY,WAAAC,EAAY,WAAAC,CAAW,IAAqB,CAChF,KAAM,CAAE,YAAAC,EAAa,SAAAC,EAAU,KAAAC,CAAK,EAAIN,EAClC,CAAE,MAAAO,EAAO,MAAAC,CAAM,EAAIJ,EACnB,CAAE,YAAAK,EAAa,eAAAC,CAAe,EAAIJ,EAGlCK,EAAeH,GAASJ,EAAY,KAAO,UAE3CQ,EAAeH,GAAa,gBAAkB,GAE9CI,EACJH,GAAkBD,GAAe,WAAWC,EAAe,MAAM,EAAI,WAAWD,EAAY,MAAM,EAEpG,OACErB,EAAC,OACC,UAAWC,EAET,qEAEA,sDACAY,GAAY,IACd,EAGA,UAAAd,EAAC,OACC,UAAWE,EAAG,wDAAyD,iBAAkBY,GAAY,SAAS,EAE7G,SAAAM,GAAO,KAAOpB,EAAC,OAAI,IAAKoB,EAAM,IAAK,IAAKA,EAAM,SAAWI,EAAc,UAAU,yBAAyB,EAC7G,EAGAvB,EAAC,OAAI,UAAWC,EAAG,0CAA2CY,GAAY,QAAQ,EAEhF,UAAAd,EAACI,EAAA,CACC,GAAG,IACH,KAAM,EACN,UAAWF,EAAG,gEAAiEY,GAAY,SAAS,EAEnG,SAAAU,EACH,EAGAvB,EAAC,OAAI,UAAU,6FAEb,UAAAA,EAAC,OAAI,UAAWC,EAAG,0BAA2BY,GAAY,SAAS,EAChE,UAAAW,GACCzB,EAACI,EAAA,CACC,KAAM,EACN,UAAWF,EAAG,mDAAoDY,GAAY,gBAAgB,EAE7F,SAAAW,EACH,EAEDC,GAAeH,GAAgB,gBAC9BvB,EAACI,EAAA,CACC,KAAM,EACN,UAAWF,EACT,iEACAY,GAAY,iBACd,EAEC,SAAAS,EAAe,eAClB,GAEJ,EAGAtB,EAAC,OAAI,UAAWC,EAAG,oBAAqBY,GAAY,eAAe,EAEjE,UAAAd,EAAC,UACC,KAAK,SACL,QAASgB,EACT,SAAUE,GAAY,EACtB,UAAWhB,EACT,8DACA,iBACA,qEACA,kDACAY,GAAY,cACd,EACA,aAAW,oBAEX,SAAAd,EAACS,EAAA,CAAU,UAAU,+BAA+B,EACtD,EAGAT,EAAC,OACC,UAAWE,EACT,oHACA,kCACAY,GAAY,aACd,EAEC,SAAAI,EACH,EAGAlB,EAAC,UACC,KAAK,SACL,QAASe,EACT,UAAWb,EACT,8DACA,iBACA,qEACAY,GAAY,cACd,EACA,aAAW,oBAEX,SAAAd,EAACW,EAAA,CAAS,UAAU,+BAA+B,EACrD,GACF,GACF,GACF,GACF,CAEJ,EAOMgB,EAAiB,CAAC,CACtB,KAAAC,EACA,aAAAC,EACA,KAAAC,EACA,KAAAC,EACA,WAAAjB,EAAa,CAAC,EACd,mBAAAkB,EACA,mBAAAC,EACA,iBAAAC,CACF,IAA2B,CAEzB,MAAMC,EAAYJ,GAAM,OAAS,qBAC3BK,EAAYL,GAAM,WAAa,qBAG/BM,EAAgBP,GAAM,WAAW,OAAO,CAACQ,EAAOzB,IAASyB,GAASzB,GAAM,UAAY,GAAI,CAAC,GAAK,EAE9F0B,EAAQT,GAAM,WAAa,CAAC,EAC5BU,EAAUD,EAAM,SAAW,EAG3BE,EAAiB,CAACC,EAAoBC,IAA4B,CACtEX,IAAqBU,EAAYC,CAAe,EAChDT,IAAmBQ,EAAYC,EAAkB,CAAC,CACpD,EAGMC,EAAiB,CAACF,EAAoBC,IAA4B,CAClEA,EAAkB,IACpBV,IAAqBS,EAAYC,CAAe,EAChDT,IAAmBQ,EAAYC,EAAkB,CAAC,EAEtD,EAEA,OACE3C,EAACK,EAAA,CAAO,KAAMuB,EAAM,aAAcC,EAChC,SAAA5B,EAACK,EAAA,CACC,UAAWJ,EAET,4HAEA,6DAEA,wDACAY,GAAY,IACd,EAGA,UAAAd,EAACO,EAAA,CACC,UAAWL,EACT,0FACAY,GAAY,MACd,EAEA,SAAAd,EAACQ,EAAA,CAAY,QAAO,GAClB,SAAAR,EAACG,EAAA,CAAQ,GAAG,KAAK,KAAM,EAAG,UAAWD,EAAG,8BAA+BY,GAAY,KAAK,EACrF,SAAAqB,EAAU,QAAQ,UAAWE,EAAc,SAAS,CAAC,EACxD,EACF,EACF,EAGArC,EAAC,OACC,UAAWE,EACT,4EACAY,GAAY,OACd,EAEC,SAAA0B,EACCxC,EAAC,OAAI,UAAU,wCACb,SAAAA,EAACI,EAAA,CAAK,KAAM,EAAG,UAAU,qBACtB,SAAAgC,EACH,EACF,EAEApC,EAAC,OAAI,UAAWE,EAAG,sBAAuBY,GAAY,QAAQ,EAC3D,SAAAyB,EAAM,IAAI1B,GACTb,EAACY,EAAA,CAEC,KAAMC,EACN,WAAYC,EACZ,WAAY,IAAM2B,EAAe5B,EAAK,GAAIA,EAAK,QAAQ,EACvD,WAAY,IAAM+B,EAAe/B,EAAK,GAAIA,EAAK,QAAQ,GAJlDA,EAAK,EAKZ,CACD,EACH,EAEJ,EAGAb,EAAC,OAAI,UAAU,sCAAsC,GACvD,EACF,CAEJ,EAEA2B,EAAe,YAAc,iBAE7B,IAAOkB,EAAQlB",
|
|
6
6
|
"names": ["jsx", "jsxs", "cn", "Heading", "Text", "Dialog", "DialogContent", "DialogHeader", "DialogTitle", "MinusIcon", "className", "PlusIcon", "CartItem", "item", "classNames", "onIncrease", "onDecrease", "merchandise", "quantity", "cost", "image", "title", "totalAmount", "subtotalAmount", "displayTitle", "displayPrice", "hasDiscount", "MiniCartDialog", "open", "onOpenChange", "cart", "copy", "onIncreaseQuantity", "onDecreaseQuantity", "onQuantityChange", "titleText", "emptyText", "totalQuantity", "total", "items", "isEmpty", "handleIncrease", "lineItemId", "currentQuantity", "handleDecrease", "MiniCartDialog_default"]
|
|
7
7
|
}
|
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
|
|
2
|
+
import type { Img } from '../../types/props.js';
|
|
3
|
+
export type MiniCartSemanticName = 'root' | 'content' | 'cartInfo' | 'cartTitle' | 'cartDescription' | 'priceSection' | 'totalPrice' | 'originalPrice' | 'saveAmount' | 'actionButton' | 'itemsGrid' | 'itemGridContainer' | 'gridItem' | 'gridItemOverlay' | 'expandButton' | 'circleProgress' | 'mobileViewMoreButton';
|
|
4
|
+
/**
|
|
5
|
+
* 圆形进度条配置
|
|
6
|
+
*/
|
|
7
|
+
export interface CircleProgressConfig {
|
|
8
|
+
/** 总阶段数 (1-4) */
|
|
9
|
+
totalSteps?: 1 | 2 | 3 | 4;
|
|
10
|
+
/** 当前完成的阶段 (0 到 totalSteps) */
|
|
11
|
+
currentStep?: number;
|
|
12
|
+
/** 中间显示的图片 */
|
|
13
|
+
image?: Img;
|
|
14
|
+
/** 底部显示的文案 */
|
|
15
|
+
label?: string;
|
|
16
|
+
/** 进度条颜色,默认为品牌色 */
|
|
17
|
+
progressColor?: string;
|
|
18
|
+
/** 底部文案背景色,默认为品牌营销色 */
|
|
19
|
+
labelColor?: string;
|
|
20
|
+
/** 背景颜色,默认为容器背景色 */
|
|
21
|
+
backgroundColor?: string;
|
|
22
|
+
/** 移动端组件尺寸,默认 48 */
|
|
23
|
+
size?: number;
|
|
24
|
+
/** laptop 以上组件尺寸,默认 80 */
|
|
25
|
+
laptopSize?: number;
|
|
26
|
+
}
|
|
3
27
|
/**
|
|
4
28
|
* 文案配置
|
|
5
29
|
*/
|
|
@@ -22,6 +46,8 @@ export interface MiniCartData {
|
|
|
22
46
|
theme?: 'light' | 'dark';
|
|
23
47
|
/** 地区代码,用于价格格式化 */
|
|
24
48
|
locale?: string;
|
|
49
|
+
/** 是否显示手机端查看更多按钮,默认 true */
|
|
50
|
+
showMobileViewMore?: boolean;
|
|
25
51
|
}
|
|
26
52
|
/**
|
|
27
53
|
* 购物车商品项类型
|
|
@@ -88,6 +114,10 @@ export interface MiniCartProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
88
114
|
* 产品信息(用于主要展示的产品)
|
|
89
115
|
*/
|
|
90
116
|
cart: Cart;
|
|
117
|
+
/**
|
|
118
|
+
* 圆形进度条配置,不传则不显示进度条
|
|
119
|
+
*/
|
|
120
|
+
progressConfig?: CircleProgressConfig;
|
|
91
121
|
/**
|
|
92
122
|
* 删除商品项的回调函数
|
|
93
123
|
* @param id 商品 ID
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{jsx as t,jsxs as r}from"react/jsx-runtime";import*as c from"react";import{cn as e}from"../../helpers/index.js";import{Button as ct}from"../../components/index.js";import{Text as A}from"../../components/index.js";import{Heading as p}from"../../components/index.js";const S=c.forwardRef(({className:D,classNames:o={},data:B,cart:a,onRemoveItem:j,onCheckout:H,onClickToView:R,...E},V)=>{const{copy:l,theme:x="light",locale:pt="us"}=B||{},W=l?.emptyCart||"Your Cart is Empty",b=l?.description||'Add one more to get <span style="color: var(--brand-color)">50% <span> off',q=l?.itemsInCart||"You have selected {count} items",G=l?.total||"Total {total}",dt=l?.totalWithCoupon||"total: {total} ({subtotal})",U=l?.clickToView||"Click to view cart",X=l?.buyNowText||"Buy Now",F=l?.savingText||"Saving {amount}",d=a?.lineItems||[],w=d.reduce((i,n)=>i+(n?.quantity||0),0),O=w===0,Y=parseFloat(a?.cost?.totalAmount?.amount||"0"),Z=parseFloat(a?.cost?.subtotalAmount?.amount||"0"),$=parseFloat(a?.cost?.savingAmount?.amount||"0"),J=a?.cost?.totalAmount?.formattedPrice||"",C=Z>Y?a?.cost?.subtotalAmount?.formattedPrice:null,y=$>0?a?.cost?.savingAmount?.formattedPrice:null,s=c.useRef(null),[f,K]=c.useState(!1),[k,M]=c.useState(!1),[g,L]=c.useState(null),N=async i=>{if(!g){L(i);try{await j?.(i,a)}finally{L(null)}}},[I,h]=c.useState(!1),[Q,_]=c.useState(0),[tt,et]=c.useState(0),ot=i=>{s.current&&(h(!0),_(i.pageX-s.current.offsetLeft),et(s.current.scrollLeft))},it=i=>{if(!I||!s.current)return;i.preventDefault();const m=(i.pageX-s.current.offsetLeft-Q)*1.5;s.current.scrollLeft=tt-m},nt=()=>{h(!1)},rt=()=>{h(!1)},T=i=>{if(s.current){const n=s.current,m=100;n.scrollBy({left:i==="right"?m:-m,behavior:"smooth"})}},v=({className:i})=>t("svg",{className:i,width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M6 4L10 8L6 12",stroke:"currentColor",strokeWidth:"1.33",strokeLinecap:"round",strokeLinejoin:"round"})}),at=({className:i})=>t("svg",{className:i,width:"20",height:"20",viewBox:"0 0 20 20",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M2.5 5H17.5M8.33333 9.16667V14.1667M11.6667 9.16667V14.1667M3.33333 5L4.16667 16.6667C4.16667 17.1087 4.34226 17.5326 4.65482 17.8452C4.96738 18.1577 5.39131 18.3333 5.83333 18.3333H14.1667C14.6087 18.3333 15.0326 18.1577 15.3452 17.8452C15.6577 17.5326 15.8333 17.1087 15.8333 16.6667L16.6667 5M7.5 5V2.5C7.5 2.27899 7.5878 2.06702 7.74408 1.91074C7.90036 1.75446 8.11232 1.66667 8.33333 1.66667H11.6667C11.8877 1.66667 12.0996 1.75446 12.2559 1.91074C12.4122 2.06702 12.5 2.27899 12.5 2.5V5",stroke:"currentColor",strokeWidth:"1.25",strokeLinecap:"round",strokeLinejoin:"round"})}),st=i=>d.length?r("div",{className:e("bg-container-primary flex gap-1 rounded-lg p-1",o?.itemsGrid),children:[d.length>0&&t("button",{onClick:()=>T("left"),className:e("border-border laptop:flex hover:bg-muted-foreground/10 laptop:flex hidden size-12 shrink-0 items-center justify-center rounded-lg transition-colors",o?.expandButton),"aria-label":"Scroll left to see more items",children:t(v,{className:"size-4 rotate-180"})}),t("div",{ref:s,onMouseDown:ot,onMouseMove:it,onMouseUp:nt,onMouseLeave:rt,className:e("scrollbar-hide laptop:gap-1 laptop:max-w-[240px] flex w-full gap-1 overflow-x-auto [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",I?"cursor-grabbing":"cursor-grab",o?.itemGridContainer),children:d.filter(n=>n&&n.id).map(n=>{const P=(n.merchandise||{}).image||{},z=P.url,lt=P.altText||"Product image";return r("div",{className:e("laptop:size-12 bg-container-secondary laptop:bg-white group relative size-16 shrink-0 rounded-lg",o?.gridItem),children:[z&&t("img",{src:z,alt:lt,draggable:!1,className:"pointer-events-none size-full select-none rounded-lg object-cover"}),g===n.id&&t("div",{className:"absolute inset-0 flex items-center justify-center rounded-lg bg-black/50",children:r("svg",{width:"20",height:"20",viewBox:"0 0 16 16",fill:"none",xmlns:"http://www.w3.org/2000/svg",className:"animate-spin text-white",children:[t("circle",{cx:"8",cy:"8",r:"6",stroke:"currentColor",strokeWidth:"2",opacity:"0.3"}),t("path",{d:"M14 8a6 6 0 0 0-6-6",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"})]})}),t("span",{role:"button",onClick:()=>N(n.id),className:e("laptop:hidden absolute right-[2px] top-[2px] cursor-pointer",g===n.id&&"pointer-events-none opacity-0"),"aria-label":"delete",children:r("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",xmlns:"http://www.w3.org/2000/svg",className:"pointer-events-none",children:[t("rect",{x:"1.33301",y:"1.33301",width:"13.3333",height:"13.3333",rx:"6.66667",fill:"white"}),t("path",{d:"M5.37705 5.28896C5.57234 5.09402 5.88839 5.09442 6.08347 5.28965L8.08602 7.29358L10.0906 5.28896C10.2858 5.09402 10.6026 5.09395 10.7977 5.28896C10.9928 5.48418 10.9926 5.80078 10.7977 5.99607L8.79312 8.00069L10.7964 10.0053C10.9913 10.2007 10.9909 10.5179 10.7957 10.7131C10.6005 10.908 10.2844 10.9074 10.0893 10.7124L8.08602 8.7078L6.08347 10.7103C5.88821 10.9056 5.57155 10.9057 5.37636 10.7103C5.18148 10.515 5.18132 10.1984 5.37636 10.0032L7.37891 8.00069L5.37636 5.99676C5.18119 5.80143 5.18181 5.48423 5.37705 5.28896Z",fill:"#767880"})]})}),n.quantity>1&&t("div",{className:"mini-cart-quantity bg-brand-0 laptop:size-4 absolute bottom-0 right-0 flex size-4 items-center justify-center rounded-full text-white",children:t(A,{className:"text-sm",html:String(n.quantity)})}),t("div",{className:e("laptop:flex absolute inset-0 hidden items-center justify-center rounded-lg bg-black/60 opacity-0 transition-opacity group-hover:opacity-100",g===n.id&&"hidden",o?.gridItemOverlay),children:t("button",{onClick:()=>N(n.id),className:"flex items-center justify-center rounded-full bg-white/20 p-1 transition-colors hover:bg-white/30","aria-label":"Remove item",children:t(at,{className:"laptop:size-3 pointer-events-none size-4 text-white"})})})]},n.id)})}),d.length>0&&t("button",{onClick:()=>T("right"),className:e("border-border laptop:flex hover:bg-muted-foreground/10 laptop:flex hidden size-12 shrink-0 items-center justify-center rounded-lg transition-colors",o?.expandButton),"aria-label":"Scroll right to see more items",children:t(v,{className:"size-4"})})]}):null,u=!O&&d.length>0;return t("div",{ref:V,className:e("bg-container-secondary-1 text-info-primary tablet:px-6 laptop:px-12 desktop:px-12 lg-desktop:px-[128px] laptop:py-[16px] flex w-full px-4 py-[12px]","flex-col items-stretch gap-3","laptop:flex-row laptop:items-center laptop:justify-around","laptop:items-center laptop:gap-4","tablet:gap-6 laptop:gap-8",D,o?.root,{"aiui-dark bg-container-primary":x==="dark"}),...E,children:r("div",{className:e("laptop:flex-row flex w-full flex-col gap-4","laptop:flex-1 laptop:items-start","tablet:gap-6 laptop:gap-8",o?.content),children:[r("div",{className:"laptop:flex-1 flex w-full flex-col",children:[t("div",{className:e("tablet:gap-2 flex flex-col gap-1",o?.cartInfo),children:u?r("div",{className:"flex w-full items-center gap-2",children:[t(p,{size:2,as:"h3",className:e("",o?.cartTitle),html:q.replace("{count}",`<span class="text-brand-0">${w||0}</span>`)}),r(p,{size:1,as:"h5",onClick:()=>{window.innerWidth<1025?K(!f):R?.(a)},className:e("flex cursor-pointer items-center gap-1",o?.expandButton),children:[t(p,{as:"h6",size:1,className:"laptop:block hidden text-nowrap",html:U}),t(v,{className:e("size-4 transition-transform",f?"laptop:rotate-0 -rotate-90":"laptop:rotate-0 rotate-90")})]})]}):t(p,{as:"h3",size:2,className:e("tablet:text-2xl text-xl font-semibold",o?.cartTitle),html:W})}),t("div",{children:b&&t(A,{size:2,className:e("mini-cart-description",o?.cartDescription),html:b})})]}),u&&t("div",{className:e("laptop:block",f?"block":"hidden"),children:st(x)}),u&&t("hr",{className:"laptop:hidden border-lines w-full border-t"}),r("div",{className:e("tablet:gap-6 laptop:justify-end flex flex-row items-center justify-between gap-4",o?.priceSection),children:[r("div",{className:"flex flex-col items-end justify-center gap-1",children:[r("div",{className:"flex items-center gap-2",children:[t(p,{as:"h6",size:2,className:e(" whitespace-nowrap ",o?.totalPrice),html:G.replace("{total}",J)}),C&&t(p,{as:"h6",size:2,className:e("whitespace-nowrap line-through",o?.originalPrice),html:C})]}),y&&t(p,{size:2,as:"h6",className:e("laptop:text-right text-marketing-0 w-full text-left",o?.saveAmount),html:F.replace("{amount}",y)})]}),t(ct,{disabled:!u,loading:k,onClick:async()=>{if(!k){M(!0);try{await H?.(a)}finally{M(!1)}}},className:e("whitespace-nowrap",o?.actionButton),children:X})]})]})})});S.displayName="MiniCart";var ht=S;export{ht as default};
|
|
1
|
+
"use client";import{jsx as t,jsxs as i}from"react/jsx-runtime";import*as a from"react";import{cn as o}from"../../helpers/index.js";import{Button as vt}from"../../components/index.js";import{Text as y}from"../../components/index.js";import{Heading as m}from"../../components/index.js";import bt from"./CircleProgress.js";const V=a.forwardRef(({className:W,classNames:r={},data:q,cart:l,progressConfig:s,onRemoveItem:G,onCheckout:U,onClickToView:C,...X},F)=>{const{copy:p,theme:k="light",locale:wt="us",showMobileViewMore:O=!0}=q||{},Y=p?.emptyCart||"Your Cart is Empty",M=p?.description||"",Z=p?.itemsInCart||"You have selected {count} items",$=p?.total||"Total {total}",yt=p?.totalWithCoupon||"total: {total} ({subtotal})",L=p?.clickToView||"Click to view cart",J=p?.buyNowText||"Buy Now",K=p?.savingText||"Saving {amount}",d=a.useMemo(()=>l?.lineItems||[],[l?.lineItems]),S=d.reduce((e,n)=>e+(n?.quantity||0),0),Q=S===0,_=parseFloat(l?.cost?.totalAmount?.amount||"0"),tt=parseFloat(l?.cost?.subtotalAmount?.amount||"0"),et=parseFloat(l?.cost?.savingAmount?.amount||"0"),ot=l?.cost?.totalAmount?.formattedPrice||"",N=tt>_?l?.cost?.subtotalAmount?.formattedPrice:null,P=et>0?l?.cost?.savingAmount?.formattedPrice:null,c=a.useRef(null),[x,rt]=a.useState(!1),[I,z]=a.useState(!1),[T,A]=a.useState(null),B=async e=>{if(!T){A(e);try{await G?.(e,l)}finally{A(null)}}},[j,v]=a.useState(!1),[nt,at]=a.useState(0),[it,lt]=a.useState(0),[D,st]=a.useState(!1),[R,ct]=a.useState(!0),f=a.useCallback(()=>{const e=c.current;if(!e)return;const{scrollLeft:n,scrollWidth:u,clientWidth:h}=e;st(n>0),ct(n<u-h-1)},[]),pt=a.useCallback(()=>{f()},[f]);a.useEffect(()=>{f()},[d.length,f]);const dt=e=>{c.current&&(v(!0),at(e.pageX-c.current.offsetLeft),lt(c.current.scrollLeft))},ut=e=>{if(!j||!c.current)return;e.preventDefault();const u=(e.pageX-c.current.offsetLeft-nt)*1.5;c.current.scrollLeft=it-u},mt=()=>{v(!1)},gt=()=>{v(!1)},E=e=>{if(c.current){const n=c.current,u=100;n.scrollBy({left:e==="right"?u:-u,behavior:"smooth"})}},b=({className:e})=>t("svg",{className:e,width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M6 4L10 8L6 12",stroke:"currentColor",strokeWidth:"1.33",strokeLinecap:"round",strokeLinejoin:"round"})}),ft=({className:e})=>t("svg",{className:e,width:"20",height:"20",viewBox:"0 0 20 20",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M2.5 5H17.5M8.33333 9.16667V14.1667M11.6667 9.16667V14.1667M3.33333 5L4.16667 16.6667C4.16667 17.1087 4.34226 17.5326 4.65482 17.8452C4.96738 18.1577 5.39131 18.3333 5.83333 18.3333H14.1667C14.6087 18.3333 15.0326 18.1577 15.3452 17.8452C15.6577 17.5326 15.8333 17.1087 15.8333 16.6667L16.6667 5M7.5 5V2.5C7.5 2.27899 7.5878 2.06702 7.74408 1.91074C7.90036 1.75446 8.11232 1.66667 8.33333 1.66667H11.6667C11.8877 1.66667 12.0996 1.75446 12.2559 1.91074C12.4122 2.06702 12.5 2.27899 12.5 2.5V5",stroke:"currentColor",strokeWidth:"1.25",strokeLinecap:"round",strokeLinejoin:"round"})}),ht=e=>d.length?i("div",{className:o("laptop:bg-container-secondary-0 flex gap-1 rounded-lg p-1",r?.itemsGrid),children:[d.length>=5&&t("button",{onClick:()=>E("left"),className:o("border-border laptop:flex hover:bg-muted-foreground/10 hidden w-[32px] shrink-0 items-center justify-center rounded-lg px-2 transition-colors",!D&&"laptop:bg-container-secondary-1 laptop:text-transparent laptop:pointer-events-none laptop:-my-1 laptop:-ml-1 laptop:py-1 laptop:pl-1 laptop:rounded-r-none",r?.expandButton,{"laptop:bg-container-secondary-0":e==="dark","laptop:bg-container-primary":e==="dark"&&!D}),"aria-label":"Scroll left to see more items",children:t(b,{className:"laptop:size-4 size-5 rotate-180"})}),i("div",{ref:c,onMouseDown:dt,onMouseMove:ut,onMouseUp:mt,onMouseLeave:gt,onScroll:pt,className:o("scrollbar-hide laptop:gap-1 laptop:w-[256px] laptop:shrink-0 flex w-full gap-1 overflow-x-auto [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",j?"cursor-grabbing":"cursor-grab",r?.itemGridContainer),children:[d.filter(n=>n&&n.id).map(n=>{const h=(n.merchandise||{}).image||{},H=h.url,xt=h.altText||"Product image",w=T===n.id;return i("div",{className:o("laptop:size-12 group relative size-16 shrink-0",r?.gridItem),children:[H&&t("img",{src:H,alt:xt,draggable:!1,className:"pointer-events-none size-full select-none rounded-lg object-cover"}),w&&t("div",{className:"absolute inset-0 flex items-center justify-center rounded-lg bg-black/50",children:i("svg",{width:"20",height:"20",viewBox:"0 0 16 16",fill:"none",xmlns:"http://www.w3.org/2000/svg",className:"animate-spin text-white",children:[t("circle",{cx:"8",cy:"8",r:"6",stroke:"currentColor",strokeWidth:"2",opacity:"0.3"}),t("path",{d:"M14 8a6 6 0 0 0-6-6",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"})]})}),t("span",{role:"button",onClick:()=>B(n.id),className:o("laptop:hidden absolute right-[2px] top-[2px] cursor-pointer",w&&"pointer-events-none opacity-0"),"aria-label":"delete",children:i("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",xmlns:"http://www.w3.org/2000/svg",className:"pointer-events-none",children:[t("rect",{x:"1.33301",y:"1.33301",width:"13.3333",height:"13.3333",rx:"6.66667",fill:"white"}),t("path",{d:"M5.37705 5.28896C5.57234 5.09402 5.88839 5.09442 6.08347 5.28965L8.08602 7.29358L10.0906 5.28896C10.2858 5.09402 10.6026 5.09395 10.7977 5.28896C10.9928 5.48418 10.9926 5.80078 10.7977 5.99607L8.79312 8.00069L10.7964 10.0053C10.9913 10.2007 10.9909 10.5179 10.7957 10.7131C10.6005 10.908 10.2844 10.9074 10.0893 10.7124L8.08602 8.7078L6.08347 10.7103C5.88821 10.9056 5.57155 10.9057 5.37636 10.7103C5.18148 10.515 5.18132 10.1984 5.37636 10.0032L7.37891 8.00069L5.37636 5.99676C5.18119 5.80143 5.18181 5.48423 5.37705 5.28896Z",fill:"#767880"})]})}),n.quantity>1&&t("div",{className:"mini-cart-quantity bg-brand-0 laptop:size-4 absolute bottom-0 right-0 flex size-4 items-center justify-center rounded-full text-white",children:t(y,{className:"text-sm",html:String(n.quantity)})}),t("div",{role:"button",onClick:()=>B(n.id),className:o("absolute inset-0 hidden cursor-pointer items-center justify-center rounded-lg bg-black/60 transition-opacity","laptop:flex laptop:opacity-0 laptop:group-hover:opacity-100",w&&"laptop:hidden",r?.gridItemOverlay),"aria-label":"Remove item",children:t(ft,{className:"pointer-events-none size-[20px] text-white"})})]},n.id)}),O&&t("button",{onClick:()=>C?.(l),className:o("bg-container-secondary-0 laptop:hidden flex size-16 shrink-0 items-center justify-center rounded-md",r?.mobileViewMoreButton),"aria-label":L,children:t("svg",{width:"20",height:"20",viewBox:"0 0 20 20",fill:"none",xmlns:"http://www.w3.org/2000/svg",className:"text-info-quaternary",children:t("path",{d:"M7.5 5L12.5 10L7.5 15",stroke:"currentColor",strokeWidth:"1.67",strokeLinecap:"round",strokeLinejoin:"round"})})})]}),d.length>=5&&t("button",{onClick:()=>E("right"),className:o("border-border laptop:flex hover:bg-muted-foreground/10 hidden w-[32px] shrink-0 items-center justify-center rounded-lg px-2 transition-colors",!R&&"laptop:bg-container-secondary-1 laptop:text-transparent laptop:pointer-events-none laptop:-my-1 laptop:-mr-1 laptop:py-1 laptop:pr-1 laptop:rounded-l-none",r?.expandButton,{"laptop:bg-container-secondary-0":e==="dark","laptop:bg-container-primary":e==="dark"&&!R}),"aria-label":"Scroll right to see more items",children:t(b,{className:"laptop:size-4 size-5"})})]}):null,g=!Q&&d.length>0;return t("div",{ref:F,className:o("bg-container-secondary-1 text-info-primary tablet:px-6 laptop:px-12 desktop:px-12 lg-desktop:px-[128px] laptop:py-[16px] flex w-full px-4 py-[12px]","flex-col items-stretch gap-3","laptop:flex-row laptop:items-center laptop:justify-around","laptop:items-center laptop:gap-4","tablet:gap-6 laptop:gap-8",W,r?.root,{"aiui-dark bg-container-primary":k==="dark"}),...X,children:i("div",{className:o("laptop:flex-row flex w-full flex-col gap-4","laptop:flex-1 laptop:items-center laptop:justify-between","tablet:gap-6 laptop:gap-8",r?.content),children:[i("div",{className:o("relative flex shrink flex-row items-center gap-2","desktop:gap-4",s&&"laptop:pl-[104px] pl-[72px]"),children:[s&&t(bt,{totalSteps:s.totalSteps,currentStep:s.currentStep,image:s.image,label:s.label,progressColor:s.progressColor,labelColor:s.labelColor,backgroundColor:s.backgroundColor,size:s.size,laptopSize:s.laptopSize,className:o("absolute bottom-0 left-0","lg-desktop:bottom-auto lg-desktop:top-[-46px] desktop:bottom-auto desktop:top-[-52px]",r?.circleProgress)}),i("div",{className:"laptop:flex-1 flex w-full flex-col",children:[t("div",{className:o("tablet:gap-2 flex flex-col gap-1",r?.cartInfo),children:g?i("div",{className:"flex w-full items-center gap-2",children:[t(m,{size:2,as:"h3",className:o("",r?.cartTitle),html:Z.replace("{count}",`<span class="text-brand-0">${S||0}</span>`)}),i(m,{size:1,as:"h5",onClick:()=>{window.innerWidth<1025?rt(!x):C?.(l)},className:o("flex cursor-pointer items-center gap-1",r?.expandButton),children:[t(y,{as:"span",size:1,className:"desktop:block hidden text-nowrap text-[16px] ",html:L}),t(b,{className:o("size-4 transition-transform",x?"laptop:rotate-0 -rotate-90":"laptop:rotate-0 rotate-90")})]})]}):t(m,{as:"h3",size:2,className:o("tablet:text-2xl text-xl font-semibold",r?.cartTitle),html:Y})}),M&&t(y,{size:2,className:o("mini-cart-description text-info-tertiary desktop:text-[16px] lg-desktop:text-[18px] text-[14px]",r?.cartDescription),html:M})]})]}),g&&t("div",{className:o("laptop:block laptop:shrink",x?"block":"hidden"),children:ht(k)}),g&&t("hr",{className:"laptop:hidden border-lines w-full border-t"}),i("div",{className:o("tablet:gap-6 laptop:gap-4 laptop:justify-end flex flex-row items-stretch justify-between gap-4",r?.priceSection),children:[i("div",{className:"flex flex-col items-end justify-center",children:[i("div",{className:"flex items-center gap-2",children:[t(m,{as:"h6",size:2,className:o("whitespace-nowrap text-nowrap",r?.totalPrice),html:$.replace("{total}",ot)}),N&&t(m,{as:"h6",size:2,className:o("text-info-tertiary whitespace-nowrap line-through",r?.originalPrice),html:N})]}),P&&t(m,{size:2,as:"h6",className:o("laptop:text-right text-marketing-1 w-full whitespace-nowrap text-nowrap text-left",r?.saveAmount),html:K.replace("{amount}",P)})]}),t(vt,{disabled:!g,loading:I,onClick:async()=>{if(!I){z(!0);try{await U?.(l)}finally{z(!1)}}},className:o("whitespace-nowrap",r?.actionButton),children:J})]})]})})});V.displayName="MiniCart";var Nt=V;export{Nt as default};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/biz-components/MiniCart/index.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { cn } from '../../helpers/index.js'\nimport { Button } from '../../components/index.js'\nimport { Text } from '../../components/index.js'\nimport { Heading } from '../../components/index.js'\nimport type { Theme } from '../../types/props.js'\n\nexport type MiniCartSemanticName =\n | 'root'\n | 'content'\n | 'cartInfo'\n | 'cartTitle'\n | 'cartDescription'\n | 'priceSection'\n | 'totalPrice'\n | 'originalPrice'\n | 'saveAmount'\n | 'actionButton'\n | 'itemsGrid'\n | 'itemGridContainer'\n | 'gridItem'\n | 'gridItemOverlay'\n | 'expandButton'\n\n/**\n * \u6587\u6848\u914D\u7F6E\n */\nexport interface MiniCartCopy {\n emptyCart: string\n description: string\n total: string\n itemsInCart: string\n totalWithCoupon: string\n clickToView: string\n buyNowText: string\n savingText: string\n}\n\n/**\n * MiniCart \u4E1A\u52A1\u7EC4\u4EF6\u6570\u636E\u63A5\u53E3\n */\nexport interface MiniCartData {\n /** \u6587\u6848\u914D\u7F6E */\n copy?: MiniCartCopy\n theme?: 'light' | 'dark'\n /** \u5730\u533A\u4EE3\u7801\uFF0C\u7528\u4E8E\u4EF7\u683C\u683C\u5F0F\u5316 */\n locale?: string\n}\n\n/**\n * \u8D2D\u7269\u8F66\u5546\u54C1\u9879\u7C7B\u578B\n */\nexport type CartLineItem = {\n id: string\n quantity: number\n cost: {\n totalAmount: {\n amount: string\n currencyCode: string\n formattedPrice: string\n }\n subtotalAmount?: {\n amount: string\n currencyCode: string\n formattedPrice?: string\n }\n }\n merchandise: {\n id: string\n sku: string\n /** \u5546\u54C1\u6807\u9898 - MiniCartDialog \u9700\u8981 */\n title?: string\n image: {\n url: string\n altText: string | null\n }\n }\n}\n\n/**\n * \u8D2D\u7269\u8F66\u7C7B\u578B\n */\nexport type Cart = {\n id: string\n checkoutUrl: string\n lineItems: CartLineItem[]\n cost: {\n totalAmount: {\n amount: string\n currencyCode: string\n formattedPrice: string\n }\n subtotalAmount?: {\n amount: string\n currencyCode: string\n formattedPrice?: string\n }\n savingAmount?: {\n amount?: string\n currencyCode: string\n formattedPrice?: string\n }\n }\n}\n\nexport interface MiniCartProps extends React.HTMLAttributes<HTMLDivElement> {\n /** \u4E1A\u52A1\u6570\u636E */\n data: MiniCartData\n /**\n * \u5404\u90E8\u5206\u7684\u81EA\u5B9A\u4E49\u6837\u5F0F\u7C7B\u540D\n */\n classNames?: Partial<Record<MiniCartSemanticName, string>>\n /**\n * \u4EA7\u54C1\u4FE1\u606F\uFF08\u7528\u4E8E\u4E3B\u8981\u5C55\u793A\u7684\u4EA7\u54C1\uFF09\n */\n cart: Cart\n /**\n * \u5220\u9664\u5546\u54C1\u9879\u7684\u56DE\u8C03\u51FD\u6570\n * @param id \u5546\u54C1 ID\n * @param cart \u8D2D\u7269\u8F66\u6570\u636E\n * @returns \u652F\u6301\u8FD4\u56DE Promise\uFF0C\u5185\u90E8\u81EA\u52A8\u5904\u7406 loading \u72B6\u6001\n */\n onRemoveItem?: (id: string, cart: Cart) => void | Promise<void>\n /**\n * \u70B9\u51FB\u7ED3\u7B97\u6309\u94AE\u7684\u56DE\u8C03\u51FD\u6570\n * @param cart\n * @returns \u652F\u6301\u8FD4\u56DE Promise\uFF0C\u5185\u90E8\u81EA\u52A8\u5904\u7406 loading \u72B6\u6001\n */\n onCheckout?: (cart: Cart) => void | Promise<void>\n /**\n * \u70B9\u51FBclick to view\u7684\u56DE\u8C03\u51FD\u6570\n * @param cart\n * @returns\n */\n onClickToView?: (cart: Cart) => void\n}\n\n/**\n * MiniCart - \u8FF7\u4F60\u8D2D\u7269\u8F66\n *\n * @description \u8FF7\u4F60\u8D2D\u7269\u8F66\uFF08Mini Cart\uFF09\u662F\u4E00\u4E2A\u5E38\u89C1\u7684\u7535\u5546UI\u7EC4\u4EF6\uFF0C\u901A\u5E38\u5728\u7528\u6237\u6D4F\u89C8\u5546\u54C1\u65F6\u4EE5\u5E95\u90E8\u60AC\u6D6E\u7684\u5F62\u5F0F\u51FA\u73B0\uFF0C\u5141\u8BB8\u7528\u6237\u5FEB\u901F\u67E5\u770B\u3001\u7F16\u8F91\u8D2D\u7269\u8F66\u5185\u5BB9\u800C\u4E0D\u79BB\u5F00\u5F53\u524D\u9875\u9762\uFF0C\u540C\u65F6\u53EF\u4EE5\u627F\u8F7D\u6EE1\u8D60\uFF0C\u6EE1\u51CF\u7B49\u6D3B\u52A8\u3002\n */\nconst MiniCart = React.forwardRef<HTMLDivElement, MiniCartProps>(\n ({ className, classNames = {}, data, cart, onRemoveItem, onCheckout, onClickToView, ...props }, ref) => {\n const { copy, theme = 'light', locale = 'us' } = data || {}\n\n // \u6587\u6848\u914D\u7F6E\uFF0C\u5E26\u9ED8\u8BA4\u503C\n const emptyCart = copy?.emptyCart || 'Your Cart is Empty'\n const description =\n copy?.description || 'Add one more to get <span style=\"color: var(--brand-color)\">50% <span> off'\n const itemsInCart = copy?.itemsInCart || 'You have selected {count} items'\n const total = copy?.total || 'Total {total}'\n const totalWithCoupon = copy?.totalWithCoupon || 'total: {total} ({subtotal})'\n const clickToView = copy?.clickToView || 'Click to view cart'\n const buyNowText = copy?.buyNowText || 'Buy Now'\n const savingText = copy?.savingText || 'Saving {amount}'\n\n // \u4ECECart\u5BF9\u8C61\u4E2D\u63D0\u53D6\u6570\u636E\uFF0C\u4F7F\u7528\u53EF\u9009\u94FE\u548C\u9ED8\u8BA4\u503C\n const items = cart?.lineItems || []\n const itemCount = items.reduce((total, item) => total + (item?.quantity || 0), 0)\n const isEmpty = itemCount === 0\n\n // \u63D0\u524D\u8D4B\u503C\u6240\u6709\u91D1\u989D\u76F8\u5173\u53D8\u91CF\n const totalAmount = parseFloat(cart?.cost?.totalAmount?.amount || '0')\n const subtotalAmount = parseFloat(cart?.cost?.subtotalAmount?.amount || '0')\n const savingAmount = parseFloat(cart?.cost?.savingAmount?.amount || '0')\n\n // \u8BA1\u7B97\u4EF7\u683C\u4FE1\u606F\n const finalPrice = cart?.cost?.totalAmount?.formattedPrice || ''\n const originalPrice = subtotalAmount > totalAmount ? cart?.cost?.subtotalAmount?.formattedPrice : null\n const savingPrice = savingAmount > 0 ? cart?.cost?.savingAmount?.formattedPrice : null\n\n // \u6EDA\u52A8\u5BB9\u5668\u5F15\u7528\n const scrollContainerRef = React.useRef<HTMLDivElement>(null)\n\n // \u79FB\u52A8\u7AEF\u4EA7\u54C1\u5C55\u5F00\u72B6\u6001\n const [isProductsExpanded, setIsProductsExpanded] = React.useState(false)\n\n // checkout loading \u72B6\u6001\n const [checkoutLoading, setCheckoutLoading] = React.useState(false)\n\n // \u5220\u9664\u5546\u54C1 loading \u72B6\u6001\uFF08\u5B58\u50A8\u6B63\u5728\u5220\u9664\u7684\u5546\u54C1 ID\uFF09\n const [removingItemId, setRemovingItemId] = React.useState<string | null>(null)\n\n // \u5904\u7406\u5220\u9664\u5546\u54C1\n const handleRemoveItem = async (id: string) => {\n if (removingItemId) return\n setRemovingItemId(id)\n try {\n await onRemoveItem?.(id, cart)\n } finally {\n setRemovingItemId(null)\n }\n }\n\n // \u9F20\u6807\u62D6\u62FD\u6EDA\u52A8\u72B6\u6001\n const [isDragging, setIsDragging] = React.useState(false)\n const [startX, setStartX] = React.useState(0)\n const [scrollLeft, setScrollLeft] = React.useState(0)\n\n // \u9F20\u6807\u62D6\u62FD\u6EDA\u52A8\u5904\u7406\n const handleMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {\n if (!scrollContainerRef.current) return\n setIsDragging(true)\n setStartX(e.pageX - scrollContainerRef.current.offsetLeft)\n setScrollLeft(scrollContainerRef.current.scrollLeft)\n }\n\n const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {\n if (!isDragging || !scrollContainerRef.current) return\n e.preventDefault()\n const x = e.pageX - scrollContainerRef.current.offsetLeft\n const walk = (x - startX) * 1.5 // \u6EDA\u52A8\u901F\u5EA6\u500D\u6570\n scrollContainerRef.current.scrollLeft = scrollLeft - walk\n }\n\n const handleMouseUp = () => {\n setIsDragging(false)\n }\n\n const handleMouseLeave = () => {\n setIsDragging(false)\n }\n\n // \u6C34\u5E73\u6EDA\u52A8\u51FD\u6570\n const scrollHorizontally = (direction: 'left' | 'right') => {\n if (scrollContainerRef.current) {\n const container = scrollContainerRef.current\n const scrollAmount = 100 // \u6BCF\u6B21\u6EDA\u52A8\u7684\u50CF\u7D20\u6570\uFF08\u8C03\u5C0F\u4E00\u4E9B\uFF09\n container.scrollBy({ left: direction === 'right' ? scrollAmount : -scrollAmount, behavior: 'smooth' })\n }\n }\n\n // \u7BAD\u5934\u56FE\u6807\u7EC4\u4EF6\n const ArrowIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M6 4L10 8L6 12\"\n stroke=\"currentColor\"\n strokeWidth=\"1.33\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n )\n\n // \u5220\u9664\u56FE\u6807\u7EC4\u4EF6\n const DeleteIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M2.5 5H17.5M8.33333 9.16667V14.1667M11.6667 9.16667V14.1667M3.33333 5L4.16667 16.6667C4.16667 17.1087 4.34226 17.5326 4.65482 17.8452C4.96738 18.1577 5.39131 18.3333 5.83333 18.3333H14.1667C14.6087 18.3333 15.0326 18.1577 15.3452 17.8452C15.6577 17.5326 15.8333 17.1087 15.8333 16.6667L16.6667 5M7.5 5V2.5C7.5 2.27899 7.5878 2.06702 7.74408 1.91074C7.90036 1.75446 8.11232 1.66667 8.33333 1.66667H11.6667C11.8877 1.66667 12.0996 1.75446 12.2559 1.91074C12.4122 2.06702 12.5 2.27899 12.5 2.5V5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.25\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n )\n\n // Render items grid\n const renderItemsGrid = (theme: Theme) => {\n if (!items.length) return null\n\n return (\n <div className={cn('bg-container-primary flex gap-1 rounded-lg p-1', classNames?.itemsGrid)}>\n {/* \u5DE6\u6EDA\u52A8\u6309\u94AE - \u684C\u9762\u7AEF\u663E\u793A */}\n {items.length > 0 && (\n <button\n onClick={() => scrollHorizontally('left')}\n className={cn(\n 'border-border laptop:flex hover:bg-muted-foreground/10 laptop:flex hidden size-12 shrink-0 items-center justify-center rounded-lg transition-colors',\n classNames?.expandButton\n )}\n aria-label=\"Scroll left to see more items\"\n >\n <ArrowIcon className=\"size-4 rotate-180\" />\n </button>\n )}\n\n <div\n ref={scrollContainerRef}\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseLeave}\n className={cn(\n 'scrollbar-hide laptop:gap-1 laptop:max-w-[240px] flex w-full gap-1 overflow-x-auto [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden',\n isDragging ? 'cursor-grabbing' : 'cursor-grab',\n classNames?.itemGridContainer\n )}\n >\n {items\n .filter(line => line && line.id)\n .map(line => {\n const safeproduct = line.merchandise || {}\n const safeImage = safeproduct.image || {}\n const imageUrl = safeImage.url\n const imageAlt = safeImage.altText || 'Product image'\n\n return (\n <div\n key={line.id}\n className={cn(\n 'laptop:size-12 bg-container-secondary laptop:bg-white group relative size-16 shrink-0 rounded-lg',\n classNames?.gridItem\n )}\n >\n {imageUrl && (\n <img\n src={imageUrl}\n alt={imageAlt}\n draggable={false}\n className=\"pointer-events-none size-full select-none rounded-lg object-cover\"\n />\n )}\n {/* \u5220\u9664 loading \u906E\u7F69 */}\n {removingItemId === line.id && (\n <div className=\"absolute inset-0 flex items-center justify-center rounded-lg bg-black/50\">\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"animate-spin text-white\"\n >\n <circle cx=\"8\" cy=\"8\" r=\"6\" stroke=\"currentColor\" strokeWidth=\"2\" opacity=\"0.3\" />\n <path d=\"M14 8a6 6 0 0 0-6-6\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n </div>\n )}\n <span\n role=\"button\"\n onClick={() => handleRemoveItem(line.id)}\n className={cn(\n 'laptop:hidden absolute right-[2px] top-[2px] cursor-pointer',\n removingItemId === line.id && 'pointer-events-none opacity-0'\n )}\n aria-label=\"delete\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"pointer-events-none\"\n >\n <rect x=\"1.33301\" y=\"1.33301\" width=\"13.3333\" height=\"13.3333\" rx=\"6.66667\" fill=\"white\" />\n <path\n d=\"M5.37705 5.28896C5.57234 5.09402 5.88839 5.09442 6.08347 5.28965L8.08602 7.29358L10.0906 5.28896C10.2858 5.09402 10.6026 5.09395 10.7977 5.28896C10.9928 5.48418 10.9926 5.80078 10.7977 5.99607L8.79312 8.00069L10.7964 10.0053C10.9913 10.2007 10.9909 10.5179 10.7957 10.7131C10.6005 10.908 10.2844 10.9074 10.0893 10.7124L8.08602 8.7078L6.08347 10.7103C5.88821 10.9056 5.57155 10.9057 5.37636 10.7103C5.18148 10.515 5.18132 10.1984 5.37636 10.0032L7.37891 8.00069L5.37636 5.99676C5.18119 5.80143 5.18181 5.48423 5.37705 5.28896Z\"\n fill=\"#767880\"\n />\n </svg>\n </span>\n {line.quantity > 1 && (\n <div className=\"mini-cart-quantity bg-brand-0 laptop:size-4 absolute bottom-0 right-0 flex size-4 items-center justify-center rounded-full text-white\">\n <Text className=\"text-sm\" html={String(line.quantity)} />\n </div>\n )}\n\n <div\n className={cn(\n 'laptop:flex absolute inset-0 hidden items-center justify-center rounded-lg bg-black/60 opacity-0 transition-opacity group-hover:opacity-100',\n removingItemId === line.id && 'hidden',\n classNames?.gridItemOverlay\n )}\n >\n <button\n onClick={() => handleRemoveItem(line.id)}\n className=\"flex items-center justify-center rounded-full bg-white/20 p-1 transition-colors hover:bg-white/30\"\n aria-label=\"Remove item\"\n >\n <DeleteIcon className=\"laptop:size-3 pointer-events-none size-4 text-white\" />\n </button>\n </div>\n </div>\n )\n })}\n </div>\n\n {/* \u53F3\u6EDA\u52A8\u6309\u94AE - \u684C\u9762\u7AEF\u663E\u793A */}\n {items.length > 0 && (\n <button\n onClick={() => scrollHorizontally('right')}\n className={cn(\n 'border-border laptop:flex hover:bg-muted-foreground/10 laptop:flex hidden size-12 shrink-0 items-center justify-center rounded-lg transition-colors',\n classNames?.expandButton\n )}\n aria-label=\"Scroll right to see more items\"\n >\n <ArrowIcon className=\"size-4\" />\n </button>\n )}\n </div>\n )\n }\n\n // Check if cart has items\n const hasItems = !isEmpty && items.length > 0\n\n return (\n <div\n ref={ref}\n className={cn(\n 'bg-container-secondary-1 text-info-primary tablet:px-6 laptop:px-12 desktop:px-12 lg-desktop:px-[128px] laptop:py-[16px] flex w-full px-4 py-[12px]',\n // \u79FB\u52A8\u7AEF\u5782\u76F4\u5E03\u5C40\uFF0C\u5927\u5C4F\u5E55\u6C34\u5E73\u5E03\u5C40\n 'flex-col items-stretch gap-3',\n 'laptop:flex-row laptop:items-center laptop:justify-around',\n hasItems ? 'laptop:items-center laptop:gap-4' : 'laptop:items-center laptop:gap-4',\n 'tablet:gap-6 laptop:gap-8',\n className,\n classNames?.root,\n {\n 'aiui-dark bg-container-primary': theme === 'dark',\n }\n )}\n {...props}\n >\n {/* \u79FB\u52A8\u7AEF\uFF1A\u5782\u76F4\u6392\u5217 | \u684C\u9762\u7AEF\uFF1A\u6C34\u5E73\u4E09\u5217\u5E03\u5C40 */}\n <div\n className={cn(\n 'laptop:flex-row flex w-full flex-col gap-4',\n 'laptop:flex-1 laptop:items-start',\n 'tablet:gap-6 laptop:gap-8',\n classNames?.content\n )}\n >\n {/* Center: Cart info and dynamic content */}\n <div className=\"laptop:flex-1 flex w-full flex-col\">\n {/* Cart title area */}\n <div className={cn('tablet:gap-2 flex flex-col gap-1', classNames?.cartInfo)}>\n {hasItems ? (\n <div className=\"flex w-full items-center gap-2\">\n <Heading\n size={2}\n as=\"h3\"\n className={cn('', classNames?.cartTitle)}\n html={itemsInCart.replace('{count}', `<span class=\"text-brand-0\">${itemCount || 0}</span>`)}\n />\n\n {/* Click to view link / Toggle products */}\n <Heading\n size={1}\n as=\"h5\"\n onClick={() => {\n // \u79FB\u52A8\u7AEF\uFF1A\u5207\u6362\u4EA7\u54C1\u5C55\u5F00\u72B6\u6001\uFF0C\u684C\u9762\u7AEF\uFF1A\u8C03\u7528\u539F\u56DE\u8C03\n const isMobile = window.innerWidth < 1025\n if (isMobile) {\n setIsProductsExpanded(!isProductsExpanded)\n } else {\n onClickToView?.(cart)\n }\n }}\n className={cn('flex cursor-pointer items-center gap-1', classNames?.expandButton)}\n >\n {/* \u684C\u9762\u7AEF\u663E\u793A\u6587\u5B57 + \u56FE\u6807\uFF0C\u79FB\u52A8\u7AEF\u53EA\u663E\u793A\u56FE\u6807 */}\n <Heading as=\"h6\" size={1} className=\"laptop:block hidden text-nowrap\" html={clickToView} />\n <ArrowIcon\n className={cn(\n 'size-4 transition-transform',\n isProductsExpanded ? 'laptop:rotate-0 -rotate-90' : 'laptop:rotate-0 rotate-90'\n )}\n />\n </Heading>\n </div>\n ) : (\n <Heading\n as=\"h3\"\n size={2}\n className={cn('tablet:text-2xl text-xl font-semibold', classNames?.cartTitle)}\n html={emptyCart}\n />\n )}\n </div>\n <div>\n {description && (\n <Text\n size={2}\n className={cn('mini-cart-description', classNames?.cartDescription)}\n html={description}\n />\n )}\n </div>\n </div>\n\n {/* Items grid (\u79FB\u52A8\u7AEF\uFF1A\u6839\u636E\u5C55\u5F00\u72B6\u6001\u663E\u793A\uFF0C\u684C\u9762\u7AEF\uFF1A\u59CB\u7EC8\u663E\u793A) */}\n {hasItems && (\n <div className={cn('laptop:block', isProductsExpanded ? 'block' : 'hidden')}>{renderItemsGrid(theme)}</div>\n )}\n {/* \u79FB\u52A8\u7AEF\uFF1A\u5206\u5272\u7EBF\uFF08\u53EA\u5728\u6709\u5546\u54C1\u65F6\u663E\u793A\uFF09 */}\n {hasItems && <hr className=\"laptop:hidden border-lines w-full border-t\" />}\n\n {/* Price and button area */}\n <div\n className={cn(\n 'tablet:gap-6 laptop:justify-end flex flex-row items-center justify-between gap-4',\n classNames?.priceSection\n )}\n >\n {/* Price info */}\n <div className=\"flex flex-col items-end justify-center gap-1\">\n {/* Main price row */}\n <div className=\"flex items-center gap-2\">\n <Heading\n as=\"h6\"\n size={2}\n className={cn(' whitespace-nowrap ', classNames?.totalPrice)}\n html={total.replace('{total}', finalPrice)}\n />\n\n {/* Original price (if discounted) */}\n {originalPrice && (\n <Heading\n as=\"h6\"\n size={2}\n className={cn('whitespace-nowrap line-through', classNames?.originalPrice)}\n html={originalPrice}\n />\n )}\n </div>\n\n {/* Save amount */}\n {savingPrice && (\n <Heading\n size={2}\n as=\"h6\"\n className={cn('laptop:text-right text-marketing-0 w-full text-left', classNames?.saveAmount)}\n html={savingText.replace('{amount}', savingPrice)}\n />\n )}\n </div>\n\n {/* Action button */}\n <Button\n disabled={!hasItems}\n loading={checkoutLoading}\n onClick={async () => {\n if (checkoutLoading) return\n setCheckoutLoading(true)\n try {\n await onCheckout?.(cart)\n } finally {\n setCheckoutLoading(false)\n }\n }}\n className={cn('whitespace-nowrap', classNames?.actionButton)}\n >\n {buyNowText}\n </Button>\n </div>\n </div>\n </div>\n )\n }\n)\n\nMiniCart.displayName = 'MiniCart'\nexport default MiniCart\n"],
|
|
5
|
-
"mappings": "
|
|
6
|
-
"names": ["jsx", "jsxs", "React", "cn", "Button", "Text", "Heading", "MiniCart", "className", "classNames", "data", "cart", "onRemoveItem", "onCheckout", "onClickToView", "props", "ref", "copy", "theme", "locale", "emptyCart", "description", "itemsInCart", "total", "totalWithCoupon", "clickToView", "buyNowText", "savingText", "items", "itemCount", "item", "isEmpty", "totalAmount", "subtotalAmount", "savingAmount", "finalPrice", "originalPrice", "savingPrice", "scrollContainerRef", "isProductsExpanded", "setIsProductsExpanded", "checkoutLoading", "setCheckoutLoading", "removingItemId", "setRemovingItemId", "handleRemoveItem", "id", "isDragging", "setIsDragging", "startX", "setStartX", "scrollLeft", "setScrollLeft", "
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { cn } from '../../helpers/index.js'\nimport { Button } from '../../components/index.js'\nimport { Text } from '../../components/index.js'\nimport { Heading } from '../../components/index.js'\nimport type { Theme, Img } from '../../types/props.js'\nimport CircleProgress from './CircleProgress.js'\n\nexport type MiniCartSemanticName =\n | 'root'\n | 'content'\n | 'cartInfo'\n | 'cartTitle'\n | 'cartDescription'\n | 'priceSection'\n | 'totalPrice'\n | 'originalPrice'\n | 'saveAmount'\n | 'actionButton'\n | 'itemsGrid'\n | 'itemGridContainer'\n | 'gridItem'\n | 'gridItemOverlay'\n | 'expandButton'\n | 'circleProgress'\n | 'mobileViewMoreButton'\n\n/**\n * \u5706\u5F62\u8FDB\u5EA6\u6761\u914D\u7F6E\n */\nexport interface CircleProgressConfig {\n /** \u603B\u9636\u6BB5\u6570 (1-4) */\n totalSteps?: 1 | 2 | 3 | 4\n /** \u5F53\u524D\u5B8C\u6210\u7684\u9636\u6BB5 (0 \u5230 totalSteps) */\n currentStep?: number\n /** \u4E2D\u95F4\u663E\u793A\u7684\u56FE\u7247 */\n image?: Img\n /** \u5E95\u90E8\u663E\u793A\u7684\u6587\u6848 */\n label?: string\n /** \u8FDB\u5EA6\u6761\u989C\u8272\uFF0C\u9ED8\u8BA4\u4E3A\u54C1\u724C\u8272 */\n progressColor?: string\n /** \u5E95\u90E8\u6587\u6848\u80CC\u666F\u8272\uFF0C\u9ED8\u8BA4\u4E3A\u54C1\u724C\u8425\u9500\u8272 */\n labelColor?: string\n /** \u80CC\u666F\u989C\u8272\uFF0C\u9ED8\u8BA4\u4E3A\u5BB9\u5668\u80CC\u666F\u8272 */\n backgroundColor?: string\n /** \u79FB\u52A8\u7AEF\u7EC4\u4EF6\u5C3A\u5BF8\uFF0C\u9ED8\u8BA4 48 */\n size?: number\n /** laptop \u4EE5\u4E0A\u7EC4\u4EF6\u5C3A\u5BF8\uFF0C\u9ED8\u8BA4 80 */\n laptopSize?: number\n}\n\n/**\n * \u6587\u6848\u914D\u7F6E\n */\nexport interface MiniCartCopy {\n emptyCart: string\n description: string\n total: string\n itemsInCart: string\n totalWithCoupon: string\n clickToView: string\n buyNowText: string\n savingText: string\n}\n\n/**\n * MiniCart \u4E1A\u52A1\u7EC4\u4EF6\u6570\u636E\u63A5\u53E3\n */\nexport interface MiniCartData {\n /** \u6587\u6848\u914D\u7F6E */\n copy?: MiniCartCopy\n theme?: 'light' | 'dark'\n /** \u5730\u533A\u4EE3\u7801\uFF0C\u7528\u4E8E\u4EF7\u683C\u683C\u5F0F\u5316 */\n locale?: string\n /** \u662F\u5426\u663E\u793A\u624B\u673A\u7AEF\u67E5\u770B\u66F4\u591A\u6309\u94AE\uFF0C\u9ED8\u8BA4 true */\n showMobileViewMore?: boolean\n}\n\n/**\n * \u8D2D\u7269\u8F66\u5546\u54C1\u9879\u7C7B\u578B\n */\nexport type CartLineItem = {\n id: string\n quantity: number\n cost: {\n totalAmount: {\n amount: string\n currencyCode: string\n formattedPrice: string\n }\n subtotalAmount?: {\n amount: string\n currencyCode: string\n formattedPrice?: string\n }\n }\n merchandise: {\n id: string\n sku: string\n /** \u5546\u54C1\u6807\u9898 - MiniCartDialog \u9700\u8981 */\n title?: string\n image: {\n url: string\n altText: string | null\n }\n }\n}\n\n/**\n * \u8D2D\u7269\u8F66\u7C7B\u578B\n */\nexport type Cart = {\n id: string\n checkoutUrl: string\n lineItems: CartLineItem[]\n cost: {\n totalAmount: {\n amount: string\n currencyCode: string\n formattedPrice: string\n }\n subtotalAmount?: {\n amount: string\n currencyCode: string\n formattedPrice?: string\n }\n savingAmount?: {\n amount?: string\n currencyCode: string\n formattedPrice?: string\n }\n }\n}\n\nexport interface MiniCartProps extends React.HTMLAttributes<HTMLDivElement> {\n /** \u4E1A\u52A1\u6570\u636E */\n data: MiniCartData\n /**\n * \u5404\u90E8\u5206\u7684\u81EA\u5B9A\u4E49\u6837\u5F0F\u7C7B\u540D\n */\n classNames?: Partial<Record<MiniCartSemanticName, string>>\n /**\n * \u4EA7\u54C1\u4FE1\u606F\uFF08\u7528\u4E8E\u4E3B\u8981\u5C55\u793A\u7684\u4EA7\u54C1\uFF09\n */\n cart: Cart\n /**\n * \u5706\u5F62\u8FDB\u5EA6\u6761\u914D\u7F6E\uFF0C\u4E0D\u4F20\u5219\u4E0D\u663E\u793A\u8FDB\u5EA6\u6761\n */\n progressConfig?: CircleProgressConfig\n /**\n * \u5220\u9664\u5546\u54C1\u9879\u7684\u56DE\u8C03\u51FD\u6570\n * @param id \u5546\u54C1 ID\n * @param cart \u8D2D\u7269\u8F66\u6570\u636E\n * @returns \u652F\u6301\u8FD4\u56DE Promise\uFF0C\u5185\u90E8\u81EA\u52A8\u5904\u7406 loading \u72B6\u6001\n */\n onRemoveItem?: (id: string, cart: Cart) => void | Promise<void>\n /**\n * \u70B9\u51FB\u7ED3\u7B97\u6309\u94AE\u7684\u56DE\u8C03\u51FD\u6570\n * @param cart\n * @returns \u652F\u6301\u8FD4\u56DE Promise\uFF0C\u5185\u90E8\u81EA\u52A8\u5904\u7406 loading \u72B6\u6001\n */\n onCheckout?: (cart: Cart) => void | Promise<void>\n /**\n * \u70B9\u51FBclick to view\u7684\u56DE\u8C03\u51FD\u6570\n * @param cart\n * @returns\n */\n onClickToView?: (cart: Cart) => void\n}\n\n/**\n * MiniCart - \u8FF7\u4F60\u8D2D\u7269\u8F66\n *\n * @description \u8FF7\u4F60\u8D2D\u7269\u8F66\uFF08Mini Cart\uFF09\u662F\u4E00\u4E2A\u5E38\u89C1\u7684\u7535\u5546UI\u7EC4\u4EF6\uFF0C\u901A\u5E38\u5728\u7528\u6237\u6D4F\u89C8\u5546\u54C1\u65F6\u4EE5\u5E95\u90E8\u60AC\u6D6E\u7684\u5F62\u5F0F\u51FA\u73B0\uFF0C\u5141\u8BB8\u7528\u6237\u5FEB\u901F\u67E5\u770B\u3001\u7F16\u8F91\u8D2D\u7269\u8F66\u5185\u5BB9\u800C\u4E0D\u79BB\u5F00\u5F53\u524D\u9875\u9762\uFF0C\u540C\u65F6\u53EF\u4EE5\u627F\u8F7D\u6EE1\u8D60\uFF0C\u6EE1\u51CF\u7B49\u6D3B\u52A8\u3002\n */\nconst MiniCart = React.forwardRef<HTMLDivElement, MiniCartProps>(\n (\n { className, classNames = {}, data, cart, progressConfig, onRemoveItem, onCheckout, onClickToView, ...props },\n ref\n ) => {\n const { copy, theme = 'light', locale = 'us', showMobileViewMore = true } = data || {}\n\n // \u6587\u6848\u914D\u7F6E\uFF0C\u5E26\u9ED8\u8BA4\u503C\n const emptyCart = copy?.emptyCart || 'Your Cart is Empty'\n const description = copy?.description || ''\n const itemsInCart = copy?.itemsInCart || 'You have selected {count} items'\n const total = copy?.total || 'Total {total}'\n const totalWithCoupon = copy?.totalWithCoupon || 'total: {total} ({subtotal})'\n const clickToView = copy?.clickToView || 'Click to view cart'\n const buyNowText = copy?.buyNowText || 'Buy Now'\n const savingText = copy?.savingText || 'Saving {amount}'\n\n // \u4ECECart\u5BF9\u8C61\u4E2D\u63D0\u53D6\u6570\u636E\uFF0C\u4F7F\u7528\u53EF\u9009\u94FE\u548C\u9ED8\u8BA4\u503C\n const items = React.useMemo(() => cart?.lineItems || [], [cart?.lineItems])\n const itemCount = items.reduce((total, item) => total + (item?.quantity || 0), 0)\n const isEmpty = itemCount === 0\n\n // \u63D0\u524D\u8D4B\u503C\u6240\u6709\u91D1\u989D\u76F8\u5173\u53D8\u91CF\n const totalAmount = parseFloat(cart?.cost?.totalAmount?.amount || '0')\n const subtotalAmount = parseFloat(cart?.cost?.subtotalAmount?.amount || '0')\n const savingAmount = parseFloat(cart?.cost?.savingAmount?.amount || '0')\n\n // \u8BA1\u7B97\u4EF7\u683C\u4FE1\u606F\n const finalPrice = cart?.cost?.totalAmount?.formattedPrice || ''\n const originalPrice = subtotalAmount > totalAmount ? cart?.cost?.subtotalAmount?.formattedPrice : null\n const savingPrice = savingAmount > 0 ? cart?.cost?.savingAmount?.formattedPrice : null\n\n // \u6EDA\u52A8\u5BB9\u5668\u5F15\u7528\n const scrollContainerRef = React.useRef<HTMLDivElement>(null)\n\n // \u79FB\u52A8\u7AEF\u4EA7\u54C1\u5C55\u5F00\u72B6\u6001\n const [isProductsExpanded, setIsProductsExpanded] = React.useState(false)\n\n // checkout loading \u72B6\u6001\n const [checkoutLoading, setCheckoutLoading] = React.useState(false)\n\n // \u5220\u9664\u5546\u54C1 loading \u72B6\u6001\n const [removingItemId, setRemovingItemId] = React.useState<string | null>(null)\n\n // \u5904\u7406\u5220\u9664\u5546\u54C1\n const handleRemoveItem = async (id: string) => {\n if (removingItemId) return\n setRemovingItemId(id)\n try {\n await onRemoveItem?.(id, cart)\n } finally {\n setRemovingItemId(null)\n }\n }\n\n // \u9F20\u6807\u62D6\u62FD\u6EDA\u52A8\u72B6\u6001\n const [isDragging, setIsDragging] = React.useState(false)\n const [startX, setStartX] = React.useState(0)\n const [scrollLeft, setScrollLeft] = React.useState(0)\n\n // \u6EDA\u52A8\u4F4D\u7F6E\u72B6\u6001\uFF08\u63A7\u5236\u5DE6\u53F3\u6309\u94AE\u663E\u793A\uFF09\n const [canScrollLeft, setCanScrollLeft] = React.useState(false)\n const [canScrollRight, setCanScrollRight] = React.useState(true)\n\n // \u68C0\u67E5\u6EDA\u52A8\u4F4D\u7F6E\uFF0C\u66F4\u65B0\u6309\u94AE\u663E\u793A\u72B6\u6001\n const updateScrollButtons = React.useCallback(() => {\n const container = scrollContainerRef.current\n if (!container) return\n\n const { scrollLeft, scrollWidth, clientWidth } = container\n setCanScrollLeft(scrollLeft > 0)\n setCanScrollRight(scrollLeft < scrollWidth - clientWidth - 1)\n }, [])\n\n // \u76D1\u542C\u6EDA\u52A8\u4E8B\u4EF6\n const handleScroll = React.useCallback(() => {\n updateScrollButtons()\n }, [updateScrollButtons])\n\n // \u521D\u59CB\u5316\u548C items \u53D8\u5316\u65F6\u66F4\u65B0\u6EDA\u52A8\u72B6\u6001\n React.useEffect(() => {\n updateScrollButtons()\n }, [items.length, updateScrollButtons])\n\n // \u9F20\u6807\u62D6\u62FD\u6EDA\u52A8\u5904\u7406\n const handleMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {\n if (!scrollContainerRef.current) return\n setIsDragging(true)\n setStartX(e.pageX - scrollContainerRef.current.offsetLeft)\n setScrollLeft(scrollContainerRef.current.scrollLeft)\n }\n\n const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {\n if (!isDragging || !scrollContainerRef.current) return\n e.preventDefault()\n const x = e.pageX - scrollContainerRef.current.offsetLeft\n const walk = (x - startX) * 1.5 // \u6EDA\u52A8\u901F\u5EA6\u500D\u6570\n scrollContainerRef.current.scrollLeft = scrollLeft - walk\n }\n\n const handleMouseUp = () => {\n setIsDragging(false)\n }\n\n const handleMouseLeave = () => {\n setIsDragging(false)\n }\n\n // \u6C34\u5E73\u6EDA\u52A8\u51FD\u6570\n const scrollHorizontally = (direction: 'left' | 'right') => {\n if (scrollContainerRef.current) {\n const container = scrollContainerRef.current\n const scrollAmount = 100 // \u6BCF\u6B21\u6EDA\u52A8\u7684\u50CF\u7D20\u6570\uFF08\u8C03\u5C0F\u4E00\u4E9B\uFF09\n container.scrollBy({ left: direction === 'right' ? scrollAmount : -scrollAmount, behavior: 'smooth' })\n }\n }\n\n // \u7BAD\u5934\u56FE\u6807\u7EC4\u4EF6\n const ArrowIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M6 4L10 8L6 12\"\n stroke=\"currentColor\"\n strokeWidth=\"1.33\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n )\n\n // \u5220\u9664\u56FE\u6807\u7EC4\u4EF6\n const DeleteIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M2.5 5H17.5M8.33333 9.16667V14.1667M11.6667 9.16667V14.1667M3.33333 5L4.16667 16.6667C4.16667 17.1087 4.34226 17.5326 4.65482 17.8452C4.96738 18.1577 5.39131 18.3333 5.83333 18.3333H14.1667C14.6087 18.3333 15.0326 18.1577 15.3452 17.8452C15.6577 17.5326 15.8333 17.1087 15.8333 16.6667L16.6667 5M7.5 5V2.5C7.5 2.27899 7.5878 2.06702 7.74408 1.91074C7.90036 1.75446 8.11232 1.66667 8.33333 1.66667H11.6667C11.8877 1.66667 12.0996 1.75446 12.2559 1.91074C12.4122 2.06702 12.5 2.27899 12.5 2.5V5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.25\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n )\n\n // Render items grid\n const renderItemsGrid = (theme: Theme) => {\n if (!items.length) return null\n\n return (\n <div className={cn('laptop:bg-container-secondary-0 flex gap-1 rounded-lg p-1', classNames?.itemsGrid)}>\n {/* \u5DE6\u6EDA\u52A8\u6309\u94AE - \u684C\u9762\u7AEF\u663E\u793A\uFF0C\u5C11\u4E8E5\u4E2A\u5546\u54C1\u65F6\u4E0D\u6E32\u67D3\uFF0C\u6EDA\u52A8\u5230\u5F00\u5934\u65F6\u9690\u85CF\u4F46\u4FDD\u6301\u5360\u4F4D */}\n {items.length >= 5 && (\n <button\n onClick={() => scrollHorizontally('left')}\n className={cn(\n 'border-border laptop:flex hover:bg-muted-foreground/10 hidden w-[32px] shrink-0 items-center justify-center rounded-lg px-2 transition-colors',\n !canScrollLeft &&\n 'laptop:bg-container-secondary-1 laptop:text-transparent laptop:pointer-events-none laptop:-my-1 laptop:-ml-1 laptop:py-1 laptop:pl-1 laptop:rounded-r-none',\n classNames?.expandButton,\n {\n 'laptop:bg-container-secondary-0': theme === 'dark',\n 'laptop:bg-container-primary': theme === 'dark' && !canScrollLeft,\n }\n )}\n aria-label=\"Scroll left to see more items\"\n >\n <ArrowIcon className=\"laptop:size-4 size-5 rotate-180\" />\n </button>\n )}\n\n <div\n ref={scrollContainerRef}\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseLeave}\n onScroll={handleScroll}\n className={cn(\n 'scrollbar-hide laptop:gap-1 laptop:w-[256px] laptop:shrink-0 flex w-full gap-1 overflow-x-auto [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden',\n isDragging ? 'cursor-grabbing' : 'cursor-grab',\n classNames?.itemGridContainer\n )}\n >\n {items\n .filter(line => line && line.id)\n .map(line => {\n const safeProduct = line.merchandise || {}\n const safeImage = safeProduct.image || {}\n const imageUrl = safeImage.url\n const imageAlt = safeImage.altText || 'Product image'\n const isLoading = removingItemId === line.id\n\n return (\n <div\n key={line.id}\n className={cn('laptop:size-12 group relative size-16 shrink-0', classNames?.gridItem)}\n >\n {imageUrl && (\n <img\n src={imageUrl}\n alt={imageAlt}\n draggable={false}\n className=\"pointer-events-none size-full select-none rounded-lg object-cover\"\n />\n )}\n {/* \u5220\u9664 loading \u906E\u7F69 */}\n {isLoading && (\n <div className=\"absolute inset-0 flex items-center justify-center rounded-lg bg-black/50\">\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"animate-spin text-white\"\n >\n <circle cx=\"8\" cy=\"8\" r=\"6\" stroke=\"currentColor\" strokeWidth=\"2\" opacity=\"0.3\" />\n <path d=\"M14 8a6 6 0 0 0-6-6\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n </div>\n )}\n <span\n role=\"button\"\n onClick={() => handleRemoveItem(line.id)}\n className={cn(\n 'laptop:hidden absolute right-[2px] top-[2px] cursor-pointer',\n isLoading && 'pointer-events-none opacity-0'\n )}\n aria-label=\"delete\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"pointer-events-none\"\n >\n <rect x=\"1.33301\" y=\"1.33301\" width=\"13.3333\" height=\"13.3333\" rx=\"6.66667\" fill=\"white\" />\n <path\n d=\"M5.37705 5.28896C5.57234 5.09402 5.88839 5.09442 6.08347 5.28965L8.08602 7.29358L10.0906 5.28896C10.2858 5.09402 10.6026 5.09395 10.7977 5.28896C10.9928 5.48418 10.9926 5.80078 10.7977 5.99607L8.79312 8.00069L10.7964 10.0053C10.9913 10.2007 10.9909 10.5179 10.7957 10.7131C10.6005 10.908 10.2844 10.9074 10.0893 10.7124L8.08602 8.7078L6.08347 10.7103C5.88821 10.9056 5.57155 10.9057 5.37636 10.7103C5.18148 10.515 5.18132 10.1984 5.37636 10.0032L7.37891 8.00069L5.37636 5.99676C5.18119 5.80143 5.18181 5.48423 5.37705 5.28896Z\"\n fill=\"#767880\"\n />\n </svg>\n </span>\n {line.quantity > 1 && (\n <div className=\"mini-cart-quantity bg-brand-0 laptop:size-4 absolute bottom-0 right-0 flex size-4 items-center justify-center rounded-full text-white\">\n <Text className=\"text-sm\" html={String(line.quantity)} />\n </div>\n )}\n\n <div\n role=\"button\"\n onClick={() => handleRemoveItem(line.id)}\n className={cn(\n 'absolute inset-0 hidden cursor-pointer items-center justify-center rounded-lg bg-black/60 transition-opacity',\n 'laptop:flex laptop:opacity-0 laptop:group-hover:opacity-100',\n isLoading && 'laptop:hidden',\n classNames?.gridItemOverlay\n )}\n aria-label=\"Remove item\"\n >\n <DeleteIcon className=\"pointer-events-none size-[20px] text-white\" />\n </div>\n </div>\n )\n })}\n\n {/* \u624B\u673A\u7AEF\u67E5\u770B\u66F4\u591A\u6309\u94AE */}\n {showMobileViewMore && (\n <button\n onClick={() => onClickToView?.(cart)}\n className={cn(\n 'bg-container-secondary-0 laptop:hidden flex size-16 shrink-0 items-center justify-center rounded-md',\n classNames?.mobileViewMoreButton\n )}\n aria-label={clickToView}\n >\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"text-info-quaternary\"\n >\n <path\n d=\"M7.5 5L12.5 10L7.5 15\"\n stroke=\"currentColor\"\n strokeWidth=\"1.67\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n )}\n </div>\n\n {/* \u53F3\u6EDA\u52A8\u6309\u94AE - \u684C\u9762\u7AEF\u663E\u793A\uFF0C\u5C11\u4E8E5\u4E2A\u5546\u54C1\u65F6\u4E0D\u6E32\u67D3\uFF0C\u6EDA\u52A8\u5230\u7ED3\u5C3E\u65F6\u9690\u85CF\u4F46\u4FDD\u6301\u5360\u4F4D */}\n {items.length >= 5 && (\n <button\n onClick={() => scrollHorizontally('right')}\n className={cn(\n 'border-border laptop:flex hover:bg-muted-foreground/10 hidden w-[32px] shrink-0 items-center justify-center rounded-lg px-2 transition-colors',\n !canScrollRight &&\n 'laptop:bg-container-secondary-1 laptop:text-transparent laptop:pointer-events-none laptop:-my-1 laptop:-mr-1 laptop:py-1 laptop:pr-1 laptop:rounded-l-none',\n classNames?.expandButton,\n {\n 'laptop:bg-container-secondary-0': theme === 'dark',\n 'laptop:bg-container-primary': theme === 'dark' && !canScrollRight,\n }\n )}\n aria-label=\"Scroll right to see more items\"\n >\n <ArrowIcon className=\"laptop:size-4 size-5\" />\n </button>\n )}\n </div>\n )\n }\n\n // Check if cart has items\n const hasItems = !isEmpty && items.length > 0\n\n return (\n <div\n ref={ref}\n className={cn(\n 'bg-container-secondary-1 text-info-primary tablet:px-6 laptop:px-12 desktop:px-12 lg-desktop:px-[128px] laptop:py-[16px] flex w-full px-4 py-[12px]',\n // \u79FB\u52A8\u7AEF\u5782\u76F4\u5E03\u5C40\uFF0C\u5927\u5C4F\u5E55\u6C34\u5E73\u5E03\u5C40\n 'flex-col items-stretch gap-3',\n 'laptop:flex-row laptop:items-center laptop:justify-around',\n hasItems ? 'laptop:items-center laptop:gap-4' : 'laptop:items-center laptop:gap-4',\n 'tablet:gap-6 laptop:gap-8',\n className,\n classNames?.root,\n {\n 'aiui-dark bg-container-primary': theme === 'dark',\n }\n )}\n {...props}\n >\n {/* \u79FB\u52A8\u7AEF\uFF1A\u5782\u76F4\u6392\u5217 | \u684C\u9762\u7AEF\uFF1A\u6C34\u5E73\u4E09\u5217\u5E03\u5C40 */}\n <div\n className={cn(\n 'laptop:flex-row flex w-full flex-col gap-4',\n 'laptop:flex-1 laptop:items-center laptop:justify-between',\n 'tablet:gap-6 laptop:gap-8',\n classNames?.content\n )}\n >\n <div\n className={cn(\n 'relative flex shrink flex-row items-center gap-2',\n 'desktop:gap-4',\n progressConfig && 'laptop:pl-[104px] pl-[72px]'\n )}\n >\n {/* \u5DE6\u4FA7\u5706\u5F62\u8FDB\u5EA6\u6761 - \u53EA\u6709\u914D\u7F6E\u4E86\u624D\u663E\u793A */}\n {progressConfig && (\n <CircleProgress\n totalSteps={progressConfig.totalSteps}\n currentStep={progressConfig.currentStep}\n image={progressConfig.image}\n label={progressConfig.label}\n progressColor={progressConfig.progressColor}\n labelColor={progressConfig.labelColor}\n backgroundColor={progressConfig.backgroundColor}\n size={progressConfig.size}\n laptopSize={progressConfig.laptopSize}\n className={cn(\n 'absolute bottom-0 left-0',\n 'lg-desktop:bottom-auto lg-desktop:top-[-46px] desktop:bottom-auto desktop:top-[-52px]',\n classNames?.circleProgress\n )}\n />\n )}\n {/* Center: Cart info and dynamic content */}\n <div className=\"laptop:flex-1 flex w-full flex-col\">\n {/* Cart title area */}\n <div className={cn('tablet:gap-2 flex flex-col gap-1', classNames?.cartInfo)}>\n {hasItems ? (\n <div className=\"flex w-full items-center gap-2\">\n <Heading\n size={2}\n as=\"h3\"\n className={cn('', classNames?.cartTitle)}\n html={itemsInCart.replace('{count}', `<span class=\"text-brand-0\">${itemCount || 0}</span>`)}\n />\n\n {/* Click to view link / Toggle products */}\n <Heading\n size={1}\n as=\"h5\"\n onClick={() => {\n // \u79FB\u52A8\u7AEF\uFF1A\u5207\u6362\u4EA7\u54C1\u5C55\u5F00\u72B6\u6001\uFF0C\u684C\u9762\u7AEF\uFF1A\u8C03\u7528\u539F\u56DE\u8C03\n const isMobile = window.innerWidth < 1025\n if (isMobile) {\n setIsProductsExpanded(!isProductsExpanded)\n } else {\n onClickToView?.(cart)\n }\n }}\n className={cn('flex cursor-pointer items-center gap-1', classNames?.expandButton)}\n >\n {/* \u684C\u9762\u7AEF\u663E\u793A\u6587\u5B57 + \u56FE\u6807\uFF0C\u79FB\u52A8\u7AEF\u53EA\u663E\u793A\u56FE\u6807 */}\n <Text\n as=\"span\"\n size={1}\n className=\"desktop:block hidden text-nowrap text-[16px] \"\n html={clickToView}\n />\n <ArrowIcon\n className={cn(\n 'size-4 transition-transform',\n isProductsExpanded ? 'laptop:rotate-0 -rotate-90' : 'laptop:rotate-0 rotate-90'\n )}\n />\n </Heading>\n </div>\n ) : (\n <Heading\n as=\"h3\"\n size={2}\n className={cn('tablet:text-2xl text-xl font-semibold', classNames?.cartTitle)}\n html={emptyCart}\n />\n )}\n </div>\n\n {description && (\n <Text\n size={2}\n className={cn(\n 'mini-cart-description text-info-tertiary desktop:text-[16px] lg-desktop:text-[18px] text-[14px]',\n classNames?.cartDescription\n )}\n html={description}\n />\n )}\n </div>\n </div>\n\n {/* Items grid (\u79FB\u52A8\u7AEF\uFF1A\u6839\u636E\u5C55\u5F00\u72B6\u6001\u663E\u793A\uFF0C\u684C\u9762\u7AEF\uFF1A\u59CB\u7EC8\u663E\u793A) */}\n {hasItems && (\n <div className={cn('laptop:block laptop:shrink', isProductsExpanded ? 'block' : 'hidden')}>\n {renderItemsGrid(theme)}\n </div>\n )}\n {/* \u79FB\u52A8\u7AEF\uFF1A\u5206\u5272\u7EBF\uFF08\u53EA\u5728\u6709\u5546\u54C1\u65F6\u663E\u793A\uFF09 */}\n {hasItems && <hr className=\"laptop:hidden border-lines w-full border-t\" />}\n\n {/* Price and button area */}\n <div\n className={cn(\n 'tablet:gap-6 laptop:gap-4 laptop:justify-end flex flex-row items-stretch justify-between gap-4',\n classNames?.priceSection\n )}\n >\n {/* Price info */}\n <div className=\"flex flex-col items-end justify-center\">\n {/* Main price row */}\n <div className=\"flex items-center gap-2\">\n <Heading\n as=\"h6\"\n size={2}\n className={cn('whitespace-nowrap text-nowrap', classNames?.totalPrice)}\n html={total.replace('{total}', finalPrice)}\n />\n\n {/* Original price (if discounted) */}\n {originalPrice && (\n <Heading\n as=\"h6\"\n size={2}\n className={cn('text-info-tertiary whitespace-nowrap line-through', classNames?.originalPrice)}\n html={originalPrice}\n />\n )}\n </div>\n\n {/* Save amount */}\n {savingPrice && (\n <Heading\n size={2}\n as=\"h6\"\n className={cn(\n 'laptop:text-right text-marketing-1 w-full whitespace-nowrap text-nowrap text-left',\n classNames?.saveAmount\n )}\n html={savingText.replace('{amount}', savingPrice)}\n />\n )}\n </div>\n\n {/* Action button */}\n <Button\n disabled={!hasItems}\n loading={checkoutLoading}\n onClick={async () => {\n if (checkoutLoading) return\n setCheckoutLoading(true)\n try {\n await onCheckout?.(cart)\n } finally {\n setCheckoutLoading(false)\n }\n }}\n className={cn('whitespace-nowrap', classNames?.actionButton)}\n >\n {buyNowText}\n </Button>\n </div>\n </div>\n </div>\n )\n }\n)\n\nMiniCart.displayName = 'MiniCart'\nexport default MiniCart\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["jsx", "jsxs", "React", "cn", "Button", "Text", "Heading", "CircleProgress", "MiniCart", "className", "classNames", "data", "cart", "progressConfig", "onRemoveItem", "onCheckout", "onClickToView", "props", "ref", "copy", "theme", "locale", "showMobileViewMore", "emptyCart", "description", "itemsInCart", "total", "totalWithCoupon", "clickToView", "buyNowText", "savingText", "items", "itemCount", "item", "isEmpty", "totalAmount", "subtotalAmount", "savingAmount", "finalPrice", "originalPrice", "savingPrice", "scrollContainerRef", "isProductsExpanded", "setIsProductsExpanded", "checkoutLoading", "setCheckoutLoading", "removingItemId", "setRemovingItemId", "handleRemoveItem", "id", "isDragging", "setIsDragging", "startX", "setStartX", "scrollLeft", "setScrollLeft", "canScrollLeft", "setCanScrollLeft", "canScrollRight", "setCanScrollRight", "updateScrollButtons", "container", "scrollWidth", "clientWidth", "handleScroll", "handleMouseDown", "handleMouseMove", "walk", "handleMouseUp", "handleMouseLeave", "scrollHorizontally", "direction", "scrollAmount", "ArrowIcon", "DeleteIcon", "renderItemsGrid", "line", "safeImage", "imageUrl", "imageAlt", "isLoading", "hasItems", "MiniCart_default"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { PriceData } from './types.js';
|
|
3
|
+
export interface SceneShelfFooterProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
/** 总价标签 */
|
|
5
|
+
totalPriceLabel?: string;
|
|
6
|
+
/** 当前总价 */
|
|
7
|
+
totalCurrentPrice?: PriceData;
|
|
8
|
+
/** 原总价 */
|
|
9
|
+
totalOriginalPrice?: PriceData;
|
|
10
|
+
/** 添加到购物车按钮文本 */
|
|
11
|
+
addToCartButtonText?: string;
|
|
12
|
+
/** 立即购买按钮文本 */
|
|
13
|
+
shopNowButtonText?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* SceneShelf Footer 组件
|
|
17
|
+
*
|
|
18
|
+
* @description 底部区域,包含总价和按钮组
|
|
19
|
+
*/
|
|
20
|
+
declare const SceneShelfFooter: React.ForwardRefExoticComponent<SceneShelfFooterProps & React.RefAttributes<HTMLDivElement>>;
|
|
21
|
+
export { SceneShelfFooter };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{jsx as a,jsxs as c}from"react/jsx-runtime";import*as i from"react";import{cn as o}from"../../helpers/index.js";import{Button as f,Text as l}from"../../components/index.js";import{useSceneShelfContext as D}from"./context.js";const u=i.forwardRef(({totalPriceLabel:m,totalCurrentPrice:T,totalOriginalPrice:g,addToCartButtonText:P,shopNowButtonText:h,className:N,...w},C)=>{const t=D(),d=m??t?.totalPriceLabel??"Total Price:",r=T??t?.totalCurrentPrice,s=g??t?.totalOriginalPrice,S=P??t?.addToCartButtonText??"Add to Cart",y=h??t?.shopNowButtonText??"Shop Now",n=t?.selectedProducts??[],v=t?.onAddToCart,b=t?.onShopNow,B=t?.showOriginalPrice??!0,e=t?.classNames,[L,p]=i.useState(!1),[A,x]=i.useState(!1),O=async()=>{p(!0);try{await v?.(n)}finally{p(!1)}},k=async()=>{x(!0);try{await b?.(n)}finally{x(!1)}};return c("div",{ref:C,className:o("tablet:items-end tablet:flex-row flex flex-col items-start justify-between gap-4",N,e?.footer),...w,children:[c("div",{className:o("flex flex-wrap items-center gap-1",e?.totalPrice),children:[d&&a(l,{as:"span",size:2,className:"text-info-primary lg-desktop:text-[24px] text-[20px]",children:d}),r&&a(l,{as:"span",size:2,className:o("text-info-primary lg-desktop:text-[24px] text-[20px]",e?.currentTotalPrice),children:r.formatted}),B&&s&&r&&s.value>r.value&&a(l,{as:"span",size:2,className:o("text-info-quaternary lg-desktop:text-[24px] text-[20px] line-through",e?.originalTotalPrice),children:s.formatted})]}),c("div",{className:o("flex gap-3",e?.buttonGroup),children:[a(f,{variant:"secondary",onClick:O,disabled:n.length===0,loading:L,children:S}),a(f,{variant:"primary",onClick:k,disabled:n.length===0,loading:A,children:y})]})]})});u.displayName="SceneShelf.Footer";export{u as SceneShelfFooter};
|
|
2
|
+
//# sourceMappingURL=Footer.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/biz-components/SceneShelf/Footer.tsx"],
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { cn } from '../../helpers/index.js'\nimport { Button, Text } from '../../components/index.js'\nimport { useSceneShelfContext } from './context.js'\nimport type { PriceData } from './types.js'\n\nexport interface SceneShelfFooterProps extends React.HTMLAttributes<HTMLDivElement> {\n /** \u603B\u4EF7\u6807\u7B7E */\n totalPriceLabel?: string\n /** \u5F53\u524D\u603B\u4EF7 */\n totalCurrentPrice?: PriceData\n /** \u539F\u603B\u4EF7 */\n totalOriginalPrice?: PriceData\n /** \u6DFB\u52A0\u5230\u8D2D\u7269\u8F66\u6309\u94AE\u6587\u672C */\n addToCartButtonText?: string\n /** \u7ACB\u5373\u8D2D\u4E70\u6309\u94AE\u6587\u672C */\n shopNowButtonText?: string\n}\n\n/**\n * SceneShelf Footer \u7EC4\u4EF6\n *\n * @description \u5E95\u90E8\u533A\u57DF\uFF0C\u5305\u542B\u603B\u4EF7\u548C\u6309\u94AE\u7EC4\n */\nconst SceneShelfFooter = React.forwardRef<HTMLDivElement, SceneShelfFooterProps>(\n (\n {\n totalPriceLabel: totalPriceLabelProp,\n totalCurrentPrice: totalCurrentPriceProp,\n totalOriginalPrice: totalOriginalPriceProp,\n addToCartButtonText: addToCartButtonTextProp,\n shopNowButtonText: shopNowButtonTextProp,\n className,\n ...props\n },\n ref\n ) => {\n const context = useSceneShelfContext()\n\n // Props \u4F18\u5148\u7EA7\u9AD8\u4E8E Context\n const totalPriceLabel = totalPriceLabelProp ?? context?.totalPriceLabel ?? 'Total Price:'\n const totalCurrentPrice = totalCurrentPriceProp ?? context?.totalCurrentPrice\n const totalOriginalPrice = totalOriginalPriceProp ?? context?.totalOriginalPrice\n const addToCartButtonText = addToCartButtonTextProp ?? context?.addToCartButtonText ?? 'Add to Cart'\n const shopNowButtonText = shopNowButtonTextProp ?? context?.shopNowButtonText ?? 'Shop Now'\n\n const selectedProducts = context?.selectedProducts ?? []\n const onAddToCart = context?.onAddToCart\n const onShopNow = context?.onShopNow\n const showOriginalPrice = context?.showOriginalPrice ?? true\n const classNames = context?.classNames\n\n // \u6309\u94AE loading \u72B6\u6001\n const [addToCartLoading, setAddToCartLoading] = React.useState(false)\n const [shopNowLoading, setShopNowLoading] = React.useState(false)\n\n // \u5904\u7406\u6DFB\u52A0\u5230\u8D2D\u7269\u8F66\n const handleAddToCart = async () => {\n setAddToCartLoading(true)\n try {\n await onAddToCart?.(selectedProducts)\n } finally {\n setAddToCartLoading(false)\n }\n }\n\n // \u5904\u7406\u7ACB\u5373\u8D2D\u4E70\n const handleShopNow = async () => {\n setShopNowLoading(true)\n try {\n await onShopNow?.(selectedProducts)\n } finally {\n setShopNowLoading(false)\n }\n }\n\n return (\n <div\n ref={ref}\n className={cn(\n 'tablet:items-end tablet:flex-row flex flex-col items-start justify-between gap-4',\n className,\n classNames?.footer\n )}\n {...props}\n >\n {/* \u603B\u4EF7 */}\n <div className={cn('flex flex-wrap items-center gap-1', classNames?.totalPrice)}>\n {totalPriceLabel && (\n <Text as=\"span\" size={2} className=\"text-info-primary lg-desktop:text-[24px] text-[20px]\">\n {totalPriceLabel}\n </Text>\n )}\n {totalCurrentPrice && (\n <Text\n as=\"span\"\n size={2}\n className={cn('text-info-primary lg-desktop:text-[24px] text-[20px]', classNames?.currentTotalPrice)}\n >\n {totalCurrentPrice.formatted}\n </Text>\n )}\n {showOriginalPrice &&\n totalOriginalPrice &&\n totalCurrentPrice &&\n totalOriginalPrice.value > totalCurrentPrice.value && (\n <Text\n as=\"span\"\n size={2}\n className={cn(\n 'text-info-quaternary lg-desktop:text-[24px] text-[20px] line-through',\n classNames?.originalTotalPrice\n )}\n >\n {totalOriginalPrice.formatted}\n </Text>\n )}\n </div>\n\n {/* \u6309\u94AE\u7EC4 */}\n <div className={cn('flex gap-3', classNames?.buttonGroup)}>\n <Button\n variant=\"secondary\"\n onClick={handleAddToCart}\n disabled={selectedProducts.length === 0}\n loading={addToCartLoading}\n >\n {addToCartButtonText}\n </Button>\n <Button\n variant=\"primary\"\n onClick={handleShopNow}\n disabled={selectedProducts.length === 0}\n loading={shopNowLoading}\n >\n {shopNowButtonText}\n </Button>\n </div>\n </div>\n )\n }\n)\n\nSceneShelfFooter.displayName = 'SceneShelf.Footer'\n\nexport { SceneShelfFooter }\n"],
|
|
5
|
+
"mappings": "aAyFQ,OAEI,OAAAA,EAFJ,QAAAC,MAAA,oBAvFR,UAAYC,MAAW,QACvB,OAAS,MAAAC,MAAU,yBACnB,OAAS,UAAAC,EAAQ,QAAAC,MAAY,4BAC7B,OAAS,wBAAAC,MAA4B,eAqBrC,MAAMC,EAAmBL,EAAM,WAC7B,CACE,CACE,gBAAiBM,EACjB,kBAAmBC,EACnB,mBAAoBC,EACpB,oBAAqBC,EACrB,kBAAmBC,EACnB,UAAAC,EACA,GAAGC,CACL,EACAC,IACG,CACH,MAAMC,EAAUV,EAAqB,EAG/BW,EAAkBT,GAAuBQ,GAAS,iBAAmB,eACrEE,EAAoBT,GAAyBO,GAAS,kBACtDG,EAAqBT,GAA0BM,GAAS,mBACxDI,EAAsBT,GAA2BK,GAAS,qBAAuB,cACjFK,EAAoBT,GAAyBI,GAAS,mBAAqB,WAE3EM,EAAmBN,GAAS,kBAAoB,CAAC,EACjDO,EAAcP,GAAS,YACvBQ,EAAYR,GAAS,UACrBS,EAAoBT,GAAS,mBAAqB,GAClDU,EAAaV,GAAS,WAGtB,CAACW,EAAkBC,CAAmB,EAAI1B,EAAM,SAAS,EAAK,EAC9D,CAAC2B,EAAgBC,CAAiB,EAAI5B,EAAM,SAAS,EAAK,EAG1D6B,EAAkB,SAAY,CAClCH,EAAoB,EAAI,EACxB,GAAI,CACF,MAAML,IAAcD,CAAgB,CACtC,QAAE,CACAM,EAAoB,EAAK,CAC3B,CACF,EAGMI,EAAgB,SAAY,CAChCF,EAAkB,EAAI,EACtB,GAAI,CACF,MAAMN,IAAYF,CAAgB,CACpC,QAAE,CACAQ,EAAkB,EAAK,CACzB,CACF,EAEA,OACE7B,EAAC,OACC,IAAKc,EACL,UAAWZ,EACT,mFACAU,EACAa,GAAY,MACd,EACC,GAAGZ,EAGJ,UAAAb,EAAC,OAAI,UAAWE,EAAG,oCAAqCuB,GAAY,UAAU,EAC3E,UAAAT,GACCjB,EAACK,EAAA,CAAK,GAAG,OAAO,KAAM,EAAG,UAAU,uDAChC,SAAAY,EACH,EAEDC,GACClB,EAACK,EAAA,CACC,GAAG,OACH,KAAM,EACN,UAAWF,EAAG,uDAAwDuB,GAAY,iBAAiB,EAElG,SAAAR,EAAkB,UACrB,EAEDO,GACCN,GACAD,GACAC,EAAmB,MAAQD,EAAkB,OAC3ClB,EAACK,EAAA,CACC,GAAG,OACH,KAAM,EACN,UAAWF,EACT,uEACAuB,GAAY,kBACd,EAEC,SAAAP,EAAmB,UACtB,GAEN,EAGAlB,EAAC,OAAI,UAAWE,EAAG,aAAcuB,GAAY,WAAW,EACtD,UAAA1B,EAACI,EAAA,CACC,QAAQ,YACR,QAAS2B,EACT,SAAUT,EAAiB,SAAW,EACtC,QAASK,EAER,SAAAP,EACH,EACApB,EAACI,EAAA,CACC,QAAQ,UACR,QAAS4B,EACT,SAAUV,EAAiB,SAAW,EACtC,QAASO,EAER,SAAAR,EACH,GACF,GACF,CAEJ,CACF,EAEAd,EAAiB,YAAc",
|
|
6
|
+
"names": ["jsx", "jsxs", "React", "cn", "Button", "Text", "useSceneShelfContext", "SceneShelfFooter", "totalPriceLabelProp", "totalCurrentPriceProp", "totalOriginalPriceProp", "addToCartButtonTextProp", "shopNowButtonTextProp", "className", "props", "ref", "context", "totalPriceLabel", "totalCurrentPrice", "totalOriginalPrice", "addToCartButtonText", "shopNowButtonText", "selectedProducts", "onAddToCart", "onShopNow", "showOriginalPrice", "classNames", "addToCartLoading", "setAddToCartLoading", "shopNowLoading", "setShopNowLoading", "handleAddToCart", "handleShopNow"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { SceneProductCardSemanticName, SceneProductCardData } from './types.js';
|
|
3
|
+
export interface SceneProductCardProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
/** 产品数据 */
|
|
5
|
+
product: SceneProductCardData;
|
|
6
|
+
/** 是否选中 */
|
|
7
|
+
selected?: boolean;
|
|
8
|
+
/** 选中状态变化回调 */
|
|
9
|
+
onSelectChange?: (selected: boolean, product: SceneProductCardData) => void;
|
|
10
|
+
/** 是否显示标签 */
|
|
11
|
+
showTags?: boolean;
|
|
12
|
+
/** 是否显示原价 */
|
|
13
|
+
showOriginalPrice?: boolean;
|
|
14
|
+
/** 语义化类名 */
|
|
15
|
+
classNames?: Partial<Record<SceneProductCardSemanticName, string>>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* SceneProductCard - 场景推荐货架产品卡片
|
|
19
|
+
*
|
|
20
|
+
* @description 用于场景推荐货架的可选中产品卡片组件
|
|
21
|
+
*/
|
|
22
|
+
declare const SceneProductCard: React.ForwardRefExoticComponent<SceneProductCardProps & React.RefAttributes<HTMLDivElement>>;
|
|
23
|
+
export { SceneProductCard };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{jsx as s,jsxs as n}from"react/jsx-runtime";import*as w from"react";import{cn as a}from"../../helpers/index.js";import{Checkbox as y,Badge as T,Heading as z,Text as d,Picture as D}from"../../components/index.js";import{useSceneShelfContext as O}from"./context.js";const p=w.forwardRef(({className:g,classNames:m,product:e,selected:x,onSelectChange:f,showTags:h,showOriginalPrice:b,...P},C)=>{const o=O(),u=h??o?.showTags??!0,k=b??o?.showOriginalPrice??!0,t=m??o?.classNames??{},l=x??(o?o.selectedIds.has(e.id):!1),c=f??o?.onSelectChange,i=e.soldOut??!1,S=r=>{i||typeof r=="boolean"&&c?.(r,e)},N=()=>{i||c?.(!l,e)};return n("div",{ref:C,className:a("lg-desktop:gap-2 lg-desktop:h-[362px] lg-desktop:px-6 lg-desktop:pb-6 lg-desktop:pt-4 rounded-box box-border flex h-[284px] flex-col gap-2 border-2 border-solid p-4 pb-6 transition-colors",i?"cursor-not-allowed opacity-50":"cursor-pointer",l?a("border-brand-0 bg-container-secondary-0",t?.cardSelected):a("border-lines bg-container-primary",t?.card),g),onClick:N,...P,children:[s("div",{className:a("lg-desktop:left-6 lg-desktop:top-6 absolute left-4 top-4 flex flex-wrap gap-1 pr-9",t?.tags),children:u&&e.tags?.map((r,v)=>s(T,{variant:r.variant||"outline",size:"sm",children:r.label},v))}),s(y,{checked:l,disabled:i,onCheckedChange:S,onClick:r=>r.stopPropagation(),className:a("text-brand-0 border-brand-0 lg-desktop:right-6 lg-desktop:top-6 absolute right-4 top-4 size-5 shrink-0",t?.checkbox)}),s("div",{className:a("flex flex-1 items-center justify-center",t?.image),children:s(D,{source:e.imageUrl,alt:e.imageAlt||e.title,className:"lg-desktop:size-[175px] aspect-square size-[124px] ",imgClassName:"object-contain"})}),n("div",{className:"flex flex-col gap-4",children:[s(z,{as:"h3",size:2,className:a("text-info-primary line-clamp-2",t?.title),html:e.title}),n("div",{className:a("flex flex-wrap items-center gap-1",t?.priceWrapper),children:[s(d,{as:"span",size:2,className:a("text-info-primary lg-desktop:text-[24px] text-[20px]",t?.currentPrice),children:e.currentPrice.formatted}),k&&e.originalPrice&&e.originalPrice.value>e.currentPrice.value&&s(d,{as:"span",size:2,className:a("text-info-quaternary lg-desktop:text-[24px] text-[20px] line-through",t?.originalPrice),children:e.originalPrice.formatted})]})]})]})});p.displayName="SceneShelf.ProductCard";export{p as SceneProductCard};
|
|
2
|
+
//# sourceMappingURL=ProductCard.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/biz-components/SceneShelf/ProductCard.tsx"],
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { cn } from '../../helpers/index.js'\nimport { Checkbox, Badge, Heading, Text, Picture } from '../../components/index.js'\nimport { useSceneShelfContext } from './context.js'\nimport type { SceneProductCardSemanticName, SceneProductCardData } from './types.js'\n\nexport interface SceneProductCardProps extends React.HTMLAttributes<HTMLDivElement> {\n /** \u4EA7\u54C1\u6570\u636E */\n product: SceneProductCardData\n /** \u662F\u5426\u9009\u4E2D */\n selected?: boolean\n /** \u9009\u4E2D\u72B6\u6001\u53D8\u5316\u56DE\u8C03 */\n onSelectChange?: (selected: boolean, product: SceneProductCardData) => void\n /** \u662F\u5426\u663E\u793A\u6807\u7B7E */\n showTags?: boolean\n /** \u662F\u5426\u663E\u793A\u539F\u4EF7 */\n showOriginalPrice?: boolean\n /** \u8BED\u4E49\u5316\u7C7B\u540D */\n classNames?: Partial<Record<SceneProductCardSemanticName, string>>\n}\n\n/**\n * SceneProductCard - \u573A\u666F\u63A8\u8350\u8D27\u67B6\u4EA7\u54C1\u5361\u7247\n *\n * @description \u7528\u4E8E\u573A\u666F\u63A8\u8350\u8D27\u67B6\u7684\u53EF\u9009\u4E2D\u4EA7\u54C1\u5361\u7247\u7EC4\u4EF6\n */\nconst SceneProductCard = React.forwardRef<HTMLDivElement, SceneProductCardProps>(\n (\n {\n className,\n classNames: classNamesProp,\n product,\n selected: selectedProp,\n onSelectChange: onSelectChangeProp,\n showTags: showTagsProp,\n showOriginalPrice: showOriginalPriceProp,\n ...props\n },\n ref\n ) => {\n // \u4ECE Context \u8BFB\u53D6\u914D\u7F6E\n const context = useSceneShelfContext()\n\n // Props \u4F18\u5148\u7EA7\u9AD8\u4E8E Context\n const showTags = showTagsProp ?? context?.showTags ?? true\n const showOriginalPrice = showOriginalPriceProp ?? context?.showOriginalPrice ?? true\n const classNames = classNamesProp ?? context?.classNames ?? {}\n\n // \u9009\u4E2D\u72B6\u6001\u548C\u56DE\u8C03\u4ECE Context \u83B7\u53D6\n const selected = selectedProp ?? (context ? context.selectedIds.has(product.id) : false)\n const onSelectChange = onSelectChangeProp ?? context?.onSelectChange\n const disabled = product.soldOut ?? false\n\n const handleCheckboxChange = (checked: boolean | 'indeterminate') => {\n if (disabled) return\n if (typeof checked === 'boolean') {\n onSelectChange?.(checked, product)\n }\n }\n\n const handleCardClick = () => {\n if (disabled) return\n onSelectChange?.(!selected, product)\n }\n\n return (\n <div\n ref={ref}\n className={cn(\n 'lg-desktop:gap-2 lg-desktop:h-[362px] lg-desktop:px-6 lg-desktop:pb-6 lg-desktop:pt-4 rounded-box box-border flex h-[284px] flex-col gap-2 border-2 border-solid p-4 pb-6 transition-colors',\n disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer',\n selected\n ? cn('border-brand-0 bg-container-secondary-0', classNames?.cardSelected)\n : cn('border-lines bg-container-primary', classNames?.card),\n className\n )}\n onClick={handleCardClick}\n {...props}\n >\n {/* \u6807\u7B7E\u533A\u57DF */}\n <div\n className={cn(\n 'lg-desktop:left-6 lg-desktop:top-6 absolute left-4 top-4 flex flex-wrap gap-1 pr-9',\n classNames?.tags\n )}\n >\n {showTags &&\n product.tags?.map((tag, index) => (\n <Badge key={index} variant={tag.variant || 'outline'} size=\"sm\">\n {tag.label}\n </Badge>\n ))}\n </div>\n\n {/* Checkbox */}\n <Checkbox\n checked={selected}\n disabled={disabled}\n onCheckedChange={handleCheckboxChange}\n onClick={e => e.stopPropagation()}\n className={cn(\n 'text-brand-0 border-brand-0 lg-desktop:right-6 lg-desktop:top-6 absolute right-4 top-4 size-5 shrink-0',\n classNames?.checkbox\n )}\n />\n\n {/* \u4EA7\u54C1\u56FE\u7247 */}\n <div className={cn('flex flex-1 items-center justify-center', classNames?.image)}>\n <Picture\n source={product.imageUrl}\n alt={product.imageAlt || product.title}\n className=\"lg-desktop:size-[175px] aspect-square size-[124px] \"\n imgClassName=\"object-contain\"\n />\n </div>\n\n {/* \u4EA7\u54C1\u4FE1\u606F */}\n <div className=\"flex flex-col gap-4\">\n {/* \u4EA7\u54C1\u540D\u79F0 */}\n <Heading\n as=\"h3\"\n size={2}\n className={cn('text-info-primary line-clamp-2', classNames?.title)}\n html={product.title}\n />\n\n {/* \u4EF7\u683C\u533A\u57DF */}\n <div className={cn('flex flex-wrap items-center gap-1', classNames?.priceWrapper)}>\n <Text\n as=\"span\"\n size={2}\n className={cn('text-info-primary lg-desktop:text-[24px] text-[20px]', classNames?.currentPrice)}\n >\n {product.currentPrice.formatted}\n </Text>\n {showOriginalPrice && product.originalPrice && product.originalPrice.value > product.currentPrice.value && (\n <Text\n as=\"span\"\n size={2}\n className={cn(\n 'text-info-quaternary lg-desktop:text-[24px] text-[20px] line-through',\n classNames?.originalPrice\n )}\n >\n {product.originalPrice.formatted}\n </Text>\n )}\n </div>\n </div>\n </div>\n )\n }\n)\n\nSceneProductCard.displayName = 'SceneShelf.ProductCard'\n\nexport { SceneProductCard }\n"],
|
|
5
|
+
"mappings": "aA0Fc,cAAAA,EAuCJ,QAAAC,MAvCI,oBAxFd,UAAYC,MAAW,QACvB,OAAS,MAAAC,MAAU,yBACnB,OAAS,YAAAC,EAAU,SAAAC,EAAO,WAAAC,EAAS,QAAAC,EAAM,WAAAC,MAAe,4BACxD,OAAS,wBAAAC,MAA4B,eAuBrC,MAAMC,EAAmBR,EAAM,WAC7B,CACE,CACE,UAAAS,EACA,WAAYC,EACZ,QAAAC,EACA,SAAUC,EACV,eAAgBC,EAChB,SAAUC,EACV,kBAAmBC,EACnB,GAAGC,CACL,EACAC,IACG,CAEH,MAAMC,EAAUX,EAAqB,EAG/BY,EAAWL,GAAgBI,GAAS,UAAY,GAChDE,EAAoBL,GAAyBG,GAAS,mBAAqB,GAC3EG,EAAaX,GAAkBQ,GAAS,YAAc,CAAC,EAGvDI,EAAWV,IAAiBM,EAAUA,EAAQ,YAAY,IAAIP,EAAQ,EAAE,EAAI,IAC5EY,EAAiBV,GAAsBK,GAAS,eAChDM,EAAWb,EAAQ,SAAW,GAE9Bc,EAAwBC,GAAuC,CAC/DF,GACA,OAAOE,GAAY,WACrBH,IAAiBG,EAASf,CAAO,CAErC,EAEMgB,EAAkB,IAAM,CACxBH,GACJD,IAAiB,CAACD,EAAUX,CAAO,CACrC,EAEA,OACEZ,EAAC,OACC,IAAKkB,EACL,UAAWhB,EACT,8LACAuB,EAAW,gCAAkC,iBAC7CF,EACIrB,EAAG,0CAA2CoB,GAAY,YAAY,EACtEpB,EAAG,oCAAqCoB,GAAY,IAAI,EAC5DZ,CACF,EACA,QAASkB,EACR,GAAGX,EAGJ,UAAAlB,EAAC,OACC,UAAWG,EACT,qFACAoB,GAAY,IACd,EAEC,SAAAF,GACCR,EAAQ,MAAM,IAAI,CAACiB,EAAKC,IACtB/B,EAACK,EAAA,CAAkB,QAASyB,EAAI,SAAW,UAAW,KAAK,KACxD,SAAAA,EAAI,OADKC,CAEZ,CACD,EACL,EAGA/B,EAACI,EAAA,CACC,QAASoB,EACT,SAAUE,EACV,gBAAiBC,EACjB,QAASK,GAAKA,EAAE,gBAAgB,EAChC,UAAW7B,EACT,yGACAoB,GAAY,QACd,EACF,EAGAvB,EAAC,OAAI,UAAWG,EAAG,0CAA2CoB,GAAY,KAAK,EAC7E,SAAAvB,EAACQ,EAAA,CACC,OAAQK,EAAQ,SAChB,IAAKA,EAAQ,UAAYA,EAAQ,MACjC,UAAU,sDACV,aAAa,iBACf,EACF,EAGAZ,EAAC,OAAI,UAAU,sBAEb,UAAAD,EAACM,EAAA,CACC,GAAG,KACH,KAAM,EACN,UAAWH,EAAG,iCAAkCoB,GAAY,KAAK,EACjE,KAAMV,EAAQ,MAChB,EAGAZ,EAAC,OAAI,UAAWE,EAAG,oCAAqCoB,GAAY,YAAY,EAC9E,UAAAvB,EAACO,EAAA,CACC,GAAG,OACH,KAAM,EACN,UAAWJ,EAAG,uDAAwDoB,GAAY,YAAY,EAE7F,SAAAV,EAAQ,aAAa,UACxB,EACCS,GAAqBT,EAAQ,eAAiBA,EAAQ,cAAc,MAAQA,EAAQ,aAAa,OAChGb,EAACO,EAAA,CACC,GAAG,OACH,KAAM,EACN,UAAWJ,EACT,uEACAoB,GAAY,aACd,EAEC,SAAAV,EAAQ,cAAc,UACzB,GAEJ,GACF,GACF,CAEJ,CACF,EAEAH,EAAiB,YAAc",
|
|
6
|
+
"names": ["jsx", "jsxs", "React", "cn", "Checkbox", "Badge", "Heading", "Text", "Picture", "useSceneShelfContext", "SceneProductCard", "className", "classNamesProp", "product", "selectedProp", "onSelectChangeProp", "showTagsProp", "showOriginalPriceProp", "props", "ref", "context", "showTags", "showOriginalPrice", "classNames", "selected", "onSelectChange", "disabled", "handleCheckboxChange", "checked", "handleCardClick", "tag", "index", "e"]
|
|
7
|
+
}
|