@anker-in/headless-ui 1.1.55 → 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/GiftBox/index.js +1 -1
- package/dist/cjs/biz-components/GiftBox/index.js.map +2 -2
- package/dist/cjs/biz-components/HeroBanner/HeroBanner.js +1 -1
- package/dist/cjs/biz-components/HeroBanner/HeroBanner.js.map +3 -3
- 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/MediaPlayerSticky/index.js +1 -1
- package/dist/cjs/biz-components/MediaPlayerSticky/index.js.map +2 -2
- package/dist/cjs/biz-components/MediaSceneSwitcher/MediaSceneSwitcher.js +2 -2
- package/dist/cjs/biz-components/MediaSceneSwitcher/MediaSceneSwitcher.js.map +2 -2
- package/dist/cjs/biz-components/MediaSceneSwitcher/types.d.ts +1 -0
- package/dist/cjs/biz-components/MediaSceneSwitcher/types.js +1 -1
- package/dist/cjs/biz-components/MediaSceneSwitcher/types.js.map +1 -1
- 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 +8 -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/cjs/stories/decorators/dataPropsDecorator.d.ts +16 -0
- package/dist/cjs/stories/decorators/dataPropsDecorator.js +2 -0
- package/dist/cjs/stories/decorators/dataPropsDecorator.js.map +7 -0
- 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/GiftBox/index.js +1 -1
- package/dist/esm/biz-components/GiftBox/index.js.map +2 -2
- package/dist/esm/biz-components/HeroBanner/HeroBanner.js +1 -1
- package/dist/esm/biz-components/HeroBanner/HeroBanner.js.map +3 -3
- 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/MediaPlayerSticky/index.js +1 -1
- package/dist/esm/biz-components/MediaPlayerSticky/index.js.map +2 -2
- package/dist/esm/biz-components/MediaSceneSwitcher/MediaSceneSwitcher.js +2 -2
- package/dist/esm/biz-components/MediaSceneSwitcher/MediaSceneSwitcher.js.map +2 -2
- package/dist/esm/biz-components/MediaSceneSwitcher/types.d.ts +1 -0
- 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 +8 -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/esm/stories/decorators/dataPropsDecorator.d.ts +16 -0
- package/dist/esm/stories/decorators/dataPropsDecorator.js +2 -0
- package/dist/esm/stories/decorators/dataPropsDecorator.js.map +7 -0
- 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 +6 -2
- package/style.css +20 -3
- package/tailwind.config.js +1 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";"use client";var U=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var H=Object.prototype.hasOwnProperty;var V=(t,s)=>{for(var
|
|
1
|
+
"use strict";"use client";var U=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var H=Object.prototype.hasOwnProperty;var V=(t,s)=>{for(var a in s)U(t,a,{get:s[a],enumerable:!0})},_=(t,s,a,m)=>{if(s&&typeof s=="object"||typeof s=="function")for(let i of R(s))!H.call(t,i)&&i!==a&&U(t,i,{get:()=>s[i],enumerable:!(m=j(s,i))||m.enumerable});return t};var q=t=>_(U({},"__esModule",{value:!0}),t);var G={};V(G,{default:()=>Q});module.exports=q(G);var e=require("react/jsx-runtime"),o=require("react"),D=require("react-responsive"),d=require("../../helpers/utils.js"),C=require("../../shared/Styles.js"),r=require("../../components/index.js"),f=require("../../hooks/useExposure.js"),w=require("swiper/react"),F=require("swiper/modules"),Y=require("swiper/css");const S="media",A="media_scene_switcher",v=3e3,$=({data:t,configuration:s,theme:a})=>{const m=(0,o.useRef)(null),i=s?.isActive||!1;return(0,f.useExposure)(m,{componentType:S,componentName:A,componentTitle:t?.title,position:(s?.index??0)+1}),(0,e.jsxs)("div",{ref:m,className:(0,d.cn)("media-scene-switcher-item rounded-box cursor-pointer overflow-hidden transition-colors","relative text-[#6D6D6F]",i?"opacity-100":"opacity-60",{"bg-[#1D1D1F] text-white":i,"bg-[#EAEAEC] text-[1D1D1F]":i&&a==="light"}),onClick:()=>s?.onItemClick?.(s?.index??0),children:[(0,e.jsxs)("div",{className:"media-scene-switcher-item-content laptop:gap-[32px] laptop:p-[12px] desktop:gap-[48px] desktop:p-[24px] flex items-center justify-between gap-[24px]",children:[(0,e.jsxs)("div",{children:[(0,e.jsx)("div",{className:"media-scene-switcher-item-title flex-1",children:(0,e.jsx)(r.Heading,{as:"h6",size:2,html:t?.title})}),t?.description&&i&&(0,e.jsx)(r.Text,{size:2,className:"media-scene-switcher-item-description tablet:text-base desktop:text-lg mt-1 text-sm font-bold",html:t.description})]}),(0,e.jsx)("div",{className:(0,d.cn)("media-scene-switcher-item-badge rounded-btn border-[1.6px] px-[18px] py-[7px]",a==="dark"?"border-[#B5B7BB]":"border-[#4A4C56]",{"!border-[#F5F6F7]":a==="dark"&&i}),children:(0,e.jsx)(r.Heading,{as:"h6",size:2,html:t?.tag})})]}),(0,e.jsx)("div",{className:(0,d.cn)("media-scene-switcher-progress absolute bottom-0 left-0 h-[2px] w-full",{"media-scene-switcher-progress-active":i}),style:{transform:"translate3d(-100%, 0, 0)",background:"linear-gradient(90deg, #3ad1ff 0%, #008cd6 100%)",animation:i?`progress-bar ${v}ms ease-out`:"none"}})]})},O=({data:t,configuration:s,theme:a})=>{const m=(0,o.useRef)(null),i=s?.isActive||!1,p=(0,D.useMediaQuery)({query:"(max-width: 768px)"});(0,f.useExposure)(m,{componentType:S,componentName:A,componentTitle:t?.title,position:(s?.index??0)+1});const n=p&&t?.mobVideoUrl?.url?t.mobVideoUrl.url:t?.videoUrl?.url,x=p&&t?.mobImageUrl?.url?t.mobImageUrl.url:t?.imageUrl?.url,b=x||t?.videoUrl?.thumbnailURL||"";return(0,e.jsxs)("div",{ref:m,className:(0,d.cn)("media-scene-switcher-mobile-item rounded-box flex h-[360px] w-[296px] max-w-full flex-col overflow-hidden",{"aiui-dark":a==="dark"}),children:[(0,e.jsx)("div",{className:"media-scene-switcher-mobile-media relative aspect-[554/480] w-full overflow-hidden",children:n?(0,e.jsx)("video",{src:n,playsInline:!0,autoPlay:!0,loop:!0,muted:!0,poster:b,className:"size-full object-cover"}):x?(0,e.jsx)(r.Picture,{className:"size-full",imgClassName:"size-full object-cover",source:x,alt:t?.title||""}):null}),(0,e.jsxs)("div",{className:(0,d.cn)("media-scene-switcher-mobile-bottom flex items-start justify-between gap-[8px] p-[16px]","text-[#6D6D6F]",{"bg-[#1D1D1F] text-white":i,"bg-[#EAEAEC] text-[1D1D1F]":i&&a==="light"}),children:[(0,e.jsxs)("div",{children:[(0,e.jsx)("div",{className:"media-scene-switcher-mobile-title line-clamp-3 h-[72px] flex-1",children:(0,e.jsx)(r.Heading,{as:"h6",size:2,html:t?.title})}),t?.description&&i&&(0,e.jsx)(r.Text,{size:2,className:"media-scene-switcher-item-description tablet:text-base desktop:text-lg mt-1 line-clamp-3 text-sm font-bold",html:t.description})]}),(0,e.jsx)("div",{className:(0,d.cn)("media-scene-switcher-mobile-badge rounded-btn shrink-0 border-[1.6px] px-[12px] py-[5px]",a==="dark"?"border-[#B5B7BB]":"border-[#4A4C56]",{"!border-[#F5F6F7]":a==="dark"&&i}),children:(0,e.jsx)(r.Heading,{as:"h6",size:1,html:t?.tag})})]}),(0,e.jsx)("div",{className:(0,d.cn)("media-scene-switcher-progress h-[2px] w-full",{"media-scene-switcher-progress-active":i}),style:{transform:"translate3d(-100%, 0, 0)",background:"linear-gradient(90deg, #3ad1ff 0%, #008cd6 100%)",animation:i?`progress-bar ${v}ms ease-out`:"none"}})]})},M=(0,o.forwardRef)(({className:t="",data:s,id:a},m)=>{const{title:i,subtitle:p,items:n=[],theme:x="light",layout:b,titleIcon:u}=s||{},[g,N]=(0,o.useState)(0),[T,B]=(0,o.useState)(0),k=(0,o.useRef)(null),h=(0,o.useRef)(0),z=(0,D.useMediaQuery)({query:"(max-width: 1023px)"});(0,o.useImperativeHandle)(m,()=>k.current),(0,f.useExposure)(k,{componentType:S,componentName:A,componentTitle:i}),(0,o.useEffect)(()=>{if(!(z||n.length===0))return h.current=window.setInterval(()=>{N(l=>(l+1)%n.length)},v),()=>{h.current&&window.clearInterval(h.current)}},[z,n.length]);const P=l=>{N(l),h.current&&window.clearInterval(h.current),h.current=window.setInterval(()=>{N(c=>(c+1)%n.length)},v)},y=n[g],J=y?.videoUrl?.url,W=y?.imageUrl?.url||y?.videoUrl?.thumbnailURL||"";return(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("style",{children:`
|
|
2
2
|
@keyframes progress-bar {
|
|
3
3
|
from {
|
|
4
4
|
transform: translate3d(-100%, 0, 0);
|
|
@@ -7,5 +7,5 @@
|
|
|
7
7
|
transform: translate3d(0, 0, 0);
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
|
-
`}),(0,e.jsxs)("section",{id:
|
|
10
|
+
`}),(0,e.jsxs)("section",{id:a,ref:k,className:(0,d.cn)("media-scene-switcher text-info-primary w-full",{"aiui-dark":x==="dark"},t),children:[(0,e.jsxs)("div",{className:"media-scene-switcher-desktop laptop:gap-[24px] lg-desktop:gap-[40px] laptop:flex hidden w-full items-stretch gap-[20px] overflow-hidden",children:[(0,e.jsx)("div",{className:(0,d.cn)("media-scene-switcher-preview rounded-box laptop:flex-1 relative aspect-[824/640] max-w-[824px] shrink-0 overflow-hidden",{"order-1":b==="right"}),children:n.map((l,c)=>{const E=l?.videoUrl?.url,I=l?.imageUrl?.url,L=I||l?.videoUrl?.thumbnailURL||"";return(0,e.jsx)("div",{className:(0,d.cn)("media-scene-switcher-media rounded-box absolute inset-0 hidden size-full overflow-hidden",{"inline-block":c===g}),children:E?(0,e.jsx)("video",{src:E,playsInline:!0,autoPlay:!0,loop:!0,muted:!0,poster:L,className:"size-full object-cover"}):I?(0,e.jsx)(r.Picture,{className:"size-full",imgClassName:"size-full object-cover",source:I,alt:l?.title||""}):null},l.id||c)})}),(0,e.jsxs)("div",{className:"media-scene-switcher-sidebar laptop:flex-1 flex shrink-0 flex-col justify-between",children:[(0,e.jsxs)("div",{className:"media-scene-switcher-header flex flex-col",children:[(0,e.jsxs)("div",{className:"desktop:gap-2 flex items-center gap-1",children:[i&&(0,e.jsx)(r.Heading,{as:"h3",html:i,size:4,className:"media-scene-switcher-title text-info-primary tablet:!text-[40px] desktop:!text-[56px] lg-desktop:!text-[64px] text-[40px] leading-none text-[#00BEFA]"}),u&&(0,e.jsx)(r.Picture,{source:u.url,alt:u.alt||"title icon",className:"desktop:h-8 lg-desktop:h-10 h-6",imgClassName:"!w-auto h-full"})]}),p&&(0,e.jsx)(r.Text,{as:"span",size:4,html:p,className:"media-scene-switcher-subtitle tablet:text-[14px] laptop:text-[14px] desktop:text-[16px] lg-desktop:text-[18px] relative -top-2 mt-3 text-[14px]"})]}),(0,e.jsx)("div",{className:"media-scene-switcher-list flex flex-col gap-[16px]",children:n.map((l,c)=>(0,e.jsx)($,{data:l,configuration:{index:c,isActive:c===g,onItemClick:P},theme:x},l.id||c))})]})]}),(0,e.jsxs)("div",{className:"media-scene-switcher-mobile laptop:hidden flex flex-col overflow-visible",children:[(0,e.jsxs)("div",{className:"media-scene-switcher-mobile-header",children:[(0,e.jsxs)("div",{className:"desktop:gap-2 flex items-center gap-1",children:[i&&(0,e.jsx)(r.Heading,{as:"h2",html:i,size:2,className:"media-scene-switcher-title tablet:!text-[40px] desktop:!text-[56px] lg-desktop:!text-[64px] text-[40px] leading-tight text-[#00BEFA]"}),u&&(0,e.jsx)(r.Picture,{source:u.url,alt:u.alt||"title icon",className:"desktop:h-8 lg-desktop:h-10 h-6",imgClassName:"!w-auto h-full"})]}),p&&(0,e.jsx)(r.Text,{as:"span",size:4,html:p,className:"media-scene-switcher-subtitle text-[14px]"})]}),(0,e.jsx)("div",{className:"media-scene-switcher-mobile-swiper mt-[24px] overflow-visible",children:(0,e.jsx)(w.Swiper,{onSlideChange:l=>B(l.realIndex),initialSlide:0,modules:[F.Autoplay],loop:n.length>1,autoplay:n.length>1?{delay:v,disableOnInteraction:!1}:!1,spaceBetween:12,slidesPerView:"auto",watchSlidesProgress:!0,className:"w-full !overflow-visible",children:n.map((l,c)=>(0,e.jsx)(w.SwiperSlide,{className:"!h-auto !w-[296px] max-w-full",children:(0,e.jsx)(O,{data:l,configuration:{index:c,isActive:c===T},theme:x})},l.id||c))})})]})]})]})});M.displayName="MediaSceneSwitcher";var Q=(0,C.withLayout)(M,{style:"overflow: hidden;"});
|
|
11
11
|
//# sourceMappingURL=MediaSceneSwitcher.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/biz-components/MediaSceneSwitcher/MediaSceneSwitcher.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\nimport { useState, useRef, useEffect, forwardRef, useImperativeHandle } from 'react'\nimport { useMediaQuery } from 'react-responsive'\nimport { cn } from '../../helpers/utils.js'\nimport { withLayout } from '../../shared/Styles.js'\nimport { Heading, Text, Picture } from '../../components/index.js'\nimport { useExposure } from '../../hooks/useExposure.js'\nimport type { MediaSceneSwitcherProps, MediaSceneSwitcherItem } from './types.js'\nimport { Swiper, SwiperSlide } from 'swiper/react'\nimport { Autoplay } from 'swiper/modules'\nimport 'swiper/css'\nimport type { Theme } from '../../types/props.js'\n\nconst componentType = 'media'\nconst componentName = 'media_scene_switcher'\nconst INTERVAL_TIME = 3000\n\ninterface ItemProps {\n data: MediaSceneSwitcherItem\n configuration?: {\n index: number\n isActive?: boolean\n onItemClick?: (index: number) => void\n }\n theme?: Theme\n}\n\nconst DesktopItem = ({ data, configuration, theme }: ItemProps) => {\n const ref = useRef<HTMLDivElement>(null)\n const isActive = configuration?.isActive || false\n\n useExposure(ref, {\n componentType,\n componentName,\n componentTitle: data?.title,\n position: (configuration?.index ?? 0) + 1,\n })\n\n return (\n <div\n ref={ref}\n className={cn(\n 'media-scene-switcher-item rounded-box cursor-pointer overflow-hidden transition-colors',\n 'relative text-[#6D6D6F]',\n isActive ? 'opacity-100' : 'opacity-60',\n {\n 'bg-[#1D1D1F] text-white': isActive,\n 'bg-[#EAEAEC] text-[1D1D1F]': isActive && theme === 'light',\n }\n )}\n onClick={() => configuration?.onItemClick?.(configuration?.index ?? 0)}\n >\n <div className=\"media-scene-switcher-item-content laptop:gap-[32px] laptop:p-[12px] desktop:gap-[48px] desktop:p-[24px] flex items-center justify-between gap-[24px]\">\n <div className=\"media-scene-switcher-item-title flex-1\">\n <Heading as=\"h6\" size={2} html={data?.title} />\n </div>\n <div\n className={cn(\n 'media-scene-switcher-item-badge rounded-btn border-[1.6px] px-[18px] py-[7px]',\n theme === 'dark' ? 'border-[#B5B7BB]' : 'border-[#4A4C56]',\n {\n '!border-[#F5F6F7]': theme === 'dark' && isActive,\n }\n )}\n >\n <Heading as=\"h6\" size={2} html={data?.tag} />\n </div>\n </div>\n <div\n className={cn('media-scene-switcher-progress absolute bottom-0 left-0 h-[2px] w-full', {\n 'media-scene-switcher-progress-active': isActive,\n })}\n style={{\n transform: 'translate3d(-100%, 0, 0)',\n background: 'linear-gradient(90deg, #3ad1ff 0%, #008cd6 100%)',\n animation: isActive ? `progress-bar ${INTERVAL_TIME}ms ease-out` : 'none',\n }}\n />\n </div>\n )\n}\n\nconst MobileItem = ({ data, configuration, theme }: ItemProps) => {\n const ref = useRef<HTMLDivElement>(null)\n const isActive = configuration?.isActive || false\n const isMobile = useMediaQuery({ query: '(max-width: 768px)' })\n\n useExposure(ref, {\n componentType,\n componentName,\n componentTitle: data?.title,\n position: (configuration?.index ?? 0) + 1,\n })\n\n const videoUrl = isMobile && data?.mobVideoUrl?.url ? data.mobVideoUrl.url : data?.videoUrl?.url\n const imageUrl = isMobile && data?.mobImageUrl?.url ? data.mobImageUrl.url : data?.imageUrl?.url\n const posterUrl = imageUrl || data?.videoUrl?.thumbnailURL || ''\n\n return (\n <div\n ref={ref}\n className={cn(\n 'media-scene-switcher-mobile-item rounded-box flex h-[360px] w-[296px] max-w-full flex-col overflow-hidden',\n {\n 'aiui-dark': theme === 'dark',\n }\n )}\n >\n <div className=\"media-scene-switcher-mobile-media relative aspect-[554/480] w-full overflow-hidden\">\n {videoUrl ? (\n <video src={videoUrl} playsInline autoPlay loop muted poster={posterUrl} className=\"size-full object-cover\" />\n ) : imageUrl ? (\n <Picture\n className=\"size-full\"\n imgClassName=\"size-full object-cover\"\n source={imageUrl}\n alt={data?.title || ''}\n />\n ) : null}\n </div>\n <div\n className={cn(\n 'media-scene-switcher-mobile-bottom flex items-start justify-between gap-[8px] p-[16px]',\n 'text-[#6D6D6F]',\n {\n 'bg-[#1D1D1F] text-white': isActive,\n 'bg-[#EAEAEC] text-[1D1D1F]': isActive && theme === 'light',\n }\n )}\n >\n <div className=\"media-scene-switcher-mobile-title line-clamp-3 h-[72px] flex-1\">\n <Heading as=\"h6\" size={2} html={data?.title} />\n </div>\n <div\n className={cn(\n 'media-scene-switcher-mobile-badge rounded-btn shrink-0 border-[1.6px] px-[12px] py-[5px]',\n theme === 'dark' ? 'border-[#B5B7BB]' : 'border-[#4A4C56]',\n {\n '!border-[#F5F6F7]': theme === 'dark' && isActive,\n }\n )}\n >\n <Heading as=\"h6\" size={1} html={data?.tag} />\n </div>\n </div>\n <div\n className={cn('media-scene-switcher-progress h-[2px] w-full', {\n 'media-scene-switcher-progress-active': isActive,\n })}\n style={{\n transform: 'translate3d(-100%, 0, 0)',\n background: 'linear-gradient(90deg, #3ad1ff 0%, #008cd6 100%)',\n animation: isActive ? `progress-bar ${INTERVAL_TIME}ms ease-out` : 'none',\n }}\n />\n </div>\n )\n}\n\nconst MediaSceneSwitcher = forwardRef<HTMLDivElement, MediaSceneSwitcherProps>(({ className = '', data, id }, ref) => {\n const { title, subtitle, items = [], theme = 'light', layout, titleIcon } = data || {}\n const [currentIndex, setCurrentIndex] = useState(0)\n const [activeIndex, setActiveIndex] = useState(0)\n const innerRef = useRef<HTMLDivElement>(null)\n const intervalRef = useRef<number>(0)\n const isMobile = useMediaQuery({ query: '(max-width: 1023px)' })\n\n useImperativeHandle(ref, () => innerRef.current as HTMLDivElement)\n\n useExposure(innerRef, {\n componentType,\n componentName,\n componentTitle: title,\n })\n\n // Auto-play functionality for desktop\n useEffect(() => {\n if (isMobile || items.length === 0) return\n\n intervalRef.current = window.setInterval(() => {\n setCurrentIndex(prev => (prev + 1) % items.length)\n }, INTERVAL_TIME)\n\n return () => {\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current)\n }\n }\n }, [isMobile, items.length])\n\n const handleItemClick = (index: number) => {\n setCurrentIndex(index)\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current)\n }\n intervalRef.current = window.setInterval(() => {\n setCurrentIndex(prev => (prev + 1) % items.length)\n }, INTERVAL_TIME)\n }\n\n const currentItem = items[currentIndex]\n const videoUrl = currentItem?.videoUrl?.url\n const imageUrl = currentItem?.imageUrl?.url\n const posterUrl = imageUrl || currentItem?.videoUrl?.thumbnailURL || ''\n\n return (\n <>\n <style>{`\n @keyframes progress-bar {\n from {\n transform: translate3d(-100%, 0, 0);\n }\n to {\n transform: translate3d(0, 0, 0);\n }\n }\n `}</style>\n <section\n id={id}\n ref={innerRef}\n className={cn(\n 'media-scene-switcher text-info-primary w-full',\n {\n 'aiui-dark': theme === 'dark',\n },\n className\n )}\n >\n {/* Desktop Layout */}\n <div className=\"media-scene-switcher-desktop laptop:gap-[24px] lg-desktop:gap-[40px] laptop:flex hidden w-full items-stretch gap-[20px] overflow-hidden\">\n <div\n className={cn(\n 'media-scene-switcher-preview rounded-box laptop:flex-1 relative aspect-[824/640] max-w-[824px] shrink-0 overflow-hidden',\n {\n 'order-1': layout === 'right',\n }\n )}\n >\n {items.map((item, index) => {\n const itemVideoUrl = item?.videoUrl?.url\n const itemImageUrl = item?.imageUrl?.url\n const itemPosterUrl = itemImageUrl || item?.videoUrl?.thumbnailURL || ''\n\n return (\n <div\n key={item.id || index}\n className={cn(\n 'media-scene-switcher-media rounded-box absolute inset-0 hidden size-full overflow-hidden',\n {\n 'inline-block': index === currentIndex,\n }\n )}\n >\n {itemVideoUrl ? (\n <video\n src={itemVideoUrl}\n playsInline\n autoPlay\n loop\n muted\n poster={itemPosterUrl}\n className=\"size-full object-cover\"\n />\n ) : itemImageUrl ? (\n <Picture\n className=\"size-full\"\n imgClassName=\"size-full object-cover\"\n source={itemImageUrl}\n alt={item?.title || ''}\n />\n ) : null}\n </div>\n )\n })}\n </div>\n\n <div className=\"media-scene-switcher-sidebar laptop:flex-1 flex shrink-0 flex-col justify-between\">\n <div className=\"media-scene-switcher-header flex flex-col\">\n <div className=\"desktop:gap-2 flex items-center gap-1\">\n {title && (\n <Heading\n as=\"h3\"\n html={title}\n size={4}\n className=\"media-scene-switcher-title text-info-primary tablet:!text-[40px] desktop:!text-[56px] lg-desktop:!text-[64px] text-[40px] leading-none text-[#00BEFA]\"\n />\n )}\n {titleIcon && (\n <Picture\n source={titleIcon.url}\n alt={titleIcon.alt || 'title icon'}\n className=\"desktop:h-8 lg-desktop:h-10 h-6\"\n imgClassName=\"!w-auto h-full\"\n />\n )}\n </div>\n\n {subtitle && (\n <Text\n as=\"span\"\n size={4}\n html={subtitle}\n className=\"media-scene-switcher-subtitle tablet:text-[14px] laptop:text-[14px] desktop:text-[16px] lg-desktop:text-[18px] relative -top-2 mt-3 text-[14px]\"\n />\n )}\n </div>\n\n <div className=\"media-scene-switcher-list flex flex-col gap-[16px]\">\n {items.map((item, index) => (\n <DesktopItem\n key={item.id || index}\n data={item}\n configuration={{\n index,\n isActive: index === currentIndex,\n onItemClick: handleItemClick,\n }}\n theme={theme}\n />\n ))}\n </div>\n </div>\n </div>\n\n {/* Mobile Layout */}\n <div className=\"media-scene-switcher-mobile laptop:hidden flex flex-col overflow-visible\">\n <div className=\"media-scene-switcher-mobile-header\">\n <div className=\"desktop:gap-2 flex items-center gap-1\">\n {title && (\n <Heading\n as=\"h2\"\n html={title}\n size={2}\n className=\"media-scene-switcher-title tablet:!text-[40px] desktop:!text-[56px] lg-desktop:!text-[64px] text-[40px] leading-tight text-[#00BEFA]\"\n />\n )}\n {titleIcon && (\n <Picture\n source={titleIcon.url}\n alt={titleIcon.alt || 'title icon'}\n className=\"desktop:h-8 lg-desktop:h-10 h-6\"\n imgClassName=\"!w-auto h-full\"\n />\n )}\n </div>\n {subtitle && (\n <Text as=\"span\" size={4} html={subtitle} className=\"media-scene-switcher-subtitle text-[14px]\" />\n )}\n </div>\n\n <div className=\"media-scene-switcher-mobile-swiper mt-[24px] overflow-visible\">\n <Swiper\n onSlideChange={swiper => setActiveIndex(swiper.realIndex)}\n initialSlide={0}\n modules={[Autoplay]}\n loop={items.length > 1}\n autoplay={items.length > 1 ? { delay: INTERVAL_TIME, disableOnInteraction: false } : false}\n spaceBetween={12}\n slidesPerView=\"auto\"\n watchSlidesProgress={true}\n className=\"w-full !overflow-visible\"\n >\n {items.map((item, index) => (\n <SwiperSlide key={item.id || index} className=\"!h-auto !w-[296px] max-w-full\">\n <MobileItem\n data={item}\n configuration={{\n index,\n isActive: index === activeIndex,\n }}\n theme={theme}\n />\n </SwiperSlide>\n ))}\n </Swiper>\n </div>\n </div>\n </section>\n </>\n )\n})\n\nMediaSceneSwitcher.displayName = 'MediaSceneSwitcher'\n\nexport default withLayout(MediaSceneSwitcher, { style: 'overflow: hidden;' })\n"],
|
|
5
|
-
"mappings": "sbAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,aAAAE,IAAA,eAAAC,EAAAH,
|
|
4
|
+
"sourcesContent": ["'use client'\nimport { useState, useRef, useEffect, forwardRef, useImperativeHandle } from 'react'\nimport { useMediaQuery } from 'react-responsive'\nimport { cn } from '../../helpers/utils.js'\nimport { withLayout } from '../../shared/Styles.js'\nimport { Heading, Text, Picture } from '../../components/index.js'\nimport { useExposure } from '../../hooks/useExposure.js'\nimport type { MediaSceneSwitcherProps, MediaSceneSwitcherItem } from './types.js'\nimport { Swiper, SwiperSlide } from 'swiper/react'\nimport { Autoplay } from 'swiper/modules'\nimport 'swiper/css'\nimport type { Theme } from '../../types/props.js'\n\nconst componentType = 'media'\nconst componentName = 'media_scene_switcher'\nconst INTERVAL_TIME = 3000\n\ninterface ItemProps {\n data: MediaSceneSwitcherItem\n configuration?: {\n index: number\n isActive?: boolean\n onItemClick?: (index: number) => void\n }\n theme?: Theme\n}\n\nconst DesktopItem = ({ data, configuration, theme }: ItemProps) => {\n const ref = useRef<HTMLDivElement>(null)\n const isActive = configuration?.isActive || false\n\n useExposure(ref, {\n componentType,\n componentName,\n componentTitle: data?.title,\n position: (configuration?.index ?? 0) + 1,\n })\n\n return (\n <div\n ref={ref}\n className={cn(\n 'media-scene-switcher-item rounded-box cursor-pointer overflow-hidden transition-colors',\n 'relative text-[#6D6D6F]',\n isActive ? 'opacity-100' : 'opacity-60',\n {\n 'bg-[#1D1D1F] text-white': isActive,\n 'bg-[#EAEAEC] text-[1D1D1F]': isActive && theme === 'light',\n }\n )}\n onClick={() => configuration?.onItemClick?.(configuration?.index ?? 0)}\n >\n <div className=\"media-scene-switcher-item-content laptop:gap-[32px] laptop:p-[12px] desktop:gap-[48px] desktop:p-[24px] flex items-center justify-between gap-[24px]\">\n <div>\n <div className=\"media-scene-switcher-item-title flex-1\">\n <Heading as=\"h6\" size={2} html={data?.title} />\n </div>\n {data?.description && isActive && (\n <Text\n size={2}\n className=\"media-scene-switcher-item-description tablet:text-base desktop:text-lg mt-1 text-sm font-bold\"\n html={data.description}\n />\n )}\n </div>\n\n <div\n className={cn(\n 'media-scene-switcher-item-badge rounded-btn border-[1.6px] px-[18px] py-[7px]',\n theme === 'dark' ? 'border-[#B5B7BB]' : 'border-[#4A4C56]',\n {\n '!border-[#F5F6F7]': theme === 'dark' && isActive,\n }\n )}\n >\n <Heading as=\"h6\" size={2} html={data?.tag} />\n </div>\n </div>\n <div\n className={cn('media-scene-switcher-progress absolute bottom-0 left-0 h-[2px] w-full', {\n 'media-scene-switcher-progress-active': isActive,\n })}\n style={{\n transform: 'translate3d(-100%, 0, 0)',\n background: 'linear-gradient(90deg, #3ad1ff 0%, #008cd6 100%)',\n animation: isActive ? `progress-bar ${INTERVAL_TIME}ms ease-out` : 'none',\n }}\n />\n </div>\n )\n}\n\nconst MobileItem = ({ data, configuration, theme }: ItemProps) => {\n const ref = useRef<HTMLDivElement>(null)\n const isActive = configuration?.isActive || false\n const isMobile = useMediaQuery({ query: '(max-width: 768px)' })\n\n useExposure(ref, {\n componentType,\n componentName,\n componentTitle: data?.title,\n position: (configuration?.index ?? 0) + 1,\n })\n\n const videoUrl = isMobile && data?.mobVideoUrl?.url ? data.mobVideoUrl.url : data?.videoUrl?.url\n const imageUrl = isMobile && data?.mobImageUrl?.url ? data.mobImageUrl.url : data?.imageUrl?.url\n const posterUrl = imageUrl || data?.videoUrl?.thumbnailURL || ''\n\n return (\n <div\n ref={ref}\n className={cn(\n 'media-scene-switcher-mobile-item rounded-box flex h-[360px] w-[296px] max-w-full flex-col overflow-hidden',\n {\n 'aiui-dark': theme === 'dark',\n }\n )}\n >\n <div className=\"media-scene-switcher-mobile-media relative aspect-[554/480] w-full overflow-hidden\">\n {videoUrl ? (\n <video src={videoUrl} playsInline autoPlay loop muted poster={posterUrl} className=\"size-full object-cover\" />\n ) : imageUrl ? (\n <Picture\n className=\"size-full\"\n imgClassName=\"size-full object-cover\"\n source={imageUrl}\n alt={data?.title || ''}\n />\n ) : null}\n </div>\n <div\n className={cn(\n 'media-scene-switcher-mobile-bottom flex items-start justify-between gap-[8px] p-[16px]',\n 'text-[#6D6D6F]',\n {\n 'bg-[#1D1D1F] text-white': isActive,\n 'bg-[#EAEAEC] text-[1D1D1F]': isActive && theme === 'light',\n }\n )}\n >\n <div>\n <div className=\"media-scene-switcher-mobile-title line-clamp-3 h-[72px] flex-1\">\n <Heading as=\"h6\" size={2} html={data?.title} />\n </div>\n {data?.description && isActive && (\n <Text\n size={2}\n className=\"media-scene-switcher-item-description tablet:text-base desktop:text-lg mt-1 line-clamp-3 text-sm font-bold\"\n html={data.description}\n />\n )}\n </div>\n <div\n className={cn(\n 'media-scene-switcher-mobile-badge rounded-btn shrink-0 border-[1.6px] px-[12px] py-[5px]',\n theme === 'dark' ? 'border-[#B5B7BB]' : 'border-[#4A4C56]',\n {\n '!border-[#F5F6F7]': theme === 'dark' && isActive,\n }\n )}\n >\n <Heading as=\"h6\" size={1} html={data?.tag} />\n </div>\n </div>\n <div\n className={cn('media-scene-switcher-progress h-[2px] w-full', {\n 'media-scene-switcher-progress-active': isActive,\n })}\n style={{\n transform: 'translate3d(-100%, 0, 0)',\n background: 'linear-gradient(90deg, #3ad1ff 0%, #008cd6 100%)',\n animation: isActive ? `progress-bar ${INTERVAL_TIME}ms ease-out` : 'none',\n }}\n />\n </div>\n )\n}\n\nconst MediaSceneSwitcher = forwardRef<HTMLDivElement, MediaSceneSwitcherProps>(({ className = '', data, id }, ref) => {\n const { title, subtitle, items = [], theme = 'light', layout, titleIcon } = data || {}\n const [currentIndex, setCurrentIndex] = useState(0)\n const [activeIndex, setActiveIndex] = useState(0)\n const innerRef = useRef<HTMLDivElement>(null)\n const intervalRef = useRef<number>(0)\n const isMobile = useMediaQuery({ query: '(max-width: 1023px)' })\n\n useImperativeHandle(ref, () => innerRef.current as HTMLDivElement)\n\n useExposure(innerRef, {\n componentType,\n componentName,\n componentTitle: title,\n })\n\n // Auto-play functionality for desktop\n useEffect(() => {\n if (isMobile || items.length === 0) return\n\n intervalRef.current = window.setInterval(() => {\n setCurrentIndex(prev => (prev + 1) % items.length)\n }, INTERVAL_TIME)\n\n return () => {\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current)\n }\n }\n }, [isMobile, items.length])\n\n const handleItemClick = (index: number) => {\n setCurrentIndex(index)\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current)\n }\n intervalRef.current = window.setInterval(() => {\n setCurrentIndex(prev => (prev + 1) % items.length)\n }, INTERVAL_TIME)\n }\n\n const currentItem = items[currentIndex]\n const videoUrl = currentItem?.videoUrl?.url\n const imageUrl = currentItem?.imageUrl?.url\n const posterUrl = imageUrl || currentItem?.videoUrl?.thumbnailURL || ''\n\n return (\n <>\n <style>{`\n @keyframes progress-bar {\n from {\n transform: translate3d(-100%, 0, 0);\n }\n to {\n transform: translate3d(0, 0, 0);\n }\n }\n `}</style>\n <section\n id={id}\n ref={innerRef}\n className={cn(\n 'media-scene-switcher text-info-primary w-full',\n {\n 'aiui-dark': theme === 'dark',\n },\n className\n )}\n >\n {/* Desktop Layout */}\n <div className=\"media-scene-switcher-desktop laptop:gap-[24px] lg-desktop:gap-[40px] laptop:flex hidden w-full items-stretch gap-[20px] overflow-hidden\">\n <div\n className={cn(\n 'media-scene-switcher-preview rounded-box laptop:flex-1 relative aspect-[824/640] max-w-[824px] shrink-0 overflow-hidden',\n {\n 'order-1': layout === 'right',\n }\n )}\n >\n {items.map((item, index) => {\n const itemVideoUrl = item?.videoUrl?.url\n const itemImageUrl = item?.imageUrl?.url\n const itemPosterUrl = itemImageUrl || item?.videoUrl?.thumbnailURL || ''\n\n return (\n <div\n key={item.id || index}\n className={cn(\n 'media-scene-switcher-media rounded-box absolute inset-0 hidden size-full overflow-hidden',\n {\n 'inline-block': index === currentIndex,\n }\n )}\n >\n {itemVideoUrl ? (\n <video\n src={itemVideoUrl}\n playsInline\n autoPlay\n loop\n muted\n poster={itemPosterUrl}\n className=\"size-full object-cover\"\n />\n ) : itemImageUrl ? (\n <Picture\n className=\"size-full\"\n imgClassName=\"size-full object-cover\"\n source={itemImageUrl}\n alt={item?.title || ''}\n />\n ) : null}\n </div>\n )\n })}\n </div>\n\n <div className=\"media-scene-switcher-sidebar laptop:flex-1 flex shrink-0 flex-col justify-between\">\n <div className=\"media-scene-switcher-header flex flex-col\">\n <div className=\"desktop:gap-2 flex items-center gap-1\">\n {title && (\n <Heading\n as=\"h3\"\n html={title}\n size={4}\n className=\"media-scene-switcher-title text-info-primary tablet:!text-[40px] desktop:!text-[56px] lg-desktop:!text-[64px] text-[40px] leading-none text-[#00BEFA]\"\n />\n )}\n {titleIcon && (\n <Picture\n source={titleIcon.url}\n alt={titleIcon.alt || 'title icon'}\n className=\"desktop:h-8 lg-desktop:h-10 h-6\"\n imgClassName=\"!w-auto h-full\"\n />\n )}\n </div>\n\n {subtitle && (\n <Text\n as=\"span\"\n size={4}\n html={subtitle}\n className=\"media-scene-switcher-subtitle tablet:text-[14px] laptop:text-[14px] desktop:text-[16px] lg-desktop:text-[18px] relative -top-2 mt-3 text-[14px]\"\n />\n )}\n </div>\n\n <div className=\"media-scene-switcher-list flex flex-col gap-[16px]\">\n {items.map((item, index) => (\n <DesktopItem\n key={item.id || index}\n data={item}\n configuration={{\n index,\n isActive: index === currentIndex,\n onItemClick: handleItemClick,\n }}\n theme={theme}\n />\n ))}\n </div>\n </div>\n </div>\n\n {/* Mobile Layout */}\n <div className=\"media-scene-switcher-mobile laptop:hidden flex flex-col overflow-visible\">\n <div className=\"media-scene-switcher-mobile-header\">\n <div className=\"desktop:gap-2 flex items-center gap-1\">\n {title && (\n <Heading\n as=\"h2\"\n html={title}\n size={2}\n className=\"media-scene-switcher-title tablet:!text-[40px] desktop:!text-[56px] lg-desktop:!text-[64px] text-[40px] leading-tight text-[#00BEFA]\"\n />\n )}\n {titleIcon && (\n <Picture\n source={titleIcon.url}\n alt={titleIcon.alt || 'title icon'}\n className=\"desktop:h-8 lg-desktop:h-10 h-6\"\n imgClassName=\"!w-auto h-full\"\n />\n )}\n </div>\n {subtitle && (\n <Text as=\"span\" size={4} html={subtitle} className=\"media-scene-switcher-subtitle text-[14px]\" />\n )}\n </div>\n\n <div className=\"media-scene-switcher-mobile-swiper mt-[24px] overflow-visible\">\n <Swiper\n onSlideChange={swiper => setActiveIndex(swiper.realIndex)}\n initialSlide={0}\n modules={[Autoplay]}\n loop={items.length > 1}\n autoplay={items.length > 1 ? { delay: INTERVAL_TIME, disableOnInteraction: false } : false}\n spaceBetween={12}\n slidesPerView=\"auto\"\n watchSlidesProgress={true}\n className=\"w-full !overflow-visible\"\n >\n {items.map((item, index) => (\n <SwiperSlide key={item.id || index} className=\"!h-auto !w-[296px] max-w-full\">\n <MobileItem\n data={item}\n configuration={{\n index,\n isActive: index === activeIndex,\n }}\n theme={theme}\n />\n </SwiperSlide>\n ))}\n </Swiper>\n </div>\n </div>\n </section>\n </>\n )\n})\n\nMediaSceneSwitcher.displayName = 'MediaSceneSwitcher'\n\nexport default withLayout(MediaSceneSwitcher, { style: 'overflow: hidden;' })\n"],
|
|
5
|
+
"mappings": "sbAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,aAAAE,IAAA,eAAAC,EAAAH,GAqDQ,IAAAI,EAAA,6BApDRC,EAA6E,iBAC7EC,EAA8B,4BAC9BC,EAAmB,kCACnBC,EAA2B,kCAC3BC,EAAuC,qCACvCC,EAA4B,sCAE5BL,EAAoC,wBACpCM,EAAyB,0BACzBC,EAAO,sBAGP,MAAMC,EAAgB,QAChBC,EAAgB,uBAChBC,EAAgB,IAYhBC,EAAc,CAAC,CAAE,KAAAC,EAAM,cAAAC,EAAe,MAAAC,CAAM,IAAiB,CACjE,MAAMC,KAAM,UAAuB,IAAI,EACjCC,EAAWH,GAAe,UAAY,GAE5C,wBAAYE,EAAK,CACf,cAAAP,EACA,cAAAC,EACA,eAAgBG,GAAM,MACtB,UAAWC,GAAe,OAAS,GAAK,CAC1C,CAAC,KAGC,QAAC,OACC,IAAKE,EACL,aAAW,MACT,yFACA,0BACAC,EAAW,cAAgB,aAC3B,CACE,0BAA2BA,EAC3B,6BAA8BA,GAAYF,IAAU,OACtD,CACF,EACA,QAAS,IAAMD,GAAe,cAAcA,GAAe,OAAS,CAAC,EAErE,qBAAC,OAAI,UAAU,uJACb,qBAAC,OACC,oBAAC,OAAI,UAAU,yCACb,mBAAC,WAAQ,GAAG,KAAK,KAAM,EAAG,KAAMD,GAAM,MAAO,EAC/C,EACCA,GAAM,aAAeI,MACpB,OAAC,QACC,KAAM,EACN,UAAU,gGACV,KAAMJ,EAAK,YACb,GAEJ,KAEA,OAAC,OACC,aAAW,MACT,gFACAE,IAAU,OAAS,mBAAqB,mBACxC,CACE,oBAAqBA,IAAU,QAAUE,CAC3C,CACF,EAEA,mBAAC,WAAQ,GAAG,KAAK,KAAM,EAAG,KAAMJ,GAAM,IAAK,EAC7C,GACF,KACA,OAAC,OACC,aAAW,MAAG,wEAAyE,CACrF,uCAAwCI,CAC1C,CAAC,EACD,MAAO,CACL,UAAW,2BACX,WAAY,mDACZ,UAAWA,EAAW,gBAAgBN,CAAa,cAAgB,MACrE,EACF,GACF,CAEJ,EAEMO,EAAa,CAAC,CAAE,KAAAL,EAAM,cAAAC,EAAe,MAAAC,CAAM,IAAiB,CAChE,MAAMC,KAAM,UAAuB,IAAI,EACjCC,EAAWH,GAAe,UAAY,GACtCK,KAAW,iBAAc,CAAE,MAAO,oBAAqB,CAAC,KAE9D,eAAYH,EAAK,CACf,cAAAP,EACA,cAAAC,EACA,eAAgBG,GAAM,MACtB,UAAWC,GAAe,OAAS,GAAK,CAC1C,CAAC,EAED,MAAMM,EAAWD,GAAYN,GAAM,aAAa,IAAMA,EAAK,YAAY,IAAMA,GAAM,UAAU,IACvFQ,EAAWF,GAAYN,GAAM,aAAa,IAAMA,EAAK,YAAY,IAAMA,GAAM,UAAU,IACvFS,EAAYD,GAAYR,GAAM,UAAU,cAAgB,GAE9D,SACE,QAAC,OACC,IAAKG,EACL,aAAW,MACT,4GACA,CACE,YAAaD,IAAU,MACzB,CACF,EAEA,oBAAC,OAAI,UAAU,qFACZ,SAAAK,KACC,OAAC,SAAM,IAAKA,EAAU,YAAW,GAAC,SAAQ,GAAC,KAAI,GAAC,MAAK,GAAC,OAAQE,EAAW,UAAU,yBAAyB,EAC1GD,KACF,OAAC,WACC,UAAU,YACV,aAAa,yBACb,OAAQA,EACR,IAAKR,GAAM,OAAS,GACtB,EACE,KACN,KACA,QAAC,OACC,aAAW,MACT,yFACA,iBACA,CACE,0BAA2BI,EAC3B,6BAA8BA,GAAYF,IAAU,OACtD,CACF,EAEA,qBAAC,OACC,oBAAC,OAAI,UAAU,iEACb,mBAAC,WAAQ,GAAG,KAAK,KAAM,EAAG,KAAMF,GAAM,MAAO,EAC/C,EACCA,GAAM,aAAeI,MACpB,OAAC,QACC,KAAM,EACN,UAAU,6GACV,KAAMJ,EAAK,YACb,GAEJ,KACA,OAAC,OACC,aAAW,MACT,2FACAE,IAAU,OAAS,mBAAqB,mBACxC,CACE,oBAAqBA,IAAU,QAAUE,CAC3C,CACF,EAEA,mBAAC,WAAQ,GAAG,KAAK,KAAM,EAAG,KAAMJ,GAAM,IAAK,EAC7C,GACF,KACA,OAAC,OACC,aAAW,MAAG,+CAAgD,CAC5D,uCAAwCI,CAC1C,CAAC,EACD,MAAO,CACL,UAAW,2BACX,WAAY,mDACZ,UAAWA,EAAW,gBAAgBN,CAAa,cAAgB,MACrE,EACF,GACF,CAEJ,EAEMY,KAAqB,cAAoD,CAAC,CAAE,UAAAC,EAAY,GAAI,KAAAX,EAAM,GAAAY,CAAG,EAAGT,IAAQ,CACpH,KAAM,CAAE,MAAAU,EAAO,SAAAC,EAAU,MAAAC,EAAQ,CAAC,EAAG,MAAAb,EAAQ,QAAS,OAAAc,EAAQ,UAAAC,CAAU,EAAIjB,GAAQ,CAAC,EAC/E,CAACkB,EAAcC,CAAe,KAAI,YAAS,CAAC,EAC5C,CAACC,EAAaC,CAAc,KAAI,YAAS,CAAC,EAC1CC,KAAW,UAAuB,IAAI,EACtCC,KAAc,UAAe,CAAC,EAC9BjB,KAAW,iBAAc,CAAE,MAAO,qBAAsB,CAAC,KAE/D,uBAAoBH,EAAK,IAAMmB,EAAS,OAAyB,KAEjE,eAAYA,EAAU,CACpB,cAAA1B,EACA,cAAAC,EACA,eAAgBgB,CAClB,CAAC,KAGD,aAAU,IAAM,CACd,GAAI,EAAAP,GAAYS,EAAM,SAAW,GAEjC,OAAAQ,EAAY,QAAU,OAAO,YAAY,IAAM,CAC7CJ,EAAgBK,IAASA,EAAO,GAAKT,EAAM,MAAM,CACnD,EAAGjB,CAAa,EAET,IAAM,CACPyB,EAAY,SACd,OAAO,cAAcA,EAAY,OAAO,CAE5C,CACF,EAAG,CAACjB,EAAUS,EAAM,MAAM,CAAC,EAE3B,MAAMU,EAAmBC,GAAkB,CACzCP,EAAgBO,CAAK,EACjBH,EAAY,SACd,OAAO,cAAcA,EAAY,OAAO,EAE1CA,EAAY,QAAU,OAAO,YAAY,IAAM,CAC7CJ,EAAgBK,IAASA,EAAO,GAAKT,EAAM,MAAM,CACnD,EAAGjB,CAAa,CAClB,EAEM6B,EAAcZ,EAAMG,CAAY,EAChCX,EAAWoB,GAAa,UAAU,IAElClB,EADWkB,GAAa,UAAU,KACVA,GAAa,UAAU,cAAgB,GAErE,SACE,oBACE,oBAAC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UASJ,KACJ,QAAC,WACC,GAAIf,EACJ,IAAKU,EACL,aAAW,MACT,gDACA,CACE,YAAapB,IAAU,MACzB,EACAS,CACF,EAGA,qBAAC,OAAI,UAAU,0IACb,oBAAC,OACC,aAAW,MACT,0HACA,CACE,UAAWK,IAAW,OACxB,CACF,EAEC,SAAAD,EAAM,IAAI,CAACa,EAAMF,IAAU,CAC1B,MAAMG,EAAeD,GAAM,UAAU,IAC/BE,EAAeF,GAAM,UAAU,IAC/BG,EAAgBD,GAAgBF,GAAM,UAAU,cAAgB,GAEtE,SACE,OAAC,OAEC,aAAW,MACT,2FACA,CACE,eAAgBF,IAAUR,CAC5B,CACF,EAEC,SAAAW,KACC,OAAC,SACC,IAAKA,EACL,YAAW,GACX,SAAQ,GACR,KAAI,GACJ,MAAK,GACL,OAAQE,EACR,UAAU,yBACZ,EACED,KACF,OAAC,WACC,UAAU,YACV,aAAa,yBACb,OAAQA,EACR,IAAKF,GAAM,OAAS,GACtB,EACE,MAzBCA,EAAK,IAAMF,CA0BlB,CAEJ,CAAC,EACH,KAEA,QAAC,OAAI,UAAU,oFACb,qBAAC,OAAI,UAAU,4CACb,qBAAC,OAAI,UAAU,wCACZ,UAAAb,MACC,OAAC,WACC,GAAG,KACH,KAAMA,EACN,KAAM,EACN,UAAU,wJACZ,EAEDI,MACC,OAAC,WACC,OAAQA,EAAU,IAClB,IAAKA,EAAU,KAAO,aACtB,UAAU,kCACV,aAAa,iBACf,GAEJ,EAECH,MACC,OAAC,QACC,GAAG,OACH,KAAM,EACN,KAAMA,EACN,UAAU,kJACZ,GAEJ,KAEA,OAAC,OAAI,UAAU,qDACZ,SAAAC,EAAM,IAAI,CAACa,EAAMF,OAChB,OAAC3B,EAAA,CAEC,KAAM6B,EACN,cAAe,CACb,MAAAF,EACA,SAAUA,IAAUR,EACpB,YAAaO,CACf,EACA,MAAOvB,GAPF0B,EAAK,IAAMF,CAQlB,CACD,EACH,GACF,GACF,KAGA,QAAC,OAAI,UAAU,2EACb,qBAAC,OAAI,UAAU,qCACb,qBAAC,OAAI,UAAU,wCACZ,UAAAb,MACC,OAAC,WACC,GAAG,KACH,KAAMA,EACN,KAAM,EACN,UAAU,uIACZ,EAEDI,MACC,OAAC,WACC,OAAQA,EAAU,IAClB,IAAKA,EAAU,KAAO,aACtB,UAAU,kCACV,aAAa,iBACf,GAEJ,EACCH,MACC,OAAC,QAAK,GAAG,OAAO,KAAM,EAAG,KAAMA,EAAU,UAAU,4CAA4C,GAEnG,KAEA,OAAC,OAAI,UAAU,gEACb,mBAAC,UACC,cAAekB,GAAUX,EAAeW,EAAO,SAAS,EACxD,aAAc,EACd,QAAS,CAAC,UAAQ,EAClB,KAAMjB,EAAM,OAAS,EACrB,SAAUA,EAAM,OAAS,EAAI,CAAE,MAAOjB,EAAe,qBAAsB,EAAM,EAAI,GACrF,aAAc,GACd,cAAc,OACd,oBAAqB,GACrB,UAAU,2BAET,SAAAiB,EAAM,IAAI,CAACa,EAAMF,OAChB,OAAC,eAAmC,UAAU,gCAC5C,mBAACrB,EAAA,CACC,KAAMuB,EACN,cAAe,CACb,MAAAF,EACA,SAAUA,IAAUN,CACtB,EACA,MAAOlB,EACT,GARgB0B,EAAK,IAAMF,CAS7B,CACD,EACH,EACF,GACF,GACF,GACF,CAEJ,CAAC,EAEDhB,EAAmB,YAAc,qBAEjC,IAAOzB,KAAQ,cAAWyB,EAAoB,CAAE,MAAO,mBAAoB,CAAC",
|
|
6
6
|
"names": ["MediaSceneSwitcher_exports", "__export", "MediaSceneSwitcher_default", "__toCommonJS", "import_jsx_runtime", "import_react", "import_react_responsive", "import_utils", "import_Styles", "import_components", "import_useExposure", "import_modules", "import_css", "componentType", "componentName", "INTERVAL_TIME", "DesktopItem", "data", "configuration", "theme", "ref", "isActive", "MobileItem", "isMobile", "videoUrl", "imageUrl", "posterUrl", "MediaSceneSwitcher", "className", "id", "title", "subtitle", "items", "layout", "titleIcon", "currentIndex", "setCurrentIndex", "activeIndex", "setActiveIndex", "innerRef", "intervalRef", "prev", "handleItemClick", "index", "currentItem", "item", "itemVideoUrl", "itemImageUrl", "itemPosterUrl", "swiper"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var n=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var a=Object.prototype.hasOwnProperty;var
|
|
1
|
+
"use strict";var n=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var a=Object.prototype.hasOwnProperty;var s=(t,e,o,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of m(e))!a.call(t,i)&&i!==o&&n(t,i,{get:()=>e[i],enumerable:!(r=l(e,i))||r.enumerable});return t};var d=t=>s(n({},"__esModule",{value:!0}),t);var p={};module.exports=d(p);
|
|
2
2
|
//# sourceMappingURL=types.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/biz-components/MediaSceneSwitcher/types.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ComponentCommonProps, Media, Theme } from '../../types/props.js'\n\nexport interface MediaSceneSwitcherItem {\n id: string\n title: string\n tag?: string\n videoUrl?: Media | null\n imageUrl?: Media | null\n mobVideoUrl?: Media | null\n mobImageUrl?: Media | null\n}\n\nexport interface MediaSceneSwitcherProps extends ComponentCommonProps {\n data: {\n titleIcon?: Media\n title?: string\n subtitle?: string\n items?: MediaSceneSwitcherItem[]\n /** \u4E3B\u9898\uFF0C\u9ED8\u8BA4 light */\n theme?: Theme\n layout?: 'left' | 'right'\n }\n}\n"],
|
|
4
|
+
"sourcesContent": ["import type { ComponentCommonProps, Media, Theme } from '../../types/props.js'\n\nexport interface MediaSceneSwitcherItem {\n id: string\n title: string\n description?: string\n tag?: string\n videoUrl?: Media | null\n imageUrl?: Media | null\n mobVideoUrl?: Media | null\n mobImageUrl?: Media | null\n}\n\nexport interface MediaSceneSwitcherProps extends ComponentCommonProps {\n data: {\n titleIcon?: Media\n title?: string\n subtitle?: string\n items?: MediaSceneSwitcherItem[]\n /** \u4E3B\u9898\uFF0C\u9ED8\u8BA4 light */\n theme?: Theme\n layout?: 'left' | 'right'\n }\n}\n"],
|
|
5
5
|
"mappings": "+WAAA,IAAAA,EAAA,kBAAAC,EAAAD",
|
|
6
6
|
"names": ["types_exports", "__toCommonJS"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";"use client";var z=Object.create;var
|
|
1
|
+
"use strict";"use client";var z=Object.create;var p=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var I=Object.getOwnPropertyNames;var _=Object.getPrototypeOf,q=Object.prototype.hasOwnProperty;var E=(e,i)=>{for(var r in i)p(e,r,{get:i[r],enumerable:!0})},k=(e,i,r,d)=>{if(i&&typeof i=="object"||typeof i=="function")for(let s of I(i))!q.call(e,s)&&s!==r&&p(e,s,{get:()=>i[s],enumerable:!(d=A(i,s))||d.enumerable});return e};var H=(e,i,r)=>(r=e!=null?z(_(e)):{},k(i||!e||!e.__esModule?p(r,"default",{value:e,enumerable:!0}):r,e)),R=e=>k(p({},"__esModule",{value:!0}),e);var K={};E(K,{ProductCard:()=>f,default:()=>G});module.exports=R(K);var a=require("react/jsx-runtime"),c=H(require("react")),n=require("../../helpers/index.js"),t=require("../../components/index.js");const O=5;function j(e,i,r,d){if(e===void 0)return!0;switch(e){case"always":return!0;case"never":return!1;case"below-quantity":return i===void 0?!0:r<=i;case"below-percentage":return i===void 0?!0:r/d*100<=i;default:return!0}}const f=c.forwardRef(({product:e,className:i,stockDisplayMode:r,stockThresholdValue:d,onLearnMore:s,onShopNow:S,onAddToCart:w,classNames:l,secondaryButtonText:y,secondaryButtonFun:b,primaryButtonText:g,primaryButtonFun:v,showOriginalPrice:N,copy:u,onProductImageClick:x},P)=>{const[B,F]=c.useState(!1),[L,M]=c.useState(!1),T=c.useMemo(()=>e?.availableForSale&&e?.quantityAvailable<=0?O:e?.availableForSale?(e?.quantityAvailable??0)/(e?.totalInventory??1)*100:0,[e?.availableForSale,e?.quantityAvailable,e?.totalInventory]),C=async(o,m)=>{if(!o)return;const h=m==="primary"?F:M;h(!0);try{switch(o){case"buyNow":await S?.(e);break;case"addCart":await w?.(e);break;case"learnMore":await s?.(e);break;default:break}}finally{h(!1)}},D=e.availableForSale&&e.quantityAvailable<=0;return(0,a.jsxs)(t.Card,{ref:P,className:(0,n.cn)("tablet:min-w-[auto] hover:bg-container-secondary-0 flex h-full min-w-[296px] flex-col overflow-hidden border-none",e.custom_link?"cursor-pointer":"",i,l?.productCard),children:[(0,a.jsxs)("div",{className:(0,n.cn)("media-shelf-product-card-image-wrapper desktop:h-[240px] relative h-[200px] shrink-0 overflow-hidden",l?.productCardImageWrapper),children:[(0,a.jsx)("div",{className:(0,n.cn)("media-shelf-product-card-image-bg absolute inset-0 ",l?.productCardImageBg),children:(0,a.jsx)("a",{onClick:()=>x?.(e),...!x&&{href:e.custom_link||e.listingLink},className:"cursor-pointer",children:(0,a.jsx)(t.Picture,{source:e.custom_image||e.image,alt:e.name,className:(0,n.cn)("h-full",l?.productCardImage),imgClassName:"h-full object-contain"})})}),(0,a.jsx)("div",{className:"lg-desktop:h-[28px] absolute left-4 top-4 flex h-[24px]",children:e.tags?.map((o,m)=>o.label?(0,a.jsx)(t.Badge,{size:"sm",variant:o.variant||"outline",className:(0,n.cn)("mr-1"),promotionalType:o.promotionalType,children:o.label},m):(0,a.jsx)(c.Fragment,{children:o},m))})]}),(0,a.jsxs)(t.CardContent,{className:"desktop:p-6 bg-container-primary laptop:gap-6 flex h-[calc(100%-240px)] grow flex-col justify-between gap-4 p-4",children:[(0,a.jsxs)("div",{className:"flex-0",children:[(0,a.jsx)(t.Heading,{as:"h3",size:2,className:(0,n.cn)("text-info-primary mb-1 line-clamp-2 tracking-tight",l?.productTitle),children:e.custom_name||e.name}),(e.custom_description||e?.description)&&(0,a.jsx)(t.Text,{size:2,className:(0,n.cn)("text-info-primary line-clamp-1",l?.productDescription),html:e.custom_description||e.description})]}),j(r,d,e?.quantityAvailable??0,e?.totalInventory??0)&&(0,a.jsxs)("div",{"data-total":e?.totalInventory??0,"data-available":e?.quantityAvailable??0,className:"space-y-2",children:[(0,a.jsx)(t.Progress,{value:T,max:100,min:0,size:"base",variant:"default","aria-label":"stock progress",classNames:{progressBar:"transition-all duration-300 ease-in-out"}}),(0,a.jsx)(t.Text,{size:3,className:"text-info-tertiary desktop:text-[16px] lg-desktop:text-[18px] text-[12px]",children:D?u?.limitedStock:u?.stockDisplayText?.replace("{count}",`${e.availableForSale?e.quantityAvailable:0}`)})]}),(0,a.jsxs)("div",{children:[e?.priceLabel&&e?.availableForSale&&(0,a.jsx)(t.Text,{size:4,className:(0,n.cn)("text-marketing-1 desktop:text-[16px] lg-desktop:text-[18px] mt-2 text-[12px]",l?.productPriceLabel),children:e.priceLabel}),(0,a.jsx)("div",{className:(0,n.cn)("mb-2",l?.productPrice),children:(0,a.jsx)("div",{className:"flex items-baseline gap-2",children:e.availableForSale?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.Heading,{size:2,className:"text-info-primary",as:"h6",children:e.price}),N&&e.originalPrice&&(0,a.jsx)(t.Heading,{size:2,className:"text-info-tertiary line-through",as:"h6",children:e.originalPrice})]}):(0,a.jsx)(t.Heading,{size:2,className:"text-info-tertiary",children:u?.outOfStockLabel??"Sold Out"})})}),(0,a.jsxs)("div",{className:(0,n.cn)("lg-desktop:gap-3 tablet:flex-nowrap flex flex-wrap gap-2",l?.buttonGroup),children:[y&&(0,a.jsx)(t.Button,{variant:"secondary",size:"base",className:(0,n.cn)("tablet:w-fit w-full",l?.secondaryButton),onClick:()=>C(b,"secondary"),disabled:!e.availableForSale&&b!=="learnMore",loading:L,children:y}),g&&(0,a.jsx)(t.Button,{variant:"primary",size:"base",className:(0,n.cn)("tablet:w-fit w-full",l?.primaryButton),onClick:()=>C(v,"primary"),disabled:!e.availableForSale&&v!=="learnMore",loading:B,children:g})]})]})]})]})});f.displayName="MediaShelf.ProductCard";var G=f;
|
|
2
2
|
//# sourceMappingURL=ProductCard.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/biz-components/MediaShelf/ProductCard.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { cn } from '../../helpers/index.js'\nimport { Button, Badge, Card, CardContent, Picture, Text, Heading, Progress } from '../../components/index.js'\n\nimport type {\n ButtonFunctionType,\n CopyConfig,\n ProductCardData,\n StockDisplayMode,\n MediaShelfSemanticName,\n} from './types.js'\n\n/**\n * \u8D85\u5356\u65F6\u5E93\u5B58\u6761\u663E\u793A\u7684\u6700\u5C0F\u767E\u5206\u6BD4\n * \u9632\u6B62\u8D85\u5356\u65F6\u5E93\u5B58\u6761\u663E\u793A\u4E3A\u6EE1\u683C\uFF08100%\uFF09\u6216\u5B8C\u5168\u7A7A\uFF080%\uFF09\n */\nconst OVERSELLING_STOCK_PERCENTAGE = 5\n\n/**\n * \u5224\u65AD\u662F\u5426\u5E94\u8BE5\u663E\u793A\u5E93\u5B58\u4FE1\u606F\n * @param stockDisplayMode \u5E93\u5B58\u5C55\u793A\u6A21\u5F0F\n * @param stockThresholdValue \u5E93\u5B58\u9608\u503C\uFF08\u5F53\u6A21\u5F0F\u4E3A below-quantity \u6216 below-percentage \u65F6\u4F7F\u7528\uFF09\n * @param quantityAvailable \u53EF\u7528\u5E93\u5B58\u6570\u91CF\n * @param totalInventory \u603B\u5E93\u5B58\n * @returns \u662F\u5426\u663E\u793A\u5E93\u5B58\u4FE1\u606F\n */\nfunction shouldShowStock(\n stockDisplayMode: StockDisplayMode | undefined,\n stockThresholdValue: number | undefined,\n quantityAvailable: number,\n totalInventory: number\n): boolean {\n // \u672A\u914D\u7F6E\u65F6\u9ED8\u8BA4\u663E\u793A\n if (stockDisplayMode === undefined) {\n return true\n }\n\n // \u6839\u636E\u5C55\u793A\u6A21\u5F0F\u5224\u65AD\n switch (stockDisplayMode) {\n case 'always':\n // \u603B\u662F\u663E\u793A\n return true\n\n case 'never':\n // \u6C38\u4E0D\u663E\u793A\n return false\n\n case 'below-quantity':\n // \u5F53\u5E93\u5B58\u6570\u91CF\u4F4E\u4E8E\u9608\u503C\u65F6\u663E\u793A\n if (stockThresholdValue === undefined) {\n return true // \u6CA1\u6709\u8BBE\u7F6E\u9608\u503C\u65F6\u9ED8\u8BA4\u663E\u793A\n }\n\n return quantityAvailable <= stockThresholdValue\n\n case 'below-percentage':\n // \u5F53\u5E93\u5B58\u767E\u5206\u6BD4\u4F4E\u4E8E\u9608\u503C\u65F6\u663E\u793A\n if (stockThresholdValue === undefined) {\n return true // \u6CA1\u6709\u8BBE\u7F6E\u9608\u503C\u65F6\u9ED8\u8BA4\u663E\u793A\n }\n return (quantityAvailable / totalInventory) * 100 <= stockThresholdValue\n\n default:\n // \u672A\u77E5\u6A21\u5F0F\u65F6\u9ED8\u8BA4\u663E\u793A\n return true\n }\n}\n\n/**\n * MediaShelf ProductCard \u7EC4\u4EF6 Props \u63A5\u53E3\n */\nexport interface MediaShelfProductCardProps {\n /** \u4EA7\u54C1\u6570\u636E */\n product: ProductCardData\n /** \u6837\u5F0F\u7C7B\u540D */\n className?: string\n /** \u5E93\u5B58\u5C55\u793A\u6A21\u5F0F */\n stockDisplayMode?: StockDisplayMode\n /** \u5E93\u5B58\u9608\u503C\uFF08\u5F53\u6A21\u5F0F\u4E3A below-quantity \u6216 below-percentage \u65F6\u4F7F\u7528\uFF09 */\n stockThresholdValue?: number\n /** \u70B9\u51FB\u4E86\u89E3\u66F4\u591A\u56DE\u8C03 */\n onLearnMore?: (product: ProductCardData) => void\n /** \u70B9\u51FB\u7ACB\u5373\u8D2D\u4E70\u56DE\u8C03 */\n onShopNow?: (product: ProductCardData) => void\n /** \u70B9\u51FB\u52A0\u5165\u8D2D\u7269\u8F66\u56DE\u8C03 */\n onAddToCart?: (product: ProductCardData) => void\n /** \u8BED\u4E49\u5316\u7C7B\u540D */\n classNames?: Partial<Record<MediaShelfSemanticName, string>>\n /** \u4E86\u89E3\u66F4\u591A\u6309\u94AE\u6587\u672C */\n secondaryButtonText?: string\n /** \u4E86\u89E3\u66F4\u591A\u6309\u94AE\u529F\u80FD */\n secondaryButtonFun?: ButtonFunctionType\n /** \u7ACB\u5373\u8D2D\u4E70\u6309\u94AE\u6587\u672C */\n primaryButtonText?: string\n /** \u7ACB\u5373\u8D2D\u4E70\u6309\u94AE\u529F\u80FD */\n primaryButtonFun?: ButtonFunctionType\n /** \u662F\u5426\u5C55\u793A\u539F\u4EF7\uFF08\u5220\u9664\u7EBF\u4EF7\u683C\uFF09 */\n showOriginalPrice?: boolean\n /** \u6587\u6848\u914D\u7F6E */\n copy?: CopyConfig\n /** \u70B9\u51FB\u4EA7\u54C1\u56FE\u7247\u56DE\u8C03 */\n onProductImageClick?: (product: ProductCardData) => void\n}\n\n/**\n * MediaShelf \u4EA7\u54C1\u5361\u7247\u7EC4\u4EF6\n */\nconst ProductCard = React.forwardRef<HTMLDivElement, MediaShelfProductCardProps>(\n (\n {\n product,\n className,\n stockDisplayMode,\n stockThresholdValue,\n onLearnMore,\n onShopNow,\n onAddToCart,\n classNames,\n secondaryButtonText,\n secondaryButtonFun,\n primaryButtonText,\n primaryButtonFun,\n showOriginalPrice,\n copy,\n onProductImageClick,\n },\n ref\n ) => {\n const [primaryLoading, setPrimaryLoading] = React.useState(false)\n const [secondaryLoading, setSecondaryLoading] = React.useState(false)\n\n const stockPercentage = React.useMemo(() => {\n if (product?.availableForSale && product?.quantityAvailable <= 0) {\n return OVERSELLING_STOCK_PERCENTAGE\n }\n // \u4E0D\u53EF\u552E\u65F6\u663E\u793A0%\n if (!product?.availableForSale) {\n return 0\n }\n return ((product?.quantityAvailable ?? 0) / (product?.totalInventory ?? 1)) * 100\n }, [product?.availableForSale, product?.quantityAvailable, product?.totalInventory])\n\n // \u6839\u636E\u6309\u94AE\u529F\u80FD\u7C7B\u578B\u8C03\u7528\u76F8\u5E94\u7684\u56DE\u8C03\u51FD\u6570\n const handleButtonClick = async (buttonFun?: ButtonFunctionType, buttonType?: 'primary' | 'secondary') => {\n if (!buttonFun) return\n\n const setLoading = buttonType === 'primary' ? setPrimaryLoading : setSecondaryLoading\n setLoading(true)\n\n try {\n switch (buttonFun) {\n case 'buyNow':\n await onShopNow?.(product)\n break\n case 'addCart':\n await onAddToCart?.(product)\n break\n case 'learnMore':\n await onLearnMore?.(product)\n break\n default:\n break\n }\n } finally {\n setLoading(false)\n }\n }\n\n const overselling = product.availableForSale && product.quantityAvailable <= 0\n\n return (\n <Card\n ref={ref}\n className={cn(\n 'flex h-full min-w-[296px] flex-col overflow-hidden',\n product.custom_link ? 'cursor-pointer' : '',\n className,\n classNames?.productCard\n )}\n >\n {/* \u56FE\u7247\u533A\u57DF */}\n <div\n className={cn(\n 'media-shelf-product-card-image-wrapper desktop:h-[240px] relative h-[200px] shrink-0 overflow-hidden',\n classNames?.productCardImageWrapper\n )}\n >\n {/* \u80CC\u666F\u56FE\u7247 */}\n <div className={cn('media-shelf-product-card-image-bg absolute inset-0 ', classNames?.productCardImageBg)}>\n <a\n onClick={() => onProductImageClick?.(product)}\n {...(!onProductImageClick && {\n href: product.custom_link || product.listingLink,\n })}\n className=\"cursor-pointer\"\n >\n <Picture\n source={product.custom_image || product.image}\n alt={product.name}\n className={cn('h-full', classNames?.productCardImage)}\n imgClassName=\"h-full object-contain\"\n />\n </a>\n </div>\n\n {/* \u6807\u7B7E\u533A\u57DF */}\n <div className=\"lg-desktop:h-[28px] absolute left-4 top-4 flex h-[24px]\">\n {product.tags?.map((tag: any, index) =>\n (tag as any).label ? (\n <Badge\n key={index}\n size=\"sm\"\n variant={(tag.variant as any) || 'outline'}\n className={cn('mr-1')}\n promotionalType={tag.promotionalType}\n >\n {tag.label}\n </Badge>\n ) : (\n <React.Fragment key={index}>{tag}</React.Fragment>\n )\n )}\n </div>\n </div>\n\n {/* \u5185\u5BB9\u533A\u57DF */}\n <CardContent className=\"desktop:p-6 flex h-[calc(100%-240px)] grow flex-col justify-between p-4\">\n {/* \u4EA7\u54C1\u6807\u9898\u548C\u526F\u6807\u9898 */}\n <div className=\"mb-6 flex-1\">\n <Heading\n as=\"h3\"\n size={2}\n className={cn('text-info-primary mb-1 line-clamp-2 tracking-tight', classNames?.productTitle)}\n >\n {product.custom_name || product.name}\n </Heading>\n {(product.custom_description || product?.description) && (\n <Text\n size={2}\n className={cn('text-info-primary line-clamp-1', classNames?.productDescription)}\n html={product.custom_description || product.description}\n />\n )}\n </div>\n\n {/* \u5E93\u5B58\u4FE1\u606F */}\n {shouldShowStock(\n stockDisplayMode,\n stockThresholdValue,\n product?.quantityAvailable ?? 0,\n product?.totalInventory ?? 0\n ) && (\n <div\n data-total={product?.totalInventory ?? 0}\n data-available={product?.quantityAvailable ?? 0}\n className=\"space-y-2\"\n >\n <Progress\n value={stockPercentage}\n max={100}\n min={0}\n size=\"base\"\n variant=\"default\"\n aria-label=\"stock progress\"\n classNames={{\n progressBar: 'transition-all duration-300 ease-in-out',\n }}\n />\n <Text size={3} className=\"text-info-tertiary text-[14px]\">\n {overselling\n ? copy?.limitedStock\n : copy?.stockDisplayText?.replace(\n '{count}',\n `${product.availableForSale ? product.quantityAvailable : 0}`\n )}\n </Text>\n </div>\n )}\n\n {/** \u4EF7\u683C\u6807\u7B7E */}\n <>\n {product?.priceLabel && product?.availableForSale && (\n <Text\n size={4}\n className={cn(\n 'text-marketing-1 desktop:text-[16px] lg-desktop:text-[18px] mt-2 text-[12px]',\n classNames?.productPriceLabel\n )}\n >\n {product.priceLabel}\n </Text>\n )}\n </>\n {/* \u4EF7\u683C\u533A\u57DF */}\n <div className={cn('mb-6', classNames?.productPrice)}>\n <div className=\"flex items-baseline gap-2\">\n {product.availableForSale ? (\n <>\n <Heading size={2} className=\"text-info-primary\" as=\"h6\">\n {product.price}\n </Heading>\n {showOriginalPrice && product.originalPrice && (\n <Heading size={2} className=\"text-info-tertiary line-through\" as=\"h6\">\n {product.originalPrice}\n </Heading>\n )}\n </>\n ) : (\n <Heading size={2} className=\"text-info-tertiary\">\n {copy?.outOfStockLabel ?? 'Sold Out'}\n </Heading>\n )}\n </div>\n </div>\n\n {/* \u6309\u94AE\u533A\u57DF */}\n <div className={cn('lg-desktop:gap-3 tablet:flex-nowrap flex flex-wrap gap-2', classNames?.buttonGroup)}>\n {secondaryButtonText && (\n <Button\n variant=\"secondary\"\n size=\"base\"\n className={cn('tablet:w-fit w-full', classNames?.secondaryButton)}\n onClick={() => handleButtonClick(secondaryButtonFun, 'secondary')}\n disabled={!product.availableForSale && secondaryButtonFun !== 'learnMore'}\n loading={secondaryLoading}\n >\n {secondaryButtonText}\n </Button>\n )}\n {primaryButtonText && (\n <Button\n variant=\"primary\"\n size=\"base\"\n className={cn('tablet:w-fit w-full', classNames?.primaryButton)}\n onClick={() => handleButtonClick(primaryButtonFun, 'primary')}\n disabled={!product.availableForSale && primaryButtonFun !== 'learnMore'}\n loading={primaryLoading}\n >\n {primaryButtonText}\n </Button>\n )}\n </div>\n </CardContent>\n </Card>\n )\n }\n)\n\nProductCard.displayName = 'MediaShelf.ProductCard'\n\nexport default ProductCard\nexport { ProductCard }\n"],
|
|
5
|
-
"mappings": "ukBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,iBAAAE,EAAA,YAAAC,IAAA,eAAAC,EAAAJ,
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { cn } from '../../helpers/index.js'\nimport { Button, Badge, Card, CardContent, Picture, Text, Heading, Progress } from '../../components/index.js'\n\nimport type {\n ButtonFunctionType,\n CopyConfig,\n ProductCardData,\n StockDisplayMode,\n MediaShelfSemanticName,\n} from './types.js'\nimport type { Theme } from '../../types/props.js'\n\n/**\n * \u8D85\u5356\u65F6\u5E93\u5B58\u6761\u663E\u793A\u7684\u6700\u5C0F\u767E\u5206\u6BD4\n * \u9632\u6B62\u8D85\u5356\u65F6\u5E93\u5B58\u6761\u663E\u793A\u4E3A\u6EE1\u683C\uFF08100%\uFF09\u6216\u5B8C\u5168\u7A7A\uFF080%\uFF09\n */\nconst OVERSELLING_STOCK_PERCENTAGE = 5\n\n/**\n * \u5224\u65AD\u662F\u5426\u5E94\u8BE5\u663E\u793A\u5E93\u5B58\u4FE1\u606F\n * @param stockDisplayMode \u5E93\u5B58\u5C55\u793A\u6A21\u5F0F\n * @param stockThresholdValue \u5E93\u5B58\u9608\u503C\uFF08\u5F53\u6A21\u5F0F\u4E3A below-quantity \u6216 below-percentage \u65F6\u4F7F\u7528\uFF09\n * @param quantityAvailable \u53EF\u7528\u5E93\u5B58\u6570\u91CF\n * @param totalInventory \u603B\u5E93\u5B58\n * @returns \u662F\u5426\u663E\u793A\u5E93\u5B58\u4FE1\u606F\n */\nfunction shouldShowStock(\n stockDisplayMode: StockDisplayMode | undefined,\n stockThresholdValue: number | undefined,\n quantityAvailable: number,\n totalInventory: number\n): boolean {\n // \u672A\u914D\u7F6E\u65F6\u9ED8\u8BA4\u663E\u793A\n if (stockDisplayMode === undefined) {\n return true\n }\n\n // \u6839\u636E\u5C55\u793A\u6A21\u5F0F\u5224\u65AD\n switch (stockDisplayMode) {\n case 'always':\n // \u603B\u662F\u663E\u793A\n return true\n\n case 'never':\n // \u6C38\u4E0D\u663E\u793A\n return false\n\n case 'below-quantity':\n // \u5F53\u5E93\u5B58\u6570\u91CF\u4F4E\u4E8E\u9608\u503C\u65F6\u663E\u793A\n if (stockThresholdValue === undefined) {\n return true // \u6CA1\u6709\u8BBE\u7F6E\u9608\u503C\u65F6\u9ED8\u8BA4\u663E\u793A\n }\n\n return quantityAvailable <= stockThresholdValue\n\n case 'below-percentage':\n // \u5F53\u5E93\u5B58\u767E\u5206\u6BD4\u4F4E\u4E8E\u9608\u503C\u65F6\u663E\u793A\n if (stockThresholdValue === undefined) {\n return true // \u6CA1\u6709\u8BBE\u7F6E\u9608\u503C\u65F6\u9ED8\u8BA4\u663E\u793A\n }\n return (quantityAvailable / totalInventory) * 100 <= stockThresholdValue\n\n default:\n // \u672A\u77E5\u6A21\u5F0F\u65F6\u9ED8\u8BA4\u663E\u793A\n return true\n }\n}\n\n/**\n * MediaShelf ProductCard \u7EC4\u4EF6 Props \u63A5\u53E3\n */\nexport interface MediaShelfProductCardProps {\n /** \u4EA7\u54C1\u6570\u636E */\n product: ProductCardData\n /** \u6837\u5F0F\u7C7B\u540D */\n className?: string\n /** \u5E93\u5B58\u5C55\u793A\u6A21\u5F0F */\n stockDisplayMode?: StockDisplayMode\n /** \u5E93\u5B58\u9608\u503C\uFF08\u5F53\u6A21\u5F0F\u4E3A below-quantity \u6216 below-percentage \u65F6\u4F7F\u7528\uFF09 */\n stockThresholdValue?: number\n /** \u70B9\u51FB\u4E86\u89E3\u66F4\u591A\u56DE\u8C03 */\n onLearnMore?: (product: ProductCardData) => void\n /** \u70B9\u51FB\u7ACB\u5373\u8D2D\u4E70\u56DE\u8C03 */\n onShopNow?: (product: ProductCardData) => void\n /** \u70B9\u51FB\u52A0\u5165\u8D2D\u7269\u8F66\u56DE\u8C03 */\n onAddToCart?: (product: ProductCardData) => void\n /** \u8BED\u4E49\u5316\u7C7B\u540D */\n classNames?: Partial<Record<MediaShelfSemanticName, string>>\n /** \u4E86\u89E3\u66F4\u591A\u6309\u94AE\u6587\u672C */\n secondaryButtonText?: string\n /** \u4E86\u89E3\u66F4\u591A\u6309\u94AE\u529F\u80FD */\n secondaryButtonFun?: ButtonFunctionType\n /** \u7ACB\u5373\u8D2D\u4E70\u6309\u94AE\u6587\u672C */\n primaryButtonText?: string\n /** \u7ACB\u5373\u8D2D\u4E70\u6309\u94AE\u529F\u80FD */\n primaryButtonFun?: ButtonFunctionType\n /** \u662F\u5426\u5C55\u793A\u539F\u4EF7\uFF08\u5220\u9664\u7EBF\u4EF7\u683C\uFF09 */\n showOriginalPrice?: boolean\n /** \u6587\u6848\u914D\u7F6E */\n copy?: CopyConfig\n /** \u70B9\u51FB\u4EA7\u54C1\u56FE\u7247\u56DE\u8C03 */\n onProductImageClick?: (product: ProductCardData) => void\n}\n\n/**\n * MediaShelf \u4EA7\u54C1\u5361\u7247\u7EC4\u4EF6\n */\nconst ProductCard = React.forwardRef<HTMLDivElement, MediaShelfProductCardProps>(\n (\n {\n product,\n className,\n stockDisplayMode,\n stockThresholdValue,\n onLearnMore,\n onShopNow,\n onAddToCart,\n classNames,\n secondaryButtonText,\n secondaryButtonFun,\n primaryButtonText,\n primaryButtonFun,\n showOriginalPrice,\n copy,\n onProductImageClick,\n },\n ref\n ) => {\n const [primaryLoading, setPrimaryLoading] = React.useState(false)\n const [secondaryLoading, setSecondaryLoading] = React.useState(false)\n\n const stockPercentage = React.useMemo(() => {\n if (product?.availableForSale && product?.quantityAvailable <= 0) {\n return OVERSELLING_STOCK_PERCENTAGE\n }\n // \u4E0D\u53EF\u552E\u65F6\u663E\u793A0%\n if (!product?.availableForSale) {\n return 0\n }\n return ((product?.quantityAvailable ?? 0) / (product?.totalInventory ?? 1)) * 100\n }, [product?.availableForSale, product?.quantityAvailable, product?.totalInventory])\n\n // \u6839\u636E\u6309\u94AE\u529F\u80FD\u7C7B\u578B\u8C03\u7528\u76F8\u5E94\u7684\u56DE\u8C03\u51FD\u6570\n const handleButtonClick = async (buttonFun?: ButtonFunctionType, buttonType?: 'primary' | 'secondary') => {\n if (!buttonFun) return\n\n const setLoading = buttonType === 'primary' ? setPrimaryLoading : setSecondaryLoading\n setLoading(true)\n\n try {\n switch (buttonFun) {\n case 'buyNow':\n await onShopNow?.(product)\n break\n case 'addCart':\n await onAddToCart?.(product)\n break\n case 'learnMore':\n await onLearnMore?.(product)\n break\n default:\n break\n }\n } finally {\n setLoading(false)\n }\n }\n\n const overselling = product.availableForSale && product.quantityAvailable <= 0\n\n return (\n <Card\n ref={ref}\n className={cn(\n 'tablet:min-w-[auto] hover:bg-container-secondary-0 flex h-full min-w-[296px] flex-col overflow-hidden border-none',\n product.custom_link ? 'cursor-pointer' : '',\n className,\n classNames?.productCard\n )}\n >\n {/* \u56FE\u7247\u533A\u57DF */}\n <div\n className={cn(\n 'media-shelf-product-card-image-wrapper desktop:h-[240px] relative h-[200px] shrink-0 overflow-hidden',\n classNames?.productCardImageWrapper\n )}\n >\n {/* \u80CC\u666F\u56FE\u7247 */}\n <div className={cn('media-shelf-product-card-image-bg absolute inset-0 ', classNames?.productCardImageBg)}>\n <a\n onClick={() => onProductImageClick?.(product)}\n {...(!onProductImageClick && {\n href: product.custom_link || product.listingLink,\n })}\n className=\"cursor-pointer\"\n >\n <Picture\n source={product.custom_image || product.image}\n alt={product.name}\n className={cn('h-full', classNames?.productCardImage)}\n imgClassName=\"h-full object-contain\"\n />\n </a>\n </div>\n\n {/* \u6807\u7B7E\u533A\u57DF */}\n <div className=\"lg-desktop:h-[28px] absolute left-4 top-4 flex h-[24px]\">\n {product.tags?.map((tag: any, index) =>\n (tag as any).label ? (\n <Badge\n key={index}\n size=\"sm\"\n variant={(tag.variant as any) || 'outline'}\n className={cn('mr-1')}\n promotionalType={tag.promotionalType}\n >\n {tag.label}\n </Badge>\n ) : (\n <React.Fragment key={index}>{tag}</React.Fragment>\n )\n )}\n </div>\n </div>\n\n {/* \u5185\u5BB9\u533A\u57DF */}\n <CardContent className=\"desktop:p-6 bg-container-primary laptop:gap-6 flex h-[calc(100%-240px)] grow flex-col justify-between gap-4 p-4\">\n {/* \u4EA7\u54C1\u6807\u9898\u548C\u526F\u6807\u9898 */}\n <div className=\"flex-0\">\n <Heading\n as=\"h3\"\n size={2}\n className={cn('text-info-primary mb-1 line-clamp-2 tracking-tight', classNames?.productTitle)}\n >\n {product.custom_name || product.name}\n </Heading>\n {(product.custom_description || product?.description) && (\n <Text\n size={2}\n className={cn('text-info-primary line-clamp-1', classNames?.productDescription)}\n html={product.custom_description || product.description}\n />\n )}\n </div>\n\n {/* \u5E93\u5B58\u4FE1\u606F */}\n {shouldShowStock(\n stockDisplayMode,\n stockThresholdValue,\n product?.quantityAvailable ?? 0,\n product?.totalInventory ?? 0\n ) && (\n <div\n data-total={product?.totalInventory ?? 0}\n data-available={product?.quantityAvailable ?? 0}\n className=\"space-y-2\"\n >\n <Progress\n value={stockPercentage}\n max={100}\n min={0}\n size=\"base\"\n variant=\"default\"\n aria-label=\"stock progress\"\n classNames={{\n progressBar: 'transition-all duration-300 ease-in-out',\n }}\n />\n <Text size={3} className=\"text-info-tertiary desktop:text-[16px] lg-desktop:text-[18px] text-[12px]\">\n {overselling\n ? copy?.limitedStock\n : copy?.stockDisplayText?.replace(\n '{count}',\n `${product.availableForSale ? product.quantityAvailable : 0}`\n )}\n </Text>\n </div>\n )}\n\n <div>\n {/** \u4EF7\u683C\u6807\u7B7E */}\n {product?.priceLabel && product?.availableForSale && (\n <Text\n size={4}\n className={cn(\n 'text-marketing-1 desktop:text-[16px] lg-desktop:text-[18px] mt-2 text-[12px]',\n classNames?.productPriceLabel\n )}\n >\n {product.priceLabel}\n </Text>\n )}\n {/* \u4EF7\u683C\u533A\u57DF */}\n <div className={cn('mb-2', classNames?.productPrice)}>\n <div className=\"flex items-baseline gap-2\">\n {product.availableForSale ? (\n <>\n <Heading size={2} className=\"text-info-primary\" as=\"h6\">\n {product.price}\n </Heading>\n {showOriginalPrice && product.originalPrice && (\n <Heading size={2} className=\"text-info-tertiary line-through\" as=\"h6\">\n {product.originalPrice}\n </Heading>\n )}\n </>\n ) : (\n <Heading size={2} className=\"text-info-tertiary\">\n {copy?.outOfStockLabel ?? 'Sold Out'}\n </Heading>\n )}\n </div>\n </div>\n\n {/* \u6309\u94AE\u533A\u57DF */}\n <div className={cn('lg-desktop:gap-3 tablet:flex-nowrap flex flex-wrap gap-2', classNames?.buttonGroup)}>\n {secondaryButtonText && (\n <Button\n variant=\"secondary\"\n size=\"base\"\n className={cn('tablet:w-fit w-full', classNames?.secondaryButton)}\n onClick={() => handleButtonClick(secondaryButtonFun, 'secondary')}\n disabled={!product.availableForSale && secondaryButtonFun !== 'learnMore'}\n loading={secondaryLoading}\n >\n {secondaryButtonText}\n </Button>\n )}\n {primaryButtonText && (\n <Button\n variant=\"primary\"\n size=\"base\"\n className={cn('tablet:w-fit w-full', classNames?.primaryButton)}\n onClick={() => handleButtonClick(primaryButtonFun, 'primary')}\n disabled={!product.availableForSale && primaryButtonFun !== 'learnMore'}\n loading={primaryLoading}\n >\n {primaryButtonText}\n </Button>\n )}\n </div>\n </div>\n </CardContent>\n </Card>\n )\n }\n)\n\nProductCard.displayName = 'MediaShelf.ProductCard'\n\nexport default ProductCard\nexport { ProductCard }\n"],
|
|
5
|
+
"mappings": "ukBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,iBAAAE,EAAA,YAAAC,IAAA,eAAAC,EAAAJ,GAwLQ,IAAAK,EAAA,6BAtLRC,EAAuB,oBACvBC,EAAmB,kCACnBC,EAAmF,qCAenF,MAAMC,EAA+B,EAUrC,SAASC,EACPC,EACAC,EACAC,EACAC,EACS,CAET,GAAIH,IAAqB,OACvB,MAAO,GAIT,OAAQA,EAAkB,CACxB,IAAK,SAEH,MAAO,GAET,IAAK,QAEH,MAAO,GAET,IAAK,iBAEH,OAAIC,IAAwB,OACnB,GAGFC,GAAqBD,EAE9B,IAAK,mBAEH,OAAIA,IAAwB,OACnB,GAEDC,EAAoBC,EAAkB,KAAOF,EAEvD,QAEE,MAAO,EACX,CACF,CAyCA,MAAMV,EAAcI,EAAM,WACxB,CACE,CACE,QAAAS,EACA,UAAAC,EACA,iBAAAL,EACA,oBAAAC,EACA,YAAAK,EACA,UAAAC,EACA,YAAAC,EACA,WAAAC,EACA,oBAAAC,EACA,mBAAAC,EACA,kBAAAC,EACA,iBAAAC,EACA,kBAAAC,EACA,KAAAC,EACA,oBAAAC,CACF,EACAC,IACG,CACH,KAAM,CAACC,EAAgBC,CAAiB,EAAIxB,EAAM,SAAS,EAAK,EAC1D,CAACyB,EAAkBC,CAAmB,EAAI1B,EAAM,SAAS,EAAK,EAE9D2B,EAAkB3B,EAAM,QAAQ,IAChCS,GAAS,kBAAoBA,GAAS,mBAAqB,EACtDN,EAGJM,GAAS,kBAGLA,GAAS,mBAAqB,IAAMA,GAAS,gBAAkB,GAAM,IAFrE,EAGR,CAACA,GAAS,iBAAkBA,GAAS,kBAAmBA,GAAS,cAAc,CAAC,EAG7EmB,EAAoB,MAAOC,EAAgCC,IAAyC,CACxG,GAAI,CAACD,EAAW,OAEhB,MAAME,EAAaD,IAAe,UAAYN,EAAoBE,EAClEK,EAAW,EAAI,EAEf,GAAI,CACF,OAAQF,EAAW,CACjB,IAAK,SACH,MAAMjB,IAAYH,CAAO,EACzB,MACF,IAAK,UACH,MAAMI,IAAcJ,CAAO,EAC3B,MACF,IAAK,YACH,MAAME,IAAcF,CAAO,EAC3B,MACF,QACE,KACJ,CACF,QAAE,CACAsB,EAAW,EAAK,CAClB,CACF,EAEMC,EAAcvB,EAAQ,kBAAoBA,EAAQ,mBAAqB,EAE7E,SACE,QAAC,QACC,IAAKa,EACL,aAAW,MACT,oHACAb,EAAQ,YAAc,iBAAmB,GACzCC,EACAI,GAAY,WACd,EAGA,qBAAC,OACC,aAAW,MACT,uGACAA,GAAY,uBACd,EAGA,oBAAC,OAAI,aAAW,MAAG,sDAAuDA,GAAY,kBAAkB,EACtG,mBAAC,KACC,QAAS,IAAMO,IAAsBZ,CAAO,EAC3C,GAAI,CAACY,GAAuB,CAC3B,KAAMZ,EAAQ,aAAeA,EAAQ,WACvC,EACA,UAAU,iBAEV,mBAAC,WACC,OAAQA,EAAQ,cAAgBA,EAAQ,MACxC,IAAKA,EAAQ,KACb,aAAW,MAAG,SAAUK,GAAY,gBAAgB,EACpD,aAAa,wBACf,EACF,EACF,KAGA,OAAC,OAAI,UAAU,0DACZ,SAAAL,EAAQ,MAAM,IAAI,CAACwB,EAAUC,IAC3BD,EAAY,SACX,OAAC,SAEC,KAAK,KACL,QAAUA,EAAI,SAAmB,UACjC,aAAW,MAAG,MAAM,EACpB,gBAAiBA,EAAI,gBAEpB,SAAAA,EAAI,OANAC,CAOP,KAEA,OAAClC,EAAM,SAAN,CAA4B,SAAAiC,GAARC,CAAY,CAErC,EACF,GACF,KAGA,QAAC,eAAY,UAAU,kHAErB,qBAAC,OAAI,UAAU,SACb,oBAAC,WACC,GAAG,KACH,KAAM,EACN,aAAW,MAAG,qDAAsDpB,GAAY,YAAY,EAE3F,SAAAL,EAAQ,aAAeA,EAAQ,KAClC,GACEA,EAAQ,oBAAsBA,GAAS,iBACvC,OAAC,QACC,KAAM,EACN,aAAW,MAAG,iCAAkCK,GAAY,kBAAkB,EAC9E,KAAML,EAAQ,oBAAsBA,EAAQ,YAC9C,GAEJ,EAGCL,EACCC,EACAC,EACAG,GAAS,mBAAqB,EAC9BA,GAAS,gBAAkB,CAC7B,MACE,QAAC,OACC,aAAYA,GAAS,gBAAkB,EACvC,iBAAgBA,GAAS,mBAAqB,EAC9C,UAAU,YAEV,oBAAC,YACC,MAAOkB,EACP,IAAK,IACL,IAAK,EACL,KAAK,OACL,QAAQ,UACR,aAAW,iBACX,WAAY,CACV,YAAa,yCACf,EACF,KACA,OAAC,QAAK,KAAM,EAAG,UAAU,4EACtB,SAAAK,EACGZ,GAAM,aACNA,GAAM,kBAAkB,QACtB,UACA,GAAGX,EAAQ,iBAAmBA,EAAQ,kBAAoB,CAAC,EAC7D,EACN,GACF,KAGF,QAAC,OAEE,UAAAA,GAAS,YAAcA,GAAS,qBAC/B,OAAC,QACC,KAAM,EACN,aAAW,MACT,+EACAK,GAAY,iBACd,EAEC,SAAAL,EAAQ,WACX,KAGF,OAAC,OAAI,aAAW,MAAG,OAAQK,GAAY,YAAY,EACjD,mBAAC,OAAI,UAAU,4BACZ,SAAAL,EAAQ,oBACP,oBACE,oBAAC,WAAQ,KAAM,EAAG,UAAU,oBAAoB,GAAG,KAChD,SAAAA,EAAQ,MACX,EACCU,GAAqBV,EAAQ,kBAC5B,OAAC,WAAQ,KAAM,EAAG,UAAU,kCAAkC,GAAG,KAC9D,SAAAA,EAAQ,cACX,GAEJ,KAEA,OAAC,WAAQ,KAAM,EAAG,UAAU,qBACzB,SAAAW,GAAM,iBAAmB,WAC5B,EAEJ,EACF,KAGA,QAAC,OAAI,aAAW,MAAG,2DAA4DN,GAAY,WAAW,EACnG,UAAAC,MACC,OAAC,UACC,QAAQ,YACR,KAAK,OACL,aAAW,MAAG,sBAAuBD,GAAY,eAAe,EAChE,QAAS,IAAMc,EAAkBZ,EAAoB,WAAW,EAChE,SAAU,CAACP,EAAQ,kBAAoBO,IAAuB,YAC9D,QAASS,EAER,SAAAV,EACH,EAEDE,MACC,OAAC,UACC,QAAQ,UACR,KAAK,OACL,aAAW,MAAG,sBAAuBH,GAAY,aAAa,EAC9D,QAAS,IAAMc,EAAkBV,EAAkB,SAAS,EAC5D,SAAU,CAACT,EAAQ,kBAAoBS,IAAqB,YAC5D,QAASK,EAER,SAAAN,EACH,GAEJ,GACF,GACF,GACF,CAEJ,CACF,EAEArB,EAAY,YAAc,yBAE1B,IAAOC,EAAQD",
|
|
6
6
|
"names": ["ProductCard_exports", "__export", "ProductCard", "ProductCard_default", "__toCommonJS", "import_jsx_runtime", "React", "import_helpers", "import_components", "OVERSELLING_STOCK_PERCENTAGE", "shouldShowStock", "stockDisplayMode", "stockThresholdValue", "quantityAvailable", "totalInventory", "product", "className", "onLearnMore", "onShopNow", "onAddToCart", "classNames", "secondaryButtonText", "secondaryButtonFun", "primaryButtonText", "primaryButtonFun", "showOriginalPrice", "copy", "onProductImageClick", "ref", "primaryLoading", "setPrimaryLoading", "secondaryLoading", "setSecondaryLoading", "stockPercentage", "handleButtonClick", "buttonFun", "buttonType", "setLoading", "overselling", "tag", "index"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Img } from '../../types/props.js';
|
|
2
|
+
export interface CircleProgressProps {
|
|
3
|
+
/** 总阶段数 (1-4) */
|
|
4
|
+
totalSteps?: 1 | 2 | 3 | 4;
|
|
5
|
+
/** 当前完成的阶段 (0 到 totalSteps) */
|
|
6
|
+
currentStep?: number;
|
|
7
|
+
/** 中间显示的图片 */
|
|
8
|
+
image?: Img;
|
|
9
|
+
/** 底部显示的文案 */
|
|
10
|
+
label?: string;
|
|
11
|
+
/** 进度条颜色,默认为品牌色 */
|
|
12
|
+
progressColor?: string;
|
|
13
|
+
/** 底部文案背景色,默认为品牌营销色 */
|
|
14
|
+
labelColor?: string;
|
|
15
|
+
/** 未完成阶段的颜色 */
|
|
16
|
+
trackColor?: string;
|
|
17
|
+
/** 背景颜色,默认为容器背景色 */
|
|
18
|
+
backgroundColor?: string;
|
|
19
|
+
/** 移动端组件尺寸,默认 64 */
|
|
20
|
+
size?: number;
|
|
21
|
+
/** laptop 以上组件尺寸,默认 80 */
|
|
22
|
+
laptopSize?: number;
|
|
23
|
+
/** 段之间的间隙(像素),默认 3 */
|
|
24
|
+
gap?: number;
|
|
25
|
+
/** 自定义类名 */
|
|
26
|
+
className?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* 分段式圆形进度条组件
|
|
30
|
+
* 用于 MiniCart 左侧显示阶段性进度,支持 1-4 个阶段配置
|
|
31
|
+
* 每个阶段是独立的弧段,中间有间隙
|
|
32
|
+
* 移动端默认 64px,laptop 以上默认 80px
|
|
33
|
+
*/
|
|
34
|
+
declare const CircleProgress: {
|
|
35
|
+
({ totalSteps, currentStep, image, label, progressColor, labelColor, trackColor, backgroundColor, size, laptopSize, gap, className, }: CircleProgressProps): import("react/jsx-runtime").JSX.Element;
|
|
36
|
+
displayName: string;
|
|
37
|
+
};
|
|
38
|
+
export default CircleProgress;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";"use client";var Y=Object.create;var x=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var F=Object.getOwnPropertyNames;var L=Object.getPrototypeOf,T=Object.prototype.hasOwnProperty;var q=(e,t)=>{for(var s in t)x(e,s,{get:t[s],enumerable:!0})},P=(e,t,s,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of F(t))!T.call(e,a)&&a!==s&&x(e,a,{get:()=>t[a],enumerable:!(o=B(t,a))||o.enumerable});return e};var H=(e,t,s)=>(s=e!=null?Y(L(e)):{},P(t||!e||!e.__esModule?x(s,"default",{value:e,enumerable:!0}):s,e)),J=e=>P(x({},"__esModule",{value:!0}),e);var U={};q(U,{default:()=>Q});module.exports=J(U);var r=require("react/jsx-runtime"),K=H(require("react")),y=require("../../components/index.js"),v=require("../../helpers/index.js");const M=({totalSteps:e=4,currentStep:t=0,image:s,label:o,progressColor:a="var(--brand-color-0)",labelColor:z="var(--marketing-color-1)",trackColor:j="#DADCE0",backgroundColor:A="#EAEAEC",size:m=64,laptopSize:u=96,gap:$=3,className:w})=>{const d=Math.max(m,u),C=6,l=(d-C)/2,c=d/2,E=K.useMemo(()=>{const b=($+C)/l*(180/Math.PI),G=(360-b*e)/e,f=n=>n*Math.PI/180,I=(n,i)=>{const p=n-90,h=i-90,R=c+l*Math.cos(f(p)),D=c+l*Math.sin(f(p)),O=c+l*Math.cos(f(h)),W=c+l*Math.sin(f(h)),X=i-n>180?1:0;return`M ${R} ${D} A ${l} ${l} 0 ${X} 1 ${O} ${W}`},k=[];let N=e===2?-45:0;for(let n=0;n<e;n++){const i=N+b/2,p=i+G,h=n<t;k.push({path:I(i,p),isCompleted:h,index:n}),N=p+b/2}return k},[e,t,$,l,c]);return(0,r.jsxs)("div",{className:(0,v.cn)("relative inline-flex shrink-0 flex-col items-center","laptop:w-[--circle-laptop-size] w-[--circle-size]","laptop:h-[--circle-laptop-height] h-[--circle-height]",w),style:{"--circle-size":`${m}px`,"--circle-laptop-size":`${u}px`,"--circle-height":`${o?m+8:m}px`,"--circle-laptop-height":`${o?u+8:u}px`},children:[(0,r.jsxs)("div",{className:"laptop:size-[--circle-laptop-size] relative size-[--circle-size]",children:[(0,r.jsxs)("svg",{viewBox:`0 0 ${d} ${d}`,className:(0,v.cn)("absolute inset-0 size-full",o?"translate-y-[-8px]":""),children:[(0,r.jsx)("circle",{cx:c,cy:c,r:l,fill:A,stroke:"none"}),E.map(g=>(0,r.jsx)("path",{d:g.path,fill:"none",stroke:g.isCompleted?a:j,strokeWidth:C,strokeLinecap:"round",style:{transition:"stroke 0.3s ease-in-out"}},g.index))]}),(0,r.jsx)("div",{className:(0,v.cn)("absolute inset-[10px] flex items-center justify-center",o?"translate-y-[-8px]":""),children:(0,r.jsx)("div",{className:"flex size-full items-center justify-center overflow-hidden rounded-full",style:{backgroundColor:A},children:s?.url&&(0,r.jsx)(y.Picture,{className:"size-full",imgClassName:"object-contain",source:s.url,alt:s.alt||""})})})]}),o&&(0,r.jsx)("div",{className:"absolute bottom-0 left-1/2 flex -translate-x-1/2 items-center justify-center rounded-full px-2 py-0.5",style:{backgroundColor:z},children:(0,r.jsx)(y.Text,{className:"text-xs font-medium text-white",html:o})})]})};M.displayName="CircleProgress";var Q=M;
|
|
2
|
+
//# sourceMappingURL=CircleProgress.js.map
|
|
@@ -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": "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",
|
|
6
|
+
"names": ["CircleProgress_exports", "__export", "CircleProgress_default", "__toCommonJS", "import_jsx_runtime", "React", "import_components", "import_helpers", "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"]
|
|
7
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";"use client";var h=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var I=Object.prototype.hasOwnProperty;var N=(a,e)=>{for(var l in e)h(a,l,{get:e[l],enumerable:!0})},z=(a,e,l,p)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of D(e))!I.call(a,o)&&o!==l&&h(a,o,{get:()=>e[o],enumerable:!(p=w(e,o))||p.enumerable});return a};var P=a=>z(h({},"__esModule",{value:!0}),a);var L={};N(L,{MiniCartDialog:()=>f,default:()=>M});module.exports=P(L);var t=require("react/jsx-runtime"),i=require("../../helpers/index.js"),n=require("../../components/index.js");const T=({className:a})=>(0,t.jsx)("svg",{className:a,width:"12",height:"12",viewBox:"0 0 12 12",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:(0,t.jsx)("path",{d:"M2 6H10",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})}),k=({className:a})=>(0,t.jsx)("svg",{className:a,width:"12",height:"12",viewBox:"0 0 12 12",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:(0,t.jsx)("path",{d:"M6 2V10M2 6H10",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})}),q=({item:a,classNames:e,onIncrease:l,onDecrease:p})=>{const{merchandise:o,quantity:u,cost:y}=a,{image:c,title:b}=o,{totalAmount:d,subtotalAmount:m}=y,x=b||o.sku||"Product",g=d?.formattedPrice||"",v=m&&d&&parseFloat(m.amount)>parseFloat(d.amount);return(0,t.jsxs)("div",{className:(0,i.cn)("bg-container-primary rounded-box flex items-center gap-2 px-2 py-4","laptop:bg-container-primary laptop:gap-4 laptop:p-4",e?.item),children:[(0,t.jsx)("div",{className:(0,i.cn)("rounded-box relative size-16 shrink-0 overflow-hidden","laptop:size-20",e?.itemImage),children:c?.url&&(0,t.jsx)("img",{src:c.url,alt:c.altText||x,className:"size-full object-cover"})}),(0,t.jsxs)("div",{className:(0,i.cn)("laptop:gap-4 flex flex-1 flex-col gap-2",e?.itemInfo),children:[(0,t.jsx)(n.Text,{as:"p",size:3,className:(0,i.cn)("text-info-primary laptop:text-[16px] line-clamp-2 text-[14px]",e?.itemTitle),children:x}),(0,t.jsxs)("div",{className:"laptop:flex-row laptop:items-center laptop:justify-between flex flex-col items-start gap-1",children:[(0,t.jsxs)("div",{className:(0,i.cn)("flex items-center gap-1",e?.itemPrice),children:[g&&(0,t.jsx)(n.Text,{size:4,className:(0,i.cn)("text-info-primary laptop:text-[18px] text-[16px]",e?.itemCurrentPrice),children:g}),v&&m?.formattedPrice&&(0,t.jsx)(n.Text,{size:4,className:(0,i.cn)("text-info-tertiary laptop:text-[18px] text-[16px] line-through",e?.itemOriginalPrice),children:m.formattedPrice})]}),(0,t.jsxs)("div",{className:(0,i.cn)("flex items-center",e?.quantityControl),children:[(0,t.jsx)("button",{type:"button",onClick:p,disabled:u<=0,className:(0,i.cn)("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",e?.quantityButton),"aria-label":"Decrease quantity",children:(0,t.jsx)(T,{className:"laptop:size-3 size-[10.67px]"})}),(0,t.jsx)("div",{className:(0,i.cn)("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",e?.quantityValue),children:u}),(0,t.jsx)("button",{type:"button",onClick:l,className:(0,i.cn)("border-lines flex size-8 items-center justify-center border","laptop:size-10","text-info-primary hover:bg-container-secondary-0 transition-colors",e?.quantityButton),"aria-label":"Increase quantity",children:(0,t.jsx)(k,{className:"laptop:size-3 size-[10.67px]"})})]})]})]})]})},f=({open:a,onOpenChange:e,cart:l,copy:p,classNames:o={},onIncreaseQuantity:u,onDecreaseQuantity:y,onQuantityChange:c})=>{const b=p?.title||"Selected ({count})",d=p?.emptyText||"Your cart is empty",m=l?.lineItems?.reduce((r,s)=>r+(s?.quantity||0),0)||0,x=l?.lineItems||[],g=x.length===0,v=(r,s)=>{u?.(r,s),c?.(r,s+1)},C=(r,s)=>{s>
|
|
1
|
+
"use strict";"use client";var h=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var I=Object.prototype.hasOwnProperty;var N=(a,e)=>{for(var l in e)h(a,l,{get:e[l],enumerable:!0})},z=(a,e,l,p)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of D(e))!I.call(a,o)&&o!==l&&h(a,o,{get:()=>e[o],enumerable:!(p=w(e,o))||p.enumerable});return a};var P=a=>z(h({},"__esModule",{value:!0}),a);var L={};N(L,{MiniCartDialog:()=>f,default:()=>M});module.exports=P(L);var t=require("react/jsx-runtime"),i=require("../../helpers/index.js"),n=require("../../components/index.js");const T=({className:a})=>(0,t.jsx)("svg",{className:a,width:"12",height:"12",viewBox:"0 0 12 12",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:(0,t.jsx)("path",{d:"M2 6H10",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})}),k=({className:a})=>(0,t.jsx)("svg",{className:a,width:"12",height:"12",viewBox:"0 0 12 12",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:(0,t.jsx)("path",{d:"M6 2V10M2 6H10",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})}),q=({item:a,classNames:e,onIncrease:l,onDecrease:p})=>{const{merchandise:o,quantity:u,cost:y}=a,{image:c,title:b}=o,{totalAmount:d,subtotalAmount:m}=y,x=b||o.sku||"Product",g=d?.formattedPrice||"",v=m&&d&&parseFloat(m.amount)>parseFloat(d.amount);return(0,t.jsxs)("div",{className:(0,i.cn)("bg-container-primary rounded-box flex items-center gap-2 px-2 py-4","laptop:bg-container-primary laptop:gap-4 laptop:p-4",e?.item),children:[(0,t.jsx)("div",{className:(0,i.cn)("rounded-box relative size-16 shrink-0 overflow-hidden","laptop:size-20",e?.itemImage),children:c?.url&&(0,t.jsx)("img",{src:c.url,alt:c.altText||x,className:"size-full object-cover"})}),(0,t.jsxs)("div",{className:(0,i.cn)("laptop:gap-4 flex flex-1 flex-col gap-2",e?.itemInfo),children:[(0,t.jsx)(n.Text,{as:"p",size:3,className:(0,i.cn)("text-info-primary laptop:text-[16px] line-clamp-2 text-[14px]",e?.itemTitle),children:x}),(0,t.jsxs)("div",{className:"laptop:flex-row laptop:items-center laptop:justify-between flex flex-col items-start gap-1",children:[(0,t.jsxs)("div",{className:(0,i.cn)("flex items-center gap-1",e?.itemPrice),children:[g&&(0,t.jsx)(n.Text,{size:4,className:(0,i.cn)("text-info-primary laptop:text-[18px] text-[16px]",e?.itemCurrentPrice),children:g}),v&&m?.formattedPrice&&(0,t.jsx)(n.Text,{size:4,className:(0,i.cn)("text-info-tertiary laptop:text-[18px] text-[16px] line-through",e?.itemOriginalPrice),children:m.formattedPrice})]}),(0,t.jsxs)("div",{className:(0,i.cn)("flex items-center",e?.quantityControl),children:[(0,t.jsx)("button",{type:"button",onClick:p,disabled:u<=0,className:(0,i.cn)("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",e?.quantityButton),"aria-label":"Decrease quantity",children:(0,t.jsx)(T,{className:"laptop:size-3 size-[10.67px]"})}),(0,t.jsx)("div",{className:(0,i.cn)("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",e?.quantityValue),children:u}),(0,t.jsx)("button",{type:"button",onClick:l,className:(0,i.cn)("border-lines flex size-8 items-center justify-center border","laptop:size-10","text-info-primary hover:bg-container-secondary-0 transition-colors",e?.quantityButton),"aria-label":"Increase quantity",children:(0,t.jsx)(k,{className:"laptop:size-3 size-[10.67px]"})})]})]})]})]})},f=({open:a,onOpenChange:e,cart:l,copy:p,classNames:o={},onIncreaseQuantity:u,onDecreaseQuantity:y,onQuantityChange:c})=>{const b=p?.title||"Selected ({count})",d=p?.emptyText||"Your cart is empty",m=l?.lineItems?.reduce((r,s)=>r+(s?.quantity||0),0)||0,x=l?.lineItems||[],g=x.length===0,v=(r,s)=>{u?.(r,s),c?.(r,s+1)},C=(r,s)=>{s>0&&(y?.(r,s),c?.(r,s-1))};return(0,t.jsx)(n.Dialog,{open:a,onOpenChange:e,children:(0,t.jsxs)(n.DialogContent,{className:(0,i.cn)("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:[(0,t.jsx)(n.DialogHeader,{className:(0,i.cn)("bg-container-secondary-0 flex flex-row items-start justify-between gap-4 px-4 pb-2 pt-4",o?.header),children:(0,t.jsx)(n.DialogTitle,{asChild:!0,children:(0,t.jsx)(n.Heading,{as:"h3",size:2,className:(0,i.cn)("text-info-primary font-bold",o?.title),children:b.replace("{count}",m.toString())})})}),(0,t.jsx)("div",{className:(0,i.cn)("bg-container-secondary-0 h- flex flex-col gap-2 overflow-y-auto px-4 py-2",o?.content),children:g?(0,t.jsx)("div",{className:"flex items-center justify-center py-8",children:(0,t.jsx)(n.Text,{size:2,className:"text-info-tertiary",children:d})}):(0,t.jsx)("div",{className:(0,i.cn)("flex flex-col gap-2",o?.itemList),children:x.map(r=>(0,t.jsx)(q,{item:r,classNames:o,onIncrease:()=>v(r.id,r.quantity),onDecrease:()=>C(r.id,r.quantity)},r.id))})}),(0,t.jsx)("div",{className:"bg-container-secondary-0 h-8 w-full"})]})})};f.displayName="MiniCartDialog";var M=f;
|
|
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": "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",
|
|
6
6
|
"names": ["MiniCartDialog_exports", "__export", "MiniCartDialog", "MiniCartDialog_default", "__toCommonJS", "import_jsx_runtime", "import_helpers", "import_components", "MinusIcon", "className", "PlusIcon", "CartItem", "item", "classNames", "onIncrease", "onDecrease", "merchandise", "quantity", "cost", "image", "title", "totalAmount", "subtotalAmount", "displayTitle", "displayPrice", "hasDiscount", "open", "onOpenChange", "cart", "copy", "onIncreaseQuantity", "onDecreaseQuantity", "onQuantityChange", "titleText", "emptyText", "totalQuantity", "total", "items", "isEmpty", "handleIncrease", "lineItemId", "currentQuantity", "handleDecrease"]
|
|
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
|