fancy-ui-svelte 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (418) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +198 -0
  3. package/dist/fancy-ui/_template/Component.svelte +110 -0
  4. package/dist/fancy-ui/_template/Component.svelte.d.ts +16 -0
  5. package/dist/fancy-ui/_template/README.md +279 -0
  6. package/dist/fancy-ui/_template/index.d.ts +13 -0
  7. package/dist/fancy-ui/_template/index.js +27 -0
  8. package/dist/fancy-ui/_template/types.d.ts +53 -0
  9. package/dist/fancy-ui/_template/types.js +12 -0
  10. package/dist/fancy-ui/animated-beam/AnimatedBeam.svelte +166 -0
  11. package/dist/fancy-ui/animated-beam/AnimatedBeam.svelte.d.ts +4 -0
  12. package/dist/fancy-ui/animated-beam/AnimatedBeam.test.d.ts +1 -0
  13. package/dist/fancy-ui/animated-beam/AnimatedBeam.test.js +49 -0
  14. package/dist/fancy-ui/animated-beam/README.md +38 -0
  15. package/dist/fancy-ui/animated-beam/index.d.ts +2 -0
  16. package/dist/fancy-ui/animated-beam/index.js +1 -0
  17. package/dist/fancy-ui/animated-beam/types.d.ts +19 -0
  18. package/dist/fancy-ui/animated-beam/types.js +1 -0
  19. package/dist/fancy-ui/animated-testimonials/AnimatedTestimonials.svelte +196 -0
  20. package/dist/fancy-ui/animated-testimonials/AnimatedTestimonials.svelte.d.ts +29 -0
  21. package/dist/fancy-ui/animated-testimonials/AnimatedTestimonials.test.d.ts +1 -0
  22. package/dist/fancy-ui/animated-testimonials/AnimatedTestimonials.test.js +92 -0
  23. package/dist/fancy-ui/animated-testimonials/index.d.ts +2 -0
  24. package/dist/fancy-ui/animated-testimonials/index.js +1 -0
  25. package/dist/fancy-ui/animated-tooltip/AnimatedTooltip.svelte +97 -0
  26. package/dist/fancy-ui/animated-tooltip/AnimatedTooltip.svelte.d.ts +15 -0
  27. package/dist/fancy-ui/animated-tooltip/AnimatedTooltip.test.d.ts +1 -0
  28. package/dist/fancy-ui/animated-tooltip/AnimatedTooltip.test.js +67 -0
  29. package/dist/fancy-ui/animated-tooltip/index.d.ts +2 -0
  30. package/dist/fancy-ui/animated-tooltip/index.js +1 -0
  31. package/dist/fancy-ui/apple-card-carousel/AppleCard.svelte +226 -0
  32. package/dist/fancy-ui/apple-card-carousel/AppleCard.svelte.d.ts +27 -0
  33. package/dist/fancy-ui/apple-card-carousel/AppleCardCarousel.svelte +49 -0
  34. package/dist/fancy-ui/apple-card-carousel/AppleCardCarousel.svelte.d.ts +11 -0
  35. package/dist/fancy-ui/apple-card-carousel/AppleCardCarousel.test.d.ts +1 -0
  36. package/dist/fancy-ui/apple-card-carousel/AppleCardCarousel.test.js +85 -0
  37. package/dist/fancy-ui/apple-card-carousel/index.d.ts +3 -0
  38. package/dist/fancy-ui/apple-card-carousel/index.js +2 -0
  39. package/dist/fancy-ui/bento-grid/BentoGrid.svelte +21 -0
  40. package/dist/fancy-ui/bento-grid/BentoGrid.svelte.d.ts +7 -0
  41. package/dist/fancy-ui/bento-grid/BentoGridCard.svelte +70 -0
  42. package/dist/fancy-ui/bento-grid/BentoGridCard.svelte.d.ts +12 -0
  43. package/dist/fancy-ui/bento-grid/BentoGridItem.svelte +39 -0
  44. package/dist/fancy-ui/bento-grid/BentoGridItem.svelte.d.ts +10 -0
  45. package/dist/fancy-ui/bento-grid/README.md +51 -0
  46. package/dist/fancy-ui/bento-grid/index.d.ts +3 -0
  47. package/dist/fancy-ui/bento-grid/index.js +3 -0
  48. package/dist/fancy-ui/bg-falling-stars/FallingStarsBg.svelte +163 -0
  49. package/dist/fancy-ui/bg-falling-stars/FallingStarsBg.svelte.d.ts +11 -0
  50. package/dist/fancy-ui/bg-falling-stars/FallingStarsBg.test.d.ts +1 -0
  51. package/dist/fancy-ui/bg-falling-stars/FallingStarsBg.test.js +50 -0
  52. package/dist/fancy-ui/bg-falling-stars/README.md +22 -0
  53. package/dist/fancy-ui/bg-falling-stars/index.d.ts +2 -0
  54. package/dist/fancy-ui/bg-falling-stars/index.js +1 -0
  55. package/dist/fancy-ui/bg-stars/README.md +41 -0
  56. package/dist/fancy-ui/bg-stars/StarsBackground.svelte +205 -0
  57. package/dist/fancy-ui/bg-stars/StarsBackground.svelte.d.ts +33 -0
  58. package/dist/fancy-ui/bg-stars/StarsBackground.test.d.ts +1 -0
  59. package/dist/fancy-ui/bg-stars/StarsBackground.test.js +46 -0
  60. package/dist/fancy-ui/bg-stars/index.d.ts +1 -0
  61. package/dist/fancy-ui/bg-stars/index.js +1 -0
  62. package/dist/fancy-ui/blur-reveal/BlurReveal.svelte +126 -0
  63. package/dist/fancy-ui/blur-reveal/BlurReveal.svelte.d.ts +18 -0
  64. package/dist/fancy-ui/blur-reveal/BlurReveal.test.d.ts +1 -0
  65. package/dist/fancy-ui/blur-reveal/BlurReveal.test.js +47 -0
  66. package/dist/fancy-ui/blur-reveal/README.md +41 -0
  67. package/dist/fancy-ui/blur-reveal/index.d.ts +2 -0
  68. package/dist/fancy-ui/blur-reveal/index.js +2 -0
  69. package/dist/fancy-ui/book/Book.svelte +89 -0
  70. package/dist/fancy-ui/book/Book.svelte.d.ts +15 -0
  71. package/dist/fancy-ui/book/Book.test.d.ts +1 -0
  72. package/dist/fancy-ui/book/Book.test.js +47 -0
  73. package/dist/fancy-ui/book/BookDescription.svelte +17 -0
  74. package/dist/fancy-ui/book/BookDescription.svelte.d.ts +8 -0
  75. package/dist/fancy-ui/book/BookHeader.svelte +17 -0
  76. package/dist/fancy-ui/book/BookHeader.svelte.d.ts +8 -0
  77. package/dist/fancy-ui/book/BookTitle.svelte +17 -0
  78. package/dist/fancy-ui/book/BookTitle.svelte.d.ts +8 -0
  79. package/dist/fancy-ui/book/README.md +34 -0
  80. package/dist/fancy-ui/book/index.d.ts +128 -0
  81. package/dist/fancy-ui/book/index.js +46 -0
  82. package/dist/fancy-ui/border-beam/BorderBeam.svelte +85 -0
  83. package/dist/fancy-ui/border-beam/BorderBeam.svelte.d.ts +27 -0
  84. package/dist/fancy-ui/border-beam/BorderBeam.test.d.ts +1 -0
  85. package/dist/fancy-ui/border-beam/BorderBeam.test.js +64 -0
  86. package/dist/fancy-ui/border-beam/index.d.ts +2 -0
  87. package/dist/fancy-ui/border-beam/index.js +2 -0
  88. package/dist/fancy-ui/box-reveal/BoxReveal.svelte +73 -0
  89. package/dist/fancy-ui/box-reveal/BoxReveal.svelte.d.ts +24 -0
  90. package/dist/fancy-ui/box-reveal/BoxReveal.test.d.ts +1 -0
  91. package/dist/fancy-ui/box-reveal/BoxReveal.test.js +66 -0
  92. package/dist/fancy-ui/box-reveal/README.md +24 -0
  93. package/dist/fancy-ui/box-reveal/index.d.ts +2 -0
  94. package/dist/fancy-ui/box-reveal/index.js +2 -0
  95. package/dist/fancy-ui/card-3d/CardBody.svelte +16 -0
  96. package/dist/fancy-ui/card-3d/CardBody.svelte.d.ts +7 -0
  97. package/dist/fancy-ui/card-3d/CardContainer.svelte +53 -0
  98. package/dist/fancy-ui/card-3d/CardContainer.svelte.d.ts +8 -0
  99. package/dist/fancy-ui/card-3d/CardItem.svelte +49 -0
  100. package/dist/fancy-ui/card-3d/CardItem.svelte.d.ts +14 -0
  101. package/dist/fancy-ui/card-3d/README.md +52 -0
  102. package/dist/fancy-ui/card-3d/index.d.ts +3 -0
  103. package/dist/fancy-ui/card-3d/index.js +3 -0
  104. package/dist/fancy-ui/card-spotlight/CardSpotlight.svelte +59 -0
  105. package/dist/fancy-ui/card-spotlight/CardSpotlight.svelte.d.ts +11 -0
  106. package/dist/fancy-ui/card-spotlight/README.md +24 -0
  107. package/dist/fancy-ui/card-spotlight/index.d.ts +1 -0
  108. package/dist/fancy-ui/card-spotlight/index.js +1 -0
  109. package/dist/fancy-ui/colourful-text/ColourfulText.svelte +78 -0
  110. package/dist/fancy-ui/colourful-text/ColourfulText.svelte.d.ts +22 -0
  111. package/dist/fancy-ui/colourful-text/ColourfulText.test.d.ts +1 -0
  112. package/dist/fancy-ui/colourful-text/ColourfulText.test.js +53 -0
  113. package/dist/fancy-ui/colourful-text/README.md +21 -0
  114. package/dist/fancy-ui/colourful-text/index.d.ts +2 -0
  115. package/dist/fancy-ui/colourful-text/index.js +2 -0
  116. package/dist/fancy-ui/compare/Compare.svelte +304 -0
  117. package/dist/fancy-ui/compare/Compare.svelte.d.ts +25 -0
  118. package/dist/fancy-ui/compare/Compare.test.d.ts +1 -0
  119. package/dist/fancy-ui/compare/Compare.test.js +57 -0
  120. package/dist/fancy-ui/compare/README.md +97 -0
  121. package/dist/fancy-ui/compare/StarField.svelte +108 -0
  122. package/dist/fancy-ui/compare/StarField.svelte.d.ts +7 -0
  123. package/dist/fancy-ui/compare/index.d.ts +2 -0
  124. package/dist/fancy-ui/compare/index.js +2 -0
  125. package/dist/fancy-ui/confetti/Confetti.svelte +60 -0
  126. package/dist/fancy-ui/confetti/Confetti.svelte.d.ts +14 -0
  127. package/dist/fancy-ui/confetti/Confetti.test.d.ts +1 -0
  128. package/dist/fancy-ui/confetti/Confetti.test.js +39 -0
  129. package/dist/fancy-ui/confetti/ConfettiButton.svelte +41 -0
  130. package/dist/fancy-ui/confetti/ConfettiButton.svelte.d.ts +9 -0
  131. package/dist/fancy-ui/confetti/README.md +22 -0
  132. package/dist/fancy-ui/confetti/index.d.ts +2 -0
  133. package/dist/fancy-ui/confetti/index.js +2 -0
  134. package/dist/fancy-ui/container-scroll/ContainerScroll.svelte +82 -0
  135. package/dist/fancy-ui/container-scroll/ContainerScroll.svelte.d.ts +9 -0
  136. package/dist/fancy-ui/container-scroll/ContainerScroll.test.d.ts +1 -0
  137. package/dist/fancy-ui/container-scroll/ContainerScroll.test.js +34 -0
  138. package/dist/fancy-ui/container-scroll/README.md +28 -0
  139. package/dist/fancy-ui/container-scroll/index.d.ts +1 -0
  140. package/dist/fancy-ui/container-scroll/index.js +1 -0
  141. package/dist/fancy-ui/container-text-flip/ContainerTextFlip.svelte +78 -0
  142. package/dist/fancy-ui/container-text-flip/ContainerTextFlip.svelte.d.ts +10 -0
  143. package/dist/fancy-ui/container-text-flip/ContainerTextFlip.test.d.ts +1 -0
  144. package/dist/fancy-ui/container-text-flip/ContainerTextFlip.test.js +46 -0
  145. package/dist/fancy-ui/container-text-flip/README.md +22 -0
  146. package/dist/fancy-ui/container-text-flip/index.d.ts +1 -0
  147. package/dist/fancy-ui/container-text-flip/index.js +1 -0
  148. package/dist/fancy-ui/direction-aware-hover/DirectionAwareHover.svelte +232 -0
  149. package/dist/fancy-ui/direction-aware-hover/DirectionAwareHover.svelte.d.ts +11 -0
  150. package/dist/fancy-ui/direction-aware-hover/DirectionAwareHover.test.d.ts +1 -0
  151. package/dist/fancy-ui/direction-aware-hover/DirectionAwareHover.test.js +78 -0
  152. package/dist/fancy-ui/direction-aware-hover/README.md +47 -0
  153. package/dist/fancy-ui/direction-aware-hover/index.d.ts +1 -0
  154. package/dist/fancy-ui/direction-aware-hover/index.js +1 -0
  155. package/dist/fancy-ui/displacement-text/DisplacementText.svelte +224 -0
  156. package/dist/fancy-ui/displacement-text/DisplacementText.svelte.d.ts +19 -0
  157. package/dist/fancy-ui/displacement-text/DisplacementText.test.d.ts +1 -0
  158. package/dist/fancy-ui/displacement-text/DisplacementText.test.js +144 -0
  159. package/dist/fancy-ui/displacement-text/index.d.ts +2 -0
  160. package/dist/fancy-ui/displacement-text/index.js +1 -0
  161. package/dist/fancy-ui/dock/Dock.svelte +87 -0
  162. package/dist/fancy-ui/dock/Dock.svelte.d.ts +12 -0
  163. package/dist/fancy-ui/dock/Dock.test.d.ts +1 -0
  164. package/dist/fancy-ui/dock/Dock.test.js +51 -0
  165. package/dist/fancy-ui/dock/DockIcon.svelte +50 -0
  166. package/dist/fancy-ui/dock/DockIcon.svelte.d.ts +7 -0
  167. package/dist/fancy-ui/dock/DockSeparator.svelte +21 -0
  168. package/dist/fancy-ui/dock/DockSeparator.svelte.d.ts +6 -0
  169. package/dist/fancy-ui/dock/README.md +57 -0
  170. package/dist/fancy-ui/dock/index.d.ts +4 -0
  171. package/dist/fancy-ui/dock/index.js +4 -0
  172. package/dist/fancy-ui/dock/types.d.ts +14 -0
  173. package/dist/fancy-ui/dock/types.js +1 -0
  174. package/dist/fancy-ui/flickering-grid/FlickeringGrid.svelte +154 -0
  175. package/dist/fancy-ui/flickering-grid/FlickeringGrid.svelte.d.ts +27 -0
  176. package/dist/fancy-ui/flickering-grid/FlickeringGrid.test.d.ts +1 -0
  177. package/dist/fancy-ui/flickering-grid/FlickeringGrid.test.js +34 -0
  178. package/dist/fancy-ui/flickering-grid/README.md +24 -0
  179. package/dist/fancy-ui/flickering-grid/index.d.ts +2 -0
  180. package/dist/fancy-ui/flickering-grid/index.js +2 -0
  181. package/dist/fancy-ui/flip-card/FlipCard.svelte +48 -0
  182. package/dist/fancy-ui/flip-card/FlipCard.svelte.d.ts +10 -0
  183. package/dist/fancy-ui/flip-card/FlipCard.test.d.ts +1 -0
  184. package/dist/fancy-ui/flip-card/FlipCard.test.js +36 -0
  185. package/dist/fancy-ui/flip-card/README.md +26 -0
  186. package/dist/fancy-ui/flip-card/index.d.ts +1 -0
  187. package/dist/fancy-ui/flip-card/index.js +1 -0
  188. package/dist/fancy-ui/flip-words/FlipWords.svelte +135 -0
  189. package/dist/fancy-ui/flip-words/FlipWords.svelte.d.ts +18 -0
  190. package/dist/fancy-ui/flip-words/FlipWords.test.d.ts +1 -0
  191. package/dist/fancy-ui/flip-words/FlipWords.test.js +50 -0
  192. package/dist/fancy-ui/flip-words/README.md +17 -0
  193. package/dist/fancy-ui/flip-words/index.d.ts +2 -0
  194. package/dist/fancy-ui/flip-words/index.js +2 -0
  195. package/dist/fancy-ui/fluid-cursor/FluidCursor.svelte +1378 -0
  196. package/dist/fancy-ui/fluid-cursor/FluidCursor.svelte.d.ts +25 -0
  197. package/dist/fancy-ui/fluid-cursor/FluidCursor.test.d.ts +1 -0
  198. package/dist/fancy-ui/fluid-cursor/FluidCursor.test.js +41 -0
  199. package/dist/fancy-ui/fluid-cursor/README.md +34 -0
  200. package/dist/fancy-ui/fluid-cursor/index.d.ts +1 -0
  201. package/dist/fancy-ui/fluid-cursor/index.js +1 -0
  202. package/dist/fancy-ui/focus/Focus.svelte +177 -0
  203. package/dist/fancy-ui/focus/Focus.svelte.d.ts +12 -0
  204. package/dist/fancy-ui/focus/Focus.test.d.ts +1 -0
  205. package/dist/fancy-ui/focus/Focus.test.js +48 -0
  206. package/dist/fancy-ui/focus/README.md +21 -0
  207. package/dist/fancy-ui/focus/index.d.ts +1 -0
  208. package/dist/fancy-ui/focus/index.js +1 -0
  209. package/dist/fancy-ui/glare-card/GlareCard.svelte +133 -0
  210. package/dist/fancy-ui/glare-card/GlareCard.svelte.d.ts +8 -0
  211. package/dist/fancy-ui/glare-card/GlareCard.test.d.ts +1 -0
  212. package/dist/fancy-ui/glare-card/GlareCard.test.js +40 -0
  213. package/dist/fancy-ui/glare-card/README.md +24 -0
  214. package/dist/fancy-ui/glare-card/index.d.ts +1 -0
  215. package/dist/fancy-ui/glare-card/index.js +1 -0
  216. package/dist/fancy-ui/glow-border/GlowBorder.svelte +67 -0
  217. package/dist/fancy-ui/glow-border/GlowBorder.svelte.d.ts +10 -0
  218. package/dist/fancy-ui/glow-border/GlowBorder.test.d.ts +1 -0
  219. package/dist/fancy-ui/glow-border/GlowBorder.test.js +57 -0
  220. package/dist/fancy-ui/glow-border/README.md +54 -0
  221. package/dist/fancy-ui/glow-border/index.d.ts +1 -0
  222. package/dist/fancy-ui/glow-border/index.js +1 -0
  223. package/dist/fancy-ui/glowing-effect/GlowingEffect.svelte +182 -0
  224. package/dist/fancy-ui/glowing-effect/GlowingEffect.svelte.d.ts +15 -0
  225. package/dist/fancy-ui/glowing-effect/GlowingEffect.test.d.ts +1 -0
  226. package/dist/fancy-ui/glowing-effect/GlowingEffect.test.js +68 -0
  227. package/dist/fancy-ui/glowing-effect/README.md +29 -0
  228. package/dist/fancy-ui/glowing-effect/index.d.ts +1 -0
  229. package/dist/fancy-ui/glowing-effect/index.js +1 -0
  230. package/dist/fancy-ui/gradient-button/GradientButton.svelte +103 -0
  231. package/dist/fancy-ui/gradient-button/GradientButton.svelte.d.ts +24 -0
  232. package/dist/fancy-ui/gradient-button/GradientButton.test.d.ts +1 -0
  233. package/dist/fancy-ui/gradient-button/GradientButton.test.js +65 -0
  234. package/dist/fancy-ui/gradient-button/README.md +10 -0
  235. package/dist/fancy-ui/gradient-button/index.d.ts +2 -0
  236. package/dist/fancy-ui/gradient-button/index.js +2 -0
  237. package/dist/fancy-ui/hyper-text/HyperText.svelte +112 -0
  238. package/dist/fancy-ui/hyper-text/HyperText.svelte.d.ts +20 -0
  239. package/dist/fancy-ui/hyper-text/HyperText.test.d.ts +1 -0
  240. package/dist/fancy-ui/hyper-text/HyperText.test.js +39 -0
  241. package/dist/fancy-ui/hyper-text/README.md +19 -0
  242. package/dist/fancy-ui/hyper-text/index.d.ts +2 -0
  243. package/dist/fancy-ui/hyper-text/index.js +2 -0
  244. package/dist/fancy-ui/image-trail-cursor/ImageTrailCursor.svelte +89 -0
  245. package/dist/fancy-ui/image-trail-cursor/ImageTrailCursor.svelte.d.ts +9 -0
  246. package/dist/fancy-ui/image-trail-cursor/ImageTrailCursor.test.d.ts +1 -0
  247. package/dist/fancy-ui/image-trail-cursor/ImageTrailCursor.test.js +60 -0
  248. package/dist/fancy-ui/image-trail-cursor/README.md +36 -0
  249. package/dist/fancy-ui/image-trail-cursor/index.d.ts +3 -0
  250. package/dist/fancy-ui/image-trail-cursor/index.js +1 -0
  251. package/dist/fancy-ui/image-trail-cursor/trail-variants.d.ts +107 -0
  252. package/dist/fancy-ui/image-trail-cursor/trail-variants.js +703 -0
  253. package/dist/fancy-ui/index.d.ts +52 -0
  254. package/dist/fancy-ui/index.js +64 -0
  255. package/dist/fancy-ui/interactive-grid-pattern/InteractiveGridPattern.svelte +71 -0
  256. package/dist/fancy-ui/interactive-grid-pattern/InteractiveGridPattern.svelte.d.ts +15 -0
  257. package/dist/fancy-ui/interactive-grid-pattern/InteractiveGridPattern.test.d.ts +1 -0
  258. package/dist/fancy-ui/interactive-grid-pattern/InteractiveGridPattern.test.js +47 -0
  259. package/dist/fancy-ui/interactive-grid-pattern/README.md +30 -0
  260. package/dist/fancy-ui/interactive-grid-pattern/index.d.ts +2 -0
  261. package/dist/fancy-ui/interactive-grid-pattern/index.js +2 -0
  262. package/dist/fancy-ui/interactive-hover-button/InteractiveHoverButton.svelte +75 -0
  263. package/dist/fancy-ui/interactive-hover-button/InteractiveHoverButton.svelte.d.ts +14 -0
  264. package/dist/fancy-ui/interactive-hover-button/InteractiveHoverButton.test.d.ts +1 -0
  265. package/dist/fancy-ui/interactive-hover-button/InteractiveHoverButton.test.js +64 -0
  266. package/dist/fancy-ui/interactive-hover-button/README.md +28 -0
  267. package/dist/fancy-ui/interactive-hover-button/index.d.ts +2 -0
  268. package/dist/fancy-ui/interactive-hover-button/index.js +2 -0
  269. package/dist/fancy-ui/letter-pullup/LetterPullup.svelte +58 -0
  270. package/dist/fancy-ui/letter-pullup/LetterPullup.svelte.d.ts +17 -0
  271. package/dist/fancy-ui/letter-pullup/LetterPullup.test.d.ts +1 -0
  272. package/dist/fancy-ui/letter-pullup/LetterPullup.test.js +49 -0
  273. package/dist/fancy-ui/letter-pullup/README.md +18 -0
  274. package/dist/fancy-ui/letter-pullup/index.d.ts +2 -0
  275. package/dist/fancy-ui/letter-pullup/index.js +2 -0
  276. package/dist/fancy-ui/line-hover-link/LineHoverLink.svelte +450 -0
  277. package/dist/fancy-ui/line-hover-link/LineHoverLink.svelte.d.ts +35 -0
  278. package/dist/fancy-ui/line-hover-link/LineHoverLink.test.d.ts +1 -0
  279. package/dist/fancy-ui/line-hover-link/LineHoverLink.test.js +55 -0
  280. package/dist/fancy-ui/line-hover-link/index.d.ts +2 -0
  281. package/dist/fancy-ui/line-hover-link/index.js +1 -0
  282. package/dist/fancy-ui/line-shadow-text/LineShadowText.svelte +63 -0
  283. package/dist/fancy-ui/line-shadow-text/LineShadowText.svelte.d.ts +9 -0
  284. package/dist/fancy-ui/line-shadow-text/LineShadowText.test.d.ts +1 -0
  285. package/dist/fancy-ui/line-shadow-text/LineShadowText.test.js +59 -0
  286. package/dist/fancy-ui/line-shadow-text/README.md +12 -0
  287. package/dist/fancy-ui/line-shadow-text/index.d.ts +2 -0
  288. package/dist/fancy-ui/line-shadow-text/index.js +1 -0
  289. package/dist/fancy-ui/liquid-glass/LiquidGlass.svelte +204 -0
  290. package/dist/fancy-ui/liquid-glass/LiquidGlass.svelte.d.ts +23 -0
  291. package/dist/fancy-ui/liquid-glass/LiquidGlass.test.d.ts +1 -0
  292. package/dist/fancy-ui/liquid-glass/LiquidGlass.test.js +48 -0
  293. package/dist/fancy-ui/liquid-glass/README.md +34 -0
  294. package/dist/fancy-ui/liquid-glass/index.d.ts +1 -0
  295. package/dist/fancy-ui/liquid-glass/index.js +1 -0
  296. package/dist/fancy-ui/logo-cloud/AnimatedLogoCloud.svelte +61 -0
  297. package/dist/fancy-ui/logo-cloud/AnimatedLogoCloud.svelte.d.ts +15 -0
  298. package/dist/fancy-ui/logo-cloud/AnimatedLogoCloud.test.d.ts +1 -0
  299. package/dist/fancy-ui/logo-cloud/AnimatedLogoCloud.test.js +59 -0
  300. package/dist/fancy-ui/logo-cloud/IconLogoCloud.svelte +31 -0
  301. package/dist/fancy-ui/logo-cloud/IconLogoCloud.svelte.d.ts +11 -0
  302. package/dist/fancy-ui/logo-cloud/README.md +41 -0
  303. package/dist/fancy-ui/logo-cloud/StaticLogoCloud.svelte +31 -0
  304. package/dist/fancy-ui/logo-cloud/StaticLogoCloud.svelte.d.ts +11 -0
  305. package/dist/fancy-ui/logo-cloud/index.d.ts +4 -0
  306. package/dist/fancy-ui/logo-cloud/index.js +4 -0
  307. package/dist/fancy-ui/marquee/Marquee.svelte +70 -0
  308. package/dist/fancy-ui/marquee/Marquee.svelte.d.ts +11 -0
  309. package/dist/fancy-ui/marquee/Marquee.test.d.ts +1 -0
  310. package/dist/fancy-ui/marquee/Marquee.test.js +46 -0
  311. package/dist/fancy-ui/marquee/ReviewCard.svelte +25 -0
  312. package/dist/fancy-ui/marquee/ReviewCard.svelte.d.ts +9 -0
  313. package/dist/fancy-ui/marquee/index.d.ts +2 -0
  314. package/dist/fancy-ui/marquee/index.js +2 -0
  315. package/dist/fancy-ui/meteors/Meteors.svelte +59 -0
  316. package/dist/fancy-ui/meteors/Meteors.svelte.d.ts +15 -0
  317. package/dist/fancy-ui/meteors/Meteors.test.d.ts +1 -0
  318. package/dist/fancy-ui/meteors/Meteors.test.js +48 -0
  319. package/dist/fancy-ui/meteors/README.md +18 -0
  320. package/dist/fancy-ui/meteors/index.d.ts +2 -0
  321. package/dist/fancy-ui/meteors/index.js +2 -0
  322. package/dist/fancy-ui/neon-border/NeonBorder.svelte +135 -0
  323. package/dist/fancy-ui/neon-border/NeonBorder.svelte.d.ts +24 -0
  324. package/dist/fancy-ui/neon-border/NeonBorder.test.d.ts +1 -0
  325. package/dist/fancy-ui/neon-border/NeonBorder.test.js +80 -0
  326. package/dist/fancy-ui/neon-border/README.md +27 -0
  327. package/dist/fancy-ui/neon-border/index.d.ts +2 -0
  328. package/dist/fancy-ui/neon-border/index.js +2 -0
  329. package/dist/fancy-ui/number-ticker/NumberTicker.svelte +126 -0
  330. package/dist/fancy-ui/number-ticker/NumberTicker.svelte.d.ts +24 -0
  331. package/dist/fancy-ui/number-ticker/NumberTicker.test.d.ts +1 -0
  332. package/dist/fancy-ui/number-ticker/NumberTicker.test.js +64 -0
  333. package/dist/fancy-ui/number-ticker/README.md +22 -0
  334. package/dist/fancy-ui/number-ticker/index.d.ts +2 -0
  335. package/dist/fancy-ui/number-ticker/index.js +2 -0
  336. package/dist/fancy-ui/rainbow-button/RainbowButton.svelte +96 -0
  337. package/dist/fancy-ui/rainbow-button/RainbowButton.svelte.d.ts +18 -0
  338. package/dist/fancy-ui/rainbow-button/RainbowButton.test.d.ts +1 -0
  339. package/dist/fancy-ui/rainbow-button/RainbowButton.test.js +51 -0
  340. package/dist/fancy-ui/rainbow-button/index.d.ts +2 -0
  341. package/dist/fancy-ui/rainbow-button/index.js +2 -0
  342. package/dist/fancy-ui/registry.d.ts +72 -0
  343. package/dist/fancy-ui/registry.js +643 -0
  344. package/dist/fancy-ui/ripple/README.md +16 -0
  345. package/dist/fancy-ui/ripple/Ripple.svelte +64 -0
  346. package/dist/fancy-ui/ripple/Ripple.svelte.d.ts +13 -0
  347. package/dist/fancy-ui/ripple/Ripple.test.d.ts +1 -0
  348. package/dist/fancy-ui/ripple/Ripple.test.js +81 -0
  349. package/dist/fancy-ui/ripple/index.d.ts +1 -0
  350. package/dist/fancy-ui/ripple/index.js +1 -0
  351. package/dist/fancy-ui/ripple-button/RippleButton.svelte +111 -0
  352. package/dist/fancy-ui/ripple-button/RippleButton.svelte.d.ts +15 -0
  353. package/dist/fancy-ui/ripple-button/RippleButton.test.d.ts +1 -0
  354. package/dist/fancy-ui/ripple-button/RippleButton.test.js +44 -0
  355. package/dist/fancy-ui/ripple-button/index.d.ts +2 -0
  356. package/dist/fancy-ui/ripple-button/index.js +2 -0
  357. package/dist/fancy-ui/shimmer-button/README.md +10 -0
  358. package/dist/fancy-ui/shimmer-button/ShimmerButton.svelte +115 -0
  359. package/dist/fancy-ui/shimmer-button/ShimmerButton.svelte.d.ts +22 -0
  360. package/dist/fancy-ui/shimmer-button/ShimmerButton.test.d.ts +1 -0
  361. package/dist/fancy-ui/shimmer-button/ShimmerButton.test.js +69 -0
  362. package/dist/fancy-ui/shimmer-button/index.d.ts +2 -0
  363. package/dist/fancy-ui/shimmer-button/index.js +2 -0
  364. package/dist/fancy-ui/smooth-cursor/README.md +23 -0
  365. package/dist/fancy-ui/smooth-cursor/SmoothCursor.svelte +224 -0
  366. package/dist/fancy-ui/smooth-cursor/SmoothCursor.svelte.d.ts +20 -0
  367. package/dist/fancy-ui/smooth-cursor/index.d.ts +2 -0
  368. package/dist/fancy-ui/smooth-cursor/index.js +1 -0
  369. package/dist/fancy-ui/sparkles/README.md +15 -0
  370. package/dist/fancy-ui/sparkles/Sparkles.svelte +123 -0
  371. package/dist/fancy-ui/sparkles/Sparkles.svelte.d.ts +12 -0
  372. package/dist/fancy-ui/sparkles/Sparkles.test.d.ts +1 -0
  373. package/dist/fancy-ui/sparkles/Sparkles.test.js +66 -0
  374. package/dist/fancy-ui/sparkles/index.d.ts +1 -0
  375. package/dist/fancy-ui/sparkles/index.js +1 -0
  376. package/dist/fancy-ui/sparkles-text/README.md +19 -0
  377. package/dist/fancy-ui/sparkles-text/SparklesText.svelte +112 -0
  378. package/dist/fancy-ui/sparkles-text/SparklesText.svelte.d.ts +22 -0
  379. package/dist/fancy-ui/sparkles-text/SparklesText.test.d.ts +1 -0
  380. package/dist/fancy-ui/sparkles-text/SparklesText.test.js +54 -0
  381. package/dist/fancy-ui/sparkles-text/index.d.ts +2 -0
  382. package/dist/fancy-ui/sparkles-text/index.js +2 -0
  383. package/dist/fancy-ui/tailwind.css +3 -0
  384. package/dist/fancy-ui/text-generate-effect/README.md +14 -0
  385. package/dist/fancy-ui/text-generate-effect/TextGenerateEffect.svelte +66 -0
  386. package/dist/fancy-ui/text-generate-effect/TextGenerateEffect.svelte.d.ts +11 -0
  387. package/dist/fancy-ui/text-generate-effect/TextGenerateEffect.test.d.ts +1 -0
  388. package/dist/fancy-ui/text-generate-effect/TextGenerateEffect.test.js +73 -0
  389. package/dist/fancy-ui/text-generate-effect/index.d.ts +2 -0
  390. package/dist/fancy-ui/text-generate-effect/index.js +1 -0
  391. package/dist/fancy-ui/text-reveal-card/README.md +36 -0
  392. package/dist/fancy-ui/text-reveal-card/TextRevealCard.svelte +112 -0
  393. package/dist/fancy-ui/text-reveal-card/TextRevealCard.svelte.d.ts +12 -0
  394. package/dist/fancy-ui/text-reveal-card/TextRevealCard.test.d.ts +1 -0
  395. package/dist/fancy-ui/text-reveal-card/TextRevealCard.test.js +34 -0
  396. package/dist/fancy-ui/text-reveal-card/TextRevealStars.svelte +76 -0
  397. package/dist/fancy-ui/text-reveal-card/TextRevealStars.svelte.d.ts +7 -0
  398. package/dist/fancy-ui/text-reveal-card/index.d.ts +2 -0
  399. package/dist/fancy-ui/text-reveal-card/index.js +2 -0
  400. package/dist/fancy-ui/timeline/README.md +56 -0
  401. package/dist/fancy-ui/timeline/Timeline.svelte +141 -0
  402. package/dist/fancy-ui/timeline/Timeline.svelte.d.ts +20 -0
  403. package/dist/fancy-ui/timeline/Timeline.test.d.ts +1 -0
  404. package/dist/fancy-ui/timeline/Timeline.test.js +63 -0
  405. package/dist/fancy-ui/timeline/index.d.ts +2 -0
  406. package/dist/fancy-ui/timeline/index.js +2 -0
  407. package/dist/fancy-ui/tracing-beam/README.md +24 -0
  408. package/dist/fancy-ui/tracing-beam/TracingBeam.svelte +156 -0
  409. package/dist/fancy-ui/tracing-beam/TracingBeam.svelte.d.ts +8 -0
  410. package/dist/fancy-ui/tracing-beam/TracingBeam.test.d.ts +1 -0
  411. package/dist/fancy-ui/tracing-beam/TracingBeam.test.js +61 -0
  412. package/dist/fancy-ui/tracing-beam/index.d.ts +1 -0
  413. package/dist/fancy-ui/tracing-beam/index.js +1 -0
  414. package/dist/types.d.ts +87 -0
  415. package/dist/types.js +6 -0
  416. package/dist/utils.d.ts +12 -0
  417. package/dist/utils.js +5 -0
  418. package/package.json +105 -0
@@ -0,0 +1 @@
1
+ export { default as AnimatedTestimonials } from "./AnimatedTestimonials.svelte";
@@ -0,0 +1,97 @@
1
+ <script lang="ts" module>
2
+ import type { Snippet } from "svelte";
3
+
4
+ export interface TooltipItem {
5
+ id: number | string;
6
+ name: string;
7
+ designation: string;
8
+ image: string;
9
+ }
10
+
11
+ export interface AnimatedTooltipProps {
12
+ /** Array of items to display */
13
+ items: TooltipItem[];
14
+ /** Additional CSS classes for the container */
15
+ class?: string;
16
+ }
17
+ </script>
18
+
19
+ <script lang="ts">
20
+ import { cn } from "../../utils.js";
21
+ import { scale } from "svelte/transition";
22
+
23
+ let { items, class: className }: AnimatedTooltipProps = $props();
24
+
25
+ let hoveredIndex = $state<number | string | null>(null);
26
+ let mouseX = $state(0);
27
+
28
+ // Calculate rotation and translation based on mouse position
29
+ let rotation = $derived((mouseX / 100) * 50);
30
+ let translation = $derived((mouseX / 100) * 50);
31
+
32
+ function handleMouseEnter(event: MouseEvent, itemId: number | string) {
33
+ // Reset mouseX first to prevent offset from previous item
34
+ const rect = (event.currentTarget as HTMLElement).getBoundingClientRect();
35
+ const halfWidth = rect.width / 2;
36
+ mouseX = event.clientX - rect.left - halfWidth;
37
+ hoveredIndex = itemId;
38
+ }
39
+
40
+ function handleMouseMove(event: MouseEvent) {
41
+ if (hoveredIndex === null) return;
42
+ const rect = (event.currentTarget as HTMLElement).getBoundingClientRect();
43
+ const halfWidth = rect.width / 2;
44
+ mouseX = event.clientX - rect.left - halfWidth;
45
+ }
46
+
47
+ function handleMouseLeave() {
48
+ hoveredIndex = null;
49
+ mouseX = 0;
50
+ }
51
+ </script>
52
+
53
+ <div class={cn("flex flex-row items-center", className)}>
54
+ {#each items as item (item.id)}
55
+ <div
56
+ class="group relative -mr-4"
57
+ onmouseenter={(e) => handleMouseEnter(e, item.id)}
58
+ onmouseleave={handleMouseLeave}
59
+ onmousemove={handleMouseMove}
60
+ role="button"
61
+ tabindex="0"
62
+ >
63
+ <!-- Tooltip -->
64
+ {#if hoveredIndex === item.id}
65
+ <div
66
+ class="pointer-events-none absolute -top-16 left-1/2 z-50 flex flex-col items-center justify-center rounded-md bg-black px-4 py-2 text-xs whitespace-nowrap shadow-xl"
67
+ style="transform: translateX(calc(-50% + {translation}px)) rotate({rotation}deg);"
68
+ transition:scale={{
69
+ duration: 200,
70
+ start: 0.6,
71
+ }}
72
+ >
73
+ <!-- Gradient lines -->
74
+ <div
75
+ class="absolute right-1/2 -bottom-px z-30 me-1 h-px w-2/5 translate-x-1/2 bg-gradient-to-r from-transparent via-emerald-500 to-transparent"
76
+ ></div>
77
+ <div
78
+ class="absolute -bottom-px left-1/2 z-30 ms-1 h-px w-2/5 -translate-x-1/2 bg-gradient-to-r from-transparent via-sky-500 to-transparent"
79
+ ></div>
80
+
81
+ <!-- Content -->
82
+ <div class="relative z-30 text-base font-bold text-white">
83
+ {item.name}
84
+ </div>
85
+ <div class="text-xs text-white">{item.designation}</div>
86
+ </div>
87
+ {/if}
88
+
89
+ <!-- Avatar Image -->
90
+ <img
91
+ src={item.image}
92
+ alt={item.name}
93
+ class="relative !m-0 size-14 rounded-full border-2 border-white object-cover object-top !p-0 transition duration-500 group-hover:z-30 group-hover:scale-105"
94
+ />
95
+ </div>
96
+ {/each}
97
+ </div>
@@ -0,0 +1,15 @@
1
+ export interface TooltipItem {
2
+ id: number | string;
3
+ name: string;
4
+ designation: string;
5
+ image: string;
6
+ }
7
+ export interface AnimatedTooltipProps {
8
+ /** Array of items to display */
9
+ items: TooltipItem[];
10
+ /** Additional CSS classes for the container */
11
+ class?: string;
12
+ }
13
+ declare const AnimatedTooltip: import("svelte").Component<AnimatedTooltipProps, {}, "">;
14
+ type AnimatedTooltip = ReturnType<typeof AnimatedTooltip>;
15
+ export default AnimatedTooltip;
@@ -0,0 +1,67 @@
1
+ import { render, cleanup } from "@testing-library/svelte";
2
+ import { afterEach, describe, it, expect } from "vitest";
3
+ import AnimatedTooltip from "./AnimatedTooltip.svelte";
4
+ const mockItems = [
5
+ { id: 1, name: "Alice", designation: "Engineer", image: "/alice.jpg" },
6
+ { id: 2, name: "Bob", designation: "Designer", image: "/bob.jpg" },
7
+ ];
8
+ describe("AnimatedTooltip", () => {
9
+ afterEach(cleanup);
10
+ it("renders one avatar image per item", () => {
11
+ const { container } = render(AnimatedTooltip, {
12
+ props: { items: mockItems },
13
+ });
14
+ const imgs = container.querySelectorAll("img");
15
+ expect(imgs.length).toBe(2);
16
+ });
17
+ it("sets correct alt text on images", () => {
18
+ const { container } = render(AnimatedTooltip, {
19
+ props: { items: mockItems },
20
+ });
21
+ const imgs = container.querySelectorAll("img");
22
+ expect(imgs[0]).toHaveAttribute("alt", "Alice");
23
+ expect(imgs[1]).toHaveAttribute("alt", "Bob");
24
+ });
25
+ it("sets correct src on images", () => {
26
+ const { container } = render(AnimatedTooltip, {
27
+ props: { items: mockItems },
28
+ });
29
+ const imgs = container.querySelectorAll("img");
30
+ expect(imgs[0]).toHaveAttribute("src", "/alice.jpg");
31
+ expect(imgs[1]).toHaveAttribute("src", "/bob.jpg");
32
+ });
33
+ it("renders a flex container", () => {
34
+ const { container } = render(AnimatedTooltip, {
35
+ props: { items: mockItems },
36
+ });
37
+ const wrapper = container.firstElementChild;
38
+ expect(wrapper?.className).toContain("flex");
39
+ });
40
+ it("applies custom class names", () => {
41
+ const { container } = render(AnimatedTooltip, {
42
+ props: { items: mockItems, class: "custom" },
43
+ });
44
+ const wrapper = container.firstElementChild;
45
+ expect(wrapper?.className).toContain("custom");
46
+ });
47
+ it("renders empty when items is empty", () => {
48
+ const { container } = render(AnimatedTooltip, { props: { items: [] } });
49
+ const imgs = container.querySelectorAll("img");
50
+ expect(imgs.length).toBe(0);
51
+ });
52
+ it("each item wrapper has group class", () => {
53
+ const { container } = render(AnimatedTooltip, {
54
+ props: { items: mockItems },
55
+ });
56
+ const groups = container.querySelectorAll(".group");
57
+ expect(groups.length).toBe(2);
58
+ });
59
+ it("images have rounded-full class", () => {
60
+ const { container } = render(AnimatedTooltip, {
61
+ props: { items: mockItems },
62
+ });
63
+ const imgs = container.querySelectorAll("img");
64
+ expect(imgs[0]?.className).toContain("rounded-full");
65
+ expect(imgs[1]?.className).toContain("rounded-full");
66
+ });
67
+ });
@@ -0,0 +1,2 @@
1
+ export { default as AnimatedTooltip } from "./AnimatedTooltip.svelte";
2
+ export type { AnimatedTooltipProps, TooltipItem } from "./AnimatedTooltip.svelte";
@@ -0,0 +1 @@
1
+ export { default as AnimatedTooltip } from "./AnimatedTooltip.svelte";
@@ -0,0 +1,226 @@
1
+ <script lang="ts" module>
2
+ import type { Snippet } from "svelte";
3
+
4
+ export interface AppleCardData {
5
+ /** Category label shown above the title */
6
+ category: string;
7
+ /** Main card title */
8
+ title: string;
9
+ /** URL of the card background image */
10
+ src: string;
11
+ /** Short description shown in the expanded view */
12
+ description?: string;
13
+ /** Rich content shown in the expanded view (takes precedence over description) */
14
+ content?: Snippet;
15
+ }
16
+
17
+ /** Shared transition duration — must stay in sync with the CSS transition below */
18
+ export const TRANSITION_MS = 400;
19
+ </script>
20
+
21
+ <script lang="ts">
22
+ import { tick } from "svelte";
23
+ import { cn } from "../../utils.js";
24
+
25
+ interface Props {
26
+ card: AppleCardData;
27
+ index: number;
28
+ expandedIndex: number;
29
+ reducedMotion: boolean;
30
+ onExpand: (index: number) => void;
31
+ onCollapse: () => void;
32
+ class?: string;
33
+ }
34
+
35
+ let {
36
+ card,
37
+ index,
38
+ expandedIndex,
39
+ reducedMotion,
40
+ onExpand,
41
+ onCollapse,
42
+ class: className = "",
43
+ }: Props = $props();
44
+
45
+ let cardEl: HTMLDivElement;
46
+ let dialogEl: HTMLDivElement;
47
+ let closeBtn: HTMLButtonElement;
48
+ let rect = $state<{ top: number; left: number; width: number; height: number } | null>(null);
49
+ let overlayVisible = $state(false);
50
+ let fullyExpanded = $state(false);
51
+ let previousFocus: HTMLElement | null = null;
52
+
53
+ async function handleExpand() {
54
+ if (expandedIndex !== -1) return;
55
+ previousFocus = document.activeElement as HTMLElement;
56
+ const r = cardEl.getBoundingClientRect();
57
+ rect = { top: r.top, left: r.left, width: r.width, height: r.height };
58
+ overlayVisible = true;
59
+ onExpand(index);
60
+
61
+ // Wait for the overlay to be in the DOM before focusing
62
+ await tick();
63
+ closeBtn?.focus();
64
+
65
+ if (reducedMotion) {
66
+ fullyExpanded = true;
67
+ } else {
68
+ requestAnimationFrame(() => {
69
+ requestAnimationFrame(() => {
70
+ fullyExpanded = true;
71
+ });
72
+ });
73
+ }
74
+ }
75
+
76
+ function handleCollapse() {
77
+ fullyExpanded = false;
78
+ const delay = reducedMotion ? 0 : TRANSITION_MS;
79
+ setTimeout(() => {
80
+ overlayVisible = false;
81
+ onCollapse();
82
+ rect = null;
83
+ previousFocus?.focus();
84
+ previousFocus = null;
85
+ }, delay);
86
+ }
87
+
88
+ function handleCardKeydown(e: KeyboardEvent) {
89
+ if (e.key === "Enter" || e.key === " ") {
90
+ e.preventDefault();
91
+ handleExpand();
92
+ }
93
+ }
94
+
95
+ function handleOverlayKeydown(e: KeyboardEvent) {
96
+ if (e.key === "Escape") {
97
+ handleCollapse();
98
+ return;
99
+ }
100
+ // Simple focus trap: cycle focus within the dialog on Tab
101
+ if (e.key === "Tab" && dialogEl) {
102
+ const focusable = Array.from(
103
+ dialogEl.querySelectorAll<HTMLElement>(
104
+ 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
105
+ )
106
+ );
107
+ if (focusable.length === 0) return;
108
+ const first = focusable[0];
109
+ const last = focusable[focusable.length - 1];
110
+ if (e.shiftKey && document.activeElement === first) {
111
+ e.preventDefault();
112
+ last.focus();
113
+ } else if (!e.shiftKey && document.activeElement === last) {
114
+ e.preventDefault();
115
+ first.focus();
116
+ }
117
+ }
118
+ }
119
+ </script>
120
+
121
+ <!-- Collapsed card in the carousel -->
122
+ <div
123
+ bind:this={cardEl}
124
+ class={cn(
125
+ "relative h-80 w-56 shrink-0 cursor-pointer snap-start overflow-hidden rounded-3xl md:h-96 md:w-72",
126
+ className
127
+ )}
128
+ role="button"
129
+ tabindex="0"
130
+ aria-label="Open {card.title}"
131
+ onclick={handleExpand}
132
+ onkeydown={handleCardKeydown}
133
+ >
134
+ <img
135
+ src={card.src}
136
+ alt={card.title}
137
+ class="absolute inset-0 h-full w-full object-cover transition-transform duration-500 hover:scale-105"
138
+ draggable="false"
139
+ />
140
+ <div class="absolute inset-0 bg-gradient-to-t from-black/60 via-black/10 to-transparent"></div>
141
+ <div class="absolute bottom-0 left-0 p-5">
142
+ <p class="mb-1 text-xs font-semibold tracking-widest text-white/70 uppercase">
143
+ {card.category}
144
+ </p>
145
+ <h3 class="text-base font-semibold text-white md:text-lg">{card.title}</h3>
146
+ </div>
147
+ </div>
148
+
149
+ <!-- Expanded overlay -->
150
+ {#if overlayVisible && rect !== null}
151
+ <!-- svelte-ignore a11y_click_events_have_key_events a11y_no_static_element_interactions -->
152
+ <div
153
+ class="fixed inset-0 z-40 bg-black/80"
154
+ aria-hidden="true"
155
+ style="opacity: {fullyExpanded ? 1 : 0}; transition: opacity {reducedMotion
156
+ ? 0
157
+ : TRANSITION_MS}ms ease;"
158
+ onclick={handleCollapse}
159
+ ></div>
160
+
161
+ <div
162
+ bind:this={dialogEl}
163
+ role="dialog"
164
+ aria-modal="true"
165
+ aria-label={card.title}
166
+ tabindex="-1"
167
+ class="fixed z-50 overflow-y-auto bg-white dark:bg-neutral-900"
168
+ style="
169
+ top: {fullyExpanded ? '0px' : rect.top + 'px'};
170
+ left: {fullyExpanded ? '0px' : rect.left + 'px'};
171
+ width: {fullyExpanded ? '100vw' : rect.width + 'px'};
172
+ height: {fullyExpanded ? '100vh' : rect.height + 'px'};
173
+ border-radius: {fullyExpanded ? '0px' : '1.5rem'};
174
+ transition: {reducedMotion
175
+ ? 'none'
176
+ : `top ${TRANSITION_MS}ms cubic-bezier(0.32,0.72,0,1), left ${TRANSITION_MS}ms cubic-bezier(0.32,0.72,0,1), width ${TRANSITION_MS}ms cubic-bezier(0.32,0.72,0,1), height ${TRANSITION_MS}ms cubic-bezier(0.32,0.72,0,1), border-radius ${TRANSITION_MS}ms cubic-bezier(0.32,0.72,0,1)`};
177
+ "
178
+ onkeydown={handleOverlayKeydown}
179
+ >
180
+ <!-- Close button -->
181
+ <button
182
+ bind:this={closeBtn}
183
+ class="absolute top-4 right-4 z-10 flex h-10 w-10 items-center justify-center rounded-full bg-black/20 backdrop-blur-sm transition-colors hover:bg-black/30"
184
+ aria-label="Close"
185
+ onclick={handleCollapse}
186
+ >
187
+ <svg
188
+ xmlns="http://www.w3.org/2000/svg"
189
+ width="18"
190
+ height="18"
191
+ viewBox="0 0 24 24"
192
+ fill="none"
193
+ stroke="white"
194
+ stroke-width="2.5"
195
+ stroke-linecap="round"
196
+ stroke-linejoin="round"
197
+ >
198
+ <path d="M18 6 6 18" />
199
+ <path d="m6 6 12 12" />
200
+ </svg>
201
+ </button>
202
+
203
+ <!-- Hero image -->
204
+ <div class="relative h-72 w-full shrink-0 md:h-96">
205
+ <img src={card.src} alt={card.title} class="h-full w-full object-cover" draggable="false" />
206
+ <div
207
+ class="absolute inset-0 bg-gradient-to-t from-black/60 via-black/10 to-transparent"
208
+ ></div>
209
+ <div class="absolute bottom-0 left-0 p-6 md:p-8">
210
+ <p class="mb-2 text-xs font-semibold tracking-widest text-white/70 uppercase">
211
+ {card.category}
212
+ </p>
213
+ <h2 class="text-2xl font-bold text-white md:text-3xl">{card.title}</h2>
214
+ </div>
215
+ </div>
216
+
217
+ <!-- Content area -->
218
+ <div class="p-6 md:p-8">
219
+ {#if card.content}
220
+ {@render card.content()}
221
+ {:else if card.description}
222
+ <p class="leading-relaxed text-gray-600 dark:text-neutral-400">{card.description}</p>
223
+ {/if}
224
+ </div>
225
+ </div>
226
+ {/if}
@@ -0,0 +1,27 @@
1
+ import type { Snippet } from "svelte";
2
+ export interface AppleCardData {
3
+ /** Category label shown above the title */
4
+ category: string;
5
+ /** Main card title */
6
+ title: string;
7
+ /** URL of the card background image */
8
+ src: string;
9
+ /** Short description shown in the expanded view */
10
+ description?: string;
11
+ /** Rich content shown in the expanded view (takes precedence over description) */
12
+ content?: Snippet;
13
+ }
14
+ /** Shared transition duration — must stay in sync with the CSS transition below */
15
+ export declare const TRANSITION_MS = 400;
16
+ interface Props {
17
+ card: AppleCardData;
18
+ index: number;
19
+ expandedIndex: number;
20
+ reducedMotion: boolean;
21
+ onExpand: (index: number) => void;
22
+ onCollapse: () => void;
23
+ class?: string;
24
+ }
25
+ declare const AppleCard: import("svelte").Component<Props, {}, "">;
26
+ type AppleCard = ReturnType<typeof AppleCard>;
27
+ export default AppleCard;
@@ -0,0 +1,49 @@
1
+ <script lang="ts" module>
2
+ import type { AppleCardData } from "./AppleCard.svelte";
3
+ export type { AppleCardData };
4
+
5
+ export interface AppleCardCarouselProps {
6
+ /** Cards to display in the carousel */
7
+ cards: AppleCardData[];
8
+ /** Additional CSS classes */
9
+ class?: string;
10
+ }
11
+ </script>
12
+
13
+ <script lang="ts">
14
+ import { onMount } from "svelte";
15
+ import { cn } from "../../utils.js";
16
+ import AppleCard from "./AppleCard.svelte";
17
+
18
+ let { cards, class: className = "" }: AppleCardCarouselProps = $props();
19
+
20
+ let expandedIndex = $state(-1);
21
+ let reducedMotion = $state(false);
22
+
23
+ onMount(() => {
24
+ const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
25
+ reducedMotion = mq.matches;
26
+ const handler = (e: MediaQueryListEvent) => {
27
+ reducedMotion = e.matches;
28
+ };
29
+ mq.addEventListener("change", handler);
30
+ return () => mq.removeEventListener("change", handler);
31
+ });
32
+ </script>
33
+
34
+ <div class={cn("relative w-full", className)}>
35
+ <div
36
+ class="flex snap-x snap-mandatory gap-4 overflow-x-auto px-4 pb-4 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
37
+ >
38
+ {#each cards as card, i}
39
+ <AppleCard
40
+ {card}
41
+ index={i}
42
+ {expandedIndex}
43
+ {reducedMotion}
44
+ onExpand={(idx) => (expandedIndex = idx)}
45
+ onCollapse={() => (expandedIndex = -1)}
46
+ />
47
+ {/each}
48
+ </div>
49
+ </div>
@@ -0,0 +1,11 @@
1
+ import type { AppleCardData } from "./AppleCard.svelte";
2
+ export type { AppleCardData };
3
+ export interface AppleCardCarouselProps {
4
+ /** Cards to display in the carousel */
5
+ cards: AppleCardData[];
6
+ /** Additional CSS classes */
7
+ class?: string;
8
+ }
9
+ declare const AppleCardCarousel: import("svelte").Component<AppleCardCarouselProps, {}, "">;
10
+ type AppleCardCarousel = ReturnType<typeof AppleCardCarousel>;
11
+ export default AppleCardCarousel;
@@ -0,0 +1,85 @@
1
+ import { render, cleanup, fireEvent } from "@testing-library/svelte";
2
+ import { afterEach, beforeEach, describe, it, expect, vi } from "vitest";
3
+ import { flushSync } from "svelte";
4
+ import AppleCardCarousel from "./AppleCardCarousel.svelte";
5
+ const cards = [
6
+ { category: "Nature", title: "Mountains", src: "mountains.jpg", description: "High peaks." },
7
+ { category: "City", title: "Skyline", src: "skyline.jpg", description: "Urban lights." },
8
+ { category: "Ocean", title: "Waves", src: "waves.jpg", description: "Deep blue." },
9
+ ];
10
+ describe("AppleCardCarousel", () => {
11
+ beforeEach(() => {
12
+ vi.useFakeTimers();
13
+ });
14
+ afterEach(() => {
15
+ vi.useRealTimers();
16
+ cleanup();
17
+ });
18
+ it("renders all cards", () => {
19
+ const { getByText } = render(AppleCardCarousel, { props: { cards } });
20
+ expect(getByText("Mountains")).toBeTruthy();
21
+ expect(getByText("Skyline")).toBeTruthy();
22
+ expect(getByText("Waves")).toBeTruthy();
23
+ });
24
+ it("renders gracefully with no cards", () => {
25
+ const { container } = render(AppleCardCarousel, { props: { cards: [] } });
26
+ expect(container.querySelector("[role='button']")).toBeNull();
27
+ });
28
+ it("clicking a card shows the expanded dialog", () => {
29
+ const { getByLabelText } = render(AppleCardCarousel, { props: { cards } });
30
+ fireEvent.click(getByLabelText("Open Mountains"));
31
+ flushSync();
32
+ expect(getByLabelText("Mountains")).toBeTruthy();
33
+ });
34
+ it("expanded dialog has correct ARIA attributes", () => {
35
+ const { getByLabelText, getByRole } = render(AppleCardCarousel, { props: { cards } });
36
+ fireEvent.click(getByLabelText("Open Mountains"));
37
+ flushSync();
38
+ const dialog = getByRole("dialog");
39
+ expect(dialog).toBeTruthy();
40
+ expect(dialog.getAttribute("aria-modal")).toBe("true");
41
+ });
42
+ it("clicking the close button collapses the card", () => {
43
+ const { getByLabelText, queryByRole } = render(AppleCardCarousel, { props: { cards } });
44
+ fireEvent.click(getByLabelText("Open Mountains"));
45
+ flushSync();
46
+ fireEvent.click(getByLabelText("Close"));
47
+ flushSync(() => vi.advanceTimersByTime(400));
48
+ expect(queryByRole("dialog")).toBeNull();
49
+ });
50
+ it("pressing Escape collapses the card", () => {
51
+ const { getByLabelText, queryByRole } = render(AppleCardCarousel, { props: { cards } });
52
+ fireEvent.click(getByLabelText("Open Mountains"));
53
+ flushSync();
54
+ const dialog = getByLabelText("Mountains");
55
+ fireEvent.keyDown(dialog, { key: "Escape" });
56
+ flushSync(() => vi.advanceTimersByTime(400));
57
+ expect(queryByRole("dialog")).toBeNull();
58
+ });
59
+ it("only one card can be expanded at a time", () => {
60
+ const { getByLabelText, getAllByRole } = render(AppleCardCarousel, { props: { cards } });
61
+ fireEvent.click(getByLabelText("Open Mountains"));
62
+ flushSync();
63
+ expect(getAllByRole("dialog")).toHaveLength(1);
64
+ // Clicking another card while one is open should be a no-op
65
+ fireEvent.click(getByLabelText("Open Skyline"));
66
+ flushSync();
67
+ expect(getAllByRole("dialog")).toHaveLength(1);
68
+ });
69
+ it("clicking the backdrop collapses the card", () => {
70
+ const { getByLabelText, queryByRole } = render(AppleCardCarousel, { props: { cards } });
71
+ fireEvent.click(getByLabelText("Open Mountains"));
72
+ flushSync();
73
+ // The backdrop has aria-hidden="true"; target it via its class
74
+ const backdrop = document.querySelector(".fixed.z-40");
75
+ fireEvent.click(backdrop);
76
+ flushSync(() => vi.advanceTimersByTime(400));
77
+ expect(queryByRole("dialog")).toBeNull();
78
+ });
79
+ it("shows description text in the expanded view", () => {
80
+ const { getByLabelText, getByText } = render(AppleCardCarousel, { props: { cards } });
81
+ fireEvent.click(getByLabelText("Open Mountains"));
82
+ flushSync();
83
+ expect(getByText("High peaks.")).toBeTruthy();
84
+ });
85
+ });
@@ -0,0 +1,3 @@
1
+ export { default as AppleCardCarousel } from "./AppleCardCarousel.svelte";
2
+ export { default as AppleCard } from "./AppleCard.svelte";
3
+ export type { AppleCardCarouselProps, AppleCardData } from "./AppleCardCarousel.svelte";
@@ -0,0 +1,2 @@
1
+ export { default as AppleCardCarousel } from "./AppleCardCarousel.svelte";
2
+ export { default as AppleCard } from "./AppleCard.svelte";
@@ -0,0 +1,21 @@
1
+ <script lang="ts">
2
+ import { cn } from "../../utils";
3
+
4
+ interface Props {
5
+ class?: string;
6
+ children?: import("svelte").Snippet;
7
+ }
8
+
9
+ let { class: className = "", children }: Props = $props();
10
+ </script>
11
+
12
+ <div
13
+ class={cn(
14
+ "mx-auto grid max-w-7xl grid-cols-1 gap-4 md:auto-rows-[18rem] md:grid-cols-3",
15
+ className
16
+ )}
17
+ >
18
+ {#if children}
19
+ {@render children()}
20
+ {/if}
21
+ </div>
@@ -0,0 +1,7 @@
1
+ interface Props {
2
+ class?: string;
3
+ children?: import("svelte").Snippet;
4
+ }
5
+ declare const BentoGrid: import("svelte").Component<Props, {}, "">;
6
+ type BentoGrid = ReturnType<typeof BentoGrid>;
7
+ export default BentoGrid;