bynana-ui 1.7.0 → 1.9.0

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 (65) hide show
  1. package/dist/ai-text-loading/index.js +2 -0
  2. package/dist/ai-text-loading/index.js.map +1 -0
  3. package/dist/ai-text-loading/index.mjs +2 -0
  4. package/dist/ai-text-loading/index.mjs.map +1 -0
  5. package/dist/ai-voice/index.js +3 -0
  6. package/dist/ai-voice/index.js.map +1 -0
  7. package/dist/ai-voice/index.mjs +3 -0
  8. package/dist/ai-voice/index.mjs.map +1 -0
  9. package/dist/background-paths/index.js +2 -0
  10. package/dist/background-paths/index.js.map +1 -0
  11. package/dist/background-paths/index.mjs +2 -0
  12. package/dist/background-paths/index.mjs.map +1 -0
  13. package/dist/floating-paths/index.js +2 -0
  14. package/dist/floating-paths/index.js.map +1 -0
  15. package/dist/floating-paths/index.mjs +2 -0
  16. package/dist/floating-paths/index.mjs.map +1 -0
  17. package/dist/folder/index.js +2 -0
  18. package/dist/folder/index.js.map +1 -0
  19. package/dist/folder/index.mjs +2 -0
  20. package/dist/folder/index.mjs.map +1 -0
  21. package/dist/glare-hover/index.js +32 -0
  22. package/dist/glare-hover/index.js.map +1 -0
  23. package/dist/glare-hover/index.mjs +32 -0
  24. package/dist/glare-hover/index.mjs.map +1 -0
  25. package/dist/index.js +44 -14
  26. package/dist/index.js.map +1 -1
  27. package/dist/index.mjs +44 -14
  28. package/dist/index.mjs.map +1 -1
  29. package/dist/logo-loop/index.js +2 -0
  30. package/dist/logo-loop/index.js.map +1 -0
  31. package/dist/logo-loop/index.mjs +2 -0
  32. package/dist/logo-loop/index.mjs.map +1 -0
  33. package/dist/magnet/index.js +2 -0
  34. package/dist/magnet/index.js.map +1 -0
  35. package/dist/magnet/index.mjs +2 -0
  36. package/dist/magnet/index.mjs.map +1 -0
  37. package/dist/magnet-lines/index.js +2 -0
  38. package/dist/magnet-lines/index.js.map +1 -0
  39. package/dist/magnet-lines/index.mjs +2 -0
  40. package/dist/magnet-lines/index.mjs.map +1 -0
  41. package/dist/team-selector/index.js +3 -0
  42. package/dist/team-selector/index.js.map +1 -0
  43. package/dist/team-selector/index.mjs +3 -0
  44. package/dist/team-selector/index.mjs.map +1 -0
  45. package/dist/testimonials-stars/index.js +3 -0
  46. package/dist/testimonials-stars/index.js.map +1 -0
  47. package/dist/testimonials-stars/index.mjs +3 -0
  48. package/dist/testimonials-stars/index.mjs.map +1 -0
  49. package/dist/text-type/index.js +2 -0
  50. package/dist/text-type/index.js.map +1 -0
  51. package/dist/text-type/index.mjs +2 -0
  52. package/dist/text-type/index.mjs.map +1 -0
  53. package/dist/tooltip-interactive/index.js +2 -0
  54. package/dist/tooltip-interactive/index.js.map +1 -0
  55. package/dist/tooltip-interactive/index.mjs +2 -0
  56. package/dist/tooltip-interactive/index.mjs.map +1 -0
  57. package/dist/tooltip-magnetic/index.js +2 -0
  58. package/dist/tooltip-magnetic/index.js.map +1 -0
  59. package/dist/tooltip-magnetic/index.mjs +2 -0
  60. package/dist/tooltip-magnetic/index.mjs.map +1 -0
  61. package/dist/tooltip-rich/index.js +2 -0
  62. package/dist/tooltip-rich/index.js.map +1 -0
  63. package/dist/tooltip-rich/index.mjs +2 -0
  64. package/dist/tooltip-rich/index.mjs.map +1 -0
  65. package/package.json +17 -2
@@ -0,0 +1,2 @@
1
+ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var react=require('react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),jsxRuntime=require('react/jsx-runtime');function h(...i){return tailwindMerge.twMerge(clsx.clsx(i))}var L={SMOOTH_TAU:.25,MIN_COPIES:2,COPY_HEADROOM:2},P=react.memo(({logos:i,speed:p=120,direction:O="left",width:u="100%",logoHeight:c=28,gap:d=32,pauseOnHover:f=true,fadeOut:q=false,fadeOutColor:Z,scaleOnHover:M=false,ariaLabel:$="Partner logos",className:D,style:R})=>{let v=react.useRef(null),S=react.useRef(null),m=react.useRef(null),[o,F]=react.useState(0),[k,W]=react.useState(L.MIN_COPIES),[z,A]=react.useState(false),T=react.useMemo(()=>{let e=Math.abs(p),t=O==="left"?1:-1,r=p<0?-1:1;return e*t*r},[p,O]),s=react.useCallback(()=>{let e=v.current?.clientWidth??0,t=m.current?.getBoundingClientRect?.()?.width??0;if(t>0){F(Math.ceil(t));let r=Math.ceil(e/t)+L.COPY_HEADROOM;W(Math.max(L.MIN_COPIES,r));}},[]);react.useEffect(()=>{if(!window.ResizeObserver){let t=()=>s();return window.addEventListener("resize",t),s(),()=>window.removeEventListener("resize",t)}let e=[];return [v,m].forEach(t=>{if(t.current){let r=new ResizeObserver(s);r.observe(t.current),e.push(r);}}),s(),()=>{e.forEach(t=>t.disconnect());}},[s,i,d,c]),react.useEffect(()=>{let e=m.current?.querySelectorAll("img")??[];if(e.length===0){s();return}let t=e.length,r=()=>{t-=1,t===0&&s();};return e.forEach(n=>{let a=n;a.complete?r():(a.addEventListener("load",r,{once:true}),a.addEventListener("error",r,{once:true}));}),()=>{e.forEach(n=>{n.removeEventListener("load",r),n.removeEventListener("error",r);});}},[i,d,c,s]),react.useEffect(()=>{let e=S.current;if(!e)return;let t=null,r=null,n=0,a=0;o>0&&(n=(n%o+o)%o,e.style.transform=`translate3d(${-n}px, 0, 0)`);let b=E=>{r===null&&(r=E);let _=Math.max(0,E-r)/1e3;r=E;let G=f&&z?0:T,H=1-Math.exp(-_/L.SMOOTH_TAU);if(a+=(G-a)*H,o>0){let w=n+a*_;w=(w%o+o)%o,n=w;let X=-n;e.style.transform=`translate3d(${X}px, 0, 0)`;}t=requestAnimationFrame(b);};return t=requestAnimationFrame(b),()=>{t!==null&&cancelAnimationFrame(t);}},[T,o,z,f]);let U=react.useCallback(()=>{f&&A(true);},[f]),V=react.useCallback(()=>{f&&A(false);},[f]),x=react.useCallback((e,t)=>{let r="node"in e&&e.node,n=r?jsxRuntime.jsx("span",{"aria-hidden":!!e.href&&!e.ariaLabel,children:e.node}):jsxRuntime.jsx("img",{src:e.src,srcSet:e.srcSet,sizes:e.sizes,width:e.width,height:e.height,alt:e.alt??"",title:e.title,loading:"lazy",decoding:"async",draggable:false,style:{height:c,width:"auto"}}),a=r?e.ariaLabel??e.title:e.alt??e.title,b=e.href?jsxRuntime.jsx("a",{href:e.href,"aria-label":a||"logo link",target:"_blank",rel:"noreferrer noopener",className:h(M&&"transition-transform hover:scale-110"),children:n}):jsxRuntime.jsx("span",{className:h(M&&"transition-transform hover:scale-110"),children:n});return jsxRuntime.jsx("li",{role:"listitem",className:"flex-shrink-0",style:{marginRight:d},children:b},t)},[d,c,M]),Y=react.useMemo(()=>Array.from({length:k},(e,t)=>jsxRuntime.jsx("ul",{role:"list","aria-hidden":t>0,ref:t===0?m:void 0,className:"flex items-center",style:{height:c},children:i.map((r,n)=>x(r,`${t}-${n}`))},`copy-${t}`)),[k,i,x,c]),B=react.useMemo(()=>({width:typeof u=="number"?`${u}px`:u,...R}),[u,R]);return jsxRuntime.jsx("div",{ref:v,className:h("relative overflow-hidden",q&&"before:absolute before:left-0 before:top-0 before:bottom-0 before:w-24 before:bg-gradient-to-r before:from-white before:to-transparent before:z-10 after:absolute after:right-0 after:top-0 after:bottom-0 after:w-24 after:bg-gradient-to-l after:from-white after:to-transparent after:z-10 dark:before:from-black dark:after:from-black",D),style:B,role:"region","aria-label":$,onMouseEnter:U,onMouseLeave:V,children:jsxRuntime.jsx("div",{ref:S,className:"flex will-change-transform",children:Y})})});P.displayName="LogoLoop";var oe=P;exports.LogoLoop=P;exports.default=oe;//# sourceMappingURL=index.js.map
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/cn.ts","../../src/logo-loop/index.tsx"],"names":["cn","inputs","twMerge","clsx","ANIMATION_CONFIG","LogoLoop","memo","logos","speed","direction","width","logoHeight","gap","pauseOnHover","fadeOut","fadeOutColor","scaleOnHover","ariaLabel","className","style","containerRef","useRef","trackRef","seqRef","seqWidth","setSeqWidth","useState","copyCount","setCopyCount","isHovered","setIsHovered","targetVelocity","useMemo","magnitude","directionMultiplier","speedMultiplier","updateDimensions","useCallback","containerWidth","sequenceWidth","copiesNeeded","useEffect","handleResize","observers","ref","observer","images","remainingImages","handleImageLoad","img","htmlImg","track","rafId","lastTimestamp","offset","velocity","animate","timestamp","deltaTime","target","easingFactor","nextOffset","translateX","handleMouseEnter","handleMouseLeave","renderLogoItem","item","key","isNodeItem","content","jsx","itemAriaLabel","itemContent","logoLists","_","copyIndex","itemIndex","containerStyle","logo_loop_default"],"mappings":"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","file":"index.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs));\r\n}\r\n","\"use client\";\r\n\r\nimport {\r\n useCallback,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n memo,\r\n} from \"react\";\r\nimport { cn } from \"../utils/cn\";\r\n\r\nconst ANIMATION_CONFIG = {\r\n SMOOTH_TAU: 0.25,\r\n MIN_COPIES: 2,\r\n COPY_HEADROOM: 2,\r\n};\r\n\r\ninterface LogoItem {\r\n node?: React.ReactNode;\r\n src?: string;\r\n srcSet?: string;\r\n sizes?: string;\r\n width?: number;\r\n height?: number;\r\n alt?: string;\r\n title?: string;\r\n href?: string;\r\n ariaLabel?: string;\r\n}\r\n\r\ninterface LogoLoopProps {\r\n logos: LogoItem[];\r\n speed?: number;\r\n direction?: \"left\" | \"right\";\r\n width?: string | number;\r\n logoHeight?: number;\r\n gap?: number;\r\n pauseOnHover?: boolean;\r\n fadeOut?: boolean;\r\n fadeOutColor?: string;\r\n scaleOnHover?: boolean;\r\n ariaLabel?: string;\r\n className?: string;\r\n style?: React.CSSProperties;\r\n}\r\n\r\nexport const LogoLoop = memo<LogoLoopProps>(\r\n ({\r\n logos,\r\n speed = 120,\r\n direction = \"left\",\r\n width = \"100%\",\r\n logoHeight = 28,\r\n gap = 32,\r\n pauseOnHover = true,\r\n fadeOut = false,\r\n fadeOutColor,\r\n scaleOnHover = false,\r\n ariaLabel = \"Partner logos\",\r\n className,\r\n style,\r\n }) => {\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const trackRef = useRef<HTMLDivElement>(null);\r\n const seqRef = useRef<HTMLUListElement>(null);\r\n\r\n const [seqWidth, setSeqWidth] = useState<number>(0);\r\n const [copyCount, setCopyCount] = useState<number>(ANIMATION_CONFIG.MIN_COPIES);\r\n const [isHovered, setIsHovered] = useState<boolean>(false);\r\n\r\n const targetVelocity = useMemo(() => {\r\n const magnitude = Math.abs(speed);\r\n const directionMultiplier = direction === \"left\" ? 1 : -1;\r\n const speedMultiplier = speed < 0 ? -1 : 1;\r\n return magnitude * directionMultiplier * speedMultiplier;\r\n }, [speed, direction]);\r\n\r\n const updateDimensions = useCallback(() => {\r\n const containerWidth = containerRef.current?.clientWidth ?? 0;\r\n const sequenceWidth = seqRef.current?.getBoundingClientRect?.()?.width ?? 0;\r\n\r\n if (sequenceWidth > 0) {\r\n setSeqWidth(Math.ceil(sequenceWidth));\r\n const copiesNeeded =\r\n Math.ceil(containerWidth / sequenceWidth) + ANIMATION_CONFIG.COPY_HEADROOM;\r\n setCopyCount(Math.max(ANIMATION_CONFIG.MIN_COPIES, copiesNeeded));\r\n }\r\n }, []);\r\n\r\n // Resize observer\r\n useEffect(() => {\r\n if (!window.ResizeObserver) {\r\n const handleResize = () => updateDimensions();\r\n window.addEventListener(\"resize\", handleResize);\r\n updateDimensions();\r\n return () => window.removeEventListener(\"resize\", handleResize);\r\n }\r\n\r\n const observers: ResizeObserver[] = [];\r\n [containerRef, seqRef].forEach((ref) => {\r\n if (ref.current) {\r\n const observer = new ResizeObserver(updateDimensions);\r\n observer.observe(ref.current);\r\n observers.push(observer);\r\n }\r\n });\r\n\r\n updateDimensions();\r\n\r\n return () => {\r\n observers.forEach((observer) => observer.disconnect());\r\n };\r\n }, [updateDimensions, logos, gap, logoHeight]);\r\n\r\n // Image loader\r\n useEffect(() => {\r\n const images = seqRef.current?.querySelectorAll(\"img\") ?? [];\r\n\r\n if (images.length === 0) {\r\n updateDimensions();\r\n return;\r\n }\r\n\r\n let remainingImages = images.length;\r\n const handleImageLoad = () => {\r\n remainingImages -= 1;\r\n if (remainingImages === 0) {\r\n updateDimensions();\r\n }\r\n };\r\n\r\n images.forEach((img) => {\r\n const htmlImg = img as HTMLImageElement;\r\n if (htmlImg.complete) {\r\n handleImageLoad();\r\n } else {\r\n htmlImg.addEventListener(\"load\", handleImageLoad, { once: true });\r\n htmlImg.addEventListener(\"error\", handleImageLoad, { once: true });\r\n }\r\n });\r\n\r\n return () => {\r\n images.forEach((img) => {\r\n img.removeEventListener(\"load\", handleImageLoad);\r\n img.removeEventListener(\"error\", handleImageLoad);\r\n });\r\n };\r\n }, [logos, gap, logoHeight, updateDimensions]);\r\n\r\n // Animation loop\r\n useEffect(() => {\r\n const track = trackRef.current;\r\n if (!track) return;\r\n\r\n let rafId: number | null = null;\r\n let lastTimestamp: number | null = null;\r\n let offset = 0;\r\n let velocity = 0;\r\n\r\n if (seqWidth > 0) {\r\n offset = ((offset % seqWidth) + seqWidth) % seqWidth;\r\n track.style.transform = `translate3d(${-offset}px, 0, 0)`;\r\n }\r\n\r\n const animate = (timestamp: number) => {\r\n if (lastTimestamp === null) {\r\n lastTimestamp = timestamp;\r\n }\r\n\r\n const deltaTime = Math.max(0, timestamp - lastTimestamp) / 1000;\r\n lastTimestamp = timestamp;\r\n\r\n const target = pauseOnHover && isHovered ? 0 : targetVelocity;\r\n\r\n const easingFactor = 1 - Math.exp(-deltaTime / ANIMATION_CONFIG.SMOOTH_TAU);\r\n velocity += (target - velocity) * easingFactor;\r\n\r\n if (seqWidth > 0) {\r\n let nextOffset = offset + velocity * deltaTime;\r\n nextOffset = ((nextOffset % seqWidth) + seqWidth) % seqWidth;\r\n offset = nextOffset;\r\n\r\n const translateX = -offset;\r\n track.style.transform = `translate3d(${translateX}px, 0, 0)`;\r\n }\r\n\r\n rafId = requestAnimationFrame(animate);\r\n };\r\n\r\n rafId = requestAnimationFrame(animate);\r\n\r\n return () => {\r\n if (rafId !== null) {\r\n cancelAnimationFrame(rafId);\r\n }\r\n };\r\n }, [targetVelocity, seqWidth, isHovered, pauseOnHover]);\r\n\r\n const handleMouseEnter = useCallback(() => {\r\n if (pauseOnHover) setIsHovered(true);\r\n }, [pauseOnHover]);\r\n\r\n const handleMouseLeave = useCallback(() => {\r\n if (pauseOnHover) setIsHovered(false);\r\n }, [pauseOnHover]);\r\n\r\n const renderLogoItem = useCallback((item: LogoItem, key: string) => {\r\n const isNodeItem = \"node\" in item && item.node;\r\n\r\n const content = isNodeItem ? (\r\n <span aria-hidden={!!item.href && !item.ariaLabel}>{item.node}</span>\r\n ) : (\r\n <img\r\n src={item.src}\r\n srcSet={item.srcSet}\r\n sizes={item.sizes}\r\n width={item.width}\r\n height={item.height}\r\n alt={item.alt ?? \"\"}\r\n title={item.title}\r\n loading=\"lazy\"\r\n decoding=\"async\"\r\n draggable={false}\r\n style={{ height: logoHeight, width: \"auto\" }}\r\n />\r\n );\r\n\r\n const itemAriaLabel = isNodeItem\r\n ? item.ariaLabel ?? item.title\r\n : item.alt ?? item.title;\r\n\r\n const itemContent = item.href ? (\r\n <a\r\n href={item.href}\r\n aria-label={itemAriaLabel || \"logo link\"}\r\n target=\"_blank\"\r\n rel=\"noreferrer noopener\"\r\n className={cn(scaleOnHover && \"transition-transform hover:scale-110\")}\r\n >\r\n {content}\r\n </a>\r\n ) : (\r\n <span className={cn(scaleOnHover && \"transition-transform hover:scale-110\")}>\r\n {content}\r\n </span>\r\n );\r\n\r\n return (\r\n <li\r\n key={key}\r\n role=\"listitem\"\r\n className=\"flex-shrink-0\"\r\n style={{ marginRight: gap }}\r\n >\r\n {itemContent}\r\n </li>\r\n );\r\n }, [gap, logoHeight, scaleOnHover]);\r\n\r\n const logoLists = useMemo(\r\n () =>\r\n Array.from({ length: copyCount }, (_, copyIndex) => (\r\n <ul\r\n key={`copy-${copyIndex}`}\r\n role=\"list\"\r\n aria-hidden={copyIndex > 0}\r\n ref={copyIndex === 0 ? seqRef : undefined}\r\n className=\"flex items-center\"\r\n style={{ height: logoHeight }}\r\n >\r\n {logos.map((item, itemIndex) =>\r\n renderLogoItem(item, `${copyIndex}-${itemIndex}`)\r\n )}\r\n </ul>\r\n )),\r\n [copyCount, logos, renderLogoItem, logoHeight]\r\n );\r\n\r\n const containerStyle = useMemo(\r\n () => ({\r\n width: typeof width === \"number\" ? `${width}px` : width,\r\n ...style,\r\n }),\r\n [width, style]\r\n );\r\n\r\n return (\r\n <div\r\n ref={containerRef}\r\n className={cn(\r\n \"relative overflow-hidden\",\r\n fadeOut &&\r\n \"before:absolute before:left-0 before:top-0 before:bottom-0 before:w-24 before:bg-gradient-to-r before:from-white before:to-transparent before:z-10 after:absolute after:right-0 after:top-0 after:bottom-0 after:w-24 after:bg-gradient-to-l after:from-white after:to-transparent after:z-10 dark:before:from-black dark:after:from-black\",\r\n className\r\n )}\r\n style={containerStyle}\r\n role=\"region\"\r\n aria-label={ariaLabel}\r\n onMouseEnter={handleMouseEnter}\r\n onMouseLeave={handleMouseLeave}\r\n >\r\n <div ref={trackRef} className=\"flex will-change-transform\">\r\n {logoLists}\r\n </div>\r\n </div>\r\n );\r\n }\r\n);\r\n\r\nLogoLoop.displayName = \"LogoLoop\";\r\n\r\nexport default LogoLoop;\r\n"]}
@@ -0,0 +1,2 @@
1
+ import {memo,useRef,useState,useMemo,useCallback,useEffect}from'react';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {jsx}from'react/jsx-runtime';function h(...i){return twMerge(clsx(i))}var L={SMOOTH_TAU:.25,MIN_COPIES:2,COPY_HEADROOM:2},P=memo(({logos:i,speed:p=120,direction:O="left",width:u="100%",logoHeight:c=28,gap:d=32,pauseOnHover:f=true,fadeOut:q=false,fadeOutColor:Z,scaleOnHover:M=false,ariaLabel:$="Partner logos",className:D,style:R})=>{let v=useRef(null),S=useRef(null),m=useRef(null),[o,F]=useState(0),[k,W]=useState(L.MIN_COPIES),[z,A]=useState(false),T=useMemo(()=>{let e=Math.abs(p),t=O==="left"?1:-1,r=p<0?-1:1;return e*t*r},[p,O]),s=useCallback(()=>{let e=v.current?.clientWidth??0,t=m.current?.getBoundingClientRect?.()?.width??0;if(t>0){F(Math.ceil(t));let r=Math.ceil(e/t)+L.COPY_HEADROOM;W(Math.max(L.MIN_COPIES,r));}},[]);useEffect(()=>{if(!window.ResizeObserver){let t=()=>s();return window.addEventListener("resize",t),s(),()=>window.removeEventListener("resize",t)}let e=[];return [v,m].forEach(t=>{if(t.current){let r=new ResizeObserver(s);r.observe(t.current),e.push(r);}}),s(),()=>{e.forEach(t=>t.disconnect());}},[s,i,d,c]),useEffect(()=>{let e=m.current?.querySelectorAll("img")??[];if(e.length===0){s();return}let t=e.length,r=()=>{t-=1,t===0&&s();};return e.forEach(n=>{let a=n;a.complete?r():(a.addEventListener("load",r,{once:true}),a.addEventListener("error",r,{once:true}));}),()=>{e.forEach(n=>{n.removeEventListener("load",r),n.removeEventListener("error",r);});}},[i,d,c,s]),useEffect(()=>{let e=S.current;if(!e)return;let t=null,r=null,n=0,a=0;o>0&&(n=(n%o+o)%o,e.style.transform=`translate3d(${-n}px, 0, 0)`);let b=E=>{r===null&&(r=E);let _=Math.max(0,E-r)/1e3;r=E;let G=f&&z?0:T,H=1-Math.exp(-_/L.SMOOTH_TAU);if(a+=(G-a)*H,o>0){let w=n+a*_;w=(w%o+o)%o,n=w;let X=-n;e.style.transform=`translate3d(${X}px, 0, 0)`;}t=requestAnimationFrame(b);};return t=requestAnimationFrame(b),()=>{t!==null&&cancelAnimationFrame(t);}},[T,o,z,f]);let U=useCallback(()=>{f&&A(true);},[f]),V=useCallback(()=>{f&&A(false);},[f]),x=useCallback((e,t)=>{let r="node"in e&&e.node,n=r?jsx("span",{"aria-hidden":!!e.href&&!e.ariaLabel,children:e.node}):jsx("img",{src:e.src,srcSet:e.srcSet,sizes:e.sizes,width:e.width,height:e.height,alt:e.alt??"",title:e.title,loading:"lazy",decoding:"async",draggable:false,style:{height:c,width:"auto"}}),a=r?e.ariaLabel??e.title:e.alt??e.title,b=e.href?jsx("a",{href:e.href,"aria-label":a||"logo link",target:"_blank",rel:"noreferrer noopener",className:h(M&&"transition-transform hover:scale-110"),children:n}):jsx("span",{className:h(M&&"transition-transform hover:scale-110"),children:n});return jsx("li",{role:"listitem",className:"flex-shrink-0",style:{marginRight:d},children:b},t)},[d,c,M]),Y=useMemo(()=>Array.from({length:k},(e,t)=>jsx("ul",{role:"list","aria-hidden":t>0,ref:t===0?m:void 0,className:"flex items-center",style:{height:c},children:i.map((r,n)=>x(r,`${t}-${n}`))},`copy-${t}`)),[k,i,x,c]),B=useMemo(()=>({width:typeof u=="number"?`${u}px`:u,...R}),[u,R]);return jsx("div",{ref:v,className:h("relative overflow-hidden",q&&"before:absolute before:left-0 before:top-0 before:bottom-0 before:w-24 before:bg-gradient-to-r before:from-white before:to-transparent before:z-10 after:absolute after:right-0 after:top-0 after:bottom-0 after:w-24 after:bg-gradient-to-l after:from-white after:to-transparent after:z-10 dark:before:from-black dark:after:from-black",D),style:B,role:"region","aria-label":$,onMouseEnter:U,onMouseLeave:V,children:jsx("div",{ref:S,className:"flex will-change-transform",children:Y})})});P.displayName="LogoLoop";var oe=P;export{P as LogoLoop,oe as default};//# sourceMappingURL=index.mjs.map
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/cn.ts","../../src/logo-loop/index.tsx"],"names":["cn","inputs","twMerge","clsx","ANIMATION_CONFIG","LogoLoop","memo","logos","speed","direction","width","logoHeight","gap","pauseOnHover","fadeOut","fadeOutColor","scaleOnHover","ariaLabel","className","style","containerRef","useRef","trackRef","seqRef","seqWidth","setSeqWidth","useState","copyCount","setCopyCount","isHovered","setIsHovered","targetVelocity","useMemo","magnitude","directionMultiplier","speedMultiplier","updateDimensions","useCallback","containerWidth","sequenceWidth","copiesNeeded","useEffect","handleResize","observers","ref","observer","images","remainingImages","handleImageLoad","img","htmlImg","track","rafId","lastTimestamp","offset","velocity","animate","timestamp","deltaTime","target","easingFactor","nextOffset","translateX","handleMouseEnter","handleMouseLeave","renderLogoItem","item","key","isNodeItem","content","jsx","itemAriaLabel","itemContent","logoLists","_","copyIndex","itemIndex","containerStyle","logo_loop_default"],"mappings":"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","file":"index.mjs","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs));\r\n}\r\n","\"use client\";\r\n\r\nimport {\r\n useCallback,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n memo,\r\n} from \"react\";\r\nimport { cn } from \"../utils/cn\";\r\n\r\nconst ANIMATION_CONFIG = {\r\n SMOOTH_TAU: 0.25,\r\n MIN_COPIES: 2,\r\n COPY_HEADROOM: 2,\r\n};\r\n\r\ninterface LogoItem {\r\n node?: React.ReactNode;\r\n src?: string;\r\n srcSet?: string;\r\n sizes?: string;\r\n width?: number;\r\n height?: number;\r\n alt?: string;\r\n title?: string;\r\n href?: string;\r\n ariaLabel?: string;\r\n}\r\n\r\ninterface LogoLoopProps {\r\n logos: LogoItem[];\r\n speed?: number;\r\n direction?: \"left\" | \"right\";\r\n width?: string | number;\r\n logoHeight?: number;\r\n gap?: number;\r\n pauseOnHover?: boolean;\r\n fadeOut?: boolean;\r\n fadeOutColor?: string;\r\n scaleOnHover?: boolean;\r\n ariaLabel?: string;\r\n className?: string;\r\n style?: React.CSSProperties;\r\n}\r\n\r\nexport const LogoLoop = memo<LogoLoopProps>(\r\n ({\r\n logos,\r\n speed = 120,\r\n direction = \"left\",\r\n width = \"100%\",\r\n logoHeight = 28,\r\n gap = 32,\r\n pauseOnHover = true,\r\n fadeOut = false,\r\n fadeOutColor,\r\n scaleOnHover = false,\r\n ariaLabel = \"Partner logos\",\r\n className,\r\n style,\r\n }) => {\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const trackRef = useRef<HTMLDivElement>(null);\r\n const seqRef = useRef<HTMLUListElement>(null);\r\n\r\n const [seqWidth, setSeqWidth] = useState<number>(0);\r\n const [copyCount, setCopyCount] = useState<number>(ANIMATION_CONFIG.MIN_COPIES);\r\n const [isHovered, setIsHovered] = useState<boolean>(false);\r\n\r\n const targetVelocity = useMemo(() => {\r\n const magnitude = Math.abs(speed);\r\n const directionMultiplier = direction === \"left\" ? 1 : -1;\r\n const speedMultiplier = speed < 0 ? -1 : 1;\r\n return magnitude * directionMultiplier * speedMultiplier;\r\n }, [speed, direction]);\r\n\r\n const updateDimensions = useCallback(() => {\r\n const containerWidth = containerRef.current?.clientWidth ?? 0;\r\n const sequenceWidth = seqRef.current?.getBoundingClientRect?.()?.width ?? 0;\r\n\r\n if (sequenceWidth > 0) {\r\n setSeqWidth(Math.ceil(sequenceWidth));\r\n const copiesNeeded =\r\n Math.ceil(containerWidth / sequenceWidth) + ANIMATION_CONFIG.COPY_HEADROOM;\r\n setCopyCount(Math.max(ANIMATION_CONFIG.MIN_COPIES, copiesNeeded));\r\n }\r\n }, []);\r\n\r\n // Resize observer\r\n useEffect(() => {\r\n if (!window.ResizeObserver) {\r\n const handleResize = () => updateDimensions();\r\n window.addEventListener(\"resize\", handleResize);\r\n updateDimensions();\r\n return () => window.removeEventListener(\"resize\", handleResize);\r\n }\r\n\r\n const observers: ResizeObserver[] = [];\r\n [containerRef, seqRef].forEach((ref) => {\r\n if (ref.current) {\r\n const observer = new ResizeObserver(updateDimensions);\r\n observer.observe(ref.current);\r\n observers.push(observer);\r\n }\r\n });\r\n\r\n updateDimensions();\r\n\r\n return () => {\r\n observers.forEach((observer) => observer.disconnect());\r\n };\r\n }, [updateDimensions, logos, gap, logoHeight]);\r\n\r\n // Image loader\r\n useEffect(() => {\r\n const images = seqRef.current?.querySelectorAll(\"img\") ?? [];\r\n\r\n if (images.length === 0) {\r\n updateDimensions();\r\n return;\r\n }\r\n\r\n let remainingImages = images.length;\r\n const handleImageLoad = () => {\r\n remainingImages -= 1;\r\n if (remainingImages === 0) {\r\n updateDimensions();\r\n }\r\n };\r\n\r\n images.forEach((img) => {\r\n const htmlImg = img as HTMLImageElement;\r\n if (htmlImg.complete) {\r\n handleImageLoad();\r\n } else {\r\n htmlImg.addEventListener(\"load\", handleImageLoad, { once: true });\r\n htmlImg.addEventListener(\"error\", handleImageLoad, { once: true });\r\n }\r\n });\r\n\r\n return () => {\r\n images.forEach((img) => {\r\n img.removeEventListener(\"load\", handleImageLoad);\r\n img.removeEventListener(\"error\", handleImageLoad);\r\n });\r\n };\r\n }, [logos, gap, logoHeight, updateDimensions]);\r\n\r\n // Animation loop\r\n useEffect(() => {\r\n const track = trackRef.current;\r\n if (!track) return;\r\n\r\n let rafId: number | null = null;\r\n let lastTimestamp: number | null = null;\r\n let offset = 0;\r\n let velocity = 0;\r\n\r\n if (seqWidth > 0) {\r\n offset = ((offset % seqWidth) + seqWidth) % seqWidth;\r\n track.style.transform = `translate3d(${-offset}px, 0, 0)`;\r\n }\r\n\r\n const animate = (timestamp: number) => {\r\n if (lastTimestamp === null) {\r\n lastTimestamp = timestamp;\r\n }\r\n\r\n const deltaTime = Math.max(0, timestamp - lastTimestamp) / 1000;\r\n lastTimestamp = timestamp;\r\n\r\n const target = pauseOnHover && isHovered ? 0 : targetVelocity;\r\n\r\n const easingFactor = 1 - Math.exp(-deltaTime / ANIMATION_CONFIG.SMOOTH_TAU);\r\n velocity += (target - velocity) * easingFactor;\r\n\r\n if (seqWidth > 0) {\r\n let nextOffset = offset + velocity * deltaTime;\r\n nextOffset = ((nextOffset % seqWidth) + seqWidth) % seqWidth;\r\n offset = nextOffset;\r\n\r\n const translateX = -offset;\r\n track.style.transform = `translate3d(${translateX}px, 0, 0)`;\r\n }\r\n\r\n rafId = requestAnimationFrame(animate);\r\n };\r\n\r\n rafId = requestAnimationFrame(animate);\r\n\r\n return () => {\r\n if (rafId !== null) {\r\n cancelAnimationFrame(rafId);\r\n }\r\n };\r\n }, [targetVelocity, seqWidth, isHovered, pauseOnHover]);\r\n\r\n const handleMouseEnter = useCallback(() => {\r\n if (pauseOnHover) setIsHovered(true);\r\n }, [pauseOnHover]);\r\n\r\n const handleMouseLeave = useCallback(() => {\r\n if (pauseOnHover) setIsHovered(false);\r\n }, [pauseOnHover]);\r\n\r\n const renderLogoItem = useCallback((item: LogoItem, key: string) => {\r\n const isNodeItem = \"node\" in item && item.node;\r\n\r\n const content = isNodeItem ? (\r\n <span aria-hidden={!!item.href && !item.ariaLabel}>{item.node}</span>\r\n ) : (\r\n <img\r\n src={item.src}\r\n srcSet={item.srcSet}\r\n sizes={item.sizes}\r\n width={item.width}\r\n height={item.height}\r\n alt={item.alt ?? \"\"}\r\n title={item.title}\r\n loading=\"lazy\"\r\n decoding=\"async\"\r\n draggable={false}\r\n style={{ height: logoHeight, width: \"auto\" }}\r\n />\r\n );\r\n\r\n const itemAriaLabel = isNodeItem\r\n ? item.ariaLabel ?? item.title\r\n : item.alt ?? item.title;\r\n\r\n const itemContent = item.href ? (\r\n <a\r\n href={item.href}\r\n aria-label={itemAriaLabel || \"logo link\"}\r\n target=\"_blank\"\r\n rel=\"noreferrer noopener\"\r\n className={cn(scaleOnHover && \"transition-transform hover:scale-110\")}\r\n >\r\n {content}\r\n </a>\r\n ) : (\r\n <span className={cn(scaleOnHover && \"transition-transform hover:scale-110\")}>\r\n {content}\r\n </span>\r\n );\r\n\r\n return (\r\n <li\r\n key={key}\r\n role=\"listitem\"\r\n className=\"flex-shrink-0\"\r\n style={{ marginRight: gap }}\r\n >\r\n {itemContent}\r\n </li>\r\n );\r\n }, [gap, logoHeight, scaleOnHover]);\r\n\r\n const logoLists = useMemo(\r\n () =>\r\n Array.from({ length: copyCount }, (_, copyIndex) => (\r\n <ul\r\n key={`copy-${copyIndex}`}\r\n role=\"list\"\r\n aria-hidden={copyIndex > 0}\r\n ref={copyIndex === 0 ? seqRef : undefined}\r\n className=\"flex items-center\"\r\n style={{ height: logoHeight }}\r\n >\r\n {logos.map((item, itemIndex) =>\r\n renderLogoItem(item, `${copyIndex}-${itemIndex}`)\r\n )}\r\n </ul>\r\n )),\r\n [copyCount, logos, renderLogoItem, logoHeight]\r\n );\r\n\r\n const containerStyle = useMemo(\r\n () => ({\r\n width: typeof width === \"number\" ? `${width}px` : width,\r\n ...style,\r\n }),\r\n [width, style]\r\n );\r\n\r\n return (\r\n <div\r\n ref={containerRef}\r\n className={cn(\r\n \"relative overflow-hidden\",\r\n fadeOut &&\r\n \"before:absolute before:left-0 before:top-0 before:bottom-0 before:w-24 before:bg-gradient-to-r before:from-white before:to-transparent before:z-10 after:absolute after:right-0 after:top-0 after:bottom-0 after:w-24 after:bg-gradient-to-l after:from-white after:to-transparent after:z-10 dark:before:from-black dark:after:from-black\",\r\n className\r\n )}\r\n style={containerStyle}\r\n role=\"region\"\r\n aria-label={ariaLabel}\r\n onMouseEnter={handleMouseEnter}\r\n onMouseLeave={handleMouseLeave}\r\n >\r\n <div ref={trackRef} className=\"flex will-change-transform\">\r\n {logoLists}\r\n </div>\r\n </div>\r\n );\r\n }\r\n);\r\n\r\nLogoLoop.displayName = \"LogoLoop\";\r\n\r\nexport default LogoLoop;\r\n"]}
@@ -0,0 +1,2 @@
1
+ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var react=require('react'),jsxRuntime=require('react/jsx-runtime');function A({children:p,padding:t=100,disabled:o=false,magnetStrength:n=8,activeTransition:M="transform 0.8s ease-out",inactiveTransition:g="transform 1.2s ease-in-out",wrapperClassName:y="",innerClassName:x="",...b}){let[h,r]=react.useState(false),[a,s]=react.useState({x:0,y:0}),i=react.useRef(null);react.useEffect(()=>{if(o){s({x:0,y:0});return}let c=e=>{if(!i.current)return;let{left:E,top:R,width:l,height:f}=i.current.getBoundingClientRect(),u=E+l/2,m=R+f/2,L=Math.abs(u-e.clientX),N=Math.abs(m-e.clientY);if(L<l/2+t&&N<f/2+t){r(true);let T=(e.clientX-u)/n,X=(e.clientY-m)/n;s({x:T,y:X});}else r(false),s({x:0,y:0});};return window.addEventListener("mousemove",c),()=>{window.removeEventListener("mousemove",c);}},[t,o,n]);let w=h?M:g;return jsxRuntime.jsx("div",{ref:i,className:y,style:{position:"relative",display:"inline-block"},...b,children:jsxRuntime.jsx("div",{className:x,style:{transform:`translate3d(${a.x}px, ${a.y}px, 0)`,transition:w,willChange:"transform"},children:p})})}var P=A;exports.Magnet=A;exports.default=P;//# sourceMappingURL=index.js.map
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/magnet/index.tsx"],"names":["Magnet","children","padding","disabled","magnetStrength","activeTransition","inactiveTransition","wrapperClassName","innerClassName","props","isActive","setIsActive","useState","position","setPosition","magnetRef","useRef","useEffect","handleMouseMove","left","top","width","height","centerX","centerY","distX","distY","offsetX","offsetY","transitionStyle","jsx","magnet_default"],"mappings":"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","file":"index.js","sourcesContent":["\"use client\";\r\n\r\nimport { useState, useEffect, useRef } from \"react\";\r\n\r\ninterface MagnetProps {\r\n children: React.ReactNode;\r\n padding?: number;\r\n disabled?: boolean;\r\n magnetStrength?: number;\r\n activeTransition?: string;\r\n inactiveTransition?: string;\r\n wrapperClassName?: string;\r\n innerClassName?: string;\r\n}\r\n\r\nexport function Magnet({\r\n children,\r\n padding = 100,\r\n disabled = false,\r\n magnetStrength = 8,\r\n activeTransition = \"transform 0.8s ease-out\",\r\n inactiveTransition = \"transform 1.2s ease-in-out\",\r\n wrapperClassName = \"\",\r\n innerClassName = \"\",\r\n ...props\r\n}: MagnetProps & React.HTMLAttributes<HTMLDivElement>) {\r\n const [isActive, setIsActive] = useState(false);\r\n const [position, setPosition] = useState({ x: 0, y: 0 });\r\n const magnetRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n if (disabled) {\r\n setPosition({ x: 0, y: 0 });\r\n return;\r\n }\r\n\r\n const handleMouseMove = (e: MouseEvent) => {\r\n if (!magnetRef.current) return;\r\n\r\n const { left, top, width, height } =\r\n magnetRef.current.getBoundingClientRect();\r\n const centerX = left + width / 2;\r\n const centerY = top + height / 2;\r\n\r\n const distX = Math.abs(centerX - e.clientX);\r\n const distY = Math.abs(centerY - e.clientY);\r\n\r\n if (distX < width / 2 + padding && distY < height / 2 + padding) {\r\n setIsActive(true);\r\n\r\n const offsetX = (e.clientX - centerX) / magnetStrength;\r\n const offsetY = (e.clientY - centerY) / magnetStrength;\r\n setPosition({ x: offsetX, y: offsetY });\r\n } else {\r\n setIsActive(false);\r\n setPosition({ x: 0, y: 0 });\r\n }\r\n };\r\n\r\n window.addEventListener(\"mousemove\", handleMouseMove);\r\n return () => {\r\n window.removeEventListener(\"mousemove\", handleMouseMove);\r\n };\r\n }, [padding, disabled, magnetStrength]);\r\n\r\n const transitionStyle = isActive ? activeTransition : inactiveTransition;\r\n\r\n return (\r\n <div\r\n ref={magnetRef}\r\n className={wrapperClassName}\r\n style={{ position: \"relative\", display: \"inline-block\" }}\r\n {...props}\r\n >\r\n <div\r\n className={innerClassName}\r\n style={{\r\n transform: `translate3d(${position.x}px, ${position.y}px, 0)`,\r\n transition: transitionStyle,\r\n willChange: \"transform\",\r\n }}\r\n >\r\n {children}\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport default Magnet;\r\n"]}
@@ -0,0 +1,2 @@
1
+ import {useState,useRef,useEffect}from'react';import {jsx}from'react/jsx-runtime';function A({children:p,padding:t=100,disabled:o=false,magnetStrength:n=8,activeTransition:M="transform 0.8s ease-out",inactiveTransition:g="transform 1.2s ease-in-out",wrapperClassName:y="",innerClassName:x="",...b}){let[h,r]=useState(false),[a,s]=useState({x:0,y:0}),i=useRef(null);useEffect(()=>{if(o){s({x:0,y:0});return}let c=e=>{if(!i.current)return;let{left:E,top:R,width:l,height:f}=i.current.getBoundingClientRect(),u=E+l/2,m=R+f/2,L=Math.abs(u-e.clientX),N=Math.abs(m-e.clientY);if(L<l/2+t&&N<f/2+t){r(true);let T=(e.clientX-u)/n,X=(e.clientY-m)/n;s({x:T,y:X});}else r(false),s({x:0,y:0});};return window.addEventListener("mousemove",c),()=>{window.removeEventListener("mousemove",c);}},[t,o,n]);let w=h?M:g;return jsx("div",{ref:i,className:y,style:{position:"relative",display:"inline-block"},...b,children:jsx("div",{className:x,style:{transform:`translate3d(${a.x}px, ${a.y}px, 0)`,transition:w,willChange:"transform"},children:p})})}var P=A;export{A as Magnet,P as default};//# sourceMappingURL=index.mjs.map
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/magnet/index.tsx"],"names":["Magnet","children","padding","disabled","magnetStrength","activeTransition","inactiveTransition","wrapperClassName","innerClassName","props","isActive","setIsActive","useState","position","setPosition","magnetRef","useRef","useEffect","handleMouseMove","left","top","width","height","centerX","centerY","distX","distY","offsetX","offsetY","transitionStyle","jsx","magnet_default"],"mappings":"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","file":"index.mjs","sourcesContent":["\"use client\";\r\n\r\nimport { useState, useEffect, useRef } from \"react\";\r\n\r\ninterface MagnetProps {\r\n children: React.ReactNode;\r\n padding?: number;\r\n disabled?: boolean;\r\n magnetStrength?: number;\r\n activeTransition?: string;\r\n inactiveTransition?: string;\r\n wrapperClassName?: string;\r\n innerClassName?: string;\r\n}\r\n\r\nexport function Magnet({\r\n children,\r\n padding = 100,\r\n disabled = false,\r\n magnetStrength = 8,\r\n activeTransition = \"transform 0.8s ease-out\",\r\n inactiveTransition = \"transform 1.2s ease-in-out\",\r\n wrapperClassName = \"\",\r\n innerClassName = \"\",\r\n ...props\r\n}: MagnetProps & React.HTMLAttributes<HTMLDivElement>) {\r\n const [isActive, setIsActive] = useState(false);\r\n const [position, setPosition] = useState({ x: 0, y: 0 });\r\n const magnetRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n if (disabled) {\r\n setPosition({ x: 0, y: 0 });\r\n return;\r\n }\r\n\r\n const handleMouseMove = (e: MouseEvent) => {\r\n if (!magnetRef.current) return;\r\n\r\n const { left, top, width, height } =\r\n magnetRef.current.getBoundingClientRect();\r\n const centerX = left + width / 2;\r\n const centerY = top + height / 2;\r\n\r\n const distX = Math.abs(centerX - e.clientX);\r\n const distY = Math.abs(centerY - e.clientY);\r\n\r\n if (distX < width / 2 + padding && distY < height / 2 + padding) {\r\n setIsActive(true);\r\n\r\n const offsetX = (e.clientX - centerX) / magnetStrength;\r\n const offsetY = (e.clientY - centerY) / magnetStrength;\r\n setPosition({ x: offsetX, y: offsetY });\r\n } else {\r\n setIsActive(false);\r\n setPosition({ x: 0, y: 0 });\r\n }\r\n };\r\n\r\n window.addEventListener(\"mousemove\", handleMouseMove);\r\n return () => {\r\n window.removeEventListener(\"mousemove\", handleMouseMove);\r\n };\r\n }, [padding, disabled, magnetStrength]);\r\n\r\n const transitionStyle = isActive ? activeTransition : inactiveTransition;\r\n\r\n return (\r\n <div\r\n ref={magnetRef}\r\n className={wrapperClassName}\r\n style={{ position: \"relative\", display: \"inline-block\" }}\r\n {...props}\r\n >\r\n <div\r\n className={innerClassName}\r\n style={{\r\n transform: `translate3d(${position.x}px, ${position.y}px, 0)`,\r\n transition: transitionStyle,\r\n willChange: \"transform\",\r\n }}\r\n >\r\n {children}\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport default Magnet;\r\n"]}
@@ -0,0 +1,2 @@
1
+ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var react=require('react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),jsxRuntime=require('react/jsx-runtime');function u(...r){return tailwindMerge.twMerge(clsx.clsx(r))}function A({rows:r=9,columns:a=9,containerSize:c="60vmin",lineColor:h="#a1a1aa",lineWidth:y="0.8vmin",lineHeight:v="5vmin",baseAngle:x=0,className:M="",style:b={}}){let l=react.useRef(null);react.useEffect(()=>{let s=l.current;if(!s)return;let t=s.querySelectorAll("span"),m=e=>{t.forEach(n=>{let o=n.getBoundingClientRect(),P=o.x+o.width/2,d=o.y+o.height/2,i=e.x-P,p=e.y-d,R=Math.sqrt(p*p+i*i)||1,E=Math.acos(i/R)*180/Math.PI*(e.y>d?1:-1);n.style.setProperty("--rotate",`${E}deg`);});},g=e=>{m({x:e.clientX,y:e.clientY});};if(window.addEventListener("pointermove",g),t.length){let e=Math.floor(t.length/2),n=t[e].getBoundingClientRect();m({x:n.x,y:n.y});}return ()=>window.removeEventListener("pointermove",g)},[]);let w=r*a,C=Array.from({length:w},(s,t)=>jsxRuntime.jsx("span",{style:{"--rotate":`${x}deg`,backgroundColor:h,width:y,height:v,transform:"rotate(var(--rotate))",transition:"transform 0.3s ease",borderRadius:"9999px"}},t));return jsxRuntime.jsx("div",{ref:l,className:u("place-items-center",M),style:{display:"grid",gridTemplateColumns:`repeat(${a}, 1fr)`,gridTemplateRows:`repeat(${r}, 1fr)`,width:c,height:c,...b},children:C})}var N=A;exports.MagnetLines=A;exports.default=N;//# sourceMappingURL=index.js.map
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/cn.ts","../../src/magnet-lines/index.tsx"],"names":["cn","inputs","twMerge","clsx","MagnetLines","rows","columns","containerSize","lineColor","lineWidth","lineHeight","baseAngle","className","style","containerRef","useRef","useEffect","container","items","onPointerMove","pointer","item","rect","centerX","centerY","b","a","c","r","handlePointerMove","middleIndex","total","spans","_","i","jsx","magnet_lines_default"],"mappings":"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","file":"index.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs));\r\n}\r\n","\"use client\";\r\n\r\nimport { useRef, useEffect } from \"react\";\r\nimport { cn } from \"../utils/cn\";\r\n\r\nexport interface MagnetLinesProps {\r\n rows?: number;\r\n columns?: number;\r\n containerSize?: string;\r\n lineColor?: string;\r\n lineWidth?: string;\r\n lineHeight?: string;\r\n baseAngle?: number;\r\n className?: string;\r\n style?: React.CSSProperties;\r\n}\r\n\r\nexport function MagnetLines({\r\n rows = 9,\r\n columns = 9,\r\n containerSize = \"60vmin\",\r\n lineColor = \"#a1a1aa\",\r\n lineWidth = \"0.8vmin\",\r\n lineHeight = \"5vmin\",\r\n baseAngle = 0,\r\n className = \"\",\r\n style = {},\r\n}: MagnetLinesProps) {\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n const container = containerRef.current;\r\n if (!container) return;\r\n\r\n const items = container.querySelectorAll(\"span\");\r\n\r\n const onPointerMove = (pointer: { x: number; y: number }) => {\r\n items.forEach((item) => {\r\n const rect = item.getBoundingClientRect();\r\n const centerX = rect.x + rect.width / 2;\r\n const centerY = rect.y + rect.height / 2;\r\n\r\n const b = pointer.x - centerX;\r\n const a = pointer.y - centerY;\r\n const c = Math.sqrt(a * a + b * b) || 1;\r\n const r = ((Math.acos(b / c) * 180) / Math.PI) * (pointer.y > centerY ? 1 : -1);\r\n\r\n (item as HTMLElement).style.setProperty(\"--rotate\", `${r}deg`);\r\n });\r\n };\r\n\r\n const handlePointerMove = (e: PointerEvent) => {\r\n onPointerMove({ x: e.clientX, y: e.clientY });\r\n };\r\n\r\n window.addEventListener(\"pointermove\", handlePointerMove);\r\n\r\n if (items.length) {\r\n const middleIndex = Math.floor(items.length / 2);\r\n const rect = items[middleIndex].getBoundingClientRect();\r\n onPointerMove({ x: rect.x, y: rect.y });\r\n }\r\n\r\n return () => window.removeEventListener(\"pointermove\", handlePointerMove);\r\n }, []);\r\n\r\n const total = rows * columns;\r\n const spans = Array.from({ length: total }, (_, i) => (\r\n <span\r\n key={i}\r\n style={{\r\n \"--rotate\": `${baseAngle}deg`,\r\n backgroundColor: lineColor,\r\n width: lineWidth,\r\n height: lineHeight,\r\n transform: \"rotate(var(--rotate))\",\r\n transition: \"transform 0.3s ease\",\r\n borderRadius: \"9999px\",\r\n } as React.CSSProperties}\r\n />\r\n ));\r\n\r\n return (\r\n <div\r\n ref={containerRef}\r\n className={cn(\"place-items-center\", className)}\r\n style={{\r\n display: \"grid\",\r\n gridTemplateColumns: `repeat(${columns}, 1fr)`,\r\n gridTemplateRows: `repeat(${rows}, 1fr)`,\r\n width: containerSize,\r\n height: containerSize,\r\n ...style,\r\n }}\r\n >\r\n {spans}\r\n </div>\r\n );\r\n}\r\n\r\nexport default MagnetLines;\r\n"]}
@@ -0,0 +1,2 @@
1
+ import {useRef,useEffect}from'react';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {jsx}from'react/jsx-runtime';function u(...r){return twMerge(clsx(r))}function A({rows:r=9,columns:a=9,containerSize:c="60vmin",lineColor:h="#a1a1aa",lineWidth:y="0.8vmin",lineHeight:v="5vmin",baseAngle:x=0,className:M="",style:b={}}){let l=useRef(null);useEffect(()=>{let s=l.current;if(!s)return;let t=s.querySelectorAll("span"),m=e=>{t.forEach(n=>{let o=n.getBoundingClientRect(),P=o.x+o.width/2,d=o.y+o.height/2,i=e.x-P,p=e.y-d,R=Math.sqrt(p*p+i*i)||1,E=Math.acos(i/R)*180/Math.PI*(e.y>d?1:-1);n.style.setProperty("--rotate",`${E}deg`);});},g=e=>{m({x:e.clientX,y:e.clientY});};if(window.addEventListener("pointermove",g),t.length){let e=Math.floor(t.length/2),n=t[e].getBoundingClientRect();m({x:n.x,y:n.y});}return ()=>window.removeEventListener("pointermove",g)},[]);let w=r*a,C=Array.from({length:w},(s,t)=>jsx("span",{style:{"--rotate":`${x}deg`,backgroundColor:h,width:y,height:v,transform:"rotate(var(--rotate))",transition:"transform 0.3s ease",borderRadius:"9999px"}},t));return jsx("div",{ref:l,className:u("place-items-center",M),style:{display:"grid",gridTemplateColumns:`repeat(${a}, 1fr)`,gridTemplateRows:`repeat(${r}, 1fr)`,width:c,height:c,...b},children:C})}var N=A;export{A as MagnetLines,N as default};//# sourceMappingURL=index.mjs.map
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/cn.ts","../../src/magnet-lines/index.tsx"],"names":["cn","inputs","twMerge","clsx","MagnetLines","rows","columns","containerSize","lineColor","lineWidth","lineHeight","baseAngle","className","style","containerRef","useRef","useEffect","container","items","onPointerMove","pointer","item","rect","centerX","centerY","b","a","c","r","handlePointerMove","middleIndex","total","spans","_","i","jsx","magnet_lines_default"],"mappings":"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","file":"index.mjs","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs));\r\n}\r\n","\"use client\";\r\n\r\nimport { useRef, useEffect } from \"react\";\r\nimport { cn } from \"../utils/cn\";\r\n\r\nexport interface MagnetLinesProps {\r\n rows?: number;\r\n columns?: number;\r\n containerSize?: string;\r\n lineColor?: string;\r\n lineWidth?: string;\r\n lineHeight?: string;\r\n baseAngle?: number;\r\n className?: string;\r\n style?: React.CSSProperties;\r\n}\r\n\r\nexport function MagnetLines({\r\n rows = 9,\r\n columns = 9,\r\n containerSize = \"60vmin\",\r\n lineColor = \"#a1a1aa\",\r\n lineWidth = \"0.8vmin\",\r\n lineHeight = \"5vmin\",\r\n baseAngle = 0,\r\n className = \"\",\r\n style = {},\r\n}: MagnetLinesProps) {\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n const container = containerRef.current;\r\n if (!container) return;\r\n\r\n const items = container.querySelectorAll(\"span\");\r\n\r\n const onPointerMove = (pointer: { x: number; y: number }) => {\r\n items.forEach((item) => {\r\n const rect = item.getBoundingClientRect();\r\n const centerX = rect.x + rect.width / 2;\r\n const centerY = rect.y + rect.height / 2;\r\n\r\n const b = pointer.x - centerX;\r\n const a = pointer.y - centerY;\r\n const c = Math.sqrt(a * a + b * b) || 1;\r\n const r = ((Math.acos(b / c) * 180) / Math.PI) * (pointer.y > centerY ? 1 : -1);\r\n\r\n (item as HTMLElement).style.setProperty(\"--rotate\", `${r}deg`);\r\n });\r\n };\r\n\r\n const handlePointerMove = (e: PointerEvent) => {\r\n onPointerMove({ x: e.clientX, y: e.clientY });\r\n };\r\n\r\n window.addEventListener(\"pointermove\", handlePointerMove);\r\n\r\n if (items.length) {\r\n const middleIndex = Math.floor(items.length / 2);\r\n const rect = items[middleIndex].getBoundingClientRect();\r\n onPointerMove({ x: rect.x, y: rect.y });\r\n }\r\n\r\n return () => window.removeEventListener(\"pointermove\", handlePointerMove);\r\n }, []);\r\n\r\n const total = rows * columns;\r\n const spans = Array.from({ length: total }, (_, i) => (\r\n <span\r\n key={i}\r\n style={{\r\n \"--rotate\": `${baseAngle}deg`,\r\n backgroundColor: lineColor,\r\n width: lineWidth,\r\n height: lineHeight,\r\n transform: \"rotate(var(--rotate))\",\r\n transition: \"transform 0.3s ease\",\r\n borderRadius: \"9999px\",\r\n } as React.CSSProperties}\r\n />\r\n ));\r\n\r\n return (\r\n <div\r\n ref={containerRef}\r\n className={cn(\"place-items-center\", className)}\r\n style={{\r\n display: \"grid\",\r\n gridTemplateColumns: `repeat(${columns}, 1fr)`,\r\n gridTemplateRows: `repeat(${rows}, 1fr)`,\r\n width: containerSize,\r\n height: containerSize,\r\n ...style,\r\n }}\r\n >\r\n {spans}\r\n </div>\r\n );\r\n}\r\n\r\nexport default MagnetLines;\r\n"]}
@@ -0,0 +1,3 @@
1
+ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var framerMotion=require('framer-motion'),react=require('react'),jsxRuntime=require('react/jsx-runtime');var x=4,w=[{id:"member-1",avatarUrl:"https://i.pravatar.cc/150?img=1",name:"Team Member 1"},{id:"member-2",avatarUrl:"https://i.pravatar.cc/150?img=2",name:"Team Member 2"},{id:"member-3",avatarUrl:"https://i.pravatar.cc/150?img=3",name:"Team Member 3"},{id:"member-4",avatarUrl:"https://i.pravatar.cc/150?img=4",name:"Team Member 4"}],r={container:{initial:{opacity:0,y:20},animate:{opacity:1,y:0},exit:{opacity:0,y:-20}},avatar:{initial:{opacity:0,scale:.8},animate:{opacity:1,scale:1,transition:{duration:.3}},exit:{opacity:0,scale:.8,transition:{duration:.15}}},vibration:{initial:{x:0},animate:{x:[-5,5,-5,5,0],transition:{duration:.3}}},number:{initial:{scale:.8,opacity:0},animate:{scale:1,opacity:1,transition:{type:"spring",stiffness:400,damping:25}}}};function T({defaultValue:g=1,onChange:o,className:z="",members:h=w,maxSize:s=x}){let[t,c]=react.useState(g),[l,m]=react.useState(false),d=e=>{if(e.preventDefault(),t<s){let a=t+1;c(a),o?.(a);}else u();},b=e=>{if(e.preventDefault(),t>1){let a=t-1;c(a),o?.(a);}else u();},u=()=>{m(true),setTimeout(()=>m(false),300);},f=(e,a)=>{(e.key==="Enter"||e.key===" ")&&(e.preventDefault(),a==="increment"?d(e):b(e));},y=()=>h.slice(0,t).map((e,a)=>jsxRuntime.jsx(framerMotion.motion.div,{variants:r.avatar,initial:"initial",animate:"animate",exit:"exit",className:"flex items-center justify-center",style:{zIndex:t-a,marginLeft:a===0?0:-24},children:jsxRuntime.jsx("img",{src:e.avatarUrl,width:96,height:96,alt:e.name,className:"rounded-full object-cover w-24 h-24 shadow-lg bg-gradient-to-b from-white/5 to-white/20 dark:from-white/5 dark:to-black/20 backdrop-blur-sm hover:shadow-xl transition-all duration-300 border border-white/10 dark:border-white/5"})},e.id));return jsxRuntime.jsx(framerMotion.motion.div,{variants:r.container,initial:"initial",animate:"animate",exit:"exit",className:`flex w-full flex-col items-center justify-center gap-8 ${z}`,children:jsxRuntime.jsxs("fieldset",{className:"w-full",children:[jsxRuntime.jsx("legend",{className:"sr-only",children:"Team size selector"}),jsxRuntime.jsx("div",{className:"relative h-24 w-full flex justify-center",children:jsxRuntime.jsx(framerMotion.AnimatePresence,{mode:"popLayout",children:y()})}),jsxRuntime.jsxs(framerMotion.motion.div,{variants:l?r.vibration:void 0,initial:"initial",animate:l?"animate":"initial",className:"flex items-center justify-center gap-8 mt-8",children:[jsxRuntime.jsx("button",{type:"button",onClick:b,onKeyDown:e=>f(e,"decrement"),disabled:t<=1,"aria-label":"Decrease team size",className:"h-12 w-12 rounded-full bg-gradient-to-b from-white to-zinc-50 dark:from-zinc-800 dark:to-zinc-900 border border-zinc-200/80 dark:border-zinc-700/80 shadow-md hover:shadow-lg hover:border-zinc-300 dark:hover:border-zinc-600 active:from-zinc-50 active:to-zinc-100 dark:active:from-zinc-900 dark:active:to-zinc-800 text-zinc-900 dark:text-zinc-100 disabled:opacity-40 disabled:cursor-not-allowed transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-500/30 dark:focus-visible:ring-zinc-400/30 focus-visible:ring-offset-2",children:jsxRuntime.jsx("span",{className:"text-2xl font-medium select-none",children:"-"})}),jsxRuntime.jsx(framerMotion.motion.output,{variants:r.number,initial:"initial",animate:"animate",className:"text-2xl font-medium bg-clip-text text-transparent bg-gradient-to-b from-zinc-800 to-zinc-600 dark:from-zinc-200 dark:to-zinc-400 select-none","aria-label":`Current team size: ${t}`,children:t},t),jsxRuntime.jsx("button",{type:"button",onClick:d,onKeyDown:e=>f(e,"increment"),disabled:t>=s,"aria-label":"Increase team size",className:"h-12 w-12 rounded-full bg-gradient-to-b from-white to-zinc-50 dark:from-zinc-800 dark:to-zinc-900 border border-zinc-200/80 dark:border-zinc-700/80 shadow-md hover:shadow-lg hover:border-zinc-300 dark:hover:border-zinc-600 active:from-zinc-50 active:to-zinc-100 dark:active:from-zinc-900 dark:active:to-zinc-800 text-zinc-900 dark:text-zinc-100 disabled:opacity-40 disabled:cursor-not-allowed transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-500/30 dark:focus-visible:ring-zinc-400/30 focus-visible:ring-offset-2",children:jsxRuntime.jsx("span",{className:"text-2xl font-medium select-none",children:"+"})})]})]})})}var E=T;
2
+ exports.TeamSelector=T;exports.default=E;//# sourceMappingURL=index.js.map
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/team-selector/index.tsx"],"names":["MAX_TEAM_SIZE","DEFAULT_TEAM_MEMBERS","animations","TeamSelector","defaultValue","onChange","className","members","maxSize","peopleCount","setPeopleCount","useState","isVibrating","setIsVibrating","handleIncrement","newCount","triggerVibration","handleDecrement","handleKeyDown","action","renderAvatars","member","index","jsx","motion","jsxs","AnimatePresence","team_selector_default"],"mappings":"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","file":"index.js","sourcesContent":["\"use client\";\r\n\r\nimport { AnimatePresence, motion, type Variants } from \"framer-motion\";\r\nimport { useState } from \"react\";\r\n\r\nconst MAX_TEAM_SIZE = 4;\r\n\r\ninterface TeamMember {\r\n id: string;\r\n avatarUrl: string;\r\n name: string;\r\n}\r\n\r\nconst DEFAULT_TEAM_MEMBERS: TeamMember[] = [\r\n {\r\n id: \"member-1\",\r\n avatarUrl: \"https://i.pravatar.cc/150?img=1\",\r\n name: \"Team Member 1\",\r\n },\r\n {\r\n id: \"member-2\",\r\n avatarUrl: \"https://i.pravatar.cc/150?img=2\",\r\n name: \"Team Member 2\",\r\n },\r\n {\r\n id: \"member-3\",\r\n avatarUrl: \"https://i.pravatar.cc/150?img=3\",\r\n name: \"Team Member 3\",\r\n },\r\n {\r\n id: \"member-4\",\r\n avatarUrl: \"https://i.pravatar.cc/150?img=4\",\r\n name: \"Team Member 4\",\r\n },\r\n];\r\n\r\nconst animations = {\r\n container: {\r\n initial: { opacity: 0, y: 20 },\r\n animate: { opacity: 1, y: 0 },\r\n exit: { opacity: 0, y: -20 },\r\n } satisfies Variants,\r\n avatar: {\r\n initial: { opacity: 0, scale: 0.8 },\r\n animate: {\r\n opacity: 1,\r\n scale: 1,\r\n transition: { duration: 0.3 },\r\n },\r\n exit: {\r\n opacity: 0,\r\n scale: 0.8,\r\n transition: { duration: 0.15 },\r\n },\r\n } satisfies Variants,\r\n vibration: {\r\n initial: { x: 0 },\r\n animate: {\r\n x: [-5, 5, -5, 5, 0],\r\n transition: { duration: 0.3 },\r\n },\r\n } satisfies Variants,\r\n number: {\r\n initial: { scale: 0.8, opacity: 0 },\r\n animate: {\r\n scale: 1,\r\n opacity: 1,\r\n transition: {\r\n type: \"spring\",\r\n stiffness: 400,\r\n damping: 25,\r\n },\r\n },\r\n } satisfies Variants,\r\n};\r\n\r\nexport interface TeamSelectorProps {\r\n defaultValue?: number;\r\n onChange?: (size: number) => void;\r\n className?: string;\r\n members?: TeamMember[];\r\n maxSize?: number;\r\n}\r\n\r\nexport function TeamSelector({\r\n defaultValue = 1,\r\n onChange,\r\n className = \"\",\r\n members = DEFAULT_TEAM_MEMBERS,\r\n maxSize = MAX_TEAM_SIZE,\r\n}: TeamSelectorProps) {\r\n const [peopleCount, setPeopleCount] = useState(defaultValue);\r\n const [isVibrating, setIsVibrating] = useState(false);\r\n\r\n const handleIncrement = (e: React.MouseEvent | React.KeyboardEvent) => {\r\n e.preventDefault();\r\n if (peopleCount < maxSize) {\r\n const newCount = peopleCount + 1;\r\n setPeopleCount(newCount);\r\n onChange?.(newCount);\r\n } else {\r\n triggerVibration();\r\n }\r\n };\r\n\r\n const handleDecrement = (e: React.MouseEvent | React.KeyboardEvent) => {\r\n e.preventDefault();\r\n if (peopleCount > 1) {\r\n const newCount = peopleCount - 1;\r\n setPeopleCount(newCount);\r\n onChange?.(newCount);\r\n } else {\r\n triggerVibration();\r\n }\r\n };\r\n\r\n const triggerVibration = () => {\r\n setIsVibrating(true);\r\n setTimeout(() => setIsVibrating(false), 300);\r\n };\r\n\r\n const handleKeyDown = (\r\n e: React.KeyboardEvent,\r\n action: \"increment\" | \"decrement\"\r\n ) => {\r\n if (e.key === \"Enter\" || e.key === \" \") {\r\n e.preventDefault();\r\n action === \"increment\" ? handleIncrement(e) : handleDecrement(e);\r\n }\r\n };\r\n\r\n const renderAvatars = () =>\r\n members.slice(0, peopleCount).map((member, index) => (\r\n <motion.div\r\n key={member.id}\r\n variants={animations.avatar}\r\n initial=\"initial\"\r\n animate=\"animate\"\r\n exit=\"exit\"\r\n className=\"flex items-center justify-center\"\r\n style={{\r\n zIndex: peopleCount - index,\r\n marginLeft: index === 0 ? 0 : -24,\r\n }}\r\n >\r\n <img\r\n src={member.avatarUrl}\r\n width={96}\r\n height={96}\r\n alt={member.name}\r\n className=\"rounded-full object-cover w-24 h-24 shadow-lg bg-gradient-to-b from-white/5 to-white/20 dark:from-white/5 dark:to-black/20 backdrop-blur-sm hover:shadow-xl transition-all duration-300 border border-white/10 dark:border-white/5\"\r\n />\r\n </motion.div>\r\n ));\r\n\r\n return (\r\n <motion.div\r\n variants={animations.container}\r\n initial=\"initial\"\r\n animate=\"animate\"\r\n exit=\"exit\"\r\n className={`flex w-full flex-col items-center justify-center gap-8 ${className}`}\r\n >\r\n <fieldset className=\"w-full\">\r\n <legend className=\"sr-only\">Team size selector</legend>\r\n <div className=\"relative h-24 w-full flex justify-center\">\r\n <AnimatePresence mode=\"popLayout\">{renderAvatars()}</AnimatePresence>\r\n </div>\r\n\r\n <motion.div\r\n variants={isVibrating ? animations.vibration : undefined}\r\n initial=\"initial\"\r\n animate={isVibrating ? \"animate\" : \"initial\"}\r\n className=\"flex items-center justify-center gap-8 mt-8\"\r\n >\r\n <button\r\n type=\"button\"\r\n onClick={handleDecrement}\r\n onKeyDown={(e) => handleKeyDown(e, \"decrement\")}\r\n disabled={peopleCount <= 1}\r\n aria-label=\"Decrease team size\"\r\n className=\"h-12 w-12 rounded-full bg-gradient-to-b from-white to-zinc-50 dark:from-zinc-800 dark:to-zinc-900 border border-zinc-200/80 dark:border-zinc-700/80 shadow-md hover:shadow-lg hover:border-zinc-300 dark:hover:border-zinc-600 active:from-zinc-50 active:to-zinc-100 dark:active:from-zinc-900 dark:active:to-zinc-800 text-zinc-900 dark:text-zinc-100 disabled:opacity-40 disabled:cursor-not-allowed transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-500/30 dark:focus-visible:ring-zinc-400/30 focus-visible:ring-offset-2\"\r\n >\r\n <span className=\"text-2xl font-medium select-none\">-</span>\r\n </button>\r\n\r\n <motion.output\r\n key={peopleCount}\r\n variants={animations.number}\r\n initial=\"initial\"\r\n animate=\"animate\"\r\n className=\"text-2xl font-medium bg-clip-text text-transparent bg-gradient-to-b from-zinc-800 to-zinc-600 dark:from-zinc-200 dark:to-zinc-400 select-none\"\r\n aria-label={`Current team size: ${peopleCount}`}\r\n >\r\n {peopleCount}\r\n </motion.output>\r\n\r\n <button\r\n type=\"button\"\r\n onClick={handleIncrement}\r\n onKeyDown={(e) => handleKeyDown(e, \"increment\")}\r\n disabled={peopleCount >= maxSize}\r\n aria-label=\"Increase team size\"\r\n className=\"h-12 w-12 rounded-full bg-gradient-to-b from-white to-zinc-50 dark:from-zinc-800 dark:to-zinc-900 border border-zinc-200/80 dark:border-zinc-700/80 shadow-md hover:shadow-lg hover:border-zinc-300 dark:hover:border-zinc-600 active:from-zinc-50 active:to-zinc-100 dark:active:from-zinc-900 dark:active:to-zinc-800 text-zinc-900 dark:text-zinc-100 disabled:opacity-40 disabled:cursor-not-allowed transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-500/30 dark:focus-visible:ring-zinc-400/30 focus-visible:ring-offset-2\"\r\n >\r\n <span className=\"text-2xl font-medium select-none\">+</span>\r\n </button>\r\n </motion.div>\r\n </fieldset>\r\n </motion.div>\r\n );\r\n}\r\n\r\nexport default TeamSelector;\r\n"]}
@@ -0,0 +1,3 @@
1
+ import {motion,AnimatePresence}from'framer-motion';import {useState}from'react';import {jsx,jsxs}from'react/jsx-runtime';var x=4,w=[{id:"member-1",avatarUrl:"https://i.pravatar.cc/150?img=1",name:"Team Member 1"},{id:"member-2",avatarUrl:"https://i.pravatar.cc/150?img=2",name:"Team Member 2"},{id:"member-3",avatarUrl:"https://i.pravatar.cc/150?img=3",name:"Team Member 3"},{id:"member-4",avatarUrl:"https://i.pravatar.cc/150?img=4",name:"Team Member 4"}],r={container:{initial:{opacity:0,y:20},animate:{opacity:1,y:0},exit:{opacity:0,y:-20}},avatar:{initial:{opacity:0,scale:.8},animate:{opacity:1,scale:1,transition:{duration:.3}},exit:{opacity:0,scale:.8,transition:{duration:.15}}},vibration:{initial:{x:0},animate:{x:[-5,5,-5,5,0],transition:{duration:.3}}},number:{initial:{scale:.8,opacity:0},animate:{scale:1,opacity:1,transition:{type:"spring",stiffness:400,damping:25}}}};function T({defaultValue:g=1,onChange:o,className:z="",members:h=w,maxSize:s=x}){let[t,c]=useState(g),[l,m]=useState(false),d=e=>{if(e.preventDefault(),t<s){let a=t+1;c(a),o?.(a);}else u();},b=e=>{if(e.preventDefault(),t>1){let a=t-1;c(a),o?.(a);}else u();},u=()=>{m(true),setTimeout(()=>m(false),300);},f=(e,a)=>{(e.key==="Enter"||e.key===" ")&&(e.preventDefault(),a==="increment"?d(e):b(e));},y=()=>h.slice(0,t).map((e,a)=>jsx(motion.div,{variants:r.avatar,initial:"initial",animate:"animate",exit:"exit",className:"flex items-center justify-center",style:{zIndex:t-a,marginLeft:a===0?0:-24},children:jsx("img",{src:e.avatarUrl,width:96,height:96,alt:e.name,className:"rounded-full object-cover w-24 h-24 shadow-lg bg-gradient-to-b from-white/5 to-white/20 dark:from-white/5 dark:to-black/20 backdrop-blur-sm hover:shadow-xl transition-all duration-300 border border-white/10 dark:border-white/5"})},e.id));return jsx(motion.div,{variants:r.container,initial:"initial",animate:"animate",exit:"exit",className:`flex w-full flex-col items-center justify-center gap-8 ${z}`,children:jsxs("fieldset",{className:"w-full",children:[jsx("legend",{className:"sr-only",children:"Team size selector"}),jsx("div",{className:"relative h-24 w-full flex justify-center",children:jsx(AnimatePresence,{mode:"popLayout",children:y()})}),jsxs(motion.div,{variants:l?r.vibration:void 0,initial:"initial",animate:l?"animate":"initial",className:"flex items-center justify-center gap-8 mt-8",children:[jsx("button",{type:"button",onClick:b,onKeyDown:e=>f(e,"decrement"),disabled:t<=1,"aria-label":"Decrease team size",className:"h-12 w-12 rounded-full bg-gradient-to-b from-white to-zinc-50 dark:from-zinc-800 dark:to-zinc-900 border border-zinc-200/80 dark:border-zinc-700/80 shadow-md hover:shadow-lg hover:border-zinc-300 dark:hover:border-zinc-600 active:from-zinc-50 active:to-zinc-100 dark:active:from-zinc-900 dark:active:to-zinc-800 text-zinc-900 dark:text-zinc-100 disabled:opacity-40 disabled:cursor-not-allowed transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-500/30 dark:focus-visible:ring-zinc-400/30 focus-visible:ring-offset-2",children:jsx("span",{className:"text-2xl font-medium select-none",children:"-"})}),jsx(motion.output,{variants:r.number,initial:"initial",animate:"animate",className:"text-2xl font-medium bg-clip-text text-transparent bg-gradient-to-b from-zinc-800 to-zinc-600 dark:from-zinc-200 dark:to-zinc-400 select-none","aria-label":`Current team size: ${t}`,children:t},t),jsx("button",{type:"button",onClick:d,onKeyDown:e=>f(e,"increment"),disabled:t>=s,"aria-label":"Increase team size",className:"h-12 w-12 rounded-full bg-gradient-to-b from-white to-zinc-50 dark:from-zinc-800 dark:to-zinc-900 border border-zinc-200/80 dark:border-zinc-700/80 shadow-md hover:shadow-lg hover:border-zinc-300 dark:hover:border-zinc-600 active:from-zinc-50 active:to-zinc-100 dark:active:from-zinc-900 dark:active:to-zinc-800 text-zinc-900 dark:text-zinc-100 disabled:opacity-40 disabled:cursor-not-allowed transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-500/30 dark:focus-visible:ring-zinc-400/30 focus-visible:ring-offset-2",children:jsx("span",{className:"text-2xl font-medium select-none",children:"+"})})]})]})})}var E=T;
2
+ export{T as TeamSelector,E as default};//# sourceMappingURL=index.mjs.map
3
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/team-selector/index.tsx"],"names":["MAX_TEAM_SIZE","DEFAULT_TEAM_MEMBERS","animations","TeamSelector","defaultValue","onChange","className","members","maxSize","peopleCount","setPeopleCount","useState","isVibrating","setIsVibrating","handleIncrement","newCount","triggerVibration","handleDecrement","handleKeyDown","action","renderAvatars","member","index","jsx","motion","jsxs","AnimatePresence","team_selector_default"],"mappings":"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","file":"index.mjs","sourcesContent":["\"use client\";\r\n\r\nimport { AnimatePresence, motion, type Variants } from \"framer-motion\";\r\nimport { useState } from \"react\";\r\n\r\nconst MAX_TEAM_SIZE = 4;\r\n\r\ninterface TeamMember {\r\n id: string;\r\n avatarUrl: string;\r\n name: string;\r\n}\r\n\r\nconst DEFAULT_TEAM_MEMBERS: TeamMember[] = [\r\n {\r\n id: \"member-1\",\r\n avatarUrl: \"https://i.pravatar.cc/150?img=1\",\r\n name: \"Team Member 1\",\r\n },\r\n {\r\n id: \"member-2\",\r\n avatarUrl: \"https://i.pravatar.cc/150?img=2\",\r\n name: \"Team Member 2\",\r\n },\r\n {\r\n id: \"member-3\",\r\n avatarUrl: \"https://i.pravatar.cc/150?img=3\",\r\n name: \"Team Member 3\",\r\n },\r\n {\r\n id: \"member-4\",\r\n avatarUrl: \"https://i.pravatar.cc/150?img=4\",\r\n name: \"Team Member 4\",\r\n },\r\n];\r\n\r\nconst animations = {\r\n container: {\r\n initial: { opacity: 0, y: 20 },\r\n animate: { opacity: 1, y: 0 },\r\n exit: { opacity: 0, y: -20 },\r\n } satisfies Variants,\r\n avatar: {\r\n initial: { opacity: 0, scale: 0.8 },\r\n animate: {\r\n opacity: 1,\r\n scale: 1,\r\n transition: { duration: 0.3 },\r\n },\r\n exit: {\r\n opacity: 0,\r\n scale: 0.8,\r\n transition: { duration: 0.15 },\r\n },\r\n } satisfies Variants,\r\n vibration: {\r\n initial: { x: 0 },\r\n animate: {\r\n x: [-5, 5, -5, 5, 0],\r\n transition: { duration: 0.3 },\r\n },\r\n } satisfies Variants,\r\n number: {\r\n initial: { scale: 0.8, opacity: 0 },\r\n animate: {\r\n scale: 1,\r\n opacity: 1,\r\n transition: {\r\n type: \"spring\",\r\n stiffness: 400,\r\n damping: 25,\r\n },\r\n },\r\n } satisfies Variants,\r\n};\r\n\r\nexport interface TeamSelectorProps {\r\n defaultValue?: number;\r\n onChange?: (size: number) => void;\r\n className?: string;\r\n members?: TeamMember[];\r\n maxSize?: number;\r\n}\r\n\r\nexport function TeamSelector({\r\n defaultValue = 1,\r\n onChange,\r\n className = \"\",\r\n members = DEFAULT_TEAM_MEMBERS,\r\n maxSize = MAX_TEAM_SIZE,\r\n}: TeamSelectorProps) {\r\n const [peopleCount, setPeopleCount] = useState(defaultValue);\r\n const [isVibrating, setIsVibrating] = useState(false);\r\n\r\n const handleIncrement = (e: React.MouseEvent | React.KeyboardEvent) => {\r\n e.preventDefault();\r\n if (peopleCount < maxSize) {\r\n const newCount = peopleCount + 1;\r\n setPeopleCount(newCount);\r\n onChange?.(newCount);\r\n } else {\r\n triggerVibration();\r\n }\r\n };\r\n\r\n const handleDecrement = (e: React.MouseEvent | React.KeyboardEvent) => {\r\n e.preventDefault();\r\n if (peopleCount > 1) {\r\n const newCount = peopleCount - 1;\r\n setPeopleCount(newCount);\r\n onChange?.(newCount);\r\n } else {\r\n triggerVibration();\r\n }\r\n };\r\n\r\n const triggerVibration = () => {\r\n setIsVibrating(true);\r\n setTimeout(() => setIsVibrating(false), 300);\r\n };\r\n\r\n const handleKeyDown = (\r\n e: React.KeyboardEvent,\r\n action: \"increment\" | \"decrement\"\r\n ) => {\r\n if (e.key === \"Enter\" || e.key === \" \") {\r\n e.preventDefault();\r\n action === \"increment\" ? handleIncrement(e) : handleDecrement(e);\r\n }\r\n };\r\n\r\n const renderAvatars = () =>\r\n members.slice(0, peopleCount).map((member, index) => (\r\n <motion.div\r\n key={member.id}\r\n variants={animations.avatar}\r\n initial=\"initial\"\r\n animate=\"animate\"\r\n exit=\"exit\"\r\n className=\"flex items-center justify-center\"\r\n style={{\r\n zIndex: peopleCount - index,\r\n marginLeft: index === 0 ? 0 : -24,\r\n }}\r\n >\r\n <img\r\n src={member.avatarUrl}\r\n width={96}\r\n height={96}\r\n alt={member.name}\r\n className=\"rounded-full object-cover w-24 h-24 shadow-lg bg-gradient-to-b from-white/5 to-white/20 dark:from-white/5 dark:to-black/20 backdrop-blur-sm hover:shadow-xl transition-all duration-300 border border-white/10 dark:border-white/5\"\r\n />\r\n </motion.div>\r\n ));\r\n\r\n return (\r\n <motion.div\r\n variants={animations.container}\r\n initial=\"initial\"\r\n animate=\"animate\"\r\n exit=\"exit\"\r\n className={`flex w-full flex-col items-center justify-center gap-8 ${className}`}\r\n >\r\n <fieldset className=\"w-full\">\r\n <legend className=\"sr-only\">Team size selector</legend>\r\n <div className=\"relative h-24 w-full flex justify-center\">\r\n <AnimatePresence mode=\"popLayout\">{renderAvatars()}</AnimatePresence>\r\n </div>\r\n\r\n <motion.div\r\n variants={isVibrating ? animations.vibration : undefined}\r\n initial=\"initial\"\r\n animate={isVibrating ? \"animate\" : \"initial\"}\r\n className=\"flex items-center justify-center gap-8 mt-8\"\r\n >\r\n <button\r\n type=\"button\"\r\n onClick={handleDecrement}\r\n onKeyDown={(e) => handleKeyDown(e, \"decrement\")}\r\n disabled={peopleCount <= 1}\r\n aria-label=\"Decrease team size\"\r\n className=\"h-12 w-12 rounded-full bg-gradient-to-b from-white to-zinc-50 dark:from-zinc-800 dark:to-zinc-900 border border-zinc-200/80 dark:border-zinc-700/80 shadow-md hover:shadow-lg hover:border-zinc-300 dark:hover:border-zinc-600 active:from-zinc-50 active:to-zinc-100 dark:active:from-zinc-900 dark:active:to-zinc-800 text-zinc-900 dark:text-zinc-100 disabled:opacity-40 disabled:cursor-not-allowed transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-500/30 dark:focus-visible:ring-zinc-400/30 focus-visible:ring-offset-2\"\r\n >\r\n <span className=\"text-2xl font-medium select-none\">-</span>\r\n </button>\r\n\r\n <motion.output\r\n key={peopleCount}\r\n variants={animations.number}\r\n initial=\"initial\"\r\n animate=\"animate\"\r\n className=\"text-2xl font-medium bg-clip-text text-transparent bg-gradient-to-b from-zinc-800 to-zinc-600 dark:from-zinc-200 dark:to-zinc-400 select-none\"\r\n aria-label={`Current team size: ${peopleCount}`}\r\n >\r\n {peopleCount}\r\n </motion.output>\r\n\r\n <button\r\n type=\"button\"\r\n onClick={handleIncrement}\r\n onKeyDown={(e) => handleKeyDown(e, \"increment\")}\r\n disabled={peopleCount >= maxSize}\r\n aria-label=\"Increase team size\"\r\n className=\"h-12 w-12 rounded-full bg-gradient-to-b from-white to-zinc-50 dark:from-zinc-800 dark:to-zinc-900 border border-zinc-200/80 dark:border-zinc-700/80 shadow-md hover:shadow-lg hover:border-zinc-300 dark:hover:border-zinc-600 active:from-zinc-50 active:to-zinc-100 dark:active:from-zinc-900 dark:active:to-zinc-800 text-zinc-900 dark:text-zinc-100 disabled:opacity-40 disabled:cursor-not-allowed transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-500/30 dark:focus-visible:ring-zinc-400/30 focus-visible:ring-offset-2\"\r\n >\r\n <span className=\"text-2xl font-medium select-none\">+</span>\r\n </button>\r\n </motion.div>\r\n </fieldset>\r\n </motion.div>\r\n );\r\n}\r\n\r\nexport default TeamSelector;\r\n"]}
@@ -0,0 +1,3 @@
1
+ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),jsxRuntime=require('react/jsx-runtime');function n(...a){return tailwindMerge.twMerge(clsx.clsx(a))}var m=({filled:a,className:s})=>jsxRuntime.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:a?"currentColor":"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:s,children:jsxRuntime.jsx("polygon",{points:"12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"})}),p=[{content:"This UI library has revolutionized how we build user interfaces. The animations are buttery smooth and the developer experience is incredible.",avatar:"https://i.pravatar.cc/150?img=1",name:"Eduardo Calvo",role:"CEO & Founder",stars:5},{content:"The design system is incredibly well thought out. Every component feels intentional and polished.",avatar:"https://i.pravatar.cc/150?img=2",name:"Drew Cano",role:"Head of Design",stars:5},{content:"Best UI library I've used. The TypeScript support is excellent and the components are highly customizable.",avatar:"https://i.pravatar.cc/150?img=3",name:"Marcus Johnson",role:"Lead Developer",stars:5},{content:"Our users love the smooth interactions. It's made our product feel premium and professional.",avatar:"https://i.pravatar.cc/150?img=4",name:"Emily Rodriguez",role:"Product Manager",stars:4}];function u({className:a="",title:s="Developer Reviews",description:o="See what the community is saying. Real feedback from developers building amazing user experiences.",testimonials:l=p}){return jsxRuntime.jsx("div",{className:n("min-h-[400px] w-full py-24",a),children:jsxRuntime.jsxs("div",{className:"container mx-auto w-full max-w-5xl px-6",children:[jsxRuntime.jsxs("div",{className:"mb-12",children:[jsxRuntime.jsx("h2",{className:"text-zinc-900 dark:text-zinc-100 text-4xl font-semibold",children:s}),jsxRuntime.jsx("p",{className:"text-zinc-600 dark:text-zinc-500 my-4 text-lg text-balance",children:o})]}),jsxRuntime.jsx("div",{className:"grid gap-6 lg:grid-cols-2",children:l.map(r=>jsxRuntime.jsxs("div",{className:"group hover:bg-zinc-50 dark:hover:bg-zinc-950 hover:border-zinc-400 dark:hover:border-zinc-700 rounded-2xl border border-zinc-300 dark:border-zinc-800 bg-white dark:bg-zinc-950 px-4 py-3 duration-200 transition-all hover:-translate-y-1",children:[jsxRuntime.jsx("div",{className:"flex gap-1",children:Array.from({length:5}).map((v,i)=>jsxRuntime.jsx(m,{filled:i<(r.stars||0),className:n("size-4 transition-colors duration-200",i<(r.stars||0)?"fill-pink-400 stroke-pink-400":"fill-zinc-300 dark:fill-zinc-700 stroke-zinc-400 dark:stroke-zinc-600")},`${r.name}-star-${i}`))}),jsxRuntime.jsx("p",{className:"text-zinc-900 dark:text-zinc-100 my-4",children:r.content}),jsxRuntime.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntime.jsx("img",{src:r.avatar,alt:r.name,className:"size-6 rounded-full border border-zinc-300 dark:border-zinc-700 object-cover"}),jsxRuntime.jsx("div",{className:"text-zinc-900 dark:text-zinc-100 text-sm font-medium",children:r.name}),jsxRuntime.jsx("span",{"aria-hidden":true,className:"bg-zinc-400 dark:bg-zinc-600 size-1 rounded-full"}),jsxRuntime.jsx("span",{className:"text-zinc-500 text-sm",children:r.role})]})]},r.name))})]})})}var z=u;
2
+ exports.TestimonialsStars=u;exports.default=z;//# sourceMappingURL=index.js.map
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/cn.ts","../../src/testimonials-stars/index.tsx"],"names":["cn","inputs","twMerge","clsx","StarIcon","filled","className","jsx","defaultTestimonials","TestimonialsStars","title","description","testimonials","jsxs","testimonial","_","testimonials_stars_default"],"mappings":"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","file":"index.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs));\r\n}\r\n","\"use client\";\r\n\r\nimport { cn } from \"../utils/cn\";\r\n\r\nconst StarIcon = ({ filled, className }: { filled: boolean; className?: string }) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"24\"\r\n height=\"24\"\r\n viewBox=\"0 0 24 24\"\r\n fill={filled ? \"currentColor\" : \"none\"}\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n className={className}\r\n >\r\n <polygon points=\"12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2\" />\r\n </svg>\r\n);\r\n\r\nexport interface TestimonialItem {\r\n content: string;\r\n avatar: string;\r\n name: string;\r\n role: string;\r\n stars?: number;\r\n}\r\n\r\ninterface TestimonialsStarsProps {\r\n className?: string;\r\n title?: string;\r\n description?: string;\r\n testimonials?: TestimonialItem[];\r\n}\r\n\r\nconst defaultTestimonials: TestimonialItem[] = [\r\n {\r\n content:\r\n \"This UI library has revolutionized how we build user interfaces. The animations are buttery smooth and the developer experience is incredible.\",\r\n avatar: \"https://i.pravatar.cc/150?img=1\",\r\n name: \"Eduardo Calvo\",\r\n role: \"CEO & Founder\",\r\n stars: 5,\r\n },\r\n {\r\n content:\r\n \"The design system is incredibly well thought out. Every component feels intentional and polished.\",\r\n avatar: \"https://i.pravatar.cc/150?img=2\",\r\n name: \"Drew Cano\",\r\n role: \"Head of Design\",\r\n stars: 5,\r\n },\r\n {\r\n content:\r\n \"Best UI library I've used. The TypeScript support is excellent and the components are highly customizable.\",\r\n avatar: \"https://i.pravatar.cc/150?img=3\",\r\n name: \"Marcus Johnson\",\r\n role: \"Lead Developer\",\r\n stars: 5,\r\n },\r\n {\r\n content:\r\n \"Our users love the smooth interactions. It's made our product feel premium and professional.\",\r\n avatar: \"https://i.pravatar.cc/150?img=4\",\r\n name: \"Emily Rodriguez\",\r\n role: \"Product Manager\",\r\n stars: 4,\r\n },\r\n];\r\n\r\nexport function TestimonialsStars({\r\n className = \"\",\r\n title = \"Developer Reviews\",\r\n description = \"See what the community is saying. Real feedback from developers building amazing user experiences.\",\r\n testimonials = defaultTestimonials,\r\n}: TestimonialsStarsProps) {\r\n return (\r\n <div className={cn(\"min-h-[400px] w-full py-24\", className)}>\r\n <div className=\"container mx-auto w-full max-w-5xl px-6\">\r\n <div className=\"mb-12\">\r\n <h2 className=\"text-zinc-900 dark:text-zinc-100 text-4xl font-semibold\">\r\n {title}\r\n </h2>\r\n <p className=\"text-zinc-600 dark:text-zinc-500 my-4 text-lg text-balance\">\r\n {description}\r\n </p>\r\n </div>\r\n\r\n <div className=\"grid gap-6 lg:grid-cols-2\">\r\n {testimonials.map((testimonial) => (\r\n <div\r\n key={testimonial.name}\r\n className=\"group hover:bg-zinc-50 dark:hover:bg-zinc-950 hover:border-zinc-400 dark:hover:border-zinc-700 rounded-2xl border border-zinc-300 dark:border-zinc-800 bg-white dark:bg-zinc-950 px-4 py-3 duration-200 transition-all hover:-translate-y-1\"\r\n >\r\n <div className=\"flex gap-1\">\r\n {Array.from({ length: 5 }).map((_, i) => (\r\n <StarIcon\r\n key={`${testimonial.name}-star-${i}`}\r\n filled={i < (testimonial.stars || 0)}\r\n className={cn(\r\n \"size-4 transition-colors duration-200\",\r\n i < (testimonial.stars || 0)\r\n ? \"fill-pink-400 stroke-pink-400\"\r\n : \"fill-zinc-300 dark:fill-zinc-700 stroke-zinc-400 dark:stroke-zinc-600\"\r\n )}\r\n />\r\n ))}\r\n </div>\r\n\r\n <p className=\"text-zinc-900 dark:text-zinc-100 my-4\">\r\n {testimonial.content}\r\n </p>\r\n\r\n <div className=\"flex items-center gap-2\">\r\n <img\r\n src={testimonial.avatar}\r\n alt={testimonial.name}\r\n className=\"size-6 rounded-full border border-zinc-300 dark:border-zinc-700 object-cover\"\r\n />\r\n <div className=\"text-zinc-900 dark:text-zinc-100 text-sm font-medium\">\r\n {testimonial.name}\r\n </div>\r\n <span\r\n aria-hidden\r\n className=\"bg-zinc-400 dark:bg-zinc-600 size-1 rounded-full\"\r\n />\r\n <span className=\"text-zinc-500 text-sm\">{testimonial.role}</span>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport default TestimonialsStars;\r\n"]}
@@ -0,0 +1,3 @@
1
+ import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {jsx,jsxs}from'react/jsx-runtime';function n(...a){return twMerge(clsx(a))}var m=({filled:a,className:s})=>jsx("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:a?"currentColor":"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:s,children:jsx("polygon",{points:"12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"})}),p=[{content:"This UI library has revolutionized how we build user interfaces. The animations are buttery smooth and the developer experience is incredible.",avatar:"https://i.pravatar.cc/150?img=1",name:"Eduardo Calvo",role:"CEO & Founder",stars:5},{content:"The design system is incredibly well thought out. Every component feels intentional and polished.",avatar:"https://i.pravatar.cc/150?img=2",name:"Drew Cano",role:"Head of Design",stars:5},{content:"Best UI library I've used. The TypeScript support is excellent and the components are highly customizable.",avatar:"https://i.pravatar.cc/150?img=3",name:"Marcus Johnson",role:"Lead Developer",stars:5},{content:"Our users love the smooth interactions. It's made our product feel premium and professional.",avatar:"https://i.pravatar.cc/150?img=4",name:"Emily Rodriguez",role:"Product Manager",stars:4}];function u({className:a="",title:s="Developer Reviews",description:o="See what the community is saying. Real feedback from developers building amazing user experiences.",testimonials:l=p}){return jsx("div",{className:n("min-h-[400px] w-full py-24",a),children:jsxs("div",{className:"container mx-auto w-full max-w-5xl px-6",children:[jsxs("div",{className:"mb-12",children:[jsx("h2",{className:"text-zinc-900 dark:text-zinc-100 text-4xl font-semibold",children:s}),jsx("p",{className:"text-zinc-600 dark:text-zinc-500 my-4 text-lg text-balance",children:o})]}),jsx("div",{className:"grid gap-6 lg:grid-cols-2",children:l.map(r=>jsxs("div",{className:"group hover:bg-zinc-50 dark:hover:bg-zinc-950 hover:border-zinc-400 dark:hover:border-zinc-700 rounded-2xl border border-zinc-300 dark:border-zinc-800 bg-white dark:bg-zinc-950 px-4 py-3 duration-200 transition-all hover:-translate-y-1",children:[jsx("div",{className:"flex gap-1",children:Array.from({length:5}).map((v,i)=>jsx(m,{filled:i<(r.stars||0),className:n("size-4 transition-colors duration-200",i<(r.stars||0)?"fill-pink-400 stroke-pink-400":"fill-zinc-300 dark:fill-zinc-700 stroke-zinc-400 dark:stroke-zinc-600")},`${r.name}-star-${i}`))}),jsx("p",{className:"text-zinc-900 dark:text-zinc-100 my-4",children:r.content}),jsxs("div",{className:"flex items-center gap-2",children:[jsx("img",{src:r.avatar,alt:r.name,className:"size-6 rounded-full border border-zinc-300 dark:border-zinc-700 object-cover"}),jsx("div",{className:"text-zinc-900 dark:text-zinc-100 text-sm font-medium",children:r.name}),jsx("span",{"aria-hidden":true,className:"bg-zinc-400 dark:bg-zinc-600 size-1 rounded-full"}),jsx("span",{className:"text-zinc-500 text-sm",children:r.role})]})]},r.name))})]})})}var z=u;
2
+ export{u as TestimonialsStars,z as default};//# sourceMappingURL=index.mjs.map
3
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/cn.ts","../../src/testimonials-stars/index.tsx"],"names":["cn","inputs","twMerge","clsx","StarIcon","filled","className","jsx","defaultTestimonials","TestimonialsStars","title","description","testimonials","jsxs","testimonial","_","testimonials_stars_default"],"mappings":"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","file":"index.mjs","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs));\r\n}\r\n","\"use client\";\r\n\r\nimport { cn } from \"../utils/cn\";\r\n\r\nconst StarIcon = ({ filled, className }: { filled: boolean; className?: string }) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"24\"\r\n height=\"24\"\r\n viewBox=\"0 0 24 24\"\r\n fill={filled ? \"currentColor\" : \"none\"}\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n className={className}\r\n >\r\n <polygon points=\"12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2\" />\r\n </svg>\r\n);\r\n\r\nexport interface TestimonialItem {\r\n content: string;\r\n avatar: string;\r\n name: string;\r\n role: string;\r\n stars?: number;\r\n}\r\n\r\ninterface TestimonialsStarsProps {\r\n className?: string;\r\n title?: string;\r\n description?: string;\r\n testimonials?: TestimonialItem[];\r\n}\r\n\r\nconst defaultTestimonials: TestimonialItem[] = [\r\n {\r\n content:\r\n \"This UI library has revolutionized how we build user interfaces. The animations are buttery smooth and the developer experience is incredible.\",\r\n avatar: \"https://i.pravatar.cc/150?img=1\",\r\n name: \"Eduardo Calvo\",\r\n role: \"CEO & Founder\",\r\n stars: 5,\r\n },\r\n {\r\n content:\r\n \"The design system is incredibly well thought out. Every component feels intentional and polished.\",\r\n avatar: \"https://i.pravatar.cc/150?img=2\",\r\n name: \"Drew Cano\",\r\n role: \"Head of Design\",\r\n stars: 5,\r\n },\r\n {\r\n content:\r\n \"Best UI library I've used. The TypeScript support is excellent and the components are highly customizable.\",\r\n avatar: \"https://i.pravatar.cc/150?img=3\",\r\n name: \"Marcus Johnson\",\r\n role: \"Lead Developer\",\r\n stars: 5,\r\n },\r\n {\r\n content:\r\n \"Our users love the smooth interactions. It's made our product feel premium and professional.\",\r\n avatar: \"https://i.pravatar.cc/150?img=4\",\r\n name: \"Emily Rodriguez\",\r\n role: \"Product Manager\",\r\n stars: 4,\r\n },\r\n];\r\n\r\nexport function TestimonialsStars({\r\n className = \"\",\r\n title = \"Developer Reviews\",\r\n description = \"See what the community is saying. Real feedback from developers building amazing user experiences.\",\r\n testimonials = defaultTestimonials,\r\n}: TestimonialsStarsProps) {\r\n return (\r\n <div className={cn(\"min-h-[400px] w-full py-24\", className)}>\r\n <div className=\"container mx-auto w-full max-w-5xl px-6\">\r\n <div className=\"mb-12\">\r\n <h2 className=\"text-zinc-900 dark:text-zinc-100 text-4xl font-semibold\">\r\n {title}\r\n </h2>\r\n <p className=\"text-zinc-600 dark:text-zinc-500 my-4 text-lg text-balance\">\r\n {description}\r\n </p>\r\n </div>\r\n\r\n <div className=\"grid gap-6 lg:grid-cols-2\">\r\n {testimonials.map((testimonial) => (\r\n <div\r\n key={testimonial.name}\r\n className=\"group hover:bg-zinc-50 dark:hover:bg-zinc-950 hover:border-zinc-400 dark:hover:border-zinc-700 rounded-2xl border border-zinc-300 dark:border-zinc-800 bg-white dark:bg-zinc-950 px-4 py-3 duration-200 transition-all hover:-translate-y-1\"\r\n >\r\n <div className=\"flex gap-1\">\r\n {Array.from({ length: 5 }).map((_, i) => (\r\n <StarIcon\r\n key={`${testimonial.name}-star-${i}`}\r\n filled={i < (testimonial.stars || 0)}\r\n className={cn(\r\n \"size-4 transition-colors duration-200\",\r\n i < (testimonial.stars || 0)\r\n ? \"fill-pink-400 stroke-pink-400\"\r\n : \"fill-zinc-300 dark:fill-zinc-700 stroke-zinc-400 dark:stroke-zinc-600\"\r\n )}\r\n />\r\n ))}\r\n </div>\r\n\r\n <p className=\"text-zinc-900 dark:text-zinc-100 my-4\">\r\n {testimonial.content}\r\n </p>\r\n\r\n <div className=\"flex items-center gap-2\">\r\n <img\r\n src={testimonial.avatar}\r\n alt={testimonial.name}\r\n className=\"size-6 rounded-full border border-zinc-300 dark:border-zinc-700 object-cover\"\r\n />\r\n <div className=\"text-zinc-900 dark:text-zinc-100 text-sm font-medium\">\r\n {testimonial.name}\r\n </div>\r\n <span\r\n aria-hidden\r\n className=\"bg-zinc-400 dark:bg-zinc-600 size-1 rounded-full\"\r\n />\r\n <span className=\"text-zinc-500 text-sm\">{testimonial.role}</span>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport default TestimonialsStars;\r\n"]}
@@ -0,0 +1,2 @@
1
+ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var react=require('react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),jsxRuntime=require('react/jsx-runtime');function h(...o){return tailwindMerge.twMerge(clsx.clsx(o))}function _({text:o,as:P="div",typingSpeed:c=50,initialDelay:C=0,pauseDuration:T=2e3,deletingSpeed:I=30,loop:E=true,className:k="",showCursor:g=true,hideCursorWhileTyping:w=false,cursorCharacter:J="|",cursorClassName:W="",cursorBlinkDuration:v=.5,textColors:p=[],variableSpeed:l,onSentenceComplete:x,startOnVisible:b=false,reverseMode:M=false,...j}){let[a,N]=react.useState(""),[u,R]=react.useState(0),[m,A]=react.useState(false),[r,q]=react.useState(0),[V,z]=react.useState(!b),[B,F]=react.useState(true),d=react.useRef(null),n=react.useMemo(()=>Array.isArray(o)?o:[o],[o]),H=react.useCallback(()=>{if(!l)return c;let{min:e,max:t}=l;return Math.random()*(t-e)+e},[l,c]),G=()=>{if(p.length!==0)return p[r%p.length]};react.useEffect(()=>{if(!b||!d.current)return;let e=new IntersectionObserver(t=>{t.forEach(f=>{f.isIntersecting&&z(true);});},{threshold:.1});return e.observe(d.current),()=>e.disconnect()},[b]),react.useEffect(()=>{if(g){let e=setInterval(()=>{F(t=>!t);},v*1e3);return ()=>clearInterval(e)}},[g,v]),react.useEffect(()=>{if(!V)return;let e,t=n[r],f=M?t.split("").reverse().join(""):t,L=()=>{if(m)if(a===""){if(A(false),r===n.length-1&&!E)return;x&&x(n[r],r),q(s=>(s+1)%n.length),R(0),e=setTimeout(()=>{},T);}else e=setTimeout(()=>{N(s=>s.slice(0,-1));},I);else u<f.length?e=setTimeout(()=>{N(s=>s+f[u]),R(s=>s+1);},l?H():c):n.length>1&&(e=setTimeout(()=>{A(true);},T));};return u===0&&!m&&a===""?e=setTimeout(L,C):L(),()=>clearTimeout(e)},[u,a,m,c,I,T,n,r,E,C,V,M,l,x,H]);let K=w&&(u<n[r].length||m);return react.createElement(P,{ref:d,className:h("inline-flex",k),...j},jsxRuntime.jsx("span",{style:{color:G()||"inherit"},children:a}),g&&jsxRuntime.jsx("span",{className:h("transition-opacity",W,K&&"opacity-0",!B&&"opacity-0"),children:J}))}var se=_;exports.TextType=_;exports.default=se;//# sourceMappingURL=index.js.map
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/cn.ts","../../src/text-type/index.tsx"],"names":["cn","inputs","twMerge","clsx","TextType","text","Component","typingSpeed","initialDelay","pauseDuration","deletingSpeed","loop","className","showCursor","hideCursorWhileTyping","cursorCharacter","cursorClassName","cursorBlinkDuration","textColors","variableSpeed","onSentenceComplete","startOnVisible","reverseMode","props","displayedText","setDisplayedText","useState","currentCharIndex","setCurrentCharIndex","isDeleting","setIsDeleting","currentTextIndex","setCurrentTextIndex","isVisible","setIsVisible","cursorVisible","setCursorVisible","containerRef","useRef","textArray","useMemo","getRandomSpeed","useCallback","min","max","getCurrentTextColor","useEffect","observer","entries","entry","interval","prev","timeout","currentText","processedText","executeTypingAnimation","shouldHideCursor","createElement","jsx","text_type_default"],"mappings":"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","file":"index.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs));\r\n}\r\n","\"use client\";\r\n\r\nimport {\r\n ElementType,\r\n useEffect,\r\n useRef,\r\n useState,\r\n createElement,\r\n useMemo,\r\n useCallback,\r\n} from \"react\";\r\nimport { cn } from \"../utils/cn\";\r\n\r\ninterface TextTypeProps {\r\n className?: string;\r\n showCursor?: boolean;\r\n hideCursorWhileTyping?: boolean;\r\n cursorCharacter?: string | React.ReactNode;\r\n cursorBlinkDuration?: number;\r\n cursorClassName?: string;\r\n text: string | string[];\r\n as?: ElementType;\r\n typingSpeed?: number;\r\n initialDelay?: number;\r\n pauseDuration?: number;\r\n deletingSpeed?: number;\r\n loop?: boolean;\r\n textColors?: string[];\r\n variableSpeed?: { min: number; max: number };\r\n onSentenceComplete?: (sentence: string, index: number) => void;\r\n startOnVisible?: boolean;\r\n reverseMode?: boolean;\r\n}\r\n\r\nexport function TextType({\r\n text,\r\n as: Component = \"div\",\r\n typingSpeed = 50,\r\n initialDelay = 0,\r\n pauseDuration = 2000,\r\n deletingSpeed = 30,\r\n loop = true,\r\n className = \"\",\r\n showCursor = true,\r\n hideCursorWhileTyping = false,\r\n cursorCharacter = \"|\",\r\n cursorClassName = \"\",\r\n cursorBlinkDuration = 0.5,\r\n textColors = [],\r\n variableSpeed,\r\n onSentenceComplete,\r\n startOnVisible = false,\r\n reverseMode = false,\r\n ...props\r\n}: TextTypeProps & React.HTMLAttributes<HTMLElement>) {\r\n const [displayedText, setDisplayedText] = useState(\"\");\r\n const [currentCharIndex, setCurrentCharIndex] = useState(0);\r\n const [isDeleting, setIsDeleting] = useState(false);\r\n const [currentTextIndex, setCurrentTextIndex] = useState(0);\r\n const [isVisible, setIsVisible] = useState(!startOnVisible);\r\n const [cursorVisible, setCursorVisible] = useState(true);\r\n const containerRef = useRef<HTMLElement>(null);\r\n\r\n const textArray = useMemo(\r\n () => (Array.isArray(text) ? text : [text]),\r\n [text]\r\n );\r\n\r\n const getRandomSpeed = useCallback(() => {\r\n if (!variableSpeed) return typingSpeed;\r\n const { min, max } = variableSpeed;\r\n return Math.random() * (max - min) + min;\r\n }, [variableSpeed, typingSpeed]);\r\n\r\n const getCurrentTextColor = () => {\r\n if (textColors.length === 0) return;\r\n return textColors[currentTextIndex % textColors.length];\r\n };\r\n\r\n useEffect(() => {\r\n if (!startOnVisible || !containerRef.current) return;\r\n\r\n const observer = new IntersectionObserver(\r\n (entries) => {\r\n entries.forEach((entry) => {\r\n if (entry.isIntersecting) {\r\n setIsVisible(true);\r\n }\r\n });\r\n },\r\n { threshold: 0.1 }\r\n );\r\n\r\n observer.observe(containerRef.current);\r\n return () => observer.disconnect();\r\n }, [startOnVisible]);\r\n\r\n useEffect(() => {\r\n if (showCursor) {\r\n const interval = setInterval(() => {\r\n setCursorVisible((prev) => !prev);\r\n }, cursorBlinkDuration * 1000);\r\n return () => clearInterval(interval);\r\n }\r\n }, [showCursor, cursorBlinkDuration]);\r\n\r\n useEffect(() => {\r\n if (!isVisible) return;\r\n\r\n let timeout: NodeJS.Timeout;\r\n\r\n const currentText = textArray[currentTextIndex];\r\n const processedText = reverseMode\r\n ? currentText.split(\"\").reverse().join(\"\")\r\n : currentText;\r\n\r\n const executeTypingAnimation = () => {\r\n if (isDeleting) {\r\n if (displayedText === \"\") {\r\n setIsDeleting(false);\r\n if (currentTextIndex === textArray.length - 1 && !loop) {\r\n return;\r\n }\r\n\r\n if (onSentenceComplete) {\r\n onSentenceComplete(textArray[currentTextIndex], currentTextIndex);\r\n }\r\n\r\n setCurrentTextIndex((prev) => (prev + 1) % textArray.length);\r\n setCurrentCharIndex(0);\r\n timeout = setTimeout(() => {}, pauseDuration);\r\n } else {\r\n timeout = setTimeout(() => {\r\n setDisplayedText((prev) => prev.slice(0, -1));\r\n }, deletingSpeed);\r\n }\r\n } else {\r\n if (currentCharIndex < processedText.length) {\r\n timeout = setTimeout(\r\n () => {\r\n setDisplayedText((prev) => prev + processedText[currentCharIndex]);\r\n setCurrentCharIndex((prev) => prev + 1);\r\n },\r\n variableSpeed ? getRandomSpeed() : typingSpeed\r\n );\r\n } else if (textArray.length > 1) {\r\n timeout = setTimeout(() => {\r\n setIsDeleting(true);\r\n }, pauseDuration);\r\n }\r\n }\r\n };\r\n\r\n if (currentCharIndex === 0 && !isDeleting && displayedText === \"\") {\r\n timeout = setTimeout(executeTypingAnimation, initialDelay);\r\n } else {\r\n executeTypingAnimation();\r\n }\r\n\r\n return () => clearTimeout(timeout);\r\n }, [\r\n currentCharIndex,\r\n displayedText,\r\n isDeleting,\r\n typingSpeed,\r\n deletingSpeed,\r\n pauseDuration,\r\n textArray,\r\n currentTextIndex,\r\n loop,\r\n initialDelay,\r\n isVisible,\r\n reverseMode,\r\n variableSpeed,\r\n onSentenceComplete,\r\n getRandomSpeed,\r\n ]);\r\n\r\n const shouldHideCursor =\r\n hideCursorWhileTyping &&\r\n (currentCharIndex < textArray[currentTextIndex].length || isDeleting);\r\n\r\n return createElement(\r\n Component,\r\n {\r\n ref: containerRef,\r\n className: cn(\"inline-flex\", className),\r\n ...props,\r\n },\r\n <span style={{ color: getCurrentTextColor() || \"inherit\" }}>\r\n {displayedText}\r\n </span>,\r\n showCursor && (\r\n <span\r\n className={cn(\r\n \"transition-opacity\",\r\n cursorClassName,\r\n shouldHideCursor && \"opacity-0\",\r\n !cursorVisible && \"opacity-0\"\r\n )}\r\n >\r\n {cursorCharacter}\r\n </span>\r\n )\r\n );\r\n}\r\n\r\nexport default TextType;\r\n"]}
@@ -0,0 +1,2 @@
1
+ import {useState,useRef,useMemo,useCallback,useEffect,createElement}from'react';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {jsx}from'react/jsx-runtime';function h(...o){return twMerge(clsx(o))}function _({text:o,as:P="div",typingSpeed:c=50,initialDelay:C=0,pauseDuration:T=2e3,deletingSpeed:I=30,loop:E=true,className:k="",showCursor:g=true,hideCursorWhileTyping:w=false,cursorCharacter:J="|",cursorClassName:W="",cursorBlinkDuration:v=.5,textColors:p=[],variableSpeed:l,onSentenceComplete:x,startOnVisible:b=false,reverseMode:M=false,...j}){let[a,N]=useState(""),[u,R]=useState(0),[m,A]=useState(false),[r,q]=useState(0),[V,z]=useState(!b),[B,F]=useState(true),d=useRef(null),n=useMemo(()=>Array.isArray(o)?o:[o],[o]),H=useCallback(()=>{if(!l)return c;let{min:e,max:t}=l;return Math.random()*(t-e)+e},[l,c]),G=()=>{if(p.length!==0)return p[r%p.length]};useEffect(()=>{if(!b||!d.current)return;let e=new IntersectionObserver(t=>{t.forEach(f=>{f.isIntersecting&&z(true);});},{threshold:.1});return e.observe(d.current),()=>e.disconnect()},[b]),useEffect(()=>{if(g){let e=setInterval(()=>{F(t=>!t);},v*1e3);return ()=>clearInterval(e)}},[g,v]),useEffect(()=>{if(!V)return;let e,t=n[r],f=M?t.split("").reverse().join(""):t,L=()=>{if(m)if(a===""){if(A(false),r===n.length-1&&!E)return;x&&x(n[r],r),q(s=>(s+1)%n.length),R(0),e=setTimeout(()=>{},T);}else e=setTimeout(()=>{N(s=>s.slice(0,-1));},I);else u<f.length?e=setTimeout(()=>{N(s=>s+f[u]),R(s=>s+1);},l?H():c):n.length>1&&(e=setTimeout(()=>{A(true);},T));};return u===0&&!m&&a===""?e=setTimeout(L,C):L(),()=>clearTimeout(e)},[u,a,m,c,I,T,n,r,E,C,V,M,l,x,H]);let K=w&&(u<n[r].length||m);return createElement(P,{ref:d,className:h("inline-flex",k),...j},jsx("span",{style:{color:G()||"inherit"},children:a}),g&&jsx("span",{className:h("transition-opacity",W,K&&"opacity-0",!B&&"opacity-0"),children:J}))}var se=_;export{_ as TextType,se as default};//# sourceMappingURL=index.mjs.map
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/cn.ts","../../src/text-type/index.tsx"],"names":["cn","inputs","twMerge","clsx","TextType","text","Component","typingSpeed","initialDelay","pauseDuration","deletingSpeed","loop","className","showCursor","hideCursorWhileTyping","cursorCharacter","cursorClassName","cursorBlinkDuration","textColors","variableSpeed","onSentenceComplete","startOnVisible","reverseMode","props","displayedText","setDisplayedText","useState","currentCharIndex","setCurrentCharIndex","isDeleting","setIsDeleting","currentTextIndex","setCurrentTextIndex","isVisible","setIsVisible","cursorVisible","setCursorVisible","containerRef","useRef","textArray","useMemo","getRandomSpeed","useCallback","min","max","getCurrentTextColor","useEffect","observer","entries","entry","interval","prev","timeout","currentText","processedText","executeTypingAnimation","shouldHideCursor","createElement","jsx","text_type_default"],"mappings":"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","file":"index.mjs","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs));\r\n}\r\n","\"use client\";\r\n\r\nimport {\r\n ElementType,\r\n useEffect,\r\n useRef,\r\n useState,\r\n createElement,\r\n useMemo,\r\n useCallback,\r\n} from \"react\";\r\nimport { cn } from \"../utils/cn\";\r\n\r\ninterface TextTypeProps {\r\n className?: string;\r\n showCursor?: boolean;\r\n hideCursorWhileTyping?: boolean;\r\n cursorCharacter?: string | React.ReactNode;\r\n cursorBlinkDuration?: number;\r\n cursorClassName?: string;\r\n text: string | string[];\r\n as?: ElementType;\r\n typingSpeed?: number;\r\n initialDelay?: number;\r\n pauseDuration?: number;\r\n deletingSpeed?: number;\r\n loop?: boolean;\r\n textColors?: string[];\r\n variableSpeed?: { min: number; max: number };\r\n onSentenceComplete?: (sentence: string, index: number) => void;\r\n startOnVisible?: boolean;\r\n reverseMode?: boolean;\r\n}\r\n\r\nexport function TextType({\r\n text,\r\n as: Component = \"div\",\r\n typingSpeed = 50,\r\n initialDelay = 0,\r\n pauseDuration = 2000,\r\n deletingSpeed = 30,\r\n loop = true,\r\n className = \"\",\r\n showCursor = true,\r\n hideCursorWhileTyping = false,\r\n cursorCharacter = \"|\",\r\n cursorClassName = \"\",\r\n cursorBlinkDuration = 0.5,\r\n textColors = [],\r\n variableSpeed,\r\n onSentenceComplete,\r\n startOnVisible = false,\r\n reverseMode = false,\r\n ...props\r\n}: TextTypeProps & React.HTMLAttributes<HTMLElement>) {\r\n const [displayedText, setDisplayedText] = useState(\"\");\r\n const [currentCharIndex, setCurrentCharIndex] = useState(0);\r\n const [isDeleting, setIsDeleting] = useState(false);\r\n const [currentTextIndex, setCurrentTextIndex] = useState(0);\r\n const [isVisible, setIsVisible] = useState(!startOnVisible);\r\n const [cursorVisible, setCursorVisible] = useState(true);\r\n const containerRef = useRef<HTMLElement>(null);\r\n\r\n const textArray = useMemo(\r\n () => (Array.isArray(text) ? text : [text]),\r\n [text]\r\n );\r\n\r\n const getRandomSpeed = useCallback(() => {\r\n if (!variableSpeed) return typingSpeed;\r\n const { min, max } = variableSpeed;\r\n return Math.random() * (max - min) + min;\r\n }, [variableSpeed, typingSpeed]);\r\n\r\n const getCurrentTextColor = () => {\r\n if (textColors.length === 0) return;\r\n return textColors[currentTextIndex % textColors.length];\r\n };\r\n\r\n useEffect(() => {\r\n if (!startOnVisible || !containerRef.current) return;\r\n\r\n const observer = new IntersectionObserver(\r\n (entries) => {\r\n entries.forEach((entry) => {\r\n if (entry.isIntersecting) {\r\n setIsVisible(true);\r\n }\r\n });\r\n },\r\n { threshold: 0.1 }\r\n );\r\n\r\n observer.observe(containerRef.current);\r\n return () => observer.disconnect();\r\n }, [startOnVisible]);\r\n\r\n useEffect(() => {\r\n if (showCursor) {\r\n const interval = setInterval(() => {\r\n setCursorVisible((prev) => !prev);\r\n }, cursorBlinkDuration * 1000);\r\n return () => clearInterval(interval);\r\n }\r\n }, [showCursor, cursorBlinkDuration]);\r\n\r\n useEffect(() => {\r\n if (!isVisible) return;\r\n\r\n let timeout: NodeJS.Timeout;\r\n\r\n const currentText = textArray[currentTextIndex];\r\n const processedText = reverseMode\r\n ? currentText.split(\"\").reverse().join(\"\")\r\n : currentText;\r\n\r\n const executeTypingAnimation = () => {\r\n if (isDeleting) {\r\n if (displayedText === \"\") {\r\n setIsDeleting(false);\r\n if (currentTextIndex === textArray.length - 1 && !loop) {\r\n return;\r\n }\r\n\r\n if (onSentenceComplete) {\r\n onSentenceComplete(textArray[currentTextIndex], currentTextIndex);\r\n }\r\n\r\n setCurrentTextIndex((prev) => (prev + 1) % textArray.length);\r\n setCurrentCharIndex(0);\r\n timeout = setTimeout(() => {}, pauseDuration);\r\n } else {\r\n timeout = setTimeout(() => {\r\n setDisplayedText((prev) => prev.slice(0, -1));\r\n }, deletingSpeed);\r\n }\r\n } else {\r\n if (currentCharIndex < processedText.length) {\r\n timeout = setTimeout(\r\n () => {\r\n setDisplayedText((prev) => prev + processedText[currentCharIndex]);\r\n setCurrentCharIndex((prev) => prev + 1);\r\n },\r\n variableSpeed ? getRandomSpeed() : typingSpeed\r\n );\r\n } else if (textArray.length > 1) {\r\n timeout = setTimeout(() => {\r\n setIsDeleting(true);\r\n }, pauseDuration);\r\n }\r\n }\r\n };\r\n\r\n if (currentCharIndex === 0 && !isDeleting && displayedText === \"\") {\r\n timeout = setTimeout(executeTypingAnimation, initialDelay);\r\n } else {\r\n executeTypingAnimation();\r\n }\r\n\r\n return () => clearTimeout(timeout);\r\n }, [\r\n currentCharIndex,\r\n displayedText,\r\n isDeleting,\r\n typingSpeed,\r\n deletingSpeed,\r\n pauseDuration,\r\n textArray,\r\n currentTextIndex,\r\n loop,\r\n initialDelay,\r\n isVisible,\r\n reverseMode,\r\n variableSpeed,\r\n onSentenceComplete,\r\n getRandomSpeed,\r\n ]);\r\n\r\n const shouldHideCursor =\r\n hideCursorWhileTyping &&\r\n (currentCharIndex < textArray[currentTextIndex].length || isDeleting);\r\n\r\n return createElement(\r\n Component,\r\n {\r\n ref: containerRef,\r\n className: cn(\"inline-flex\", className),\r\n ...props,\r\n },\r\n <span style={{ color: getCurrentTextColor() || \"inherit\" }}>\r\n {displayedText}\r\n </span>,\r\n showCursor && (\r\n <span\r\n className={cn(\r\n \"transition-opacity\",\r\n cursorClassName,\r\n shouldHideCursor && \"opacity-0\",\r\n !cursorVisible && \"opacity-0\"\r\n )}\r\n >\r\n {cursorCharacter}\r\n </span>\r\n )\r\n );\r\n}\r\n\r\nexport default TextType;\r\n"]}
@@ -0,0 +1,2 @@
1
+ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var react=require('react'),framerMotion=require('framer-motion'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),jsxRuntime=require('react/jsx-runtime');function r(...i){return tailwindMerge.twMerge(clsx.clsx(i))}function R({title:i,content:k,actions:m=[],children:g,position:a="top",trigger:o="hover",persistent:c=false,className:z}){let[f,n]=react.useState(false),[y,p]=react.useState(false),l=react.useRef(void 0),d=react.useRef(null),N=()=>{l.current&&clearTimeout(l.current),n(true);},v=()=>{c&&y||(l.current=setTimeout(()=>n(false),100));},w=()=>{o==="click"&&n(!f);},b=()=>n(false);react.useEffect(()=>{let t=u=>{d.current&&!d.current.contains(u.target)&&o==="click"&&n(false);};return document.addEventListener("mousedown",t),()=>document.removeEventListener("mousedown",t)},[o]);let C=()=>{switch(a){case "top":return "bottom-full left-1/2 -translate-x-1/2 mb-3";case "bottom":return "top-full left-1/2 -translate-x-1/2 mt-3";case "left":return "right-full top-1/2 -translate-y-1/2 mr-3";case "right":return "left-full top-1/2 -translate-y-1/2 ml-3";default:return "bottom-full left-1/2 -translate-x-1/2 mb-3"}},T=o==="hover"?{onMouseEnter:N,onMouseLeave:v}:{onClick:w};return jsxRuntime.jsxs("div",{className:r("relative inline-block",z),...T,children:[g,jsxRuntime.jsx(framerMotion.AnimatePresence,{children:f&&jsxRuntime.jsx(framerMotion.motion.div,{ref:d,initial:{opacity:0,scale:.95,y:a==="top"?10:-10},animate:{opacity:1,scale:1,y:0},exit:{opacity:0,scale:.95,y:a==="top"?10:-10},transition:{type:"spring",stiffness:300,damping:25},onMouseEnter:()=>p(true),onMouseLeave:()=>{p(false),o==="hover"&&v();},className:r("absolute z-50 w-80 bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 rounded-xl shadow-xl backdrop-blur-sm",C()),children:jsxRuntime.jsxs("div",{className:"p-4 space-y-3",children:[jsxRuntime.jsxs("div",{className:"flex items-start justify-between gap-2",children:[jsxRuntime.jsxs("div",{className:"flex-1 space-y-1",children:[i&&jsxRuntime.jsx("h3",{className:"font-semibold text-zinc-900 dark:text-zinc-100 text-sm",children:i}),jsxRuntime.jsx("p",{className:"text-sm text-zinc-600 dark:text-zinc-400 leading-relaxed",children:k})]}),(o==="click"||c)&&jsxRuntime.jsx("button",{onClick:b,className:"text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-200 transition-colors p-1 rounded-md hover:bg-zinc-100 dark:hover:bg-zinc-800",children:jsxRuntime.jsx("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:jsxRuntime.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]}),m.length>0&&jsxRuntime.jsx("div",{className:"flex gap-2 pt-2 border-t border-zinc-200 dark:border-zinc-800",children:m.map((t,u)=>jsxRuntime.jsx("button",{onClick:()=>{t.onClick(),c||b();},className:r("text-xs h-8 px-3 rounded-md font-medium transition-colors",t.variant==="destructive"?"bg-red-500 text-white hover:bg-red-600":t.variant==="secondary"?"bg-zinc-100 dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 hover:bg-zinc-200 dark:hover:bg-zinc-700":"bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 hover:bg-zinc-800 dark:hover:bg-zinc-100"),children:t.label},u))})]})})})]})}var D=R;exports.TooltipInteractive=R;exports.default=D;//# sourceMappingURL=index.js.map
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/cn.ts","../../src/tooltip-interactive/index.tsx"],"names":["cn","inputs","twMerge","clsx","TooltipInteractive","title","content","actions","children","position","trigger","persistent","className","isVisible","setIsVisible","useState","isHovered","setIsHovered","timeoutRef","useRef","tooltipRef","showTooltip","hideTooltip","handleClick","handleClose","useEffect","handleClickOutside","event","getPositionClasses","triggerProps","jsxs","jsx","AnimatePresence","motion","action","index","tooltip_interactive_default"],"mappings":"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","file":"index.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs));\r\n}\r\n","\"use client\";\r\n\r\nimport { useState, useRef, useEffect } from \"react\";\r\nimport { motion, AnimatePresence } from \"framer-motion\";\r\nimport { cn } from \"../utils/cn\";\r\n\r\ninterface TooltipAction {\r\n label: string;\r\n onClick: () => void;\r\n variant?: \"default\" | \"secondary\" | \"destructive\";\r\n}\r\n\r\nexport interface TooltipInteractiveProps {\r\n title?: string;\r\n content: string;\r\n actions?: TooltipAction[];\r\n children: React.ReactNode;\r\n position?: \"top\" | \"bottom\" | \"left\" | \"right\";\r\n trigger?: \"hover\" | \"click\";\r\n persistent?: boolean;\r\n className?: string;\r\n}\r\n\r\nexport function TooltipInteractive({\r\n title,\r\n content,\r\n actions = [],\r\n children,\r\n position = \"top\",\r\n trigger = \"hover\",\r\n persistent = false,\r\n className,\r\n}: TooltipInteractiveProps) {\r\n const [isVisible, setIsVisible] = useState(false);\r\n const [isHovered, setIsHovered] = useState(false);\r\n const timeoutRef = useRef<NodeJS.Timeout>(undefined);\r\n const tooltipRef = useRef<HTMLDivElement>(null);\r\n\r\n const showTooltip = () => {\r\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\r\n setIsVisible(true);\r\n };\r\n\r\n const hideTooltip = () => {\r\n if (persistent && isHovered) return;\r\n timeoutRef.current = setTimeout(() => setIsVisible(false), 100);\r\n };\r\n\r\n const handleClick = () => {\r\n if (trigger === \"click\") setIsVisible(!isVisible);\r\n };\r\n\r\n const handleClose = () => setIsVisible(false);\r\n\r\n useEffect(() => {\r\n const handleClickOutside = (event: MouseEvent) => {\r\n if (tooltipRef.current && !tooltipRef.current.contains(event.target as Node)) {\r\n if (trigger === \"click\") setIsVisible(false);\r\n }\r\n };\r\n document.addEventListener(\"mousedown\", handleClickOutside);\r\n return () => document.removeEventListener(\"mousedown\", handleClickOutside);\r\n }, [trigger]);\r\n\r\n const getPositionClasses = () => {\r\n switch (position) {\r\n case \"top\": return \"bottom-full left-1/2 -translate-x-1/2 mb-3\";\r\n case \"bottom\": return \"top-full left-1/2 -translate-x-1/2 mt-3\";\r\n case \"left\": return \"right-full top-1/2 -translate-y-1/2 mr-3\";\r\n case \"right\": return \"left-full top-1/2 -translate-y-1/2 ml-3\";\r\n default: return \"bottom-full left-1/2 -translate-x-1/2 mb-3\";\r\n }\r\n };\r\n\r\n const triggerProps = trigger === \"hover\"\r\n ? { onMouseEnter: showTooltip, onMouseLeave: hideTooltip }\r\n : { onClick: handleClick };\r\n\r\n return (\r\n <div className={cn(\"relative inline-block\", className)} {...triggerProps}>\r\n {children}\r\n <AnimatePresence>\r\n {isVisible && (\r\n <motion.div\r\n ref={tooltipRef}\r\n initial={{ opacity: 0, scale: 0.95, y: position === \"top\" ? 10 : -10 }}\r\n animate={{ opacity: 1, scale: 1, y: 0 }}\r\n exit={{ opacity: 0, scale: 0.95, y: position === \"top\" ? 10 : -10 }}\r\n transition={{ type: \"spring\", stiffness: 300, damping: 25 }}\r\n onMouseEnter={() => setIsHovered(true)}\r\n onMouseLeave={() => { setIsHovered(false); if (trigger === \"hover\") hideTooltip(); }}\r\n className={cn(\"absolute z-50 w-80 bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 rounded-xl shadow-xl backdrop-blur-sm\", getPositionClasses())}\r\n >\r\n <div className=\"p-4 space-y-3\">\r\n <div className=\"flex items-start justify-between gap-2\">\r\n <div className=\"flex-1 space-y-1\">\r\n {title && <h3 className=\"font-semibold text-zinc-900 dark:text-zinc-100 text-sm\">{title}</h3>}\r\n <p className=\"text-sm text-zinc-600 dark:text-zinc-400 leading-relaxed\">{content}</p>\r\n </div>\r\n {(trigger === \"click\" || persistent) && (\r\n <button onClick={handleClose} className=\"text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-200 transition-colors p-1 rounded-md hover:bg-zinc-100 dark:hover:bg-zinc-800\">\r\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" /></svg>\r\n </button>\r\n )}\r\n </div>\r\n {actions.length > 0 && (\r\n <div className=\"flex gap-2 pt-2 border-t border-zinc-200 dark:border-zinc-800\">\r\n {actions.map((action, index) => (\r\n <button key={index} onClick={() => { action.onClick(); if (!persistent) handleClose(); }}\r\n className={cn(\"text-xs h-8 px-3 rounded-md font-medium transition-colors\",\r\n action.variant === \"destructive\" ? \"bg-red-500 text-white hover:bg-red-600\" :\r\n action.variant === \"secondary\" ? \"bg-zinc-100 dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 hover:bg-zinc-200 dark:hover:bg-zinc-700\" :\r\n \"bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 hover:bg-zinc-800 dark:hover:bg-zinc-100\"\r\n )}\r\n >{action.label}</button>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n </motion.div>\r\n )}\r\n </AnimatePresence>\r\n </div>\r\n );\r\n}\r\n\r\nexport default TooltipInteractive;\r\n"]}
@@ -0,0 +1,2 @@
1
+ import {useState,useRef,useEffect}from'react';import {AnimatePresence,motion}from'framer-motion';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {jsxs,jsx}from'react/jsx-runtime';function r(...i){return twMerge(clsx(i))}function R({title:i,content:k,actions:m=[],children:g,position:a="top",trigger:o="hover",persistent:c=false,className:z}){let[f,n]=useState(false),[y,p]=useState(false),l=useRef(void 0),d=useRef(null),N=()=>{l.current&&clearTimeout(l.current),n(true);},v=()=>{c&&y||(l.current=setTimeout(()=>n(false),100));},w=()=>{o==="click"&&n(!f);},b=()=>n(false);useEffect(()=>{let t=u=>{d.current&&!d.current.contains(u.target)&&o==="click"&&n(false);};return document.addEventListener("mousedown",t),()=>document.removeEventListener("mousedown",t)},[o]);let C=()=>{switch(a){case "top":return "bottom-full left-1/2 -translate-x-1/2 mb-3";case "bottom":return "top-full left-1/2 -translate-x-1/2 mt-3";case "left":return "right-full top-1/2 -translate-y-1/2 mr-3";case "right":return "left-full top-1/2 -translate-y-1/2 ml-3";default:return "bottom-full left-1/2 -translate-x-1/2 mb-3"}},T=o==="hover"?{onMouseEnter:N,onMouseLeave:v}:{onClick:w};return jsxs("div",{className:r("relative inline-block",z),...T,children:[g,jsx(AnimatePresence,{children:f&&jsx(motion.div,{ref:d,initial:{opacity:0,scale:.95,y:a==="top"?10:-10},animate:{opacity:1,scale:1,y:0},exit:{opacity:0,scale:.95,y:a==="top"?10:-10},transition:{type:"spring",stiffness:300,damping:25},onMouseEnter:()=>p(true),onMouseLeave:()=>{p(false),o==="hover"&&v();},className:r("absolute z-50 w-80 bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 rounded-xl shadow-xl backdrop-blur-sm",C()),children:jsxs("div",{className:"p-4 space-y-3",children:[jsxs("div",{className:"flex items-start justify-between gap-2",children:[jsxs("div",{className:"flex-1 space-y-1",children:[i&&jsx("h3",{className:"font-semibold text-zinc-900 dark:text-zinc-100 text-sm",children:i}),jsx("p",{className:"text-sm text-zinc-600 dark:text-zinc-400 leading-relaxed",children:k})]}),(o==="click"||c)&&jsx("button",{onClick:b,className:"text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-200 transition-colors p-1 rounded-md hover:bg-zinc-100 dark:hover:bg-zinc-800",children:jsx("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]}),m.length>0&&jsx("div",{className:"flex gap-2 pt-2 border-t border-zinc-200 dark:border-zinc-800",children:m.map((t,u)=>jsx("button",{onClick:()=>{t.onClick(),c||b();},className:r("text-xs h-8 px-3 rounded-md font-medium transition-colors",t.variant==="destructive"?"bg-red-500 text-white hover:bg-red-600":t.variant==="secondary"?"bg-zinc-100 dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 hover:bg-zinc-200 dark:hover:bg-zinc-700":"bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 hover:bg-zinc-800 dark:hover:bg-zinc-100"),children:t.label},u))})]})})})]})}var D=R;export{R as TooltipInteractive,D as default};//# sourceMappingURL=index.mjs.map
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/cn.ts","../../src/tooltip-interactive/index.tsx"],"names":["cn","inputs","twMerge","clsx","TooltipInteractive","title","content","actions","children","position","trigger","persistent","className","isVisible","setIsVisible","useState","isHovered","setIsHovered","timeoutRef","useRef","tooltipRef","showTooltip","hideTooltip","handleClick","handleClose","useEffect","handleClickOutside","event","getPositionClasses","triggerProps","jsxs","jsx","AnimatePresence","motion","action","index","tooltip_interactive_default"],"mappings":"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","file":"index.mjs","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs));\r\n}\r\n","\"use client\";\r\n\r\nimport { useState, useRef, useEffect } from \"react\";\r\nimport { motion, AnimatePresence } from \"framer-motion\";\r\nimport { cn } from \"../utils/cn\";\r\n\r\ninterface TooltipAction {\r\n label: string;\r\n onClick: () => void;\r\n variant?: \"default\" | \"secondary\" | \"destructive\";\r\n}\r\n\r\nexport interface TooltipInteractiveProps {\r\n title?: string;\r\n content: string;\r\n actions?: TooltipAction[];\r\n children: React.ReactNode;\r\n position?: \"top\" | \"bottom\" | \"left\" | \"right\";\r\n trigger?: \"hover\" | \"click\";\r\n persistent?: boolean;\r\n className?: string;\r\n}\r\n\r\nexport function TooltipInteractive({\r\n title,\r\n content,\r\n actions = [],\r\n children,\r\n position = \"top\",\r\n trigger = \"hover\",\r\n persistent = false,\r\n className,\r\n}: TooltipInteractiveProps) {\r\n const [isVisible, setIsVisible] = useState(false);\r\n const [isHovered, setIsHovered] = useState(false);\r\n const timeoutRef = useRef<NodeJS.Timeout>(undefined);\r\n const tooltipRef = useRef<HTMLDivElement>(null);\r\n\r\n const showTooltip = () => {\r\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\r\n setIsVisible(true);\r\n };\r\n\r\n const hideTooltip = () => {\r\n if (persistent && isHovered) return;\r\n timeoutRef.current = setTimeout(() => setIsVisible(false), 100);\r\n };\r\n\r\n const handleClick = () => {\r\n if (trigger === \"click\") setIsVisible(!isVisible);\r\n };\r\n\r\n const handleClose = () => setIsVisible(false);\r\n\r\n useEffect(() => {\r\n const handleClickOutside = (event: MouseEvent) => {\r\n if (tooltipRef.current && !tooltipRef.current.contains(event.target as Node)) {\r\n if (trigger === \"click\") setIsVisible(false);\r\n }\r\n };\r\n document.addEventListener(\"mousedown\", handleClickOutside);\r\n return () => document.removeEventListener(\"mousedown\", handleClickOutside);\r\n }, [trigger]);\r\n\r\n const getPositionClasses = () => {\r\n switch (position) {\r\n case \"top\": return \"bottom-full left-1/2 -translate-x-1/2 mb-3\";\r\n case \"bottom\": return \"top-full left-1/2 -translate-x-1/2 mt-3\";\r\n case \"left\": return \"right-full top-1/2 -translate-y-1/2 mr-3\";\r\n case \"right\": return \"left-full top-1/2 -translate-y-1/2 ml-3\";\r\n default: return \"bottom-full left-1/2 -translate-x-1/2 mb-3\";\r\n }\r\n };\r\n\r\n const triggerProps = trigger === \"hover\"\r\n ? { onMouseEnter: showTooltip, onMouseLeave: hideTooltip }\r\n : { onClick: handleClick };\r\n\r\n return (\r\n <div className={cn(\"relative inline-block\", className)} {...triggerProps}>\r\n {children}\r\n <AnimatePresence>\r\n {isVisible && (\r\n <motion.div\r\n ref={tooltipRef}\r\n initial={{ opacity: 0, scale: 0.95, y: position === \"top\" ? 10 : -10 }}\r\n animate={{ opacity: 1, scale: 1, y: 0 }}\r\n exit={{ opacity: 0, scale: 0.95, y: position === \"top\" ? 10 : -10 }}\r\n transition={{ type: \"spring\", stiffness: 300, damping: 25 }}\r\n onMouseEnter={() => setIsHovered(true)}\r\n onMouseLeave={() => { setIsHovered(false); if (trigger === \"hover\") hideTooltip(); }}\r\n className={cn(\"absolute z-50 w-80 bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 rounded-xl shadow-xl backdrop-blur-sm\", getPositionClasses())}\r\n >\r\n <div className=\"p-4 space-y-3\">\r\n <div className=\"flex items-start justify-between gap-2\">\r\n <div className=\"flex-1 space-y-1\">\r\n {title && <h3 className=\"font-semibold text-zinc-900 dark:text-zinc-100 text-sm\">{title}</h3>}\r\n <p className=\"text-sm text-zinc-600 dark:text-zinc-400 leading-relaxed\">{content}</p>\r\n </div>\r\n {(trigger === \"click\" || persistent) && (\r\n <button onClick={handleClose} className=\"text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-200 transition-colors p-1 rounded-md hover:bg-zinc-100 dark:hover:bg-zinc-800\">\r\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" /></svg>\r\n </button>\r\n )}\r\n </div>\r\n {actions.length > 0 && (\r\n <div className=\"flex gap-2 pt-2 border-t border-zinc-200 dark:border-zinc-800\">\r\n {actions.map((action, index) => (\r\n <button key={index} onClick={() => { action.onClick(); if (!persistent) handleClose(); }}\r\n className={cn(\"text-xs h-8 px-3 rounded-md font-medium transition-colors\",\r\n action.variant === \"destructive\" ? \"bg-red-500 text-white hover:bg-red-600\" :\r\n action.variant === \"secondary\" ? \"bg-zinc-100 dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 hover:bg-zinc-200 dark:hover:bg-zinc-700\" :\r\n \"bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 hover:bg-zinc-800 dark:hover:bg-zinc-100\"\r\n )}\r\n >{action.label}</button>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n </motion.div>\r\n )}\r\n </AnimatePresence>\r\n </div>\r\n );\r\n}\r\n\r\nexport default TooltipInteractive;\r\n"]}
@@ -0,0 +1,2 @@
1
+ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var react=require('react'),framerMotion=require('framer-motion'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),jsxRuntime=require('react/jsx-runtime');function m(...i){return tailwindMerge.twMerge(clsx.clsx(i))}function L({content:i,children:h,offset:v=20,springConfig:l={stiffness:300,damping:30},className:x}){let[M,d]=react.useState(false),o=react.useRef(null),s=framerMotion.useMotionValue(0),a=framerMotion.useMotionValue(0),y=framerMotion.useSpring(s,l),z=framerMotion.useSpring(a,l),w=react.useCallback(u=>{if(!o.current)return;let e=o.current.getBoundingClientRect(),R=e.left+e.width/2,X=e.top+e.height/2,r=u.clientX-R,c=u.clientY-X,Y=Math.sqrt(r*r+c*c),I=Math.max(e.width,e.height),p=1-Math.min(Y/I,1);s.set(r*p*.5),a.set(c*p*.5);},[s,a]),N=()=>d(true),k=()=>{d(false),s.set(0),a.set(0);};return jsxRuntime.jsxs("div",{ref:o,className:m("relative inline-block",x),onMouseMove:w,onMouseEnter:N,onMouseLeave:k,children:[h,jsxRuntime.jsx(framerMotion.AnimatePresence,{children:M&&jsxRuntime.jsx(framerMotion.motion.div,{style:{x:y,y:z},initial:{opacity:0,scale:.8},animate:{opacity:1,scale:1},exit:{opacity:0,scale:.8},transition:{type:"spring",stiffness:400,damping:25},className:"absolute z-50 pointer-events-none",children:jsxRuntime.jsxs(framerMotion.motion.div,{className:"relative px-4 py-2 text-sm text-zinc-900 dark:text-zinc-100 bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 rounded-xl shadow-xl backdrop-blur-sm whitespace-nowrap",style:{translateX:"-50%",translateY:`calc(-100% - ${v}px)`},whileHover:{scale:1.05},children:[i,jsxRuntime.jsx(framerMotion.motion.div,{className:"absolute inset-0 bg-gradient-to-r from-blue-500/20 to-purple-500/20 rounded-xl -z-10 blur-sm",animate:{scale:[1,1.1,1],opacity:[.5,.8,.5]},transition:{duration:2,repeat:1/0,ease:"easeInOut"}}),jsxRuntime.jsx(framerMotion.motion.div,{initial:{scale:0},animate:{scale:1},transition:{delay:.1,type:"spring",stiffness:400},className:"absolute top-full left-1/2 -translate-x-1/2 w-0 h-0 border-4 border-l-transparent border-r-transparent border-b-transparent border-t-white dark:border-t-zinc-900"}),jsxRuntime.jsx(framerMotion.motion.div,{className:"absolute inset-0 rounded-xl border border-blue-500/30 -z-10",animate:{scale:[1,1.2,1],opacity:[.3,.6,.3]},transition:{duration:1.5,repeat:1/0,ease:"easeInOut"}})]})})})]})}var F=L;exports.TooltipMagnetic=L;exports.default=F;//# sourceMappingURL=index.js.map
2
+ //# sourceMappingURL=index.js.map