@anker-in/headless-ui 1.3.17 → 1.3.18
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/GiftShelf/index.js +1 -1
- package/dist/cjs/biz-components/GiftShelf/index.js.map +3 -3
- package/dist/cjs/biz-components/ImageWithText/ImageWithText.js +1 -1
- package/dist/cjs/biz-components/ImageWithText/ImageWithText.js.map +2 -2
- package/dist/cjs/biz-components/MediaTextOverlay/MediaTextOverlay.js +1 -1
- package/dist/cjs/biz-components/MediaTextOverlay/MediaTextOverlay.js.map +2 -2
- package/dist/cjs/biz-components/ProductCompare/index.js +1 -1
- package/dist/cjs/biz-components/ProductCompare/index.js.map +2 -2
- package/dist/cjs/biz-components/Title/index.js +1 -1
- package/dist/cjs/biz-components/Title/index.js.map +3 -3
- package/dist/esm/biz-components/GiftShelf/index.js +1 -1
- package/dist/esm/biz-components/GiftShelf/index.js.map +3 -3
- package/dist/esm/biz-components/ImageWithText/ImageWithText.js +1 -1
- package/dist/esm/biz-components/ImageWithText/ImageWithText.js.map +2 -2
- package/dist/esm/biz-components/MediaTextOverlay/MediaTextOverlay.js +1 -1
- package/dist/esm/biz-components/MediaTextOverlay/MediaTextOverlay.js.map +2 -2
- package/dist/esm/biz-components/ProductCompare/index.js +1 -1
- package/dist/esm/biz-components/ProductCompare/index.js.map +2 -2
- package/dist/esm/biz-components/Title/index.js +1 -1
- package/dist/esm/biz-components/Title/index.js.map +3 -3
- package/dist/tokens/base.css +1 -0
- package/package.json +1 -1
- package/style.css +15 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/biz-components/MediaTextOverlay/MediaTextOverlay.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport React, { useRef, useMemo, useState, useEffect, useCallback } from 'react'\nimport { withLayout } from '../../shared/Styles.js'\nimport { cn } from '../../helpers/utils.js'\nimport { useExposure } from '../../hooks/useExposure.js'\nimport { useAiuiContext } from '../AiuiProvider/index.js'\nimport Media from '../Media/index.js'\nimport type { MediaTextOverlayProps, MediaTextOverlayItem } from './types.js'\nimport 'swiper/css'\nimport 'swiper/css/navigation'\nimport { Heading } from '../../components/index.js'\nimport { Swiper, SwiperSlide } from 'swiper/react'\nimport { Navigation } from 'swiper/modules'\n\nconst PrevIcon = ({ disabled }: { disabled: boolean }) => (\n <svg\n width=\"40\"\n height=\"40\"\n viewBox=\"0 0 56 56\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"text-info-primary lg-desktop:size-[56px] size-[40px]\"\n >\n <path\n d=\"M0 28C0 43.464 12.536 56 28 56C43.464 56 56 43.464 56 28C56 12.536 43.464 0 28 0C12.536 0 0 12.536 0 28Z\"\n fill=\"currentColor\"\n fillOpacity={disabled ? '0.2' : '0.6'}\n />\n <path d=\"M31 22L25 28L31 34\" stroke=\"white\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n)\n\nconst NextIcon = ({ disabled }: { disabled: boolean }) => (\n <svg\n width=\"40\"\n height=\"40\"\n viewBox=\"0 0 56 56\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"text-info-primary lg-desktop:size-[56px] size-[40px]\"\n >\n <path\n d=\"M0 28C0 12.536 12.536 0 28 0C43.464 0 56 12.536 56 28C56 43.464 43.464 56 28 56C12.536 56 0 43.464 0 28Z\"\n fill=\"currentColor\"\n fillOpacity={disabled ? '0.2' : '0.6'}\n />\n <path d=\"M25 22L31 28L25 34\" stroke=\"white\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n)\n\nconst componentType = 'video'\nconst componentName = 'media_text_overlay'\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\ninterface ItemBlockProps {\n data: MediaTextOverlayItem\n configuration?: any\n jIndex?: number\n classNames?: any\n}\n\nconst ItemBlock = ({ data: item, configuration, jIndex, classNames = {} }: ItemBlockProps) => {\n const ref = useRef<HTMLDivElement>(null)\n const videoRef = useRef<HTMLVideoElement>(null)\n\n const { content, media } = item\n const theme = configuration?.theme || 'light'\n const size = configuration?.size || 'lg'\n const onlyOne = configuration?.onlyOne || false\n const isAutoPlay = configuration?.isAutoPlay ?? true\n\n const [isPlaying, setIsPlaying] = useState(false)\n\n useExposure(ref, {\n componentType,\n componentName,\n position: jIndex,\n componentTitle: content,\n navigation: configuration?.activeTab,\n })\n\n const hasVideo = useMemo(\n () =>\n [media.lgDesktop, media.desktop, media.laptop, media.pad, media.mobile].some(m => m?.mimeType === 'video/mp4'),\n [media]\n )\n\n const handlePlayButtonClick = useCallback(() => {\n const video = videoRef.current\n if (video) {\n if (video.paused) {\n video.play()\n setIsPlaying(true)\n } else {\n video.pause()\n setIsPlaying(false)\n }\n }\n }, [])\n\n useEffect(() => {\n const video = videoRef.current\n if (!video || !hasVideo || !isAutoPlay) return\n\n const observer = new IntersectionObserver(\n entries => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n video.play().catch(error => {\n console.warn('Video autoplay failed:', error)\n })\n } else {\n video.pause()\n }\n })\n },\n { threshold: 0.5 }\n )\n\n observer.observe(video)\n\n return () => {\n observer.disconnect()\n }\n }, [hasVideo, isAutoPlay])\n\n const sizeClasses = {\n lg: 'h-[400px] laptop:h-[384px] desktop:h-[512px] lg-desktop:h-[640px]',\n sm: 'h-[240px] laptop:h-[288px] desktop:h-[384px] lg-desktop:h-[480px]',\n }\n\n return (\n <div\n className={cn(\n 'item-wrapper rounded-box group relative box-border w-full overflow-hidden',\n onlyOne ? sizeClasses[size as keyof typeof sizeClasses] : 'desktop:h-[384px] lg-desktop:h-[480px] h-[360px]',\n {\n 'aiui-dark': theme === 'dark',\n }\n )}\n ref={ref}\n >\n <div className=\"absolute inset-0\">\n <Media\n pcImage={media.lgDesktop || media.desktop}\n desktopImage={media.desktop}\n laptopImage={media.laptop}\n padImage={media.pad}\n mobileImage={media.mobile}\n videoClassName=\"absolute inset-0 size-full object-cover\"\n imgClassName=\"absolute inset-0 size-full object-cover\"\n videoRef={videoRef}\n muted={true}\n loop={true}\n playsInline={true}\n autoPlay={isAutoPlay}\n onVideoPlay={() => setIsPlaying(true)}\n onVideoPause={() => setIsPlaying(false)}\n onVideoEnded={() => setIsPlaying(false)}\n />\n </div>\n\n {hasVideo && (\n <div className=\"desktop:p-8 absolute bottom-0 right-0 z-30 p-6\">\n <button\n type=\"button\"\n aria-label={isPlaying ? 'Pause video' : 'Play video'}\n onClick={handlePlayButtonClick}\n className={cn(\n 'flex size-14 shrink-0 items-center justify-center rounded-full bg-white/20 transition-opacity hover:opacity-80',\n classNames.playButton\n )}\n >\n {isPlaying ? <PauseIcon /> : <PlayIcon />}\n </button>\n </div>\n )}\n\n <div\n className={cn(\n 'text-info-primary laptop:px-6 laptop:pb-6 laptop:pr-24 desktop:px-8 desktop:pb-8 desktop:pr-28 absolute inset-x-0 bottom-0 z-20 flex flex-col gap-4 px-4 pb-4 pr-20',\n classNames.overlay\n )}\n >\n <div className={cn('flex items-end justify-between gap-4', classNames.content)}>\n <Heading size={2} html={content} className=\"line-clamp-3\" />\n </div>\n </div>\n </div>\n )\n}\n\nconst MediaTextOverlay = React.forwardRef<HTMLDivElement, MediaTextOverlayProps>((props, ref) => {\n const { data, className, classNames = {}, ...rest } = props\n const { items = [], theme = 'dark', size = 'sm', isShowPagination = true, isAutoPlay = true } = data\n const { locale = 'us' } = useAiuiContext()\n const swiperRef = useRef<any>(null)\n const [swiperState, setSwiperState] = useState({\n isBeginning: true,\n isEnd: false,\n })\n\n const breakpoints = useMemo(() => {\n const len = items?.length || 0\n return {\n 0: {\n spaceBetween: 12,\n slidesPerView: len > 1 ? 1.2 : 1,\n },\n 768: {\n spaceBetween: 12,\n slidesPerView: len > 2 ? 2.3 : len > 1 ? 2 : 1,\n },\n 1024: {\n spaceBetween: 16,\n slidesPerView: Math.min(len, 3),\n },\n 1440: {\n spaceBetween: 16,\n slidesPerView: Math.min(len, 4),\n },\n 1920: {\n spaceBetween: 16,\n slidesPerView: Math.min(len, 4),\n },\n }\n }, [items?.length])\n\n // \u751F\u6210\u552F\u4E00 ID\uFF0C\u79FB\u9664\u7279\u6B8A\u5B57\u7B26\u4EE5\u786E\u4FDD\u53EF\u7528\u4E8E CSS \u9009\u62E9\u5668\n const id = React.useId().replace(/:/g, '')\n const nextButtonClass = `${id}-custom-swiper-button-next`\n const prevButtonClass = `${id}-custom-swiper-button-prev`\n\n return (\n <section\n data-ui-component-id=\"MediaTextOverlay\"\n ref={ref}\n {...rest}\n className={cn('mediaTextOverlayBlock text-info-primary', className, classNames.root)}\n >\n {items && items.length > 0 ? (\n <div className=\"group relative\">\n <Swiper\n className=\"!overflow-visible\"\n modules={[Navigation]}\n navigation={{\n nextEl: `.${nextButtonClass}`,\n prevEl: `.${prevButtonClass}`,\n }}\n onSwiper={swiper => {\n swiperRef.current = swiper\n setSwiperState({\n isBeginning: swiper.isBeginning,\n isEnd: swiper.isEnd,\n })\n }}\n onReachEnd={() => {\n setSwiperState(prev => ({ ...prev, isEnd: true }))\n }}\n onReachBeginning={() => {\n setSwiperState(prev => ({ ...prev, isBeginning: true }))\n }}\n onFromEdge={() => {\n setSwiperState({ isBeginning: false, isEnd: false })\n }}\n breakpoints={breakpoints}\n >\n {items.map((item, jIndex) => (\n <SwiperSlide key={`${id}-SwiperSlide-${jIndex}`} className=\"!flex !h-[unset]\">\n <ItemBlock\n data={item}\n configuration={{\n theme,\n size,\n num: items.length,\n locale,\n onlyOne: items.length === 1,\n index: jIndex,\n isAutoPlay,\n }}\n jIndex={jIndex}\n />\n </SwiperSlide>\n ))}\n </Swiper>\n\n {isShowPagination && items.length > 1 && (\n <>\n <button\n className={`${prevButtonClass} absolute left-4 top-1/2 z-10 -translate-y-1/2 transition-opacity ${swiperState.isBeginning ? 'pointer-events-none opacity-0' : 'opacity-100 hover:opacity-80'}`}\n aria-label=\"Previous slide\"\n >\n <PrevIcon disabled={swiperState.isBeginning} />\n </button>\n <button\n className={`${nextButtonClass} absolute right-4 top-1/2 z-10 -translate-y-1/2 transition-opacity ${swiperState.isEnd ? 'pointer-events-none opacity-0' : 'opacity-100 hover:opacity-80'}`}\n aria-label=\"Next slide\"\n >\n <NextIcon disabled={swiperState.isEnd} />\n </button>\n </>\n )}\n </div>\n ) : null}\n </section>\n )\n})\n\nMediaTextOverlay.displayName = 'MediaTextOverlay'\n\nexport default withLayout(MediaTextOverlay)\nexport type { MediaTextOverlayProps }\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport React, { useRef, useMemo, useState, useEffect, useCallback } from 'react'\nimport { withLayout } from '../../shared/Styles.js'\nimport { cn } from '../../helpers/utils.js'\nimport { useExposure } from '../../hooks/useExposure.js'\nimport { useAiuiContext } from '../AiuiProvider/index.js'\nimport Media from '../Media/index.js'\nimport type { MediaTextOverlayProps, MediaTextOverlayItem } from './types.js'\nimport 'swiper/css'\nimport 'swiper/css/navigation'\nimport { Heading } from '../../components/index.js'\nimport { Swiper, SwiperSlide } from 'swiper/react'\nimport { Navigation } from 'swiper/modules'\n\nconst PrevIcon = ({ disabled }: { disabled: boolean }) => (\n <svg\n width=\"40\"\n height=\"40\"\n viewBox=\"0 0 56 56\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"text-info-primary lg-desktop:size-[56px] size-[40px]\"\n >\n <path\n d=\"M0 28C0 43.464 12.536 56 28 56C43.464 56 56 43.464 56 28C56 12.536 43.464 0 28 0C12.536 0 0 12.536 0 28Z\"\n fill=\"currentColor\"\n fillOpacity={disabled ? '0.2' : '0.6'}\n />\n <path d=\"M31 22L25 28L31 34\" stroke=\"white\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n)\n\nconst NextIcon = ({ disabled }: { disabled: boolean }) => (\n <svg\n width=\"40\"\n height=\"40\"\n viewBox=\"0 0 56 56\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"text-info-primary lg-desktop:size-[56px] size-[40px]\"\n >\n <path\n d=\"M0 28C0 12.536 12.536 0 28 0C43.464 0 56 12.536 56 28C56 43.464 43.464 56 28 56C12.536 56 0 43.464 0 28Z\"\n fill=\"currentColor\"\n fillOpacity={disabled ? '0.2' : '0.6'}\n />\n <path d=\"M25 22L31 28L25 34\" stroke=\"white\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n)\n\nconst componentType = 'video'\nconst componentName = 'media_text_overlay'\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\ninterface ItemBlockProps {\n data: MediaTextOverlayItem\n configuration?: any\n jIndex?: number\n classNames?: any\n}\n\nconst ItemBlock = ({ data: item, configuration, jIndex, classNames = {} }: ItemBlockProps) => {\n const ref = useRef<HTMLDivElement>(null)\n const videoRef = useRef<HTMLVideoElement>(null)\n\n const { content, media } = item\n const theme = configuration?.theme || 'light'\n const size = configuration?.size || 'lg'\n const onlyOne = configuration?.onlyOne || false\n const isAutoPlay = configuration?.isAutoPlay ?? true\n\n const [isPlaying, setIsPlaying] = useState(false)\n\n useExposure(ref, {\n componentType,\n componentName,\n position: jIndex,\n componentTitle: content,\n navigation: configuration?.activeTab,\n })\n\n const hasVideo = useMemo(\n () =>\n [media.lgDesktop, media.desktop, media.laptop, media.pad, media.mobile].some(m => m?.mimeType === 'video/mp4'),\n [media]\n )\n\n const handlePlayButtonClick = useCallback(() => {\n const video = videoRef.current\n if (video) {\n if (video.paused) {\n video.play()\n setIsPlaying(true)\n } else {\n video.pause()\n setIsPlaying(false)\n }\n }\n }, [])\n\n useEffect(() => {\n const video = videoRef.current\n if (!video || !hasVideo || !isAutoPlay) return\n\n const observer = new IntersectionObserver(\n entries => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n video.play().catch(error => {\n console.warn('Video autoplay failed:', error)\n })\n } else {\n video.pause()\n }\n })\n },\n { threshold: 0.5 }\n )\n\n observer.observe(video)\n\n return () => {\n observer.disconnect()\n }\n }, [hasVideo, isAutoPlay])\n\n const sizeClasses = {\n lg: 'aspect-[390/400] tablet:aspect-[768/400] laptop:aspect-[1024/384] desktop:aspect-[1440/512] lg-desktop:aspect-[1920/640]',\n sm: 'h-[240px] laptop:h-[288px] desktop:h-[384px] lg-desktop:h-[480px]',\n }\n\n return (\n <div\n className={cn(\n 'item-wrapper rounded-box group relative box-border w-full overflow-hidden',\n onlyOne\n ? sizeClasses[size as keyof typeof sizeClasses]\n : 'tablet:aspect-[768/400] laptop:aspect-[1024/384] desktop:aspect-[1440/512] lg-desktop:aspect-[1920/640] aspect-[390/400]',\n {\n 'aiui-dark': theme === 'dark',\n }\n )}\n ref={ref}\n >\n <div className=\"absolute inset-0\">\n <Media\n pcImage={media.lgDesktop || media.desktop}\n desktopImage={media.desktop}\n laptopImage={media.laptop}\n padImage={media.pad}\n mobileImage={media.mobile}\n videoClassName=\"absolute inset-0 size-full object-cover\"\n imgClassName=\"absolute inset-0 size-full object-cover\"\n videoRef={videoRef}\n muted={true}\n loop={true}\n playsInline={true}\n autoPlay={isAutoPlay}\n onVideoPlay={() => setIsPlaying(true)}\n onVideoPause={() => setIsPlaying(false)}\n onVideoEnded={() => setIsPlaying(false)}\n />\n </div>\n\n {hasVideo && (\n <div className=\"desktop:p-8 absolute bottom-0 right-0 z-30 p-6\">\n <button\n type=\"button\"\n aria-label={isPlaying ? 'Pause video' : 'Play video'}\n onClick={handlePlayButtonClick}\n className={cn(\n 'flex size-14 shrink-0 items-center justify-center rounded-full bg-white/20 transition-opacity hover:opacity-80',\n classNames.playButton\n )}\n >\n {isPlaying ? <PauseIcon /> : <PlayIcon />}\n </button>\n </div>\n )}\n\n <div\n className={cn(\n 'text-info-primary laptop:px-6 laptop:pb-6 laptop:pr-24 desktop:px-8 desktop:pb-8 desktop:pr-28 absolute inset-x-0 bottom-0 z-20 flex flex-col gap-4 px-4 pb-4 pr-20',\n classNames.overlay\n )}\n >\n <div className={cn('flex items-end justify-between gap-4', classNames.content)}>\n <Heading size={2} html={content} className=\"line-clamp-3\" />\n </div>\n </div>\n </div>\n )\n}\n\nconst MediaTextOverlay = React.forwardRef<HTMLDivElement, MediaTextOverlayProps>((props, ref) => {\n const { data, className, classNames = {}, ...rest } = props\n const { items = [], theme = 'dark', size = 'sm', isShowPagination = true, isAutoPlay = true } = data\n const { locale = 'us' } = useAiuiContext()\n const swiperRef = useRef<any>(null)\n const [swiperState, setSwiperState] = useState({\n isBeginning: true,\n isEnd: false,\n })\n\n const breakpoints = useMemo(() => {\n const len = items?.length || 0\n return {\n 0: {\n spaceBetween: 12,\n slidesPerView: len > 1 ? 1.2 : 1,\n },\n 768: {\n spaceBetween: 12,\n slidesPerView: len > 2 ? 2.3 : len > 1 ? 2 : 1,\n },\n 1024: {\n spaceBetween: 16,\n slidesPerView: Math.min(len, 3),\n },\n 1440: {\n spaceBetween: 16,\n slidesPerView: Math.min(len, 4),\n },\n 1920: {\n spaceBetween: 16,\n slidesPerView: Math.min(len, 4),\n },\n }\n }, [items?.length])\n\n // \u751F\u6210\u552F\u4E00 ID\uFF0C\u79FB\u9664\u7279\u6B8A\u5B57\u7B26\u4EE5\u786E\u4FDD\u53EF\u7528\u4E8E CSS \u9009\u62E9\u5668\n const id = React.useId().replace(/:/g, '')\n const nextButtonClass = `${id}-custom-swiper-button-next`\n const prevButtonClass = `${id}-custom-swiper-button-prev`\n\n return (\n <section\n data-ui-component-id=\"MediaTextOverlay\"\n ref={ref}\n {...rest}\n className={cn('mediaTextOverlayBlock text-info-primary', className, classNames.root)}\n >\n {items && items.length > 0 ? (\n <div className=\"group relative\">\n <Swiper\n className=\"!overflow-visible\"\n modules={[Navigation]}\n navigation={{\n nextEl: `.${nextButtonClass}`,\n prevEl: `.${prevButtonClass}`,\n }}\n onSwiper={swiper => {\n swiperRef.current = swiper\n setSwiperState({\n isBeginning: swiper.isBeginning,\n isEnd: swiper.isEnd,\n })\n }}\n onReachEnd={() => {\n setSwiperState(prev => ({ ...prev, isEnd: true }))\n }}\n onReachBeginning={() => {\n setSwiperState(prev => ({ ...prev, isBeginning: true }))\n }}\n onFromEdge={() => {\n setSwiperState({ isBeginning: false, isEnd: false })\n }}\n breakpoints={breakpoints}\n >\n {items.map((item, jIndex) => (\n <SwiperSlide key={`${id}-SwiperSlide-${jIndex}`} className=\"!flex !h-[unset]\">\n <ItemBlock\n data={item}\n configuration={{\n theme,\n size,\n num: items.length,\n locale,\n onlyOne: items.length === 1,\n index: jIndex,\n isAutoPlay,\n }}\n jIndex={jIndex}\n />\n </SwiperSlide>\n ))}\n </Swiper>\n\n {isShowPagination && items.length > 1 && (\n <>\n <button\n className={`${prevButtonClass} absolute left-4 top-1/2 z-10 -translate-y-1/2 transition-opacity ${swiperState.isBeginning ? 'pointer-events-none opacity-0' : 'opacity-100 hover:opacity-80'}`}\n aria-label=\"Previous slide\"\n >\n <PrevIcon disabled={swiperState.isBeginning} />\n </button>\n <button\n className={`${nextButtonClass} absolute right-4 top-1/2 z-10 -translate-y-1/2 transition-opacity ${swiperState.isEnd ? 'pointer-events-none opacity-0' : 'opacity-100 hover:opacity-80'}`}\n aria-label=\"Next slide\"\n >\n <NextIcon disabled={swiperState.isEnd} />\n </button>\n </>\n )}\n </div>\n ) : null}\n </section>\n )\n})\n\nMediaTextOverlay.displayName = 'MediaTextOverlay'\n\nexport default withLayout(MediaTextOverlay)\nexport type { MediaTextOverlayProps }\n"],
|
|
5
|
+
"mappings": "ukBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,aAAAE,IAAA,eAAAC,EAAAH,GAgBE,IAAAI,EAAA,6BAdFC,EAAyE,oBACzEC,EAA2B,kCAC3BC,EAAmB,kCACnBC,EAA4B,sCAC5BC,EAA+B,oCAC/BC,EAAkB,gCAElBC,EAAO,sBACPC,GAAO,iCACPC,EAAwB,qCACxBR,EAAoC,wBACpCS,EAA2B,0BAE3B,MAAMC,EAAW,CAAC,CAAE,SAAAC,CAAS,OAC3B,QAAC,OACC,MAAM,KACN,OAAO,KACP,QAAQ,YACR,KAAK,OACL,MAAM,6BACN,UAAU,uDAEV,oBAAC,QACC,EAAE,2GACF,KAAK,eACL,YAAaA,EAAW,MAAQ,MAClC,KACA,OAAC,QAAK,EAAE,qBAAqB,OAAO,QAAQ,YAAY,IAAI,cAAc,QAAQ,eAAe,QAAQ,GAC3G,EAGIC,EAAW,CAAC,CAAE,SAAAD,CAAS,OAC3B,QAAC,OACC,MAAM,KACN,OAAO,KACP,QAAQ,YACR,KAAK,OACL,MAAM,6BACN,UAAU,uDAEV,oBAAC,QACC,EAAE,2GACF,KAAK,eACL,YAAaA,EAAW,MAAQ,MAClC,KACA,OAAC,QAAK,EAAE,qBAAqB,OAAO,QAAQ,YAAY,IAAI,cAAc,QAAQ,eAAe,QAAQ,GAC3G,EAGIE,EAAgB,QAChBC,EAAgB,qBAMhBC,EAAW,OACf,OAAC,OAAI,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,MAAM,6BAA6B,cAAY,OACzG,mBAAC,QAAK,EAAE,8BAA8B,KAAK,QAAQ,EACrD,EAGIC,EAAY,OAChB,QAAC,OAAI,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,MAAM,6BAA6B,cAAY,OACzG,oBAAC,QAAK,EAAE,IAAI,EAAE,IAAI,MAAM,IAAI,OAAO,KAAK,GAAG,IAAI,KAAK,QAAQ,KAC5D,OAAC,QAAK,EAAE,KAAK,EAAE,IAAI,MAAM,IAAI,OAAO,KAAK,GAAG,IAAI,KAAK,QAAQ,GAC/D,EAUIC,EAAY,CAAC,CAAE,KAAMC,EAAM,cAAAC,EAAe,OAAAC,EAAQ,WAAAC,EAAa,CAAC,CAAE,IAAsB,CAC5F,MAAMC,KAAM,UAAuB,IAAI,EACjCC,KAAW,UAAyB,IAAI,EAExC,CAAE,QAAAC,EAAS,MAAAC,CAAM,EAAIP,EACrBQ,EAAQP,GAAe,OAAS,QAChCQ,EAAOR,GAAe,MAAQ,KAC9BS,EAAUT,GAAe,SAAW,GACpCU,EAAaV,GAAe,YAAc,GAE1C,CAACW,EAAWC,CAAY,KAAI,YAAS,EAAK,KAEhD,eAAYT,EAAK,CACf,cAAAT,EACA,cAAAC,EACA,SAAUM,EACV,eAAgBI,EAChB,WAAYL,GAAe,SAC7B,CAAC,EAED,MAAMa,KAAW,WACf,IACE,CAACP,EAAM,UAAWA,EAAM,QAASA,EAAM,OAAQA,EAAM,IAAKA,EAAM,MAAM,EAAE,KAAKQ,GAAKA,GAAG,WAAa,WAAW,EAC/G,CAACR,CAAK,CACR,EAEMS,KAAwB,eAAY,IAAM,CAC9C,MAAMC,EAAQZ,EAAS,QACnBY,IACEA,EAAM,QACRA,EAAM,KAAK,EACXJ,EAAa,EAAI,IAEjBI,EAAM,MAAM,EACZJ,EAAa,EAAK,GAGxB,EAAG,CAAC,CAAC,EAEL,sBAAU,IAAM,CACd,MAAMI,EAAQZ,EAAS,QACvB,GAAI,CAACY,GAAS,CAACH,GAAY,CAACH,EAAY,OAExC,MAAMO,EAAW,IAAI,qBACnBC,GAAW,CACTA,EAAQ,QAAQC,GAAS,CACnBA,EAAM,eACRH,EAAM,KAAK,EAAE,MAAMI,GAAS,CAC1B,QAAQ,KAAK,yBAA0BA,CAAK,CAC9C,CAAC,EAEDJ,EAAM,MAAM,CAEhB,CAAC,CACH,EACA,CAAE,UAAW,EAAI,CACnB,EAEA,OAAAC,EAAS,QAAQD,CAAK,EAEf,IAAM,CACXC,EAAS,WAAW,CACtB,CACF,EAAG,CAACJ,EAAUH,CAAU,CAAC,KAQvB,QAAC,OACC,aAAW,MACT,4EACAD,EATc,CAClB,GAAI,2HACJ,GAAI,mEACN,EAOsBD,CAAgC,EAC5C,2HACJ,CACE,YAAaD,IAAU,MACzB,CACF,EACA,IAAKJ,EAEL,oBAAC,OAAI,UAAU,mBACb,mBAAC,EAAAkB,QAAA,CACC,QAASf,EAAM,WAAaA,EAAM,QAClC,aAAcA,EAAM,QACpB,YAAaA,EAAM,OACnB,SAAUA,EAAM,IAChB,YAAaA,EAAM,OACnB,eAAe,0CACf,aAAa,0CACb,SAAUF,EACV,MAAO,GACP,KAAM,GACN,YAAa,GACb,SAAUM,EACV,YAAa,IAAME,EAAa,EAAI,EACpC,aAAc,IAAMA,EAAa,EAAK,EACtC,aAAc,IAAMA,EAAa,EAAK,EACxC,EACF,EAECC,MACC,OAAC,OAAI,UAAU,iDACb,mBAAC,UACC,KAAK,SACL,aAAYF,EAAY,cAAgB,aACxC,QAASI,EACT,aAAW,MACT,iHACAb,EAAW,UACb,EAEC,SAAAS,KAAY,OAACd,EAAA,EAAU,KAAK,OAACD,EAAA,EAAS,EACzC,EACF,KAGF,OAAC,OACC,aAAW,MACT,sKACAM,EAAW,OACb,EAEA,mBAAC,OAAI,aAAW,MAAG,uCAAwCA,EAAW,OAAO,EAC3E,mBAAC,WAAQ,KAAM,EAAG,KAAMG,EAAS,UAAU,eAAe,EAC5D,EACF,GACF,CAEJ,EAEMiB,EAAmB,EAAAC,QAAM,WAAkD,CAACC,EAAOrB,IAAQ,CAC/F,KAAM,CAAE,KAAAsB,EAAM,UAAAC,EAAW,WAAAxB,EAAa,CAAC,EAAG,GAAGyB,CAAK,EAAIH,EAChD,CAAE,MAAAI,EAAQ,CAAC,EAAG,MAAArB,EAAQ,OAAQ,KAAAC,EAAO,KAAM,iBAAAqB,EAAmB,GAAM,WAAAnB,EAAa,EAAK,EAAIe,EAC1F,CAAE,OAAAK,EAAS,IAAK,KAAI,kBAAe,EACnCC,KAAY,UAAY,IAAI,EAC5B,CAACC,EAAaC,CAAc,KAAI,YAAS,CAC7C,YAAa,GACb,MAAO,EACT,CAAC,EAEKC,KAAc,WAAQ,IAAM,CAChC,MAAMC,EAAMP,GAAO,QAAU,EAC7B,MAAO,CACL,EAAG,CACD,aAAc,GACd,cAAeO,EAAM,EAAI,IAAM,CACjC,EACA,IAAK,CACH,aAAc,GACd,cAAeA,EAAM,EAAI,IAAMA,EAAM,EAAI,EAAI,CAC/C,EACA,KAAM,CACJ,aAAc,GACd,cAAe,KAAK,IAAIA,EAAK,CAAC,CAChC,EACA,KAAM,CACJ,aAAc,GACd,cAAe,KAAK,IAAIA,EAAK,CAAC,CAChC,EACA,KAAM,CACJ,aAAc,GACd,cAAe,KAAK,IAAIA,EAAK,CAAC,CAChC,CACF,CACF,EAAG,CAACP,GAAO,MAAM,CAAC,EAGZQ,EAAK,EAAAb,QAAM,MAAM,EAAE,QAAQ,KAAM,EAAE,EACnCc,EAAkB,GAAGD,CAAE,6BACvBE,EAAkB,GAAGF,CAAE,6BAE7B,SACE,OAAC,WACC,uBAAqB,mBACrB,IAAKjC,EACJ,GAAGwB,EACJ,aAAW,MAAG,0CAA2CD,EAAWxB,EAAW,IAAI,EAElF,SAAA0B,GAASA,EAAM,OAAS,KACvB,QAAC,OAAI,UAAU,iBACb,oBAAC,UACC,UAAU,oBACV,QAAS,CAAC,YAAU,EACpB,WAAY,CACV,OAAQ,IAAIS,CAAe,GAC3B,OAAQ,IAAIC,CAAe,EAC7B,EACA,SAAUC,GAAU,CAClBR,EAAU,QAAUQ,EACpBN,EAAe,CACb,YAAaM,EAAO,YACpB,MAAOA,EAAO,KAChB,CAAC,CACH,EACA,WAAY,IAAM,CAChBN,EAAeO,IAAS,CAAE,GAAGA,EAAM,MAAO,EAAK,EAAE,CACnD,EACA,iBAAkB,IAAM,CACtBP,EAAeO,IAAS,CAAE,GAAGA,EAAM,YAAa,EAAK,EAAE,CACzD,EACA,WAAY,IAAM,CAChBP,EAAe,CAAE,YAAa,GAAO,MAAO,EAAM,CAAC,CACrD,EACA,YAAaC,EAEZ,SAAAN,EAAM,IAAI,CAAC7B,EAAME,OAChB,OAAC,eAAgD,UAAU,mBACzD,mBAACH,EAAA,CACC,KAAMC,EACN,cAAe,CACb,MAAAQ,EACA,KAAAC,EACA,IAAKoB,EAAM,OACX,OAAAE,EACA,QAASF,EAAM,SAAW,EAC1B,MAAO3B,EACP,WAAAS,CACF,EACA,OAAQT,EACV,GAbgB,GAAGmC,CAAE,gBAAgBnC,CAAM,EAc7C,CACD,EACH,EAEC4B,GAAoBD,EAAM,OAAS,MAClC,oBACE,oBAAC,UACC,UAAW,GAAGU,CAAe,qEAAqEN,EAAY,YAAc,gCAAkC,8BAA8B,GAC5L,aAAW,iBAEX,mBAACzC,EAAA,CAAS,SAAUyC,EAAY,YAAa,EAC/C,KACA,OAAC,UACC,UAAW,GAAGK,CAAe,sEAAsEL,EAAY,MAAQ,gCAAkC,8BAA8B,GACvL,aAAW,aAEX,mBAACvC,EAAA,CAAS,SAAUuC,EAAY,MAAO,EACzC,GACF,GAEJ,EACE,KACN,CAEJ,CAAC,EAEDV,EAAiB,YAAc,mBAE/B,IAAO5C,KAAQ,cAAW4C,CAAgB",
|
|
6
6
|
"names": ["MediaTextOverlay_exports", "__export", "MediaTextOverlay_default", "__toCommonJS", "import_jsx_runtime", "import_react", "import_Styles", "import_utils", "import_useExposure", "import_AiuiProvider", "import_Media", "import_css", "import_navigation", "import_components", "import_modules", "PrevIcon", "disabled", "NextIcon", "componentType", "componentName", "PlayIcon", "PauseIcon", "ItemBlock", "item", "configuration", "jIndex", "classNames", "ref", "videoRef", "content", "media", "theme", "size", "onlyOne", "isAutoPlay", "isPlaying", "setIsPlaying", "hasVideo", "m", "handlePlayButtonClick", "video", "observer", "entries", "entry", "error", "Media", "MediaTextOverlay", "React", "props", "data", "className", "rest", "items", "isShowPagination", "locale", "swiperRef", "swiperState", "setSwiperState", "breakpoints", "len", "id", "nextButtonClass", "prevButtonClass", "swiper", "prev"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var g=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var z=Object.getOwnPropertyNames;var k=Object.prototype.hasOwnProperty;var L=(e,a)=>{for(var r in a)g(e,r,{get:a[r],enumerable:!0})},C=(e,a,r,
|
|
1
|
+
"use strict";var g=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var z=Object.getOwnPropertyNames;var k=Object.prototype.hasOwnProperty;var L=(e,a)=>{for(var r in a)g(e,r,{get:a[r],enumerable:!0})},C=(e,a,r,i)=>{if(a&&typeof a=="object"||typeof a=="function")for(let o of z(a))!k.call(e,o)&&o!==r&&g(e,o,{get:()=>a[o],enumerable:!(i=R(a,o))||i.enumerable});return e};var A=e=>C(g({},"__esModule",{value:!0}),e);var B={};L(B,{default:()=>D});module.exports=A(B);var t=require("react/jsx-runtime"),c=require("react"),n=require("../../components/index.js"),p=require("../../helpers/index.js"),y=require("../../shared/Styles.js");function E({children:e,offset:a=800}){const[r,i]=(0,c.useState)(!1),o=(0,c.useRef)(null);return(0,c.useEffect)(()=>{const s=new IntersectionObserver(([x])=>x.isIntersecting&&i(!0),{rootMargin:`${a}px`});return o.current&&s.observe(o.current),()=>s.disconnect()},[a]),(0,t.jsx)("div",{ref:o,className:"size-full",children:r&&e})}function h({media:e,poster:a,className:r}){return e?.url?e.mimeType?.startsWith("video/")?(0,t.jsx)("video",{src:e.url,playsInline:!0,autoPlay:!0,muted:!0,loop:!0,poster:a?.url||"",preload:"metadata",disablePictureInPicture:!0,disableRemotePlayback:!0,className:r,width:e.width,height:e.height}):(0,t.jsx)("img",{src:e.url,alt:e.alt||"",className:r,width:e.width,height:e.height}):null}function H(e,a,r){return a===2?r==="1:1"?"laptop:flex-[1]":e===0?"laptop:flex-[2]":"laptop:flex-[3]":"laptop:flex-[1]"}function j({data:e,className:a,...r}){const{title:i,titleType:o="primary",titleIcon:s,subtitle:x,subtitleImage:m,textAlign:T="left",products:d=[],twoImageRatio:v="2:3",threeImageRatio:S="1:1:1",theme:w="light"}=e,f=T==="center"?"text-center":"text-left laptop:text-left",b=()=>o==="secondary"?3:4,I=()=>i?o==="selling-point"&&s?(0,t.jsxs)("div",{className:(0,p.cn)("product-compare-title-wrapper flex items-center gap-[8px]",f==="text-center"?"justify-center":""),children:[(0,t.jsx)("img",{src:s.url,alt:s.alt||"",className:"product-compare-title-icon laptop:size-[32px] size-[24px]"}),(0,t.jsx)(n.Heading,{as:"h2",size:b(),html:i,className:"product-compare-title",style:{color:"#00BEFA"}})]}):(0,t.jsx)(n.Heading,{as:"h2",size:b(),html:i,className:(0,p.cn)("product-compare-title",f)}):null;return(0,t.jsxs)("section",{...r,className:(0,p.cn)("product-compare text-info-primary",a,{"aiui-dark":w==="dark"}),children:[I(),x&&(0,t.jsx)(n.Text,{as:"p",size:2,html:x,className:(0,p.cn)("product-compare-subtitle tablet:text-[14px] laptop:text-[14px] desktop:text-[16px] lg-desktop:text-[18px] mt-[4px] text-[14px]",f)}),m&&(0,t.jsx)("div",{className:(0,p.cn)("product-compare-subtitle-image laptop:mt-[24px] mt-[16px]",f==="text-center"?"flex justify-center":""),children:(0,t.jsx)("img",{src:m.url,alt:m.alt||"",className:"max-w-full",width:m.width,height:m.height})}),(0,t.jsx)("div",{className:"product-compare-container tablet:flex-row tablet:flex-nowrap laptop:mt-[32px] mt-[24px] flex w-full flex-col items-stretch gap-[16px]",children:d.map((l,u)=>{const M=u===d.length-1,N=H(u,d.length,v),P=M?"bg-brand-0":"bg-[rgba(0,0,0,0.2)]";return(0,t.jsxs)("div",{className:(0,p.cn)("product-compare-item rounded-box relative shrink overflow-hidden",N,{"order-2 tablet:order-1":u===0&&d.length===2,"order-1 tablet:order-2":u===1&&d.length===2}),children:[l.text&&(0,t.jsx)("div",{className:(0,p.cn)("product-compare-label rounded-btn laptop:left-[28px] laptop:top-[28px] laptop:px-[28px] laptop:pb-[14px] laptop:pt-[15px] desktop:left-[32px] desktop:top-[32px] text-badge-foreground absolute left-[16px] top-[16px] z-10 px-[20px] pb-[10px] pt-[11px] font-bold",P),children:(0,t.jsx)(n.Heading,{as:"h6",className:"font-bold",size:1,children:l.text})}),(0,t.jsxs)(E,{offset:1500,children:[(0,t.jsx)(h,{media:l.media,poster:l.poster,className:"product-compare-media laptop:block hidden size-full object-cover"}),(0,t.jsx)(h,{media:l.mobMedia?l.mobMedia:l.media,poster:l.mobPoster?l.mobPoster:l.poster,className:"product-compare-media-mobile laptop:hidden block w-full"})]})]},u)})})]})}var D=(0,y.withLayout)(j);
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/biz-components/ProductCompare/index.tsx"],
|
|
4
|
-
"sourcesContent": ["import { useEffect, useRef, useState } from 'react'\nimport { Heading, Text } from '../../components/index.js'\nimport { cn } from '../../helpers/index.js'\nimport type { Media, Theme } from '../../types/props.js'\nimport { withLayout } from '../../shared/Styles.js'\n\nfunction LazyMedia({ children, offset = 800 }: { children: React.ReactNode; offset?: number }) {\n const [loaded, setLoaded] = useState(false)\n const ref = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n const observer = new IntersectionObserver(([entry]) => entry.isIntersecting && setLoaded(true), {\n rootMargin: `${offset}px`,\n })\n ref.current && observer.observe(ref.current)\n return () => observer.disconnect()\n }, [offset])\n\n return (\n <div ref={ref} className=\"size-full\">\n {loaded && children}\n </div>\n )\n}\n\nfunction MediaElement({ media, poster, className }: { media?: Media; poster?: Media; className?: string }) {\n if (!media?.url) return null\n\n const isVideo = media.mimeType?.startsWith('video/')\n\n if (isVideo) {\n return (\n <video\n src={media.url}\n playsInline\n autoPlay\n muted\n loop\n poster={poster?.url || ''}\n preload=\"metadata\"\n disablePictureInPicture\n disableRemotePlayback\n className={className}\n width={media.width}\n height={media.height}\n />\n )\n }\n\n return <img src={media.url} alt={media.alt || ''} className={className} width={media.width} height={media.height} />\n}\n\nexport interface ProductItemData {\n /** \u4EA7\u54C1\u6807\u7B7E\u6587\u672C */\n text?: string\n /** \u684C\u9762\u7AEF\u5A92\u4F53\uFF08\u89C6\u9891\u6216\u56FE\u7247\uFF09 */\n media?: Media\n /** \u79FB\u52A8\u7AEF\u5A92\u4F53\uFF08\u89C6\u9891\u6216\u56FE\u7247\uFF09 */\n mobMedia?: Media\n /** \u684C\u9762\u7AEF\u5C01\u9762\u56FE\uFF08\u4EC5\u7528\u4E8E\u89C6\u9891\uFF09 */\n poster?: Media\n /** \u79FB\u52A8\u7AEF\u5C01\u9762\u56FE\uFF08\u4EC5\u7528\u4E8E\u89C6\u9891\uFF09 */\n mobPoster?: Media\n}\n\n/** \u6807\u9898\u7C7B\u578B */\nexport type TitleType = 'selling-point' | 'primary' | 'secondary'\n\n/** \u6587\u672C\u5BF9\u9F50\u65B9\u5F0F */\nexport type TextAlign = 'left' | 'center'\n\n/** \u56FE\u7247\u5BBD\u5EA6\u6BD4\u4F8B\uFF082\u5F20\u56FE\u7247\u65F6\uFF09 */\nexport type TwoImageRatio = '2:3' | '1:1'\n\n/** \u56FE\u7247\u5BBD\u5EA6\u6BD4\u4F8B\uFF083\u5F20\u56FE\u7247\u65F6\uFF09 */\nexport type ThreeImageRatio = '1:1:1'\n\nexport interface ProductCompareProps extends React.HTMLAttributes<HTMLElement> {\n /** \u7EC4\u4EF6\u6570\u636E */\n data: {\n /** \u4E3B\u6807\u9898 */\n title?: string\n /** \u6807\u9898\u7C7B\u578B\uFF1Aselling-point\uFF08\u5356\u70B9\uFF09\u3001primary\uFF08\u4E00\u7EA7\u6807\u9898\uFF09\u3001secondary\uFF08\u4E8C\u7EA7\u6807\u9898\uFF09 */\n titleType?: TitleType\n /** \u6807\u9898\u56FE\u6807\uFF08\u4EC5\u5F53 titleType \u4E3A selling-point \u65F6\u6709\u6548\uFF09 */\n titleIcon?: Media\n /** \u526F\u6807\u9898 */\n subtitle?: string\n /** \u526F\u6807\u9898\u4E0B\u65B9\u7684\u56FE\u7247 */\n subtitleImage?: Media\n /** \u6587\u672C\u5BF9\u9F50\u65B9\u5F0F\uFF1Aleft\uFF08\u5DE6\u5BF9\u9F50\uFF09\u3001center\uFF08\u5C45\u4E2D\uFF09 */\n textAlign?: TextAlign\n /** \u4EA7\u54C1\u5217\u8868\uFF08\u652F\u63012-3\u4E2A\u4EA7\u54C1\uFF09 */\n products?: ProductItemData[]\n /** 2\u5F20\u56FE\u7247\u65F6\u7684\u5BBD\u5EA6\u6BD4\u4F8B */\n twoImageRatio?: TwoImageRatio\n /** 3\u5F20\u56FE\u7247\u65F6\u7684\u5BBD\u5EA6\u6BD4\u4F8B */\n threeImageRatio?: ThreeImageRatio\n /** \u4E3B\u9898\uFF1Alight \u6216 dark */\n theme?: Theme\n }\n}\n\n/**\n * \u6839\u636E\u4EA7\u54C1\u6570\u91CF\u548C\u6BD4\u4F8B\u83B7\u53D6\u5E03\u5C40\u7C7B\u540D\n */\nfunction getProductLayoutClasses(index: number, totalProducts: number, twoImageRatio?: TwoImageRatio): string {\n if (totalProducts === 2) {\n if (twoImageRatio === '1:1') {\n return 'laptop:flex-[1]'\n }\n // \u9ED8\u8BA4 2:3 \u6BD4\u4F8B\n return index === 0 ? 'laptop:flex-[2]' : 'laptop:flex-[3]'\n }\n\n if (totalProducts === 3) {\n // 1:1:1 \u6BD4\u4F8B\n return 'laptop:flex-[1]'\n }\n\n return 'laptop:flex-[1]'\n}\n\nfunction ProductCompare({ data, className, ...rest }: ProductCompareProps) {\n const {\n title,\n titleType = 'primary',\n titleIcon,\n subtitle,\n subtitleImage,\n textAlign = 'left',\n products = [],\n twoImageRatio = '2:3',\n threeImageRatio = '1:1:1',\n theme = 'light',\n } = data\n\n // \u6587\u672C\u5BF9\u9F50\u7C7B\u540D\n const alignClasses = textAlign === 'center' ? 'text-center' : 'text-left laptop:text-left'\n\n // \u6839\u636E\u6807\u9898\u7C7B\u578B\u786E\u5B9A Heading size \u548C\u6837\u5F0F\n const getTitleSize = () => {\n if (titleType === 'secondary') return 3\n return 4\n }\n\n // \u6E32\u67D3\u6807\u9898\n const renderTitle = () => {\n if (!title) return null\n\n // \u5356\u70B9\u6807\u9898\uFF08\u5305\u542B\u56FE\u6807\uFF09\n if (titleType === 'selling-point' && titleIcon) {\n return (\n <div\n className={cn(\n 'product-compare-title-wrapper flex items-center gap-[8px]',\n alignClasses === 'text-center' ? 'justify-center' : ''\n )}\n >\n <img\n src={titleIcon.url}\n alt={titleIcon.alt || ''}\n className=\"product-compare-title-icon laptop:size-[32px] size-[24px]\"\n />\n <Heading\n as=\"h2\"\n size={getTitleSize()}\n html={title}\n className=\"product-compare-title\"\n style={{ color: '#00BEFA' }}\n />\n </div>\n )\n }\n\n // \u666E\u901A\u6807\u9898\n return <Heading as=\"h2\" size={getTitleSize()} html={title} className={cn('product-compare-title', alignClasses)} />\n }\n\n return (\n <section\n {...rest}\n className={cn('product-compare text-info-primary', className, {\n 'aiui-dark': theme === 'dark',\n })}\n >\n {/* \u6807\u9898\u533A\u57DF */}\n {renderTitle()}\n\n {/* \u526F\u6807\u9898 */}\n {subtitle && (\n <Text\n as=\"p\"\n size={2}\n html={subtitle}\n className={cn(\n 'product-compare-subtitle tablet:text-[14px] laptop:text-[14px] desktop:text-[16px] lg-desktop:text-[18px] mt-[4px] text-[14px]',\n alignClasses\n )}\n />\n )}\n\n {/* \u526F\u6807\u9898\u4E0B\u65B9\u56FE\u7247 */}\n {subtitleImage && (\n <div\n className={cn(\n 'product-compare-subtitle-image laptop:mt-[24px] mt-[16px]',\n alignClasses === 'text-center' ? 'flex justify-center' : ''\n )}\n >\n <img\n src={subtitleImage.url}\n alt={subtitleImage.alt || ''}\n className=\"max-w-full\"\n width={subtitleImage.width}\n height={subtitleImage.height}\n />\n </div>\n )}\n\n {/* \u4EA7\u54C1\u5BF9\u6BD4\u5361\u7247\u5BB9\u5668 */}\n <div className=\"product-compare-container tablet:flex-row tablet:flex-nowrap laptop:mt-[32px] mt-[24px] flex w-full flex-col items-stretch gap-[16px]\">\n {products.map((product, index) => {\n const isLastProduct = index === products.length - 1\n const layoutClasses = getProductLayoutClasses(index, products.length, twoImageRatio)\n\n // \u6807\u7B7E\u6837\u5F0F\uFF1A\u6700\u540E\u4E00\u4E2A\u4EA7\u54C1\u7528 bg-brand-0\uFF0C\u5176\u4ED6\u7528 rgba(0,0,0,0.2)\n const labelBgClass = isLastProduct ? 'bg-brand-0' : 'bg-[rgba(0,0,0,0.2)]'\n\n return (\n <div\n key={index}\n className={cn('product-compare-item rounded-box relative shrink overflow-hidden', layoutClasses, {\n 'order-2 tablet:order-1': index === 0 && products.length === 2,\n 'order-1 tablet:order-2': index === 1 && products.length === 2,\n })}\n >\n {/* \u4EA7\u54C1\u6807\u7B7E */}\n {product.text && (\n <div\n className={cn(\n 'product-compare-label rounded-btn laptop:left-[28px] laptop:top-[28px] laptop:px-[28px] laptop:pb-[14px] laptop:pt-[15px] desktop:left-[32px] desktop:top-[32px] absolute left-[16px] top-[16px] z-10 px-[20px] pb-[10px] pt-[11px] font-bold
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import { useEffect, useRef, useState } from 'react'\nimport { Heading, Text } from '../../components/index.js'\nimport { cn } from '../../helpers/index.js'\nimport type { Media, Theme } from '../../types/props.js'\nimport { withLayout } from '../../shared/Styles.js'\n\nfunction LazyMedia({ children, offset = 800 }: { children: React.ReactNode; offset?: number }) {\n const [loaded, setLoaded] = useState(false)\n const ref = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n const observer = new IntersectionObserver(([entry]) => entry.isIntersecting && setLoaded(true), {\n rootMargin: `${offset}px`,\n })\n ref.current && observer.observe(ref.current)\n return () => observer.disconnect()\n }, [offset])\n\n return (\n <div ref={ref} className=\"size-full\">\n {loaded && children}\n </div>\n )\n}\n\nfunction MediaElement({ media, poster, className }: { media?: Media; poster?: Media; className?: string }) {\n if (!media?.url) return null\n\n const isVideo = media.mimeType?.startsWith('video/')\n\n if (isVideo) {\n return (\n <video\n src={media.url}\n playsInline\n autoPlay\n muted\n loop\n poster={poster?.url || ''}\n preload=\"metadata\"\n disablePictureInPicture\n disableRemotePlayback\n className={className}\n width={media.width}\n height={media.height}\n />\n )\n }\n\n return <img src={media.url} alt={media.alt || ''} className={className} width={media.width} height={media.height} />\n}\n\nexport interface ProductItemData {\n /** \u4EA7\u54C1\u6807\u7B7E\u6587\u672C */\n text?: string\n /** \u684C\u9762\u7AEF\u5A92\u4F53\uFF08\u89C6\u9891\u6216\u56FE\u7247\uFF09 */\n media?: Media\n /** \u79FB\u52A8\u7AEF\u5A92\u4F53\uFF08\u89C6\u9891\u6216\u56FE\u7247\uFF09 */\n mobMedia?: Media\n /** \u684C\u9762\u7AEF\u5C01\u9762\u56FE\uFF08\u4EC5\u7528\u4E8E\u89C6\u9891\uFF09 */\n poster?: Media\n /** \u79FB\u52A8\u7AEF\u5C01\u9762\u56FE\uFF08\u4EC5\u7528\u4E8E\u89C6\u9891\uFF09 */\n mobPoster?: Media\n}\n\n/** \u6807\u9898\u7C7B\u578B */\nexport type TitleType = 'selling-point' | 'primary' | 'secondary'\n\n/** \u6587\u672C\u5BF9\u9F50\u65B9\u5F0F */\nexport type TextAlign = 'left' | 'center'\n\n/** \u56FE\u7247\u5BBD\u5EA6\u6BD4\u4F8B\uFF082\u5F20\u56FE\u7247\u65F6\uFF09 */\nexport type TwoImageRatio = '2:3' | '1:1'\n\n/** \u56FE\u7247\u5BBD\u5EA6\u6BD4\u4F8B\uFF083\u5F20\u56FE\u7247\u65F6\uFF09 */\nexport type ThreeImageRatio = '1:1:1'\n\nexport interface ProductCompareProps extends React.HTMLAttributes<HTMLElement> {\n /** \u7EC4\u4EF6\u6570\u636E */\n data: {\n /** \u4E3B\u6807\u9898 */\n title?: string\n /** \u6807\u9898\u7C7B\u578B\uFF1Aselling-point\uFF08\u5356\u70B9\uFF09\u3001primary\uFF08\u4E00\u7EA7\u6807\u9898\uFF09\u3001secondary\uFF08\u4E8C\u7EA7\u6807\u9898\uFF09 */\n titleType?: TitleType\n /** \u6807\u9898\u56FE\u6807\uFF08\u4EC5\u5F53 titleType \u4E3A selling-point \u65F6\u6709\u6548\uFF09 */\n titleIcon?: Media\n /** \u526F\u6807\u9898 */\n subtitle?: string\n /** \u526F\u6807\u9898\u4E0B\u65B9\u7684\u56FE\u7247 */\n subtitleImage?: Media\n /** \u6587\u672C\u5BF9\u9F50\u65B9\u5F0F\uFF1Aleft\uFF08\u5DE6\u5BF9\u9F50\uFF09\u3001center\uFF08\u5C45\u4E2D\uFF09 */\n textAlign?: TextAlign\n /** \u4EA7\u54C1\u5217\u8868\uFF08\u652F\u63012-3\u4E2A\u4EA7\u54C1\uFF09 */\n products?: ProductItemData[]\n /** 2\u5F20\u56FE\u7247\u65F6\u7684\u5BBD\u5EA6\u6BD4\u4F8B */\n twoImageRatio?: TwoImageRatio\n /** 3\u5F20\u56FE\u7247\u65F6\u7684\u5BBD\u5EA6\u6BD4\u4F8B */\n threeImageRatio?: ThreeImageRatio\n /** \u4E3B\u9898\uFF1Alight \u6216 dark */\n theme?: Theme\n }\n}\n\n/**\n * \u6839\u636E\u4EA7\u54C1\u6570\u91CF\u548C\u6BD4\u4F8B\u83B7\u53D6\u5E03\u5C40\u7C7B\u540D\n */\nfunction getProductLayoutClasses(index: number, totalProducts: number, twoImageRatio?: TwoImageRatio): string {\n if (totalProducts === 2) {\n if (twoImageRatio === '1:1') {\n return 'laptop:flex-[1]'\n }\n // \u9ED8\u8BA4 2:3 \u6BD4\u4F8B\n return index === 0 ? 'laptop:flex-[2]' : 'laptop:flex-[3]'\n }\n\n if (totalProducts === 3) {\n // 1:1:1 \u6BD4\u4F8B\n return 'laptop:flex-[1]'\n }\n\n return 'laptop:flex-[1]'\n}\n\nfunction ProductCompare({ data, className, ...rest }: ProductCompareProps) {\n const {\n title,\n titleType = 'primary',\n titleIcon,\n subtitle,\n subtitleImage,\n textAlign = 'left',\n products = [],\n twoImageRatio = '2:3',\n threeImageRatio = '1:1:1',\n theme = 'light',\n } = data\n\n // \u6587\u672C\u5BF9\u9F50\u7C7B\u540D\n const alignClasses = textAlign === 'center' ? 'text-center' : 'text-left laptop:text-left'\n\n // \u6839\u636E\u6807\u9898\u7C7B\u578B\u786E\u5B9A Heading size \u548C\u6837\u5F0F\n const getTitleSize = () => {\n if (titleType === 'secondary') return 3\n return 4\n }\n\n // \u6E32\u67D3\u6807\u9898\n const renderTitle = () => {\n if (!title) return null\n\n // \u5356\u70B9\u6807\u9898\uFF08\u5305\u542B\u56FE\u6807\uFF09\n if (titleType === 'selling-point' && titleIcon) {\n return (\n <div\n className={cn(\n 'product-compare-title-wrapper flex items-center gap-[8px]',\n alignClasses === 'text-center' ? 'justify-center' : ''\n )}\n >\n <img\n src={titleIcon.url}\n alt={titleIcon.alt || ''}\n className=\"product-compare-title-icon laptop:size-[32px] size-[24px]\"\n />\n <Heading\n as=\"h2\"\n size={getTitleSize()}\n html={title}\n className=\"product-compare-title\"\n style={{ color: '#00BEFA' }}\n />\n </div>\n )\n }\n\n // \u666E\u901A\u6807\u9898\n return <Heading as=\"h2\" size={getTitleSize()} html={title} className={cn('product-compare-title', alignClasses)} />\n }\n\n return (\n <section\n {...rest}\n className={cn('product-compare text-info-primary', className, {\n 'aiui-dark': theme === 'dark',\n })}\n >\n {/* \u6807\u9898\u533A\u57DF */}\n {renderTitle()}\n\n {/* \u526F\u6807\u9898 */}\n {subtitle && (\n <Text\n as=\"p\"\n size={2}\n html={subtitle}\n className={cn(\n 'product-compare-subtitle tablet:text-[14px] laptop:text-[14px] desktop:text-[16px] lg-desktop:text-[18px] mt-[4px] text-[14px]',\n alignClasses\n )}\n />\n )}\n\n {/* \u526F\u6807\u9898\u4E0B\u65B9\u56FE\u7247 */}\n {subtitleImage && (\n <div\n className={cn(\n 'product-compare-subtitle-image laptop:mt-[24px] mt-[16px]',\n alignClasses === 'text-center' ? 'flex justify-center' : ''\n )}\n >\n <img\n src={subtitleImage.url}\n alt={subtitleImage.alt || ''}\n className=\"max-w-full\"\n width={subtitleImage.width}\n height={subtitleImage.height}\n />\n </div>\n )}\n\n {/* \u4EA7\u54C1\u5BF9\u6BD4\u5361\u7247\u5BB9\u5668 */}\n <div className=\"product-compare-container tablet:flex-row tablet:flex-nowrap laptop:mt-[32px] mt-[24px] flex w-full flex-col items-stretch gap-[16px]\">\n {products.map((product, index) => {\n const isLastProduct = index === products.length - 1\n const layoutClasses = getProductLayoutClasses(index, products.length, twoImageRatio)\n\n // \u6807\u7B7E\u6837\u5F0F\uFF1A\u6700\u540E\u4E00\u4E2A\u4EA7\u54C1\u7528 bg-brand-0\uFF0C\u5176\u4ED6\u7528 rgba(0,0,0,0.2)\n const labelBgClass = isLastProduct ? 'bg-brand-0' : 'bg-[rgba(0,0,0,0.2)]'\n\n return (\n <div\n key={index}\n className={cn('product-compare-item rounded-box relative shrink overflow-hidden', layoutClasses, {\n 'order-2 tablet:order-1': index === 0 && products.length === 2,\n 'order-1 tablet:order-2': index === 1 && products.length === 2,\n })}\n >\n {/* \u4EA7\u54C1\u6807\u7B7E */}\n {product.text && (\n <div\n className={cn(\n 'product-compare-label rounded-btn laptop:left-[28px] laptop:top-[28px] laptop:px-[28px] laptop:pb-[14px] laptop:pt-[15px] desktop:left-[32px] desktop:top-[32px] text-badge-foreground absolute left-[16px] top-[16px] z-10 px-[20px] pb-[10px] pt-[11px] font-bold',\n labelBgClass\n )}\n >\n <Heading as=\"h6\" className=\"font-bold\" size={1}>\n {product.text}\n </Heading>\n </div>\n )}\n\n {/* \u4EA7\u54C1\u5A92\u4F53 */}\n <LazyMedia offset={1500}>\n <MediaElement\n media={product.media}\n poster={product.poster}\n className=\"product-compare-media laptop:block hidden size-full object-cover\"\n />\n <MediaElement\n media={product.mobMedia ? product.mobMedia : product.media}\n poster={product.mobPoster ? product.mobPoster : product.poster}\n className=\"product-compare-media-mobile laptop:hidden block w-full\"\n />\n </LazyMedia>\n </div>\n )\n })}\n </div>\n </section>\n )\n}\n\nexport default withLayout(ProductCompare)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["ProductCompare_exports", "__export", "ProductCompare_default", "__toCommonJS", "import_jsx_runtime", "import_react", "import_components", "import_helpers", "import_Styles", "LazyMedia", "children", "offset", "loaded", "setLoaded", "ref", "observer", "entry", "MediaElement", "media", "poster", "className", "getProductLayoutClasses", "index", "totalProducts", "twoImageRatio", "ProductCompare", "data", "rest", "title", "titleType", "titleIcon", "subtitle", "subtitleImage", "textAlign", "products", "threeImageRatio", "theme", "alignClasses", "getTitleSize", "renderTitle", "product", "isLastProduct", "layoutClasses", "labelBgClass"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";"use client";var dt=Object.create;var w=Object.defineProperty;var ct=Object.getOwnPropertyDescriptor;var ut=Object.getOwnPropertyNames;var mt=Object.getPrototypeOf,pt=Object.prototype.hasOwnProperty;var ft=(t,n)=>{for(var e in n)w(t,e,{get:n[e],enumerable:!0})},
|
|
1
|
+
"use strict";"use client";var dt=Object.create;var w=Object.defineProperty;var ct=Object.getOwnPropertyDescriptor;var ut=Object.getOwnPropertyNames;var mt=Object.getPrototypeOf,pt=Object.prototype.hasOwnProperty;var ft=(t,n)=>{for(var e in n)w(t,e,{get:n[e],enumerable:!0})},N=(t,n,e,s)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of ut(n))!pt.call(t,r)&&r!==e&&w(t,r,{get:()=>n[r],enumerable:!(s=ct(n,r))||s.enumerable});return t};var ht=(t,n,e)=>(e=t!=null?dt(mt(t)):{},N(n||!t||!t.__esModule?w(e,"default",{value:t,enumerable:!0}):e,t)),gt=t=>N(w({},"__esModule",{value:!0}),t);var yt={};ft(yt,{default:()=>vt});module.exports=gt(yt);var i=require("react/jsx-runtime"),a=ht(require("react")),b=require("gsap"),F=require("gsap/dist/SplitText"),H=require("gsap/dist/ScrollTrigger"),l=require("../../helpers/utils.js"),L=require("class-variance-authority"),d=require("../../components/index.js"),B=require("../../shared/Styles.js"),I=require("../../shared/trackUrlRef.js"),j=require("react-intersection-observer");const P="link",S="title";function xt(t){if(!t)return!1;if(typeof t=="string")return t.trim().length>0;const n=t?.root?.children;return!Array.isArray(n)||n.length===0?!1:n.some(e=>{const s=e?.children;return!Array.isArray(s)||s.length===0?!1:s.some(r=>typeof r?.text=="string"&&r.text.length>0)})}const wt=(0,L.cva)("",{variants:{theme:{light:"text-[#080A0F]",dark:"text-[#F5F6F7]"}},defaultVariants:{theme:"light"}}),bt=(0,L.cva)("desktop:text-base desktop:mt-2 lg-desktop:text-[18px] mt-1 text-[14px] font-bold leading-[1.4] tracking-[-0.36px]",{variants:{theme:{light:"text-[#080A0F]",dark:"text-[#F5F6F7]"}},defaultVariants:{theme:"light"}}),$=({data:t,onClick:n,className:e})=>{const{theme:s="light",extensions:r,title:h,caption:v,align:g}=t;if(!r?.textLink)return null;const u=r?.link?(0,I.trackUrlRef)(r.link,`${P}_${S}`):void 0;return(0,i.jsxs)("a",{className:(0,l.cn)({"aiui-dark":s==="dark"},"hover:text-brand-0 [&_svg_path]:hover:fill-brand-0 lg-desktop:text-base flex cursor-pointer items-center overflow-hidden text-sm font-[700] leading-[1.4] transition-all duration-[0.4s]",{"text-[#080A0F]":s==="light"},{"text-[#F5F6F7]":s==="dark"},{"justify-center mt-4":g==="center"},{"mt-1 laptop:mt-0":g==="left"},e),...u?{href:u}:{},"data-headless-type-name":`${P}#${S}`,"data-headless-title-desc-button":`${h}#${v}`,...n?{onClick:n}:{},children:[(0,i.jsx)("div",{className:"truncate whitespace-nowrap",children:r?.textLink}),(0,i.jsx)("div",{className:"lg-desktop:size-5 size-4",children:(0,i.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"100%",height:"100%",viewBox:"0 0 16 16",fill:"none",children:(0,i.jsx)("path",{d:"M5.52827 3.52864C5.78862 3.26829 6.21063 3.26829 6.47098 3.52864L10.471 7.52864C10.7313 7.78899 10.7313 8.21099 10.471 8.47134L6.47098 12.4713C6.21063 12.7317 5.78862 12.7317 5.52827 12.4713C5.26792 12.211 5.26792 11.789 5.52827 11.5286L9.05692 7.99999L5.52827 4.47134C5.26792 4.21099 5.26792 3.78899 5.52827 3.52864Z",fill:s==="dark"?"#F5F6F7":"#080A0F",className:"transition-all duration-[0.4s]"})})})]})},_=a.default.forwardRef(({data:t,className:n,classNames:e,as:s="h2",weight:r="bold",onButtonClick:h,...v},g)=>{const{title:u,titleSize:O=4,caption:C,subtitle:D,content:M,countdown:o,showCountdown:U=!1,theme:x="light",extensions:W,align:m="left"}=t,E=(0,a.useRef)(null),p=(0,a.useRef)(null),c=(0,a.useRef)(null),f=(0,a.useRef)(null),[Z,q]=(0,a.useState)(!0),{ref:G,inView:z}=(0,j.useInView)();(0,a.useImperativeHandle)(g,()=>E.current);const J=()=>{q(!1)},K=o?.targetDateTime||o?.targetDate||"",Q=o?.targetDateTime_tz,X=o?.labels?{day:o.labels.days||"Day",hour:o.labels.hours||"Hours",minute:o.labels.minutes||"Mins",second:o.labels.seconds||"Secs"}:void 0;return(0,a.useEffect)(()=>{b.gsap.registerPlugin(F.SplitText,H.ScrollTrigger);function Y(){if(!p.current)return;const tt=p.current?.clientHeight||80;c.current&&c.current.revert(),f.current&&f.current.kill(),c.current=new F.SplitText(p.current,{type:"words",wordsClass:"word"});const y=c.current.words;b.gsap.set(y,{opacity:0}),f.current=H.ScrollTrigger.create({trigger:p.current,start:"bottom bottom-=4%",end:`bottom+=${tt*1.5+60}px bottom-=4%`,scrub:!0,invalidateOnRefresh:!0,onUpdate:et=>{const nt=et.progress,R=y.length||1,rt=.5,k=1/R,V=k*(1-rt),A=(R-1)*V+k,it=Math.min(1,A>0?nt/A:0);y.forEach((st,ot)=>{const at=ot*V,lt=k;let T=(it-at)/lt;T=Math.max(0,Math.min(1,T)),b.gsap.set(st,{opacity:T})})}})}return z&&Y(),()=>{c.current&&c.current.revert(),f.current&&f.current.kill()}},[z]),(0,i.jsxs)("div",{...v,id:W?.id,className:(0,l.cn)("titleBottom title-box flex items-end justify-between gap-2 pb-6",n,e?.wrapper),ref:E,children:[(0,i.jsxs)("div",{ref:G,className:(0,l.cn)("flex-1",e?.container,{"aiui-dark":x==="dark","text-center":m==="center","text-left":m==="left"}),children:[(C||u)&&(0,i.jsx)(d.Heading,{ref:p,as:s,size:O,html:C||u,weight:r,className:(0,l.cn)(wt({theme:x}),e?.title)}),D&&(0,i.jsx)(d.Text,{html:D,as:"p",className:(0,l.cn)(bt({theme:x}),e?.subtitle)}),xt(M)&&(0,i.jsx)(d.Text,{html:M,as:"div",size:4,className:(0,l.cn)("title-content text-info-primary desktop:text-base desktop:mt-4 lg-desktop:text-[18px] mt-2 text-[14px] leading-[1.6]",e?.content)}),(0,i.jsx)($,{data:t,className:(0,l.cn)({"laptop:hidden":m==="left"},e?.button),onClick:h}),U&&o&&Z&&(0,i.jsx)(d.Countdown,{endDate:K,endDate_tz:Q,timeLabels:X,showDays:o?.showDays,showHours:o?.showHours,showMinutes:o?.showMinutes,showSeconds:o?.showSeconds,theme:x,onExpire:J,hideWhenExpired:!0,align:m==="center"?"center":"left",className:(0,l.cn)("mt-4",e?.countdown)})]}),(0,i.jsx)($,{data:t,className:(0,l.cn)("hidden",{"laptop:flex":m==="left"},e?.button),onClick:h})]})});_.displayName="Title";var vt=(0,B.withLayout)(_);
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/biz-components/Title/index.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\nimport React, { useEffect, useRef, useImperativeHandle, useState } from 'react'\nimport { gsap } from 'gsap'\nimport { SplitText } from 'gsap/dist/SplitText'\nimport { ScrollTrigger } from 'gsap/dist/ScrollTrigger'\nimport { cn } from '../../helpers/utils.js'\nimport { cva } from 'class-variance-authority'\nimport { Heading, Text, Countdown, type HeadingProps } from '../../components/index.js'\nimport { withLayout } from '../../shared/Styles.js'\nimport type { TitlePropsBase } from './types.js'\n\nexport interface TitleProps extends TitlePropsBase, Omit<React.HTMLAttributes<HTMLDivElement>, 'className' | 'title'> {}\nimport { trackUrlRef } from '../../shared/trackUrlRef.js'\nimport { useInView } from 'react-intersection-observer'\n\nconst componentType = 'link'\nconst componentName = 'title'\n\n/**\n * \u6807\u9898\u6837\u5F0F\u53D8\u4F53\n */\nconst titleHeadingVariants = cva('', {\n variants: {\n theme: {\n light: 'text-[#080A0F]',\n dark: 'text-[#F5F6F7]',\n },\n },\n defaultVariants: {\n theme: 'light',\n },\n})\n\n/**\n * \u526F\u6807\u9898\u6837\u5F0F\u53D8\u4F53\n */\nconst subtitleVariants = cva(\n 'desktop:text-base desktop:mt-2 lg-desktop:text-[18px] mt-1 text-[14px] font-bold leading-[1.4] tracking-[-0.36px]',\n {\n variants: {\n theme: {\n light: 'text-[#080A0F]',\n dark: 'text-[#F5F6F7]',\n },\n },\n defaultVariants: {\n theme: 'light',\n },\n }\n)\n\nconst TitleButton = ({\n data,\n onClick,\n className,\n}: {\n data: TitleProps['data']\n onClick?: () => void\n className?: string\n}) => {\n const { theme = 'light', extensions, title, caption, align } = data\n if (!extensions?.textLink) return null\n\n const href = extensions?.link ? trackUrlRef(extensions.link, `${componentType}_${componentName}`) : undefined\n\n return (\n <a\n className={cn(\n { 'aiui-dark': theme === 'dark' },\n 'hover:text-brand-0 [&_svg_path]:hover:fill-brand-0 lg-desktop:text-base flex cursor-pointer items-center overflow-hidden text-sm font-[700] leading-[1.4] transition-all duration-[0.4s]',\n { 'text-[#080A0F]': theme === 'light' },\n { 'text-[#F5F6F7]': theme === 'dark' },\n { 'justify-center mt-4': align === 'center' },\n { 'mt-1 laptop:mt-0': align === 'left' },\n className\n )}\n {...(href ? { href } : {})}\n data-headless-type-name={`${componentType}#${componentName}`}\n data-headless-title-desc-button={`${title}#${caption}`}\n {...(onClick ? { onClick } : {})}\n >\n <div className=\"truncate whitespace-nowrap\">{extensions?.textLink}</div>\n <div className=\"lg-desktop:size-5 size-4\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"100%\" height=\"100%\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n d=\"M5.52827 3.52864C5.78862 3.26829 6.21063 3.26829 6.47098 3.52864L10.471 7.52864C10.7313 7.78899 10.7313 8.21099 10.471 8.47134L6.47098 12.4713C6.21063 12.7317 5.78862 12.7317 5.52827 12.4713C5.26792 12.211 5.26792 11.789 5.52827 11.5286L9.05692 7.99999L5.52827 4.47134C5.26792 4.21099 5.26792 3.78899 5.52827 3.52864Z\"\n fill={theme === 'dark' ? '#F5F6F7' : '#080A0F'}\n className=\"transition-all duration-[0.4s]\"\n />\n </svg>\n </div>\n </a>\n )\n}\n\nconst Title = React.forwardRef<HTMLDivElement, TitleProps>(\n ({ data, className, classNames, as = 'h2', weight = 'bold', onButtonClick, ...rest }, ref) => {\n const {\n title,\n titleSize = 4,\n caption,\n subtitle,\n content,\n countdown,\n showCountdown = false,\n theme = 'light',\n extensions,\n align = 'left',\n } = data\n const innerRef = useRef<HTMLDivElement>(null)\n const titleRef = useRef<HTMLHeadingElement>(null)\n const splitTextInstance = useRef<SplitText | null>(null)\n const scrollTriggerRef = useRef<ScrollTrigger | null>(null)\n\n // \u63A7\u5236\u5012\u8BA1\u65F6\u663E\u793A\u72B6\u6001\n const [isCountdownVisible, setIsCountdownVisible] = useState(true)\n\n const { ref: inViewRef, inView } = useInView()\n\n useImperativeHandle(ref, () => innerRef.current as HTMLDivElement)\n\n // \u5012\u8BA1\u65F6\u7ED3\u675F\u56DE\u8C03\n const handleCountdownEnd = () => {\n setIsCountdownVisible(false)\n }\n\n // CMS field mapping: new targetDateTime > legacy targetDate\n const countdownEndDate = countdown?.targetDateTime || countdown?.targetDate || ''\n const countdownTz = countdown?.targetDateTime_tz\n // Label mapping: plural keys (Title CMS format) \u2192 atomic Countdown format\n const countdownLabels = countdown?.labels\n ? {\n day: countdown.labels.days || 'Day',\n hour: countdown.labels.hours || 'Hours',\n minute: countdown.labels.minutes || 'Mins',\n second: countdown.labels.seconds || 'Secs',\n }\n : undefined\n\n useEffect(() => {\n gsap.registerPlugin(SplitText, ScrollTrigger)\n function gsapResize() {\n if (!titleRef.current) return\n const height = titleRef.current?.clientHeight || 80\n if (splitTextInstance.current) {\n splitTextInstance.current.revert()\n }\n if (scrollTriggerRef.current) {\n scrollTriggerRef.current.kill()\n }\n splitTextInstance.current = new SplitText(titleRef.current, {\n type: 'words',\n wordsClass: 'word',\n })\n const words = splitTextInstance.current.words\n gsap.set(words, { opacity: 0 })\n scrollTriggerRef.current = ScrollTrigger.create({\n trigger: titleRef.current,\n start: 'bottom bottom-=4%',\n end: `bottom+=${height * 1.5 + 60}px bottom-=4%`,\n scrub: true,\n invalidateOnRefresh: true,\n onUpdate: (self: any) => {\n const progress = self.progress\n const total = words.length || 1\n const overlap = 0.5\n const interval = 1 / total\n const step = interval * (1 - overlap)\n const lastEnd = (total - 1) * step + interval\n const normalizedProgress = Math.min(1, lastEnd > 0 ? progress / lastEnd : 0)\n words.forEach((word: any, i: number) => {\n const start = i * step\n const width = interval\n let opacity = (normalizedProgress - start) / width\n opacity = Math.max(0, Math.min(1, opacity))\n gsap.set(word, { opacity })\n })\n },\n })\n }\n\n if (inView) {\n gsapResize()\n }\n\n return () => {\n splitTextInstance.current && splitTextInstance.current.revert()\n // ScrollTrigger.getAll().forEach((t: { kill: () => any }) => t.kill())\n scrollTriggerRef.current && scrollTriggerRef.current.kill()\n }\n }, [inView])\n\n return (\n <div\n {...rest}\n id={extensions?.id}\n className={cn(\n 'titleBottom title-box flex items-end justify-between gap-2 pb-6',\n className,\n classNames?.wrapper\n )}\n ref={innerRef}\n >\n <div\n ref={inViewRef}\n className={cn('flex-1', classNames?.container, {\n 'aiui-dark': theme === 'dark',\n 'text-center': align === 'center',\n 'text-left': align === 'left',\n })}\n >\n {(caption || title) && (\n <Heading\n ref={titleRef}\n as={as}\n size={titleSize as HeadingProps['size']}\n html={caption || title}\n weight={weight}\n className={cn(titleHeadingVariants({ theme }), classNames?.title)}\n />\n )}\n {subtitle && (\n <Text html={subtitle} as=\"p\" className={cn(subtitleVariants({ theme }), classNames?.subtitle)} />\n )}\n {content && (\n <Text\n html={content}\n as=\"div\"\n size={4}\n className={cn(\n 'title-content text-info-primary desktop:text-base desktop:mt-4 lg-desktop:text-[18px] mt-2 text-[14px] leading-[1.6]',\n classNames?.content\n )}\n />\n )}\n <TitleButton\n data={data}\n className={cn({ 'laptop:hidden': align === 'left' }, classNames?.button)}\n onClick={onButtonClick}\n />\n {showCountdown && countdown && isCountdownVisible && (\n <Countdown\n endDate={countdownEndDate}\n endDate_tz={countdownTz}\n timeLabels={countdownLabels}\n showDays={countdown?.showDays}\n showHours={countdown?.showHours}\n showMinutes={countdown?.showMinutes}\n showSeconds={countdown?.showSeconds}\n theme={theme}\n onExpire={handleCountdownEnd}\n hideWhenExpired={true}\n align={align === 'center' ? 'center' : 'left'}\n className={cn('mt-4', classNames?.countdown)}\n />\n )}\n </div>\n <TitleButton\n data={data}\n className={cn('hidden', { ['laptop:flex']: align === 'left' }, classNames?.button)}\n onClick={onButtonClick}\n />\n </div>\n )\n }\n)\n\nTitle.displayName = 'Title'\n\nexport default withLayout(Title)\n"],
|
|
5
|
-
"mappings": "olBAAA,IAAAA,GAAA,GAAAC,GAAAD,GAAA,aAAAE,KAAA,eAAAC,GAAAH,
|
|
6
|
-
"names": ["Title_exports", "__export", "Title_default", "__toCommonJS", "import_jsx_runtime", "import_react", "import_gsap", "import_SplitText", "import_ScrollTrigger", "import_utils", "import_class_variance_authority", "import_components", "import_Styles", "import_trackUrlRef", "import_react_intersection_observer", "componentType", "componentName", "titleHeadingVariants", "subtitleVariants", "TitleButton", "data", "onClick", "className", "theme", "extensions", "title", "caption", "align", "href", "Title", "React", "classNames", "as", "weight", "onButtonClick", "rest", "ref", "titleSize", "subtitle", "
|
|
4
|
+
"sourcesContent": ["'use client'\nimport React, { useEffect, useRef, useImperativeHandle, useState } from 'react'\nimport { gsap } from 'gsap'\nimport { SplitText } from 'gsap/dist/SplitText'\nimport { ScrollTrigger } from 'gsap/dist/ScrollTrigger'\nimport { cn } from '../../helpers/utils.js'\nimport { cva } from 'class-variance-authority'\nimport { Heading, Text, Countdown, type HeadingProps } from '../../components/index.js'\nimport { withLayout } from '../../shared/Styles.js'\nimport type { TitlePropsBase } from './types.js'\n\nexport interface TitleProps extends TitlePropsBase, Omit<React.HTMLAttributes<HTMLDivElement>, 'className' | 'title'> {}\nimport { trackUrlRef } from '../../shared/trackUrlRef.js'\nimport { useInView } from 'react-intersection-observer'\n\nconst componentType = 'link'\nconst componentName = 'title'\n\n/**\n * \u5224\u65AD content \u5B57\u6BB5\u662F\u5426\u6709\u5B9E\u9645\u53EF\u89C1\u5185\u5BB9\u3002\n * - string\uFF1A\u53BB\u6389\u7A7A\u767D\u540E\u975E\u7A7A\u5373\u6709\u5185\u5BB9\n * - SerializedEditorState\uFF1A\u68C0\u67E5 root.children \u5185\u662F\u5426\u5B58\u5728\u975E\u7A7A\u6587\u672C\u8282\u70B9\uFF0C\n * \u907F\u514D convertLexicalToHTML \u628A\u7A7A\u6587\u6863\u8F93\u51FA\u4E3A <div class=\"payload-richtext\"></div>\n */\nfunction hasVisibleContent(content: string | { root?: { children?: unknown[] } } | null | undefined): boolean {\n if (!content) return false\n if (typeof content === 'string') return content.trim().length > 0\n const children = content?.root?.children\n if (!Array.isArray(children) || children.length === 0) return false\n return children.some((node: any) => {\n const nodeChildren = node?.children\n if (!Array.isArray(nodeChildren) || nodeChildren.length === 0) return false\n return nodeChildren.some((child: any) => typeof child?.text === 'string' && child.text.length > 0)\n })\n}\n\n/**\n * \u6807\u9898\u6837\u5F0F\u53D8\u4F53\n */\nconst titleHeadingVariants = cva('', {\n variants: {\n theme: {\n light: 'text-[#080A0F]',\n dark: 'text-[#F5F6F7]',\n },\n },\n defaultVariants: {\n theme: 'light',\n },\n})\n\n/**\n * \u526F\u6807\u9898\u6837\u5F0F\u53D8\u4F53\n */\nconst subtitleVariants = cva(\n 'desktop:text-base desktop:mt-2 lg-desktop:text-[18px] mt-1 text-[14px] font-bold leading-[1.4] tracking-[-0.36px]',\n {\n variants: {\n theme: {\n light: 'text-[#080A0F]',\n dark: 'text-[#F5F6F7]',\n },\n },\n defaultVariants: {\n theme: 'light',\n },\n }\n)\n\nconst TitleButton = ({\n data,\n onClick,\n className,\n}: {\n data: TitleProps['data']\n onClick?: () => void\n className?: string\n}) => {\n const { theme = 'light', extensions, title, caption, align } = data\n if (!extensions?.textLink) return null\n\n const href = extensions?.link ? trackUrlRef(extensions.link, `${componentType}_${componentName}`) : undefined\n\n return (\n <a\n className={cn(\n { 'aiui-dark': theme === 'dark' },\n 'hover:text-brand-0 [&_svg_path]:hover:fill-brand-0 lg-desktop:text-base flex cursor-pointer items-center overflow-hidden text-sm font-[700] leading-[1.4] transition-all duration-[0.4s]',\n { 'text-[#080A0F]': theme === 'light' },\n { 'text-[#F5F6F7]': theme === 'dark' },\n { 'justify-center mt-4': align === 'center' },\n { 'mt-1 laptop:mt-0': align === 'left' },\n className\n )}\n {...(href ? { href } : {})}\n data-headless-type-name={`${componentType}#${componentName}`}\n data-headless-title-desc-button={`${title}#${caption}`}\n {...(onClick ? { onClick } : {})}\n >\n <div className=\"truncate whitespace-nowrap\">{extensions?.textLink}</div>\n <div className=\"lg-desktop:size-5 size-4\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"100%\" height=\"100%\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n d=\"M5.52827 3.52864C5.78862 3.26829 6.21063 3.26829 6.47098 3.52864L10.471 7.52864C10.7313 7.78899 10.7313 8.21099 10.471 8.47134L6.47098 12.4713C6.21063 12.7317 5.78862 12.7317 5.52827 12.4713C5.26792 12.211 5.26792 11.789 5.52827 11.5286L9.05692 7.99999L5.52827 4.47134C5.26792 4.21099 5.26792 3.78899 5.52827 3.52864Z\"\n fill={theme === 'dark' ? '#F5F6F7' : '#080A0F'}\n className=\"transition-all duration-[0.4s]\"\n />\n </svg>\n </div>\n </a>\n )\n}\n\nconst Title = React.forwardRef<HTMLDivElement, TitleProps>(\n ({ data, className, classNames, as = 'h2', weight = 'bold', onButtonClick, ...rest }, ref) => {\n const {\n title,\n titleSize = 4,\n caption,\n subtitle,\n content,\n countdown,\n showCountdown = false,\n theme = 'light',\n extensions,\n align = 'left',\n } = data\n const innerRef = useRef<HTMLDivElement>(null)\n const titleRef = useRef<HTMLHeadingElement>(null)\n const splitTextInstance = useRef<SplitText | null>(null)\n const scrollTriggerRef = useRef<ScrollTrigger | null>(null)\n\n // \u63A7\u5236\u5012\u8BA1\u65F6\u663E\u793A\u72B6\u6001\n const [isCountdownVisible, setIsCountdownVisible] = useState(true)\n\n const { ref: inViewRef, inView } = useInView()\n\n useImperativeHandle(ref, () => innerRef.current as HTMLDivElement)\n\n // \u5012\u8BA1\u65F6\u7ED3\u675F\u56DE\u8C03\n const handleCountdownEnd = () => {\n setIsCountdownVisible(false)\n }\n\n // CMS field mapping: new targetDateTime > legacy targetDate\n const countdownEndDate = countdown?.targetDateTime || countdown?.targetDate || ''\n const countdownTz = countdown?.targetDateTime_tz\n // Label mapping: plural keys (Title CMS format) \u2192 atomic Countdown format\n const countdownLabels = countdown?.labels\n ? {\n day: countdown.labels.days || 'Day',\n hour: countdown.labels.hours || 'Hours',\n minute: countdown.labels.minutes || 'Mins',\n second: countdown.labels.seconds || 'Secs',\n }\n : undefined\n\n useEffect(() => {\n gsap.registerPlugin(SplitText, ScrollTrigger)\n function gsapResize() {\n if (!titleRef.current) return\n const height = titleRef.current?.clientHeight || 80\n if (splitTextInstance.current) {\n splitTextInstance.current.revert()\n }\n if (scrollTriggerRef.current) {\n scrollTriggerRef.current.kill()\n }\n splitTextInstance.current = new SplitText(titleRef.current, {\n type: 'words',\n wordsClass: 'word',\n })\n const words = splitTextInstance.current.words\n gsap.set(words, { opacity: 0 })\n scrollTriggerRef.current = ScrollTrigger.create({\n trigger: titleRef.current,\n start: 'bottom bottom-=4%',\n end: `bottom+=${height * 1.5 + 60}px bottom-=4%`,\n scrub: true,\n invalidateOnRefresh: true,\n onUpdate: (self: any) => {\n const progress = self.progress\n const total = words.length || 1\n const overlap = 0.5\n const interval = 1 / total\n const step = interval * (1 - overlap)\n const lastEnd = (total - 1) * step + interval\n const normalizedProgress = Math.min(1, lastEnd > 0 ? progress / lastEnd : 0)\n words.forEach((word: any, i: number) => {\n const start = i * step\n const width = interval\n let opacity = (normalizedProgress - start) / width\n opacity = Math.max(0, Math.min(1, opacity))\n gsap.set(word, { opacity })\n })\n },\n })\n }\n\n if (inView) {\n gsapResize()\n }\n\n return () => {\n splitTextInstance.current && splitTextInstance.current.revert()\n // ScrollTrigger.getAll().forEach((t: { kill: () => any }) => t.kill())\n scrollTriggerRef.current && scrollTriggerRef.current.kill()\n }\n }, [inView])\n\n return (\n <div\n {...rest}\n id={extensions?.id}\n className={cn(\n 'titleBottom title-box flex items-end justify-between gap-2 pb-6',\n className,\n classNames?.wrapper\n )}\n ref={innerRef}\n >\n <div\n ref={inViewRef}\n className={cn('flex-1', classNames?.container, {\n 'aiui-dark': theme === 'dark',\n 'text-center': align === 'center',\n 'text-left': align === 'left',\n })}\n >\n {(caption || title) && (\n <Heading\n ref={titleRef}\n as={as}\n size={titleSize as HeadingProps['size']}\n html={caption || title}\n weight={weight}\n className={cn(titleHeadingVariants({ theme }), classNames?.title)}\n />\n )}\n {subtitle && (\n <Text html={subtitle} as=\"p\" className={cn(subtitleVariants({ theme }), classNames?.subtitle)} />\n )}\n {hasVisibleContent(content) && (\n <Text\n html={content}\n as=\"div\"\n size={4}\n className={cn(\n 'title-content text-info-primary desktop:text-base desktop:mt-4 lg-desktop:text-[18px] mt-2 text-[14px] leading-[1.6]',\n classNames?.content\n )}\n />\n )}\n <TitleButton\n data={data}\n className={cn({ 'laptop:hidden': align === 'left' }, classNames?.button)}\n onClick={onButtonClick}\n />\n {showCountdown && countdown && isCountdownVisible && (\n <Countdown\n endDate={countdownEndDate}\n endDate_tz={countdownTz}\n timeLabels={countdownLabels}\n showDays={countdown?.showDays}\n showHours={countdown?.showHours}\n showMinutes={countdown?.showMinutes}\n showSeconds={countdown?.showSeconds}\n theme={theme}\n onExpire={handleCountdownEnd}\n hideWhenExpired={true}\n align={align === 'center' ? 'center' : 'left'}\n className={cn('mt-4', classNames?.countdown)}\n />\n )}\n </div>\n <TitleButton\n data={data}\n className={cn('hidden', { ['laptop:flex']: align === 'left' }, classNames?.button)}\n onClick={onButtonClick}\n />\n </div>\n )\n }\n)\n\nTitle.displayName = 'Title'\n\nexport default withLayout(Title)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Title_exports", "__export", "Title_default", "__toCommonJS", "import_jsx_runtime", "import_react", "import_gsap", "import_SplitText", "import_ScrollTrigger", "import_utils", "import_class_variance_authority", "import_components", "import_Styles", "import_trackUrlRef", "import_react_intersection_observer", "componentType", "componentName", "hasVisibleContent", "content", "children", "node", "nodeChildren", "child", "titleHeadingVariants", "subtitleVariants", "TitleButton", "data", "onClick", "className", "theme", "extensions", "title", "caption", "align", "href", "Title", "React", "classNames", "as", "weight", "onButtonClick", "rest", "ref", "titleSize", "subtitle", "countdown", "showCountdown", "innerRef", "titleRef", "splitTextInstance", "scrollTriggerRef", "isCountdownVisible", "setIsCountdownVisible", "inViewRef", "inView", "handleCountdownEnd", "countdownEndDate", "countdownTz", "countdownLabels", "gsapResize", "height", "words", "self", "progress", "total", "overlap", "interval", "step", "lastEnd", "normalizedProgress", "word", "i", "start", "width", "opacity"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{jsx as o,jsxs as y}from"react/jsx-runtime";import*as n from"react";import{cn as m}from"../../helpers/index.js";import{Text as C,Picture as E,Button as
|
|
1
|
+
"use client";import{jsx as o,jsxs as y}from"react/jsx-runtime";import*as n from"react";import{cn as m}from"../../helpers/index.js";import{Text as C,Picture as E,Button as ot,Container as nt,Heading as at}from"../../components/index.js";import{cva as T}from"class-variance-authority";import{Swiper as st,SwiperSlide as rt}from"swiper/react";import{withLayout as it}from"../../shared/Styles.js";import{formatVariantPrice as lt}from"../Listing/utils/index.js";import{useAiuiContext as ut}from"../AiuiProvider/index.js";import{replaceTemplate as L}from"../Listing/utils/textFormat.js";const ct=T("desktop:px-6 rounded-card relative min-w-0 overflow-hidden p-4",{variants:{state:{light:"bg-[#EAEAEC]",dark:"bg-[#1E2024]"}},defaultVariants:{state:"light"}}),dt=T("",{variants:{layout:{vertical:"",horizontal:"desktop:flex desktop:flex-row desktop:items-stretch desktop:gap-10"}},defaultVariants:{layout:"vertical"}}),ft=T("desktop:max-w-[268px] lg-desktop:max-w-[356px] lg-desktop:h-[171px] relative mx-auto h-[118px] max-w-[256px] ",{variants:{layout:{vertical:"",horizontal:"desktop:flex-1 desktop:h-[122px] lg-desktop:h-[161px]"}},defaultVariants:{layout:"vertical"}}),pt=T("mt-3",{variants:{layout:{vertical:"",horizontal:"desktop:mt-0 desktop:flex-1 desktop:flex desktop:flex-col desktop:justify-center"}},defaultVariants:{layout:"vertical"}}),mt=T("mt-4 self-start",{variants:{state:{light:"bg-[#080A0F] text-white",dark:"bg-white text-[#080A0F]"}},defaultVariants:{state:"light"}}),M=T("",{variants:{state:{light:"text-[#080A0F]",dark:"text-white"}},defaultVariants:{state:"light"}}),U=t=>{if(!t)return;const e=[];return t.lgDesktop?.url&&e.push(`${t.lgDesktop.url} 1920`),t.desktop?.url&&e.push(`${t.desktop.url} 1439`),t.laptop?.url&&e.push(`${t.laptop.url} 1024`),t.tablet?.url&&e.push(`${t.tablet.url} 767`),t.default?.url&&e.push(t.default.url),e.length>0?e.join(", "):void 0},q=t=>t&&(t.default?.alt||t.tablet?.alt||t.laptop?.alt||t.desktop?.alt||t.lgDesktop?.alt)||"",ht=t=>{const e=Math.floor(t/3600),a=Math.floor(t%3600/60),i=t%60;return`${e.toString().padStart(2,"0")}:${a.toString().padStart(2,"0")}:${i.toString().padStart(2,"0")}`},j=t=>{if(typeof t=="number")return t;const e=new Date(t).getTime();return isNaN(e)?0:e},O=t=>{if(!t)return!1;const e=j(t.startTime),a=(t.durationDays??1)*24*3600*1e3,i=t.rounds??1,d=Date.now();if(d<e)return!1;const h=d-e,u=Math.floor(h/a)+1;if(u>i)return!1;const f=e+u*a-d,s=5*60*1e3;return f<=s&&f>0},H=(t,e)=>{if(!t||!e)return t||"";const a=j(e.startTime),i=(e.durationDays??1)*24*3600*1e3,d=e.rounds??1,h=Date.now();if(h<a){const g=new Date(a),l=`${(g.getUTCMonth()+1).toString().padStart(2,"0")}${g.getUTCDate().toString().padStart(2,"0")}`;return`${t}${l}`}const u=h-a,w=Math.min(Math.floor(u/i)+1,d),f=a+(w-1)*i,s=new Date(f),p=`${(s.getUTCMonth()+1).toString().padStart(2,"0")}${s.getUTCDate().toString().padStart(2,"0")}`;return`${t}${p}`},W=n.memo(({config:t,theme:e="light",className:a,countdownText:i="Next round start time",lastRoundText:d="Last round",beforeStartText:h="Start time",countdownIcon:u,onStateChange:w})=>{const[f,s]=n.useState(0),[p,g]=n.useState("beforeStart"),l=n.useMemo(()=>j(t.startTime),[t.startTime]),S=t.rounds??1,N=(t.durationDays??1)*24*3600*1e3;n.useEffect(()=>{const P=()=>{const x=Date.now();if(x<l){const G=Math.max(0,Math.floor((l-x)/1e3));s(G),g("beforeStart");return}const R=x-l,b=Math.floor(R/N)+1;if(b>S){g("finished");return}const D=l+b*N,r=Math.max(0,Math.floor((D-x)/1e3));s(r),g(b===S?"lastRound":"running")};P();const A=setInterval(P,1e3);return()=>clearInterval(A)},[l,N,S]),n.useEffect(()=>{w?.(p)},[p,w]);const V=n.useMemo(()=>{switch(p){case"beforeStart":return h;case"lastRound":return d;default:return i}},[p,h,d,i]);return p==="finished"?null:y("div",{className:m("desktop:gap-2 laptop:text-base flex items-center gap-1 text-sm",e==="dark"?"text-white":"text-[#080A0F]",a),children:[u&&o(E,{source:u.url,alt:u.alt,className:"laptop:size-5 size-4 shrink-0",imgClassName:"size-full object-contain"}),o(C,{html:V,className:"whitespace-nowrap font-bold"}),o("span",{className:"font-bold",children:"|"}),o(C,{className:"font-bold",html:ht(f)})]})});W.displayName="Countdown";const J=n.memo(({progress:t,theme:e="light",className:a})=>{const i=Math.min(100,Math.max(0,t));return o("div",{className:m("flex h-2 w-full items-stretch overflow-hidden rounded-full",e==="dark"?"bg-white/20":"bg-black/20",a),role:"progressbar","aria-valuenow":i,"aria-valuemin":0,"aria-valuemax":100,children:o("div",{className:m("h-full rounded-full transition-all duration-300",e==="dark"?"bg-white":"bg-[#080A0F]"),style:{width:`${i}%`}})})});J.displayName="ProgressBar";const K=n.memo(({item:t,theme:e="light",layout:a="vertical",className:i,buttonClassName:d,countdownClassName:h,onButtonClick:u,onProductImageClick:w,buildData:f,buttonText:s,remainText:p,lowStockText:g,soldOutButtonText:l,discountText:S="Only {price}",countdownText:N,countdownIcon:V,lastRoundText:P,beforeStartText:A,comingSoonButtonText:x,loading:R})=>{const{locale:b="us",currencyCode:D}=ut(),r=t.products?.[0],[G,X]=n.useState(()=>O(t.countdown)),[I,Y]=n.useState(()=>H(t.codePrefix,t.countdown)),[$,Z]=n.useState("beforeStart");n.useEffect(()=>{const v=()=>{X(O(t.countdown));const F=H(t.codePrefix,t.countdown);Y(_=>_!==F?F:_)};v();const z=setInterval(v,1e3);return()=>clearInterval(z)},[t.codePrefix,t.countdown]);const tt=n.useCallback(v=>{Z(v)},[]),B=n.useMemo(()=>!r?.handle||!f?.products?.length?null:f.products.find(v=>v.handle===r.handle)||null,[r?.handle,f?.products]),c=n.useMemo(()=>B?.variants?.find(v=>v?.sku===r?.sku)||{},[r?.sku,B?.variants]),k=n.useMemo(()=>{const{price:v,basePrice:z}=lt({locale:D==="CAD"?"us":b||"us",baseAmount:c?.price?.amount,amount:r?.custom_price??c?.price?.amount,currencyCode:B?.price?.currencyCode||"USD"});return{value:z,description:r?.custom_description,salePrice:L(S||"",{price:v})}},[B,c,b,S,r?.custom_price,r?.custom_description]),et=n.useCallback(()=>{u?.({product:r,code:I})},[u,I,r]);return y("div",{className:m(ct({state:e}),i),"data-ui-component-id":"GiftShelfCard",children:[t.countdown&&o("div",{className:"laptop:h-[24px] mb-4 h-[20px]",children:o(W,{config:t.countdown,theme:e,className:h,countdownText:N,lastRoundText:P,beforeStartText:A,countdownIcon:V,onStateChange:tt})}),y("div",{className:dt({layout:a}),children:[y("div",{className:ft({layout:a}),children:[t.backgroundImage&&(w?o("a",{onClick:()=>r&&w(r),className:"cursor-pointer",children:o(E,{source:U(t.backgroundImage),alt:q(t.backgroundImage),className:"rounded-card size-full overflow-hidden object-cover",imgClassName:"h-full w-full object-cover"})}):o(E,{source:U(t.backgroundImage),alt:q(t.backgroundImage),className:"rounded-card size-full overflow-hidden object-cover",imgClassName:"h-full w-full object-cover"})),o("div",{className:"absolute top-1/2 z-10 w-full -translate-y-1/2 px-6",children:y("div",{className:"flex flex-col gap-1",children:[k.value&&o(at,{html:k.value,size:4,className:m("font-bold leading-none",M({state:e}))}),k.description&&o(C,{html:k.description,className:m("text-base font-bold opacity-60",M({state:e}))})]})})]}),y("div",{className:pt({layout:a}),children:[k.salePrice&&o(C,{as:"p",html:k.salePrice,className:m("lg-desktop:text-2xl text-xl font-bold",M({state:e}))}),o(J,{progress:r?.custom_inventory?(c?.quantityAvailable||0)/r.custom_inventory*100:0,theme:e,className:m("mb-1 mt-2",c?.availableForSale&&(c?.quantityAvailable??0)<=0&&"invisible")}),p&&(c?.quantityAvailable??0)>=0&&o(C,{html:L(p,{inventory:r?.custom_inventory?.toString()||"",quantity:c?.quantityAvailable?.toString()||"0"}),as:"p",className:m("laptop:text-base text-sm font-bold",M({state:e}))}),g&&c?.availableForSale&&(c?.quantityAvailable??0)<0&&o(C,{html:g,as:"p",className:m("laptop:text-base text-sm font-bold text-red-500",M({state:e}))}),o(ot,{size:"lg",className:m(mt({state:e}),d),onClick:et,disabled:!c?.availableForSale||R||G||$==="beforeStart"||$==="finished",loading:R&&c?.availableForSale,children:$==="beforeStart"?x||s:c?.availableForSale?s:l||s})]})]})]})});K.displayName="GiftShelfCard";const Q=n.forwardRef(({classNames:t={},data:e,onButtonClick:a,onProductImageClick:i,buildData:d,loading:h,...u},w)=>{const f=e.theme||"light",s=n.useMemo(()=>e?.items?.length||4,[e?.items]),p=s===2?"horizontal":"vertical",g=n.useMemo(()=>{const l=S=>{switch(S){case"mobile":return{slidesPerView:1.2,spaceBetween:12};case"tablet":return s<=2?{slidesPerView:2,spaceBetween:12}:{slidesPerView:2.5,spaceBetween:12};case"laptop":return s<=3?{slidesPerView:s,spaceBetween:16}:{slidesPerView:3.01,spaceBetween:16};case"desktop":return{slidesPerView:Math.min(s,4),spaceBetween:20}}};return{0:l("mobile"),768:l("tablet"),1025:l("laptop"),1440:l("desktop")}},[s]);return o(nt,{ref:w,className:m(t?.root),childClassName:"overflow-hidden","data-ui-component-id":"GiftShelf",...u,children:o(st,{breakpoints:g,className:"w-full !overflow-visible",children:e.items.map((l,S)=>o(rt,{children:o(K,{item:l,theme:f,layout:p,className:t?.card,buttonClassName:t?.button,countdownClassName:t?.countdown,onButtonClick:a,onProductImageClick:i,buildData:d,buttonText:e.buttonText,discountText:e.discountText,remainText:e.remainText,lowStockText:e.lowStockText,soldOutButtonText:e.soldOutButtonText,countdownText:e.countdownText,lastRoundText:e.lastRoundText,countdownIcon:e?.countdownIcon,beforeStartText:e.beforeStartText,comingSoonButtonText:e.comingSoonButtonText,loading:h})},"giftShelfCardItem"+S))})})});Q.displayName="GiftShelf";var Tt=it(Q);export{Tt as default};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|