@anker-in/headless-ui 1.2.1 → 1.2.2
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/MediaSceneSwitcherV2/index.js +1 -1
- package/dist/cjs/biz-components/MediaSceneSwitcherV2/index.js.map +3 -3
- package/dist/esm/biz-components/MediaSceneSwitcherV2/index.js +1 -1
- package/dist/esm/biz-components/MediaSceneSwitcherV2/index.js.map +3 -3
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";"use client";var
|
|
1
|
+
"use strict";"use client";var Y=Object.create;var k=Object.defineProperty;var _=Object.getOwnPropertyDescriptor;var q=Object.getOwnPropertyNames;var Q=Object.getPrototypeOf,G=Object.prototype.hasOwnProperty;var J=(a,i)=>{for(var n in i)k(a,n,{get:i[n],enumerable:!0})},H=(a,i,n,d)=>{if(i&&typeof i=="object"||typeof i=="function")for(let m of q(i))!G.call(a,m)&&m!==n&&k(a,m,{get:()=>i[m],enumerable:!(d=_(i,m))||d.enumerable});return a};var F=(a,i,n)=>(n=a!=null?Y(Q(a)):{},H(i||!a||!a.__esModule?k(n,"default",{value:a,enumerable:!0}):n,a)),K=a=>H(k({},"__esModule",{value:!0}),a);var $={};J($,{default:()=>Z});module.exports=K($);var t=require("react/jsx-runtime"),p=F(require("react")),T=require("swiper/react"),u=require("swiper/modules"),B=require("react-responsive"),o=require("../../helpers/index.js"),c=require("../../components/index.js"),O=require("../../shared/Styles.js"),M=F(require("../Media/index.js"));const A=a=>({pcImage:a.lgDesktop,desktopImage:a.desktop,laptopImage:a.laptop,padImage:a.tablet,mobileImage:a.mobile}),X=3e3,P=p.forwardRef(({className:a,classNames:i={},data:n,onSceneChange:d,...m},W)=>{const{title:I,subtitle:V,items:l,defaultActiveIndex:C=0,layout:D="left",autoplay:f=!0,autoplayDelay:w=X}=n,[s,v]=p.useState(C),E=p.useRef(null),h=p.useRef(0),x=p.useRef([]),N=p.useRef(!1),y=(0,B.useMediaQuery)({minWidth:1025});p.useEffect(()=>!f||l.length<=1||!y?void 0:((()=>{h.current=window.setInterval(()=>{v(e=>(e+1)%l.length)},w)})(),()=>{h.current&&window.clearInterval(h.current)}),[f,w,l.length,y]),p.useEffect(()=>{if(!y||!x.current[s])return;const r=x.current[s],e=r?.parentElement;if(!e||e.scrollHeight<=e.clientHeight)return;const b=requestAnimationFrame(()=>{const L=e.getBoundingClientRect(),S=r.getBoundingClientRect();if(S.top>=L.top&&S.bottom<=L.bottom)return;const U=S.top-L.top-e.clientHeight/2+S.height/2;e.scrollTo({top:e.scrollTop+U,behavior:"smooth"})});return()=>cancelAnimationFrame(b)},[s,y]);const R=p.useCallback(r=>{v(r),N.current=!0,d?.(r,l[r]),E.current?.slideTo(r),f&&l.length>1&&(h.current&&window.clearInterval(h.current),h.current=window.setInterval(()=>{v(e=>(e+1)%l.length)},w))},[l,d,f,w]),j=p.useCallback(r=>{if(N.current){N.current=!1;return}const e=r.realIndex;v(e),d?.(e,l[e])},[l,d]),g=l[s],z=D==="top";return(0,t.jsxs)("div",{ref:W,className:(0,o.cn)("scene-switcher-root","text-info-primary w-full",a,i.root,{"aiui-dark":n.theme==="dark"}),...m,children:[(I||V)&&(0,t.jsxs)("div",{className:(0,o.cn)("scene-switcher-header mb-6",i.header),children:[I&&(0,t.jsx)(c.Heading,{as:"h2",size:4,html:I,className:(0,o.cn)("scene-switcher-title",i.title)}),V&&(0,t.jsx)(c.Text,{as:"p",size:3,className:(0,o.cn)("",i?.subtitle),html:V})]}),(0,t.jsx)("div",{className:(0,o.cn)("scene-switcher-swiper","laptop:hidden !overflow-visible",i.swiper),children:(0,t.jsx)(T.Swiper,{modules:[u.FreeMode,u.Mousewheel,u.Autoplay],onSwiper:r=>{E.current=r},className:"!overflow-visible",onSlideChange:j,slidesPerView:"auto",spaceBetween:12,freeMode:!0,mousewheel:{forceToAxis:!0},initialSlide:C,loop:f&&l.length>1,autoplay:f&&l.length>1?{delay:w,disableOnInteraction:!1}:!1,breakpoints:{768:{spaceBetween:16}},children:l.map((r,e)=>(0,t.jsx)(T.SwiperSlide,{className:"h-[462px] !w-[296px]",children:(0,t.jsxs)("div",{className:(0,o.cn)("scene-switcher-slide","flex cursor-pointer flex-col",i.slide),onClick:()=>R(e),children:[(0,t.jsx)("div",{className:(0,o.cn)("scene-switcher-slide-media","rounded-box relative aspect-[296/320] w-full overflow-hidden",i.slideMedia),children:(0,t.jsx)(M.default,{...A(r.media),className:"rounded-t-box size-full overflow-hidden object-cover"})}),(0,t.jsxs)("div",{className:(0,o.cn)("scene-switcher-slide-content"," mt-6 border-t pt-4",s===e?"border-info-primary border-t-4":"border-lines-primary",i.slideContent),children:[(0,t.jsx)(c.Heading,{className:(0,o.cn)("scene-switcher-tab-title ",s===e?"text-info-primary":"text-info-tertiary",r.title),size:3,as:"h3",html:r.title}),r.description&&(0,t.jsx)(c.Text,{className:(0,o.cn)("desktop:text-[16px] lg-desktop:text-[18px] line-clamp-2 text-[14px]",s===e?"text-info-primary":"text-info-tertiary"),html:r.description})]})]})},e))})}),z&&(0,t.jsxs)("div",{className:(0,o.cn)("scene-switcher-container","laptop:flex laptop:flex-col hidden","laptop:h-[470px] desktop:h-[628px] lg-desktop:h-[746px] desktop:gap-[32px] gap-[16px]",i.container),children:[(0,t.jsx)("div",{className:(0,o.cn)("scene-switcher-media-wrapper","rounded-box flex-1 overflow-hidden",i.mediaWrapper),children:g&&(0,t.jsx)(M.default,{...A(g.media),className:(0,o.cn)("scene-switcher-media","rounded-box size-full object-cover",i.media)})}),(0,t.jsx)("div",{className:(0,o.cn)("scene-switcher-tab-list","border-lines-primary laptop:gap-4 desktop:gap-4 lg-desktop:gap-4 flex border-t",i.tabList),children:l.map((r,e)=>(0,t.jsxs)("div",{ref:b=>{x.current[e]=b},className:(0,o.cn)("scene-switcher-tab-item","desktop:pt-6 -mt-px flex-1 cursor-pointer border-t-2 pt-4 transition-colors",s===e?"border-info-primary border-t-4":"hover:border-lines-primary border-transparent",i.tabItem),onClick:()=>R(e),role:"button","aria-selected":s===e,children:[(0,t.jsx)(c.Heading,{className:(0,o.cn)("scene-switcher-tab-title line-clamp-2",s===e?"text-info-primary":"text-info-tertiary",r.title),size:3,as:"h3",html:r.title}),r.description&&(0,t.jsx)(c.Text,{className:(0,o.cn)("desktop:text-[16px] lg-desktop:text-[18px] line-clamp-2 text-[14px]",s===e?"text-info-primary":"text-info-tertiary"),html:r.description})]},e))})]}),!z&&(0,t.jsxs)("div",{className:(0,o.cn)("scene-switcher-container","laptop:flex laptop:gap-6 desktop:gap-8 lg-desktop:gap-10 hidden","laptop:h-[336px] desktop:h-[448px] lg-desktop:h-[560px]",D==="right"&&"flex-row-reverse",i.container),children:[(0,t.jsx)("div",{className:(0,o.cn)("scene-switcher-tab-list","laptop:w-[320px] desktop:w-[400px] lg-desktop:w-[544px] flex items-center",i.tabList),children:(0,t.jsx)("div",{className:"flex max-h-full w-full flex-col overflow-y-auto",children:l.map((r,e)=>(0,t.jsxs)(p.Fragment,{children:[e>0&&(0,t.jsx)("div",{className:"border-lines-primary h-8 shrink-0 border-l-4"}),(0,t.jsxs)("div",{ref:b=>{x.current[e]=b},className:(0,o.cn)("scene-switcher-tab-item","shrink-0 cursor-pointer border-l-4 pl-5",s===e?"border-info-primary border-l-[6px]":"border-lines-primary hover:border-info-tertiary",i.tabItem),onClick:()=>R(e),role:"button","aria-selected":s===e,children:[(0,t.jsx)(c.Heading,{className:(0,o.cn)("scene-switcher-tab-title desktop:line-clamp-3 line-clamp-2",s===e?"text-info-primary":"text-info-tertiary",r.title),size:3,as:"h3",html:r.title}),r.description&&(0,t.jsx)(c.Text,{className:(0,o.cn)("desktop:text-[16px] lg-desktop:text-[18px] line-clamp-2 text-[14px]",s===e?"text-info-primary":"text-info-tertiary hidden"),html:r.description})]})]},e))})}),(0,t.jsx)("div",{className:(0,o.cn)("scene-switcher-media-wrapper","rounded-box flex-1 overflow-hidden",i.mediaWrapper),children:g&&(0,t.jsx)(M.default,{...A(g.media),className:(0,o.cn)("scene-switcher-media","rounded-box size-full h-full overflow-visible object-cover",i.media)})})]})]})});P.displayName="MediaSceneSwitcherV2";var Z=(0,O.withLayout)(P);
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/biz-components/MediaSceneSwitcherV2/index.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Swiper, SwiperSlide } from 'swiper/react'\nimport { FreeMode, Mousewheel, Autoplay } from 'swiper/modules'\nimport type { Swiper as SwiperType } from 'swiper'\nimport { useMediaQuery } from 'react-responsive'\nimport { cn } from '../../helpers/index.js'\nimport type { Media as MediaType, Theme } from '../../types/props.js'\nimport { Heading, Text } from '../../components/index.js'\nimport { withLayout } from '../../shared/Styles.js'\nimport Media from '../Media/index.js'\n\nexport type MediaSceneSwitcherV2SemanticName =\n | 'root'\n | 'header'\n | 'title'\n | 'subtitle'\n | 'container'\n | 'tabList'\n | 'tabItem'\n | 'tabTitle'\n | 'tabDescription'\n | 'mediaWrapper'\n | 'media'\n | 'swiper'\n | 'slide'\n | 'slideMedia'\n | 'slideContent'\n\n/**\n * \u573A\u666F\u9879\u6570\u636E\u63A5\u53E3\n */\nexport interface MediaSceneSwitcherV2Item {\n /** \u573A\u666F\u6807\u9898 */\n title: string\n /** \u573A\u666F\u63CF\u8FF0 */\n description?: string\n /** \u573A\u666F\u5A92\u4F53\uFF08\u56FE\u7247/\u89C6\u9891\uFF09 */\n media: {\n mobile?: MediaType\n tablet?: MediaType\n laptop?: MediaType\n desktop?: MediaType\n lgDesktop?: MediaType\n }\n}\n\n/**\n * \u5E03\u5C40\u6A21\u5F0F\n * - left: \u5DE6\u6587\u53F3\u56FE\uFF08laptop+ \u9ED8\u8BA4\uFF09\n * - right: \u5DE6\u56FE\u53F3\u6587\n * - top: \u4E0A\u56FE\u4E0B\u6587\uFF08swiper \u5361\u7247\u6A21\u5F0F\uFF09\n */\nexport type MediaSceneSwitcherV2Layout = 'left' | 'right' | 'top'\n\n/**\n * MediaSceneSwitcherV2 \u4E1A\u52A1\u7EC4\u4EF6\u6570\u636E\u63A5\u53E3\n */\nexport interface MediaSceneSwitcherV2Data {\n /** \u4E3B\u9898 */\n theme?: Theme\n /** \u4E3B\u6807\u9898 */\n title?: string\n /** \u526F\u6807\u9898 */\n subtitle?: string\n /** \u573A\u666F\u5217\u8868 */\n items: MediaSceneSwitcherV2Item[]\n /** \u9ED8\u8BA4\u9009\u4E2D\u7684\u573A\u666F\u7D22\u5F15 */\n defaultActiveIndex?: number\n /** \u5E03\u5C40\u6A21\u5F0F\uFF0C\u9ED8\u8BA4 text-left */\n layout?: MediaSceneSwitcherV2Layout\n /** \u662F\u5426\u5F00\u542F\u81EA\u52A8\u8F6E\u64AD\uFF0C\u9ED8\u8BA4 true */\n autoplay?: boolean\n /** \u81EA\u52A8\u8F6E\u64AD\u95F4\u9694\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09\uFF0C\u9ED8\u8BA4 3000 */\n autoplayDelay?: number\n}\n\nexport interface MediaSceneSwitcherV2Props extends React.HTMLAttributes<HTMLDivElement> {\n /** \u4E1A\u52A1\u6570\u636E */\n data: MediaSceneSwitcherV2Data\n /** \u8BED\u4E49\u5316\u7C7B\u540D\u8986\u76D6 */\n classNames?: Partial<Record<MediaSceneSwitcherV2SemanticName, string>>\n /** \u573A\u666F\u5207\u6362\u56DE\u8C03 */\n onSceneChange?: (index: number, scene: MediaSceneSwitcherV2Item) => void\n}\n\nconst toMediaProps = (media: MediaSceneSwitcherV2Item['media']) => ({\n pcImage: media.lgDesktop,\n desktopImage: media.desktop,\n laptopImage: media.laptop,\n padImage: media.tablet,\n mobileImage: media.mobile,\n})\n\n/**\n * MediaSceneSwitcherV2 - \u591A\u573A\u666F\u5207\u6362\u7EC4\u4EF6\n *\n * @description \u7528\u4E8E\u5C55\u793A\u591A\u4E2A\u573A\u666F\u7684\u5207\u6362\u7EC4\u4EF6\uFF0C\u652F\u6301\u54CD\u5E94\u5F0F\u5E03\u5C40\uFF1A\n * - mobile/tablet: \u6A2A\u5411\u6ED1\u52A8\u5361\u7247\u5E03\u5C40\n * - laptop+: \u5DE6\u6587\u53F3\u56FE / \u5DE6\u56FE\u53F3\u6587\u5E03\u5C40\n */\nconst DEFAULT_AUTOPLAY_DELAY = 3000\n\nconst MediaSceneSwitcherV2 = React.forwardRef<HTMLDivElement, MediaSceneSwitcherV2Props>(\n ({ className, classNames = {}, data, onSceneChange, ...props }, ref) => {\n const {\n title,\n subtitle,\n items: scenes,\n defaultActiveIndex = 0,\n layout = 'left',\n autoplay = true,\n autoplayDelay = DEFAULT_AUTOPLAY_DELAY,\n } = data\n const [activeIndex, setActiveIndex] = React.useState(defaultActiveIndex)\n const swiperRef = React.useRef<SwiperType | null>(null)\n const intervalRef = React.useRef<number>(0)\n const tabRefs = React.useRef<(HTMLDivElement | null)[]>([])\n\n // \u5224\u65AD\u662F\u5426\u662F\u684C\u9762\u7AEF\n const isLaptopOrLarger = useMediaQuery({ minWidth: 1025 })\n\n // \u684C\u9762\u7AEF\u81EA\u52A8\u8F6E\u64AD\uFF08\u53EA\u5728 laptop+ \u751F\u6548\uFF0C\u624B\u673A\u7AEF\u7531 Swiper \u7684 onSlideChange \u540C\u6B65\uFF09\n React.useEffect(() => {\n if (!autoplay || scenes.length <= 1 || !isLaptopOrLarger) return\n\n const startAutoplay = () => {\n intervalRef.current = window.setInterval(() => {\n setActiveIndex(prev => (prev + 1) % scenes.length)\n }, autoplayDelay)\n }\n\n startAutoplay()\n\n return () => {\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current)\n }\n }\n }, [autoplay, autoplayDelay, scenes.length, isLaptopOrLarger])\n\n // \u5F53 activeIndex \u53D8\u5316\u65F6\u81EA\u52A8\u6EDA\u52A8\u5230\u5BF9\u5E94\u7684 tab\uFF08\u4EC5\u5F53\u7236\u5BB9\u5668\u53EF\u6EDA\u52A8\u65F6\uFF09\n React.useEffect(() => {\n if (!isLaptopOrLarger || !tabRefs.current[activeIndex]) return\n\n const tabElement = tabRefs.current[activeIndex]\n const parentContainer = tabElement?.parentElement\n\n // \u68C0\u67E5\u7236\u5BB9\u5668\u662F\u5426\u53EF\u6EDA\u52A8\n if (!parentContainer || parentContainer.scrollHeight <= parentContainer.clientHeight) return\n\n // \u4F7F\u7528 requestAnimationFrame \u907F\u514D\u963B\u585E\u4E3B\u7EBF\u7A0B\n const rafId = requestAnimationFrame(() => {\n const containerRect = parentContainer.getBoundingClientRect()\n const tabRect = tabElement.getBoundingClientRect()\n\n // \u68C0\u67E5\u5143\u7D20\u662F\u5426\u5DF2\u5728\u53EF\u89C6\u533A\u57DF\u5185\n const isVisible = tabRect.top >= containerRect.top && tabRect.bottom <= containerRect.bottom\n\n // \u5982\u679C\u5DF2\u7ECF\u53EF\u89C1\uFF0C\u4E0D\u9700\u8981\u6EDA\u52A8\n if (isVisible) return\n\n // \u8BA1\u7B97\u6EDA\u52A8\u8DDD\u79BB\uFF0C\u8BA9 tab \u5C3D\u91CF\u5C45\u4E2D\u663E\u793A\n const scrollOffset = tabRect.top - containerRect.top - parentContainer.clientHeight / 2 + tabRect.height / 2\n\n parentContainer.scrollTo({\n top: parentContainer.scrollTop + scrollOffset,\n behavior: 'smooth',\n })\n })\n\n return () => cancelAnimationFrame(rafId)\n }, [activeIndex, isLaptopOrLarger])\n\n const handleSceneClick = React.useCallback(\n (index: number) => {\n setActiveIndex(index)\n onSceneChange?.(index, scenes[index])\n // \u540C\u6B65 swiper \u4F4D\u7F6E\n swiperRef.current?.slideTo(index)\n\n // \u91CD\u7F6E\u81EA\u52A8\u8F6E\u64AD\u8BA1\u65F6\u5668\n if (autoplay && scenes.length > 1) {\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current)\n }\n intervalRef.current = window.setInterval(() => {\n setActiveIndex(prev => (prev + 1) % scenes.length)\n }, autoplayDelay)\n }\n },\n [scenes, onSceneChange, autoplay, autoplayDelay]\n )\n\n const handleSlideChange = React.useCallback(\n (swiper: SwiperType) => {\n // \u4F7F\u7528 realIndex \u4EE5\u6B63\u786E\u5904\u7406 loop \u6A21\u5F0F\n const index = swiper.realIndex\n setActiveIndex(index)\n onSceneChange?.(index, scenes[index])\n },\n [scenes, onSceneChange]\n )\n\n const activeScene = scenes[activeIndex]\n\n const isMediaTop = layout === 'top'\n\n return (\n <div\n ref={ref}\n className={cn('scene-switcher-root', 'text-info-primary w-full', className, classNames.root, {\n 'aiui-dark': data.theme === 'dark',\n })}\n {...props}\n >\n {/* \u6807\u9898\u533A\u57DF */}\n {(title || subtitle) && (\n <div className={cn('scene-switcher-header mb-6', classNames.header)}>\n {title && (\n <Heading as=\"h2\" size={4} html={title} className={cn('scene-switcher-title', classNames.title)} />\n )}\n {subtitle && <Text as=\"p\" size={3} className={cn('', classNames?.subtitle)} html={subtitle} />}\n </div>\n )}\n {/* Mobile/Tablet: \u6A2A\u5411\u6ED1\u52A8\u5361\u7247\u5E03\u5C40 */}\n <div className={cn('scene-switcher-swiper', 'laptop:hidden !overflow-visible', classNames.swiper)}>\n <Swiper\n modules={[FreeMode, Mousewheel, Autoplay]}\n onSwiper={swiper => {\n swiperRef.current = swiper\n }}\n className=\"!overflow-visible\"\n onSlideChange={handleSlideChange}\n slidesPerView=\"auto\"\n spaceBetween={12}\n freeMode={true}\n mousewheel={{ forceToAxis: true }}\n initialSlide={defaultActiveIndex}\n loop={autoplay && scenes.length > 1}\n autoplay={autoplay && scenes.length > 1 ? { delay: autoplayDelay, disableOnInteraction: false } : false}\n breakpoints={{\n 768: { spaceBetween: 16 },\n }}\n >\n {scenes.map((scene, index) => (\n <SwiperSlide key={index} className=\"h-[462px] !w-[296px]\">\n <div\n className={cn('scene-switcher-slide', 'flex cursor-pointer flex-col', classNames.slide)}\n onClick={() => handleSceneClick(index)}\n >\n {/* \u5A92\u4F53 */}\n <div\n className={cn(\n 'scene-switcher-slide-media',\n 'rounded-box relative aspect-[296/320] w-full overflow-hidden',\n classNames.slideMedia\n )}\n >\n <Media\n {...toMediaProps(scene.media)}\n className=\"rounded-t-box size-full overflow-hidden object-cover\"\n />\n </div>\n {/* \u6587\u5B57\u5185\u5BB9 */}\n <div\n className={cn(\n 'scene-switcher-slide-content',\n ' mt-6 border-t pt-4',\n activeIndex === index ? 'border-info-primary border-t-4' : 'border-lines-primary',\n classNames.slideContent\n )}\n >\n <Heading\n className={cn(\n 'scene-switcher-tab-title ',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary',\n scene.title\n )}\n size={3}\n as={'h3'}\n html={scene.title}\n />\n {scene.description && (\n <Text\n className={cn(\n 'desktop:text-[16px] lg-desktop:text-[18px] line-clamp-2 text-[14px]',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary'\n )}\n html={scene.description}\n />\n )}\n </div>\n </div>\n </SwiperSlide>\n ))}\n </Swiper>\n </div>\n\n {/* Laptop+: media-top \u5E03\u5C40 (\u4E0A\u56FE\u4E0B\u6587) */}\n {isMediaTop && (\n <div\n className={cn(\n 'scene-switcher-container',\n 'laptop:flex laptop:flex-col hidden',\n 'laptop:h-[470px] desktop:h-[628px] lg-desktop:h-[746px] desktop:gap-[32px] gap-[16px]',\n classNames.container\n )}\n >\n {/* \u5A92\u4F53\u533A\u57DF - \u663E\u793A\u5F53\u524D\u9009\u4E2D */}\n <div\n className={cn(\n 'scene-switcher-media-wrapper',\n 'rounded-box flex-1 overflow-hidden',\n classNames.mediaWrapper\n )}\n >\n {activeScene && (\n <Media\n {...toMediaProps(activeScene.media)}\n className={cn('scene-switcher-media', 'rounded-box size-full object-cover', classNames.media)}\n />\n )}\n </div>\n\n {/* Tab \u5217\u8868 - \u6A2A\u5411\u6392\u5217 */}\n <div\n className={cn(\n 'scene-switcher-tab-list',\n 'border-lines-primary laptop:gap-4 desktop:gap-4 lg-desktop:gap-4 flex border-t',\n classNames.tabList\n )}\n >\n {scenes.map((scene, index) => (\n <div\n key={index}\n ref={el => {\n tabRefs.current[index] = el\n }}\n className={cn(\n 'scene-switcher-tab-item',\n 'desktop:pt-6 -mt-px flex-1 cursor-pointer border-t-2 pt-4 transition-colors',\n activeIndex === index\n ? 'border-info-primary border-t-4'\n : 'hover:border-lines-primary border-transparent',\n classNames.tabItem\n )}\n onClick={() => handleSceneClick(index)}\n role=\"button\"\n aria-selected={activeIndex === index}\n >\n <Heading\n className={cn(\n 'scene-switcher-tab-title line-clamp-2',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary',\n scene.title\n )}\n size={3}\n as={'h3'}\n html={scene.title}\n />\n {scene.description && (\n <Text\n className={cn(\n 'desktop:text-[16px] lg-desktop:text-[18px] line-clamp-2 text-[14px]',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary'\n )}\n html={scene.description}\n />\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Laptop+: \u5DE6\u6587\u53F3\u56FE / \u5DE6\u56FE\u53F3\u6587\u5E03\u5C40 */}\n {!isMediaTop && (\n <div\n className={cn(\n 'scene-switcher-container',\n 'laptop:flex laptop:gap-6 desktop:gap-8 lg-desktop:gap-10 hidden',\n 'laptop:h-[336px] desktop:h-[448px] lg-desktop:h-[560px]',\n layout === 'right' && 'flex-row-reverse',\n classNames.container\n )}\n >\n {/* Tab \u5217\u8868 - \u5916\u5C42\u5C45\u4E2D */}\n <div\n className={cn(\n 'scene-switcher-tab-list',\n 'laptop:w-[320px] desktop:w-[400px] lg-desktop:w-[544px] flex items-center',\n classNames.tabList\n )}\n >\n {/* \u5185\u5C42\u6EDA\u52A8 */}\n <div className=\"flex max-h-full w-full flex-col overflow-y-auto\">\n {scenes.map((scene, index) => (\n <React.Fragment key={index}>\n {index > 0 && <div className=\"border-lines-primary h-8 shrink-0 border-l-4\" />}\n <div\n ref={el => {\n tabRefs.current[index] = el\n }}\n className={cn(\n 'scene-switcher-tab-item',\n 'shrink-0 cursor-pointer border-l-4 pl-5',\n activeIndex === index\n ? 'border-info-primary border-l-[6px]'\n : 'border-lines-primary hover:border-info-tertiary',\n classNames.tabItem\n )}\n onClick={() => handleSceneClick(index)}\n role=\"button\"\n aria-selected={activeIndex === index}\n >\n <Heading\n className={cn(\n 'scene-switcher-tab-title desktop:line-clamp-3 line-clamp-2',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary',\n scene.title\n )}\n size={3}\n as={'h3'}\n html={scene.title}\n />\n {scene.description && (\n <Text\n className={cn(\n 'desktop:text-[16px] lg-desktop:text-[18px] line-clamp-2 text-[14px]',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary hidden'\n )}\n html={scene.description}\n />\n )}\n </div>\n </React.Fragment>\n ))}\n </div>\n </div>\n\n {/* \u5A92\u4F53\u533A\u57DF */}\n <div\n className={cn(\n 'scene-switcher-media-wrapper',\n 'rounded-box flex-1 overflow-hidden',\n classNames.mediaWrapper\n )}\n >\n {activeScene && (\n <Media\n {...toMediaProps(activeScene.media)}\n className={cn(\n 'scene-switcher-media',\n 'rounded-box size-full h-full overflow-visible object-cover',\n classNames.media\n )}\n />\n )}\n </div>\n </div>\n )}\n </div>\n )\n }\n)\n\nMediaSceneSwitcherV2.displayName = 'MediaSceneSwitcherV2'\nexport default withLayout(MediaSceneSwitcherV2)\n"],
|
|
5
|
-
"mappings": "ukBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,aAAAE,IAAA,eAAAC,EAAAH,
|
|
6
|
-
"names": ["MediaSceneSwitcherV2_exports", "__export", "MediaSceneSwitcherV2_default", "__toCommonJS", "import_jsx_runtime", "React", "import_react", "import_modules", "import_react_responsive", "import_helpers", "import_components", "import_Styles", "import_Media", "toMediaProps", "media", "DEFAULT_AUTOPLAY_DELAY", "MediaSceneSwitcherV2", "className", "classNames", "data", "onSceneChange", "props", "ref", "title", "subtitle", "scenes", "defaultActiveIndex", "layout", "autoplay", "autoplayDelay", "activeIndex", "setActiveIndex", "swiperRef", "intervalRef", "tabRefs", "isLaptopOrLarger", "prev", "tabElement", "parentContainer", "rafId", "containerRect", "tabRect", "scrollOffset", "handleSceneClick", "index", "handleSlideChange", "swiper", "activeScene", "isMediaTop", "scene", "Media", "el"]
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Swiper, SwiperSlide } from 'swiper/react'\nimport { FreeMode, Mousewheel, Autoplay } from 'swiper/modules'\nimport type { Swiper as SwiperType } from 'swiper'\nimport { useMediaQuery } from 'react-responsive'\nimport { cn } from '../../helpers/index.js'\nimport type { Media as MediaType, Theme } from '../../types/props.js'\nimport { Heading, Text } from '../../components/index.js'\nimport { withLayout } from '../../shared/Styles.js'\nimport Media from '../Media/index.js'\n\nexport type MediaSceneSwitcherV2SemanticName =\n | 'root'\n | 'header'\n | 'title'\n | 'subtitle'\n | 'container'\n | 'tabList'\n | 'tabItem'\n | 'tabTitle'\n | 'tabDescription'\n | 'mediaWrapper'\n | 'media'\n | 'swiper'\n | 'slide'\n | 'slideMedia'\n | 'slideContent'\n\n/**\n * \u573A\u666F\u9879\u6570\u636E\u63A5\u53E3\n */\nexport interface MediaSceneSwitcherV2Item {\n /** \u573A\u666F\u6807\u9898 */\n title: string\n /** \u573A\u666F\u63CF\u8FF0 */\n description?: string\n /** \u573A\u666F\u5A92\u4F53\uFF08\u56FE\u7247/\u89C6\u9891\uFF09 */\n media: {\n mobile?: MediaType\n tablet?: MediaType\n laptop?: MediaType\n desktop?: MediaType\n lgDesktop?: MediaType\n }\n}\n\n/**\n * \u5E03\u5C40\u6A21\u5F0F\n * - left: \u5DE6\u6587\u53F3\u56FE\uFF08laptop+ \u9ED8\u8BA4\uFF09\n * - right: \u5DE6\u56FE\u53F3\u6587\n * - top: \u4E0A\u56FE\u4E0B\u6587\uFF08swiper \u5361\u7247\u6A21\u5F0F\uFF09\n */\nexport type MediaSceneSwitcherV2Layout = 'left' | 'right' | 'top'\n\n/**\n * MediaSceneSwitcherV2 \u4E1A\u52A1\u7EC4\u4EF6\u6570\u636E\u63A5\u53E3\n */\nexport interface MediaSceneSwitcherV2Data {\n /** \u4E3B\u9898 */\n theme?: Theme\n /** \u4E3B\u6807\u9898 */\n title?: string\n /** \u526F\u6807\u9898 */\n subtitle?: string\n /** \u573A\u666F\u5217\u8868 */\n items: MediaSceneSwitcherV2Item[]\n /** \u9ED8\u8BA4\u9009\u4E2D\u7684\u573A\u666F\u7D22\u5F15 */\n defaultActiveIndex?: number\n /** \u5E03\u5C40\u6A21\u5F0F\uFF0C\u9ED8\u8BA4 text-left */\n layout?: MediaSceneSwitcherV2Layout\n /** \u662F\u5426\u5F00\u542F\u81EA\u52A8\u8F6E\u64AD\uFF0C\u9ED8\u8BA4 true */\n autoplay?: boolean\n /** \u81EA\u52A8\u8F6E\u64AD\u95F4\u9694\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09\uFF0C\u9ED8\u8BA4 3000 */\n autoplayDelay?: number\n}\n\nexport interface MediaSceneSwitcherV2Props extends React.HTMLAttributes<HTMLDivElement> {\n /** \u4E1A\u52A1\u6570\u636E */\n data: MediaSceneSwitcherV2Data\n /** \u8BED\u4E49\u5316\u7C7B\u540D\u8986\u76D6 */\n classNames?: Partial<Record<MediaSceneSwitcherV2SemanticName, string>>\n /** \u573A\u666F\u5207\u6362\u56DE\u8C03 */\n onSceneChange?: (index: number, scene: MediaSceneSwitcherV2Item) => void\n}\n\nconst toMediaProps = (media: MediaSceneSwitcherV2Item['media']) => ({\n pcImage: media.lgDesktop,\n desktopImage: media.desktop,\n laptopImage: media.laptop,\n padImage: media.tablet,\n mobileImage: media.mobile,\n})\n\n/**\n * MediaSceneSwitcherV2 - \u591A\u573A\u666F\u5207\u6362\u7EC4\u4EF6\n *\n * @description \u7528\u4E8E\u5C55\u793A\u591A\u4E2A\u573A\u666F\u7684\u5207\u6362\u7EC4\u4EF6\uFF0C\u652F\u6301\u54CD\u5E94\u5F0F\u5E03\u5C40\uFF1A\n * - mobile/tablet: \u6A2A\u5411\u6ED1\u52A8\u5361\u7247\u5E03\u5C40\n * - laptop+: \u5DE6\u6587\u53F3\u56FE / \u5DE6\u56FE\u53F3\u6587\u5E03\u5C40\n */\nconst DEFAULT_AUTOPLAY_DELAY = 3000\n\nconst MediaSceneSwitcherV2 = React.forwardRef<HTMLDivElement, MediaSceneSwitcherV2Props>(\n ({ className, classNames = {}, data, onSceneChange, ...props }, ref) => {\n const {\n title,\n subtitle,\n items: scenes,\n defaultActiveIndex = 0,\n layout = 'left',\n autoplay = true,\n autoplayDelay = DEFAULT_AUTOPLAY_DELAY,\n } = data\n const [activeIndex, setActiveIndex] = React.useState(defaultActiveIndex)\n const swiperRef = React.useRef<SwiperType | null>(null)\n const intervalRef = React.useRef<number>(0)\n const tabRefs = React.useRef<(HTMLDivElement | null)[]>([])\n const isClickTriggered = React.useRef(false)\n\n // \u5224\u65AD\u662F\u5426\u662F\u684C\u9762\u7AEF\n const isLaptopOrLarger = useMediaQuery({ minWidth: 1025 })\n\n // \u684C\u9762\u7AEF\u81EA\u52A8\u8F6E\u64AD\uFF08\u53EA\u5728 laptop+ \u751F\u6548\uFF0C\u624B\u673A\u7AEF\u7531 Swiper \u7684 onSlideChange \u540C\u6B65\uFF09\n React.useEffect(() => {\n if (!autoplay || scenes.length <= 1 || !isLaptopOrLarger) return\n\n const startAutoplay = () => {\n intervalRef.current = window.setInterval(() => {\n setActiveIndex(prev => (prev + 1) % scenes.length)\n }, autoplayDelay)\n }\n\n startAutoplay()\n\n return () => {\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current)\n }\n }\n }, [autoplay, autoplayDelay, scenes.length, isLaptopOrLarger])\n\n // \u5F53 activeIndex \u53D8\u5316\u65F6\u81EA\u52A8\u6EDA\u52A8\u5230\u5BF9\u5E94\u7684 tab\uFF08\u4EC5\u5F53\u7236\u5BB9\u5668\u53EF\u6EDA\u52A8\u65F6\uFF09\n React.useEffect(() => {\n if (!isLaptopOrLarger || !tabRefs.current[activeIndex]) return\n\n const tabElement = tabRefs.current[activeIndex]\n const parentContainer = tabElement?.parentElement\n\n // \u68C0\u67E5\u7236\u5BB9\u5668\u662F\u5426\u53EF\u6EDA\u52A8\n if (!parentContainer || parentContainer.scrollHeight <= parentContainer.clientHeight) return\n\n // \u4F7F\u7528 requestAnimationFrame \u907F\u514D\u963B\u585E\u4E3B\u7EBF\u7A0B\n const rafId = requestAnimationFrame(() => {\n const containerRect = parentContainer.getBoundingClientRect()\n const tabRect = tabElement.getBoundingClientRect()\n\n // \u68C0\u67E5\u5143\u7D20\u662F\u5426\u5DF2\u5728\u53EF\u89C6\u533A\u57DF\u5185\n const isVisible = tabRect.top >= containerRect.top && tabRect.bottom <= containerRect.bottom\n\n // \u5982\u679C\u5DF2\u7ECF\u53EF\u89C1\uFF0C\u4E0D\u9700\u8981\u6EDA\u52A8\n if (isVisible) return\n\n // \u8BA1\u7B97\u6EDA\u52A8\u8DDD\u79BB\uFF0C\u8BA9 tab \u5C3D\u91CF\u5C45\u4E2D\u663E\u793A\n const scrollOffset = tabRect.top - containerRect.top - parentContainer.clientHeight / 2 + tabRect.height / 2\n\n parentContainer.scrollTo({\n top: parentContainer.scrollTop + scrollOffset,\n behavior: 'smooth',\n })\n })\n\n return () => cancelAnimationFrame(rafId)\n }, [activeIndex, isLaptopOrLarger])\n\n const handleSceneClick = React.useCallback(\n (index: number) => {\n setActiveIndex(index)\n isClickTriggered.current = true\n onSceneChange?.(index, scenes[index])\n swiperRef.current?.slideTo(index)\n\n // \u91CD\u7F6E\u81EA\u52A8\u8F6E\u64AD\u8BA1\u65F6\u5668\n if (autoplay && scenes.length > 1) {\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current)\n }\n intervalRef.current = window.setInterval(() => {\n setActiveIndex(prev => (prev + 1) % scenes.length)\n }, autoplayDelay)\n }\n },\n [scenes, onSceneChange, autoplay, autoplayDelay]\n )\n\n const handleSlideChange = React.useCallback(\n (swiper: SwiperType) => {\n if (isClickTriggered.current) {\n isClickTriggered.current = false\n return\n }\n const index = swiper.realIndex\n setActiveIndex(index)\n onSceneChange?.(index, scenes[index])\n },\n [scenes, onSceneChange]\n )\n\n const activeScene = scenes[activeIndex]\n\n const isMediaTop = layout === 'top'\n\n return (\n <div\n ref={ref}\n className={cn('scene-switcher-root', 'text-info-primary w-full', className, classNames.root, {\n 'aiui-dark': data.theme === 'dark',\n })}\n {...props}\n >\n {/* \u6807\u9898\u533A\u57DF */}\n {(title || subtitle) && (\n <div className={cn('scene-switcher-header mb-6', classNames.header)}>\n {title && (\n <Heading as=\"h2\" size={4} html={title} className={cn('scene-switcher-title', classNames.title)} />\n )}\n {subtitle && <Text as=\"p\" size={3} className={cn('', classNames?.subtitle)} html={subtitle} />}\n </div>\n )}\n {/* Mobile/Tablet: \u6A2A\u5411\u6ED1\u52A8\u5361\u7247\u5E03\u5C40 */}\n <div className={cn('scene-switcher-swiper', 'laptop:hidden !overflow-visible', classNames.swiper)}>\n <Swiper\n modules={[FreeMode, Mousewheel, Autoplay]}\n onSwiper={swiper => {\n swiperRef.current = swiper\n }}\n className=\"!overflow-visible\"\n onSlideChange={handleSlideChange}\n slidesPerView=\"auto\"\n spaceBetween={12}\n freeMode={true}\n mousewheel={{ forceToAxis: true }}\n initialSlide={defaultActiveIndex}\n loop={autoplay && scenes.length > 1}\n autoplay={autoplay && scenes.length > 1 ? { delay: autoplayDelay, disableOnInteraction: false } : false}\n breakpoints={{\n 768: { spaceBetween: 16 },\n }}\n >\n {scenes.map((scene, index) => (\n <SwiperSlide key={index} className=\"h-[462px] !w-[296px]\">\n <div\n className={cn('scene-switcher-slide', 'flex cursor-pointer flex-col', classNames.slide)}\n onClick={() => handleSceneClick(index)}\n >\n {/* \u5A92\u4F53 */}\n <div\n className={cn(\n 'scene-switcher-slide-media',\n 'rounded-box relative aspect-[296/320] w-full overflow-hidden',\n classNames.slideMedia\n )}\n >\n <Media\n {...toMediaProps(scene.media)}\n className=\"rounded-t-box size-full overflow-hidden object-cover\"\n />\n </div>\n {/* \u6587\u5B57\u5185\u5BB9 */}\n <div\n className={cn(\n 'scene-switcher-slide-content',\n ' mt-6 border-t pt-4',\n activeIndex === index ? 'border-info-primary border-t-4' : 'border-lines-primary',\n classNames.slideContent\n )}\n >\n <Heading\n className={cn(\n 'scene-switcher-tab-title ',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary',\n scene.title\n )}\n size={3}\n as={'h3'}\n html={scene.title}\n />\n {scene.description && (\n <Text\n className={cn(\n 'desktop:text-[16px] lg-desktop:text-[18px] line-clamp-2 text-[14px]',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary'\n )}\n html={scene.description}\n />\n )}\n </div>\n </div>\n </SwiperSlide>\n ))}\n </Swiper>\n </div>\n\n {/* Laptop+: media-top \u5E03\u5C40 (\u4E0A\u56FE\u4E0B\u6587) */}\n {isMediaTop && (\n <div\n className={cn(\n 'scene-switcher-container',\n 'laptop:flex laptop:flex-col hidden',\n 'laptop:h-[470px] desktop:h-[628px] lg-desktop:h-[746px] desktop:gap-[32px] gap-[16px]',\n classNames.container\n )}\n >\n {/* \u5A92\u4F53\u533A\u57DF - \u663E\u793A\u5F53\u524D\u9009\u4E2D */}\n <div\n className={cn(\n 'scene-switcher-media-wrapper',\n 'rounded-box flex-1 overflow-hidden',\n classNames.mediaWrapper\n )}\n >\n {activeScene && (\n <Media\n {...toMediaProps(activeScene.media)}\n className={cn('scene-switcher-media', 'rounded-box size-full object-cover', classNames.media)}\n />\n )}\n </div>\n\n {/* Tab \u5217\u8868 - \u6A2A\u5411\u6392\u5217 */}\n <div\n className={cn(\n 'scene-switcher-tab-list',\n 'border-lines-primary laptop:gap-4 desktop:gap-4 lg-desktop:gap-4 flex border-t',\n classNames.tabList\n )}\n >\n {scenes.map((scene, index) => (\n <div\n key={index}\n ref={el => {\n tabRefs.current[index] = el\n }}\n className={cn(\n 'scene-switcher-tab-item',\n 'desktop:pt-6 -mt-px flex-1 cursor-pointer border-t-2 pt-4 transition-colors',\n activeIndex === index\n ? 'border-info-primary border-t-4'\n : 'hover:border-lines-primary border-transparent',\n classNames.tabItem\n )}\n onClick={() => handleSceneClick(index)}\n role=\"button\"\n aria-selected={activeIndex === index}\n >\n <Heading\n className={cn(\n 'scene-switcher-tab-title line-clamp-2',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary',\n scene.title\n )}\n size={3}\n as={'h3'}\n html={scene.title}\n />\n {scene.description && (\n <Text\n className={cn(\n 'desktop:text-[16px] lg-desktop:text-[18px] line-clamp-2 text-[14px]',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary'\n )}\n html={scene.description}\n />\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Laptop+: \u5DE6\u6587\u53F3\u56FE / \u5DE6\u56FE\u53F3\u6587\u5E03\u5C40 */}\n {!isMediaTop && (\n <div\n className={cn(\n 'scene-switcher-container',\n 'laptop:flex laptop:gap-6 desktop:gap-8 lg-desktop:gap-10 hidden',\n 'laptop:h-[336px] desktop:h-[448px] lg-desktop:h-[560px]',\n layout === 'right' && 'flex-row-reverse',\n classNames.container\n )}\n >\n {/* Tab \u5217\u8868 - \u5916\u5C42\u5C45\u4E2D */}\n <div\n className={cn(\n 'scene-switcher-tab-list',\n 'laptop:w-[320px] desktop:w-[400px] lg-desktop:w-[544px] flex items-center',\n classNames.tabList\n )}\n >\n {/* \u5185\u5C42\u6EDA\u52A8 */}\n <div className=\"flex max-h-full w-full flex-col overflow-y-auto\">\n {scenes.map((scene, index) => (\n <React.Fragment key={index}>\n {index > 0 && <div className=\"border-lines-primary h-8 shrink-0 border-l-4\" />}\n <div\n ref={el => {\n tabRefs.current[index] = el\n }}\n className={cn(\n 'scene-switcher-tab-item',\n 'shrink-0 cursor-pointer border-l-4 pl-5',\n activeIndex === index\n ? 'border-info-primary border-l-[6px]'\n : 'border-lines-primary hover:border-info-tertiary',\n classNames.tabItem\n )}\n onClick={() => handleSceneClick(index)}\n role=\"button\"\n aria-selected={activeIndex === index}\n >\n <Heading\n className={cn(\n 'scene-switcher-tab-title desktop:line-clamp-3 line-clamp-2',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary',\n scene.title\n )}\n size={3}\n as={'h3'}\n html={scene.title}\n />\n {scene.description && (\n <Text\n className={cn(\n 'desktop:text-[16px] lg-desktop:text-[18px] line-clamp-2 text-[14px]',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary hidden'\n )}\n html={scene.description}\n />\n )}\n </div>\n </React.Fragment>\n ))}\n </div>\n </div>\n\n {/* \u5A92\u4F53\u533A\u57DF */}\n <div\n className={cn(\n 'scene-switcher-media-wrapper',\n 'rounded-box flex-1 overflow-hidden',\n classNames.mediaWrapper\n )}\n >\n {activeScene && (\n <Media\n {...toMediaProps(activeScene.media)}\n className={cn(\n 'scene-switcher-media',\n 'rounded-box size-full h-full overflow-visible object-cover',\n classNames.media\n )}\n />\n )}\n </div>\n </div>\n )}\n </div>\n )\n }\n)\n\nMediaSceneSwitcherV2.displayName = 'MediaSceneSwitcherV2'\nexport default withLayout(MediaSceneSwitcherV2)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["MediaSceneSwitcherV2_exports", "__export", "MediaSceneSwitcherV2_default", "__toCommonJS", "import_jsx_runtime", "React", "import_react", "import_modules", "import_react_responsive", "import_helpers", "import_components", "import_Styles", "import_Media", "toMediaProps", "media", "DEFAULT_AUTOPLAY_DELAY", "MediaSceneSwitcherV2", "className", "classNames", "data", "onSceneChange", "props", "ref", "title", "subtitle", "scenes", "defaultActiveIndex", "layout", "autoplay", "autoplayDelay", "activeIndex", "setActiveIndex", "swiperRef", "intervalRef", "tabRefs", "isClickTriggered", "isLaptopOrLarger", "prev", "tabElement", "parentContainer", "rafId", "containerRect", "tabRect", "scrollOffset", "handleSceneClick", "index", "handleSlideChange", "swiper", "activeScene", "isMediaTop", "scene", "Media", "el"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{jsx as r,jsxs as n}from"react/jsx-runtime";import*as s from"react";import{Swiper as
|
|
1
|
+
"use client";import{jsx as r,jsxs as n}from"react/jsx-runtime";import*as s from"react";import{Swiper as B,SwiperSlide as O}from"swiper/react";import{FreeMode as W,Mousewheel as j,Autoplay as U}from"swiper/modules";import{useMediaQuery as Y}from"react-responsive";import{cn as i}from"../../helpers/index.js";import{Heading as y,Text as g}from"../../components/index.js";import{withLayout as _}from"../../shared/Styles.js";import V from"../Media/index.js";const N=p=>({pcImage:p.lgDesktop,desktopImage:p.desktop,laptopImage:p.laptop,padImage:p.tablet,mobileImage:p.mobile}),q=3e3,E=s.forwardRef(({className:p,classNames:o={},data:R,onSceneChange:h,...z},H)=>{const{title:S,subtitle:k,items:a,defaultActiveIndex:L=0,layout:A="left",autoplay:c=!0,autoplayDelay:m=q}=R,[l,u]=s.useState(L),C=s.useRef(null),d=s.useRef(0),w=s.useRef([]),M=s.useRef(!1),b=Y({minWidth:1025});s.useEffect(()=>!c||a.length<=1||!b?void 0:((()=>{d.current=window.setInterval(()=>{u(e=>(e+1)%a.length)},m)})(),()=>{d.current&&window.clearInterval(d.current)}),[c,m,a.length,b]),s.useEffect(()=>{if(!b||!w.current[l])return;const t=w.current[l],e=t?.parentElement;if(!e||e.scrollHeight<=e.clientHeight)return;const f=requestAnimationFrame(()=>{const I=e.getBoundingClientRect(),x=t.getBoundingClientRect();if(x.top>=I.top&&x.bottom<=I.bottom)return;const P=x.top-I.top-e.clientHeight/2+x.height/2;e.scrollTo({top:e.scrollTop+P,behavior:"smooth"})});return()=>cancelAnimationFrame(f)},[l,b]);const T=s.useCallback(t=>{u(t),M.current=!0,h?.(t,a[t]),C.current?.slideTo(t),c&&a.length>1&&(d.current&&window.clearInterval(d.current),d.current=window.setInterval(()=>{u(e=>(e+1)%a.length)},m))},[a,h,c,m]),F=s.useCallback(t=>{if(M.current){M.current=!1;return}const e=t.realIndex;u(e),h?.(e,a[e])},[a,h]),v=a[l],D=A==="top";return n("div",{ref:H,className:i("scene-switcher-root","text-info-primary w-full",p,o.root,{"aiui-dark":R.theme==="dark"}),...z,children:[(S||k)&&n("div",{className:i("scene-switcher-header mb-6",o.header),children:[S&&r(y,{as:"h2",size:4,html:S,className:i("scene-switcher-title",o.title)}),k&&r(g,{as:"p",size:3,className:i("",o?.subtitle),html:k})]}),r("div",{className:i("scene-switcher-swiper","laptop:hidden !overflow-visible",o.swiper),children:r(B,{modules:[W,j,U],onSwiper:t=>{C.current=t},className:"!overflow-visible",onSlideChange:F,slidesPerView:"auto",spaceBetween:12,freeMode:!0,mousewheel:{forceToAxis:!0},initialSlide:L,loop:c&&a.length>1,autoplay:c&&a.length>1?{delay:m,disableOnInteraction:!1}:!1,breakpoints:{768:{spaceBetween:16}},children:a.map((t,e)=>r(O,{className:"h-[462px] !w-[296px]",children:n("div",{className:i("scene-switcher-slide","flex cursor-pointer flex-col",o.slide),onClick:()=>T(e),children:[r("div",{className:i("scene-switcher-slide-media","rounded-box relative aspect-[296/320] w-full overflow-hidden",o.slideMedia),children:r(V,{...N(t.media),className:"rounded-t-box size-full overflow-hidden object-cover"})}),n("div",{className:i("scene-switcher-slide-content"," mt-6 border-t pt-4",l===e?"border-info-primary border-t-4":"border-lines-primary",o.slideContent),children:[r(y,{className:i("scene-switcher-tab-title ",l===e?"text-info-primary":"text-info-tertiary",t.title),size:3,as:"h3",html:t.title}),t.description&&r(g,{className:i("desktop:text-[16px] lg-desktop:text-[18px] line-clamp-2 text-[14px]",l===e?"text-info-primary":"text-info-tertiary"),html:t.description})]})]})},e))})}),D&&n("div",{className:i("scene-switcher-container","laptop:flex laptop:flex-col hidden","laptop:h-[470px] desktop:h-[628px] lg-desktop:h-[746px] desktop:gap-[32px] gap-[16px]",o.container),children:[r("div",{className:i("scene-switcher-media-wrapper","rounded-box flex-1 overflow-hidden",o.mediaWrapper),children:v&&r(V,{...N(v.media),className:i("scene-switcher-media","rounded-box size-full object-cover",o.media)})}),r("div",{className:i("scene-switcher-tab-list","border-lines-primary laptop:gap-4 desktop:gap-4 lg-desktop:gap-4 flex border-t",o.tabList),children:a.map((t,e)=>n("div",{ref:f=>{w.current[e]=f},className:i("scene-switcher-tab-item","desktop:pt-6 -mt-px flex-1 cursor-pointer border-t-2 pt-4 transition-colors",l===e?"border-info-primary border-t-4":"hover:border-lines-primary border-transparent",o.tabItem),onClick:()=>T(e),role:"button","aria-selected":l===e,children:[r(y,{className:i("scene-switcher-tab-title line-clamp-2",l===e?"text-info-primary":"text-info-tertiary",t.title),size:3,as:"h3",html:t.title}),t.description&&r(g,{className:i("desktop:text-[16px] lg-desktop:text-[18px] line-clamp-2 text-[14px]",l===e?"text-info-primary":"text-info-tertiary"),html:t.description})]},e))})]}),!D&&n("div",{className:i("scene-switcher-container","laptop:flex laptop:gap-6 desktop:gap-8 lg-desktop:gap-10 hidden","laptop:h-[336px] desktop:h-[448px] lg-desktop:h-[560px]",A==="right"&&"flex-row-reverse",o.container),children:[r("div",{className:i("scene-switcher-tab-list","laptop:w-[320px] desktop:w-[400px] lg-desktop:w-[544px] flex items-center",o.tabList),children:r("div",{className:"flex max-h-full w-full flex-col overflow-y-auto",children:a.map((t,e)=>n(s.Fragment,{children:[e>0&&r("div",{className:"border-lines-primary h-8 shrink-0 border-l-4"}),n("div",{ref:f=>{w.current[e]=f},className:i("scene-switcher-tab-item","shrink-0 cursor-pointer border-l-4 pl-5",l===e?"border-info-primary border-l-[6px]":"border-lines-primary hover:border-info-tertiary",o.tabItem),onClick:()=>T(e),role:"button","aria-selected":l===e,children:[r(y,{className:i("scene-switcher-tab-title desktop:line-clamp-3 line-clamp-2",l===e?"text-info-primary":"text-info-tertiary",t.title),size:3,as:"h3",html:t.title}),t.description&&r(g,{className:i("desktop:text-[16px] lg-desktop:text-[18px] line-clamp-2 text-[14px]",l===e?"text-info-primary":"text-info-tertiary hidden"),html:t.description})]})]},e))})}),r("div",{className:i("scene-switcher-media-wrapper","rounded-box flex-1 overflow-hidden",o.mediaWrapper),children:v&&r(V,{...N(v.media),className:i("scene-switcher-media","rounded-box size-full h-full overflow-visible object-cover",o.media)})})]})]})});E.displayName="MediaSceneSwitcherV2";var te=_(E);export{te as default};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/biz-components/MediaSceneSwitcherV2/index.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Swiper, SwiperSlide } from 'swiper/react'\nimport { FreeMode, Mousewheel, Autoplay } from 'swiper/modules'\nimport type { Swiper as SwiperType } from 'swiper'\nimport { useMediaQuery } from 'react-responsive'\nimport { cn } from '../../helpers/index.js'\nimport type { Media as MediaType, Theme } from '../../types/props.js'\nimport { Heading, Text } from '../../components/index.js'\nimport { withLayout } from '../../shared/Styles.js'\nimport Media from '../Media/index.js'\n\nexport type MediaSceneSwitcherV2SemanticName =\n | 'root'\n | 'header'\n | 'title'\n | 'subtitle'\n | 'container'\n | 'tabList'\n | 'tabItem'\n | 'tabTitle'\n | 'tabDescription'\n | 'mediaWrapper'\n | 'media'\n | 'swiper'\n | 'slide'\n | 'slideMedia'\n | 'slideContent'\n\n/**\n * \u573A\u666F\u9879\u6570\u636E\u63A5\u53E3\n */\nexport interface MediaSceneSwitcherV2Item {\n /** \u573A\u666F\u6807\u9898 */\n title: string\n /** \u573A\u666F\u63CF\u8FF0 */\n description?: string\n /** \u573A\u666F\u5A92\u4F53\uFF08\u56FE\u7247/\u89C6\u9891\uFF09 */\n media: {\n mobile?: MediaType\n tablet?: MediaType\n laptop?: MediaType\n desktop?: MediaType\n lgDesktop?: MediaType\n }\n}\n\n/**\n * \u5E03\u5C40\u6A21\u5F0F\n * - left: \u5DE6\u6587\u53F3\u56FE\uFF08laptop+ \u9ED8\u8BA4\uFF09\n * - right: \u5DE6\u56FE\u53F3\u6587\n * - top: \u4E0A\u56FE\u4E0B\u6587\uFF08swiper \u5361\u7247\u6A21\u5F0F\uFF09\n */\nexport type MediaSceneSwitcherV2Layout = 'left' | 'right' | 'top'\n\n/**\n * MediaSceneSwitcherV2 \u4E1A\u52A1\u7EC4\u4EF6\u6570\u636E\u63A5\u53E3\n */\nexport interface MediaSceneSwitcherV2Data {\n /** \u4E3B\u9898 */\n theme?: Theme\n /** \u4E3B\u6807\u9898 */\n title?: string\n /** \u526F\u6807\u9898 */\n subtitle?: string\n /** \u573A\u666F\u5217\u8868 */\n items: MediaSceneSwitcherV2Item[]\n /** \u9ED8\u8BA4\u9009\u4E2D\u7684\u573A\u666F\u7D22\u5F15 */\n defaultActiveIndex?: number\n /** \u5E03\u5C40\u6A21\u5F0F\uFF0C\u9ED8\u8BA4 text-left */\n layout?: MediaSceneSwitcherV2Layout\n /** \u662F\u5426\u5F00\u542F\u81EA\u52A8\u8F6E\u64AD\uFF0C\u9ED8\u8BA4 true */\n autoplay?: boolean\n /** \u81EA\u52A8\u8F6E\u64AD\u95F4\u9694\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09\uFF0C\u9ED8\u8BA4 3000 */\n autoplayDelay?: number\n}\n\nexport interface MediaSceneSwitcherV2Props extends React.HTMLAttributes<HTMLDivElement> {\n /** \u4E1A\u52A1\u6570\u636E */\n data: MediaSceneSwitcherV2Data\n /** \u8BED\u4E49\u5316\u7C7B\u540D\u8986\u76D6 */\n classNames?: Partial<Record<MediaSceneSwitcherV2SemanticName, string>>\n /** \u573A\u666F\u5207\u6362\u56DE\u8C03 */\n onSceneChange?: (index: number, scene: MediaSceneSwitcherV2Item) => void\n}\n\nconst toMediaProps = (media: MediaSceneSwitcherV2Item['media']) => ({\n pcImage: media.lgDesktop,\n desktopImage: media.desktop,\n laptopImage: media.laptop,\n padImage: media.tablet,\n mobileImage: media.mobile,\n})\n\n/**\n * MediaSceneSwitcherV2 - \u591A\u573A\u666F\u5207\u6362\u7EC4\u4EF6\n *\n * @description \u7528\u4E8E\u5C55\u793A\u591A\u4E2A\u573A\u666F\u7684\u5207\u6362\u7EC4\u4EF6\uFF0C\u652F\u6301\u54CD\u5E94\u5F0F\u5E03\u5C40\uFF1A\n * - mobile/tablet: \u6A2A\u5411\u6ED1\u52A8\u5361\u7247\u5E03\u5C40\n * - laptop+: \u5DE6\u6587\u53F3\u56FE / \u5DE6\u56FE\u53F3\u6587\u5E03\u5C40\n */\nconst DEFAULT_AUTOPLAY_DELAY = 3000\n\nconst MediaSceneSwitcherV2 = React.forwardRef<HTMLDivElement, MediaSceneSwitcherV2Props>(\n ({ className, classNames = {}, data, onSceneChange, ...props }, ref) => {\n const {\n title,\n subtitle,\n items: scenes,\n defaultActiveIndex = 0,\n layout = 'left',\n autoplay = true,\n autoplayDelay = DEFAULT_AUTOPLAY_DELAY,\n } = data\n const [activeIndex, setActiveIndex] = React.useState(defaultActiveIndex)\n const swiperRef = React.useRef<SwiperType | null>(null)\n const intervalRef = React.useRef<number>(0)\n const tabRefs = React.useRef<(HTMLDivElement | null)[]>([])\n\n // \u5224\u65AD\u662F\u5426\u662F\u684C\u9762\u7AEF\n const isLaptopOrLarger = useMediaQuery({ minWidth: 1025 })\n\n // \u684C\u9762\u7AEF\u81EA\u52A8\u8F6E\u64AD\uFF08\u53EA\u5728 laptop+ \u751F\u6548\uFF0C\u624B\u673A\u7AEF\u7531 Swiper \u7684 onSlideChange \u540C\u6B65\uFF09\n React.useEffect(() => {\n if (!autoplay || scenes.length <= 1 || !isLaptopOrLarger) return\n\n const startAutoplay = () => {\n intervalRef.current = window.setInterval(() => {\n setActiveIndex(prev => (prev + 1) % scenes.length)\n }, autoplayDelay)\n }\n\n startAutoplay()\n\n return () => {\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current)\n }\n }\n }, [autoplay, autoplayDelay, scenes.length, isLaptopOrLarger])\n\n // \u5F53 activeIndex \u53D8\u5316\u65F6\u81EA\u52A8\u6EDA\u52A8\u5230\u5BF9\u5E94\u7684 tab\uFF08\u4EC5\u5F53\u7236\u5BB9\u5668\u53EF\u6EDA\u52A8\u65F6\uFF09\n React.useEffect(() => {\n if (!isLaptopOrLarger || !tabRefs.current[activeIndex]) return\n\n const tabElement = tabRefs.current[activeIndex]\n const parentContainer = tabElement?.parentElement\n\n // \u68C0\u67E5\u7236\u5BB9\u5668\u662F\u5426\u53EF\u6EDA\u52A8\n if (!parentContainer || parentContainer.scrollHeight <= parentContainer.clientHeight) return\n\n // \u4F7F\u7528 requestAnimationFrame \u907F\u514D\u963B\u585E\u4E3B\u7EBF\u7A0B\n const rafId = requestAnimationFrame(() => {\n const containerRect = parentContainer.getBoundingClientRect()\n const tabRect = tabElement.getBoundingClientRect()\n\n // \u68C0\u67E5\u5143\u7D20\u662F\u5426\u5DF2\u5728\u53EF\u89C6\u533A\u57DF\u5185\n const isVisible = tabRect.top >= containerRect.top && tabRect.bottom <= containerRect.bottom\n\n // \u5982\u679C\u5DF2\u7ECF\u53EF\u89C1\uFF0C\u4E0D\u9700\u8981\u6EDA\u52A8\n if (isVisible) return\n\n // \u8BA1\u7B97\u6EDA\u52A8\u8DDD\u79BB\uFF0C\u8BA9 tab \u5C3D\u91CF\u5C45\u4E2D\u663E\u793A\n const scrollOffset = tabRect.top - containerRect.top - parentContainer.clientHeight / 2 + tabRect.height / 2\n\n parentContainer.scrollTo({\n top: parentContainer.scrollTop + scrollOffset,\n behavior: 'smooth',\n })\n })\n\n return () => cancelAnimationFrame(rafId)\n }, [activeIndex, isLaptopOrLarger])\n\n const handleSceneClick = React.useCallback(\n (index: number) => {\n setActiveIndex(index)\n onSceneChange?.(index, scenes[index])\n // \u540C\u6B65 swiper \u4F4D\u7F6E\n swiperRef.current?.slideTo(index)\n\n // \u91CD\u7F6E\u81EA\u52A8\u8F6E\u64AD\u8BA1\u65F6\u5668\n if (autoplay && scenes.length > 1) {\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current)\n }\n intervalRef.current = window.setInterval(() => {\n setActiveIndex(prev => (prev + 1) % scenes.length)\n }, autoplayDelay)\n }\n },\n [scenes, onSceneChange, autoplay, autoplayDelay]\n )\n\n const handleSlideChange = React.useCallback(\n (swiper: SwiperType) => {\n // \u4F7F\u7528 realIndex \u4EE5\u6B63\u786E\u5904\u7406 loop \u6A21\u5F0F\n const index = swiper.realIndex\n setActiveIndex(index)\n onSceneChange?.(index, scenes[index])\n },\n [scenes, onSceneChange]\n )\n\n const activeScene = scenes[activeIndex]\n\n const isMediaTop = layout === 'top'\n\n return (\n <div\n ref={ref}\n className={cn('scene-switcher-root', 'text-info-primary w-full', className, classNames.root, {\n 'aiui-dark': data.theme === 'dark',\n })}\n {...props}\n >\n {/* \u6807\u9898\u533A\u57DF */}\n {(title || subtitle) && (\n <div className={cn('scene-switcher-header mb-6', classNames.header)}>\n {title && (\n <Heading as=\"h2\" size={4} html={title} className={cn('scene-switcher-title', classNames.title)} />\n )}\n {subtitle && <Text as=\"p\" size={3} className={cn('', classNames?.subtitle)} html={subtitle} />}\n </div>\n )}\n {/* Mobile/Tablet: \u6A2A\u5411\u6ED1\u52A8\u5361\u7247\u5E03\u5C40 */}\n <div className={cn('scene-switcher-swiper', 'laptop:hidden !overflow-visible', classNames.swiper)}>\n <Swiper\n modules={[FreeMode, Mousewheel, Autoplay]}\n onSwiper={swiper => {\n swiperRef.current = swiper\n }}\n className=\"!overflow-visible\"\n onSlideChange={handleSlideChange}\n slidesPerView=\"auto\"\n spaceBetween={12}\n freeMode={true}\n mousewheel={{ forceToAxis: true }}\n initialSlide={defaultActiveIndex}\n loop={autoplay && scenes.length > 1}\n autoplay={autoplay && scenes.length > 1 ? { delay: autoplayDelay, disableOnInteraction: false } : false}\n breakpoints={{\n 768: { spaceBetween: 16 },\n }}\n >\n {scenes.map((scene, index) => (\n <SwiperSlide key={index} className=\"h-[462px] !w-[296px]\">\n <div\n className={cn('scene-switcher-slide', 'flex cursor-pointer flex-col', classNames.slide)}\n onClick={() => handleSceneClick(index)}\n >\n {/* \u5A92\u4F53 */}\n <div\n className={cn(\n 'scene-switcher-slide-media',\n 'rounded-box relative aspect-[296/320] w-full overflow-hidden',\n classNames.slideMedia\n )}\n >\n <Media\n {...toMediaProps(scene.media)}\n className=\"rounded-t-box size-full overflow-hidden object-cover\"\n />\n </div>\n {/* \u6587\u5B57\u5185\u5BB9 */}\n <div\n className={cn(\n 'scene-switcher-slide-content',\n ' mt-6 border-t pt-4',\n activeIndex === index ? 'border-info-primary border-t-4' : 'border-lines-primary',\n classNames.slideContent\n )}\n >\n <Heading\n className={cn(\n 'scene-switcher-tab-title ',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary',\n scene.title\n )}\n size={3}\n as={'h3'}\n html={scene.title}\n />\n {scene.description && (\n <Text\n className={cn(\n 'desktop:text-[16px] lg-desktop:text-[18px] line-clamp-2 text-[14px]',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary'\n )}\n html={scene.description}\n />\n )}\n </div>\n </div>\n </SwiperSlide>\n ))}\n </Swiper>\n </div>\n\n {/* Laptop+: media-top \u5E03\u5C40 (\u4E0A\u56FE\u4E0B\u6587) */}\n {isMediaTop && (\n <div\n className={cn(\n 'scene-switcher-container',\n 'laptop:flex laptop:flex-col hidden',\n 'laptop:h-[470px] desktop:h-[628px] lg-desktop:h-[746px] desktop:gap-[32px] gap-[16px]',\n classNames.container\n )}\n >\n {/* \u5A92\u4F53\u533A\u57DF - \u663E\u793A\u5F53\u524D\u9009\u4E2D */}\n <div\n className={cn(\n 'scene-switcher-media-wrapper',\n 'rounded-box flex-1 overflow-hidden',\n classNames.mediaWrapper\n )}\n >\n {activeScene && (\n <Media\n {...toMediaProps(activeScene.media)}\n className={cn('scene-switcher-media', 'rounded-box size-full object-cover', classNames.media)}\n />\n )}\n </div>\n\n {/* Tab \u5217\u8868 - \u6A2A\u5411\u6392\u5217 */}\n <div\n className={cn(\n 'scene-switcher-tab-list',\n 'border-lines-primary laptop:gap-4 desktop:gap-4 lg-desktop:gap-4 flex border-t',\n classNames.tabList\n )}\n >\n {scenes.map((scene, index) => (\n <div\n key={index}\n ref={el => {\n tabRefs.current[index] = el\n }}\n className={cn(\n 'scene-switcher-tab-item',\n 'desktop:pt-6 -mt-px flex-1 cursor-pointer border-t-2 pt-4 transition-colors',\n activeIndex === index\n ? 'border-info-primary border-t-4'\n : 'hover:border-lines-primary border-transparent',\n classNames.tabItem\n )}\n onClick={() => handleSceneClick(index)}\n role=\"button\"\n aria-selected={activeIndex === index}\n >\n <Heading\n className={cn(\n 'scene-switcher-tab-title line-clamp-2',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary',\n scene.title\n )}\n size={3}\n as={'h3'}\n html={scene.title}\n />\n {scene.description && (\n <Text\n className={cn(\n 'desktop:text-[16px] lg-desktop:text-[18px] line-clamp-2 text-[14px]',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary'\n )}\n html={scene.description}\n />\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Laptop+: \u5DE6\u6587\u53F3\u56FE / \u5DE6\u56FE\u53F3\u6587\u5E03\u5C40 */}\n {!isMediaTop && (\n <div\n className={cn(\n 'scene-switcher-container',\n 'laptop:flex laptop:gap-6 desktop:gap-8 lg-desktop:gap-10 hidden',\n 'laptop:h-[336px] desktop:h-[448px] lg-desktop:h-[560px]',\n layout === 'right' && 'flex-row-reverse',\n classNames.container\n )}\n >\n {/* Tab \u5217\u8868 - \u5916\u5C42\u5C45\u4E2D */}\n <div\n className={cn(\n 'scene-switcher-tab-list',\n 'laptop:w-[320px] desktop:w-[400px] lg-desktop:w-[544px] flex items-center',\n classNames.tabList\n )}\n >\n {/* \u5185\u5C42\u6EDA\u52A8 */}\n <div className=\"flex max-h-full w-full flex-col overflow-y-auto\">\n {scenes.map((scene, index) => (\n <React.Fragment key={index}>\n {index > 0 && <div className=\"border-lines-primary h-8 shrink-0 border-l-4\" />}\n <div\n ref={el => {\n tabRefs.current[index] = el\n }}\n className={cn(\n 'scene-switcher-tab-item',\n 'shrink-0 cursor-pointer border-l-4 pl-5',\n activeIndex === index\n ? 'border-info-primary border-l-[6px]'\n : 'border-lines-primary hover:border-info-tertiary',\n classNames.tabItem\n )}\n onClick={() => handleSceneClick(index)}\n role=\"button\"\n aria-selected={activeIndex === index}\n >\n <Heading\n className={cn(\n 'scene-switcher-tab-title desktop:line-clamp-3 line-clamp-2',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary',\n scene.title\n )}\n size={3}\n as={'h3'}\n html={scene.title}\n />\n {scene.description && (\n <Text\n className={cn(\n 'desktop:text-[16px] lg-desktop:text-[18px] line-clamp-2 text-[14px]',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary hidden'\n )}\n html={scene.description}\n />\n )}\n </div>\n </React.Fragment>\n ))}\n </div>\n </div>\n\n {/* \u5A92\u4F53\u533A\u57DF */}\n <div\n className={cn(\n 'scene-switcher-media-wrapper',\n 'rounded-box flex-1 overflow-hidden',\n classNames.mediaWrapper\n )}\n >\n {activeScene && (\n <Media\n {...toMediaProps(activeScene.media)}\n className={cn(\n 'scene-switcher-media',\n 'rounded-box size-full h-full overflow-visible object-cover',\n classNames.media\n )}\n />\n )}\n </div>\n </div>\n )}\n </div>\n )\n }\n)\n\nMediaSceneSwitcherV2.displayName = 'MediaSceneSwitcherV2'\nexport default withLayout(MediaSceneSwitcherV2)\n"],
|
|
5
|
-
"mappings": "
|
|
6
|
-
"names": ["jsx", "jsxs", "React", "Swiper", "SwiperSlide", "FreeMode", "Mousewheel", "Autoplay", "useMediaQuery", "cn", "Heading", "Text", "withLayout", "Media", "toMediaProps", "media", "DEFAULT_AUTOPLAY_DELAY", "MediaSceneSwitcherV2", "className", "classNames", "data", "onSceneChange", "props", "ref", "title", "subtitle", "scenes", "defaultActiveIndex", "layout", "autoplay", "autoplayDelay", "activeIndex", "setActiveIndex", "swiperRef", "intervalRef", "tabRefs", "isLaptopOrLarger", "prev", "tabElement", "parentContainer", "rafId", "containerRect", "tabRect", "scrollOffset", "handleSceneClick", "index", "handleSlideChange", "swiper", "activeScene", "isMediaTop", "scene", "el", "MediaSceneSwitcherV2_default"]
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Swiper, SwiperSlide } from 'swiper/react'\nimport { FreeMode, Mousewheel, Autoplay } from 'swiper/modules'\nimport type { Swiper as SwiperType } from 'swiper'\nimport { useMediaQuery } from 'react-responsive'\nimport { cn } from '../../helpers/index.js'\nimport type { Media as MediaType, Theme } from '../../types/props.js'\nimport { Heading, Text } from '../../components/index.js'\nimport { withLayout } from '../../shared/Styles.js'\nimport Media from '../Media/index.js'\n\nexport type MediaSceneSwitcherV2SemanticName =\n | 'root'\n | 'header'\n | 'title'\n | 'subtitle'\n | 'container'\n | 'tabList'\n | 'tabItem'\n | 'tabTitle'\n | 'tabDescription'\n | 'mediaWrapper'\n | 'media'\n | 'swiper'\n | 'slide'\n | 'slideMedia'\n | 'slideContent'\n\n/**\n * \u573A\u666F\u9879\u6570\u636E\u63A5\u53E3\n */\nexport interface MediaSceneSwitcherV2Item {\n /** \u573A\u666F\u6807\u9898 */\n title: string\n /** \u573A\u666F\u63CF\u8FF0 */\n description?: string\n /** \u573A\u666F\u5A92\u4F53\uFF08\u56FE\u7247/\u89C6\u9891\uFF09 */\n media: {\n mobile?: MediaType\n tablet?: MediaType\n laptop?: MediaType\n desktop?: MediaType\n lgDesktop?: MediaType\n }\n}\n\n/**\n * \u5E03\u5C40\u6A21\u5F0F\n * - left: \u5DE6\u6587\u53F3\u56FE\uFF08laptop+ \u9ED8\u8BA4\uFF09\n * - right: \u5DE6\u56FE\u53F3\u6587\n * - top: \u4E0A\u56FE\u4E0B\u6587\uFF08swiper \u5361\u7247\u6A21\u5F0F\uFF09\n */\nexport type MediaSceneSwitcherV2Layout = 'left' | 'right' | 'top'\n\n/**\n * MediaSceneSwitcherV2 \u4E1A\u52A1\u7EC4\u4EF6\u6570\u636E\u63A5\u53E3\n */\nexport interface MediaSceneSwitcherV2Data {\n /** \u4E3B\u9898 */\n theme?: Theme\n /** \u4E3B\u6807\u9898 */\n title?: string\n /** \u526F\u6807\u9898 */\n subtitle?: string\n /** \u573A\u666F\u5217\u8868 */\n items: MediaSceneSwitcherV2Item[]\n /** \u9ED8\u8BA4\u9009\u4E2D\u7684\u573A\u666F\u7D22\u5F15 */\n defaultActiveIndex?: number\n /** \u5E03\u5C40\u6A21\u5F0F\uFF0C\u9ED8\u8BA4 text-left */\n layout?: MediaSceneSwitcherV2Layout\n /** \u662F\u5426\u5F00\u542F\u81EA\u52A8\u8F6E\u64AD\uFF0C\u9ED8\u8BA4 true */\n autoplay?: boolean\n /** \u81EA\u52A8\u8F6E\u64AD\u95F4\u9694\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09\uFF0C\u9ED8\u8BA4 3000 */\n autoplayDelay?: number\n}\n\nexport interface MediaSceneSwitcherV2Props extends React.HTMLAttributes<HTMLDivElement> {\n /** \u4E1A\u52A1\u6570\u636E */\n data: MediaSceneSwitcherV2Data\n /** \u8BED\u4E49\u5316\u7C7B\u540D\u8986\u76D6 */\n classNames?: Partial<Record<MediaSceneSwitcherV2SemanticName, string>>\n /** \u573A\u666F\u5207\u6362\u56DE\u8C03 */\n onSceneChange?: (index: number, scene: MediaSceneSwitcherV2Item) => void\n}\n\nconst toMediaProps = (media: MediaSceneSwitcherV2Item['media']) => ({\n pcImage: media.lgDesktop,\n desktopImage: media.desktop,\n laptopImage: media.laptop,\n padImage: media.tablet,\n mobileImage: media.mobile,\n})\n\n/**\n * MediaSceneSwitcherV2 - \u591A\u573A\u666F\u5207\u6362\u7EC4\u4EF6\n *\n * @description \u7528\u4E8E\u5C55\u793A\u591A\u4E2A\u573A\u666F\u7684\u5207\u6362\u7EC4\u4EF6\uFF0C\u652F\u6301\u54CD\u5E94\u5F0F\u5E03\u5C40\uFF1A\n * - mobile/tablet: \u6A2A\u5411\u6ED1\u52A8\u5361\u7247\u5E03\u5C40\n * - laptop+: \u5DE6\u6587\u53F3\u56FE / \u5DE6\u56FE\u53F3\u6587\u5E03\u5C40\n */\nconst DEFAULT_AUTOPLAY_DELAY = 3000\n\nconst MediaSceneSwitcherV2 = React.forwardRef<HTMLDivElement, MediaSceneSwitcherV2Props>(\n ({ className, classNames = {}, data, onSceneChange, ...props }, ref) => {\n const {\n title,\n subtitle,\n items: scenes,\n defaultActiveIndex = 0,\n layout = 'left',\n autoplay = true,\n autoplayDelay = DEFAULT_AUTOPLAY_DELAY,\n } = data\n const [activeIndex, setActiveIndex] = React.useState(defaultActiveIndex)\n const swiperRef = React.useRef<SwiperType | null>(null)\n const intervalRef = React.useRef<number>(0)\n const tabRefs = React.useRef<(HTMLDivElement | null)[]>([])\n const isClickTriggered = React.useRef(false)\n\n // \u5224\u65AD\u662F\u5426\u662F\u684C\u9762\u7AEF\n const isLaptopOrLarger = useMediaQuery({ minWidth: 1025 })\n\n // \u684C\u9762\u7AEF\u81EA\u52A8\u8F6E\u64AD\uFF08\u53EA\u5728 laptop+ \u751F\u6548\uFF0C\u624B\u673A\u7AEF\u7531 Swiper \u7684 onSlideChange \u540C\u6B65\uFF09\n React.useEffect(() => {\n if (!autoplay || scenes.length <= 1 || !isLaptopOrLarger) return\n\n const startAutoplay = () => {\n intervalRef.current = window.setInterval(() => {\n setActiveIndex(prev => (prev + 1) % scenes.length)\n }, autoplayDelay)\n }\n\n startAutoplay()\n\n return () => {\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current)\n }\n }\n }, [autoplay, autoplayDelay, scenes.length, isLaptopOrLarger])\n\n // \u5F53 activeIndex \u53D8\u5316\u65F6\u81EA\u52A8\u6EDA\u52A8\u5230\u5BF9\u5E94\u7684 tab\uFF08\u4EC5\u5F53\u7236\u5BB9\u5668\u53EF\u6EDA\u52A8\u65F6\uFF09\n React.useEffect(() => {\n if (!isLaptopOrLarger || !tabRefs.current[activeIndex]) return\n\n const tabElement = tabRefs.current[activeIndex]\n const parentContainer = tabElement?.parentElement\n\n // \u68C0\u67E5\u7236\u5BB9\u5668\u662F\u5426\u53EF\u6EDA\u52A8\n if (!parentContainer || parentContainer.scrollHeight <= parentContainer.clientHeight) return\n\n // \u4F7F\u7528 requestAnimationFrame \u907F\u514D\u963B\u585E\u4E3B\u7EBF\u7A0B\n const rafId = requestAnimationFrame(() => {\n const containerRect = parentContainer.getBoundingClientRect()\n const tabRect = tabElement.getBoundingClientRect()\n\n // \u68C0\u67E5\u5143\u7D20\u662F\u5426\u5DF2\u5728\u53EF\u89C6\u533A\u57DF\u5185\n const isVisible = tabRect.top >= containerRect.top && tabRect.bottom <= containerRect.bottom\n\n // \u5982\u679C\u5DF2\u7ECF\u53EF\u89C1\uFF0C\u4E0D\u9700\u8981\u6EDA\u52A8\n if (isVisible) return\n\n // \u8BA1\u7B97\u6EDA\u52A8\u8DDD\u79BB\uFF0C\u8BA9 tab \u5C3D\u91CF\u5C45\u4E2D\u663E\u793A\n const scrollOffset = tabRect.top - containerRect.top - parentContainer.clientHeight / 2 + tabRect.height / 2\n\n parentContainer.scrollTo({\n top: parentContainer.scrollTop + scrollOffset,\n behavior: 'smooth',\n })\n })\n\n return () => cancelAnimationFrame(rafId)\n }, [activeIndex, isLaptopOrLarger])\n\n const handleSceneClick = React.useCallback(\n (index: number) => {\n setActiveIndex(index)\n isClickTriggered.current = true\n onSceneChange?.(index, scenes[index])\n swiperRef.current?.slideTo(index)\n\n // \u91CD\u7F6E\u81EA\u52A8\u8F6E\u64AD\u8BA1\u65F6\u5668\n if (autoplay && scenes.length > 1) {\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current)\n }\n intervalRef.current = window.setInterval(() => {\n setActiveIndex(prev => (prev + 1) % scenes.length)\n }, autoplayDelay)\n }\n },\n [scenes, onSceneChange, autoplay, autoplayDelay]\n )\n\n const handleSlideChange = React.useCallback(\n (swiper: SwiperType) => {\n if (isClickTriggered.current) {\n isClickTriggered.current = false\n return\n }\n const index = swiper.realIndex\n setActiveIndex(index)\n onSceneChange?.(index, scenes[index])\n },\n [scenes, onSceneChange]\n )\n\n const activeScene = scenes[activeIndex]\n\n const isMediaTop = layout === 'top'\n\n return (\n <div\n ref={ref}\n className={cn('scene-switcher-root', 'text-info-primary w-full', className, classNames.root, {\n 'aiui-dark': data.theme === 'dark',\n })}\n {...props}\n >\n {/* \u6807\u9898\u533A\u57DF */}\n {(title || subtitle) && (\n <div className={cn('scene-switcher-header mb-6', classNames.header)}>\n {title && (\n <Heading as=\"h2\" size={4} html={title} className={cn('scene-switcher-title', classNames.title)} />\n )}\n {subtitle && <Text as=\"p\" size={3} className={cn('', classNames?.subtitle)} html={subtitle} />}\n </div>\n )}\n {/* Mobile/Tablet: \u6A2A\u5411\u6ED1\u52A8\u5361\u7247\u5E03\u5C40 */}\n <div className={cn('scene-switcher-swiper', 'laptop:hidden !overflow-visible', classNames.swiper)}>\n <Swiper\n modules={[FreeMode, Mousewheel, Autoplay]}\n onSwiper={swiper => {\n swiperRef.current = swiper\n }}\n className=\"!overflow-visible\"\n onSlideChange={handleSlideChange}\n slidesPerView=\"auto\"\n spaceBetween={12}\n freeMode={true}\n mousewheel={{ forceToAxis: true }}\n initialSlide={defaultActiveIndex}\n loop={autoplay && scenes.length > 1}\n autoplay={autoplay && scenes.length > 1 ? { delay: autoplayDelay, disableOnInteraction: false } : false}\n breakpoints={{\n 768: { spaceBetween: 16 },\n }}\n >\n {scenes.map((scene, index) => (\n <SwiperSlide key={index} className=\"h-[462px] !w-[296px]\">\n <div\n className={cn('scene-switcher-slide', 'flex cursor-pointer flex-col', classNames.slide)}\n onClick={() => handleSceneClick(index)}\n >\n {/* \u5A92\u4F53 */}\n <div\n className={cn(\n 'scene-switcher-slide-media',\n 'rounded-box relative aspect-[296/320] w-full overflow-hidden',\n classNames.slideMedia\n )}\n >\n <Media\n {...toMediaProps(scene.media)}\n className=\"rounded-t-box size-full overflow-hidden object-cover\"\n />\n </div>\n {/* \u6587\u5B57\u5185\u5BB9 */}\n <div\n className={cn(\n 'scene-switcher-slide-content',\n ' mt-6 border-t pt-4',\n activeIndex === index ? 'border-info-primary border-t-4' : 'border-lines-primary',\n classNames.slideContent\n )}\n >\n <Heading\n className={cn(\n 'scene-switcher-tab-title ',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary',\n scene.title\n )}\n size={3}\n as={'h3'}\n html={scene.title}\n />\n {scene.description && (\n <Text\n className={cn(\n 'desktop:text-[16px] lg-desktop:text-[18px] line-clamp-2 text-[14px]',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary'\n )}\n html={scene.description}\n />\n )}\n </div>\n </div>\n </SwiperSlide>\n ))}\n </Swiper>\n </div>\n\n {/* Laptop+: media-top \u5E03\u5C40 (\u4E0A\u56FE\u4E0B\u6587) */}\n {isMediaTop && (\n <div\n className={cn(\n 'scene-switcher-container',\n 'laptop:flex laptop:flex-col hidden',\n 'laptop:h-[470px] desktop:h-[628px] lg-desktop:h-[746px] desktop:gap-[32px] gap-[16px]',\n classNames.container\n )}\n >\n {/* \u5A92\u4F53\u533A\u57DF - \u663E\u793A\u5F53\u524D\u9009\u4E2D */}\n <div\n className={cn(\n 'scene-switcher-media-wrapper',\n 'rounded-box flex-1 overflow-hidden',\n classNames.mediaWrapper\n )}\n >\n {activeScene && (\n <Media\n {...toMediaProps(activeScene.media)}\n className={cn('scene-switcher-media', 'rounded-box size-full object-cover', classNames.media)}\n />\n )}\n </div>\n\n {/* Tab \u5217\u8868 - \u6A2A\u5411\u6392\u5217 */}\n <div\n className={cn(\n 'scene-switcher-tab-list',\n 'border-lines-primary laptop:gap-4 desktop:gap-4 lg-desktop:gap-4 flex border-t',\n classNames.tabList\n )}\n >\n {scenes.map((scene, index) => (\n <div\n key={index}\n ref={el => {\n tabRefs.current[index] = el\n }}\n className={cn(\n 'scene-switcher-tab-item',\n 'desktop:pt-6 -mt-px flex-1 cursor-pointer border-t-2 pt-4 transition-colors',\n activeIndex === index\n ? 'border-info-primary border-t-4'\n : 'hover:border-lines-primary border-transparent',\n classNames.tabItem\n )}\n onClick={() => handleSceneClick(index)}\n role=\"button\"\n aria-selected={activeIndex === index}\n >\n <Heading\n className={cn(\n 'scene-switcher-tab-title line-clamp-2',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary',\n scene.title\n )}\n size={3}\n as={'h3'}\n html={scene.title}\n />\n {scene.description && (\n <Text\n className={cn(\n 'desktop:text-[16px] lg-desktop:text-[18px] line-clamp-2 text-[14px]',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary'\n )}\n html={scene.description}\n />\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Laptop+: \u5DE6\u6587\u53F3\u56FE / \u5DE6\u56FE\u53F3\u6587\u5E03\u5C40 */}\n {!isMediaTop && (\n <div\n className={cn(\n 'scene-switcher-container',\n 'laptop:flex laptop:gap-6 desktop:gap-8 lg-desktop:gap-10 hidden',\n 'laptop:h-[336px] desktop:h-[448px] lg-desktop:h-[560px]',\n layout === 'right' && 'flex-row-reverse',\n classNames.container\n )}\n >\n {/* Tab \u5217\u8868 - \u5916\u5C42\u5C45\u4E2D */}\n <div\n className={cn(\n 'scene-switcher-tab-list',\n 'laptop:w-[320px] desktop:w-[400px] lg-desktop:w-[544px] flex items-center',\n classNames.tabList\n )}\n >\n {/* \u5185\u5C42\u6EDA\u52A8 */}\n <div className=\"flex max-h-full w-full flex-col overflow-y-auto\">\n {scenes.map((scene, index) => (\n <React.Fragment key={index}>\n {index > 0 && <div className=\"border-lines-primary h-8 shrink-0 border-l-4\" />}\n <div\n ref={el => {\n tabRefs.current[index] = el\n }}\n className={cn(\n 'scene-switcher-tab-item',\n 'shrink-0 cursor-pointer border-l-4 pl-5',\n activeIndex === index\n ? 'border-info-primary border-l-[6px]'\n : 'border-lines-primary hover:border-info-tertiary',\n classNames.tabItem\n )}\n onClick={() => handleSceneClick(index)}\n role=\"button\"\n aria-selected={activeIndex === index}\n >\n <Heading\n className={cn(\n 'scene-switcher-tab-title desktop:line-clamp-3 line-clamp-2',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary',\n scene.title\n )}\n size={3}\n as={'h3'}\n html={scene.title}\n />\n {scene.description && (\n <Text\n className={cn(\n 'desktop:text-[16px] lg-desktop:text-[18px] line-clamp-2 text-[14px]',\n activeIndex === index ? 'text-info-primary' : 'text-info-tertiary hidden'\n )}\n html={scene.description}\n />\n )}\n </div>\n </React.Fragment>\n ))}\n </div>\n </div>\n\n {/* \u5A92\u4F53\u533A\u57DF */}\n <div\n className={cn(\n 'scene-switcher-media-wrapper',\n 'rounded-box flex-1 overflow-hidden',\n classNames.mediaWrapper\n )}\n >\n {activeScene && (\n <Media\n {...toMediaProps(activeScene.media)}\n className={cn(\n 'scene-switcher-media',\n 'rounded-box size-full h-full overflow-visible object-cover',\n classNames.media\n )}\n />\n )}\n </div>\n </div>\n )}\n </div>\n )\n }\n)\n\nMediaSceneSwitcherV2.displayName = 'MediaSceneSwitcherV2'\nexport default withLayout(MediaSceneSwitcherV2)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["jsx", "jsxs", "React", "Swiper", "SwiperSlide", "FreeMode", "Mousewheel", "Autoplay", "useMediaQuery", "cn", "Heading", "Text", "withLayout", "Media", "toMediaProps", "media", "DEFAULT_AUTOPLAY_DELAY", "MediaSceneSwitcherV2", "className", "classNames", "data", "onSceneChange", "props", "ref", "title", "subtitle", "scenes", "defaultActiveIndex", "layout", "autoplay", "autoplayDelay", "activeIndex", "setActiveIndex", "swiperRef", "intervalRef", "tabRefs", "isClickTriggered", "isLaptopOrLarger", "prev", "tabElement", "parentContainer", "rafId", "containerRect", "tabRect", "scrollOffset", "handleSceneClick", "index", "handleSlideChange", "swiper", "activeScene", "isMediaTop", "scene", "el", "MediaSceneSwitcherV2_default"]
|
|
7
7
|
}
|