1import{r as m,k as n,cv as J,cx as E,dg as B,dh as Y,di as V,dj as q,bP as z,cw as X,y as K}from"./index-Bn1bbOAe.js";import{u as Q,C as Z,T as nn,P as en,a as tn,b as on,c as sn}from"./useComponentProps-CkrCaLvB.js";import{C as an}from"./Customize-DBLruEgy.js";import{P as b}from"./PreviewSwitch-BKSQdkt2.js";import{D as rn}from"./Dependencies-BritF_2p.js";import{u as cn}from"./useForceRerender-CvsfwHEi.js";import{P as T}from"./PreviewSlider-CJmB9pdC.js";import"./index-CKdJydTQ.js";import"./backgroundThemeProps-BAOOEp3Q.js";import"./ShikiCode-CUach_VP.js";import"./aiExport--nnywH9U.js";import"./IconSelect-CgfYlisg.js";import"./sparkles-DtoGwhqa.js";import"./maximize-2-DQy3aI7-.js";import"./preview-slider-B9GA5uEa.js";import"./copy--0PRdOLE.js";import"./useScrubGesture-BHz_XSAB.js";const ln=[{title:"Text Animations",description:"Cool text animations for your projects.",id:1,icon:n.jsx(B,{className:"carousel-icon"})},{title:"Animations",description:"Smooth animations for your projects.",id:2,icon:n.jsx(Y,{className:"carousel-icon"})},{title:"Components",description:"Reusable components for your projects.",id:3,icon:n.jsx(V,{className:"carousel-icon"})},{title:"Backgrounds",description:"Beautiful backgrounds and patterns for your projects.",id:4,icon:n.jsx(q,{className:"carousel-icon"})},{title:"Common UI",description:"Common UI components are coming soon!",id:5,icon:n.jsx(z,{className:"carousel-icon"})}],N=0,w=500,L=16,dn={type:"spring",stiffness:300,damping:30};function mn({item:e,index:a,itemWidth:x,round:u,trackItemOffset:d,x:i,transition:f}){const g=[-(a+1)*d,-a*d,-(a-1)*d],c=X(i,g,[90,0,-90],{clamp:!1});return n.jsxs(E.div,{className:`carousel-item ${u?"round":""}`,style:{width:x,height:u?x:"100%",rotateY:c,...u&&{borderRadius:"50%"}},transition:f,children:[n.jsx("div",{className:`carousel-item-header ${u?"round":""}`,children:n.jsx("span",{className:"carousel-icon-container",children:e.icon})}),n.jsxs("div",{className:"carousel-item-content",children:[n.jsx("div",{className:"carousel-item-title",children:e.title}),n.jsx("p",{className:"carousel-item-description",children:e.description})]})]},`${(e==null?void 0:e.id)??a}-${a}`)}function un({items:e=ln,baseWidth:a=300,autoplay:x=!1,autoplayDelay:u=3e3,pauseOnHover:d=!1,loop:i=!1,round:f=!1}){const h=a-32,c=h+L,l=m.useMemo(()=>i?e.length===0?[]:[e[e.length-1],...e,e[0]]:e,[e,i]),[r,p]=m.useState(i?1:0),o=J(0),[C,O]=m.useState(!1),[M,y]=m.useState(!1),[D,v]=m.useState(!1),R=m.useRef(null);m.useEffect(()=>{if(d&&R.current){const s=R.current,t=()=>O(!0),I=()=>O(!1);return s.addEventListener("mouseenter",t),s.addEventListener("mouseleave",I),()=>{s.removeEventListener("mouseenter",t),s.removeEventListener("mouseleave",I)}}},[d]),m.useEffect(()=>{if(!x||l.length<=1||d&&C)return;const s=setInterval(()=>{p(t=>Math.min(t+1,l.length-1))},u);return()=>clearInterval(s)},[x,u,C,d,l.length]),m.useEffect(()=>{const s=i?1:0;p(s),o.set(-s*c)},[e.length,i,c,o]),m.useEffect(()=>{!i&&r>l.length-1&&p(Math.max(0,l.length-1))},[l.length,i,r]);const P=M?{duration:0}:dn,H=()=>{v(!0)},j=()=>
1{if(!i||l.length<=1){v(!1);return}const s=l.length-1;if(r===s){y(!0);const t=1;p(t),o.set(-t*c),requestAnimationFrame(()=>{y(!1),v(!1)});return}if(r===0){y(!0);const t=e.length;p(t),o.set(-t*c),requestAnimationFrame(()=>{y(!1),v(!1)});return}v(!1)},$=(s,t)=>{const{offset:I,velocity:A}=t,k=I.x<-N||A.x<-w?1:I.x>N||A.x>w?-1:0;k!==0&&p(_=>{const G=_+k,U=l.length-1;return Math.max(0,Math.min(G,U))})},W=i?{}:{dragConstraints:{left:-c*Math.max(l.length-1,0),right:0}},F=e.length===0?0:i?(r-1+e.length)%e.length:Math.min(r,e.length-1);return n.jsxs("div",{ref:R,className:`carousel-container ${f?"round":""}`,style:{width:`${a}px`,...f&&{height:`${a}px`,borderRadius:"50%"}},children:[n.jsx(E.div,{className:"carousel-track",drag:D?!1:"x",...W,style:{width:h,gap:`${L}px`,perspective:1e3,perspectiveOrigin:`${r*c+h/2}px 50%`,x:o},onDragEnd:$,animate:{x:-(r*c)},transition:P,onAnimationStart:H,onAnimationComplete:j,children:l.map((s,t)=>n.jsx(mn,{item:s,index:t,itemWidth:h,round:f,trackItemOffset:c,x:o,transition:P},`${(s==null?void 0:s.id)??t}-${t}`))}),n.jsx("div",{className:`carousel-indicators-container ${f?"round":""}`,children:n.jsx("div",{className:"carousel-indicators",children:e.map((s,t)=>n.jsx(E.button,{type:"button",className:`carousel-indicator ${F===t?"active":"inactive"}`,"aria-label":`Go to slide ${t+1}`,"aria-current":F===t,animate:{scale:F===t?1.2:1},onClick:()=>p(i?t+1:t),transition:{duration:.15}},t))})})]})}const fn=`'use client'; 2 3import { useEffect, useMemo, useRef, useState } from 'react'; 4import { motion, useMotionValue, useTransform } from 'motion/react'; 5// replace icons with your own if needed 6import { FiCircle, FiCode, FiFileText, FiLayers, FiLayout } from 'react-icons/fi'; 7 8import './Carousel.css'; 9 10const DEFAULT_ITEMS = [ 11 { 12 title: 'Text Animations', 13 description: 'Cool text animations for your projects.', 14 id: 1, 15 icon: <FiFileText className="carousel-icon" /> 16 }, 17 { 18 title: 'Animations', 19 description: 'Smooth animations for your projects.', 20 id: 2, 21 icon: <FiCircle className="carousel-icon" /> 22 }, 23 { 24 title: 'Components', 25 description: 'Reusable components for your projects.', 26 id: 3, 27 icon: <FiLayers className="carousel-icon" /> 28 }, 29 { 30 title: 'Backgrounds', 31 description: 'Beautiful backgrounds and patterns for your projects.', 32 id: 4, 33 icon: <FiLayout className="carousel-icon" /> 34 }, 35 { 36 title: 'Common UI', 37 description: 'Common UI components are coming soon!', 38 id: 5, 39 icon: <FiCode className="carousel-icon" /> 40 } 41]; 42 43const DRAG_BUFFER = 0; 44const VELOCITY_THRESHOLD = 500; 45const GAP = 16; 46const SPRING_OPTIONS = { type: 'spring', stiffness: 300, damping: 30 }; 47 48function CarouselItem({ item, index, itemWidth, round, trackItemOffset, x, transition }) { 49 const range = [-(index + 1) * trackItemOffset, -index * trackItemOffset, -(index - 1) * trackItemOffset]; 50 const outputRange = [90, 0, -90]; 51 const rotateY = useTransform(x, range, outputRange, { clamp: false }); 52 53 return ( 54 <motion.div 55 key={\`\${item?.id ?? index}-\${index}\`} 56 className={\`carousel-item \${round ? 'round' : ''}\`} 57 style={{ 58 width: itemWidth, 59 height: round ? itemWidth : '100%', 60 rotateY: rotateY, 61 ...(round && { borderRadius: '50%' }) 62 }} 63 transition={transition} 64 > 65 <div className={\`carousel-item-header \${round ? 'round' : ''}\`}> 66 <span className="carousel-icon-container">{item.icon}</span> 67 </div> 68 <div className="carousel-item-content"> 69 <div className="carousel-item-title">{item.title}</div> 70 <p className="carousel-item-description">{item.description}</p> 71 </div> 72 </motion.div> 73 ); 74} 75 76export default function Carousel({ 77 items = DEFAULT_ITEMS, 78 baseWidth = 300, 79 autoplay = false, 80 autoplayDelay = 3000, 81 pauseOnHover = false, 82 loop = false, 83 round = false 84}) { 85 const containerPadding = 16; 86 const itemWidth = baseWidth - containerPadding * 2; 87 const trackItemOffset = itemWidth + GAP; 88 const itemsForRender = useMemo(() => { 89 if (!loop) return items; 90 if (items.length === 0) return []; 91 return [items[items.length - 1], ...items, items[0]]; 92 }, [items, loop]); 93 94 const [position, setPosition] = useState(loop ? 1 : 0); 95 const x = useMotionValue(0); 96 const [isHovered, setIsHovered] = useState(false); 97 const [isJumping, setIsJumping] = useState(false); 98 const [isAnimating, setIsAnimating] = useState(false); 99 100 const containerRef = useRef(null); 101 useEffect(() => { 102 if (pauseOnHover && containerRef.current) { 103 const container = containerRef.current; 104 const handleMouseEnter = () => setIsHovered(true); 105 const handleMouseLeave = () => setIsHovered(false); 106 container.addEventListener('mouseenter', handleMouseEnter); 107 container.addEventListener('mouseleave', handleMouseLeave); 108 return () => { 109 container.removeEventListener('mouseenter', handleMouseEnter); 110 container.removeEventListener('mouseleave', handleMouseLeave); 111 }; 112 } 113 }, [pauseOnHover]); 114 115 useEffect(() => { 116 if (!autoplay || itemsForRender.length <= 1) return undefined; 117 if (pauseOnHover && isHovered) return undefined; 118 119 const timer = setInterval(() => { 120 setPosition(prev => Math.min(prev + 1, itemsForRender.length - 1)); 121 }, autoplayDelay); 122 123 return () => clearInterval(timer); 124 }, [autoplay, autoplayDelay, isHovered, pauseOnHover, itemsForRender.length]); 125 126 useEffect(() => { 127 const startingPosition = loop ? 1 : 0; 128 setPosition(startingPosition); 129 x.set(-startingPosition * trackItemOffset); 130 }, [items.length, loop, trackItemOffset, x]); 131 132 useEffect(() => { 133 if (!loop && position > itemsForRender.length - 1) { 134 setPosition(Math.max(0, itemsForRender.length - 1)); 135 } 136 }, [itemsForRender.length, loop, position]); 137 138 const effectiveTransition = isJumping ? { duration: 0 } : SPRING_OPTIONS; 139 140 const handleAnimationStart = () => { 141 setIsAnimating(true); 142 }; 143 144 const handleAnimationComplete = () => { 145 if (!loop || itemsForRender.length <= 1) { 146 setIsAnimating(false); 147 return; 148 } 149 const lastCloneIndex = itemsForRender.length - 1; 150 151 if (position === lastCloneIndex) { 152 setIsJumping(true); 153 const target = 1; 154 setPosition(target); 155 x.set(-target * trackItemOffset); 156 requestAnimationFrame(() => { 157 setIsJumping(false); 158 setIsAnimating(false); 159 }); 160 return; 161 } 162 163 if (position === 0) { 164 setIsJumping(true); 165 const target = items.length; 166 setPosition(target); 167 x.set(-target * trackItemOffset); 168 requestAnimationFrame(() => { 169 setIsJumping(false); 170 setIsAnimating(false); 171 }); 172 return; 173 } 174 175 setIsAnimating(false); 176 }; 177 178 const handleDragEnd = (_, info) => { 179 const { offset, velocity } = info; 180 const direction = 181 offset.x < -DRAG_BUFFER || velocity.x < -VELOCITY_THRESHOLD 182 ? 1 183 : offset.x > DRAG_BUFFER || velocity.x > VELOCITY_THRESHOLD 184 ? -1 185 : 0; 186 187 if (direction === 0) return; 188 189 setPosition(prev => { 190 const next = prev + direction; 191 const max = itemsForRender.length - 1;
192 return Math.max(0, Math.min(next, max)); 193 }); 194 }; 195 196 const dragProps = loop 197 ? {} 198 : { 199 dragConstraints: { 200 left: -trackItemOffset * Math.max(itemsForRender.length - 1, 0), 201 right: 0 202 } 203 }; 204 205 const activeIndex = 206 items.length === 0 ? 0 : loop ? (position - 1 + items.length) % items.length : Math.min(position, items.length - 1); 207 208 return ( 209 <div 210 ref={containerRef} 211 className={\`carousel-container \${round ? 'round' : ''}\`} 212 style={{ 213 width: \`\${baseWidth}px\`, 214 ...(round && { height: \`\${baseWidth}px\`, borderRadius: '50%' }) 215 }} 216 > 217 <motion.div 218 className="carousel-track" 219 drag={isAnimating ? false : 'x'} 220 {...dragProps} 221 style={{ 222 width: itemWidth, 223 gap: \`\${GAP}px\`, 224 perspective: 1000, 225 perspectiveOrigin: \`\${position * trackItemOffset + itemWidth / 2}px 50%\`, 226 x 227 }} 228 onDragEnd={handleDragEnd} 229 animate={{ x: -(position * trackItemOffset) }} 230 transition={effectiveTransition} 231 onAnimationStart={handleAnimationStart} 232 onAnimationComplete={handleAnimationComplete} 233 > 234 {itemsForRender.map((item, index) => ( 235 <CarouselItem 236 key={\`\${item?.id ?? index}-\${index}\`} 237 item={item} 238 index={index} 239 itemWidth={itemWidth} 240 round={round} 241 trackItemOffset={trackItemOffset} 242 x={x} 243 transition={effectiveTransition} 244 /> 245 ))} 246 </motion.div> 247 <div className={\`carousel-indicators-container \${round ? 'round' : ''}\`}> 248 <div className="carousel-indicators"> 249 {items.map((_, index) => ( 250 <motion.button 251 type="button" 252 key={index} 253 className={\`carousel-indicator \${activeIndex === index ? 'active' : 'inactive'}\`} 254 aria-label={\`Go to slide \${index + 1}\`} 255 aria-current={activeIndex === index} 256 animate={{ 257 scale: activeIndex === index ? 1.2 : 1 258 }} 259 onClick={() => setPosition(loop ? index + 1 : index)} 260 transition={{ duration: 0.15 }} 261 /> 262 ))} 263 </div> 264 </div> 265 </div> 266 ); 267} 268`,pn=`.carousel-container { 269 position: relative; 270 overflow: hidden; 271 border: 1px solid #555; 272 border-radius: 24px; 273 padding: 16px; 274 --outer-r: 24px; 275 --p-distance: 12px; 276} 277 278.carousel-track { 279 display: flex; 280} 281 282.carousel-item { 283 position: relative; 284 display: flex; 285 flex-shrink: 0; 286 flex-direction: column; 287 align-items: flex-start; 288 justify-content: space-between; 289 border: 1px solid #555; 290 border-radius: calc(var(--outer-r) - var(--p-distance)); 291 background-color: #1B1722; 292 overflow: hidden; 293 cursor: grab; 294} 295 296.carousel-item:active { 297 cursor: grabbing; 298} 299 300.carousel-container.round { 301 border: 1px solid #555; 302} 303 304.carousel-item.round { 305 background-color: #1B1722; 306 position: relative; 307 bottom: 0.1em; 308 border: 1px solid #555; 309 justify-content: center; 310 align-items: center; 311 text-align: center; 312} 313 314.carousel-item-header.round { 315 padding: 0; 316 margin: 0; 317} 318 319.carousel-indicators-container.round { 320 position: absolute; 321 z-index: 2; 322 bottom: 3em; 323 left: 50%; 324 transform: translateX(-50%); 325} 326 327.carousel-indicator.active { 328 background-color: #333333; 329} 330 331.carousel-indicator.inactive { 332 background-color: rgba(51, 51, 51, 0.4); 333} 334 335.carousel-item-header { 336 margin-bottom: 16px; 337 padding: 20px; 338 padding-top: 20px; 339} 340 341.carousel-icon-container { 342 display: flex; 343 height: 28px; 344 width: 28px; 345 align-items: center; 346 justify-content: center; 347 border-radius: 50%; 348 background-color: #fff; 349} 350 351.carousel-icon { 352 height: 16px; 353 width: 16px; 354 color: #120F17; 355} 356 357.carousel-item-content { 358 padding: 20px; 359 padding-bottom: 20px; 360} 361 362.carousel-item-title { 363 margin-bottom: 4px; 364 font-weight: 900; 365 font-size: 18px; 366 color: #fff; 367} 368 369.carousel-item-description { 370 font-size: 14px; 371 color: #fff; 372} 373 374.carousel-indicators-container { 375 display: flex; 376 width: 100%; 377 justify-content: center; 378} 379 380.carousel-indicators { 381 margin-top: 16px; 382 display: flex; 383 width: 150px; 384 justify-content: space-between; 385 padding: 0 32px; 386} 387 388.carousel-indicator { 389 height: 8px; 390 width: 8px; 391 border: none; 392 padding: 0; 393 appearance: none; 394 border-radius: 50%; 395 cursor: pointer; 396 transition: background-color 150ms; 397} 398 399.carousel-indicator:focus-visible { 400 outline: 2px solid #fff; 401 outline-offset: 2px; 402} 403 404.carousel-indicator.active { 405 background-color: #fff; 406} 407 408.carousel-indicator.inactive { 409 background-color: #555; 410} 411`,hn=`'use client'; 412 413import { useEffect, useMemo, useRef, useState } from 'react'; 414import { motion, useMotionValue, useTransform } from 'motion/react'; 415// replace icons with your own if needed 416import { FiCircle, FiCode, FiFileText, FiLayers, FiLayout } from 'react-icons/fi'; 417 418const DEFAULT_ITEMS = [ 419 { 420 title: 'Text Animations', 421 description: 'Cool text animations for your projects.', 422 id: 1, 423 icon: <FiFileText className="h-[16px] w-[16px] text-white" /> 424 }, 425 { 426 title: 'Animations', 427 description: 'Smooth animations for your projects.', 428 id: 2, 429 icon: <FiCircle className="h-[16px] w-[16px] text-white" /> 430 }, 431 { 432 title: 'Components', 433 description: 'Reusable components for your projects.', 434 id: 3, 435 icon: <FiLayers className="h-[16px] w-[16px] text-white" /> 436 }, 437 {
438 title: 'Backgrounds', 439 description: 'Beautiful backgrounds and patterns for your projects.', 440 id: 4, 441 icon: <FiLayout className="h-[16px] w-[16px] text-white" /> 442 }, 443 { 444 title: 'Common UI', 445 description: 'Common UI components are coming soon!', 446 id: 5, 447 icon: <FiCode className="h-[16px] w-[16px] text-white" /> 448 } 449]; 450 451const DRAG_BUFFER = 0; 452const VELOCITY_THRESHOLD = 500; 453const GAP = 16; 454const SPRING_OPTIONS = { type: 'spring', stiffness: 300, damping: 30 }; 455 456function CarouselItem({ item, index, itemWidth, round, trackItemOffset, x, transition }) { 457 const range = [-(index + 1) * trackItemOffset, -index * trackItemOffset, -(index - 1) * trackItemOffset]; 458 const outputRange = [90, 0, -90]; 459 const rotateY = useTransform(x, range, outputRange, { clamp: false }); 460 461 return ( 462 <motion.div 463 key={\`\${item?.id ?? index}-\${index}\`} 464 className={\`relative shrink-0 flex flex-col \${ 465 round 466 ? 'items-center justify-center text-center bg-[#120F17] border-0' 467 : 'items-start justify-between bg-[#222] border border-[#222] rounded-[12px]' 468 } overflow-hidden cursor-grab active:cursor-grabbing\`} 469 style={{ 470 width: itemWidth, 471 height: round ? itemWidth : '100%', 472 rotateY: rotateY, 473 ...(round && { borderRadius: '50%' }) 474 }} 475 transition={transition} 476 > 477 <div className={\`\${round ? 'p-0 m-0' : 'mb-4 p-5'}\`}> 478 <span className="flex h-[28px] w-[28px] items-center justify-center rounded-full bg-[#120F17]"> 479 {item.icon} 480 </span> 481 </div> 482 <div className="p-5"> 483 <div className="mb-1 font-black text-lg text-white">{item.title}</div> 484 <p className="text-sm text-white">{item.description}</p> 485 </div> 486 </motion.div> 487 ); 488} 489 490export default function Carousel({ 491 items = DEFAULT_ITEMS, 492 baseWidth = 300, 493 autoplay = false, 494 autoplayDelay = 3000, 495 pauseOnHover = false, 496 loop = false, 497 round = false 498}) { 499 const containerPadding = 16; 500 const itemWidth = baseWidth - containerPadding * 2; 501 const trackItemOffset = itemWidth + GAP; 502 const itemsForRender = useMemo(() => { 503 if (!loop) return items; 504 if (items.length === 0) return []; 505 return [items[items.length - 1], ...items, items[0]]; 506 }, [items, loop]); 507 508 const [position, setPosition] = useState(loop ? 1 : 0); 509 const x = useMotionValue(0); 510 const [isHovered, setIsHovered] = useState(false); 511 const [isJumping, setIsJumping] = useState(false); 512 const [isAnimating, setIsAnimating] = useState(false); 513 514 const containerRef = useRef(null); 515 useEffect(() => { 516 if (pauseOnHover && containerRef.current) { 517 const container = containerRef.current; 518 const handleMouseEnter = () => setIsHovered(true); 519 const handleMouseLeave = () => setIsHovered(false); 520 container.addEventListener('mouseenter', handleMouseEnter); 521 container.addEventListener('mouseleave', handleMouseLeave); 522 return () => { 523 container.removeEventListener('mouseenter', handleMouseEnter); 524 container.removeEventListener('mouseleave', handleMouseLeave); 525 }; 526 } 527 }, [pauseOnHover]); 528 529 useEffect(() => { 530 if (!autoplay || itemsForRender.length <= 1) return undefined; 531 if (pauseOnHover && isHovered) return undefined; 532 533 const timer = setInterval(() => { 534 setPosition(prev => Math.min(prev + 1, itemsForRender.length - 1)); 535 }, autoplayDelay); 536 537 return () => clearInterval(timer); 538 }, [autoplay, autoplayDelay, isHovered, pauseOnHover, itemsForRender.length]); 539 540 useEffect(() => { 541 const startingPosition = loop ? 1 : 0; 542 setPosition(startingPosition); 543 x.set(-startingPosition * trackItemOffset); 544 }, [items.length, loop, trackItemOffset, x]); 545 546 useEffect(() => { 547 if (!loop && position > itemsForRender.length - 1) { 548 setPosition(Math.max(0, itemsForRender.length - 1)); 549 } 550 }, [itemsForRender.length, loop, position]); 551 552 const effectiveTransition = isJumping ? { duration: 0 } : SPRING_OPTIONS; 553 554 const handleAnimationStart = () => { 555 setIsAnimating(true); 556 }; 557 558 const handleAnimationComplete = () => { 559 if (!loop || itemsForRender.length <= 1) { 560 setIsAnimating(false); 561 return; 562 } 563 const lastCloneIndex = itemsForRender.length - 1; 564 565 if (position === lastCloneIndex) { 566 setIsJumping(true); 567 const target = 1; 568 setPosition(target); 569 x.set(-target * trackItemOffset); 570 requestAnimationFrame(() => { 571 setIsJumping(false); 572 setIsAnimating(false); 573 }); 574 return; 575 } 576 577 if (position === 0) { 578 setIsJumping(true); 579 const target = items.length; 580 setPosition(target); 581 x.set(-target * trackItemOffset); 582 requestAnimationFrame(() => { 583 setIsJumping(false); 584 setIsAnimating(false); 585 }); 586 return; 587 } 588 589 setIsAnimating(false); 590 }; 591 592 const handleDragEnd = (_, info) => { 593 const { offset, velocity } = info; 594 const direction = 595 offset.x < -DRAG_BUFFER || velocity.x < -VELOCITY_THRESHOLD 596 ? 1 597 : offset.x > DRAG_BUFFER || velocity.x > VELOCITY_THRESHOLD 598 ? -1 599 : 0; 600 601 if (direction === 0) return; 602 603 setPosition(prev => { 604 const next = prev + direction; 605 const max = itemsForRender.length - 1;
606 return Math.max(0, Math.min(next, max)); 607 }); 608 }; 609 610 const dragProps = loop 611 ? {} 612 : { 613 dragConstraints: { 614 left: -trackItemOffset * Math.max(itemsForRender.length - 1, 0), 615 right: 0 616 } 617 }; 618 619 const activeIndex = 620 items.length === 0 ? 0 : loop ? (position - 1 + items.length) % items.length : Math.min(position, items.length - 1); 621 622 return ( 623 <div 624 ref={containerRef} 625 className={\`relative overflow-hidden p-4 \${ 626 round ? 'rounded-full border border-white' : 'rounded-[24px] border border-[#222]' 627 }\`} 628 style={{ 629 width: \`\${baseWidth}px\`, 630 ...(round && { height: \`\${baseWidth}px\` }) 631 }} 632 > 633 <motion.div 634 className="flex" 635 drag={isAnimating ? false : 'x'} 636 {...dragProps} 637 style={{ 638 width: itemWidth, 639 gap: \`\${GAP}px\`, 640 perspective: 1000, 641 perspectiveOrigin: \`\${position * trackItemOffset + itemWidth / 2}px 50%\`, 642 x 643 }} 644 onDragEnd={handleDragEnd} 645 animate={{ x: -(position * trackItemOffset) }} 646 transition={effectiveTransition} 647 onAnimationStart={handleAnimationStart} 648 onAnimationComplete={handleAnimationComplete} 649 > 650 {itemsForRender.map((item, index) => ( 651 <CarouselItem 652 key={\`\${item?.id ?? index}-\${index}\`} 653 item={item} 654 index={index} 655 itemWidth={itemWidth} 656 round={round} 657 trackItemOffset={trackItemOffset} 658 x={x} 659 transition={effectiveTransition} 660 /> 661 ))} 662 </motion.div> 663 <div className={\`flex w-full justify-center \${round ? 'absolute z-20 bottom-12 left-1/2 -translate-x-1/2' : ''}\`}> 664 <div className="mt-4 flex w-[150px] justify-between px-8"> 665 {items.map((_, index) => ( 666 <motion.button 667 type="button" 668 key={index} 669 aria-label={\`Go to slide \${index + 1}\`} 670 aria-current={activeIndex === index} 671 className={\`h-2 w-2 rounded-full cursor-pointer border-0 p-0 appearance-none transition-colors duration-150 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white \${ 672 activeIndex === index 673 ? round 674 ? 'bg-white' 675 : 'bg-[#333333]' 676 : round 677 ? 'bg-[#555]' 678 : 'bg-[rgba(51,51,51,0.4)]' 679 }\`} 680 animate={{ 681 scale: activeIndex === index ? 1.2 : 1 682 }} 683 onClick={() => setPosition(loop ? index + 1 : index)} 684 transition={{ duration: 0.15 }} 685 /> 686 ))} 687 </div> 688 </div> 689 </div> 690 ); 691} 692`,xn=`'use client'; 693 694import { useEffect, useMemo, useRef, useState } from 'react'; 695import { motion, type PanInfo, useMotionValue, useTransform } from 'motion/react'; 696// replace icons with your own if needed 697import { FiCircle, FiCode, FiFileText, FiLayers, FiLayout } from 'react-icons/fi'; 698import './Carousel.css'; 699 700export interface CarouselItem { 701 title: string; 702 description: string; 703 id: number; 704 icon: React.ReactElement; 705} 706 707export interface CarouselProps { 708 items?: CarouselItem[]; 709 baseWidth?: number; 710 autoplay?: boolean; 711 autoplayDelay?: number; 712 pauseOnHover?: boolean; 713 loop?: boolean; 714 round?: boolean; 715} 716 717const DEFAULT_ITEMS: CarouselItem[] = [ 718 { 719 title: 'Text Animations', 720 description: 'Cool text animations for your projects.', 721 id: 1, 722 icon: <FiFileText className="carousel-icon" /> 723 }, 724 { 725 title: 'Animations', 726 description: 'Smooth animations for your projects.', 727 id: 2, 728 icon: <FiCircle className="carousel-icon" /> 729 }, 730 { 731 title: 'Components', 732 description: 'Reusable components for your projects.', 733 id: 3, 734 icon: <FiLayers className="carousel-icon" /> 735 }, 736 { 737 title: 'Backgrounds', 738 description: 'Beautiful backgrounds and patterns for your projects.', 739 id: 4,
740 icon: <FiLayout className="carousel-icon" /> 741 }, 742 { 743 title: 'Common UI', 744 description: 'Common UI components are coming soon!', 745 id: 5, 746 icon: <FiCode className="carousel-icon" /> 747 } 748]; 749 750const DRAG_BUFFER = 0; 751const VELOCITY_THRESHOLD = 500; 752const GAP = 16; 753const SPRING_OPTIONS = { type: 'spring' as const, stiffness: 300, damping: 30 }; 754 755interface CarouselItemProps { 756 item: CarouselItem; 757 index: number; 758 itemWidth: number; 759 round: boolean; 760 trackItemOffset: number; 761 x: any; 762 transition: any; 763} 764 765function CarouselItem({ item, index, itemWidth, round, trackItemOffset, x, transition }: CarouselItemProps) { 766 const range = [-(index + 1) * trackItemOffset, -index * trackItemOffset, -(index - 1) * trackItemOffset]; 767 const outputRange = [90, 0, -90]; 768 const rotateY = useTransform(x, range, outputRange, { clamp: false }); 769 770 return ( 771 <motion.div 772 key={\`\${item?.id ?? index}-\${index}\`} 773 className={\`carousel-item \${round ? 'round' : ''}\`} 774 style={{ 775 width: itemWidth, 776 height: round ? itemWidth : '100%', 777 rotateY: rotateY, 778 ...(round && { borderRadius: '50%' }) 779 }} 780 transition={transition} 781 > 782 <div className={\`carousel-item-header \${round ? 'round' : ''}\`}> 783 <span className="carousel-icon-container">{item.icon}</span> 784 </div> 785 <div className="carousel-item-content"> 786 <div className="carousel-item-title">{item.title}</div> 787 <p className="carousel-item-description">{item.description}</p> 788 </div> 789 </motion.div> 790 ); 791} 792 793export default function Carousel({ 794 items = DEFAULT_ITEMS, 795 baseWidth = 300, 796 autoplay = false, 797 autoplayDelay = 3000, 798 pauseOnHover = false, 799 loop = false, 800 round = false 801}: CarouselProps): React.JSX.Element { 802 const containerPadding = 16; 803 const itemWidth = baseWidth - containerPadding * 2; 804 const trackItemOffset = itemWidth + GAP; 805 const itemsForRender = useMemo(() => { 806 if (!loop) return items; 807 if (items.length === 0) return []; 808 return [items[items.length - 1], ...items, items[0]]; 809 }, [items, loop]); 810 811 const [position, setPosition] = useState<number>(loop ? 1 : 0); 812 const x = useMotionValue(0); 813 const [isHovered, setIsHovered] = useState<boolean>(false); 814 const [isJumping, setIsJumping] = useState<boolean>(false); 815 const [isAnimating, setIsAnimating] = useState<boolean>(false); 816 817 const containerRef = useRef<HTMLDivElement>(null); 818 useEffect(() => { 819 if (pauseOnHover && containerRef.current) { 820 const container = containerRef.current; 821 const handleMouseEnter = () => setIsHovered(true); 822 const handleMouseLeave = () => setIsHovered(false); 823 container.addEventListener('mouseenter', handleMouseEnter); 824 container.addEventListener('mouseleave', handleMouseLeave); 825 return () => { 826 container.removeEventListener('mouseenter', handleMouseEnter); 827 container.removeEventListener('mouseleave', handleMouseLeave); 828 }; 829 } 830 }, [pauseOnHover]); 831 832 useEffect(() => { 833 if (!autoplay || itemsForRender.length <= 1) return undefined; 834 if (pauseOnHover && isHovered) return undefined; 835 836 const timer = setInterval(() => { 837 setPosition(prev => Math.min(prev + 1, itemsForRender.length - 1)); 838 }, autoplayDelay); 839 840 return () => clearInterval(timer); 841 }, [autoplay, autoplayDelay, isHovered, pauseOnHover, itemsForRender.length]); 842 843 useEffect(() => { 844 const startingPosition = loop ? 1 : 0; 845 setPosition(startingPosition); 846 x.set(-startingPosition * trackItemOffset); 847 }, [items.length, loop, trackItemOffset, x]); 848 849 useEffect(() => { 850 if (!loop && position > itemsForRender.length - 1) { 851 setPosition(Math.max(0, itemsForRender.length - 1)); 852 } 853 }, [itemsForRender.length, loop, position]); 854 855 const effectiveTransition = isJumping ? { duration: 0 } : SPRING_OPTIONS; 856 857 const handleAnimationStart = () => { 858 setIsAnimating(true); 859 }; 860 861 const handleAnimationComplete = () => { 862 if (!loop || itemsForRender.length <= 1) { 863 setIsAnimating(false); 864 return; 865 } 866 const lastCloneIndex = itemsForRender.length - 1; 867 868 if (position === lastCloneIndex) { 869 setIsJumping(true); 870 const target = 1; 871 setPosition(target); 872 x.set(-target * trackItemOffset); 873 requestAnimationFrame(() => { 874 setIsJumping(false); 875 setIsAnimating(false); 876 }); 877 return; 878 } 879 880 if (position === 0) { 881 setIsJumping(true); 882 const target = items.length; 883 setPosition(target); 884 x.set(-target * trackItemOffset); 885 requestAnimationFrame(() => { 886 setIsJumping(false); 887 setIsAnimating(false); 888 }); 889 return; 890 } 891 892 setIsAnimating(false); 893 }; 894 895 const handleDragEnd = (_: MouseEvent | TouchEvent | PointerEvent, info: PanInfo): void => { 896 const { offset, velocity } = info; 897 const direction = 898 offset.x < -DRAG_BUFFER || velocity.x < -VELOCITY_THRESHOLD 899 ? 1 900 : offset.x > DRAG_BUFFER || velocity.x > VELOCITY_THRESHOLD 901 ? -1 902 : 0; 903 904 if (direction === 0) return; 905 906 setPosition(prev => { 907 const next = prev + direction; 908 const max = itemsForRender.length - 1;
909 return Math.max(0, Math.min(next, max)); 910 }); 911 }; 912 913 const dragProps = loop 914 ? {} 915 : { 916 dragConstraints: { 917 left: -trackItemOffset * Math.max(itemsForRender.length - 1, 0), 918 right: 0 919 } 920 }; 921 922 const activeIndex = 923 items.length === 0 ? 0 : loop ? (position - 1 + items.length) % items.length : Math.min(position, items.length - 1); 924 925 return ( 926 <div 927 ref={containerRef} 928 className={\`carousel-container \${round ? 'round' : ''}\`} 929 style={{ 930 width: \`\${baseWidth}px\`, 931 ...(round && { height: \`\${baseWidth}px\`, borderRadius: '50%' }) 932 }} 933 > 934 <motion.div 935 className="carousel-track" 936 drag={isAnimating ? false : 'x'} 937 {...dragProps} 938 style={{ 939 width: itemWidth, 940 gap: \`\${GAP}px\`, 941 perspective: 1000, 942 perspectiveOrigin: \`\${position * trackItemOffset + itemWidth / 2}px 50%\`, 943 x 944 }} 945 onDragEnd={handleDragEnd} 946 animate={{ x: -(position * trackItemOffset) }} 947 transition={effectiveTransition} 948 onAnimationStart={handleAnimationStart} 949 onAnimationComplete={handleAnimationComplete} 950 > 951 {itemsForRender.map((item, index) => ( 952 <CarouselItem 953 key={\`\${item?.id ?? index}-\${index}\`} 954 item={item} 955 index={index} 956 itemWidth={itemWidth} 957 round={round} 958 trackItemOffset={trackItemOffset} 959 x={x} 960 transition={effectiveTransition} 961 /> 962 ))} 963 </motion.div> 964 <div className={\`carousel-indicators-container \${round ? 'round' : ''}\`}> 965 <div className="carousel-indicators"> 966 {items.map((_, index) => ( 967 <motion.button 968 type="button" 969 key={index} 970 className={\`carousel-indicator \${activeIndex === index ? 'active' : 'inactive'}\`} 971 aria-label={\`Go to slide \${index + 1}\`} 972 aria-current={activeIndex === index} 973 animate={{ 974 scale: activeIndex === index ? 1.2 : 1 975 }} 976 onClick={() => setPosition(loop ? index + 1 : index)} 977 transition={{ duration: 0.15 }} 978 /> 979 ))} 980 </div> 981 </div> 982 </div> 983 ); 984} 985`,gn=`'use client'; 986 987import { useEffect, useMemo, useRef, useState } from 'react'; 988import { motion, type PanInfo, useMotionValue, useTransform } from 'motion/react'; 989import React, { type JSX } from 'react'; 990 991// replace icons with your own if needed 992import { FiCircle, FiCode, FiFileText, FiLayers, FiLayout } from 'react-icons/fi'; 993export interface CarouselItem { 994 title: string; 995 description: string; 996 id: number; 997 icon: React.ReactNode; 998} 999 1000export interface CarouselProps { 1001 items?: CarouselItem[]; 1002 baseWidth?: number; 1003 autoplay?: boolean; 1004 autoplayDelay?: number; 1005 pauseOnHover?: boolean; 1006 loop?: boolean; 1007 round?: boolean; 1008} 1009 1010const DEFAULT_ITEMS: CarouselItem[] = [ 1011 { 1012 title: 'Text Animations', 1013 description: 'Cool text animations for your projects.', 1014 id: 1, 1015 icon: <FiFileText className="h-[16px] w-[16px] text-white" /> 1016 }, 1017 { 1018 title: 'Animations', 1019 description: 'Smooth animations for your projects.', 1020 id: 2, 1021 icon: <FiCircle className="h-[16px] w-[16px] text-white" /> 1022 }, 1023 { 1024 title: 'Components', 1025 description: 'Reusable components for your projects.', 1026 id: 3, 1027 icon: <FiLayers className="h-[16px] w-[16px] text-white" /> 1028 }, 1029 { 1030 title: 'Backgrounds', 1031 description: 'Beautiful backgrounds and patterns for your projects.', 1032 id: 4, 1033 icon: <FiLayout className="h-[16px] w-[16px] text-white" /> 1034 }, 1035 { 1036 title: 'Common UI', 1037 description: 'Common UI components are coming soon!', 1038 id: 5, 1039 icon: <FiCode className="h-[16px] w-[16px] text-white" /> 1040 } 1041]; 1042 1043const DRAG_BUFFER = 0; 1044const VELOCITY_THRESHOLD = 500; 1045const GAP = 16; 1046const SPRING_OPTIONS = { type: 'spring' as const, stiffness: 300, damping: 30 }; 1047 1048interface CarouselItemProps { 1049 item: CarouselItem; 1050 index: number; 1051 itemWidth: number; 1052 round: boolean; 1053 trackItemOffset: number; 1054 x: any; 1055 transition: any; 1056} 1057
1058function CarouselItem({ item, index, itemWidth, round, trackItemOffset, x, transition }: CarouselItemProps) { 1059 const range = [-(index + 1) * trackItemOffset, -index * trackItemOffset, -(index - 1) * trackItemOffset]; 1060 const outputRange = [90, 0, -90]; 1061 const rotateY = useTransform(x, range, outputRange, { clamp: false }); 1062 1063 return ( 1064 <motion.div 1065 key={\`\${item?.id ?? index}-\${index}\`} 1066 className={\`relative shrink-0 flex flex-col \${ 1067 round 1068 ? 'items-center justify-center text-center bg-[#120F17] border-0' 1069 : 'items-start justify-between bg-[#222] border border-[#222] rounded-[12px]' 1070 } overflow-hidden cursor-grab active:cursor-grabbing\`} 1071 style={{ 1072 width: itemWidth, 1073 height: round ? itemWidth : '100%', 1074 rotateY: rotateY, 1075 ...(round && { borderRadius: '50%' }) 1076 }} 1077 transition={transition} 1078 > 1079 <div className={\`\${round ? 'p-0 m-0' : 'mb-4 p-5'}\`}> 1080 <span className="flex h-[28px] w-[28px] items-center justify-center rounded-full bg-[#120F17]"> 1081 {item.icon} 1082 </span> 1083 </div> 1084 <div className="p-5"> 1085 <div className="mb-1 font-black text-lg text-white">{item.title}</div> 1086 <p className="text-sm text-white">{item.description}</p> 1087 </div> 1088 </motion.div> 1089 ); 1090} 1091 1092export default function Carousel({ 1093 items = DEFAULT_ITEMS, 1094 baseWidth = 300, 1095 autoplay = false, 1096 autoplayDelay = 3000, 1097 pauseOnHover = false, 1098 loop = false, 1099 round = false 1100}: CarouselProps): JSX.Element { 1101 const containerPadding = 16; 1102 const itemWidth = baseWidth - containerPadding * 2; 1103 const trackItemOffset = itemWidth + GAP; 1104 const itemsForRender = useMemo(() => { 1105 if (!loop) return items; 1106 if (items.length === 0) return []; 1107 return [items[items.length - 1], ...items, items[0]]; 1108 }, [items, loop]); 1109 1110 const [position, setPosition] = useState<number>(loop ? 1 : 0); 1111 const x = useMotionValue(0); 1112 const [isHovered, setIsHovered] = useState<boolean>(false); 1113 const [isJumping, setIsJumping] = useState<boolean>(false); 1114 const [isAnimating, setIsAnimating] = useState<boolean>(false); 1115 1116 const containerRef = useRef<HTMLDivElement>(null); 1117 useEffect(() => { 1118 if (pauseOnHover && containerRef.current) { 1119 const container = containerRef.current; 1120 const handleMouseEnter = () => setIsHovered(true); 1121 const handleMouseLeave = () => setIsHovered(false); 1122 container.addEventListener('mouseenter', handleMouseEnter); 1123 container.addEventListener('mouseleave', handleMouseLeave); 1124 return () => { 1125 container.removeEventListener('mouseenter', handleMouseEnter); 1126 container.removeEventListener('mouseleave', handleMouseLeave); 1127 }; 1128 } 1129 }, [pauseOnHover]); 1130 1131 useEffect(() => { 1132 if (!autoplay || itemsForRender.length <= 1) return undefined; 1133 if (pauseOnHover && isHovered) return undefined; 1134 1135 const timer = setInterval(() => { 1136 setPosition(prev => Math.min(prev + 1, itemsForRender.length - 1)); 1137 }, autoplayDelay); 1138 1139 return () => clearInterval(timer); 1140 }, [autoplay, autoplayDelay, isHovered, pauseOnHover, itemsForRender.length]); 1141 1142 useEffect(() => { 1143 const startingPosition = loop ? 1 : 0; 1144 setPosition(startingPosition); 1145 x.set(-startingPosition * trackItemOffset); 1146 }, [items.length, loop, trackItemOffset, x]); 1147 1148 useEffect(() => { 1149 if (!loop && position > itemsForRender.length - 1) { 1150 setPosition(Math.max(0, itemsForRender.length - 1)); 1151 } 1152 }, [itemsForRender.length, loop, position]); 1153 1154 const effectiveTransition = isJumping ? { duration: 0 } : SPRING_OPTIONS; 1155 1156 const handleAnimationStart = () => { 1157 setIsAnimating(true); 1158 }; 1159 1160 const handleAnimationComplete = () => { 1161 if (!loop || itemsForRender.length <= 1) { 1162 setIsAnimating(false); 1163 return; 1164 } 1165 const lastCloneIndex = itemsForRender.length - 1; 1166 1167 if (position === lastCloneIndex) { 1168 setIsJumping(true); 1169 const target = 1; 1170 setPosition(target); 1171 x.set(-target * trackItemOffset); 1172 requestAnimationFrame(() => { 1173 setIsJumping(false); 1174 setIsAnimating(false); 1175 }); 1176 return; 1177 } 1178 1179 if (position === 0) { 1180 setIsJumping(true); 1181 const target = items.length; 1182 setPosition(target); 1183 x.set(-target * trackItemOffset); 1184 requestAnimationFrame(() => { 1185 setIsJumping(false); 1186 setIsAnimating(false); 1187 }); 1188 return; 1189 } 1190 1191 setIsAnimating(false); 1192 }; 1193 1194 const handleDragEnd = (_: MouseEvent | TouchEvent | PointerEvent, info: PanInfo): void => { 1195 const { offset, velocity } = info; 1196 const direction = 1197 offset.x < -DRAG_BUFFER || velocity.x < -VELOCITY_THRESHOLD 1198 ? 1 1199 : offset.x > DRAG_BUFFER || velocity.x > VELOCITY_THRESHOLD 1200 ? -1 1201 : 0; 1202 1203 if (direction === 0) return; 1204 1205 setPosition(prev => { 1206 const next = prev + direction; 1207 const max = itemsForRender.length - 1;
1208 return Math.max(0, Math.min(next, max)); 1209 }); 1210 }; 1211 1212 const dragProps = loop 1213 ? {} 1214 : { 1215 dragConstraints: { 1216 left: -trackItemOffset * Math.max(itemsForRender.length - 1, 0), 1217 right: 0 1218 } 1219 }; 1220 1221 const activeIndex = 1222 items.length === 0 ? 0 : loop ? (position - 1 + items.length) % items.length : Math.min(position, items.length - 1); 1223 1224 return ( 1225 <div 1226 ref={containerRef} 1227 className={\`relative overflow-hidden p-4 \${ 1228 round ? 'rounded-full border border-white' : 'rounded-[24px] border border-[#222]' 1229 }\`} 1230 style={{ 1231 width: \`\${baseWidth}px\`, 1232 ...(round && { height: \`\${baseWidth}px\` }) 1233 }} 1234 > 1235 <motion.div 1236 className="flex" 1237 drag={isAnimating ? false : 'x'} 1238 {...dragProps} 1239 style={{ 1240 width: itemWidth, 1241 gap: \`\${GAP}px\`, 1242 perspective: 1000, 1243 perspectiveOrigin: \`\${position * trackItemOffset + itemWidth / 2}px 50%\`, 1244 x 1245 }} 1246 onDragEnd={handleDragEnd} 1247 animate={{ x: -(position * trackItemOffset) }} 1248 transition={effectiveTransition} 1249 onAnimationStart={handleAnimationStart} 1250 onAnimationComplete={handleAnimationComplete} 1251 > 1252 {itemsForRender.map((item, index) => ( 1253 <CarouselItem 1254 key={\`\${item?.id ?? index}-\${index}\`} 1255 item={item} 1256 index={index} 1257 itemWidth={itemWidth} 1258 round={round} 1259 trackItemOffset={trackItemOffset} 1260 x={x} 1261 transition={effectiveTransition} 1262 /> 1263 ))} 1264 </motion.div> 1265 <div className={\`flex w-full justify-center \${round ? 'absolute z-20 bottom-12 left-1/2 -translate-x-1/2' : ''}\`}> 1266 <div className="mt-4 flex w-[150px] justify-between px-8"> 1267 {items.map((_, index) => ( 1268 <motion.button 1269 type="button" 1270 key={index} 1271 aria-label={\`Go to slide \${index + 1}\`} 1272 aria-current={activeIndex === index} 1273 className={\`h-2 w-2 rounded-full cursor-pointer border-0 p-0 appearance-none transition-colors duration-150 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white \${ 1274 activeIndex === index 1275 ? round 1276 ? 'bg-white' 1277 : 'bg-[#333333]' 1278 : round 1279 ? 'bg-[#555]' 1280 : 'bg-[rgba(51,51,51,0.4)]' 1281 }\`} 1282 animate={{ 1283 scale: activeIndex === index ? 1.2 : 1 1284 }} 1285 onClick={() => setPosition(loop ? index + 1 : index)} 1286 transition={{ duration: 0.15 }} 1287 /> 1288 ))} 1289 </div> 1290 </div> 1291 </div> 1292 ); 1293} 1294`,vn={dependencies:"motion",usage:`import Carousel from './Carousel' 1295 1296<div style={{ height: '600px', position: 'relative' }}> 1297 <Carousel 1298 baseWidth={300} 1299 autoplay={true} 1300 autoplayDelay={3000} 1301 pauseOnHover={true} 1302 loop={true} 1303 round={false} 1304 /> 1305</div>`,code:fn,css:pn,tailwind:hn,tsCode:xn,tsTailwind:gn},S={baseWidth:300,autoplay:!1,autoplayDelay:3e3,pauseOnHover:!1,loop:!1,round:!1},Dn=()=>{const{props:e,updateProp:a,resetProps:x,hasChanges:u}=Q(S),{baseWidth:d,autoplay:i,autoplayDelay:f,pauseOnHover:g,loop:h,round:c}=e,[l,r]=cn(),p=m.useMemo(()=>[{name:"items",type:"CarouselItem[]",default:"DEFAULT_ITEMS",description:"An array of carousel items. Each item must include title, description, id, and icon."},{name:"baseWidth",type:"number",default:"300",description:"Total width (in px) of the carousel container. Effective item width is baseWidth minus padding."},{name:"autoplay",type:"boolean",default:"false",description:"Enables automatic scrolling to the next item at a fixed interval."},{name:"autoplayDelay",type:"number",default:"3000",description:"Delay in milliseconds between automatic scrolls when autoplay is enabled."},{name:"pauseOnHover",type:"boolean",default:"false",description:"Pauses the autoplay functionality when the carousel is hovered."},{name:"loop",type:"boolean",default:"false",description:"When true, the carousel loops seamlessly from the last item back to the first."},{name:"round",type:"boolean",default:"false",description:"When true, the carousel is rendered with a 1:1 aspect ratio and circular container/items."}],[]);return n.jsx(Z,{props:e,defaultProps:S,resetProps:x,hasChanges:u,children:n.jsxs(nn,{children:[n.jsxs(en,{children:[n.jsx(K,{position:"relative",className:"demo-container",h:4
130500,overflow:"hidden",children:n.jsx(un,{baseWidth:d,autoplay:i,autoplayDelay:f,pauseOnHover:g,loop:h,round:c},l)}),n.jsxs(an,{children:[n.jsx(T,{title:"Width",min:250,max:330,step:10,value:d,onChange:o=>{a("baseWidth",o),r()}}),n.jsx(b,{title:"Round Variant",isChecked:c,onChange:o=>{a("round",o),r()}}),n.jsx(b,{title:"Loop",isChecked:h,onChange:o=>{a("loop",o),r()}}),n.jsx(b,{title:"Autoplay",isChecked:i,onChange:o=>{a("autoplay",o),r()}}),n.jsx(T,{title:"Delay",min:1e3,max:4e3,step:1e3,value:f,isDisabled:!i,onChange:o=>{a("autoplayDelay",o),r()}}),n.jsx(b,{title:"Pause On Hover",isChecked:g,isDisabled:!i,onChange:o=>{a("pauseOnHover",o),r()}})]}),n.jsx(tn,{data:p}),n.jsx(rn,{dependencyList:["motion"]})]}),n.jsx(on,{children:n.jsx(sn,{codeObject:vn,componentName:"Carousel"})})]})})};export{Dn as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.