@anker-in/headless-ui 1.3.55 → 1.3.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/cjs/biz-components/ActiveShelf/ProductCard.js +1 -1
  2. package/dist/cjs/biz-components/ActiveShelf/ProductCard.js.map +2 -2
  3. package/dist/cjs/biz-components/BuyOneGetOneShelf/PriceAndActions.js +1 -1
  4. package/dist/cjs/biz-components/BuyOneGetOneShelf/PriceAndActions.js.map +2 -2
  5. package/dist/cjs/biz-components/CreditsShelf/ProductCard.js +1 -1
  6. package/dist/cjs/biz-components/CreditsShelf/ProductCard.js.map +2 -2
  7. package/dist/cjs/biz-components/ImageOverlayShelf/ProductCard.js +1 -1
  8. package/dist/cjs/biz-components/ImageOverlayShelf/ProductCard.js.map +2 -2
  9. package/dist/cjs/biz-components/Marquee/Marquee.js +1 -1
  10. package/dist/cjs/biz-components/Marquee/Marquee.js.map +2 -2
  11. package/dist/cjs/biz-components/Marquee/type.d.ts +1 -0
  12. package/dist/cjs/biz-components/Marquee/type.js +1 -1
  13. package/dist/cjs/biz-components/Marquee/type.js.map +1 -1
  14. package/dist/cjs/biz-components/MediaShelf/ProductCard.js +1 -1
  15. package/dist/cjs/biz-components/MediaShelf/ProductCard.js.map +2 -2
  16. package/dist/cjs/biz-components/SceneShelf/ProductsPanel.js +1 -1
  17. package/dist/cjs/biz-components/SceneShelf/ProductsPanel.js.map +2 -2
  18. package/dist/cjs/biz-components/SceneShelfV2/index.js +1 -1
  19. package/dist/cjs/biz-components/SceneShelfV2/index.js.map +2 -2
  20. package/dist/cjs/biz-components/SceneShelfV3/ProductCard.js +1 -1
  21. package/dist/cjs/biz-components/SceneShelfV3/ProductCard.js.map +2 -2
  22. package/dist/esm/biz-components/ActiveShelf/ProductCard.js +1 -1
  23. package/dist/esm/biz-components/ActiveShelf/ProductCard.js.map +2 -2
  24. package/dist/esm/biz-components/BuyOneGetOneShelf/PriceAndActions.js +1 -1
  25. package/dist/esm/biz-components/BuyOneGetOneShelf/PriceAndActions.js.map +2 -2
  26. package/dist/esm/biz-components/CreditsShelf/ProductCard.js +1 -1
  27. package/dist/esm/biz-components/CreditsShelf/ProductCard.js.map +2 -2
  28. package/dist/esm/biz-components/ImageOverlayShelf/ProductCard.js +1 -1
  29. package/dist/esm/biz-components/ImageOverlayShelf/ProductCard.js.map +2 -2
  30. package/dist/esm/biz-components/Marquee/Marquee.js +1 -1
  31. package/dist/esm/biz-components/Marquee/Marquee.js.map +2 -2
  32. package/dist/esm/biz-components/Marquee/type.d.ts +1 -0
  33. package/dist/esm/biz-components/MediaShelf/ProductCard.js +1 -1
  34. package/dist/esm/biz-components/MediaShelf/ProductCard.js.map +2 -2
  35. package/dist/esm/biz-components/SceneShelf/ProductsPanel.js +1 -1
  36. package/dist/esm/biz-components/SceneShelf/ProductsPanel.js.map +2 -2
  37. package/dist/esm/biz-components/SceneShelfV2/index.js +1 -1
  38. package/dist/esm/biz-components/SceneShelfV2/index.js.map +2 -2
  39. package/dist/esm/biz-components/SceneShelfV3/ProductCard.js +1 -1
  40. package/dist/esm/biz-components/SceneShelfV3/ProductCard.js.map +2 -2
  41. package/package.json +1 -1
  42. package/style.css +18 -6
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/biz-components/Marquee/Marquee.tsx"],
4
- "sourcesContent": ["'use client'\nimport React, { useRef, useImperativeHandle, useLayoutEffect, useState, type RefObject } from 'react'\nimport { Picture, Text } from '../../components/index.js'\nimport { cn } from '../../helpers/utils.js'\nimport { withLayout } from '../../shared/Styles.js'\nimport type {\n MarqueeProps,\n MarqueeItemProps,\n MarqueeImageContentProps,\n MarqueeTextContentProps,\n MarqueeIconAndTextContentProps,\n MarqueePictureContentProps,\n} from './type.js'\n\nimport 'swiper/css'\n\nimport { useExposure } from '../../hooks/useExposure.js'\n\nconst componentType = 'image'\nconst componentName = 'marquee'\n\nconst Marquee = React.forwardRef<HTMLDivElement, MarqueeProps>(\n ({ data: { items = [], speed = 3000, reverseDirection = false, key: dataKey } = {}, className }, ref) => {\n const innerRef = useRef<HTMLDivElement>(null)\n const trackRef = useRef<HTMLDivElement>(null)\n\n useImperativeHandle(ref, () => innerRef.current as HTMLDivElement)\n\n useExposure(innerRef as unknown as RefObject<HTMLDivElement>, {\n componentType,\n componentName,\n })\n\n const duration = `${speed * 5}ms`\n const gap = 'clamp(24px, 4vw, 64px)'\n\n const [copies, setCopies] = useState(2)\n\n useLayoutEffect(() => {\n const track = trackRef.current\n if (!track) return\n\n const calcCopies = () => {\n const trackWidth = track.offsetWidth\n if (trackWidth === 0) return\n const viewportWidth = window.innerWidth\n const minCopies = Math.ceil(viewportWidth / trackWidth)\n setCopies(Math.max(2, minCopies))\n }\n\n calcCopies()\n innerRef.current?.style.setProperty('--track-width', `${track.offsetWidth}px`)\n\n const ro = new ResizeObserver(() => {\n calcCopies()\n innerRef.current?.style.setProperty('--track-width', `${track.offsetWidth}px`)\n })\n ro.observe(track)\n return () => ro.disconnect()\n }, [items])\n\n return (\n <div\n ref={innerRef}\n id={dataKey ? `Marquee-${dataKey}` : undefined}\n className={cn('text-info-primary w-full', className)}\n >\n <div\n className={cn(\n 'flex h-full w-max items-center',\n reverseDirection ? 'animate-marquee-reverse' : 'animate-marquee'\n )}\n style={{ '--marquee-duration': duration } as React.CSSProperties}\n >\n {/* \u539F\u59CB\u8F68\u9053\uFF1A\u7528 ref \u6D4B\u91CF\u771F\u5B9E\u5BBD\u5EA6 */}\n <div ref={trackRef} className=\"flex h-full shrink-0 items-center\" style={{ gap, paddingRight: gap }}>\n {items.map((item, index) => (\n <div key={(item?.id ?? '') + '-orig-' + index} className=\"shrink-0\">\n <MarqueeItem data={item} />\n </div>\n ))}\n </div>\n\n {Array.from({ length: copies }).map((_, copyIndex) => (\n <div\n key={`copy-group-${copyIndex}`}\n className=\"flex h-full shrink-0 items-center\"\n style={{ gap, paddingRight: gap }}\n aria-hidden=\"true\"\n >\n {items.map((item, index) => (\n <div key={(item?.id ?? '') + '-copy-' + copyIndex + '-' + index} className=\"shrink-0\">\n <MarqueeItem data={item} />\n </div>\n ))}\n </div>\n ))}\n </div>\n </div>\n )\n }\n)\n\nMarquee.displayName = 'Marquee'\n\n// \u2500\u2500\u2500 Sub-components \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 MarqueeItem = ({ data, configuration }: MarqueeItemProps) => {\n return (\n <>\n {data.type === 'image' && (\n <MarqueeImageContent image={data?.image} imageClassName={configuration?.imageClassName} />\n )}\n {data.type === 'text' && <MarqueeTextContent text={data?.text} textClassName={configuration?.textClassName} />}\n {data.type === 'iconAndText' && (\n <MarqueeIconAndTextContent\n icon={data?.iconImage}\n text={data?.iconText}\n iconClassName={configuration?.iconClassName}\n textClassName={configuration?.textClassName}\n />\n )}\n {data.type === 'picture' && (\n <MarqueePictureContent pictureImage={data?.pictureImage} pictureClassName={configuration?.pictureClassName} />\n )}\n </>\n )\n}\n\nMarqueeItem.displayName = 'MarqueeItem'\n\nconst MarqueeImageContent = ({ image, imageClassName }: MarqueeImageContentProps) => {\n return (\n <div className=\"laptop:w-[120px] h-full w-[72px] shrink-0\">\n <Picture source={image?.url} alt={image?.alt || ''} imgClassName={cn('object-cover', imageClassName)} />\n </div>\n )\n}\n\nMarqueeImageContent.displayName = 'MarqueeImageContent'\n\nconst MarqueeTextContent = React.forwardRef<HTMLDivElement, MarqueeTextContentProps>(({ text, textClassName }, ref) => {\n return (\n <Text\n as=\"div\"\n ref={ref}\n html={text}\n className={cn('text-lines-2 flex size-full items-center justify-center font-bold leading-[1.2]', textClassName)}\n />\n )\n})\n\nMarqueeTextContent.displayName = 'MarqueeTextContent'\n\nconst MarqueeIconAndTextContent = ({ icon, text, iconClassName, textClassName }: MarqueeIconAndTextContentProps) => {\n return (\n <div className=\"laptop:h-[72px] laptop:gap-2 flex h-[48px] items-center gap-1\">\n {icon && (\n <img\n src={icon?.url}\n alt={icon?.alt || ''}\n className={cn('desktop:size-6 size-5 shrink-0 object-contain', iconClassName)}\n />\n )}\n {text && (\n <Text\n as=\"div\"\n html={text}\n className={cn(\n 'laptop:text-[16px] lg-desktop::text-[18px] flex h-full items-center text-[14px] ',\n textClassName\n )}\n />\n )}\n </div>\n )\n}\n\nMarqueeIconAndTextContent.displayName = 'MarqueeIconAndTextContent'\n\nconst MarqueePictureContent = ({ pictureImage, pictureClassName }: MarqueePictureContentProps) => {\n return (\n <div className=\"lg-desktop:size-[128px] desktop:size-[112px] laptop:size-[96px] tablet:size-[72px] size-[72px] shrink-0\">\n <Picture\n source={pictureImage?.url}\n alt={pictureImage?.alt || ''}\n className=\"w-full\"\n imgClassName={cn('object-contain', pictureClassName)}\n />\n </div>\n )\n}\n\nMarqueePictureContent.displayName = 'MarqueePictureContent'\n\nexport default withLayout(Marquee)\nexport { MarqueeItem, MarqueeImageContent, MarqueeTextContent, MarqueeIconAndTextContent, MarqueePictureContent }\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["'use client'\nimport React, { useRef, useImperativeHandle, useLayoutEffect, useState, type RefObject } from 'react'\nimport { Picture, Text } from '../../components/index.js'\nimport { cn } from '../../helpers/utils.js'\nimport { withLayout } from '../../shared/Styles.js'\nimport type {\n MarqueeProps,\n MarqueeItemProps,\n MarqueeImageContentProps,\n MarqueeTextContentProps,\n MarqueeIconAndTextContentProps,\n MarqueePictureContentProps,\n} from './type.js'\n\nimport 'swiper/css'\n\nimport { useExposure } from '../../hooks/useExposure.js'\n\nconst componentType = 'image'\nconst componentName = 'marquee'\n\nconst Marquee = React.forwardRef<HTMLDivElement, MarqueeProps>(\n ({ data: { items = [], speed = 3000, reverseDirection = false, key: dataKey } = {}, className }, ref) => {\n const innerRef = useRef<HTMLDivElement>(null)\n const trackRef = useRef<HTMLDivElement>(null)\n\n useImperativeHandle(ref, () => innerRef.current as HTMLDivElement)\n\n useExposure(innerRef as unknown as RefObject<HTMLDivElement>, {\n componentType,\n componentName,\n })\n\n const duration = `${speed * 5}ms`\n const gap = 'clamp(24px, 4vw, 64px)'\n\n const [copies, setCopies] = useState(2)\n\n useLayoutEffect(() => {\n const track = trackRef.current\n if (!track) return\n\n const calcCopies = () => {\n const trackWidth = track.offsetWidth\n if (trackWidth === 0) return\n const viewportWidth = window.innerWidth\n const minCopies = Math.ceil(viewportWidth / trackWidth)\n setCopies(Math.max(2, minCopies))\n }\n\n calcCopies()\n innerRef.current?.style.setProperty('--track-width', `${track.offsetWidth}px`)\n\n const ro = new ResizeObserver(() => {\n calcCopies()\n innerRef.current?.style.setProperty('--track-width', `${track.offsetWidth}px`)\n })\n ro.observe(track)\n return () => ro.disconnect()\n }, [items])\n\n return (\n <div\n ref={innerRef}\n id={dataKey ? `Marquee-${dataKey}` : undefined}\n className={cn('text-info-primary w-full', className)}\n >\n <div\n className={cn(\n 'flex h-full w-max items-center',\n reverseDirection ? 'animate-marquee-reverse' : 'animate-marquee'\n )}\n style={{ '--marquee-duration': duration } as React.CSSProperties}\n >\n {/* \u539F\u59CB\u8F68\u9053\uFF1A\u7528 ref \u6D4B\u91CF\u771F\u5B9E\u5BBD\u5EA6 */}\n <div ref={trackRef} className=\"flex h-full shrink-0 items-center\" style={{ gap, paddingRight: gap }}>\n {items.map((item, index) => (\n <div key={(item?.id ?? '') + '-orig-' + index} className=\"shrink-0\">\n <MarqueeItem data={item} />\n </div>\n ))}\n </div>\n\n {Array.from({ length: copies }).map((_, copyIndex) => (\n <div\n key={`copy-group-${copyIndex}`}\n className=\"flex h-full shrink-0 items-center\"\n style={{ gap, paddingRight: gap }}\n aria-hidden=\"true\"\n >\n {items.map((item, index) => (\n <div key={(item?.id ?? '') + '-copy-' + copyIndex + '-' + index} className=\"shrink-0\">\n <MarqueeItem data={item} />\n </div>\n ))}\n </div>\n ))}\n </div>\n </div>\n )\n }\n)\n\nMarquee.displayName = 'Marquee'\n\n// \u2500\u2500\u2500 Sub-components \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 MarqueeItem = ({ data, configuration }: MarqueeItemProps) => {\n return (\n <>\n {data.type === 'image' && (\n <MarqueeImageContent image={data?.image} imageClassName={configuration?.imageClassName} />\n )}\n {data.type === 'text' && (\n <MarqueeTextContent text={data?.text ?? data?.textContent} textClassName={configuration?.textClassName} />\n )}\n {data.type === 'iconAndText' && (\n <MarqueeIconAndTextContent\n icon={data?.iconImage}\n text={data?.iconText}\n iconClassName={configuration?.iconClassName}\n textClassName={configuration?.textClassName}\n />\n )}\n {data.type === 'picture' && (\n <MarqueePictureContent pictureImage={data?.pictureImage} pictureClassName={configuration?.pictureClassName} />\n )}\n </>\n )\n}\n\nMarqueeItem.displayName = 'MarqueeItem'\n\nconst MarqueeImageContent = ({ image, imageClassName }: MarqueeImageContentProps) => {\n return (\n <div className=\"laptop:w-[120px] h-full w-[72px] shrink-0\">\n <Picture source={image?.url} alt={image?.alt || ''} imgClassName={cn('object-cover', imageClassName)} />\n </div>\n )\n}\n\nMarqueeImageContent.displayName = 'MarqueeImageContent'\n\nconst MarqueeTextContent = React.forwardRef<HTMLDivElement, MarqueeTextContentProps>(({ text, textClassName }, ref) => {\n return (\n <Text\n as=\"div\"\n ref={ref}\n html={text}\n className={cn('text-lines-2 flex size-full items-center justify-center font-bold leading-[1.2]', textClassName)}\n />\n )\n})\n\nMarqueeTextContent.displayName = 'MarqueeTextContent'\n\nconst MarqueeIconAndTextContent = ({ icon, text, iconClassName, textClassName }: MarqueeIconAndTextContentProps) => {\n return (\n <div className=\"laptop:h-[72px] laptop:gap-2 flex h-[48px] items-center gap-1\">\n {icon && (\n <img\n src={icon?.url}\n alt={icon?.alt || ''}\n className={cn('desktop:size-6 size-5 shrink-0 object-contain', iconClassName)}\n />\n )}\n {text && (\n <Text\n as=\"div\"\n html={text}\n className={cn(\n 'laptop:text-[16px] lg-desktop::text-[18px] flex h-full items-center text-[14px] ',\n textClassName\n )}\n />\n )}\n </div>\n )\n}\n\nMarqueeIconAndTextContent.displayName = 'MarqueeIconAndTextContent'\n\nconst MarqueePictureContent = ({ pictureImage, pictureClassName }: MarqueePictureContentProps) => {\n return (\n <div className=\"lg-desktop:size-[128px] desktop:size-[112px] laptop:size-[96px] tablet:size-[72px] size-[72px] shrink-0\">\n <Picture\n source={pictureImage?.url}\n alt={pictureImage?.alt || ''}\n className=\"w-full\"\n imgClassName={cn('object-contain', pictureClassName)}\n />\n </div>\n )\n}\n\nMarqueePictureContent.displayName = 'MarqueePictureContent'\n\nexport default withLayout(Marquee)\nexport { MarqueeItem, MarqueeImageContent, MarqueeTextContent, MarqueeIconAndTextContent, MarqueePictureContent }\n"],
5
+ "mappings": "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",
6
6
  "names": ["Fragment", "jsx", "jsxs", "React", "useRef", "useImperativeHandle", "useLayoutEffect", "useState", "Picture", "Text", "cn", "withLayout", "useExposure", "componentType", "componentName", "Marquee", "items", "speed", "reverseDirection", "dataKey", "className", "ref", "innerRef", "trackRef", "duration", "gap", "copies", "setCopies", "track", "calcCopies", "trackWidth", "viewportWidth", "minCopies", "ro", "item", "index", "MarqueeItem", "_", "copyIndex", "data", "configuration", "MarqueeImageContent", "MarqueeTextContent", "MarqueeIconAndTextContent", "MarqueePictureContent", "image", "imageClassName", "text", "textClassName", "icon", "iconClassName", "pictureImage", "pictureClassName", "Marquee_default"]
7
7
  }
@@ -19,6 +19,7 @@ interface MarqueeItemProps {
19
19
  type: 'image' | 'text' | 'iconAndText' | 'picture';
20
20
  image?: Img;
21
21
  text?: string;
22
+ textContent?: string;
22
23
  iconImage?: Img;
23
24
  iconText?: string;
24
25
  pictureImage?: Img;
@@ -1,2 +1,2 @@
1
- "use client";import{Fragment as O,jsx as a,jsxs as r}from"react/jsx-runtime";import*as o from"react";import{cn as t}from"../../helpers/index.js";import{Button as C,Badge as A,Card as q,CardContent as $,Picture as E,Text as y,Heading as c,Progress as H}from"../../components/index.js";const R=5;function I(e,l,d,f){if(e===void 0)return!0;switch(e){case"always":return!0;case"never":return!1;case"below-quantity":return l===void 0?!0:d<=l;case"below-percentage":return l===void 0?!0:d/f*100<=l;default:return!0}}const g=o.forwardRef(({product:e,className:l,stockDisplayMode:d,stockThresholdValue:f,onLearnMore:S,onShopNow:w,onAddToCart:P,classNames:i,secondaryButtonText:u,secondaryButtonFun:v,primaryButtonText:b,primaryButtonFun:h,showOriginalPrice:N,copy:p,onProductImageClick:s,showTags:M=!0},F)=>{const[L,B]=o.useState(!1),[D,T]=o.useState(!1),z=o.useMemo(()=>e?.availableForSale&&e?.quantityAvailable<=0?R:e?.availableForSale?(e?.quantityAvailable??0)/(e?.totalInventory??1)*100:0,[e?.availableForSale,e?.quantityAvailable,e?.totalInventory]),x=async(n,m)=>{if(!n)return;const k=m==="primary"?B:T;k(!0);try{switch(n){case"buyNow":await w?.(e);break;case"addCart":await P?.(e);break;case"learnMore":await S?.(e);break;default:break}}finally{k(!1)}},_=e.availableForSale&&e.quantityAvailable<=0;return r(q,{ref:F,className:t("tablet:min-w-[auto] hover:bg-container-secondary-0 flex h-full min-w-[296px] flex-col overflow-hidden border-none",e.custom_link?"cursor-pointer":"",l,i?.productCard),children:[r("div",{className:t("media-shelf-product-card-image-wrapper desktop:h-[240px] relative h-[200px] shrink-0 overflow-hidden",i?.productCardImageWrapper),children:[a("div",{className:t("media-shelf-product-card-image-bg absolute inset-0 ",i?.productCardImageBg),children:a("a",{onClick:()=>s?.(e),...!s&&{href:e.custom_link||e.listingLink},className:"cursor-pointer",children:a(E,{source:e.custom_image||e.image,alt:e.name,className:t("h-full",i?.productCardImage),imgClassName:"h-full object-contain"})})}),M&&e.tags&&e.tags.length>0&&a("div",{className:"lg-desktop:h-[28px] absolute left-4 top-4 flex h-[24px]",children:e.tags.map((n,m)=>n.label?a(A,{size:"sm",variant:n.variant||"outline",className:t("mr-1"),promotionalType:n.promotionalType,children:n.label},m):a(o.Fragment,{children:n},m))})]}),r($,{className:"desktop:p-6 bg-container-primary laptop:gap-6 flex h-[calc(100%-240px)] grow flex-col justify-between gap-4 p-4",children:[r("div",{className:"flex-0",children:[a(c,{as:"h3",size:2,className:t("text-info-primary mb-1 line-clamp-2 tracking-tight",s?"cursor-pointer":"",i?.productTitle),onClick:s?()=>s(e):void 0,children:e.custom_name||e.name}),(e.custom_description||e?.description)&&a(y,{size:2,className:t("text-info-primary line-clamp-1",i?.productDescription),html:e.custom_description||e.description})]}),I(d,f,e?.quantityAvailable??0,e?.totalInventory??0)&&r("div",{"data-total":e?.totalInventory??0,"data-available":e?.quantityAvailable??0,className:"space-y-2",children:[a(H,{value:z,max:100,min:0,size:"base",variant:"default","aria-label":"stock progress",classNames:{progressBar:"transition-all duration-300 ease-in-out"}}),a(y,{size:3,className:"text-info-tertiary desktop:text-[16px] lg-desktop:text-[18px] text-[12px]",children:_?p?.limitedStock:p?.stockDisplayText?.replace("{count}",`${e.availableForSale?e.quantityAvailable:0}`)})]}),r("div",{children:[a("div",{className:t("mb-2",i?.productPrice),children:a("div",{className:"flex items-baseline gap-2",children:e.availableForSale?r(O,{children:[a(c,{size:2,className:"text-info-primary",as:"h6",children:e.price}),N&&e.originalPrice&&a(c,{size:2,className:t("text-info-tertiary line-through",i?.originalPrice),as:"h6",children:e.originalPrice})]}):a(c,{size:2,className:"text-info-tertiary",children:p?.outOfStockLabel??"Sold Out"})})}),e?.priceLabel&&e?.availableForSale&&a(y,{size:4,className:t("text-marketing-1 desktop:text-[16px] lg-desktop:text-[18px] mt-2 text-[12px]",i?.productPriceLabel),children:e.priceLabel}),r("div",{className:t("lg-desktop:gap-3 tablet:flex-nowrap flex flex-wrap gap-2",i?.buttonGroup),children:[u&&a(C,{variant:"secondary",size:"base",className:t("tablet:w-fit w-full",i?.secondaryButton),onClick:()=>x(v,"secondary"),disabled:!e.availableForSale&&v!=="learnMore",loading:D,"data-headless-type-name":"MediaShelf#ProductCard","data-headless-title-desc-button":`${e.custom_name||e.name}#${e.description||""}#${u}`,"data-headless-sku":e.sku,children:u}),b&&a(C,{variant:"primary",size:"base",className:t("tablet:w-fit w-full",i?.primaryButton),onClick:()=>x(h,"primary"),disabled:!e.availableForSale&&h!=="learnMore",loading:L,"data-headless-type-name":"MediaShelf#ProductCard","data-headless-title-desc-button":`${e.custom_name||e.name}#${e.description||""}#${b}`,"data-headless-sku":e.sku,children:b})]})]})]})]})});g.displayName="MediaShelf.ProductCard";var K=g;export{g as ProductCard,K as default};
1
+ "use client";import{Fragment as O,jsx as a,jsxs as l}from"react/jsx-runtime";import*as o from"react";import{cn as t}from"../../helpers/index.js";import{Button as k,Badge as A,Card as q,CardContent as $,Picture as E,Text as y,Heading as c,Progress as H}from"../../components/index.js";const R=5;function I(e,r,d,f){if(e===void 0)return!0;switch(e){case"always":return!0;case"never":return!1;case"below-quantity":return r===void 0?!0:d<=r;case"below-percentage":return r===void 0?!0:d/f*100<=r;default:return!0}}const g=o.forwardRef(({product:e,className:r,stockDisplayMode:d,stockThresholdValue:f,onLearnMore:C,onShopNow:S,onAddToCart:P,classNames:i,secondaryButtonText:b,secondaryButtonFun:v,primaryButtonText:u,primaryButtonFun:h,showOriginalPrice:N,copy:p,onProductImageClick:s,showTags:M=!0},F)=>{const[L,B]=o.useState(!1),[D,T]=o.useState(!1),z=o.useMemo(()=>e?.availableForSale&&e?.quantityAvailable<=0?R:e?.availableForSale?(e?.quantityAvailable??0)/(e?.totalInventory??1)*100:0,[e?.availableForSale,e?.quantityAvailable,e?.totalInventory]),x=async(n,m)=>{if(!n)return;const w=m==="primary"?B:T;w(!0);try{switch(n){case"buyNow":await S?.(e);break;case"addCart":await P?.(e);break;case"learnMore":await C?.(e);break;default:break}}finally{w(!1)}},_=e.availableForSale&&e.quantityAvailable<=0;return l(q,{ref:F,className:t("tablet:min-w-[auto] hover:bg-container-secondary-0 flex h-full min-w-[296px] flex-col overflow-hidden border-none",e.custom_link?"cursor-pointer":"",r,i?.productCard),children:[l("div",{className:t("media-shelf-product-card-image-wrapper desktop:h-[240px] relative h-[200px] shrink-0 overflow-hidden",i?.productCardImageWrapper),children:[a("div",{className:t("media-shelf-product-card-image-bg absolute inset-0 ",i?.productCardImageBg),children:a("a",{onClick:()=>s?.(e),...!s&&{href:e.custom_link||e.listingLink},className:"cursor-pointer",children:a(E,{source:e.custom_image||e.image,alt:e.name,className:t("h-full",i?.productCardImage),imgClassName:"h-full object-contain"})})}),M&&e.tags&&e.tags.length>0&&a("div",{className:"lg-desktop:h-[28px] absolute left-4 top-4 flex h-[24px]",children:e.tags.map((n,m)=>n.label?a(A,{size:"sm",variant:n.variant||"outline",className:t("mr-1"),promotionalType:n.promotionalType,children:n.label},m):a(o.Fragment,{children:n},m))})]}),l($,{className:"desktop:p-6 bg-container-primary laptop:gap-6 flex h-[calc(100%-240px)] grow flex-col justify-between gap-4 p-4",children:[l("div",{className:"flex-0",children:[a(c,{as:"h3",size:2,className:t("text-info-primary mb-1 line-clamp-2 tracking-tight",s?"cursor-pointer":"",i?.productTitle),onClick:s?()=>s(e):void 0,children:e.custom_name||e.name}),(e.custom_description||e?.description)&&a(y,{size:2,className:t("text-info-primary line-clamp-1",i?.productDescription),html:e.custom_description||e.description})]}),I(d,f,e?.quantityAvailable??0,e?.totalInventory??0)&&l("div",{"data-total":e?.totalInventory??0,"data-available":e?.quantityAvailable??0,className:"space-y-2",children:[a(H,{value:z,max:100,min:0,size:"base",variant:"default","aria-label":"stock progress",classNames:{progressBar:"transition-all duration-300 ease-in-out"}}),a(y,{size:3,className:"text-info-tertiary desktop:text-[16px] lg-desktop:text-[18px] text-[12px]",children:_?p?.limitedStock:p?.stockDisplayText?.replace("{count}",`${e.availableForSale?e.quantityAvailable:0}`)})]}),l("div",{children:[a("div",{className:t("mb-2",i?.productPrice),children:a("div",{className:"flex items-baseline gap-2",children:e.availableForSale?l(O,{children:[a(c,{size:2,className:"text-info-primary",as:"h6",children:e.price}),N&&e.originalPrice&&a(c,{size:2,className:t("text-info-tertiary line-through",i?.originalPrice),as:"h6",children:e.originalPrice})]}):a(c,{size:2,className:"text-info-tertiary",children:p?.outOfStockLabel??"Sold Out"})})}),e?.priceLabel&&e?.availableForSale&&a(y,{size:4,className:t("text-marketing-1 desktop:text-[16px] lg-desktop:text-[18px] mt-2 text-[12px]",i?.productPriceLabel),children:e.priceLabel}),l("div",{className:t("lg-desktop:gap-3 tablet:flex-nowrap flex flex-wrap gap-2",i?.buttonGroup),children:[b&&a(k,{variant:"secondary",size:"base",className:t("tablet:w-fit tablet:min-w-0 tablet:whitespace-normal tablet:text-center w-full whitespace-nowrap",i?.secondaryButton),onClick:()=>x(v,"secondary"),disabled:!e.availableForSale&&v!=="learnMore",loading:D,"data-headless-type-name":"MediaShelf#ProductCard","data-headless-title-desc-button":`${e.custom_name||e.name}#${e.description||""}#${b}`,"data-headless-sku":e.sku,children:b}),u&&a(k,{variant:"primary",size:"base",className:t("tablet:w-fit tablet:min-w-0 tablet:whitespace-normal tablet:text-center w-full whitespace-nowrap",i?.primaryButton),onClick:()=>x(h,"primary"),disabled:!e.availableForSale&&h!=="learnMore",loading:L,"data-headless-type-name":"MediaShelf#ProductCard","data-headless-title-desc-button":`${e.custom_name||e.name}#${e.description||""}#${u}`,"data-headless-sku":e.sku,children:u})]})]})]})]})});g.displayName="MediaShelf.ProductCard";var K=g;export{g as ProductCard,K as default};
2
2
  //# sourceMappingURL=ProductCard.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/biz-components/MediaShelf/ProductCard.tsx"],
4
- "sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { cn } from '../../helpers/index.js'\nimport { Button, Badge, Card, CardContent, Picture, Text, Heading, Progress } from '../../components/index.js'\n\nimport type {\n ButtonFunctionType,\n CopyConfig,\n ProductCardData,\n StockDisplayMode,\n MediaShelfSemanticName,\n} from './types.js'\n\n/**\n * \u8D85\u5356\u65F6\u5E93\u5B58\u6761\u663E\u793A\u7684\u6700\u5C0F\u767E\u5206\u6BD4\n * \u9632\u6B62\u8D85\u5356\u65F6\u5E93\u5B58\u6761\u663E\u793A\u4E3A\u6EE1\u683C\uFF08100%\uFF09\u6216\u5B8C\u5168\u7A7A\uFF080%\uFF09\n */\nconst OVERSELLING_STOCK_PERCENTAGE = 5\n\n/**\n * \u5224\u65AD\u662F\u5426\u5E94\u8BE5\u663E\u793A\u5E93\u5B58\u4FE1\u606F\n * @param stockDisplayMode \u5E93\u5B58\u5C55\u793A\u6A21\u5F0F\n * @param stockThresholdValue \u5E93\u5B58\u9608\u503C\uFF08\u5F53\u6A21\u5F0F\u4E3A below-quantity \u6216 below-percentage \u65F6\u4F7F\u7528\uFF09\n * @param quantityAvailable \u53EF\u7528\u5E93\u5B58\u6570\u91CF\n * @param totalInventory \u603B\u5E93\u5B58\n * @returns \u662F\u5426\u663E\u793A\u5E93\u5B58\u4FE1\u606F\n */\nfunction shouldShowStock(\n stockDisplayMode: StockDisplayMode | undefined,\n stockThresholdValue: number | undefined,\n quantityAvailable: number,\n totalInventory: number\n): boolean {\n // \u672A\u914D\u7F6E\u65F6\u9ED8\u8BA4\u663E\u793A\n if (stockDisplayMode === undefined) {\n return true\n }\n\n // \u6839\u636E\u5C55\u793A\u6A21\u5F0F\u5224\u65AD\n switch (stockDisplayMode) {\n case 'always':\n // \u603B\u662F\u663E\u793A\n return true\n\n case 'never':\n // \u6C38\u4E0D\u663E\u793A\n return false\n\n case 'below-quantity':\n // \u5F53\u5E93\u5B58\u6570\u91CF\u4F4E\u4E8E\u9608\u503C\u65F6\u663E\u793A\n if (stockThresholdValue === undefined) {\n return true // \u6CA1\u6709\u8BBE\u7F6E\u9608\u503C\u65F6\u9ED8\u8BA4\u663E\u793A\n }\n\n return quantityAvailable <= stockThresholdValue\n\n case 'below-percentage':\n // \u5F53\u5E93\u5B58\u767E\u5206\u6BD4\u4F4E\u4E8E\u9608\u503C\u65F6\u663E\u793A\n if (stockThresholdValue === undefined) {\n return true // \u6CA1\u6709\u8BBE\u7F6E\u9608\u503C\u65F6\u9ED8\u8BA4\u663E\u793A\n }\n return (quantityAvailable / totalInventory) * 100 <= stockThresholdValue\n\n default:\n // \u672A\u77E5\u6A21\u5F0F\u65F6\u9ED8\u8BA4\u663E\u793A\n return true\n }\n}\n\n/**\n * MediaShelf ProductCard \u7EC4\u4EF6 Props \u63A5\u53E3\n */\nexport interface MediaShelfProductCardProps {\n /** \u4EA7\u54C1\u6570\u636E */\n product: ProductCardData\n /** \u6837\u5F0F\u7C7B\u540D */\n className?: string\n /** \u5E93\u5B58\u5C55\u793A\u6A21\u5F0F */\n stockDisplayMode?: StockDisplayMode\n /** \u5E93\u5B58\u9608\u503C\uFF08\u5F53\u6A21\u5F0F\u4E3A below-quantity \u6216 below-percentage \u65F6\u4F7F\u7528\uFF09 */\n stockThresholdValue?: number\n /** \u70B9\u51FB\u4E86\u89E3\u66F4\u591A\u56DE\u8C03 */\n onLearnMore?: (product: ProductCardData) => void\n /** \u70B9\u51FB\u7ACB\u5373\u8D2D\u4E70\u56DE\u8C03 */\n onShopNow?: (product: ProductCardData) => void\n /** \u70B9\u51FB\u52A0\u5165\u8D2D\u7269\u8F66\u56DE\u8C03 */\n onAddToCart?: (product: ProductCardData) => void\n /** \u8BED\u4E49\u5316\u7C7B\u540D */\n classNames?: Partial<Record<MediaShelfSemanticName, string>>\n /** \u4E86\u89E3\u66F4\u591A\u6309\u94AE\u6587\u672C */\n secondaryButtonText?: string\n /** \u4E86\u89E3\u66F4\u591A\u6309\u94AE\u529F\u80FD */\n secondaryButtonFun?: ButtonFunctionType\n /** \u7ACB\u5373\u8D2D\u4E70\u6309\u94AE\u6587\u672C */\n primaryButtonText?: string\n /** \u7ACB\u5373\u8D2D\u4E70\u6309\u94AE\u529F\u80FD */\n primaryButtonFun?: ButtonFunctionType\n /** \u662F\u5426\u5C55\u793A\u539F\u4EF7\uFF08\u5220\u9664\u7EBF\u4EF7\u683C\uFF09 */\n showOriginalPrice?: boolean\n /** \u6587\u6848\u914D\u7F6E */\n copy?: CopyConfig\n /** \u70B9\u51FB\u4EA7\u54C1\u56FE\u7247\u56DE\u8C03 */\n onProductImageClick?: (product: ProductCardData) => void\n /** \u662F\u5426\u5C55\u793A\u6807\u7B7E */\n showTags?: boolean\n}\n\n/**\n * MediaShelf \u4EA7\u54C1\u5361\u7247\u7EC4\u4EF6\n */\nconst ProductCard = React.forwardRef<HTMLDivElement, MediaShelfProductCardProps>(\n (\n {\n product,\n className,\n stockDisplayMode,\n stockThresholdValue,\n onLearnMore,\n onShopNow,\n onAddToCart,\n classNames,\n secondaryButtonText,\n secondaryButtonFun,\n primaryButtonText,\n primaryButtonFun,\n showOriginalPrice,\n copy,\n onProductImageClick,\n showTags = true,\n },\n ref\n ) => {\n const [primaryLoading, setPrimaryLoading] = React.useState(false)\n const [secondaryLoading, setSecondaryLoading] = React.useState(false)\n\n const stockPercentage = React.useMemo(() => {\n if (product?.availableForSale && product?.quantityAvailable <= 0) {\n return OVERSELLING_STOCK_PERCENTAGE\n }\n // \u4E0D\u53EF\u552E\u65F6\u663E\u793A0%\n if (!product?.availableForSale) {\n return 0\n }\n return ((product?.quantityAvailable ?? 0) / (product?.totalInventory ?? 1)) * 100\n }, [product?.availableForSale, product?.quantityAvailable, product?.totalInventory])\n\n // \u6839\u636E\u6309\u94AE\u529F\u80FD\u7C7B\u578B\u8C03\u7528\u76F8\u5E94\u7684\u56DE\u8C03\u51FD\u6570\n const handleButtonClick = async (buttonFun?: ButtonFunctionType, buttonType?: 'primary' | 'secondary') => {\n if (!buttonFun) return\n\n const setLoading = buttonType === 'primary' ? setPrimaryLoading : setSecondaryLoading\n setLoading(true)\n\n try {\n switch (buttonFun) {\n case 'buyNow':\n await onShopNow?.(product)\n break\n case 'addCart':\n await onAddToCart?.(product)\n break\n case 'learnMore':\n await onLearnMore?.(product)\n break\n default:\n break\n }\n } finally {\n setLoading(false)\n }\n }\n\n const overselling = product.availableForSale && product.quantityAvailable <= 0\n\n return (\n <Card\n ref={ref}\n className={cn(\n 'tablet:min-w-[auto] hover:bg-container-secondary-0 flex h-full min-w-[296px] flex-col overflow-hidden border-none',\n product.custom_link ? 'cursor-pointer' : '',\n className,\n classNames?.productCard\n )}\n >\n {/* \u56FE\u7247\u533A\u57DF */}\n <div\n className={cn(\n 'media-shelf-product-card-image-wrapper desktop:h-[240px] relative h-[200px] shrink-0 overflow-hidden',\n classNames?.productCardImageWrapper\n )}\n >\n {/* \u80CC\u666F\u56FE\u7247 */}\n <div className={cn('media-shelf-product-card-image-bg absolute inset-0 ', classNames?.productCardImageBg)}>\n <a\n onClick={() => onProductImageClick?.(product)}\n {...(!onProductImageClick && {\n href: product.custom_link || product.listingLink,\n })}\n className=\"cursor-pointer\"\n >\n <Picture\n source={product.custom_image || product.image}\n alt={product.name}\n className={cn('h-full', classNames?.productCardImage)}\n imgClassName=\"h-full object-contain\"\n />\n </a>\n </div>\n\n {/* \u6807\u7B7E\u533A\u57DF */}\n {showTags && product.tags && product.tags.length > 0 && (\n <div className=\"lg-desktop:h-[28px] absolute left-4 top-4 flex h-[24px]\">\n {product.tags.map((tag: any, index) =>\n (tag as any).label ? (\n <Badge\n key={index}\n size=\"sm\"\n variant={(tag.variant as any) || 'outline'}\n className={cn('mr-1')}\n promotionalType={tag.promotionalType}\n >\n {tag.label}\n </Badge>\n ) : (\n <React.Fragment key={index}>{tag}</React.Fragment>\n )\n )}\n </div>\n )}\n </div>\n\n {/* \u5185\u5BB9\u533A\u57DF */}\n <CardContent className=\"desktop:p-6 bg-container-primary laptop:gap-6 flex h-[calc(100%-240px)] grow flex-col justify-between gap-4 p-4\">\n {/* \u4EA7\u54C1\u6807\u9898\u548C\u526F\u6807\u9898 */}\n <div className=\"flex-0\">\n <Heading\n as=\"h3\"\n size={2}\n className={cn(\n 'text-info-primary mb-1 line-clamp-2 tracking-tight',\n onProductImageClick ? 'cursor-pointer' : '',\n classNames?.productTitle\n )}\n onClick={onProductImageClick ? () => onProductImageClick(product) : undefined}\n >\n {product.custom_name || product.name}\n </Heading>\n {(product.custom_description || product?.description) && (\n <Text\n size={2}\n className={cn('text-info-primary line-clamp-1', classNames?.productDescription)}\n html={product.custom_description || product.description}\n />\n )}\n </div>\n\n {/* \u5E93\u5B58\u4FE1\u606F */}\n {shouldShowStock(\n stockDisplayMode,\n stockThresholdValue,\n product?.quantityAvailable ?? 0,\n product?.totalInventory ?? 0\n ) && (\n <div\n data-total={product?.totalInventory ?? 0}\n data-available={product?.quantityAvailable ?? 0}\n className=\"space-y-2\"\n >\n <Progress\n value={stockPercentage}\n max={100}\n min={0}\n size=\"base\"\n variant=\"default\"\n aria-label=\"stock progress\"\n classNames={{\n progressBar: 'transition-all duration-300 ease-in-out',\n }}\n />\n <Text size={3} className=\"text-info-tertiary desktop:text-[16px] lg-desktop:text-[18px] text-[12px]\">\n {overselling\n ? copy?.limitedStock\n : copy?.stockDisplayText?.replace(\n '{count}',\n `${product.availableForSale ? product.quantityAvailable : 0}`\n )}\n </Text>\n </div>\n )}\n\n <div>\n {/* \u4EF7\u683C\u533A\u57DF */}\n <div className={cn('mb-2', classNames?.productPrice)}>\n <div className=\"flex items-baseline gap-2\">\n {product.availableForSale ? (\n <>\n <Heading size={2} className=\"text-info-primary\" as=\"h6\">\n {product.price}\n </Heading>\n {showOriginalPrice && product.originalPrice && (\n <Heading\n size={2}\n className={cn('text-info-tertiary line-through', classNames?.originalPrice)}\n as=\"h6\"\n >\n {product.originalPrice}\n </Heading>\n )}\n </>\n ) : (\n <Heading size={2} className=\"text-info-tertiary\">\n {copy?.outOfStockLabel ?? 'Sold Out'}\n </Heading>\n )}\n </div>\n </div>\n\n {product?.priceLabel && product?.availableForSale && (\n <Text\n size={4}\n className={cn(\n 'text-marketing-1 desktop:text-[16px] lg-desktop:text-[18px] mt-2 text-[12px]',\n classNames?.productPriceLabel\n )}\n >\n {product.priceLabel}\n </Text>\n )}\n\n {/* \u6309\u94AE\u533A\u57DF */}\n <div className={cn('lg-desktop:gap-3 tablet:flex-nowrap flex flex-wrap gap-2', classNames?.buttonGroup)}>\n {secondaryButtonText && (\n <Button\n variant=\"secondary\"\n size=\"base\"\n className={cn('tablet:w-fit w-full', classNames?.secondaryButton)}\n onClick={() => handleButtonClick(secondaryButtonFun, 'secondary')}\n disabled={!product.availableForSale && secondaryButtonFun !== 'learnMore'}\n loading={secondaryLoading}\n data-headless-type-name=\"MediaShelf#ProductCard\"\n data-headless-title-desc-button={`${product.custom_name || product.name}#${product.description || ''}#${secondaryButtonText}`}\n data-headless-sku={product.sku}\n >\n {secondaryButtonText}\n </Button>\n )}\n {primaryButtonText && (\n <Button\n variant=\"primary\"\n size=\"base\"\n className={cn('tablet:w-fit w-full', classNames?.primaryButton)}\n onClick={() => handleButtonClick(primaryButtonFun, 'primary')}\n disabled={!product.availableForSale && primaryButtonFun !== 'learnMore'}\n loading={primaryLoading}\n data-headless-type-name=\"MediaShelf#ProductCard\"\n data-headless-title-desc-button={`${product.custom_name || product.name}#${product.description || ''}#${primaryButtonText}`}\n data-headless-sku={product.sku}\n >\n {primaryButtonText}\n </Button>\n )}\n </div>\n </div>\n </CardContent>\n </Card>\n )\n }\n)\n\nProductCard.displayName = 'MediaShelf.ProductCard'\n\nexport default ProductCard\nexport { ProductCard }\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { cn } from '../../helpers/index.js'\nimport { Button, Badge, Card, CardContent, Picture, Text, Heading, Progress } from '../../components/index.js'\n\nimport type {\n ButtonFunctionType,\n CopyConfig,\n ProductCardData,\n StockDisplayMode,\n MediaShelfSemanticName,\n} from './types.js'\n\n/**\n * \u8D85\u5356\u65F6\u5E93\u5B58\u6761\u663E\u793A\u7684\u6700\u5C0F\u767E\u5206\u6BD4\n * \u9632\u6B62\u8D85\u5356\u65F6\u5E93\u5B58\u6761\u663E\u793A\u4E3A\u6EE1\u683C\uFF08100%\uFF09\u6216\u5B8C\u5168\u7A7A\uFF080%\uFF09\n */\nconst OVERSELLING_STOCK_PERCENTAGE = 5\n\n/**\n * \u5224\u65AD\u662F\u5426\u5E94\u8BE5\u663E\u793A\u5E93\u5B58\u4FE1\u606F\n * @param stockDisplayMode \u5E93\u5B58\u5C55\u793A\u6A21\u5F0F\n * @param stockThresholdValue \u5E93\u5B58\u9608\u503C\uFF08\u5F53\u6A21\u5F0F\u4E3A below-quantity \u6216 below-percentage \u65F6\u4F7F\u7528\uFF09\n * @param quantityAvailable \u53EF\u7528\u5E93\u5B58\u6570\u91CF\n * @param totalInventory \u603B\u5E93\u5B58\n * @returns \u662F\u5426\u663E\u793A\u5E93\u5B58\u4FE1\u606F\n */\nfunction shouldShowStock(\n stockDisplayMode: StockDisplayMode | undefined,\n stockThresholdValue: number | undefined,\n quantityAvailable: number,\n totalInventory: number\n): boolean {\n // \u672A\u914D\u7F6E\u65F6\u9ED8\u8BA4\u663E\u793A\n if (stockDisplayMode === undefined) {\n return true\n }\n\n // \u6839\u636E\u5C55\u793A\u6A21\u5F0F\u5224\u65AD\n switch (stockDisplayMode) {\n case 'always':\n // \u603B\u662F\u663E\u793A\n return true\n\n case 'never':\n // \u6C38\u4E0D\u663E\u793A\n return false\n\n case 'below-quantity':\n // \u5F53\u5E93\u5B58\u6570\u91CF\u4F4E\u4E8E\u9608\u503C\u65F6\u663E\u793A\n if (stockThresholdValue === undefined) {\n return true // \u6CA1\u6709\u8BBE\u7F6E\u9608\u503C\u65F6\u9ED8\u8BA4\u663E\u793A\n }\n\n return quantityAvailable <= stockThresholdValue\n\n case 'below-percentage':\n // \u5F53\u5E93\u5B58\u767E\u5206\u6BD4\u4F4E\u4E8E\u9608\u503C\u65F6\u663E\u793A\n if (stockThresholdValue === undefined) {\n return true // \u6CA1\u6709\u8BBE\u7F6E\u9608\u503C\u65F6\u9ED8\u8BA4\u663E\u793A\n }\n return (quantityAvailable / totalInventory) * 100 <= stockThresholdValue\n\n default:\n // \u672A\u77E5\u6A21\u5F0F\u65F6\u9ED8\u8BA4\u663E\u793A\n return true\n }\n}\n\n/**\n * MediaShelf ProductCard \u7EC4\u4EF6 Props \u63A5\u53E3\n */\nexport interface MediaShelfProductCardProps {\n /** \u4EA7\u54C1\u6570\u636E */\n product: ProductCardData\n /** \u6837\u5F0F\u7C7B\u540D */\n className?: string\n /** \u5E93\u5B58\u5C55\u793A\u6A21\u5F0F */\n stockDisplayMode?: StockDisplayMode\n /** \u5E93\u5B58\u9608\u503C\uFF08\u5F53\u6A21\u5F0F\u4E3A below-quantity \u6216 below-percentage \u65F6\u4F7F\u7528\uFF09 */\n stockThresholdValue?: number\n /** \u70B9\u51FB\u4E86\u89E3\u66F4\u591A\u56DE\u8C03 */\n onLearnMore?: (product: ProductCardData) => void\n /** \u70B9\u51FB\u7ACB\u5373\u8D2D\u4E70\u56DE\u8C03 */\n onShopNow?: (product: ProductCardData) => void\n /** \u70B9\u51FB\u52A0\u5165\u8D2D\u7269\u8F66\u56DE\u8C03 */\n onAddToCart?: (product: ProductCardData) => void\n /** \u8BED\u4E49\u5316\u7C7B\u540D */\n classNames?: Partial<Record<MediaShelfSemanticName, string>>\n /** \u4E86\u89E3\u66F4\u591A\u6309\u94AE\u6587\u672C */\n secondaryButtonText?: string\n /** \u4E86\u89E3\u66F4\u591A\u6309\u94AE\u529F\u80FD */\n secondaryButtonFun?: ButtonFunctionType\n /** \u7ACB\u5373\u8D2D\u4E70\u6309\u94AE\u6587\u672C */\n primaryButtonText?: string\n /** \u7ACB\u5373\u8D2D\u4E70\u6309\u94AE\u529F\u80FD */\n primaryButtonFun?: ButtonFunctionType\n /** \u662F\u5426\u5C55\u793A\u539F\u4EF7\uFF08\u5220\u9664\u7EBF\u4EF7\u683C\uFF09 */\n showOriginalPrice?: boolean\n /** \u6587\u6848\u914D\u7F6E */\n copy?: CopyConfig\n /** \u70B9\u51FB\u4EA7\u54C1\u56FE\u7247\u56DE\u8C03 */\n onProductImageClick?: (product: ProductCardData) => void\n /** \u662F\u5426\u5C55\u793A\u6807\u7B7E */\n showTags?: boolean\n}\n\n/**\n * MediaShelf \u4EA7\u54C1\u5361\u7247\u7EC4\u4EF6\n */\nconst ProductCard = React.forwardRef<HTMLDivElement, MediaShelfProductCardProps>(\n (\n {\n product,\n className,\n stockDisplayMode,\n stockThresholdValue,\n onLearnMore,\n onShopNow,\n onAddToCart,\n classNames,\n secondaryButtonText,\n secondaryButtonFun,\n primaryButtonText,\n primaryButtonFun,\n showOriginalPrice,\n copy,\n onProductImageClick,\n showTags = true,\n },\n ref\n ) => {\n const [primaryLoading, setPrimaryLoading] = React.useState(false)\n const [secondaryLoading, setSecondaryLoading] = React.useState(false)\n\n const stockPercentage = React.useMemo(() => {\n if (product?.availableForSale && product?.quantityAvailable <= 0) {\n return OVERSELLING_STOCK_PERCENTAGE\n }\n // \u4E0D\u53EF\u552E\u65F6\u663E\u793A0%\n if (!product?.availableForSale) {\n return 0\n }\n return ((product?.quantityAvailable ?? 0) / (product?.totalInventory ?? 1)) * 100\n }, [product?.availableForSale, product?.quantityAvailable, product?.totalInventory])\n\n // \u6839\u636E\u6309\u94AE\u529F\u80FD\u7C7B\u578B\u8C03\u7528\u76F8\u5E94\u7684\u56DE\u8C03\u51FD\u6570\n const handleButtonClick = async (buttonFun?: ButtonFunctionType, buttonType?: 'primary' | 'secondary') => {\n if (!buttonFun) return\n\n const setLoading = buttonType === 'primary' ? setPrimaryLoading : setSecondaryLoading\n setLoading(true)\n\n try {\n switch (buttonFun) {\n case 'buyNow':\n await onShopNow?.(product)\n break\n case 'addCart':\n await onAddToCart?.(product)\n break\n case 'learnMore':\n await onLearnMore?.(product)\n break\n default:\n break\n }\n } finally {\n setLoading(false)\n }\n }\n\n const overselling = product.availableForSale && product.quantityAvailable <= 0\n\n return (\n <Card\n ref={ref}\n className={cn(\n 'tablet:min-w-[auto] hover:bg-container-secondary-0 flex h-full min-w-[296px] flex-col overflow-hidden border-none',\n product.custom_link ? 'cursor-pointer' : '',\n className,\n classNames?.productCard\n )}\n >\n {/* \u56FE\u7247\u533A\u57DF */}\n <div\n className={cn(\n 'media-shelf-product-card-image-wrapper desktop:h-[240px] relative h-[200px] shrink-0 overflow-hidden',\n classNames?.productCardImageWrapper\n )}\n >\n {/* \u80CC\u666F\u56FE\u7247 */}\n <div className={cn('media-shelf-product-card-image-bg absolute inset-0 ', classNames?.productCardImageBg)}>\n <a\n onClick={() => onProductImageClick?.(product)}\n {...(!onProductImageClick && {\n href: product.custom_link || product.listingLink,\n })}\n className=\"cursor-pointer\"\n >\n <Picture\n source={product.custom_image || product.image}\n alt={product.name}\n className={cn('h-full', classNames?.productCardImage)}\n imgClassName=\"h-full object-contain\"\n />\n </a>\n </div>\n\n {/* \u6807\u7B7E\u533A\u57DF */}\n {showTags && product.tags && product.tags.length > 0 && (\n <div className=\"lg-desktop:h-[28px] absolute left-4 top-4 flex h-[24px]\">\n {product.tags.map((tag: any, index) =>\n (tag as any).label ? (\n <Badge\n key={index}\n size=\"sm\"\n variant={(tag.variant as any) || 'outline'}\n className={cn('mr-1')}\n promotionalType={tag.promotionalType}\n >\n {tag.label}\n </Badge>\n ) : (\n <React.Fragment key={index}>{tag}</React.Fragment>\n )\n )}\n </div>\n )}\n </div>\n\n {/* \u5185\u5BB9\u533A\u57DF */}\n <CardContent className=\"desktop:p-6 bg-container-primary laptop:gap-6 flex h-[calc(100%-240px)] grow flex-col justify-between gap-4 p-4\">\n {/* \u4EA7\u54C1\u6807\u9898\u548C\u526F\u6807\u9898 */}\n <div className=\"flex-0\">\n <Heading\n as=\"h3\"\n size={2}\n className={cn(\n 'text-info-primary mb-1 line-clamp-2 tracking-tight',\n onProductImageClick ? 'cursor-pointer' : '',\n classNames?.productTitle\n )}\n onClick={onProductImageClick ? () => onProductImageClick(product) : undefined}\n >\n {product.custom_name || product.name}\n </Heading>\n {(product.custom_description || product?.description) && (\n <Text\n size={2}\n className={cn('text-info-primary line-clamp-1', classNames?.productDescription)}\n html={product.custom_description || product.description}\n />\n )}\n </div>\n\n {/* \u5E93\u5B58\u4FE1\u606F */}\n {shouldShowStock(\n stockDisplayMode,\n stockThresholdValue,\n product?.quantityAvailable ?? 0,\n product?.totalInventory ?? 0\n ) && (\n <div\n data-total={product?.totalInventory ?? 0}\n data-available={product?.quantityAvailable ?? 0}\n className=\"space-y-2\"\n >\n <Progress\n value={stockPercentage}\n max={100}\n min={0}\n size=\"base\"\n variant=\"default\"\n aria-label=\"stock progress\"\n classNames={{\n progressBar: 'transition-all duration-300 ease-in-out',\n }}\n />\n <Text size={3} className=\"text-info-tertiary desktop:text-[16px] lg-desktop:text-[18px] text-[12px]\">\n {overselling\n ? copy?.limitedStock\n : copy?.stockDisplayText?.replace(\n '{count}',\n `${product.availableForSale ? product.quantityAvailable : 0}`\n )}\n </Text>\n </div>\n )}\n\n <div>\n {/* \u4EF7\u683C\u533A\u57DF */}\n <div className={cn('mb-2', classNames?.productPrice)}>\n <div className=\"flex items-baseline gap-2\">\n {product.availableForSale ? (\n <>\n <Heading size={2} className=\"text-info-primary\" as=\"h6\">\n {product.price}\n </Heading>\n {showOriginalPrice && product.originalPrice && (\n <Heading\n size={2}\n className={cn('text-info-tertiary line-through', classNames?.originalPrice)}\n as=\"h6\"\n >\n {product.originalPrice}\n </Heading>\n )}\n </>\n ) : (\n <Heading size={2} className=\"text-info-tertiary\">\n {copy?.outOfStockLabel ?? 'Sold Out'}\n </Heading>\n )}\n </div>\n </div>\n\n {product?.priceLabel && product?.availableForSale && (\n <Text\n size={4}\n className={cn(\n 'text-marketing-1 desktop:text-[16px] lg-desktop:text-[18px] mt-2 text-[12px]',\n classNames?.productPriceLabel\n )}\n >\n {product.priceLabel}\n </Text>\n )}\n\n {/* \u6309\u94AE\u533A\u57DF */}\n <div className={cn('lg-desktop:gap-3 tablet:flex-nowrap flex flex-wrap gap-2', classNames?.buttonGroup)}>\n {secondaryButtonText && (\n <Button\n variant=\"secondary\"\n size=\"base\"\n className={cn(\n 'tablet:w-fit tablet:min-w-0 tablet:whitespace-normal tablet:text-center w-full whitespace-nowrap',\n classNames?.secondaryButton\n )}\n onClick={() => handleButtonClick(secondaryButtonFun, 'secondary')}\n disabled={!product.availableForSale && secondaryButtonFun !== 'learnMore'}\n loading={secondaryLoading}\n data-headless-type-name=\"MediaShelf#ProductCard\"\n data-headless-title-desc-button={`${product.custom_name || product.name}#${product.description || ''}#${secondaryButtonText}`}\n data-headless-sku={product.sku}\n >\n {secondaryButtonText}\n </Button>\n )}\n {primaryButtonText && (\n <Button\n variant=\"primary\"\n size=\"base\"\n className={cn(\n 'tablet:w-fit tablet:min-w-0 tablet:whitespace-normal tablet:text-center w-full whitespace-nowrap',\n classNames?.primaryButton\n )}\n onClick={() => handleButtonClick(primaryButtonFun, 'primary')}\n disabled={!product.availableForSale && primaryButtonFun !== 'learnMore'}\n loading={primaryLoading}\n data-headless-type-name=\"MediaShelf#ProductCard\"\n data-headless-title-desc-button={`${product.custom_name || product.name}#${product.description || ''}#${primaryButtonText}`}\n data-headless-sku={product.sku}\n >\n {primaryButtonText}\n </Button>\n )}\n </div>\n </div>\n </CardContent>\n </Card>\n )\n }\n)\n\nProductCard.displayName = 'MediaShelf.ProductCard'\n\nexport default ProductCard\nexport { ProductCard }\n"],
5
+ "mappings": "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",
6
6
  "names": ["Fragment", "jsx", "jsxs", "React", "cn", "Button", "Badge", "Card", "CardContent", "Picture", "Text", "Heading", "Progress", "OVERSELLING_STOCK_PERCENTAGE", "shouldShowStock", "stockDisplayMode", "stockThresholdValue", "quantityAvailable", "totalInventory", "ProductCard", "product", "className", "onLearnMore", "onShopNow", "onAddToCart", "classNames", "secondaryButtonText", "secondaryButtonFun", "primaryButtonText", "primaryButtonFun", "showOriginalPrice", "copy", "onProductImageClick", "showTags", "ref", "primaryLoading", "setPrimaryLoading", "secondaryLoading", "setSecondaryLoading", "stockPercentage", "handleButtonClick", "buttonFun", "buttonType", "setLoading", "overselling", "tag", "index", "ProductCard_default"]
7
7
  }
@@ -1,2 +1,2 @@
1
- "use client";import{jsx as t,jsxs as i}from"react/jsx-runtime";import*as c from"react";import{Swiper as K,SwiperSlide as Q}from"swiper/react";import{FreeMode as U,Mousewheel as W}from"swiper/modules";import{cn as r}from"../../helpers/index.js";import{Heading as X,Button as T,Text as d}from"../../components/index.js";import{useSceneShelfContext as Y}from"./context.js";import"swiper/css";const S=c.forwardRef(({title:m,totalPriceLabel:N,totalCurrentPrice:L,totalOriginalPrice:v,primaryButtonText:k,primaryButtonFun:C,secondaryButtonText:D,secondaryButtonFun:F,bundleDiscountLabel:M,className:A,children:R,...O},z)=>{const e=Y(),a=e?.classNames,x=N??e?.totalPriceLabel??"Total Price:",s=L??e?.totalCurrentPrice,u=v??e?.totalOriginalPrice,f=k??e?.primaryButtonText??"Shop Now",y=C??e?.primaryButtonFun??"buyNow",P=D??e?.secondaryButtonText??"Add to Cart",b=F??e?.secondaryButtonFun??"addCart",l=M??e?.bundleDiscountLabel,n=e?.selectedProducts??[],V=e?.onLearnMore,H=e?.onShopNow,j=e?.onAddToCart,E=e?.showOriginalPrice??!0,[q,G]=c.useState(!1),[I,J]=c.useState(!1),g=c.Children.toArray(R),w=async(o,p)=>{if(!o)return;const h=p==="primary"?G:J;h(!0);try{switch(o){case"buyNow":await H?.(n);break;case"addCart":await j?.(n);break;case"learnMore":await V?.(n);break;default:break}}finally{h(!1)}},B=o=>o==="learnMore"?!1:n.length===0;return i("div",{ref:z,className:r("bg-container-primary laptop:p-6 lg-desktop:p-8 flex min-w-0 flex-1 flex-col justify-between overflow-hidden p-4",A,a?.content),...O,children:[m&&t(X,{as:"h2",size:3,className:r("text-info-primary flex-0 mb-[16px] line-clamp-1 shrink-0",a?.title),html:m}),t("div",{className:r("lg-desktop:mb-[24px] mb-[16px] flex-1 ",a?.productList),children:t(K,{modules:[U,W],freeMode:!0,mousewheel:{forceToAxis:!0},slidesPerView:"auto",spaceBetween:10,breakpoints:{0:{slidesPerView:1.5},768:{spaceBetween:16,slidesPerView:2.8},1024:{slidesPerView:2.3},1440:{spaceBetween:16,slidesPerView:g.length<=3?3:3.2}},children:g.map((o,p)=>t(Q,{className:"h-fit shrink-0",children:o},p))})}),i("div",{className:r("tablet:items-end tablet:flex-row flex-0 flex flex-col items-start justify-between gap-2",a?.footer),children:[i("div",{className:"flex flex-col",children:[i("div",{className:r("flex flex-wrap items-center gap-1",a?.totalPrice),children:[x&&t(d,{as:"span",size:2,className:"text-info-primary lg-desktop:text-[24px] text-[20px]",children:x}),s&&t(d,{as:"span",size:2,className:r("text-info-primary lg-desktop:text-[24px] text-[20px]",a?.currentTotalPrice),children:s.formatted}),E&&u&&s&&u.value>s.value&&t(d,{as:"span",size:2,className:r("text-info-quaternary lg-desktop:text-[24px] text-[20px] line-through",a?.originalTotalPrice),children:u.formatted})]}),l&&t(d,{as:"span",size:2,className:r("lg-desktop:text-[18px] desktop:text-[16px] line-clamp-1 text-[14px]",a?.bundleDiscountLabel),children:typeof l=="function"?l(n):l})]}),i("div",{className:r("flex gap-3",a?.buttonGroup),children:[P&&t(T,{variant:"secondary",onClick:()=>w(b,"secondary"),disabled:B(b),loading:I,children:P}),f&&t(T,{variant:"primary",onClick:()=>w(y,"primary"),disabled:B(y),loading:q,children:f})]})]})]})});S.displayName="SceneShelf.ProductsPanel";export{S as SceneShelfProductsPanel};
1
+ "use client";import{jsx as t,jsxs as i}from"react/jsx-runtime";import*as l from"react";import{Swiper as K,SwiperSlide as Q}from"swiper/react";import{FreeMode as U,Mousewheel as W}from"swiper/modules";import{cn as r}from"../../helpers/index.js";import{Heading as X,Button as T,Text as d}from"../../components/index.js";import{useSceneShelfContext as Y}from"./context.js";import"swiper/css";const N=l.forwardRef(({title:m,totalPriceLabel:S,totalCurrentPrice:L,totalOriginalPrice:v,primaryButtonText:k,primaryButtonFun:C,secondaryButtonText:D,secondaryButtonFun:F,bundleDiscountLabel:M,className:A,children:R,...O},z)=>{const e=Y(),a=e?.classNames,x=S??e?.totalPriceLabel??"Total Price:",s=L??e?.totalCurrentPrice,u=v??e?.totalOriginalPrice,f=k??e?.primaryButtonText??"Shop Now",y=C??e?.primaryButtonFun??"buyNow",P=D??e?.secondaryButtonText??"Add to Cart",w=F??e?.secondaryButtonFun??"addCart",c=M??e?.bundleDiscountLabel,n=e?.selectedProducts??[],V=e?.onLearnMore,H=e?.onShopNow,j=e?.onAddToCart,E=e?.showOriginalPrice??!0,[q,G]=l.useState(!1),[I,J]=l.useState(!1),b=l.Children.toArray(R),g=async(o,p)=>{if(!o)return;const B=p==="primary"?G:J;B(!0);try{switch(o){case"buyNow":await H?.(n);break;case"addCart":await j?.(n);break;case"learnMore":await V?.(n);break;default:break}}finally{B(!1)}},h=o=>o==="learnMore"?!1:n.length===0;return i("div",{ref:z,className:r("bg-container-primary laptop:p-6 lg-desktop:p-8 flex min-w-0 flex-1 flex-col justify-between overflow-hidden p-4",A,a?.content),...O,children:[m&&t(X,{as:"h2",size:3,className:r("text-info-primary flex-0 mb-[16px] line-clamp-1 shrink-0",a?.title),html:m}),t("div",{className:r("lg-desktop:mb-[24px] mb-[16px] flex-1 ",a?.productList),children:t(K,{modules:[U,W],freeMode:!0,mousewheel:{forceToAxis:!0},slidesPerView:"auto",spaceBetween:10,breakpoints:{0:{slidesPerView:1.5},768:{spaceBetween:16,slidesPerView:2.8},1024:{slidesPerView:2.3},1440:{spaceBetween:16,slidesPerView:b.length<=3?3:3.2}},children:b.map((o,p)=>t(Q,{className:"h-fit shrink-0",children:o},p))})}),i("div",{className:r("tablet:items-end tablet:flex-row flex-0 flex flex-col items-start justify-between gap-2",a?.footer),children:[i("div",{className:"flex flex-col",children:[i("div",{className:r("flex flex-wrap items-center gap-1",a?.totalPrice),children:[x&&t(d,{as:"span",size:2,className:"text-info-primary lg-desktop:text-[24px] text-[20px]",children:x}),s&&t(d,{as:"span",size:2,className:r("text-info-primary lg-desktop:text-[24px] text-[20px]",a?.currentTotalPrice),children:s.formatted}),E&&u&&s&&u.value>s.value&&t(d,{as:"span",size:2,className:r("text-info-quaternary lg-desktop:text-[24px] text-[20px] line-through",a?.originalTotalPrice),children:u.formatted})]}),c&&t(d,{as:"span",size:2,className:r("lg-desktop:text-[18px] desktop:text-[16px] line-clamp-1 text-[14px]",a?.bundleDiscountLabel),children:typeof c=="function"?c(n):c})]}),i("div",{className:r("flex items-stretch gap-3",a?.buttonGroup),children:[P&&t(T,{variant:"secondary",className:"min-w-0 whitespace-normal text-center",onClick:()=>g(w,"secondary"),disabled:h(w),loading:I,children:P}),f&&t(T,{variant:"primary",className:"min-w-0 whitespace-normal text-center",onClick:()=>g(y,"primary"),disabled:h(y),loading:q,children:f})]})]})]})});N.displayName="SceneShelf.ProductsPanel";export{N as SceneShelfProductsPanel};
2
2
  //# sourceMappingURL=ProductsPanel.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/biz-components/SceneShelf/ProductsPanel.tsx"],
4
- "sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Swiper, SwiperSlide } from 'swiper/react'\nimport { FreeMode, Mousewheel } from 'swiper/modules'\nimport { cn } from '../../helpers/index.js'\nimport { Heading, Button, Text } from '../../components/index.js'\nimport { useSceneShelfContext } from './context.js'\nimport type { PriceData, ButtonFunctionType, SceneProductCardData } from './types.js'\nimport 'swiper/css'\n\nexport interface SceneShelfProductsPanelProps extends React.HTMLAttributes<HTMLDivElement> {\n /** \u6807\u9898 */\n title?: string\n /** \u603B\u4EF7\u6807\u7B7E */\n totalPriceLabel?: string\n /** \u5F53\u524D\u603B\u4EF7 */\n totalCurrentPrice?: PriceData\n /** \u539F\u603B\u4EF7 */\n totalOriginalPrice?: PriceData\n /** \u4E3B\u8981\u6309\u94AE\u6587\u672C */\n primaryButtonText?: string\n /** \u4E3B\u8981\u6309\u94AE\u529F\u80FD\u7C7B\u578B */\n primaryButtonFun?: ButtonFunctionType\n /** \u6B21\u8981\u6309\u94AE\u6587\u672C */\n secondaryButtonText?: string\n /** \u6B21\u8981\u6309\u94AE\u529F\u80FD\u7C7B\u578B */\n secondaryButtonFun?: ButtonFunctionType\n /**\n * \u5957\u9910\u6298\u6263\u6807\u7B7E\uFF0C\u652F\u6301 string \u6216 render prop\n * @param selectedProducts \u5F53\u524D\u9009\u4E2D\u7684\u4EA7\u54C1\u5217\u8868\n */\n bundleDiscountLabel?: string | ((selectedProducts: SceneProductCardData[]) => React.ReactNode)\n /** \u5B50\u7EC4\u4EF6\uFF08ProductCard \u6216\u81EA\u5B9A\u4E49\u5361\u7247\uFF09 */\n children: React.ReactNode\n}\n\n/**\n * SceneShelf ProductsPanel \u7EC4\u4EF6\n *\n * @description \u4EA7\u54C1\u9762\u677F\u7EC4\u4EF6\uFF0C\u5305\u542B\u4EA7\u54C1\u5217\u8868\uFF08Swiper\uFF09\u548C\u5E95\u90E8\u64CD\u4F5C\u533A\u57DF\uFF08\u603B\u4EF7 + \u6309\u94AE\uFF09\n */\nconst SceneShelfProductsPanel = React.forwardRef<HTMLDivElement, SceneShelfProductsPanelProps>(\n (\n {\n title,\n totalPriceLabel: totalPriceLabelProp,\n totalCurrentPrice: totalCurrentPriceProp,\n totalOriginalPrice: totalOriginalPriceProp,\n primaryButtonText: primaryButtonTextProp,\n primaryButtonFun: primaryButtonFunProp,\n secondaryButtonText: secondaryButtonTextProp,\n secondaryButtonFun: secondaryButtonFunProp,\n bundleDiscountLabel: bundleDiscountLabelProp,\n className,\n children,\n ...props\n },\n ref\n ) => {\n const context = useSceneShelfContext()\n const classNames = context?.classNames\n\n // Props \u4F18\u5148\u7EA7\u9AD8\u4E8E Context\n const totalPriceLabel = totalPriceLabelProp ?? context?.totalPriceLabel ?? 'Total Price:'\n const totalCurrentPrice = totalCurrentPriceProp ?? context?.totalCurrentPrice\n const totalOriginalPrice = totalOriginalPriceProp ?? context?.totalOriginalPrice\n const primaryButtonText = primaryButtonTextProp ?? context?.primaryButtonText ?? 'Shop Now'\n const primaryButtonFun = primaryButtonFunProp ?? context?.primaryButtonFun ?? 'buyNow'\n const secondaryButtonText = secondaryButtonTextProp ?? context?.secondaryButtonText ?? 'Add to Cart'\n const secondaryButtonFun = secondaryButtonFunProp ?? context?.secondaryButtonFun ?? 'addCart'\n const bundleDiscountLabel = bundleDiscountLabelProp ?? context?.bundleDiscountLabel\n\n const selectedProducts = context?.selectedProducts ?? []\n const onLearnMore = context?.onLearnMore\n const onShopNow = context?.onShopNow\n const onAddToCart = context?.onAddToCart\n const showOriginalPrice = context?.showOriginalPrice ?? true\n\n // \u6309\u94AE loading \u72B6\u6001\n const [primaryLoading, setPrimaryLoading] = React.useState(false)\n const [secondaryLoading, setSecondaryLoading] = React.useState(false)\n\n // \u5C06 children \u8F6C\u6362\u4E3A\u6570\u7EC4\n const childrenArray = React.Children.toArray(children)\n\n // \u6839\u636E\u6309\u94AE\u529F\u80FD\u7C7B\u578B\u8C03\u7528\u76F8\u5E94\u7684\u56DE\u8C03\u51FD\u6570\n const handleButtonClick = async (buttonFun?: ButtonFunctionType, buttonType?: 'primary' | 'secondary') => {\n if (!buttonFun) return\n\n const setLoading = buttonType === 'primary' ? setPrimaryLoading : setSecondaryLoading\n setLoading(true)\n\n try {\n switch (buttonFun) {\n case 'buyNow':\n await onShopNow?.(selectedProducts)\n break\n case 'addCart':\n await onAddToCart?.(selectedProducts)\n break\n case 'learnMore':\n await onLearnMore?.(selectedProducts)\n break\n default:\n break\n }\n } finally {\n setLoading(false)\n }\n }\n\n // \u5224\u65AD\u6309\u94AE\u662F\u5426\u5E94\u8BE5\u88AB\u7981\u7528\uFF08learnMore \u4E0D\u9700\u8981\u68C0\u67E5\u9009\u4E2D\u4EA7\u54C1\u6570\u91CF\uFF09\n const isButtonDisabled = (buttonFun?: ButtonFunctionType) => {\n if (buttonFun === 'learnMore') return false\n return selectedProducts.length === 0\n }\n\n return (\n <div\n ref={ref}\n className={cn(\n 'bg-container-primary laptop:p-6 lg-desktop:p-8 flex min-w-0 flex-1 flex-col justify-between overflow-hidden p-4',\n className,\n classNames?.content\n )}\n {...props}\n >\n {/* \u6807\u9898 */}\n {title && (\n <Heading\n as=\"h2\"\n size={3}\n className={cn('text-info-primary flex-0 mb-[16px] line-clamp-1 shrink-0', classNames?.title)}\n html={title}\n />\n )}\n\n {/* \u4EA7\u54C1\u5217\u8868 - Swiper \u5BB9\u5668 */}\n <div className={cn('lg-desktop:mb-[24px] mb-[16px] flex-1 ', classNames?.productList)}>\n <Swiper\n modules={[FreeMode, Mousewheel]}\n freeMode={true}\n mousewheel={{\n forceToAxis: true,\n }}\n slidesPerView=\"auto\"\n spaceBetween={10}\n breakpoints={{\n 0: {\n slidesPerView: 1.5,\n },\n 768: {\n spaceBetween: 16,\n slidesPerView: 2.8,\n },\n 1024: {\n slidesPerView: 2.3,\n },\n 1440: {\n spaceBetween: 16,\n slidesPerView: childrenArray.length <= 3 ? 3 : 3.2,\n },\n }}\n >\n {childrenArray.map((child, index) => (\n <SwiperSlide key={index} className=\"h-fit shrink-0\">\n {child}\n </SwiperSlide>\n ))}\n </Swiper>\n </div>\n\n {/* \u5E95\u90E8\u533A\u57DF - \u603B\u4EF7 + \u6309\u94AE */}\n <div\n className={cn(\n 'tablet:items-end tablet:flex-row flex-0 flex flex-col items-start justify-between gap-2',\n classNames?.footer\n )}\n >\n <div className=\"flex flex-col\">\n {/* \u603B\u4EF7 */}\n <div className={cn('flex flex-wrap items-center gap-1', classNames?.totalPrice)}>\n {totalPriceLabel && (\n <Text as=\"span\" size={2} className=\"text-info-primary lg-desktop:text-[24px] text-[20px]\">\n {totalPriceLabel}\n </Text>\n )}\n {totalCurrentPrice && (\n <Text\n as=\"span\"\n size={2}\n className={cn('text-info-primary lg-desktop:text-[24px] text-[20px]', classNames?.currentTotalPrice)}\n >\n {totalCurrentPrice.formatted}\n </Text>\n )}\n {showOriginalPrice &&\n totalOriginalPrice &&\n totalCurrentPrice &&\n totalOriginalPrice.value > totalCurrentPrice.value && (\n <Text\n as=\"span\"\n size={2}\n className={cn(\n 'text-info-quaternary lg-desktop:text-[24px] text-[20px] line-through',\n classNames?.originalTotalPrice\n )}\n >\n {totalOriginalPrice.formatted}\n </Text>\n )}\n </div>\n {bundleDiscountLabel && (\n <Text\n as=\"span\"\n size={2}\n className={cn(\n 'lg-desktop:text-[18px] desktop:text-[16px] line-clamp-1 text-[14px]',\n classNames?.bundleDiscountLabel\n )}\n >\n {typeof bundleDiscountLabel === 'function'\n ? bundleDiscountLabel(selectedProducts)\n : bundleDiscountLabel}\n </Text>\n )}\n </div>\n\n {/* \u6309\u94AE\u7EC4 */}\n <div className={cn('flex gap-3', classNames?.buttonGroup)}>\n {secondaryButtonText && (\n <Button\n variant=\"secondary\"\n onClick={() => handleButtonClick(secondaryButtonFun, 'secondary')}\n disabled={isButtonDisabled(secondaryButtonFun)}\n loading={secondaryLoading}\n >\n {secondaryButtonText}\n </Button>\n )}\n {primaryButtonText && (\n <Button\n variant=\"primary\"\n onClick={() => handleButtonClick(primaryButtonFun, 'primary')}\n disabled={isButtonDisabled(primaryButtonFun)}\n loading={primaryLoading}\n >\n {primaryButtonText}\n </Button>\n )}\n </div>\n </div>\n </div>\n )\n }\n)\n\nSceneShelfProductsPanel.displayName = 'SceneShelf.ProductsPanel'\n\nexport { SceneShelfProductsPanel }\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Swiper, SwiperSlide } from 'swiper/react'\nimport { FreeMode, Mousewheel } from 'swiper/modules'\nimport { cn } from '../../helpers/index.js'\nimport { Heading, Button, Text } from '../../components/index.js'\nimport { useSceneShelfContext } from './context.js'\nimport type { PriceData, ButtonFunctionType, SceneProductCardData } from './types.js'\nimport 'swiper/css'\n\nexport interface SceneShelfProductsPanelProps extends React.HTMLAttributes<HTMLDivElement> {\n /** \u6807\u9898 */\n title?: string\n /** \u603B\u4EF7\u6807\u7B7E */\n totalPriceLabel?: string\n /** \u5F53\u524D\u603B\u4EF7 */\n totalCurrentPrice?: PriceData\n /** \u539F\u603B\u4EF7 */\n totalOriginalPrice?: PriceData\n /** \u4E3B\u8981\u6309\u94AE\u6587\u672C */\n primaryButtonText?: string\n /** \u4E3B\u8981\u6309\u94AE\u529F\u80FD\u7C7B\u578B */\n primaryButtonFun?: ButtonFunctionType\n /** \u6B21\u8981\u6309\u94AE\u6587\u672C */\n secondaryButtonText?: string\n /** \u6B21\u8981\u6309\u94AE\u529F\u80FD\u7C7B\u578B */\n secondaryButtonFun?: ButtonFunctionType\n /**\n * \u5957\u9910\u6298\u6263\u6807\u7B7E\uFF0C\u652F\u6301 string \u6216 render prop\n * @param selectedProducts \u5F53\u524D\u9009\u4E2D\u7684\u4EA7\u54C1\u5217\u8868\n */\n bundleDiscountLabel?: string | ((selectedProducts: SceneProductCardData[]) => React.ReactNode)\n /** \u5B50\u7EC4\u4EF6\uFF08ProductCard \u6216\u81EA\u5B9A\u4E49\u5361\u7247\uFF09 */\n children: React.ReactNode\n}\n\n/**\n * SceneShelf ProductsPanel \u7EC4\u4EF6\n *\n * @description \u4EA7\u54C1\u9762\u677F\u7EC4\u4EF6\uFF0C\u5305\u542B\u4EA7\u54C1\u5217\u8868\uFF08Swiper\uFF09\u548C\u5E95\u90E8\u64CD\u4F5C\u533A\u57DF\uFF08\u603B\u4EF7 + \u6309\u94AE\uFF09\n */\nconst SceneShelfProductsPanel = React.forwardRef<HTMLDivElement, SceneShelfProductsPanelProps>(\n (\n {\n title,\n totalPriceLabel: totalPriceLabelProp,\n totalCurrentPrice: totalCurrentPriceProp,\n totalOriginalPrice: totalOriginalPriceProp,\n primaryButtonText: primaryButtonTextProp,\n primaryButtonFun: primaryButtonFunProp,\n secondaryButtonText: secondaryButtonTextProp,\n secondaryButtonFun: secondaryButtonFunProp,\n bundleDiscountLabel: bundleDiscountLabelProp,\n className,\n children,\n ...props\n },\n ref\n ) => {\n const context = useSceneShelfContext()\n const classNames = context?.classNames\n\n // Props \u4F18\u5148\u7EA7\u9AD8\u4E8E Context\n const totalPriceLabel = totalPriceLabelProp ?? context?.totalPriceLabel ?? 'Total Price:'\n const totalCurrentPrice = totalCurrentPriceProp ?? context?.totalCurrentPrice\n const totalOriginalPrice = totalOriginalPriceProp ?? context?.totalOriginalPrice\n const primaryButtonText = primaryButtonTextProp ?? context?.primaryButtonText ?? 'Shop Now'\n const primaryButtonFun = primaryButtonFunProp ?? context?.primaryButtonFun ?? 'buyNow'\n const secondaryButtonText = secondaryButtonTextProp ?? context?.secondaryButtonText ?? 'Add to Cart'\n const secondaryButtonFun = secondaryButtonFunProp ?? context?.secondaryButtonFun ?? 'addCart'\n const bundleDiscountLabel = bundleDiscountLabelProp ?? context?.bundleDiscountLabel\n\n const selectedProducts = context?.selectedProducts ?? []\n const onLearnMore = context?.onLearnMore\n const onShopNow = context?.onShopNow\n const onAddToCart = context?.onAddToCart\n const showOriginalPrice = context?.showOriginalPrice ?? true\n\n // \u6309\u94AE loading \u72B6\u6001\n const [primaryLoading, setPrimaryLoading] = React.useState(false)\n const [secondaryLoading, setSecondaryLoading] = React.useState(false)\n\n // \u5C06 children \u8F6C\u6362\u4E3A\u6570\u7EC4\n const childrenArray = React.Children.toArray(children)\n\n // \u6839\u636E\u6309\u94AE\u529F\u80FD\u7C7B\u578B\u8C03\u7528\u76F8\u5E94\u7684\u56DE\u8C03\u51FD\u6570\n const handleButtonClick = async (buttonFun?: ButtonFunctionType, buttonType?: 'primary' | 'secondary') => {\n if (!buttonFun) return\n\n const setLoading = buttonType === 'primary' ? setPrimaryLoading : setSecondaryLoading\n setLoading(true)\n\n try {\n switch (buttonFun) {\n case 'buyNow':\n await onShopNow?.(selectedProducts)\n break\n case 'addCart':\n await onAddToCart?.(selectedProducts)\n break\n case 'learnMore':\n await onLearnMore?.(selectedProducts)\n break\n default:\n break\n }\n } finally {\n setLoading(false)\n }\n }\n\n // \u5224\u65AD\u6309\u94AE\u662F\u5426\u5E94\u8BE5\u88AB\u7981\u7528\uFF08learnMore \u4E0D\u9700\u8981\u68C0\u67E5\u9009\u4E2D\u4EA7\u54C1\u6570\u91CF\uFF09\n const isButtonDisabled = (buttonFun?: ButtonFunctionType) => {\n if (buttonFun === 'learnMore') return false\n return selectedProducts.length === 0\n }\n\n return (\n <div\n ref={ref}\n className={cn(\n 'bg-container-primary laptop:p-6 lg-desktop:p-8 flex min-w-0 flex-1 flex-col justify-between overflow-hidden p-4',\n className,\n classNames?.content\n )}\n {...props}\n >\n {/* \u6807\u9898 */}\n {title && (\n <Heading\n as=\"h2\"\n size={3}\n className={cn('text-info-primary flex-0 mb-[16px] line-clamp-1 shrink-0', classNames?.title)}\n html={title}\n />\n )}\n\n {/* \u4EA7\u54C1\u5217\u8868 - Swiper \u5BB9\u5668 */}\n <div className={cn('lg-desktop:mb-[24px] mb-[16px] flex-1 ', classNames?.productList)}>\n <Swiper\n modules={[FreeMode, Mousewheel]}\n freeMode={true}\n mousewheel={{\n forceToAxis: true,\n }}\n slidesPerView=\"auto\"\n spaceBetween={10}\n breakpoints={{\n 0: {\n slidesPerView: 1.5,\n },\n 768: {\n spaceBetween: 16,\n slidesPerView: 2.8,\n },\n 1024: {\n slidesPerView: 2.3,\n },\n 1440: {\n spaceBetween: 16,\n slidesPerView: childrenArray.length <= 3 ? 3 : 3.2,\n },\n }}\n >\n {childrenArray.map((child, index) => (\n <SwiperSlide key={index} className=\"h-fit shrink-0\">\n {child}\n </SwiperSlide>\n ))}\n </Swiper>\n </div>\n\n {/* \u5E95\u90E8\u533A\u57DF - \u603B\u4EF7 + \u6309\u94AE */}\n <div\n className={cn(\n 'tablet:items-end tablet:flex-row flex-0 flex flex-col items-start justify-between gap-2',\n classNames?.footer\n )}\n >\n <div className=\"flex flex-col\">\n {/* \u603B\u4EF7 */}\n <div className={cn('flex flex-wrap items-center gap-1', classNames?.totalPrice)}>\n {totalPriceLabel && (\n <Text as=\"span\" size={2} className=\"text-info-primary lg-desktop:text-[24px] text-[20px]\">\n {totalPriceLabel}\n </Text>\n )}\n {totalCurrentPrice && (\n <Text\n as=\"span\"\n size={2}\n className={cn('text-info-primary lg-desktop:text-[24px] text-[20px]', classNames?.currentTotalPrice)}\n >\n {totalCurrentPrice.formatted}\n </Text>\n )}\n {showOriginalPrice &&\n totalOriginalPrice &&\n totalCurrentPrice &&\n totalOriginalPrice.value > totalCurrentPrice.value && (\n <Text\n as=\"span\"\n size={2}\n className={cn(\n 'text-info-quaternary lg-desktop:text-[24px] text-[20px] line-through',\n classNames?.originalTotalPrice\n )}\n >\n {totalOriginalPrice.formatted}\n </Text>\n )}\n </div>\n {bundleDiscountLabel && (\n <Text\n as=\"span\"\n size={2}\n className={cn(\n 'lg-desktop:text-[18px] desktop:text-[16px] line-clamp-1 text-[14px]',\n classNames?.bundleDiscountLabel\n )}\n >\n {typeof bundleDiscountLabel === 'function'\n ? bundleDiscountLabel(selectedProducts)\n : bundleDiscountLabel}\n </Text>\n )}\n </div>\n\n {/* \u6309\u94AE\u7EC4 */}\n <div className={cn('flex items-stretch gap-3', classNames?.buttonGroup)}>\n {secondaryButtonText && (\n <Button\n variant=\"secondary\"\n className=\"min-w-0 whitespace-normal text-center\"\n onClick={() => handleButtonClick(secondaryButtonFun, 'secondary')}\n disabled={isButtonDisabled(secondaryButtonFun)}\n loading={secondaryLoading}\n >\n {secondaryButtonText}\n </Button>\n )}\n {primaryButtonText && (\n <Button\n variant=\"primary\"\n className=\"min-w-0 whitespace-normal text-center\"\n onClick={() => handleButtonClick(primaryButtonFun, 'primary')}\n disabled={isButtonDisabled(primaryButtonFun)}\n loading={primaryLoading}\n >\n {primaryButtonText}\n </Button>\n )}\n </div>\n </div>\n </div>\n )\n }\n)\n\nSceneShelfProductsPanel.displayName = 'SceneShelf.ProductsPanel'\n\nexport { SceneShelfProductsPanel }\n"],
5
+ "mappings": "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",
6
6
  "names": ["jsx", "jsxs", "React", "Swiper", "SwiperSlide", "FreeMode", "Mousewheel", "cn", "Heading", "Button", "Text", "useSceneShelfContext", "SceneShelfProductsPanel", "title", "totalPriceLabelProp", "totalCurrentPriceProp", "totalOriginalPriceProp", "primaryButtonTextProp", "primaryButtonFunProp", "secondaryButtonTextProp", "secondaryButtonFunProp", "bundleDiscountLabelProp", "className", "children", "props", "ref", "context", "classNames", "totalPriceLabel", "totalCurrentPrice", "totalOriginalPrice", "primaryButtonText", "primaryButtonFun", "secondaryButtonText", "secondaryButtonFun", "bundleDiscountLabel", "selectedProducts", "onLearnMore", "onShopNow", "onAddToCart", "showOriginalPrice", "primaryLoading", "setPrimaryLoading", "secondaryLoading", "setSecondaryLoading", "childrenArray", "handleButtonClick", "buttonFun", "buttonType", "setLoading", "isButtonDisabled", "child", "index"]
7
7
  }
@@ -1,2 +1,2 @@
1
- "use client";import{Fragment as de,jsx as t,jsxs as d}from"react/jsx-runtime";import*as a from"react";import{cn as o,getLocalizedPath as q}from"../../helpers/index.js";import{Heading as E,Text as O,Badge as J,Button as G,Picture as U}from"../../components/index.js";import X from"../Media/index.js";import{Swiper as Y,SwiperSlide as Z}from"swiper/react";import{Mousewheel as ee}from"swiper/modules";import"swiper/css";import"swiper/css/navigation";import{withLayout as te}from"../../shared/Styles.js";import{useGridRowCount as ie}from"../../hooks/useGridRowCount.js";import{useExposure as oe}from"../../hooks/useExposure.js";import{useViewItemList as ae}from"../../hooks/useViewItemList.js";import{trackUrlRef as re}from"../../shared/trackUrlRef.js";import{useAiuiContext as W}from"../AiuiProvider/index.js";import{gaTrack as H}from"../../shared/track.js";const ne="shelf",se="scene_shelf_v2",le=()=>t("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:t("path",{d:"M8 5.14v13.72L19 12 8 5.14z",fill:"white"})}),ce=()=>d("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:[t("rect",{x:"6",y:"5",width:"4",height:"14",rx:"1",fill:"white"}),t("rect",{x:"14",y:"5",width:"4",height:"14",rx:"1",fill:"white"})]}),j=a.memo(({product:e,isShowTag:p=!0,onImageClick:m,onProductImageClick:l,onLearnMore:S,onShopNow:P,onAddToCart:k,secondaryButtonText:h,secondaryButtonFun:y,primaryButtonText:b,primaryButtonFun:_,classNames:r,className:n,theme:V,index:s})=>{const{locale:N="us",trackingData:L}=W(),[B,M]=a.useState(!1),[C,z]=a.useState(!1),u=L?.pageGroup,x=a.useCallback(async(c,g)=>{if(!c)return;const T=g==="primary"?M:z;T(!0);try{switch(c){case"buyNow":await P?.(e);break;case"addCart":await k?.(e);break;case"learnMore":await S?.(e?.href??"");break;default:break}}finally{T(!1)}},[S,P,k,e]),I=a.useCallback(()=>x(_,"primary"),[x,_]),R=a.useCallback(()=>x(y,"secondary"),[x,y]),f=a.useCallback(c=>{const g=l??m;!e.href&&g&&c.preventDefault(),g?.(e),H({event:"ga4Event",event_name:"select_item",item_list_name:"Scene_Shelf_2_Products",page_group:u,items:[{item_id:e.sku,item_name:e.custom_name||e.title,item_variant:e.variantId,price:e.currentPrice,index:s}]})},[s,m,l,u,e]);return d("div",{className:o("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,r?.productCard,{"bg-container-secondary-0":V==="dark"}),children:[e.href?t("a",{href:q(re(e.href,u+"_"+ne+"_"+se),N),onClick:f,className:o("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",r?.productCardImage),"aria-label":`View ${e.title}`,children:t(U,{source:e.imageUrl,alt:e.imageAlt,className:"size-full",imgClassName:"object-contain"})}):t("div",{className:o("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 ",(l??m)&&"cursor-pointer transition-opacity hover:opacity-80",r?.productCardImage),onClick:l??m?f:void 0,role:l??m?"button":void 0,tabIndex:l??m?0:void 0,"aria-label":l??m?`View ${e.title}`:void 0,children:t(U,{source:e.imageUrl,alt:e.imageAlt,className:"size-full",imgClassName:"object-contain"})}),d("div",{className:"desktop:gap-6 flex w-full flex-1 flex-col justify-between gap-4",children:[d("div",{className:"flex flex-col gap-2",children:[t("div",{className:o("scene-shelf-v2-product-card-tags flex min-h-[24px] flex-wrap gap-1",r?.productCardTags),children:p&&e?.tags?.map((c,g)=>t(J,{variant:c.variant??"outline",size:"sm",className:"",children:c.label},g))}),t(E,{as:"h3",size:2,className:o("scene-shelf-v2-product-card-title text-info-primary laptop:line-clamp-2 line-clamp-3 pr-[16%] text-[16px]",r?.productCardTitle),children:e.custom_name||e.title}),(e.custom_description||e.description)&&t(O,{as:"p",size:1,className:o("scene-shelf-v2-product-card-description text-info-primary tablet:text-[14px] desktop:text-[16px] lg-desktop:text-[18px] line-clamp-1",r?.productCardDescription),children:e.custom_description||e.description})]}),d("div",{className:"flex flex-col gap-2",children:[d("div",{className:o("scene-shelf-v2-product-card-price flex flex-wrap items-center gap-1",r?.productCardPriceWrapper),children:[t(E,{as:"h6",size:2,className:o("scene-shelf-v2-product-card-current-price text-info-primary",r?.productCardCurrentPrice),children:e.currentPrice}),e.originalPrice&&t(E,{as:"h6",size:2,className:o("scene-shelf-v2-product-card-original-price text-info-tertiary line-through",r?.productCardOriginalPrice),children:e.originalPrice})]}),e?.priceLabel&&t(O,{size:4,className:o("text-marketing-1 desktop:text-[16px] lg-desktop:text-[18px] text-[14px]",r?.productCardPriceLabel),children:e.priceLabel}),(h||b)&&d("div",{className:o("scene-shelf-v2-product-card-buttons laptop:flex-nowrap lg-desktop:gap-3 flex flex-wrap gap-2",r?.productCardButtons),children:[h&&t(G,{variant:"secondary",className:"laptop:grow-0 flex-1 whitespace-nowrap",onClick:()=>{R(),H({event:"ga4Event",event_name:"component_click",event_parameters:{page_group:u||"Home Page",component_type:"copy",component_name:"scene_shelf_product",component_title:e.title,component_description:"",button_name:h,SKU:e.sku||"",position:s}})},disabled:e.soldOut&&y!=="learnMore",loading:C,children:h}),b&&t(G,{variant:"primary",className:"laptop:grow-0 flex-1 whitespace-nowrap",onClick:()=>{I(),H({event:"ga4Event",event_name:"component_click",event_parameters:{page_group:u||"Home Page",component_type:"copy",component_name:"scene_shelf_product",component_title:e.title,component_description:"",button_name:b,SKU:e.sku||"",position:s}})},disabled:e.soldOut&&_!=="learnMore",loading:B,children:b})]})]})]})]})});j.displayName="SceneShelfV2.ProductCard";const K=a.forwardRef(({className:e,classNames:p={},data:m,onPlayClick:l,onImageClick:S,onProductImageClick:P,onLearnMore:k,onShopNow:h,onAddToCart:y,...b},_)=>{const{theme:r="light",sceneImage:n,productsTitle:V,products:s,secondaryButtonText:N,secondaryButtonFun:L,primaryButtonText:B,primaryButtonFun:M,viewMoreLimit:C=2,copy:z}=m,u=a.useRef(null),x=a.useRef(null),I=a.useRef(null),[R,f]=a.useState(!1),[c,g]=a.useState(!1),{trackingData:T}=W();oe(x,{componentType:"image",componentName:"scene_shelf_banner"}),ae(I,{componentType:"video",componentName:"scene_shelf_banner",itemListName:"Scene_Shelf_2_Products",items:s.map((i,v)=>({item_id:i.sku??"",item_name:i.title,item_variant:i.variantId??"",price:i.currentPrice,index:v})),tabName:""});const F=ie({rows:C??0,mobileCols:2}),A=a.useMemo(()=>[n?.pc,n?.desktop,n?.laptop,n?.pad,n?.mobile].some(i=>i?.mimeType==="video/mp4"),[n]),$=a.useCallback(()=>{const i=u.current;i?i.paused?(i.play(),f(!0),l?.(!0)):(i.pause(),f(!1),l?.(!1)):l?.(!0),H({event:"ga4Event",event_name:"component_click",event_parameters:{page_group:T?.pageGroup,component_type:"video",component_name:"scene_shelf_banner",position:1,creative_id:n?.pc?.id}})},[l,n?.pc?.id,T?.pageGroup]);return a.useEffect(()=>{const i=u.current;if(!i||!A)return;const v=new IntersectionObserver(w=>{w.forEach(D=>{D.isIntersecting?i.play().catch(Q=>{console.warn("Video autoplay failed:",Q)}):i.pause()})},{threshold:.5});return v.observe(i),()=>{v.disconnect()}},[]),d("div",{...b,ref:_,className:o("scene-shelf-v2-root w-full overflow-hidden",{"aiui-dark":r==="dark"},e,p?.root),children:[d("div",{className:o("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",p?.media),ref:x,children:[t(X,{pcImage:n?.pc,desktopImage:n?.desktop,laptopImage:n?.laptop,padImage:n?.pad,mobileImage:n?.mobile,className:"size-full",videoClassName:"absolute inset-0 size-full object-cover",videoRef:u,onVideoPlay:()=>f(!0),onVideoPause:()=>f(!1),onVideoEnded:()=>f(!1)}),t("div",{"aria-hidden":"true",className:o("scene-shelf-v2-media-overlay pointer-events-none absolute inset-0",p?.mediaOverlay)}),A&&t("div",{className:"desktop:gap-16 desktop:p-8 absolute inset-0 flex items-end justify-end gap-4 p-6",children:t("button",{type:"button","aria-label":R?"Pause video":"Play video",onClick:$,className:o("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",p?.mediaPlayButton),children:R?t(ce,{}):t(le,{})})})]}),d("div",{ref:I,className:o("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",p?.products),children:[V&&t(E,{as:"h2",size:3,className:o("scene-shelf-v2-products-title text-info-primary",p?.productsTitle),html:V}),t("div",{className:"tablet:hidden grid grid-cols-2 gap-3",children:(()=>{const i=C!==void 0&&C>0&&s.length>F,v=i&&!c?s.slice(0,F):s;return d(de,{children:[v.map((w,D)=>t(j,{isShowTag:m.isShowTag??!0,product:w,onImageClick:S,onProductImageClick:P,onLearnMore:k,onShopNow:h,onAddToCart:y,secondaryButtonText:N,secondaryButtonFun:L,primaryButtonText:B,primaryButtonFun:M,classNames:p,theme:r,index:D},w.productKey)),i&&t("div",{className:"col-span-2 mt-6 flex justify-center",children:d("button",{type:"button",onClick:()=>g(w=>!w),className:"text-info-primary hover:text-brand-0 flex items-center gap-2 text-[14px] font-bold transition-colors","aria-expanded":c,children:[c?z?.viewLessLabel??"View Less":z?.viewMoreLabel??"View More",t("svg",{className:o("size-4 transition-transform",c&&"rotate-180"),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:t("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})]})})]})})()}),t("div",{className:"tablet:block hidden",children:t("div",{className:"relative",children:t(Y,{slidesPerView:"auto",observer:!0,observeParents:!0,modules:[ee],mousewheel:{enabled:!0,forceToAxis:!0,sensitivity:1},className:"!overflow-visible",breakpoints:{768:{spaceBetween:16,slidesPerView:s.length>3?2.3:2},1024:{spaceBetween:16,slidesPerView:s.length>3?2.8:3},1440:{spaceBetween:16,slidesPerView:s.length>4?3.8:4},1920:{spaceBetween:16,slidesPerView:s.length>4?3.8:4}},children:s.map((i,v)=>t(Z,{className:o("!h-auto ",p.productCardSlideWrapper),children:t(j,{product:i,isShowTag:m.isShowTag??!0,onImageClick:S,onProductImageClick:P,onLearnMore:k,onShopNow:h,onAddToCart:y,secondaryButtonText:N,secondaryButtonFun:L,primaryButtonText:B,primaryButtonFun:M,classNames:p,theme:r,index:v})},i.productKey))})})})]})]})});K.displayName="SceneShelfV2";var _e=te(K);export{j as SceneShelfV2ProductCard,_e as default};
1
+ "use client";import{Fragment as de,jsx as t,jsxs as d}from"react/jsx-runtime";import*as o from"react";import{cn as a,getLocalizedPath as q}from"../../helpers/index.js";import{Heading as E,Text as O,Badge as J,Button as G,Picture as U}from"../../components/index.js";import X from"../Media/index.js";import{Swiper as Y,SwiperSlide as Z}from"swiper/react";import{Mousewheel as ee}from"swiper/modules";import"swiper/css";import"swiper/css/navigation";import{withLayout as te}from"../../shared/Styles.js";import{useGridRowCount as ie}from"../../hooks/useGridRowCount.js";import{useExposure as ae}from"../../hooks/useExposure.js";import{useViewItemList as oe}from"../../hooks/useViewItemList.js";import{trackUrlRef as re}from"../../shared/trackUrlRef.js";import{useAiuiContext as W}from"../AiuiProvider/index.js";import{gaTrack as H}from"../../shared/track.js";const ne="shelf",se="scene_shelf_v2",le=()=>t("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:t("path",{d:"M8 5.14v13.72L19 12 8 5.14z",fill:"white"})}),ce=()=>d("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:[t("rect",{x:"6",y:"5",width:"4",height:"14",rx:"1",fill:"white"}),t("rect",{x:"14",y:"5",width:"4",height:"14",rx:"1",fill:"white"})]}),j=o.memo(({product:e,isShowTag:p=!0,onImageClick:m,onProductImageClick:l,onLearnMore:S,onShopNow:P,onAddToCart:k,secondaryButtonText:h,secondaryButtonFun:y,primaryButtonText:b,primaryButtonFun:_,classNames:r,className:n,theme:V,index:s})=>{const{locale:N="us",trackingData:L}=W(),[B,M]=o.useState(!1),[C,z]=o.useState(!1),u=L?.pageGroup,x=o.useCallback(async(c,v)=>{if(!c)return;const T=v==="primary"?M:z;T(!0);try{switch(c){case"buyNow":await P?.(e);break;case"addCart":await k?.(e);break;case"learnMore":await S?.(e?.href??"");break;default:break}}finally{T(!1)}},[S,P,k,e]),I=o.useCallback(()=>x(_,"primary"),[x,_]),R=o.useCallback(()=>x(y,"secondary"),[x,y]),f=o.useCallback(c=>{const v=l??m;!e.href&&v&&c.preventDefault(),v?.(e),H({event:"ga4Event",event_name:"select_item",item_list_name:"Scene_Shelf_2_Products",page_group:u,items:[{item_id:e.sku,item_name:e.custom_name||e.title,item_variant:e.variantId,price:e.currentPrice,index:s}]})},[s,m,l,u,e]);return d("div",{className:a("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,r?.productCard,{"bg-container-secondary-0":V==="dark"}),children:[e.href?t("a",{href:q(re(e.href,u+"_"+ne+"_"+se),N),onClick:f,className:a("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",r?.productCardImage),"aria-label":`View ${e.title}`,children:t(U,{source:e.imageUrl,alt:e.imageAlt,className:"size-full",imgClassName:"object-contain"})}):t("div",{className:a("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 ",(l??m)&&"cursor-pointer transition-opacity hover:opacity-80",r?.productCardImage),onClick:l??m?f:void 0,role:l??m?"button":void 0,tabIndex:l??m?0:void 0,"aria-label":l??m?`View ${e.title}`:void 0,children:t(U,{source:e.imageUrl,alt:e.imageAlt,className:"size-full",imgClassName:"object-contain"})}),d("div",{className:"desktop:gap-6 flex w-full flex-1 flex-col justify-between gap-4",children:[d("div",{className:"flex flex-col gap-2",children:[t("div",{className:a("scene-shelf-v2-product-card-tags flex min-h-[24px] flex-wrap gap-1",r?.productCardTags),children:p&&e?.tags?.map((c,v)=>t(J,{variant:c.variant??"outline",size:"sm",className:"",children:c.label},v))}),t(E,{as:"h3",size:2,className:a("scene-shelf-v2-product-card-title text-info-primary laptop:line-clamp-2 line-clamp-3 pr-[16%] text-[16px]",r?.productCardTitle),children:e.custom_name||e.title}),(e.custom_description||e.description)&&t(O,{as:"p",size:1,className:a("scene-shelf-v2-product-card-description text-info-primary tablet:text-[14px] desktop:text-[16px] lg-desktop:text-[18px] line-clamp-1",r?.productCardDescription),children:e.custom_description||e.description})]}),d("div",{className:"flex flex-col gap-2",children:[d("div",{className:a("scene-shelf-v2-product-card-price flex flex-wrap items-center gap-1",r?.productCardPriceWrapper),children:[t(E,{as:"h6",size:2,className:a("scene-shelf-v2-product-card-current-price text-info-primary",r?.productCardCurrentPrice),children:e.currentPrice}),e.originalPrice&&t(E,{as:"h6",size:2,className:a("scene-shelf-v2-product-card-original-price text-info-tertiary line-through",r?.productCardOriginalPrice),children:e.originalPrice})]}),e?.priceLabel&&t(O,{size:4,className:a("text-marketing-1 desktop:text-[16px] lg-desktop:text-[18px] text-[14px]",r?.productCardPriceLabel),children:e.priceLabel}),(h||b)&&d("div",{className:a("scene-shelf-v2-product-card-buttons laptop:flex-nowrap lg-desktop:gap-3 flex flex-wrap gap-2",r?.productCardButtons),children:[h&&t(G,{variant:"secondary",className:"laptop:w-auto laptop:flex-1 w-full min-w-0 whitespace-normal text-center",onClick:()=>{R(),H({event:"ga4Event",event_name:"component_click",event_parameters:{page_group:u||"Home Page",component_type:"copy",component_name:"scene_shelf_product",component_title:e.title,component_description:"",button_name:h,SKU:e.sku||"",position:s}})},disabled:e.soldOut&&y!=="learnMore",loading:C,children:h}),b&&t(G,{variant:"primary",className:"laptop:w-auto laptop:flex-1 w-full min-w-0 whitespace-normal text-center",onClick:()=>{I(),H({event:"ga4Event",event_name:"component_click",event_parameters:{page_group:u||"Home Page",component_type:"copy",component_name:"scene_shelf_product",component_title:e.title,component_description:"",button_name:b,SKU:e.sku||"",position:s}})},disabled:e.soldOut&&_!=="learnMore",loading:B,children:b})]})]})]})]})});j.displayName="SceneShelfV2.ProductCard";const K=o.forwardRef(({className:e,classNames:p={},data:m,onPlayClick:l,onImageClick:S,onProductImageClick:P,onLearnMore:k,onShopNow:h,onAddToCart:y,...b},_)=>{const{theme:r="light",sceneImage:n,productsTitle:V,products:s,secondaryButtonText:N,secondaryButtonFun:L,primaryButtonText:B,primaryButtonFun:M,viewMoreLimit:C=2,copy:z}=m,u=o.useRef(null),x=o.useRef(null),I=o.useRef(null),[R,f]=o.useState(!1),[c,v]=o.useState(!1),{trackingData:T}=W();ae(x,{componentType:"image",componentName:"scene_shelf_banner"}),oe(I,{componentType:"video",componentName:"scene_shelf_banner",itemListName:"Scene_Shelf_2_Products",items:s.map((i,g)=>({item_id:i.sku??"",item_name:i.title,item_variant:i.variantId??"",price:i.currentPrice,index:g})),tabName:""});const F=ie({rows:C??0,mobileCols:2}),A=o.useMemo(()=>[n?.pc,n?.desktop,n?.laptop,n?.pad,n?.mobile].some(i=>i?.mimeType==="video/mp4"),[n]),$=o.useCallback(()=>{const i=u.current;i?i.paused?(i.play(),f(!0),l?.(!0)):(i.pause(),f(!1),l?.(!1)):l?.(!0),H({event:"ga4Event",event_name:"component_click",event_parameters:{page_group:T?.pageGroup,component_type:"video",component_name:"scene_shelf_banner",position:1,creative_id:n?.pc?.id}})},[l,n?.pc?.id,T?.pageGroup]);return o.useEffect(()=>{const i=u.current;if(!i||!A)return;const g=new IntersectionObserver(w=>{w.forEach(D=>{D.isIntersecting?i.play().catch(Q=>{console.warn("Video autoplay failed:",Q)}):i.pause()})},{threshold:.5});return g.observe(i),()=>{g.disconnect()}},[]),d("div",{...b,ref:_,className:a("scene-shelf-v2-root w-full overflow-hidden",{"aiui-dark":r==="dark"},e,p?.root),children:[d("div",{className:a("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",p?.media),ref:x,children:[t(X,{pcImage:n?.pc,desktopImage:n?.desktop,laptopImage:n?.laptop,padImage:n?.pad,mobileImage:n?.mobile,className:"size-full",videoClassName:"absolute inset-0 size-full object-cover",videoRef:u,onVideoPlay:()=>f(!0),onVideoPause:()=>f(!1),onVideoEnded:()=>f(!1)}),t("div",{"aria-hidden":"true",className:a("scene-shelf-v2-media-overlay pointer-events-none absolute inset-0",p?.mediaOverlay)}),A&&t("div",{className:"desktop:gap-16 desktop:p-8 absolute inset-0 flex items-end justify-end gap-4 p-6",children:t("button",{type:"button","aria-label":R?"Pause video":"Play video",onClick:$,className:a("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",p?.mediaPlayButton),children:R?t(ce,{}):t(le,{})})})]}),d("div",{ref:I,className:a("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",p?.products),children:[V&&t(E,{as:"h2",size:3,className:a("scene-shelf-v2-products-title text-info-primary",p?.productsTitle),html:V}),t("div",{className:"tablet:hidden grid grid-cols-2 gap-3",children:(()=>{const i=C!==void 0&&C>0&&s.length>F,g=i&&!c?s.slice(0,F):s;return d(de,{children:[g.map((w,D)=>t(j,{isShowTag:m.isShowTag??!0,product:w,onImageClick:S,onProductImageClick:P,onLearnMore:k,onShopNow:h,onAddToCart:y,secondaryButtonText:N,secondaryButtonFun:L,primaryButtonText:B,primaryButtonFun:M,classNames:p,theme:r,index:D},w.productKey)),i&&t("div",{className:"col-span-2 mt-6 flex justify-center",children:d("button",{type:"button",onClick:()=>v(w=>!w),className:"text-info-primary hover:text-brand-0 flex items-center gap-2 text-[14px] font-bold transition-colors","aria-expanded":c,children:[c?z?.viewLessLabel??"View Less":z?.viewMoreLabel??"View More",t("svg",{className:a("size-4 transition-transform",c&&"rotate-180"),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:t("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})]})})]})})()}),t("div",{className:"tablet:block hidden",children:t("div",{className:"relative",children:t(Y,{slidesPerView:"auto",observer:!0,observeParents:!0,modules:[ee],mousewheel:{enabled:!0,forceToAxis:!0,sensitivity:1},className:"!overflow-visible",breakpoints:{768:{spaceBetween:16,slidesPerView:s.length>3?2.3:2},1024:{spaceBetween:16,slidesPerView:s.length>3?2.8:3},1440:{spaceBetween:16,slidesPerView:s.length>4?3.8:4},1920:{spaceBetween:16,slidesPerView:s.length>4?3.8:4}},children:s.map((i,g)=>t(Z,{className:a("!h-auto ",p.productCardSlideWrapper),children:t(j,{product:i,isShowTag:m.isShowTag??!0,onImageClick:S,onProductImageClick:P,onLearnMore:k,onShopNow:h,onAddToCart:y,secondaryButtonText:N,secondaryButtonFun:L,primaryButtonText:B,primaryButtonFun:M,classNames:p,theme:r,index:g})},i.productKey))})})})]})]})});K.displayName="SceneShelfV2";var _e=te(K);export{j as SceneShelfV2ProductCard,_e as default};
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 | 'productCardPriceLabel'\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 /** \u4EF7\u683C\u6807\u7B7E\u6587\u672C\uFF08\u5982 \"Plus Member Price\"\uFF09 */\n priceLabel?: 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 /** @deprecated Use `onProductImageClick` instead. */\n onImageClick?: (product: SceneShelfV2Product) => void\n /** \u70B9\u51FB\u4EA7\u54C1\u56FE\u7247\u56DE\u8C03 */\n onProductImageClick?: (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 onProductImageClick?: (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 onProductImageClick,\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 const callback = onProductImageClick ?? onImageClick\n if (!product.href && callback) {\n e.preventDefault()\n }\n callback?.(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, onProductImageClick, 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 (onProductImageClick ?? onImageClick) && 'cursor-pointer transition-opacity hover:opacity-80',\n classNames?.productCardImage\n )}\n onClick={(onProductImageClick ?? onImageClick) ? handleImageClick : undefined}\n role={(onProductImageClick ?? onImageClick) ? 'button' : undefined}\n tabIndex={(onProductImageClick ?? onImageClick) ? 0 : undefined}\n aria-label={(onProductImageClick ?? 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 {product?.priceLabel && (\n <Text\n size={4}\n className={cn(\n 'text-marketing-1 desktop:text-[16px] lg-desktop:text-[18px] text-[14px]',\n classNames?.productCardPriceLabel\n )}\n >\n {product.priceLabel}\n </Text>\n )}\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 {\n className,\n classNames = {},\n data,\n onPlayClick,\n onImageClick,\n onProductImageClick,\n onLearnMore,\n onShopNow,\n onAddToCart,\n ...props\n },\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 onProductImageClick={onProductImageClick}\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 onProductImageClick={onProductImageClick}\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 | 'productCardPriceLabel'\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 /** \u4EF7\u683C\u6807\u7B7E\u6587\u672C\uFF08\u5982 \"Plus Member Price\"\uFF09 */\n priceLabel?: 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 /** @deprecated Use `onProductImageClick` instead. */\n onImageClick?: (product: SceneShelfV2Product) => void\n /** \u70B9\u51FB\u4EA7\u54C1\u56FE\u7247\u56DE\u8C03 */\n onProductImageClick?: (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 onProductImageClick?: (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 onProductImageClick,\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 const callback = onProductImageClick ?? onImageClick\n if (!product.href && callback) {\n e.preventDefault()\n }\n callback?.(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, onProductImageClick, 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 (onProductImageClick ?? onImageClick) && 'cursor-pointer transition-opacity hover:opacity-80',\n classNames?.productCardImage\n )}\n onClick={(onProductImageClick ?? onImageClick) ? handleImageClick : undefined}\n role={(onProductImageClick ?? onImageClick) ? 'button' : undefined}\n tabIndex={(onProductImageClick ?? onImageClick) ? 0 : undefined}\n aria-label={(onProductImageClick ?? 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 {product?.priceLabel && (\n <Text\n size={4}\n className={cn(\n 'text-marketing-1 desktop:text-[16px] lg-desktop:text-[18px] text-[14px]',\n classNames?.productCardPriceLabel\n )}\n >\n {product.priceLabel}\n </Text>\n )}\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:w-auto laptop:flex-1 w-full min-w-0 whitespace-normal text-center\"\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:w-auto laptop:flex-1 w-full min-w-0 whitespace-normal text-center\"\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 {\n className,\n classNames = {},\n data,\n onPlayClick,\n onImageClick,\n onProductImageClick,\n onLearnMore,\n onShopNow,\n onAddToCart,\n ...props\n },\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 onProductImageClick={onProductImageClick}\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 onProductImageClick={onProductImageClick}\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": "aAyJI,OAqiBY,YAAAA,GAriBZ,OAAAC,EAKF,QAAAC,MALE,oBAvJJ,UAAYC,MAAW,QACvB,OAAS,MAAAC,EAAI,oBAAAC,MAAwB,yBACrC,OAAS,WAAAC,EAAS,QAAAC,EAAM,SAAAC,EAAO,UAAAC,EAAQ,WAAAC,MAAe,4BACtD,OAAOC,MAAW,oBAElB,OAAS,UAAAC,EAAQ,eAAAC,MAAmB,eACpC,OAAS,cAAAC,OAAkB,iBAC3B,MAAO,aACP,MAAO,wBACP,OAAS,cAAAC,OAAkB,yBAC3B,OAAS,mBAAAC,OAAuB,iCAChC,OAAS,eAAAC,OAAmB,6BAC5B,OAAS,mBAAAC,OAAuB,iCAChC,OAAS,eAAAC,OAAmB,8BAC5B,OAAS,kBAAAC,MAAsB,2BAC/B,OAAS,WAAAC,MAAe,wBAExB,MAAMC,GAAgB,QAChBC,GAAgB,iBAmIhBC,GAAW,IACfvB,EAAC,OAAI,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,MAAM,6BAA6B,cAAY,OACzG,SAAAA,EAAC,QAAK,EAAE,8BAA8B,KAAK,QAAQ,EACrD,EAGIwB,GAAY,IAChBvB,EAAC,OAAI,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,MAAM,6BAA6B,cAAY,OACzG,UAAAD,EAAC,QAAK,EAAE,IAAI,EAAE,IAAI,MAAM,IAAI,OAAO,KAAK,GAAG,IAAI,KAAK,QAAQ,EAC5DA,EAAC,QAAK,EAAE,KAAK,EAAE,IAAI,MAAM,IAAI,OAAO,KAAK,GAAG,IAAI,KAAK,QAAQ,GAC/D,EAyBIyB,EAAmBvB,EAAM,KAC7B,CAAC,CACC,QAAAwB,EACA,UAAAC,EAAY,GACZ,aAAAC,EACA,oBAAAC,EACA,YAAAC,EACA,UAAAC,EACA,YAAAC,EACA,oBAAAC,EACA,mBAAAC,EACA,kBAAAC,EACA,iBAAAC,EACA,WAAAC,EACA,UAAAC,EACA,MAAAC,EACA,MAAAC,CACF,IAA6B,CAC3B,KAAM,CAAE,OAAAC,EAAS,KAAM,aAAAC,CAAa,EAAIvB,EAAe,EACjD,CAACwB,EAAgBC,CAAiB,EAAI1C,EAAM,SAAS,EAAK,EAC1D,CAAC2C,EAAkBC,CAAmB,EAAI5C,EAAM,SAAS,EAAK,EAE9D6C,EAAYL,GAAc,UAG1BM,EAAoB9C,EAAM,YAC9B,MAAO+C,EAAgCC,IAAyC,CAC9E,GAAI,CAACD,EAAW,OAEhB,MAAME,EAAaD,IAAe,UAAYN,EAAoBE,EAClEK,EAAW,EAAI,EACf,GAAI,CACF,OAAQF,EAAW,CACjB,IAAK,SACH,MAAMlB,IAAYL,CAAO,EACzB,MACF,IAAK,UACH,MAAMM,IAAcN,CAAO,EAC3B,MACF,IAAK,YACH,MAAMI,IAAcJ,GAAS,MAAQ,EAAE,EACvC,MACF,QACE,KACJ,CACF,QAAE,CACAyB,EAAW,EAAK,CAClB,CACF,EACA,CAACrB,EAAaC,EAAWC,EAAaN,CAAO,CAC/C,EAEM0B,EAAgBlD,EAAM,YAC1B,IAAM8C,EAAkBZ,EAAkB,SAAS,EACnD,CAACY,EAAmBZ,CAAgB,CACtC,EACMiB,EAAkBnD,EAAM,YAC5B,IAAM8C,EAAkBd,EAAoB,WAAW,EACvD,CAACc,EAAmBd,CAAkB,CACxC,EAEMoB,EAAmBpD,EAAM,YAC5BqD,GAAwB,CACvB,MAAMC,EAAW3B,GAAuBD,EACpC,CAACF,EAAQ,MAAQ8B,GACnBD,EAAE,eAAe,EAEnBC,IAAW9B,CAAO,EAClBN,EAAQ,CACN,MAAO,WACP,WAAY,cACZ,eAAgB,yBAChB,WAAY2B,EACZ,MAAO,CACL,CACE,QAASrB,EAAQ,IACjB,UAAWA,EAAQ,aAAeA,EAAQ,MAC1C,aAAcA,EAAQ,UACtB,MAAOA,EAAQ,aACf,MAAOc,CACT,CACF,CACF,CAAC,CACH,EACA,CAACA,EAAOZ,EAAcC,EAAqBkB,EAAWrB,CAAO,CAC/D,EAEA,OACEzB,EAAC,OACC,UAAWE,EACT,sMACAmC,EACAD,GAAY,YACZ,CACE,2BAA4BE,IAAU,MACxC,CACF,EAGC,UAAAb,EAAQ,KACP1B,EAAC,KACC,KAAMI,EACJc,GAAYQ,EAAQ,KAAMqB,EAAY,IAAM1B,GAAgB,IAAMC,EAAa,EAC/EmB,CACF,EACA,QAASa,EACT,UAAWnD,EACT,gMACAkC,GAAY,gBACd,EACA,aAAY,QAAQX,EAAQ,KAAK,GAEjC,SAAA1B,EAACS,EAAA,CACC,OAAQiB,EAAQ,SAChB,IAAKA,EAAQ,SACb,UAAU,YACV,aAAa,iBACf,EACF,EAEA1B,EAAC,OACC,UAAWG,EACT,8JACC0B,GAAuBD,IAAiB,qDACzCS,GAAY,gBACd,EACA,QAAUR,GAAuBD,EAAgB0B,EAAmB,OACpE,KAAOzB,GAAuBD,EAAgB,SAAW,OACzD,SAAWC,GAAuBD,EAAgB,EAAI,OACtD,aAAaC,GAAuBD,EAAgB,QAAQF,EAAQ,KAAK,GAAK,OAE9E,SAAA1B,EAACS,EAAA,CACC,OAAQiB,EAAQ,SAChB,IAAKA,EAAQ,SACb,UAAU,YACV,aAAa,iBACf,EACF,EAIFzB,EAAC,OAAI,UAAU,kEAEb,UAAAA,EAAC,OAAI,UAAU,sBACb,UAAAD,EAAC,OACC,UAAWG,EACT,qEACAkC,GAAY,eACd,EAEC,SAAAV,GACCD,GAAS,MAAM,IAAI,CAAC+B,EAAKC,IACvB1D,EAACO,EAAA,CAAgB,QAASkD,EAAI,SAAW,UAAW,KAAK,KAAK,UAAU,GACrE,SAAAA,EAAI,OADKC,CAEZ,CACD,EACL,EAEA1D,EAACK,EAAA,CACC,GAAG,KACH,KAAM,EACN,UAAWF,EACT,4GACAkC,GAAY,gBACd,EAEC,SAAAX,EAAQ,aAAeA,EAAQ,MAClC,GAEEA,EAAQ,oBAAsBA,EAAQ,cACtC1B,EAACM,EAAA,CACC,GAAG,IACH,KAAM,EACN,UAAWH,EACT,uIACAkC,GAAY,sBACd,EAEC,SAAAX,EAAQ,oBAAsBA,EAAQ,YACzC,GAEJ,EAGAzB,EAAC,OAAI,UAAU,sBAEb,UAAAA,EAAC,OACC,UAAWE,EACT,sEACAkC,GAAY,uBACd,EAEA,UAAArC,EAACK,EAAA,CACC,GAAG,KACH,KAAM,EACN,UAAWF,EACT,8DACAkC,GAAY,uBACd,EAEC,SAAAX,EAAQ,aACX,EACCA,EAAQ,eACP1B,EAACK,EAAA,CACC,GAAG,KACH,KAAM,EACN,UAAWF,EACT,6EACAkC,GAAY,wBACd,EAEC,SAAAX,EAAQ,cACX,GAEJ,EAECA,GAAS,YACR1B,EAACM,EAAA,CACC,KAAM,EACN,UAAWH,EACT,0EACAkC,GAAY,qBACd,EAEC,SAAAX,EAAQ,WACX,GAIAO,GAAuBE,IACvBlC,EAAC,OACC,UAAWE,EACT,+FACAkC,GAAY,kBACd,EAEC,UAAAJ,GACCjC,EAACQ,EAAA,CACC,QAAQ,YACR,UAAU,2EACV,QAAS,IAAM,CACb6C,EAAgB,EAChBjC,EAAQ,CACN,MAAO,WACP,WAAY,kBACZ,iBAAkB,CAChB,WAAY2B,GAAa,YACzB,eAAgB,OAChB,eAAgB,sBAChB,gBAAiBrB,EAAQ,MACzB,sBAAuB,GACvB,YAAaO,EACb,IAAKP,EAAQ,KAAO,GACpB,SAAUc,CACZ,CACF,CAAC,CACH,EACA,SAAUd,EAAQ,SAAWQ,IAAuB,YACpD,QAASW,EAER,SAAAZ,EACH,EAEDE,GACCnC,EAACQ,EAAA,CACC,QAAQ,UACR,UAAU,2EACV,QAAS,IAAM,CACb4C,EAAc,EACdhC,EAAQ,CACN,MAAO,WACP,WAAY,kBACZ,iBAAkB,CAChB,WAAY2B,GAAa,YACzB,eAAgB,OAChB,eAAgB,sBAChB,gBAAiBrB,EAAQ,MACzB,sBAAuB,GACvB,YAAaS,EACb,IAAKT,EAAQ,KAAO,GACpB,SAAUc,CACZ,CACF,CAAC,CACH,EACA,SAAUd,EAAQ,SAAWU,IAAqB,YAClD,QAASO,EAER,SAAAR,EACH,GAEJ,GAEJ,GACF,GACF,CAEJ,CACF,EAEAV,EAAiB,YAAc,2BAM/B,MAAMkC,EAAezD,EAAM,WACzB,CACE,CACE,UAAAoC,EACA,WAAAD,EAAa,CAAC,EACd,KAAAuB,EACA,YAAAC,EACA,aAAAjC,EACA,oBAAAC,EACA,YAAAC,EACA,UAAAC,EACA,YAAAC,EACA,GAAG8B,CACL,EACAC,IACG,CACH,KAAM,CACJ,MAAAxB,EAAQ,QACR,WAAAyB,EACA,cAAAC,EACA,SAAAC,EACA,oBAAAjC,EACA,mBAAAC,EACA,kBAAAC,EACA,iBAAAC,EACA,cAAA+B,EAAgB,EAChB,KAAAC,CACF,EAAIR,EACES,EAAWnE,EAAM,OAAyB,IAAI,EAC9CoE,EAAWpE,EAAM,OAAuB,IAAI,EAC5CqE,EAAoBrE,EAAM,OAAuB,IAAI,EACrD,CAACsE,EAAWC,CAAY,EAAIvE,EAAM,SAAS,EAAK,EAChD,CAACwE,EAAYC,CAAa,EAAIzE,EAAM,SAAS,EAAK,EAClD,CAAE,aAAAwC,CAAa,EAAIvB,EAAe,EAExCH,GAAYsD,EAAU,CACpB,cAAe,QACf,cAAe,oBACjB,CAAC,EAEDrD,GAAgBsD,EAAmB,CACjC,cAAe,QACf,cAAe,qBACf,aAAc,yBACd,MAAOL,EAAS,IAAI,CAACU,EAAMpC,KAAW,CACpC,QAASoC,EAAK,KAAO,GACrB,UAAWA,EAAK,MAChB,aAAcA,EAAK,WAAa,GAChC,MAAOA,EAAK,aACZ,MAAOpC,CACT,EAAE,EACF,QAAS,EACX,CAAC,EAED,MAAMqC,EAAe9D,GAAgB,CACnC,KAAMoD,GAAiB,EACvB,WAAY,CACd,CAAC,EAEKW,EAAW5E,EAAM,QACrB,IACE,CAAC8D,GAAY,GAAIA,GAAY,QAASA,GAAY,OAAQA,GAAY,IAAKA,GAAY,MAAM,EAAE,KAC7Fe,GAASA,GAAO,WAAa,WAC/B,EACF,CAACf,CAAU,CACb,EAEMgB,EAAwB9E,EAAM,YAAY,IAAM,CACpD,MAAM+E,EAAQZ,EAAS,QACnBY,EACEA,EAAM,QACRA,EAAM,KAAK,EACXR,EAAa,EAAI,EACjBZ,IAAc,EAAI,IAElBoB,EAAM,MAAM,EACZR,EAAa,EAAK,EAClBZ,IAAc,EAAK,GAGrBA,IAAc,EAAI,EAEpBzC,EAAQ,CACN,MAAO,WACP,WAAY,kBACZ,iBAAkB,CAChB,WAAYsB,GAAc,UAC1B,eAAgB,QAChB,eAAgB,qBAChB,SAAU,EACV,YAAasB,GAAY,IAAI,EAC/B,CACF,CAAC,CACH,EAAG,CAACH,EAAaG,GAAY,IAAI,GAAItB,GAAc,SAAS,CAAC,EAG7D,OAAAxC,EAAM,UAAU,IAAM,CACpB,MAAM+E,EAAQZ,EAAS,QACvB,GAAI,CAACY,GAAS,CAACH,EAAU,OAEzB,MAAMI,EAAW,IAAI,qBACnBC,GAAW,CACTA,EAAQ,QAAQC,GAAS,CACnBA,EAAM,eAERH,EAAM,KAAK,EAAE,MAAMI,GAAS,CAE1B,QAAQ,KAAK,yBAA0BA,CAAK,CAC9C,CAAC,EAGDJ,EAAM,MAAM,CAEhB,CAAC,CACH,EACA,CACE,UAAW,EACb,CACF,EAEA,OAAAC,EAAS,QAAQD,CAAK,EAEf,IAAM,CACXC,EAAS,WAAW,CACtB,CACF,EAAG,CAAC,CAAC,EAGHjF,EAAC,OACE,GAAG6D,EACJ,IAAKC,EACL,UAAW5D,EACT,6CACA,CAAE,YAAaoC,IAAU,MAAO,EAChCD,EACAD,GAAY,IACd,EAGA,UAAApC,EAAC,OACC,UAAWE,EACT,0LACAkC,GAAY,KACd,EACA,IAAKiC,EAEL,UAAAtE,EAACU,EAAA,CACC,QAASsD,GAAY,GACrB,aAAcA,GAAY,QAC1B,YAAaA,GAAY,OACzB,SAAUA,GAAY,IACtB,YAAaA,GAAY,OACzB,UAAU,YACV,eAAe,0CACf,SAAUK,EACV,YAAa,IAAMI,EAAa,EAAI,EACpC,aAAc,IAAMA,EAAa,EAAK,EACtC,aAAc,IAAMA,EAAa,EAAK,EACxC,EAEAzE,EAAC,OACC,cAAY,OACZ,UAAWG,EACT,oEACAkC,GAAY,YACd,EACF,EAGCyC,GACC9E,EAAC,OAAI,UAAU,mFACb,SAAAA,EAAC,UACC,KAAK,SACL,aAAYwE,EAAY,cAAgB,aACxC,QAASQ,EACT,UAAW7E,EACT,kJACAkC,GAAY,eACd,EAEC,SAAAmC,EAAYxE,EAACwB,GAAA,EAAU,EAAKxB,EAACuB,GAAA,EAAS,EACzC,EACF,GAEJ,EAGAtB,EAAC,OACC,IAAKsE,EACL,UAAWpE,EACT,oKACAkC,GAAY,QACd,EAEC,UAAA4B,GACCjE,EAACK,EAAA,CACC,GAAG,KACH,KAAM,EACN,UAAWF,EAAG,kDAAmDkC,GAAY,aAAa,EAC1F,KAAM4B,EACR,EAIFjE,EAAC,OAAI,UAAU,uCACX,cAAM,CACN,MAAMsF,EACJnB,IAAkB,QAAaA,EAAgB,GAAKD,EAAS,OAASW,EAClEU,EAAoBD,GAAsB,CAACZ,EAAaR,EAAS,MAAM,EAAGW,CAAY,EAAIX,EAEhG,OACEjE,EAAAF,GAAA,CACG,UAAAwF,EAAkB,IAAI,CAAC7D,EAASc,IAC/BxC,EAACyB,EAAA,CAEC,UAAWmC,EAAK,WAAa,GAC7B,QAASlC,EACT,aAAcE,EACd,oBAAqBC,EACrB,YAAaC,EACb,UAAWC,EACX,YAAaC,EACb,oBAAqBC,EACrB,mBAAoBC,EACpB,kBAAmBC,EACnB,iBAAkBC,EAClB,WAAYC,EACZ,MAAOE,EACP,MAAOC,GAdFd,EAAQ,UAef,CACD,EACA4D,GACCtF,EAAC,OAAI,UAAU,sCACb,SAAAC,EAAC,UACC,KAAK,SACL,QAAS,IAAM0E,EAAca,GAAQ,CAACA,CAAI,EAC1C,UAAU,uGACV,gBAAed,EAEd,UAAAA,EAAcN,GAAM,eAAiB,YAAgBA,GAAM,eAAiB,YAC7EpE,EAAC,OACC,UAAWG,EAAG,8BAA+BuE,GAAc,YAAY,EACvE,KAAK,OACL,OAAO,eACP,QAAQ,YAER,SAAA1E,EAAC,QAAK,cAAc,QAAQ,eAAe,QAAQ,YAAa,EAAG,EAAE,iBAAiB,EACxF,GACF,EACF,GAEJ,CAEJ,GAAG,EACL,EAGAA,EAAC,OAAI,UAAU,sBACb,SAAAA,EAAC,OAAI,UAAU,WACb,SAAAA,EAACW,EAAA,CACC,cAAc,OACd,SAAQ,GACR,eAAc,GACd,QAAS,CAACE,EAAU,EACpB,WAAY,CACV,QAAS,GACT,YAAa,GACb,YAAa,CACf,EACA,UAAU,oBACV,YAAa,CACX,IAAK,CACH,aAAc,GACd,cAAeqD,EAAS,OAAS,EAAI,IAAM,CAC7C,EACA,KAAM,CACJ,aAAc,GACd,cAAeA,EAAS,OAAS,EAAI,IAAM,CAC7C,EACA,KAAM,CACJ,aAAc,GACd,cAAeA,EAAS,OAAS,EAAI,IAAM,CAC7C,EACA,KAAM,CACJ,aAAc,GACd,cAAeA,EAAS,OAAS,EAAI,IAAM,CAC7C,CACF,EAEC,SAAAA,EAAS,IAAI,CAACxC,EAASc,IACtBxC,EAACY,EAAA,CAAqC,UAAWT,EAAG,WAAYkC,EAAW,uBAAuB,EAChG,SAAArC,EAACyB,EAAA,CACC,QAASC,EACT,UAAWkC,EAAK,WAAa,GAC7B,aAAchC,EACd,oBAAqBC,EACrB,YAAaC,EACb,UAAWC,EACX,YAAaC,EACb,oBAAqBC,EACrB,mBAAoBC,EACpB,kBAAmBC,EACnB,iBAAkBC,EAClB,WAAYC,EACZ,MAAOE,EACP,MAAOC,EACT,GAhBgBd,EAAQ,UAiB1B,CACD,EACH,EACF,EACF,GACF,GACF,CAEJ,CACF,EAEAiC,EAAa,YAAc,eAC3B,IAAO8B,GAAQ3E,GAAW6C,CAAY",
6
6
  "names": ["Fragment", "jsx", "jsxs", "React", "cn", "getLocalizedPath", "Heading", "Text", "Badge", "Button", "Picture", "Media", "Swiper", "SwiperSlide", "Mousewheel", "withLayout", "useGridRowCount", "useExposure", "useViewItemList", "trackUrlRef", "useAiuiContext", "gaTrack", "componentType", "componentName", "PlayIcon", "PauseIcon", "ProductCardInner", "product", "isShowTag", "onImageClick", "onProductImageClick", "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", "callback", "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", "shouldShowViewMore", "displayedProducts", "prev", "SceneShelfV2_default"]
7
7
  }