@anker-in/headless-ui 1.1.99 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/biz-components/BrandEquity/BrandEquity.js +1 -1
- package/dist/cjs/biz-components/BrandEquity/BrandEquity.js.map +2 -2
- package/dist/cjs/biz-components/Faq/Faq.js +1 -1
- package/dist/cjs/biz-components/Faq/Faq.js.map +2 -2
- package/dist/cjs/biz-components/Faq/types.d.ts +1 -0
- package/dist/cjs/biz-components/Faq/types.js +1 -1
- package/dist/cjs/biz-components/Faq/types.js.map +1 -1
- 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/MediaSceneSwitcherV2/index.d.ts +6 -6
- package/dist/cjs/biz-components/MediaSceneSwitcherV2/index.js +1 -1
- package/dist/cjs/biz-components/MediaSceneSwitcherV2/index.js.map +3 -3
- package/dist/cjs/biz-components/SceneShelfV2/index.js +1 -1
- package/dist/cjs/biz-components/SceneShelfV2/index.js.map +2 -2
- package/dist/esm/biz-components/BrandEquity/BrandEquity.js +1 -1
- package/dist/esm/biz-components/BrandEquity/BrandEquity.js.map +2 -2
- package/dist/esm/biz-components/Faq/Faq.js +1 -1
- package/dist/esm/biz-components/Faq/Faq.js.map +2 -2
- package/dist/esm/biz-components/Faq/types.d.ts +1 -0
- 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/MediaSceneSwitcherV2/index.d.ts +6 -6
- package/dist/esm/biz-components/MediaSceneSwitcherV2/index.js +1 -1
- package/dist/esm/biz-components/MediaSceneSwitcherV2/index.js.map +3 -3
- package/dist/esm/biz-components/SceneShelfV2/index.js +1 -1
- package/dist/esm/biz-components/SceneShelfV2/index.js.map +2 -2
- package/package.json +1 -1
- package/style.css +0 -3
|
@@ -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 Picture from '../../components/picture.js'\nimport type { Media, Theme } from '../../types/props.js'\nimport { Heading, Text } from '../../components/index.js'\nimport { withLayout } from '../../shared/Styles.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?: Media\n tablet?: Media\n laptop?: Media\n desktop?: Media\n lgDesktop?: Media\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\n/**\n * \u54CD\u5E94\u5F0F\u5A92\u4F53\u7C7B\u578B\n */\ntype ResponsiveMedia = MediaSceneSwitcherV2Item['media']\n\n/** \u65AD\u70B9\u914D\u7F6E */\nconst BREAKPOINTS: { key: keyof ResponsiveMedia; width: number }[] = [\n { key: 'lgDesktop', width: 1920 },\n { key: 'desktop', width: 1440 },\n { key: 'laptop', width: 1024 },\n { key: 'tablet', width: 768 },\n { key: 'mobile', width: 390 },\n]\n\n/**\n * \u68C0\u67E5\u5F53\u524D\u65AD\u70B9\u7684\u5A92\u4F53\u662F\u5426\u4E3A\u89C6\u9891\n */\nconst isCurrentMediaVideo = (media: ResponsiveMedia, currentBreakpoint: keyof ResponsiveMedia): boolean => {\n return media[currentBreakpoint]?.mimeType === 'video/mp4'\n}\n\n/**\n * \u5C06\u54CD\u5E94\u5F0F\u5A92\u4F53\u5BF9\u8C61\u8F6C\u4E3A Picture source \u683C\u5F0F\u5B57\u7B26\u4E32\n * \u683C\u5F0F: \"url1 1920, url2 1440, url3 1024\"\n */\nconst getImageSource = (media: ResponsiveMedia): string => {\n const sources = BREAKPOINTS.filter(({ key }) => media[key]?.url && media[key]?.mimeType !== 'video/mp4').map(\n ({ key, width }) => `${media[key]!.url} ${width}`\n )\n\n return sources.join(', ')\n}\n\n/**\n * \u83B7\u53D6 alt \u6587\u672C\n */\nconst getMediaAlt = (media: ResponsiveMedia, fallback: string): string => {\n for (const { key } of BREAKPOINTS) {\n if (media[key]?.alt) return media[key]!.alt\n }\n return fallback\n}\n\n/**\n * \u5A92\u4F53\u6E32\u67D3\u7EC4\u4EF6 - \u652F\u6301\u56FE\u7247\u548C\u89C6\u9891\uFF0C\u6839\u636E\u65AD\u70B9\u6E32\u67D3\u5BF9\u5E94\u8D44\u6E90\n */\nconst MediaRenderer: React.FC<{\n media: ResponsiveMedia\n alt: string\n className?: string\n}> = ({ media, alt, className }) => {\n const isLgDesktop = useMediaQuery({ minWidth: 1920 })\n const isDesktop = useMediaQuery({ minWidth: 1440, maxWidth: 1919 })\n const isLaptop = useMediaQuery({ minWidth: 1025, maxWidth: 1439 })\n const isTablet = useMediaQuery({ minWidth: 768, maxWidth: 1024 })\n\n // \u83B7\u53D6\u5F53\u524D\u65AD\u70B9 key\n const currentBreakpoint = React.useMemo((): keyof ResponsiveMedia => {\n if (isLgDesktop && media.lgDesktop?.url) return 'lgDesktop'\n if (isDesktop && media.desktop?.url) return 'desktop'\n if (isLaptop && media.laptop?.url) return 'laptop'\n if (isTablet && media.tablet?.url) return 'tablet'\n if (media.mobile?.url) return 'mobile'\n\n // fallback: \u8FD4\u56DE\u7B2C\u4E00\u4E2A\u6709\u6548\u7684\u65AD\u70B9\n for (const { key } of BREAKPOINTS) {\n if (media[key]?.url) return key\n }\n return 'desktop'\n }, [isLgDesktop, isDesktop, isLaptop, isTablet, media])\n\n const currentMedia = media[currentBreakpoint]\n\n if (!currentMedia?.url) return null\n\n // \u5F53\u524D\u65AD\u70B9\u662F\u89C6\u9891\u5219\u6E32\u67D3\u89C6\u9891\n if (isCurrentMediaVideo(media, currentBreakpoint)) {\n return <video src={currentMedia.url} className={className} autoPlay loop muted playsInline />\n }\n\n // \u56FE\u7247\uFF1A\u4F7F\u7528 Picture \u7EC4\u4EF6\u7684\u54CD\u5E94\u5F0F\u683C\u5F0F\n const imageSource = getImageSource(media)\n\n return (\n <Picture\n source={imageSource || currentMedia.url}\n alt={getMediaAlt(media, alt)}\n className={className}\n imgClassName=\"size-full object-cover\"\n />\n )\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 <MediaRenderer\n media={scene.media}\n alt={scene.title}\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 <MediaRenderer\n media={activeScene.media}\n alt={activeScene.title}\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 <MediaRenderer\n media={activeScene.media}\n alt={activeScene.title}\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,
|
|
6
|
-
"names": ["MediaSceneSwitcherV2_exports", "__export", "MediaSceneSwitcherV2_default", "__toCommonJS", "import_jsx_runtime", "React", "import_react", "import_modules", "import_react_responsive", "import_helpers", "
|
|
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": "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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", "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 strict";"use client";var te=Object.create;var H=Object.defineProperty;var ie=Object.getOwnPropertyDescriptor;var oe=Object.getOwnPropertyNames;var ae=Object.getPrototypeOf,ne=Object.prototype.hasOwnProperty;var re=(e,i)=>{for(var a in i)H(e,a,{get:i[a],enumerable:!0})},G=(e,i,a,u)=>{if(i&&typeof i=="object"||typeof i=="function")for(let m of oe(i))!ne.call(e,m)&&m!==a&&H(e,m,{get:()=>i[m],enumerable:!(u=ie(i,m))||u.enumerable});return e};var U=(e,i,a)=>(a=e!=null?te(ae(e)):{},G(i||!e||!e.__esModule?H(a,"default",{value:e,enumerable:!0}):a,e)),se=e=>G(H({},"__esModule",{value:!0}),e);var ue={};re(ue,{SceneShelfV2ProductCard:()=>V,default:()=>me});module.exports=se(ue);var t=require("react/jsx-runtime"),r=U(require("react")),n=require("../../helpers/index.js"),l=require("../../components/index.js"),K=U(require("../Media/index.js")),j=require("swiper/react"),$=require("swiper/modules"),ge=require("swiper/css"),ve=require("swiper/css/navigation"),Q=require("../../shared/Styles.js"),q=require("../../hooks/useGridRowCount.js"),J=require("../../hooks/useExposure.js"),X=require("../../hooks/useViewItemList.js"),Y=require("../../shared/trackUrlRef.js"),F=require("../AiuiProvider/index.js"),T=require("../../shared/track.js");const le="shelf",ce="scene_shelf_v2",de=()=>(0,t.jsx)("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:(0,t.jsx)("path",{d:"M8 5.14v13.72L19 12 8 5.14z",fill:"white"})}),pe=()=>(0,t.jsxs)("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:[(0,t.jsx)("rect",{x:"6",y:"5",width:"4",height:"14",rx:"1",fill:"white"}),(0,t.jsx)("rect",{x:"14",y:"5",width:"4",height:"14",rx:"1",fill:"white"})]}),V=r.memo(({product:e,isShowTag:i=!0,onImageClick:a,onLearnMore:u,onShopNow:m,onAddToCart:S,secondaryButtonText:h,secondaryButtonFun:x,primaryButtonText:b,primaryButtonFun:P,classNames:c,className:s,theme:N,index:d})=>{const{locale:B="us",trackingData:L}=(0,F.useAiuiContext)(),[M,z]=r.useState(!1),[_,I]=r.useState(!1),f=L?.pageGroup,y=r.useCallback(async(p,k)=>{if(!p)return;const C=k==="primary"?z:I;C(!0);try{switch(p){case"buyNow":await m?.(e);break;case"addCart":await S?.(e);break;case"learnMore":await u?.(e?.href??"");break;default:break}}finally{C(!1)}},[u,m,S,e]),R=r.useCallback(()=>y(P,"primary"),[y,P]),E=r.useCallback(()=>y(x,"secondary"),[y,x]),g=r.useCallback(p=>{!e.href&&a&&p.preventDefault(),a?.(e),(0,T.gaTrack)({event:"ga4Event",event_name:"select_item",item_list_name:"Scene_Shelf_2_Products",page_group:f,items:[{item_id:e.sku,item_name:e.custom_name||e.title,item_variant:e.variantId,price:e.currentPrice,index:d}]})},[d,a,f,e]);return(0,t.jsxs)("div",{className:(0,n.cn)("scene-shelf-v2-product-card rounded-box bg-container-secondary-1 tablet:px-6 desktop:pb-6 desktop:px-6 box-border flex h-full flex-col items-center justify-between gap-3 overflow-hidden px-2 py-4",s,c?.productCard,{"bg-container-secondary-0":N==="dark"}),children:[e.href?(0,t.jsx)("a",{href:(0,n.getLocalizedPath)((0,Y.trackUrlRef)(e.href,f+"_"+le+"_"+ce),B),onClick:g,className:(0,n.cn)("scene-shelf-v2-product-card-image desktop:size-[196px] tablet:size-[140px] lg-desktop:size-[196px] flex size-[128px] shrink-0 items-center justify-center transition-opacity hover:opacity-80",c?.productCardImage),"aria-label":`View ${e.title}`,children:(0,t.jsx)(l.Picture,{source:e.imageUrl,alt:e.imageAlt,className:"size-full",imgClassName:"object-contain"})}):(0,t.jsx)("div",{className:(0,n.cn)("scene-shelf-v2-product-card-image desktop:size-[196px] tablet:size-[140px] lg-desktop:size-[196px] flex size-[128px] shrink-0 items-center justify-center ",a&&"cursor-pointer transition-opacity hover:opacity-80",c?.productCardImage),onClick:a?g:void 0,role:a?"button":void 0,tabIndex:a?0:void 0,"aria-label":a?`View ${e.title}`:void 0,children:(0,t.jsx)(l.Picture,{source:e.imageUrl,alt:e.imageAlt,className:"size-full",imgClassName:"object-contain"})}),(0,t.jsxs)("div",{className:"desktop:gap-6 flex w-full flex-1 flex-col justify-between gap-4",children:[(0,t.jsxs)("div",{className:"flex flex-col gap-2",children:[(0,t.jsx)("div",{className:(0,n.cn)("scene-shelf-v2-product-card-tags flex min-h-[24px] flex-wrap gap-1",c?.productCardTags),children:i&&e?.tags?.map((p,k)=>(0,t.jsx)(l.Badge,{variant:p.variant??"outline",size:"sm",className:"",children:p.label},k))}),(0,t.jsx)(l.Heading,{as:"h3",size:2,className:(0,n.cn)("scene-shelf-v2-product-card-title text-info-primary laptop:line-clamp-2 tablet:text-[20px] line-clamp-3 pr-[16%] text-[16px]",c?.productCardTitle),children:e.custom_name||e.title}),(e.custom_description||e.description)&&(0,t.jsx)(l.Text,{as:"p",size:1,className:(0,n.cn)("scene-shelf-v2-product-card-description text-info-primary tablet:text-[14px] desktop:text-[16px] lg-desktop:text-[18px] line-clamp-1",c?.productCardDescription),children:e.custom_description||e.description})]}),(0,t.jsxs)("div",{className:"flex flex-col gap-2",children:[(0,t.jsxs)("div",{className:(0,n.cn)("scene-shelf-v2-product-card-price flex flex-wrap items-center gap-1",c?.productCardPriceWrapper),children:[(0,t.jsx)(l.Heading,{as:"h6",size:2,className:(0,n.cn)("scene-shelf-v2-product-card-current-price text-info-primary",c?.productCardCurrentPrice),children:e.currentPrice}),e.originalPrice&&(0,t.jsx)(l.Heading,{as:"h6",size:2,className:(0,n.cn)("scene-shelf-v2-product-card-original-price text-info-tertiary line-through",c?.productCardOriginalPrice),children:e.originalPrice})]}),(h||b)&&(0,t.jsxs)("div",{className:(0,n.cn)("scene-shelf-v2-product-card-buttons laptop:flex-nowrap lg-desktop:gap-3 flex flex-wrap gap-2",c?.productCardButtons),children:[h&&(0,t.jsx)(l.Button,{variant:"secondary",className:"laptop:grow-0 flex-1 whitespace-nowrap",onClick:()=>{E(),(0,T.gaTrack)({event:"ga4Event",event_name:"component_click",event_parameters:{page_group:f||"Home Page",component_type:"copy",component_name:"scene_shelf_product",component_title:e.title,component_description:"",button_name:h,SKU:e.sku||"",position:d}})},disabled:e.soldOut&&x!=="learnMore",loading:_,children:h}),b&&(0,t.jsx)(l.Button,{variant:"primary",className:"laptop:grow-0 flex-1 whitespace-nowrap",onClick:()=>{R(),(0,T.gaTrack)({event:"ga4Event",event_name:"component_click",event_parameters:{page_group:f||"Home Page",component_type:"copy",component_name:"scene_shelf_product",component_title:e.title,component_description:"",button_name:b,SKU:e.sku||"",position:d}})},disabled:e.soldOut&&P!=="learnMore",loading:M,children:b})]})]})]})]})});V.displayName="SceneShelfV2.ProductCard";const W=r.forwardRef(({className:e,classNames:i={},data:a,onPlayClick:u,onImageClick:m,onLearnMore:S,onShopNow:h,onAddToCart:x,...b},P)=>{const{theme:c="light",sceneImage:s,productsTitle:N,products:d,secondaryButtonText:B,secondaryButtonFun:L,primaryButtonText:M,primaryButtonFun:z,viewMoreLimit:_=2,copy:I}=a,f=r.useRef(null),y=r.useRef(null),R=r.useRef(null),[E,g]=r.useState(!1),[p,k]=r.useState(!1),{trackingData:C}=(0,F.useAiuiContext)();(0,J.useExposure)(y,{componentType:"image",componentName:"scene_shelf_banner"}),(0,X.useViewItemList)(R,{componentType:"video",componentName:"scene_shelf_banner",itemListName:"Scene_Shelf_2_Products",items:d.map((o,v)=>({item_id:o.sku??"",item_name:o.title,item_variant:o.variantId??"",price:o.currentPrice,index:v})),tabName:""});const A=(0,q.useGridRowCount)({rows:_??0,mobileCols:2}),O=r.useMemo(()=>[s?.pc,s?.desktop,s?.laptop,s?.pad,s?.mobile].some(o=>o?.mimeType==="video/mp4"),[s]),Z=r.useCallback(()=>{const o=f.current;o?o.paused?(o.play(),g(!0),u?.(!0)):(o.pause(),g(!1),u?.(!1)):u?.(!0),(0,T.gaTrack)({event:"ga4Event",event_name:"component_click",event_parameters:{page_group:C?.pageGroup,component_type:"video",component_name:"scene_shelf_banner",position:1,creative_id:s?.pc?.id}})},[u,s?.pc?.id,C?.pageGroup]);return r.useEffect(()=>{const o=f.current;if(!o||!O)return;const v=new IntersectionObserver(w=>{w.forEach(D=>{D.isIntersecting?o.play().catch(ee=>{console.warn("Video autoplay failed:",ee)}):o.pause()})},{threshold:.5});return v.observe(o),()=>{v.disconnect()}},[]),(0,t.jsxs)("div",{...b,ref:P,className:(0,n.cn)("scene-shelf-v2-root w-full overflow-hidden",{"aiui-dark":c==="dark"},e,i?.root),children:[(0,t.jsxs)("div",{className:(0,n.cn)("scene-shelf-v2-media laptop:h-[360px] tablet:h-[400px] desktop:h-[384px] rounded-box tablet:rounded-t-box tablet:rounded-b-none lg-desktop:h-[480px] relative h-[240px] overflow-hidden",i?.media),ref:y,children:[(0,t.jsx)(K.default,{pcImage:s?.pc,desktopImage:s?.desktop,laptopImage:s?.laptop,padImage:s?.pad,mobileImage:s?.mobile,className:"size-full",videoClassName:"absolute inset-0 size-full object-cover",videoRef:f,onVideoPlay:()=>g(!0),onVideoPause:()=>g(!1),onVideoEnded:()=>g(!1)}),(0,t.jsx)("div",{"aria-hidden":"true",className:(0,n.cn)("scene-shelf-v2-media-overlay pointer-events-none absolute inset-0",i?.mediaOverlay)}),O&&(0,t.jsx)("div",{className:"desktop:gap-16 desktop:p-8 absolute inset-0 flex items-end justify-end gap-4 p-6",children:(0,t.jsx)("button",{type:"button","aria-label":E?"Pause video":"Play video",onClick:Z,className:(0,n.cn)("scene-shelf-v2-media-play-button flex size-14 shrink-0 items-center justify-center rounded-full bg-white/20 transition-opacity hover:opacity-80",i?.mediaPlayButton),children:E?(0,t.jsx)(pe,{}):(0,t.jsx)(de,{})})})]}),(0,t.jsxs)("div",{ref:R,className:(0,n.cn)("scene-shelf-v2-products text-info-primary tablet:bg-container-primary laptop:p-6 desktop:p-8 rounded-b-box tablet:p-4 flex flex-col gap-4 bg-transparent p-0 pt-3",i?.products),children:[N&&(0,t.jsx)(l.Heading,{as:"h2",size:3,className:(0,n.cn)("scene-shelf-v2-products-title text-info-primary",i?.productsTitle),html:N}),(0,t.jsx)("div",{className:"tablet:hidden grid grid-cols-2 gap-3",children:(()=>{const o=_!==void 0&&_>0&&d.length>A,v=o&&!p?d.slice(0,A):d;return(0,t.jsxs)(t.Fragment,{children:[v.map((w,D)=>(0,t.jsx)(V,{isShowTag:a.isShowTag??!0,product:w,onImageClick:m,onLearnMore:S,onShopNow:h,onAddToCart:x,secondaryButtonText:B,secondaryButtonFun:L,primaryButtonText:M,primaryButtonFun:z,classNames:i,theme:c,index:D},w.productKey)),o&&(0,t.jsx)("div",{className:"col-span-2 mt-6 flex justify-center",children:(0,t.jsxs)("button",{type:"button",onClick:()=>k(w=>!w),className:"text-info-primary hover:text-brand-0 flex items-center gap-2 text-[14px] font-bold transition-colors","aria-expanded":p,children:[p?I?.viewLessLabel??"View Less":I?.viewMoreLabel??"View More",(0,t.jsx)("svg",{className:(0,n.cn)("size-4 transition-transform",p&&"rotate-180"),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})]})})]})})()}),(0,t.jsx)("div",{className:"tablet:block hidden",children:(0,t.jsx)("div",{className:"relative",children:(0,t.jsx)(j.Swiper,{slidesPerView:"auto",observer:!0,observeParents:!0,modules:[$.Mousewheel],mousewheel:{enabled:!0,forceToAxis:!0,sensitivity:1},className:"!overflow-visible",breakpoints:{768:{spaceBetween:16,slidesPerView:d.length>3?2.3:2},1024:{spaceBetween:16,slidesPerView:d.length>3?2.8:3},1440:{spaceBetween:16,slidesPerView:d.length>4?3.8:4},1920:{spaceBetween:16,slidesPerView:d.length>4?3.8:4}},children:d.map((o,v)=>(0,t.jsx)(j.SwiperSlide,{className:(0,n.cn)("!h-auto ",i.productCardSlideWrapper),children:(0,t.jsx)(V,{product:o,isShowTag:a.isShowTag??!0,onImageClick:m,onLearnMore:S,onShopNow:h,onAddToCart:x,secondaryButtonText:B,secondaryButtonFun:L,primaryButtonText:M,primaryButtonFun:z,classNames:i,theme:c,index:v})},o.productKey))})})})]})]})});W.displayName="SceneShelfV2";var me=(0,Q.withLayout)(W);
|
|
1
|
+
"use strict";"use client";var te=Object.create;var H=Object.defineProperty;var ie=Object.getOwnPropertyDescriptor;var oe=Object.getOwnPropertyNames;var ae=Object.getPrototypeOf,ne=Object.prototype.hasOwnProperty;var re=(e,i)=>{for(var a in i)H(e,a,{get:i[a],enumerable:!0})},G=(e,i,a,u)=>{if(i&&typeof i=="object"||typeof i=="function")for(let m of oe(i))!ne.call(e,m)&&m!==a&&H(e,m,{get:()=>i[m],enumerable:!(u=ie(i,m))||u.enumerable});return e};var U=(e,i,a)=>(a=e!=null?te(ae(e)):{},G(i||!e||!e.__esModule?H(a,"default",{value:e,enumerable:!0}):a,e)),se=e=>G(H({},"__esModule",{value:!0}),e);var ue={};re(ue,{SceneShelfV2ProductCard:()=>V,default:()=>me});module.exports=se(ue);var t=require("react/jsx-runtime"),r=U(require("react")),n=require("../../helpers/index.js"),l=require("../../components/index.js"),K=U(require("../Media/index.js")),j=require("swiper/react"),$=require("swiper/modules"),ge=require("swiper/css"),ve=require("swiper/css/navigation"),Q=require("../../shared/Styles.js"),q=require("../../hooks/useGridRowCount.js"),J=require("../../hooks/useExposure.js"),X=require("../../hooks/useViewItemList.js"),Y=require("../../shared/trackUrlRef.js"),F=require("../AiuiProvider/index.js"),T=require("../../shared/track.js");const le="shelf",ce="scene_shelf_v2",de=()=>(0,t.jsx)("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:(0,t.jsx)("path",{d:"M8 5.14v13.72L19 12 8 5.14z",fill:"white"})}),pe=()=>(0,t.jsxs)("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:[(0,t.jsx)("rect",{x:"6",y:"5",width:"4",height:"14",rx:"1",fill:"white"}),(0,t.jsx)("rect",{x:"14",y:"5",width:"4",height:"14",rx:"1",fill:"white"})]}),V=r.memo(({product:e,isShowTag:i=!0,onImageClick:a,onLearnMore:u,onShopNow:m,onAddToCart:S,secondaryButtonText:h,secondaryButtonFun:x,primaryButtonText:b,primaryButtonFun:P,classNames:c,className:s,theme:N,index:d})=>{const{locale:B="us",trackingData:L}=(0,F.useAiuiContext)(),[M,z]=r.useState(!1),[_,I]=r.useState(!1),f=L?.pageGroup,y=r.useCallback(async(p,k)=>{if(!p)return;const C=k==="primary"?z:I;C(!0);try{switch(p){case"buyNow":await m?.(e);break;case"addCart":await S?.(e);break;case"learnMore":await u?.(e?.href??"");break;default:break}}finally{C(!1)}},[u,m,S,e]),R=r.useCallback(()=>y(P,"primary"),[y,P]),E=r.useCallback(()=>y(x,"secondary"),[y,x]),g=r.useCallback(p=>{!e.href&&a&&p.preventDefault(),a?.(e),(0,T.gaTrack)({event:"ga4Event",event_name:"select_item",item_list_name:"Scene_Shelf_2_Products",page_group:f,items:[{item_id:e.sku,item_name:e.custom_name||e.title,item_variant:e.variantId,price:e.currentPrice,index:d}]})},[d,a,f,e]);return(0,t.jsxs)("div",{className:(0,n.cn)("scene-shelf-v2-product-card rounded-box bg-container-secondary-1 tablet:px-6 desktop:pb-6 desktop:px-6 box-border flex h-full flex-col items-center justify-between gap-3 overflow-hidden px-2 py-4",s,c?.productCard,{"bg-container-secondary-0":N==="dark"}),children:[e.href?(0,t.jsx)("a",{href:(0,n.getLocalizedPath)((0,Y.trackUrlRef)(e.href,f+"_"+le+"_"+ce),B),onClick:g,className:(0,n.cn)("scene-shelf-v2-product-card-image desktop:size-[196px] tablet:size-[140px] lg-desktop:size-[196px] flex size-[128px] shrink-0 items-center justify-center transition-opacity hover:opacity-80",c?.productCardImage),"aria-label":`View ${e.title}`,children:(0,t.jsx)(l.Picture,{source:e.imageUrl,alt:e.imageAlt,className:"size-full",imgClassName:"object-contain"})}):(0,t.jsx)("div",{className:(0,n.cn)("scene-shelf-v2-product-card-image desktop:size-[196px] tablet:size-[140px] lg-desktop:size-[196px] flex size-[128px] shrink-0 items-center justify-center ",a&&"cursor-pointer transition-opacity hover:opacity-80",c?.productCardImage),onClick:a?g:void 0,role:a?"button":void 0,tabIndex:a?0:void 0,"aria-label":a?`View ${e.title}`:void 0,children:(0,t.jsx)(l.Picture,{source:e.imageUrl,alt:e.imageAlt,className:"size-full",imgClassName:"object-contain"})}),(0,t.jsxs)("div",{className:"desktop:gap-6 flex w-full flex-1 flex-col justify-between gap-4",children:[(0,t.jsxs)("div",{className:"flex flex-col gap-2",children:[(0,t.jsx)("div",{className:(0,n.cn)("scene-shelf-v2-product-card-tags flex min-h-[24px] flex-wrap gap-1",c?.productCardTags),children:i&&e?.tags?.map((p,k)=>(0,t.jsx)(l.Badge,{variant:p.variant??"outline",size:"sm",className:"",children:p.label},k))}),(0,t.jsx)(l.Heading,{as:"h3",size:2,className:(0,n.cn)("scene-shelf-v2-product-card-title text-info-primary laptop:line-clamp-2 line-clamp-3 pr-[16%] text-[16px]",c?.productCardTitle),children:e.custom_name||e.title}),(e.custom_description||e.description)&&(0,t.jsx)(l.Text,{as:"p",size:1,className:(0,n.cn)("scene-shelf-v2-product-card-description text-info-primary tablet:text-[14px] desktop:text-[16px] lg-desktop:text-[18px] line-clamp-1",c?.productCardDescription),children:e.custom_description||e.description})]}),(0,t.jsxs)("div",{className:"flex flex-col gap-2",children:[(0,t.jsxs)("div",{className:(0,n.cn)("scene-shelf-v2-product-card-price flex flex-wrap items-center gap-1",c?.productCardPriceWrapper),children:[(0,t.jsx)(l.Heading,{as:"h6",size:2,className:(0,n.cn)("scene-shelf-v2-product-card-current-price text-info-primary",c?.productCardCurrentPrice),children:e.currentPrice}),e.originalPrice&&(0,t.jsx)(l.Heading,{as:"h6",size:2,className:(0,n.cn)("scene-shelf-v2-product-card-original-price text-info-tertiary line-through",c?.productCardOriginalPrice),children:e.originalPrice})]}),(h||b)&&(0,t.jsxs)("div",{className:(0,n.cn)("scene-shelf-v2-product-card-buttons laptop:flex-nowrap lg-desktop:gap-3 flex flex-wrap gap-2",c?.productCardButtons),children:[h&&(0,t.jsx)(l.Button,{variant:"secondary",className:"laptop:grow-0 flex-1 whitespace-nowrap",onClick:()=>{E(),(0,T.gaTrack)({event:"ga4Event",event_name:"component_click",event_parameters:{page_group:f||"Home Page",component_type:"copy",component_name:"scene_shelf_product",component_title:e.title,component_description:"",button_name:h,SKU:e.sku||"",position:d}})},disabled:e.soldOut&&x!=="learnMore",loading:_,children:h}),b&&(0,t.jsx)(l.Button,{variant:"primary",className:"laptop:grow-0 flex-1 whitespace-nowrap",onClick:()=>{R(),(0,T.gaTrack)({event:"ga4Event",event_name:"component_click",event_parameters:{page_group:f||"Home Page",component_type:"copy",component_name:"scene_shelf_product",component_title:e.title,component_description:"",button_name:b,SKU:e.sku||"",position:d}})},disabled:e.soldOut&&P!=="learnMore",loading:M,children:b})]})]})]})]})});V.displayName="SceneShelfV2.ProductCard";const W=r.forwardRef(({className:e,classNames:i={},data:a,onPlayClick:u,onImageClick:m,onLearnMore:S,onShopNow:h,onAddToCart:x,...b},P)=>{const{theme:c="light",sceneImage:s,productsTitle:N,products:d,secondaryButtonText:B,secondaryButtonFun:L,primaryButtonText:M,primaryButtonFun:z,viewMoreLimit:_=2,copy:I}=a,f=r.useRef(null),y=r.useRef(null),R=r.useRef(null),[E,g]=r.useState(!1),[p,k]=r.useState(!1),{trackingData:C}=(0,F.useAiuiContext)();(0,J.useExposure)(y,{componentType:"image",componentName:"scene_shelf_banner"}),(0,X.useViewItemList)(R,{componentType:"video",componentName:"scene_shelf_banner",itemListName:"Scene_Shelf_2_Products",items:d.map((o,v)=>({item_id:o.sku??"",item_name:o.title,item_variant:o.variantId??"",price:o.currentPrice,index:v})),tabName:""});const A=(0,q.useGridRowCount)({rows:_??0,mobileCols:2}),O=r.useMemo(()=>[s?.pc,s?.desktop,s?.laptop,s?.pad,s?.mobile].some(o=>o?.mimeType==="video/mp4"),[s]),Z=r.useCallback(()=>{const o=f.current;o?o.paused?(o.play(),g(!0),u?.(!0)):(o.pause(),g(!1),u?.(!1)):u?.(!0),(0,T.gaTrack)({event:"ga4Event",event_name:"component_click",event_parameters:{page_group:C?.pageGroup,component_type:"video",component_name:"scene_shelf_banner",position:1,creative_id:s?.pc?.id}})},[u,s?.pc?.id,C?.pageGroup]);return r.useEffect(()=>{const o=f.current;if(!o||!O)return;const v=new IntersectionObserver(w=>{w.forEach(D=>{D.isIntersecting?o.play().catch(ee=>{console.warn("Video autoplay failed:",ee)}):o.pause()})},{threshold:.5});return v.observe(o),()=>{v.disconnect()}},[]),(0,t.jsxs)("div",{...b,ref:P,className:(0,n.cn)("scene-shelf-v2-root w-full overflow-hidden",{"aiui-dark":c==="dark"},e,i?.root),children:[(0,t.jsxs)("div",{className:(0,n.cn)("scene-shelf-v2-media laptop:h-[360px] tablet:h-[400px] desktop:h-[384px] rounded-box tablet:rounded-t-box tablet:rounded-b-none lg-desktop:h-[480px] relative h-[240px] overflow-hidden",i?.media),ref:y,children:[(0,t.jsx)(K.default,{pcImage:s?.pc,desktopImage:s?.desktop,laptopImage:s?.laptop,padImage:s?.pad,mobileImage:s?.mobile,className:"size-full",videoClassName:"absolute inset-0 size-full object-cover",videoRef:f,onVideoPlay:()=>g(!0),onVideoPause:()=>g(!1),onVideoEnded:()=>g(!1)}),(0,t.jsx)("div",{"aria-hidden":"true",className:(0,n.cn)("scene-shelf-v2-media-overlay pointer-events-none absolute inset-0",i?.mediaOverlay)}),O&&(0,t.jsx)("div",{className:"desktop:gap-16 desktop:p-8 absolute inset-0 flex items-end justify-end gap-4 p-6",children:(0,t.jsx)("button",{type:"button","aria-label":E?"Pause video":"Play video",onClick:Z,className:(0,n.cn)("scene-shelf-v2-media-play-button flex size-14 shrink-0 items-center justify-center rounded-full bg-white/20 transition-opacity hover:opacity-80",i?.mediaPlayButton),children:E?(0,t.jsx)(pe,{}):(0,t.jsx)(de,{})})})]}),(0,t.jsxs)("div",{ref:R,className:(0,n.cn)("scene-shelf-v2-products text-info-primary tablet:bg-container-primary laptop:p-6 desktop:p-8 rounded-b-box tablet:p-4 flex flex-col gap-4 bg-transparent p-0 pt-3",i?.products),children:[N&&(0,t.jsx)(l.Heading,{as:"h2",size:3,className:(0,n.cn)("scene-shelf-v2-products-title text-info-primary",i?.productsTitle),html:N}),(0,t.jsx)("div",{className:"tablet:hidden grid grid-cols-2 gap-3",children:(()=>{const o=_!==void 0&&_>0&&d.length>A,v=o&&!p?d.slice(0,A):d;return(0,t.jsxs)(t.Fragment,{children:[v.map((w,D)=>(0,t.jsx)(V,{isShowTag:a.isShowTag??!0,product:w,onImageClick:m,onLearnMore:S,onShopNow:h,onAddToCart:x,secondaryButtonText:B,secondaryButtonFun:L,primaryButtonText:M,primaryButtonFun:z,classNames:i,theme:c,index:D},w.productKey)),o&&(0,t.jsx)("div",{className:"col-span-2 mt-6 flex justify-center",children:(0,t.jsxs)("button",{type:"button",onClick:()=>k(w=>!w),className:"text-info-primary hover:text-brand-0 flex items-center gap-2 text-[14px] font-bold transition-colors","aria-expanded":p,children:[p?I?.viewLessLabel??"View Less":I?.viewMoreLabel??"View More",(0,t.jsx)("svg",{className:(0,n.cn)("size-4 transition-transform",p&&"rotate-180"),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})]})})]})})()}),(0,t.jsx)("div",{className:"tablet:block hidden",children:(0,t.jsx)("div",{className:"relative",children:(0,t.jsx)(j.Swiper,{slidesPerView:"auto",observer:!0,observeParents:!0,modules:[$.Mousewheel],mousewheel:{enabled:!0,forceToAxis:!0,sensitivity:1},className:"!overflow-visible",breakpoints:{768:{spaceBetween:16,slidesPerView:d.length>3?2.3:2},1024:{spaceBetween:16,slidesPerView:d.length>3?2.8:3},1440:{spaceBetween:16,slidesPerView:d.length>4?3.8:4},1920:{spaceBetween:16,slidesPerView:d.length>4?3.8:4}},children:d.map((o,v)=>(0,t.jsx)(j.SwiperSlide,{className:(0,n.cn)("!h-auto ",i.productCardSlideWrapper),children:(0,t.jsx)(V,{product:o,isShowTag:a.isShowTag??!0,onImageClick:m,onLearnMore:S,onShopNow:h,onAddToCart:x,secondaryButtonText:B,secondaryButtonFun:L,primaryButtonText:M,primaryButtonFun:z,classNames:i,theme:c,index:v})},o.productKey))})})})]})]})});W.displayName="SceneShelfV2";var me=(0,Q.withLayout)(W);
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/biz-components/SceneShelfV2/index.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { cn, getLocalizedPath } from '../../helpers/index.js'\nimport { Heading, Text, Badge, Button, Picture } from '../../components/index.js'\nimport Media from '../Media/index.js'\nimport type { ResponsiveMedia, Theme } from '../../types/props.js'\nimport { Swiper, SwiperSlide } from 'swiper/react'\nimport { Mousewheel } from 'swiper/modules'\nimport 'swiper/css'\nimport 'swiper/css/navigation'\nimport { withLayout } from '../../shared/Styles.js'\nimport { useGridRowCount } from '../../hooks/useGridRowCount.js'\nimport { useExposure } from '../../hooks/useExposure.js'\nimport { useViewItemList } from '../../hooks/useViewItemList.js'\nimport { trackUrlRef } from '../../shared/trackUrlRef.js'\nimport { useAiuiContext } from '../AiuiProvider/index.js'\nimport { gaTrack } from '../../shared/track.js'\n\nconst componentType = 'shelf'\nconst componentName = 'scene_shelf_v2'\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Types\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * \u6309\u94AE\u529F\u80FD\u7C7B\u578B\n */\nexport type ButtonFunctionType = 'buyNow' | 'addCart' | 'learnMore'\n\nexport type SceneShelfV2SemanticName =\n | 'root'\n | 'media'\n | 'mediaOverlay'\n | 'mediaQuote'\n | 'mediaPlayButton'\n | 'products'\n | 'productsTitle'\n | 'productGrid'\n | 'productCardSlideWrapper'\n | 'productCard'\n | 'productCardImage'\n | 'productCardTags'\n | 'productCardTitle'\n | 'productCardDescription'\n | 'productCardPriceWrapper'\n | 'productCardCurrentPrice'\n | 'productCardOriginalPrice'\n | 'productCardButtons'\n\nexport interface SceneShelfV2Tag {\n label: string\n variant?: 'outline' | 'fill'\n}\n\nexport interface SceneShelfV2Product {\n /** \u4EA7\u54C1\u552F\u4E00\u6807\u8BC6 */\n productKey: string\n /** \u4EA7\u54C1\u4E3B\u6807\u9898 */\n title: string\n /** \u4EA7\u54C1\u63CF\u8FF0 */\n description?: string\n /** \u4EA7\u54C1\u56FE\u7247 */\n imageUrl: string\n imageAlt: string\n /**\n * \u4EA7\u54C1\u94FE\u63A5 URL\u3002\n */\n href?: string\n /** \u5F53\u524D\u4EF7\u683C\uFF08\u683C\u5F0F\u5316\u5B57\u7B26\u4E32\uFF0C\u5982 \"$1,999.00\"\uFF09 */\n currentPrice: string\n /** \u539F\u4EF7\uFF08\u663E\u793A\u5220\u9664\u7EBF\uFF09 */\n originalPrice?: string\n /** \u6807\u7B7E\u5217\u8868 */\n tags?: SceneShelfV2Tag[]\n /** \u662F\u5426\u552E\u7F44 */\n soldOut?: boolean\n /**\n * sku\n */\n sku?: string\n /**\n * \u53D8\u4F53id\n */\n variantId?: string\n /** \u81EA\u5B9A\u4E49\u4EA7\u54C1\u540D\u79F0 */\n custom_name?: string\n /** \u81EA\u5B9A\u4E49\u4EA7\u54C1\u63CF\u8FF0 */\n custom_description?: string\n}\n\n/**\n * \u6587\u6848\u914D\u7F6E\n */\nexport interface SceneShelfV2CopyConfig {\n /** \u67E5\u770B\u66F4\u591A\u6807\u7B7E */\n viewMoreLabel?: string\n /** \u6536\u8D77\u6807\u7B7E */\n viewLessLabel?: string\n}\n\nexport interface SceneShelfV2Data {\n theme?: 'light' | 'dark'\n isShowTag?: boolean\n sceneImage: ResponsiveMedia\n /** \u4EA7\u54C1\u533A\u6807\u9898\uFF08\u53EF\u9009\uFF09 */\n productsTitle?: string\n /** \u4EA7\u54C1\u5217\u8868 */\n products: SceneShelfV2Product[]\n /** \u6B21\u8981\u6309\u94AE\u6587\u672C */\n secondaryButtonText?: string\n /** \u6B21\u8981\u6309\u94AE\u529F\u80FD\u7C7B\u578B */\n secondaryButtonFun?: ButtonFunctionType\n /** \u4E3B\u8981\u6309\u94AE\u6587\u672C */\n primaryButtonText?: string\n /** \u4E3B\u8981\u6309\u94AE\u529F\u80FD\u7C7B\u578B */\n primaryButtonFun?: ButtonFunctionType\n /** \u67E5\u770B\u66F4\u591A\u9650\u5236\u6570\uFF08\u624B\u673A\u7AEF\u8D85\u8FC7\u4E24\u884C\u65F6\u663E\u793AviewMore\u6309\u94AE\uFF09 */\n viewMoreLimit?: number\n /** \u6587\u6848\u914D\u7F6E */\n copy?: SceneShelfV2CopyConfig\n}\n\nexport interface SceneShelfV2Props extends React.HTMLAttributes<HTMLDivElement> {\n data: SceneShelfV2Data\n /**\n * \u70B9\u51FB\u64AD\u653E/\u6682\u505C\u6309\u94AE\u56DE\u8C03\u3002\n * \u5F53\u5A92\u4F53\u533A\u4E3A\u89C6\u9891\u65F6\uFF0C\u7EC4\u4EF6\u5185\u90E8\u4F1A\u81EA\u52A8\u63A7\u5236\u64AD\u653E/\u6682\u505C,\u6B64\u56DE\u8C03\u4ECD\u4F1A\u89E6\u53D1\u3002\n */\n onPlayClick?: (isPlaying: boolean) => void\n /** \u70B9\u51FB\u4EA7\u54C1\u56FE\u7247\u56DE\u8C03 */\n onImageClick?: (product: SceneShelfV2Product) => void\n /** \u70B9\u51FB\u4E86\u89E3\u66F4\u591A\u56DE\u8C03\uFF08\u652F\u6301\u5F02\u6B65\uFF09 */\n onLearnMore?: (link: string) => void | Promise<void>\n /** \u70B9\u51FB\u7ACB\u5373\u8D2D\u4E70\u56DE\u8C03\uFF08\u652F\u6301\u5F02\u6B65\uFF09 */\n onShopNow?: (product: SceneShelfV2Product) => void | Promise<void>\n /** \u70B9\u51FB\u52A0\u5165\u8D2D\u7269\u8F66\u56DE\u8C03\uFF08\u652F\u6301\u5F02\u6B65\uFF09 */\n onAddToCart?: (product: SceneShelfV2Product) => void | Promise<void>\n classNames?: Partial<Record<SceneShelfV2SemanticName, string>>\n}\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Icons\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst PlayIcon = () => (\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M8 5.14v13.72L19 12 8 5.14z\" fill=\"white\" />\n </svg>\n)\n\nconst PauseIcon = () => (\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <rect x=\"6\" y=\"5\" width=\"4\" height=\"14\" rx=\"1\" fill=\"white\" />\n <rect x=\"14\" y=\"5\" width=\"4\" height=\"14\" rx=\"1\" fill=\"white\" />\n </svg>\n)\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Product Card\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface ProductCardInnerProps {\n product: SceneShelfV2Product\n isShowTag: boolean\n onImageClick?: (product: SceneShelfV2Product) => void\n onLearnMore?: (link: string) => void | Promise<void>\n onShopNow?: (product: SceneShelfV2Product) => void | Promise<void>\n onAddToCart?: (product: SceneShelfV2Product) => void | Promise<void>\n secondaryButtonText?: string\n secondaryButtonFun?: ButtonFunctionType\n primaryButtonText?: string\n primaryButtonFun?: ButtonFunctionType\n classNames?: Partial<Record<SceneShelfV2SemanticName, string>>\n className?: string\n theme?: Theme\n index?: number\n}\n\nconst ProductCardInner = React.memo(\n ({\n product,\n isShowTag = true,\n onImageClick,\n onLearnMore,\n onShopNow,\n onAddToCart,\n secondaryButtonText,\n secondaryButtonFun,\n primaryButtonText,\n primaryButtonFun,\n classNames,\n className,\n theme,\n index,\n }: ProductCardInnerProps) => {\n const { locale = 'us', trackingData } = useAiuiContext()\n const [primaryLoading, setPrimaryLoading] = React.useState(false)\n const [secondaryLoading, setSecondaryLoading] = React.useState(false)\n\n const pageGroup = trackingData?.pageGroup\n\n // \u6839\u636E\u6309\u94AE\u529F\u80FD\u7C7B\u578B\u8C03\u7528\u76F8\u5E94\u7684\u56DE\u8C03\u51FD\u6570\n const handleButtonClick = React.useCallback(\n async (buttonFun?: ButtonFunctionType, buttonType?: 'primary' | 'secondary') => {\n if (!buttonFun) return\n\n const setLoading = buttonType === 'primary' ? setPrimaryLoading : setSecondaryLoading\n setLoading(true)\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?.href ?? '')\n break\n default:\n break\n }\n } finally {\n setLoading(false)\n }\n },\n [onLearnMore, onShopNow, onAddToCart, product]\n )\n\n const handlePrimary = React.useCallback(\n () => handleButtonClick(primaryButtonFun, 'primary'),\n [handleButtonClick, primaryButtonFun]\n )\n const handleSecondary = React.useCallback(\n () => handleButtonClick(secondaryButtonFun, 'secondary'),\n [handleButtonClick, secondaryButtonFun]\n )\n\n const handleImageClick = React.useCallback(\n (e: React.MouseEvent) => {\n // \u5982\u679C\u6CA1\u6709\u63D0\u4F9B href \u4E14\u6709\u70B9\u51FB\u56DE\u8C03\uFF0C\u963B\u6B62\u9ED8\u8BA4\u884C\u4E3A\n if (!product.href && onImageClick) {\n e.preventDefault()\n }\n onImageClick?.(product)\n gaTrack({\n event: 'ga4Event',\n event_name: 'select_item',\n item_list_name: 'Scene_Shelf_2_Products',\n page_group: pageGroup,\n items: [\n {\n item_id: product.sku,\n item_name: product.custom_name || product.title,\n item_variant: product.variantId,\n price: product.currentPrice,\n index: index,\n },\n ],\n })\n },\n [index, onImageClick, pageGroup, product]\n )\n\n return (\n <div\n className={cn(\n 'scene-shelf-v2-product-card rounded-box bg-container-secondary-1 tablet:px-6 desktop:pb-6 desktop:px-6 box-border flex h-full flex-col items-center justify-between gap-3 overflow-hidden px-2 py-4',\n className,\n classNames?.productCard,\n {\n 'bg-container-secondary-0': theme === 'dark',\n }\n )}\n >\n {/* \u4EA7\u54C1\u56FE\u7247 */}\n {product.href ? (\n <a\n href={getLocalizedPath(\n trackUrlRef(product.href, pageGroup + '_' + componentType + '_' + componentName),\n locale\n )}\n onClick={handleImageClick}\n className={cn(\n 'scene-shelf-v2-product-card-image desktop:size-[196px] tablet:size-[140px] lg-desktop:size-[196px] flex size-[128px] shrink-0 items-center justify-center transition-opacity hover:opacity-80',\n classNames?.productCardImage\n )}\n aria-label={`View ${product.title}`}\n >\n <Picture\n source={product.imageUrl}\n alt={product.imageAlt}\n className=\"size-full\"\n imgClassName=\"object-contain\"\n />\n </a>\n ) : (\n <div\n className={cn(\n 'scene-shelf-v2-product-card-image desktop:size-[196px] tablet:size-[140px] lg-desktop:size-[196px] flex size-[128px] shrink-0 items-center justify-center ',\n onImageClick && 'cursor-pointer transition-opacity hover:opacity-80',\n classNames?.productCardImage\n )}\n onClick={onImageClick ? handleImageClick : undefined}\n role={onImageClick ? 'button' : undefined}\n tabIndex={onImageClick ? 0 : undefined}\n aria-label={onImageClick ? `View ${product.title}` : undefined}\n >\n <Picture\n source={product.imageUrl}\n alt={product.imageAlt}\n className=\"size-full\"\n imgClassName=\"object-contain\"\n />\n </div>\n )}\n\n {/* \u4EA7\u54C1\u4FE1\u606F */}\n <div className=\"desktop:gap-6 flex w-full flex-1 flex-col justify-between gap-4\">\n {/* \u6807\u7B7E + \u6807\u9898 + \u526F\u6807\u9898 */}\n <div className=\"flex flex-col gap-2\">\n <div\n className={cn(\n 'scene-shelf-v2-product-card-tags flex min-h-[24px] flex-wrap gap-1',\n classNames?.productCardTags\n )}\n >\n {isShowTag &&\n product?.tags?.map((tag, idx) => (\n <Badge key={idx} variant={tag.variant ?? 'outline'} size=\"sm\" className=\"\">\n {tag.label}\n </Badge>\n ))}\n </div>\n\n <Heading\n as=\"h3\"\n size={2}\n className={cn(\n 'scene-shelf-v2-product-card-title text-info-primary laptop:line-clamp-2 tablet:text-[20px] line-clamp-3 pr-[16%] text-[16px]',\n classNames?.productCardTitle\n )}\n >\n {product.custom_name || product.title}\n </Heading>\n\n {(product.custom_description || product.description) && (\n <Text\n as=\"p\"\n size={1}\n className={cn(\n 'scene-shelf-v2-product-card-description text-info-primary tablet:text-[14px] desktop:text-[16px] lg-desktop:text-[18px] line-clamp-1',\n classNames?.productCardDescription\n )}\n >\n {product.custom_description || product.description}\n </Text>\n )}\n </div>\n\n {/* \u4EF7\u683C + \u6309\u94AE */}\n <div className=\"flex flex-col gap-2\">\n {/* \u4EF7\u683C */}\n <div\n className={cn(\n 'scene-shelf-v2-product-card-price flex flex-wrap items-center gap-1',\n classNames?.productCardPriceWrapper\n )}\n >\n <Heading\n as=\"h6\"\n size={2}\n className={cn(\n 'scene-shelf-v2-product-card-current-price text-info-primary',\n classNames?.productCardCurrentPrice\n )}\n >\n {product.currentPrice}\n </Heading>\n {product.originalPrice && (\n <Heading\n as=\"h6\"\n size={2}\n className={cn(\n 'scene-shelf-v2-product-card-original-price text-info-tertiary line-through',\n classNames?.productCardOriginalPrice\n )}\n >\n {product.originalPrice}\n </Heading>\n )}\n </div>\n\n {/* \u6309\u94AE\u7EC4 */}\n {(secondaryButtonText || primaryButtonText) && (\n <div\n className={cn(\n 'scene-shelf-v2-product-card-buttons laptop:flex-nowrap lg-desktop:gap-3 flex flex-wrap gap-2',\n classNames?.productCardButtons\n )}\n >\n {secondaryButtonText && (\n <Button\n variant=\"secondary\"\n className=\"laptop:grow-0 flex-1 whitespace-nowrap\"\n onClick={() => {\n handleSecondary()\n gaTrack({\n event: 'ga4Event',\n event_name: 'component_click',\n event_parameters: {\n page_group: pageGroup || 'Home Page',\n component_type: 'copy',\n component_name: 'scene_shelf_product',\n component_title: product.title,\n component_description: '',\n button_name: secondaryButtonText,\n SKU: product.sku || '',\n position: index,\n },\n })\n }}\n disabled={product.soldOut && secondaryButtonFun !== 'learnMore'}\n loading={secondaryLoading}\n >\n {secondaryButtonText}\n </Button>\n )}\n {primaryButtonText && (\n <Button\n variant=\"primary\"\n className=\"laptop:grow-0 flex-1 whitespace-nowrap\"\n onClick={() => {\n handlePrimary()\n gaTrack({\n event: 'ga4Event',\n event_name: 'component_click',\n event_parameters: {\n page_group: pageGroup || 'Home Page',\n component_type: 'copy',\n component_name: 'scene_shelf_product',\n component_title: product.title,\n component_description: '',\n button_name: primaryButtonText,\n SKU: product.sku || '',\n position: index,\n },\n })\n }}\n disabled={product.soldOut && primaryButtonFun !== 'learnMore'}\n loading={primaryLoading}\n >\n {primaryButtonText}\n </Button>\n )}\n </div>\n )}\n </div>\n </div>\n </div>\n )\n }\n)\n\nProductCardInner.displayName = 'SceneShelfV2.ProductCard'\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Main Component\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst SceneShelfV2 = React.forwardRef<HTMLDivElement, SceneShelfV2Props>(\n (\n { className, classNames = {}, data, onPlayClick, onImageClick, onLearnMore, onShopNow, onAddToCart, ...props },\n ref\n ) => {\n const {\n theme = 'light',\n sceneImage,\n productsTitle,\n products,\n secondaryButtonText,\n secondaryButtonFun,\n primaryButtonText,\n primaryButtonFun,\n viewMoreLimit = 2,\n copy,\n } = data\n const videoRef = React.useRef<HTMLVideoElement>(null)\n const mediaRef = React.useRef<HTMLDivElement>(null)\n const productWrapperRef = React.useRef<HTMLDivElement>(null)\n const [isPlaying, setIsPlaying] = React.useState(false)\n const [isExpanded, setIsExpanded] = React.useState(false)\n const { trackingData } = useAiuiContext()\n\n useExposure(mediaRef, {\n componentType: 'image',\n componentName: 'scene_shelf_banner',\n })\n\n useViewItemList(productWrapperRef, {\n componentType: 'video',\n componentName: 'scene_shelf_banner',\n itemListName: 'Scene_Shelf_2_Products',\n items: products.map((item, index) => ({\n item_id: item.sku ?? '',\n item_name: item.title,\n item_variant: item.variantId ?? '',\n price: item.currentPrice,\n index: index,\n })),\n tabName: '',\n })\n\n const visibleLimit = useGridRowCount({\n rows: viewMoreLimit ?? 0,\n mobileCols: 2,\n })\n\n const hasVideo = React.useMemo(\n () =>\n [sceneImage?.pc, sceneImage?.desktop, sceneImage?.laptop, sceneImage?.pad, sceneImage?.mobile].some(\n media => media?.mimeType === 'video/mp4'\n ),\n [sceneImage]\n )\n\n const handlePlayButtonClick = React.useCallback(() => {\n const video = videoRef.current\n if (video) {\n if (video.paused) {\n video.play()\n setIsPlaying(true)\n onPlayClick?.(true)\n } else {\n video.pause()\n setIsPlaying(false)\n onPlayClick?.(false)\n }\n } else {\n onPlayClick?.(true)\n }\n gaTrack({\n event: 'ga4Event',\n event_name: 'component_click',\n event_parameters: {\n page_group: trackingData?.pageGroup,\n component_type: 'video',\n component_name: 'scene_shelf_banner',\n position: 1,\n creative_id: sceneImage?.pc?.id,\n },\n })\n }, [onPlayClick, sceneImage?.pc?.id, trackingData?.pageGroup])\n\n // \u8FDB\u5165\u89C6\u7A97\u81EA\u52A8\u64AD\u653E\n React.useEffect(() => {\n const video = videoRef.current\n if (!video || !hasVideo) return\n\n const observer = new IntersectionObserver(\n entries => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n // \u8FDB\u5165\u89C6\u7A97\uFF0C\u81EA\u52A8\u64AD\u653E\n video.play().catch(error => {\n // \u5904\u7406\u81EA\u52A8\u64AD\u653E\u5931\u8D25\uFF08\u6D4F\u89C8\u5668\u7B56\u7565\u53EF\u80FD\u963B\u6B62\u81EA\u52A8\u64AD\u653E\uFF09\n console.warn('Video autoplay failed:', error)\n })\n } else {\n // \u79BB\u5F00\u89C6\u7A97\uFF0C\u6682\u505C\u64AD\u653E\n video.pause()\n }\n })\n },\n {\n threshold: 0.5, // \u5F53\u89C6\u9891 50% \u53EF\u89C1\u65F6\u89E6\u53D1\n }\n )\n\n observer.observe(video)\n\n return () => {\n observer.disconnect()\n }\n }, [])\n\n return (\n <div\n {...props}\n ref={ref}\n className={cn(\n 'scene-shelf-v2-root w-full overflow-hidden',\n { 'aiui-dark': theme === 'dark' },\n className,\n classNames?.root\n )}\n >\n {/* \u2500\u2500 \u5A92\u4F53\u533A \u2500\u2500 */}\n <div\n className={cn(\n 'scene-shelf-v2-media laptop:h-[360px] tablet:h-[400px] desktop:h-[384px] rounded-box tablet:rounded-t-box tablet:rounded-b-none lg-desktop:h-[480px] relative h-[240px] overflow-hidden',\n classNames?.media\n )}\n ref={mediaRef}\n >\n <Media\n pcImage={sceneImage?.pc}\n desktopImage={sceneImage?.desktop}\n laptopImage={sceneImage?.laptop}\n padImage={sceneImage?.pad}\n mobileImage={sceneImage?.mobile}\n className=\"size-full\"\n videoClassName=\"absolute inset-0 size-full object-cover\"\n videoRef={videoRef}\n onVideoPlay={() => setIsPlaying(true)}\n onVideoPause={() => setIsPlaying(false)}\n onVideoEnded={() => setIsPlaying(false)}\n />\n {/* \u6E10\u53D8\u906E\u7F69 */}\n <div\n aria-hidden=\"true\"\n className={cn(\n 'scene-shelf-v2-media-overlay pointer-events-none absolute inset-0',\n classNames?.mediaOverlay\n )}\n />\n\n {/* \u5F15\u8A00 + \u64AD\u653E/\u6682\u505C\u6309\u94AE */}\n {hasVideo && (\n <div className=\"desktop:gap-16 desktop:p-8 absolute inset-0 flex items-end justify-end gap-4 p-6\">\n <button\n type=\"button\"\n aria-label={isPlaying ? 'Pause video' : 'Play video'}\n onClick={handlePlayButtonClick}\n className={cn(\n 'scene-shelf-v2-media-play-button flex size-14 shrink-0 items-center justify-center rounded-full bg-white/20 transition-opacity hover:opacity-80',\n classNames?.mediaPlayButton\n )}\n >\n {isPlaying ? <PauseIcon /> : <PlayIcon />}\n </button>\n </div>\n )}\n </div>\n\n {/* \u2500\u2500 \u4EA7\u54C1\u533A \u2500\u2500 */}\n <div\n ref={productWrapperRef}\n className={cn(\n 'scene-shelf-v2-products text-info-primary tablet:bg-container-primary laptop:p-6 desktop:p-8 rounded-b-box tablet:p-4 flex flex-col gap-4 bg-transparent p-0 pt-3',\n classNames?.products\n )}\n >\n {productsTitle && (\n <Heading\n as=\"h2\"\n size={3}\n className={cn('scene-shelf-v2-products-title text-info-primary', classNames?.productsTitle)}\n html={productsTitle}\n />\n )}\n\n {/* Mobile\uFF1A2\u5217\u5E73\u94FA */}\n <div className=\"tablet:hidden grid grid-cols-2 gap-3\">\n {(() => {\n const shouldShowViewMore =\n viewMoreLimit !== undefined && viewMoreLimit > 0 && products.length > visibleLimit\n const displayedProducts = shouldShowViewMore && !isExpanded ? products.slice(0, visibleLimit) : products\n\n return (\n <>\n {displayedProducts.map((product, index) => (\n <ProductCardInner\n key={product.productKey}\n isShowTag={data.isShowTag ?? true}\n product={product}\n onImageClick={onImageClick}\n onLearnMore={onLearnMore}\n onShopNow={onShopNow}\n onAddToCart={onAddToCart}\n secondaryButtonText={secondaryButtonText}\n secondaryButtonFun={secondaryButtonFun}\n primaryButtonText={primaryButtonText}\n primaryButtonFun={primaryButtonFun}\n classNames={classNames}\n theme={theme}\n index={index}\n />\n ))}\n {shouldShowViewMore && (\n <div className=\"col-span-2 mt-6 flex justify-center\">\n <button\n type=\"button\"\n onClick={() => setIsExpanded(prev => !prev)}\n className=\"text-info-primary hover:text-brand-0 flex items-center gap-2 text-[14px] font-bold transition-colors\"\n aria-expanded={isExpanded}\n >\n {isExpanded ? (copy?.viewLessLabel ?? 'View Less') : (copy?.viewMoreLabel ?? 'View More')}\n <svg\n className={cn('size-4 transition-transform', isExpanded && 'rotate-180')}\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 9l-7 7-7-7\" />\n </svg>\n </button>\n </div>\n )}\n </>\n )\n })()}\n </div>\n\n {/* Tablet\uFF1ASwiper \u6A2A\u6ED1 */}\n <div className=\"tablet:block hidden\">\n <div className=\"relative\">\n <Swiper\n slidesPerView=\"auto\"\n observer\n observeParents\n modules={[Mousewheel]}\n mousewheel={{\n enabled: true,\n forceToAxis: true,\n sensitivity: 1,\n }}\n className=\"!overflow-visible\"\n breakpoints={{\n 768: {\n spaceBetween: 16,\n slidesPerView: products.length > 3 ? 2.3 : 2,\n },\n 1024: {\n spaceBetween: 16,\n slidesPerView: products.length > 3 ? 2.8 : 3,\n },\n 1440: {\n spaceBetween: 16,\n slidesPerView: products.length > 4 ? 3.8 : 4,\n },\n 1920: {\n spaceBetween: 16,\n slidesPerView: products.length > 4 ? 3.8 : 4,\n },\n }}\n >\n {products.map((product, index) => (\n <SwiperSlide key={product.productKey} className={cn('!h-auto ', classNames.productCardSlideWrapper)}>\n <ProductCardInner\n product={product}\n isShowTag={data.isShowTag ?? true}\n onImageClick={onImageClick}\n onLearnMore={onLearnMore}\n onShopNow={onShopNow}\n onAddToCart={onAddToCart}\n secondaryButtonText={secondaryButtonText}\n secondaryButtonFun={secondaryButtonFun}\n primaryButtonText={primaryButtonText}\n primaryButtonFun={primaryButtonFun}\n classNames={classNames}\n theme={theme}\n index={index}\n />\n </SwiperSlide>\n ))}\n </Swiper>\n </div>\n </div>\n </div>\n </div>\n )\n }\n)\n\nSceneShelfV2.displayName = 'SceneShelfV2'\nexport default withLayout(SceneShelfV2)\nexport { ProductCardInner as SceneShelfV2ProductCard }\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { cn, getLocalizedPath } from '../../helpers/index.js'\nimport { Heading, Text, Badge, Button, Picture } from '../../components/index.js'\nimport Media from '../Media/index.js'\nimport type { ResponsiveMedia, Theme } from '../../types/props.js'\nimport { Swiper, SwiperSlide } from 'swiper/react'\nimport { Mousewheel } from 'swiper/modules'\nimport 'swiper/css'\nimport 'swiper/css/navigation'\nimport { withLayout } from '../../shared/Styles.js'\nimport { useGridRowCount } from '../../hooks/useGridRowCount.js'\nimport { useExposure } from '../../hooks/useExposure.js'\nimport { useViewItemList } from '../../hooks/useViewItemList.js'\nimport { trackUrlRef } from '../../shared/trackUrlRef.js'\nimport { useAiuiContext } from '../AiuiProvider/index.js'\nimport { gaTrack } from '../../shared/track.js'\n\nconst componentType = 'shelf'\nconst componentName = 'scene_shelf_v2'\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Types\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * \u6309\u94AE\u529F\u80FD\u7C7B\u578B\n */\nexport type ButtonFunctionType = 'buyNow' | 'addCart' | 'learnMore'\n\nexport type SceneShelfV2SemanticName =\n | 'root'\n | 'media'\n | 'mediaOverlay'\n | 'mediaQuote'\n | 'mediaPlayButton'\n | 'products'\n | 'productsTitle'\n | 'productGrid'\n | 'productCardSlideWrapper'\n | 'productCard'\n | 'productCardImage'\n | 'productCardTags'\n | 'productCardTitle'\n | 'productCardDescription'\n | 'productCardPriceWrapper'\n | 'productCardCurrentPrice'\n | 'productCardOriginalPrice'\n | 'productCardButtons'\n\nexport interface SceneShelfV2Tag {\n label: string\n variant?: 'outline' | 'fill'\n}\n\nexport interface SceneShelfV2Product {\n /** \u4EA7\u54C1\u552F\u4E00\u6807\u8BC6 */\n productKey: string\n /** \u4EA7\u54C1\u4E3B\u6807\u9898 */\n title: string\n /** \u4EA7\u54C1\u63CF\u8FF0 */\n description?: string\n /** \u4EA7\u54C1\u56FE\u7247 */\n imageUrl: string\n imageAlt: string\n /**\n * \u4EA7\u54C1\u94FE\u63A5 URL\u3002\n */\n href?: string\n /** \u5F53\u524D\u4EF7\u683C\uFF08\u683C\u5F0F\u5316\u5B57\u7B26\u4E32\uFF0C\u5982 \"$1,999.00\"\uFF09 */\n currentPrice: string\n /** \u539F\u4EF7\uFF08\u663E\u793A\u5220\u9664\u7EBF\uFF09 */\n originalPrice?: string\n /** \u6807\u7B7E\u5217\u8868 */\n tags?: SceneShelfV2Tag[]\n /** \u662F\u5426\u552E\u7F44 */\n soldOut?: boolean\n /**\n * sku\n */\n sku?: string\n /**\n * \u53D8\u4F53id\n */\n variantId?: string\n /** \u81EA\u5B9A\u4E49\u4EA7\u54C1\u540D\u79F0 */\n custom_name?: string\n /** \u81EA\u5B9A\u4E49\u4EA7\u54C1\u63CF\u8FF0 */\n custom_description?: string\n}\n\n/**\n * \u6587\u6848\u914D\u7F6E\n */\nexport interface SceneShelfV2CopyConfig {\n /** \u67E5\u770B\u66F4\u591A\u6807\u7B7E */\n viewMoreLabel?: string\n /** \u6536\u8D77\u6807\u7B7E */\n viewLessLabel?: string\n}\n\nexport interface SceneShelfV2Data {\n theme?: 'light' | 'dark'\n isShowTag?: boolean\n sceneImage: ResponsiveMedia\n /** \u4EA7\u54C1\u533A\u6807\u9898\uFF08\u53EF\u9009\uFF09 */\n productsTitle?: string\n /** \u4EA7\u54C1\u5217\u8868 */\n products: SceneShelfV2Product[]\n /** \u6B21\u8981\u6309\u94AE\u6587\u672C */\n secondaryButtonText?: string\n /** \u6B21\u8981\u6309\u94AE\u529F\u80FD\u7C7B\u578B */\n secondaryButtonFun?: ButtonFunctionType\n /** \u4E3B\u8981\u6309\u94AE\u6587\u672C */\n primaryButtonText?: string\n /** \u4E3B\u8981\u6309\u94AE\u529F\u80FD\u7C7B\u578B */\n primaryButtonFun?: ButtonFunctionType\n /** \u67E5\u770B\u66F4\u591A\u9650\u5236\u6570\uFF08\u624B\u673A\u7AEF\u8D85\u8FC7\u4E24\u884C\u65F6\u663E\u793AviewMore\u6309\u94AE\uFF09 */\n viewMoreLimit?: number\n /** \u6587\u6848\u914D\u7F6E */\n copy?: SceneShelfV2CopyConfig\n}\n\nexport interface SceneShelfV2Props extends React.HTMLAttributes<HTMLDivElement> {\n data: SceneShelfV2Data\n /**\n * \u70B9\u51FB\u64AD\u653E/\u6682\u505C\u6309\u94AE\u56DE\u8C03\u3002\n * \u5F53\u5A92\u4F53\u533A\u4E3A\u89C6\u9891\u65F6\uFF0C\u7EC4\u4EF6\u5185\u90E8\u4F1A\u81EA\u52A8\u63A7\u5236\u64AD\u653E/\u6682\u505C,\u6B64\u56DE\u8C03\u4ECD\u4F1A\u89E6\u53D1\u3002\n */\n onPlayClick?: (isPlaying: boolean) => void\n /** \u70B9\u51FB\u4EA7\u54C1\u56FE\u7247\u56DE\u8C03 */\n onImageClick?: (product: SceneShelfV2Product) => void\n /** \u70B9\u51FB\u4E86\u89E3\u66F4\u591A\u56DE\u8C03\uFF08\u652F\u6301\u5F02\u6B65\uFF09 */\n onLearnMore?: (link: string) => void | Promise<void>\n /** \u70B9\u51FB\u7ACB\u5373\u8D2D\u4E70\u56DE\u8C03\uFF08\u652F\u6301\u5F02\u6B65\uFF09 */\n onShopNow?: (product: SceneShelfV2Product) => void | Promise<void>\n /** \u70B9\u51FB\u52A0\u5165\u8D2D\u7269\u8F66\u56DE\u8C03\uFF08\u652F\u6301\u5F02\u6B65\uFF09 */\n onAddToCart?: (product: SceneShelfV2Product) => void | Promise<void>\n classNames?: Partial<Record<SceneShelfV2SemanticName, string>>\n}\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Icons\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst PlayIcon = () => (\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M8 5.14v13.72L19 12 8 5.14z\" fill=\"white\" />\n </svg>\n)\n\nconst PauseIcon = () => (\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <rect x=\"6\" y=\"5\" width=\"4\" height=\"14\" rx=\"1\" fill=\"white\" />\n <rect x=\"14\" y=\"5\" width=\"4\" height=\"14\" rx=\"1\" fill=\"white\" />\n </svg>\n)\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Product Card\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface ProductCardInnerProps {\n product: SceneShelfV2Product\n isShowTag: boolean\n onImageClick?: (product: SceneShelfV2Product) => void\n onLearnMore?: (link: string) => void | Promise<void>\n onShopNow?: (product: SceneShelfV2Product) => void | Promise<void>\n onAddToCart?: (product: SceneShelfV2Product) => void | Promise<void>\n secondaryButtonText?: string\n secondaryButtonFun?: ButtonFunctionType\n primaryButtonText?: string\n primaryButtonFun?: ButtonFunctionType\n classNames?: Partial<Record<SceneShelfV2SemanticName, string>>\n className?: string\n theme?: Theme\n index?: number\n}\n\nconst ProductCardInner = React.memo(\n ({\n product,\n isShowTag = true,\n onImageClick,\n onLearnMore,\n onShopNow,\n onAddToCart,\n secondaryButtonText,\n secondaryButtonFun,\n primaryButtonText,\n primaryButtonFun,\n classNames,\n className,\n theme,\n index,\n }: ProductCardInnerProps) => {\n const { locale = 'us', trackingData } = useAiuiContext()\n const [primaryLoading, setPrimaryLoading] = React.useState(false)\n const [secondaryLoading, setSecondaryLoading] = React.useState(false)\n\n const pageGroup = trackingData?.pageGroup\n\n // \u6839\u636E\u6309\u94AE\u529F\u80FD\u7C7B\u578B\u8C03\u7528\u76F8\u5E94\u7684\u56DE\u8C03\u51FD\u6570\n const handleButtonClick = React.useCallback(\n async (buttonFun?: ButtonFunctionType, buttonType?: 'primary' | 'secondary') => {\n if (!buttonFun) return\n\n const setLoading = buttonType === 'primary' ? setPrimaryLoading : setSecondaryLoading\n setLoading(true)\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?.href ?? '')\n break\n default:\n break\n }\n } finally {\n setLoading(false)\n }\n },\n [onLearnMore, onShopNow, onAddToCart, product]\n )\n\n const handlePrimary = React.useCallback(\n () => handleButtonClick(primaryButtonFun, 'primary'),\n [handleButtonClick, primaryButtonFun]\n )\n const handleSecondary = React.useCallback(\n () => handleButtonClick(secondaryButtonFun, 'secondary'),\n [handleButtonClick, secondaryButtonFun]\n )\n\n const handleImageClick = React.useCallback(\n (e: React.MouseEvent) => {\n // \u5982\u679C\u6CA1\u6709\u63D0\u4F9B href \u4E14\u6709\u70B9\u51FB\u56DE\u8C03\uFF0C\u963B\u6B62\u9ED8\u8BA4\u884C\u4E3A\n if (!product.href && onImageClick) {\n e.preventDefault()\n }\n onImageClick?.(product)\n gaTrack({\n event: 'ga4Event',\n event_name: 'select_item',\n item_list_name: 'Scene_Shelf_2_Products',\n page_group: pageGroup,\n items: [\n {\n item_id: product.sku,\n item_name: product.custom_name || product.title,\n item_variant: product.variantId,\n price: product.currentPrice,\n index: index,\n },\n ],\n })\n },\n [index, onImageClick, pageGroup, product]\n )\n\n return (\n <div\n className={cn(\n 'scene-shelf-v2-product-card rounded-box bg-container-secondary-1 tablet:px-6 desktop:pb-6 desktop:px-6 box-border flex h-full flex-col items-center justify-between gap-3 overflow-hidden px-2 py-4',\n className,\n classNames?.productCard,\n {\n 'bg-container-secondary-0': theme === 'dark',\n }\n )}\n >\n {/* \u4EA7\u54C1\u56FE\u7247 */}\n {product.href ? (\n <a\n href={getLocalizedPath(\n trackUrlRef(product.href, pageGroup + '_' + componentType + '_' + componentName),\n locale\n )}\n onClick={handleImageClick}\n className={cn(\n 'scene-shelf-v2-product-card-image desktop:size-[196px] tablet:size-[140px] lg-desktop:size-[196px] flex size-[128px] shrink-0 items-center justify-center transition-opacity hover:opacity-80',\n classNames?.productCardImage\n )}\n aria-label={`View ${product.title}`}\n >\n <Picture\n source={product.imageUrl}\n alt={product.imageAlt}\n className=\"size-full\"\n imgClassName=\"object-contain\"\n />\n </a>\n ) : (\n <div\n className={cn(\n 'scene-shelf-v2-product-card-image desktop:size-[196px] tablet:size-[140px] lg-desktop:size-[196px] flex size-[128px] shrink-0 items-center justify-center ',\n onImageClick && 'cursor-pointer transition-opacity hover:opacity-80',\n classNames?.productCardImage\n )}\n onClick={onImageClick ? handleImageClick : undefined}\n role={onImageClick ? 'button' : undefined}\n tabIndex={onImageClick ? 0 : undefined}\n aria-label={onImageClick ? `View ${product.title}` : undefined}\n >\n <Picture\n source={product.imageUrl}\n alt={product.imageAlt}\n className=\"size-full\"\n imgClassName=\"object-contain\"\n />\n </div>\n )}\n\n {/* \u4EA7\u54C1\u4FE1\u606F */}\n <div className=\"desktop:gap-6 flex w-full flex-1 flex-col justify-between gap-4\">\n {/* \u6807\u7B7E + \u6807\u9898 + \u526F\u6807\u9898 */}\n <div className=\"flex flex-col gap-2\">\n <div\n className={cn(\n 'scene-shelf-v2-product-card-tags flex min-h-[24px] flex-wrap gap-1',\n classNames?.productCardTags\n )}\n >\n {isShowTag &&\n product?.tags?.map((tag, idx) => (\n <Badge key={idx} variant={tag.variant ?? 'outline'} size=\"sm\" className=\"\">\n {tag.label}\n </Badge>\n ))}\n </div>\n\n <Heading\n as=\"h3\"\n size={2}\n className={cn(\n 'scene-shelf-v2-product-card-title text-info-primary laptop:line-clamp-2 line-clamp-3 pr-[16%] text-[16px]',\n classNames?.productCardTitle\n )}\n >\n {product.custom_name || product.title}\n </Heading>\n\n {(product.custom_description || product.description) && (\n <Text\n as=\"p\"\n size={1}\n className={cn(\n 'scene-shelf-v2-product-card-description text-info-primary tablet:text-[14px] desktop:text-[16px] lg-desktop:text-[18px] line-clamp-1',\n classNames?.productCardDescription\n )}\n >\n {product.custom_description || product.description}\n </Text>\n )}\n </div>\n\n {/* \u4EF7\u683C + \u6309\u94AE */}\n <div className=\"flex flex-col gap-2\">\n {/* \u4EF7\u683C */}\n <div\n className={cn(\n 'scene-shelf-v2-product-card-price flex flex-wrap items-center gap-1',\n classNames?.productCardPriceWrapper\n )}\n >\n <Heading\n as=\"h6\"\n size={2}\n className={cn(\n 'scene-shelf-v2-product-card-current-price text-info-primary',\n classNames?.productCardCurrentPrice\n )}\n >\n {product.currentPrice}\n </Heading>\n {product.originalPrice && (\n <Heading\n as=\"h6\"\n size={2}\n className={cn(\n 'scene-shelf-v2-product-card-original-price text-info-tertiary line-through',\n classNames?.productCardOriginalPrice\n )}\n >\n {product.originalPrice}\n </Heading>\n )}\n </div>\n\n {/* \u6309\u94AE\u7EC4 */}\n {(secondaryButtonText || primaryButtonText) && (\n <div\n className={cn(\n 'scene-shelf-v2-product-card-buttons laptop:flex-nowrap lg-desktop:gap-3 flex flex-wrap gap-2',\n classNames?.productCardButtons\n )}\n >\n {secondaryButtonText && (\n <Button\n variant=\"secondary\"\n className=\"laptop:grow-0 flex-1 whitespace-nowrap\"\n onClick={() => {\n handleSecondary()\n gaTrack({\n event: 'ga4Event',\n event_name: 'component_click',\n event_parameters: {\n page_group: pageGroup || 'Home Page',\n component_type: 'copy',\n component_name: 'scene_shelf_product',\n component_title: product.title,\n component_description: '',\n button_name: secondaryButtonText,\n SKU: product.sku || '',\n position: index,\n },\n })\n }}\n disabled={product.soldOut && secondaryButtonFun !== 'learnMore'}\n loading={secondaryLoading}\n >\n {secondaryButtonText}\n </Button>\n )}\n {primaryButtonText && (\n <Button\n variant=\"primary\"\n className=\"laptop:grow-0 flex-1 whitespace-nowrap\"\n onClick={() => {\n handlePrimary()\n gaTrack({\n event: 'ga4Event',\n event_name: 'component_click',\n event_parameters: {\n page_group: pageGroup || 'Home Page',\n component_type: 'copy',\n component_name: 'scene_shelf_product',\n component_title: product.title,\n component_description: '',\n button_name: primaryButtonText,\n SKU: product.sku || '',\n position: index,\n },\n })\n }}\n disabled={product.soldOut && primaryButtonFun !== 'learnMore'}\n loading={primaryLoading}\n >\n {primaryButtonText}\n </Button>\n )}\n </div>\n )}\n </div>\n </div>\n </div>\n )\n }\n)\n\nProductCardInner.displayName = 'SceneShelfV2.ProductCard'\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Main Component\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst SceneShelfV2 = React.forwardRef<HTMLDivElement, SceneShelfV2Props>(\n (\n { className, classNames = {}, data, onPlayClick, onImageClick, onLearnMore, onShopNow, onAddToCart, ...props },\n ref\n ) => {\n const {\n theme = 'light',\n sceneImage,\n productsTitle,\n products,\n secondaryButtonText,\n secondaryButtonFun,\n primaryButtonText,\n primaryButtonFun,\n viewMoreLimit = 2,\n copy,\n } = data\n const videoRef = React.useRef<HTMLVideoElement>(null)\n const mediaRef = React.useRef<HTMLDivElement>(null)\n const productWrapperRef = React.useRef<HTMLDivElement>(null)\n const [isPlaying, setIsPlaying] = React.useState(false)\n const [isExpanded, setIsExpanded] = React.useState(false)\n const { trackingData } = useAiuiContext()\n\n useExposure(mediaRef, {\n componentType: 'image',\n componentName: 'scene_shelf_banner',\n })\n\n useViewItemList(productWrapperRef, {\n componentType: 'video',\n componentName: 'scene_shelf_banner',\n itemListName: 'Scene_Shelf_2_Products',\n items: products.map((item, index) => ({\n item_id: item.sku ?? '',\n item_name: item.title,\n item_variant: item.variantId ?? '',\n price: item.currentPrice,\n index: index,\n })),\n tabName: '',\n })\n\n const visibleLimit = useGridRowCount({\n rows: viewMoreLimit ?? 0,\n mobileCols: 2,\n })\n\n const hasVideo = React.useMemo(\n () =>\n [sceneImage?.pc, sceneImage?.desktop, sceneImage?.laptop, sceneImage?.pad, sceneImage?.mobile].some(\n media => media?.mimeType === 'video/mp4'\n ),\n [sceneImage]\n )\n\n const handlePlayButtonClick = React.useCallback(() => {\n const video = videoRef.current\n if (video) {\n if (video.paused) {\n video.play()\n setIsPlaying(true)\n onPlayClick?.(true)\n } else {\n video.pause()\n setIsPlaying(false)\n onPlayClick?.(false)\n }\n } else {\n onPlayClick?.(true)\n }\n gaTrack({\n event: 'ga4Event',\n event_name: 'component_click',\n event_parameters: {\n page_group: trackingData?.pageGroup,\n component_type: 'video',\n component_name: 'scene_shelf_banner',\n position: 1,\n creative_id: sceneImage?.pc?.id,\n },\n })\n }, [onPlayClick, sceneImage?.pc?.id, trackingData?.pageGroup])\n\n // \u8FDB\u5165\u89C6\u7A97\u81EA\u52A8\u64AD\u653E\n React.useEffect(() => {\n const video = videoRef.current\n if (!video || !hasVideo) return\n\n const observer = new IntersectionObserver(\n entries => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n // \u8FDB\u5165\u89C6\u7A97\uFF0C\u81EA\u52A8\u64AD\u653E\n video.play().catch(error => {\n // \u5904\u7406\u81EA\u52A8\u64AD\u653E\u5931\u8D25\uFF08\u6D4F\u89C8\u5668\u7B56\u7565\u53EF\u80FD\u963B\u6B62\u81EA\u52A8\u64AD\u653E\uFF09\n console.warn('Video autoplay failed:', error)\n })\n } else {\n // \u79BB\u5F00\u89C6\u7A97\uFF0C\u6682\u505C\u64AD\u653E\n video.pause()\n }\n })\n },\n {\n threshold: 0.5, // \u5F53\u89C6\u9891 50% \u53EF\u89C1\u65F6\u89E6\u53D1\n }\n )\n\n observer.observe(video)\n\n return () => {\n observer.disconnect()\n }\n }, [])\n\n return (\n <div\n {...props}\n ref={ref}\n className={cn(\n 'scene-shelf-v2-root w-full overflow-hidden',\n { 'aiui-dark': theme === 'dark' },\n className,\n classNames?.root\n )}\n >\n {/* \u2500\u2500 \u5A92\u4F53\u533A \u2500\u2500 */}\n <div\n className={cn(\n 'scene-shelf-v2-media laptop:h-[360px] tablet:h-[400px] desktop:h-[384px] rounded-box tablet:rounded-t-box tablet:rounded-b-none lg-desktop:h-[480px] relative h-[240px] overflow-hidden',\n classNames?.media\n )}\n ref={mediaRef}\n >\n <Media\n pcImage={sceneImage?.pc}\n desktopImage={sceneImage?.desktop}\n laptopImage={sceneImage?.laptop}\n padImage={sceneImage?.pad}\n mobileImage={sceneImage?.mobile}\n className=\"size-full\"\n videoClassName=\"absolute inset-0 size-full object-cover\"\n videoRef={videoRef}\n onVideoPlay={() => setIsPlaying(true)}\n onVideoPause={() => setIsPlaying(false)}\n onVideoEnded={() => setIsPlaying(false)}\n />\n {/* \u6E10\u53D8\u906E\u7F69 */}\n <div\n aria-hidden=\"true\"\n className={cn(\n 'scene-shelf-v2-media-overlay pointer-events-none absolute inset-0',\n classNames?.mediaOverlay\n )}\n />\n\n {/* \u5F15\u8A00 + \u64AD\u653E/\u6682\u505C\u6309\u94AE */}\n {hasVideo && (\n <div className=\"desktop:gap-16 desktop:p-8 absolute inset-0 flex items-end justify-end gap-4 p-6\">\n <button\n type=\"button\"\n aria-label={isPlaying ? 'Pause video' : 'Play video'}\n onClick={handlePlayButtonClick}\n className={cn(\n 'scene-shelf-v2-media-play-button flex size-14 shrink-0 items-center justify-center rounded-full bg-white/20 transition-opacity hover:opacity-80',\n classNames?.mediaPlayButton\n )}\n >\n {isPlaying ? <PauseIcon /> : <PlayIcon />}\n </button>\n </div>\n )}\n </div>\n\n {/* \u2500\u2500 \u4EA7\u54C1\u533A \u2500\u2500 */}\n <div\n ref={productWrapperRef}\n className={cn(\n 'scene-shelf-v2-products text-info-primary tablet:bg-container-primary laptop:p-6 desktop:p-8 rounded-b-box tablet:p-4 flex flex-col gap-4 bg-transparent p-0 pt-3',\n classNames?.products\n )}\n >\n {productsTitle && (\n <Heading\n as=\"h2\"\n size={3}\n className={cn('scene-shelf-v2-products-title text-info-primary', classNames?.productsTitle)}\n html={productsTitle}\n />\n )}\n\n {/* Mobile\uFF1A2\u5217\u5E73\u94FA */}\n <div className=\"tablet:hidden grid grid-cols-2 gap-3\">\n {(() => {\n const shouldShowViewMore =\n viewMoreLimit !== undefined && viewMoreLimit > 0 && products.length > visibleLimit\n const displayedProducts = shouldShowViewMore && !isExpanded ? products.slice(0, visibleLimit) : products\n\n return (\n <>\n {displayedProducts.map((product, index) => (\n <ProductCardInner\n key={product.productKey}\n isShowTag={data.isShowTag ?? true}\n product={product}\n onImageClick={onImageClick}\n onLearnMore={onLearnMore}\n onShopNow={onShopNow}\n onAddToCart={onAddToCart}\n secondaryButtonText={secondaryButtonText}\n secondaryButtonFun={secondaryButtonFun}\n primaryButtonText={primaryButtonText}\n primaryButtonFun={primaryButtonFun}\n classNames={classNames}\n theme={theme}\n index={index}\n />\n ))}\n {shouldShowViewMore && (\n <div className=\"col-span-2 mt-6 flex justify-center\">\n <button\n type=\"button\"\n onClick={() => setIsExpanded(prev => !prev)}\n className=\"text-info-primary hover:text-brand-0 flex items-center gap-2 text-[14px] font-bold transition-colors\"\n aria-expanded={isExpanded}\n >\n {isExpanded ? (copy?.viewLessLabel ?? 'View Less') : (copy?.viewMoreLabel ?? 'View More')}\n <svg\n className={cn('size-4 transition-transform', isExpanded && 'rotate-180')}\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 9l-7 7-7-7\" />\n </svg>\n </button>\n </div>\n )}\n </>\n )\n })()}\n </div>\n\n {/* Tablet\uFF1ASwiper \u6A2A\u6ED1 */}\n <div className=\"tablet:block hidden\">\n <div className=\"relative\">\n <Swiper\n slidesPerView=\"auto\"\n observer\n observeParents\n modules={[Mousewheel]}\n mousewheel={{\n enabled: true,\n forceToAxis: true,\n sensitivity: 1,\n }}\n className=\"!overflow-visible\"\n breakpoints={{\n 768: {\n spaceBetween: 16,\n slidesPerView: products.length > 3 ? 2.3 : 2,\n },\n 1024: {\n spaceBetween: 16,\n slidesPerView: products.length > 3 ? 2.8 : 3,\n },\n 1440: {\n spaceBetween: 16,\n slidesPerView: products.length > 4 ? 3.8 : 4,\n },\n 1920: {\n spaceBetween: 16,\n slidesPerView: products.length > 4 ? 3.8 : 4,\n },\n }}\n >\n {products.map((product, index) => (\n <SwiperSlide key={product.productKey} className={cn('!h-auto ', classNames.productCardSlideWrapper)}>\n <ProductCardInner\n product={product}\n isShowTag={data.isShowTag ?? true}\n onImageClick={onImageClick}\n onLearnMore={onLearnMore}\n onShopNow={onShopNow}\n onAddToCart={onAddToCart}\n secondaryButtonText={secondaryButtonText}\n secondaryButtonFun={secondaryButtonFun}\n primaryButtonText={primaryButtonText}\n primaryButtonFun={primaryButtonFun}\n classNames={classNames}\n theme={theme}\n index={index}\n />\n </SwiperSlide>\n ))}\n </Swiper>\n </div>\n </div>\n </div>\n </div>\n )\n }\n)\n\nSceneShelfV2.displayName = 'SceneShelfV2'\nexport default withLayout(SceneShelfV2)\nexport { ProductCardInner as SceneShelfV2ProductCard }\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["SceneShelfV2_exports", "__export", "ProductCardInner", "SceneShelfV2_default", "__toCommonJS", "import_jsx_runtime", "React", "import_helpers", "import_components", "import_Media", "import_react", "import_modules", "import_css", "import_navigation", "import_Styles", "import_useGridRowCount", "import_useExposure", "import_useViewItemList", "import_trackUrlRef", "import_AiuiProvider", "import_track", "componentType", "componentName", "PlayIcon", "PauseIcon", "product", "isShowTag", "onImageClick", "onLearnMore", "onShopNow", "onAddToCart", "secondaryButtonText", "secondaryButtonFun", "primaryButtonText", "primaryButtonFun", "classNames", "className", "theme", "index", "locale", "trackingData", "primaryLoading", "setPrimaryLoading", "secondaryLoading", "setSecondaryLoading", "pageGroup", "handleButtonClick", "buttonFun", "buttonType", "setLoading", "handlePrimary", "handleSecondary", "handleImageClick", "e", "tag", "idx", "SceneShelfV2", "data", "onPlayClick", "props", "ref", "sceneImage", "productsTitle", "products", "viewMoreLimit", "copy", "videoRef", "mediaRef", "productWrapperRef", "isPlaying", "setIsPlaying", "isExpanded", "setIsExpanded", "item", "visibleLimit", "hasVideo", "media", "handlePlayButtonClick", "video", "observer", "entries", "entry", "error", "Media", "shouldShowViewMore", "displayedProducts", "prev"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{jsx as t,jsxs as
|
|
1
|
+
"use client";import{jsx as t,jsxs as p}from"react/jsx-runtime";import{forwardRef as w,useEffect as q,useRef as x,useState as E,useImperativeHandle as S}from"react";import{cn as s}from"../../helpers/utils.js";import v from"../../components/picture.js";import{withLayout as M}from"../../shared/Styles.js";import{useMediaQuery as B}from"react-responsive";import{useExposure as T}from"../../hooks/useExposure.js";import{Swiper as I,SwiperSlide as j}from"swiper/react";import{Pagination as P,FreeMode as L,Mousewheel as z}from"swiper/modules";import A from"../Title/index.js";const H="copy",D="store_benefits",R=(e,a)=>{const i=[];for(let r=0;r<e.length;r+=a)i.push(e.slice(r,r+a));return i},b=w(({data:{items:e=[],itemShape:a,title:i,theme:r},className:o},m)=>{const[c,k]=E(!1),u=B({query:"(max-width: 768px)"}),f=x(null),d=x(null);S(m,()=>d.current),T(d,{componentType:H,componentName:D}),q(()=>{k(u)},[u]);const h=c?R(e,3):e;return p("div",{ref:d,className:s("brand-equity-wrapper w-full",{"aiui-dark":r==="dark"},o),children:[i&&t(A,{data:{title:i}}),c?p(I,{className:s(o),modules:[L,z,P],freeMode:!0,mousewheel:{forceToAxis:!0},pagination:{clickable:!0,el:f.current},breakpoints:{0:{spaceBetween:12}},children:[h?.map((l,n)=>t(j,{className:"!flex flex-col gap-3",children:Array.isArray(l)&&l?.map((N,y)=>t(g,{data:N,itemShape:a,index:y,theme:r},y))},"SwiperSlide"+n)),t("div",{ref:f,className:"mt-3 flex justify-center"})]}):t("div",{className:s("grid grid-cols-1 gap-3","tablet:grid-cols-2","laptop:gap-4 laptop:grid-cols-10"),children:e.map((l,n)=>t(g,{data:l,itemShape:a,index:n,theme:r},n))})]})}),g=({data:e,itemShape:a,index:i,theme:r})=>p("div",{className:s("brand-equity-item",`brand-equity-item-${i+1}`,e.containerName?`brand-equity-item--${e.containerName}`:void 0,"bg-container-secondary-1 box-border flex w-full flex-col p-4","desktop:p-6 justify-between","laptop:col-span-3 lg-desktop:p-8","laptop:h-[192px] lg-desktop:h-[240px] h-[160px]",{"laptop:col-span-4":[0,5,6,11].includes(i),"bg-container-primary":r==="dark"},a==="round"?"rounded-box":"rounded-none",e.className),children:[p("div",{className:"lg-desktop:h-[36px] flex h-[30px] items-center justify-between gap-3",children:[t("h3",{className:"lg-desktop:text-[18px] desktop:text-[16px] text-info-primary text-[14px] font-bold leading-[1.2] tracking-[-0.02em]",children:e.title}),e.type==="avatar"?t("div",{className:"flex shrink-0 -space-x-2",children:e?.avatarList?.map((o,m)=>t("div",{className:s("border-container-primary size-[30px] overflow-hidden rounded-full border-2","relative inline-block shrink-0","lg-desktop:size-[36px]"),children:t(v,{source:o.avatar?.url,alt:o.avatar?.alt,className:"size-full object-cover"})},m))}):t("div",{className:"lg-desktop:size-[36px] size-[30px] shrink-0",children:t(v,{className:"size-full object-cover",source:e.icon?.url,alt:e.icon?.alt,imgClassName:"w-full h-full object-cover"})})]}),t("p",{className:"lg-desktop:text-[24px] text-info-primary line-clamp-3 text-[20px] font-bold leading-[1.2] tracking-[-0.04em]",children:e.description})]});b.displayName="BrandEquity";var U=M(b);export{U as default};
|
|
2
2
|
//# sourceMappingURL=BrandEquity.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/biz-components/BrandEquity/BrandEquity.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\nimport { forwardRef, useEffect, useRef, useState, useImperativeHandle } from 'react'\n\nimport { cn } from '../../helpers/utils.js'\nimport Picture from '../../components/picture.js'\nimport { withLayout } from '../../shared/Styles.js'\nimport type { BrandEquityProps, BrandEquityItemProps } from './types.js'\n\nimport type { Img } from '../../types/props.js'\nimport { useMediaQuery } from 'react-responsive'\nimport { useExposure } from '../../hooks/useExposure.js'\n\nimport { Swiper, SwiperSlide } from 'swiper/react'\nimport { Pagination, FreeMode, Mousewheel } from 'swiper/modules'\nimport Title from '../Title/index.js'\n\nconst componentType = 'copy'\nconst componentName = 'store_benefits'\n\nconst chunkArray = (arr: BrandEquityItemProps[], size: number) => {\n const chunks = []\n for (let i = 0; i < arr.length; i += size) {\n chunks.push(arr.slice(i, i + size))\n }\n return chunks\n}\n\nconst BrandEquity = forwardRef<HTMLDivElement, BrandEquityProps>(\n ({ data: { items = [], itemShape, title, theme }, className }, ref) => {\n const [isMobile, setIsMobile] = useState(false)\n const mediaQuery = useMediaQuery({ query: '(max-width: 768px)' })\n const paginationRef = useRef<HTMLDivElement>(null)\n const innerRef = useRef<HTMLDivElement>(null)\n useImperativeHandle(ref, () => innerRef.current as HTMLDivElement)\n useExposure(innerRef, {\n componentType,\n componentName,\n })\n\n useEffect(() => {\n setIsMobile(mediaQuery)\n }, [mediaQuery])\n\n const itemsArray = isMobile ? chunkArray(items, 3) : items\n return (\n <div ref={innerRef} className={cn('brand-equity-wrapper w-full', { 'aiui-dark': theme === 'dark' }, className)}>\n {title && <Title data={{ title: title }} />}\n {isMobile ? (\n <Swiper\n className={cn(className)}\n modules={[FreeMode, Mousewheel, Pagination]}\n freeMode={true}\n mousewheel={{\n forceToAxis: true,\n }}\n pagination={{\n clickable: true,\n el: paginationRef.current,\n }}\n breakpoints={{\n 0: {\n spaceBetween: 12,\n },\n }}\n >\n {itemsArray?.map((item, jIndex) => (\n <SwiperSlide key={'SwiperSlide' + jIndex} className=\"!flex flex-col gap-3\">\n {Array.isArray(item) &&\n item?.map((item, index) => (\n <BrandEquityItem key={index} data={item} itemShape={itemShape} index={index} />\n ))}\n </SwiperSlide>\n ))}\n <div ref={paginationRef} className=\"mt-3 flex justify-center\"></div>\n </Swiper>\n ) : (\n <div className={cn('grid grid-cols-1 gap-3', 'tablet:grid-cols-2', 'laptop:gap-4 laptop:grid-cols-10')}>\n {items.map((item, index) => (\n <BrandEquityItem key={index} data={item} itemShape={itemShape} index={index} />\n ))}\n </div>\n )}\n </div>\n )\n }\n)\n\nconst BrandEquityItem = ({\n data,\n itemShape,\n index,\n}: {\n data: BrandEquityItemProps\n itemShape?: 'round' | 'square'\n index: number\n}) => {\n return (\n <div\n className={cn(\n 'brand-equity-item',\n `brand-equity-item-${index + 1}`,\n data.containerName ? `brand-equity-item--${data.containerName}` : undefined,\n 'bg-container-
|
|
5
|
-
"mappings": "aA8CkB,cAAAA,EAER,QAAAC,MAFQ,oBA7ClB,OAAS,cAAAC,EAAY,aAAAC,EAAW,UAAAC,EAAQ,YAAAC,EAAU,uBAAAC,MAA2B,QAE7E,OAAS,MAAAC,MAAU,yBACnB,OAAOC,MAAa,8BACpB,OAAS,cAAAC,MAAkB,yBAI3B,OAAS,iBAAAC,MAAqB,mBAC9B,OAAS,eAAAC,MAAmB,6BAE5B,OAAS,UAAAC,EAAQ,eAAAC,MAAmB,eACpC,OAAS,cAAAC,EAAY,YAAAC,EAAU,cAAAC,MAAkB,iBACjD,OAAOC,MAAW,oBAElB,MAAMC,EAAgB,OAChBC,EAAgB,iBAEhBC,EAAa,CAACC,EAA6BC,IAAiB,CAChE,MAAMC,EAAS,CAAC,EAChB,QAASC,EAAI,EAAGA,EAAIH,EAAI,OAAQG,GAAKF,EACnCC,EAAO,KAAKF,EAAI,MAAMG,EAAGA,EAAIF,CAAI,CAAC,EAEpC,OAAOC,CACT,EAEME,EAAcvB,EAClB,CAAC,CAAE,KAAM,CAAE,MAAAwB,EAAQ,CAAC,EAAG,UAAAC,EAAW,MAAAC,EAAO,MAAAC,CAAM,EAAG,UAAAC,CAAU,EAAGC,IAAQ,CACrE,KAAM,CAACC,EAAUC,CAAW,EAAI5B,EAAS,EAAK,EACxC6B,EAAaxB,EAAc,CAAE,MAAO,oBAAqB,CAAC,EAC1DyB,EAAgB/B,EAAuB,IAAI,EAC3CgC,EAAWhC,EAAuB,IAAI,EAC5CE,EAAoByB,EAAK,IAAMK,EAAS,OAAyB,EACjEzB,EAAYyB,EAAU,CACpB,cAAAlB,EACA,cAAAC,CACF,CAAC,EAEDhB,EAAU,IAAM,CACd8B,EAAYC,CAAU,CACxB,EAAG,CAACA,CAAU,CAAC,EAEf,MAAMG,EAAaL,EAAWZ,EAAWM,EAAO,CAAC,EAAIA,EACrD,OACEzB,EAAC,OAAI,IAAKmC,EAAU,UAAW7B,EAAG,8BAA+B,CAAE,YAAasB,IAAU,MAAO,EAAGC,CAAS,EAC1G,UAAAF,GAAS5B,EAACiB,EAAA,CAAM,KAAM,CAAE,MAAOW,CAAM,EAAG,EACxCI,EACC/B,EAACW,EAAA,CACC,UAAWL,EAAGuB,CAAS,EACvB,QAAS,CAACf,EAAUC,EAAYF,CAAU,EAC1C,SAAU,GACV,WAAY,CACV,YAAa,EACf,EACA,WAAY,CACV,UAAW,GACX,GAAIqB,EAAc,OACpB,EACA,YAAa,CACX,EAAG,CACD,aAAc,EAChB,CACF,EAEC,UAAAE,GAAY,IAAI,CAACC,EAAMC,IACtBvC,EAACa,EAAA,CAAyC,UAAU,uBACjD,eAAM,QAAQyB,CAAI,GACjBA,GAAM,IAAI,CAACA,EAAME,IACfxC,EAACyC,EAAA,CAA4B,KAAMH,EAAM,UAAWX,EAAW,MAAOa,
|
|
4
|
+
"sourcesContent": ["'use client'\nimport { forwardRef, useEffect, useRef, useState, useImperativeHandle } from 'react'\n\nimport { cn } from '../../helpers/utils.js'\nimport Picture from '../../components/picture.js'\nimport { withLayout } from '../../shared/Styles.js'\nimport type { BrandEquityProps, BrandEquityItemProps } from './types.js'\n\nimport type { Img, Theme } from '../../types/props.js'\nimport { useMediaQuery } from 'react-responsive'\nimport { useExposure } from '../../hooks/useExposure.js'\n\nimport { Swiper, SwiperSlide } from 'swiper/react'\nimport { Pagination, FreeMode, Mousewheel } from 'swiper/modules'\nimport Title from '../Title/index.js'\n\nconst componentType = 'copy'\nconst componentName = 'store_benefits'\n\nconst chunkArray = (arr: BrandEquityItemProps[], size: number) => {\n const chunks = []\n for (let i = 0; i < arr.length; i += size) {\n chunks.push(arr.slice(i, i + size))\n }\n return chunks\n}\n\nconst BrandEquity = forwardRef<HTMLDivElement, BrandEquityProps>(\n ({ data: { items = [], itemShape, title, theme }, className }, ref) => {\n const [isMobile, setIsMobile] = useState(false)\n const mediaQuery = useMediaQuery({ query: '(max-width: 768px)' })\n const paginationRef = useRef<HTMLDivElement>(null)\n const innerRef = useRef<HTMLDivElement>(null)\n useImperativeHandle(ref, () => innerRef.current as HTMLDivElement)\n useExposure(innerRef, {\n componentType,\n componentName,\n })\n\n useEffect(() => {\n setIsMobile(mediaQuery)\n }, [mediaQuery])\n\n const itemsArray = isMobile ? chunkArray(items, 3) : items\n return (\n <div ref={innerRef} className={cn('brand-equity-wrapper w-full', { 'aiui-dark': theme === 'dark' }, className)}>\n {title && <Title data={{ title: title }} />}\n {isMobile ? (\n <Swiper\n className={cn(className)}\n modules={[FreeMode, Mousewheel, Pagination]}\n freeMode={true}\n mousewheel={{\n forceToAxis: true,\n }}\n pagination={{\n clickable: true,\n el: paginationRef.current,\n }}\n breakpoints={{\n 0: {\n spaceBetween: 12,\n },\n }}\n >\n {itemsArray?.map((item, jIndex) => (\n <SwiperSlide key={'SwiperSlide' + jIndex} className=\"!flex flex-col gap-3\">\n {Array.isArray(item) &&\n item?.map((item, index) => (\n <BrandEquityItem key={index} data={item} itemShape={itemShape} index={index} theme={theme} />\n ))}\n </SwiperSlide>\n ))}\n <div ref={paginationRef} className=\"mt-3 flex justify-center\"></div>\n </Swiper>\n ) : (\n <div className={cn('grid grid-cols-1 gap-3', 'tablet:grid-cols-2', 'laptop:gap-4 laptop:grid-cols-10')}>\n {items.map((item, index) => (\n <BrandEquityItem key={index} data={item} itemShape={itemShape} index={index} theme={theme} />\n ))}\n </div>\n )}\n </div>\n )\n }\n)\n\nconst BrandEquityItem = ({\n data,\n itemShape,\n index,\n theme,\n}: {\n data: BrandEquityItemProps\n itemShape?: 'round' | 'square'\n index: number\n theme?: Theme\n}) => {\n return (\n <div\n className={cn(\n 'brand-equity-item',\n `brand-equity-item-${index + 1}`,\n data.containerName ? `brand-equity-item--${data.containerName}` : undefined,\n 'bg-container-secondary-1 box-border flex w-full flex-col p-4',\n 'desktop:p-6 justify-between',\n 'laptop:col-span-3 lg-desktop:p-8',\n 'laptop:h-[192px] lg-desktop:h-[240px] h-[160px]',\n {\n ['laptop:col-span-4']: [0, 5, 6, 11].includes(index),\n 'bg-container-primary': theme === 'dark',\n },\n itemShape === 'round' ? 'rounded-box' : 'rounded-none',\n data.className\n )}\n >\n <div className=\"lg-desktop:h-[36px] flex h-[30px] items-center justify-between gap-3\">\n <h3 className=\"lg-desktop:text-[18px] desktop:text-[16px] text-info-primary text-[14px] font-bold leading-[1.2] tracking-[-0.02em]\">\n {data.title}\n </h3>\n {data.type === 'avatar' ? (\n <div className=\"flex shrink-0 -space-x-2\">\n {data?.avatarList?.map((item: { avatar: Img }, index: number) => (\n <div\n key={index}\n className={cn(\n 'border-container-primary size-[30px] overflow-hidden rounded-full border-2',\n 'relative inline-block shrink-0',\n 'lg-desktop:size-[36px]'\n )}\n >\n <Picture source={item.avatar?.url} alt={item.avatar?.alt} className=\"size-full object-cover\" />\n </div>\n ))}\n </div>\n ) : (\n <div className=\"lg-desktop:size-[36px] size-[30px] shrink-0\">\n <Picture\n className=\"size-full object-cover\"\n source={data.icon?.url}\n alt={data.icon?.alt}\n imgClassName=\"w-full h-full object-cover\"\n />\n </div>\n )}\n </div>\n <p className=\"lg-desktop:text-[24px] text-info-primary line-clamp-3 text-[20px] font-bold leading-[1.2] tracking-[-0.04em]\">\n {data.description}\n </p>\n </div>\n )\n}\n\nBrandEquity.displayName = 'BrandEquity'\n\nexport default withLayout(BrandEquity)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["jsx", "jsxs", "forwardRef", "useEffect", "useRef", "useState", "useImperativeHandle", "cn", "Picture", "withLayout", "useMediaQuery", "useExposure", "Swiper", "SwiperSlide", "Pagination", "FreeMode", "Mousewheel", "Title", "componentType", "componentName", "chunkArray", "arr", "size", "chunks", "i", "BrandEquity", "items", "itemShape", "title", "theme", "className", "ref", "isMobile", "setIsMobile", "mediaQuery", "paginationRef", "innerRef", "itemsArray", "item", "jIndex", "index", "BrandEquityItem", "data", "BrandEquity_default"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as p}from"react/jsx-runtime";import v,{useImperativeHandle as u,useRef as y,useState as g}from"react";import{Text as x,Heading as h}from"../../components/index.js";import{cn as a}from"../../helpers/index.js";import{withLayout as b}from"../../shared/Styles.js";const l=v.forwardRef(({data:
|
|
1
|
+
"use client";import{jsx as e,jsxs as p}from"react/jsx-runtime";import v,{useImperativeHandle as u,useRef as y,useState as g}from"react";import{Text as x,Heading as h}from"../../components/index.js";import{cn as a}from"../../helpers/index.js";import{withLayout as b}from"../../shared/Styles.js";const l=v.forwardRef(({data:i,className:n,defaultOpenIndex:t,classNames:o={}},s)=>{const r=y(null);u(s,()=>r.current);const c=Array.isArray(t)?t:t!==void 0?[t]:i?.openFirst??!0?[0]:[];return e("div",{ref:r,className:a(n,o.root),children:e("div",{children:i?.productData?.map((f,d)=>e(m,{data:f,defaultOpen:c.includes(d),classNames:o},d))})})});l.displayName="Faq";const m=({data:i,defaultOpen:n=!1,classNames:t={}})=>{const[o,s]=g(n),r=()=>{s(!o)};return e("div",{className:a("tablet:py-6 border-b border-[#E4E5E6] py-4",t.item),children:p("div",{children:[p("div",{onClick:r,className:a("tablet:gap-[128px] flex cursor-pointer items-center justify-between gap-4",t.itemHeader),children:[e(h,{as:"h3",html:i?.title,className:a("desktop:text-base lg-desktop:text-lg text-info-primary text-sm font-bold leading-[1.4]",t.title)}),e("div",{className:a("transition-transform duration-300",t.icon),children:e("svg",{xmlns:"http://www.w3.org/2000/svg",className:a("w-[20px] transition-transform duration-300",o&&"rotate-180"),width:"20",height:"21",viewBox:"0 0 20 21",fill:"none",children:e("path",{d:"M14.4111 7.41107C14.7365 7.08563 15.264 7.08563 15.5895 7.41107C15.9149 7.73651 15.9149 8.26402 15.5895 8.58946L10.5895 13.5895C10.264 13.9149 9.73651 13.9149 9.41107 13.5895L4.41107 8.58946C4.08563 8.26402 4.08563 7.73651 4.41107 7.41107C4.73651 7.08563 5.26402 7.08563 5.58946 7.41107L10.0003 11.8219L14.4111 7.41107Z",fill:"#1D1D1F"})})})]}),e("div",{className:a("overflow-hidden text-[#4A4C56] transition-all duration-300",o?"mt-2 max-h-[500px] opacity-100":"max-h-0 opacity-0",t.content),children:e(x,{html:i?.richDesc??i?.desc,className:a("desktop:text-base lg-desktop:text-lg text-info-secondary [&_a]:text-brand-0 text-sm font-bold leading-[1.4] [&_a]:underline",t.description)})})]})})};m.displayName="FaqItem";var C=b(l);export{m as FaqItem,C as default};
|
|
2
2
|
//# sourceMappingURL=Faq.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/biz-components/Faq/Faq.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\nimport React, { useImperativeHandle, useRef, useState } from 'react'\nimport type { FaqProps, FaqItem as ItemType, FaqSemanticName } from './types.js'\nimport { Text, Heading } from '../../components/index.js'\nimport { cn } from '../../helpers/index.js'\nimport { withLayout } from '../../shared/Styles.js'\n\nconst Faq = React.forwardRef<HTMLDivElement, FaqProps>(\n ({ data, className, defaultOpenIndex, classNames = {} }, ref) => {\n const innerRef = useRef<HTMLDivElement>(null)\n useImperativeHandle(ref, () => innerRef.current!)\n\n
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["'use client'\nimport React, { useImperativeHandle, useRef, useState } from 'react'\nimport type { FaqProps, FaqItem as ItemType, FaqSemanticName } from './types.js'\nimport { Text, Heading } from '../../components/index.js'\nimport { cn } from '../../helpers/index.js'\nimport { withLayout } from '../../shared/Styles.js'\n\nconst Faq = React.forwardRef<HTMLDivElement, FaqProps>(\n ({ data, className, defaultOpenIndex, classNames = {} }, ref) => {\n const innerRef = useRef<HTMLDivElement>(null)\n useImperativeHandle(ref, () => innerRef.current!)\n\n const openIndexes = Array.isArray(defaultOpenIndex)\n ? defaultOpenIndex\n : defaultOpenIndex !== undefined\n ? [defaultOpenIndex]\n : (data?.openFirst ?? true)\n ? [0]\n : []\n\n return (\n <div ref={innerRef} className={cn(className, classNames.root)}>\n <div>\n {data?.productData?.map((item: any, index: number) => (\n <FaqItem key={index} data={item} defaultOpen={openIndexes.includes(index)} classNames={classNames} />\n ))}\n </div>\n </div>\n )\n }\n)\n\nFaq.displayName = 'Faq'\n\ninterface FaqItemProps {\n data: ItemType\n defaultOpen?: boolean\n classNames?: Partial<Record<FaqSemanticName, string>>\n}\n\nconst FaqItem = ({ data, defaultOpen = false, classNames = {} }: FaqItemProps) => {\n const [open, setOpen] = useState(defaultOpen)\n\n const handleToggle = () => {\n setOpen(!open)\n }\n\n return (\n <div className={cn('tablet:py-6 border-b border-[#E4E5E6] py-4', classNames.item)}>\n <div>\n <div\n onClick={handleToggle}\n className={cn(\n 'tablet:gap-[128px] flex cursor-pointer items-center justify-between gap-4',\n classNames.itemHeader\n )}\n >\n <Heading\n as=\"h3\"\n html={data?.title}\n className={cn(\n 'desktop:text-base lg-desktop:text-lg text-info-primary text-sm font-bold leading-[1.4]',\n classNames.title\n )}\n />\n <div className={cn('transition-transform duration-300', classNames.icon)}>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className={cn('w-[20px] transition-transform duration-300', open && 'rotate-180')}\n width=\"20\"\n height=\"21\"\n viewBox=\"0 0 20 21\"\n fill=\"none\"\n >\n <path\n d=\"M14.4111 7.41107C14.7365 7.08563 15.264 7.08563 15.5895 7.41107C15.9149 7.73651 15.9149 8.26402 15.5895 8.58946L10.5895 13.5895C10.264 13.9149 9.73651 13.9149 9.41107 13.5895L4.41107 8.58946C4.08563 8.26402 4.08563 7.73651 4.41107 7.41107C4.73651 7.08563 5.26402 7.08563 5.58946 7.41107L10.0003 11.8219L14.4111 7.41107Z\"\n fill=\"#1D1D1F\"\n />\n </svg>\n </div>\n </div>\n\n {/* \u5E26\u8FC7\u6E21\u7684\u5185\u5BB9\u533A\u57DF */}\n <div\n className={cn(\n 'overflow-hidden text-[#4A4C56] transition-all duration-300',\n open ? 'mt-2 max-h-[500px] opacity-100' : 'max-h-0 opacity-0',\n classNames.content\n )}\n >\n <Text\n html={data?.richDesc ?? data?.desc}\n className={cn(\n 'desktop:text-base lg-desktop:text-lg text-info-secondary [&_a]:text-brand-0 text-sm font-bold leading-[1.4] [&_a]:underline',\n classNames.description\n )}\n />\n </div>\n </div>\n </div>\n )\n}\n\nFaqItem.displayName = 'FaqItem'\n\nexport default withLayout(Faq)\nexport { FaqItem }\n"],
|
|
5
|
+
"mappings": "aAwBY,cAAAA,EA0BJ,QAAAC,MA1BI,oBAvBZ,OAAOC,GAAS,uBAAAC,EAAqB,UAAAC,EAAQ,YAAAC,MAAgB,QAE7D,OAAS,QAAAC,EAAM,WAAAC,MAAe,4BAC9B,OAAS,MAAAC,MAAU,yBACnB,OAAS,cAAAC,MAAkB,yBAE3B,MAAMC,EAAMR,EAAM,WAChB,CAAC,CAAE,KAAAS,EAAM,UAAAC,EAAW,iBAAAC,EAAkB,WAAAC,EAAa,CAAC,CAAE,EAAGC,IAAQ,CAC/D,MAAMC,EAAWZ,EAAuB,IAAI,EAC5CD,EAAoBY,EAAK,IAAMC,EAAS,OAAQ,EAEhD,MAAMC,EAAc,MAAM,QAAQJ,CAAgB,EAC9CA,EACAA,IAAqB,OACnB,CAACA,CAAgB,EAChBF,GAAM,WAAa,GAClB,CAAC,CAAC,EACF,CAAC,EAET,OACEX,EAAC,OAAI,IAAKgB,EAAU,UAAWR,EAAGI,EAAWE,EAAW,IAAI,EAC1D,SAAAd,EAAC,OACE,SAAAW,GAAM,aAAa,IAAI,CAACO,EAAWC,IAClCnB,EAACoB,EAAA,CAAoB,KAAMF,EAAM,YAAaD,EAAY,SAASE,CAAK,EAAG,WAAYL,GAAzEK,CAAqF,CACpG,EACH,EACF,CAEJ,CACF,EAEAT,EAAI,YAAc,MAQlB,MAAMU,EAAU,CAAC,CAAE,KAAAT,EAAM,YAAAU,EAAc,GAAO,WAAAP,EAAa,CAAC,CAAE,IAAoB,CAChF,KAAM,CAACQ,EAAMC,CAAO,EAAIlB,EAASgB,CAAW,EAEtCG,EAAe,IAAM,CACzBD,EAAQ,CAACD,CAAI,CACf,EAEA,OACEtB,EAAC,OAAI,UAAWQ,EAAG,6CAA8CM,EAAW,IAAI,EAC9E,SAAAb,EAAC,OACC,UAAAA,EAAC,OACC,QAASuB,EACT,UAAWhB,EACT,4EACAM,EAAW,UACb,EAEA,UAAAd,EAACO,EAAA,CACC,GAAG,KACH,KAAMI,GAAM,MACZ,UAAWH,EACT,yFACAM,EAAW,KACb,EACF,EACAd,EAAC,OAAI,UAAWQ,EAAG,oCAAqCM,EAAW,IAAI,EACrE,SAAAd,EAAC,OACC,MAAM,6BACN,UAAWQ,EAAG,6CAA8Cc,GAAQ,YAAY,EAChF,MAAM,KACN,OAAO,KACP,QAAQ,YACR,KAAK,OAEL,SAAAtB,EAAC,QACC,EAAE,kUACF,KAAK,UACP,EACF,EACF,GACF,EAGAA,EAAC,OACC,UAAWQ,EACT,6DACAc,EAAO,iCAAmC,oBAC1CR,EAAW,OACb,EAEA,SAAAd,EAACM,EAAA,CACC,KAAMK,GAAM,UAAYA,GAAM,KAC9B,UAAWH,EACT,8HACAM,EAAW,WACb,EACF,EACF,GACF,EACF,CAEJ,EAEAM,EAAQ,YAAc,UAEtB,IAAOK,EAAQhB,EAAWC,CAAG",
|
|
6
6
|
"names": ["jsx", "jsxs", "React", "useImperativeHandle", "useRef", "useState", "Text", "Heading", "cn", "withLayout", "Faq", "data", "className", "defaultOpenIndex", "classNames", "ref", "innerRef", "openIndexes", "item", "index", "FaqItem", "defaultOpen", "open", "setOpen", "handleToggle", "Faq_default"]
|
|
7
7
|
}
|