@mova-ui/react 0.1.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.
- package/LICENSE +21 -0
- package/README.md +46 -0
- package/bin/mova.mjs +84 -0
- package/dist/hooks/use-mouse-position.d.ts +8 -0
- package/dist/hooks/use-reduced-motion.d.ts +1 -0
- package/dist/hooks/use-scroll-progress.d.ts +2 -0
- package/dist/hooks/use-stagger.d.ts +7 -0
- package/dist/hooks/use-web-haptics.d.ts +4 -0
- package/dist/index.d.ts +164 -0
- package/dist/index.js +4032 -0
- package/dist/lib/presets.d.ts +32 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/styles.css +2 -0
- package/dist/ui/cursor/cursor-trail.d.ts +8 -0
- package/dist/ui/cursor/mouse-follow.d.ts +9 -0
- package/dist/ui/cursor/spotlight.d.ts +9 -0
- package/dist/ui/entrance/fade-down.d.ts +10 -0
- package/dist/ui/entrance/fade-in.d.ts +9 -0
- package/dist/ui/entrance/fade-up.d.ts +10 -0
- package/dist/ui/entrance/scale-in.d.ts +10 -0
- package/dist/ui/entrance/slide-left.d.ts +10 -0
- package/dist/ui/entrance/slide-right.d.ts +10 -0
- package/dist/ui/entrance/zoom-in.d.ts +11 -0
- package/dist/ui/hover/card-hover.d.ts +13 -0
- package/dist/ui/hover/glow-button.d.ts +10 -0
- package/dist/ui/hover/magnetic-button.d.ts +10 -0
- package/dist/ui/hover/tilt-card.d.ts +9 -0
- package/dist/ui/loading/accordion-loader.d.ts +2 -0
- package/dist/ui/loading/app-icon-load.d.ts +2 -0
- package/dist/ui/loading/apple-breathe.d.ts +2 -0
- package/dist/ui/loading/apple-equalizer.d.ts +2 -0
- package/dist/ui/loading/apple-icon-morph.d.ts +2 -0
- package/dist/ui/loading/apple-pulse-dots.d.ts +2 -0
- package/dist/ui/loading/apple-scale-pulse.d.ts +2 -0
- package/dist/ui/loading/apple-sound-wave.d.ts +2 -0
- package/dist/ui/loading/apple-text-reveal.d.ts +2 -0
- package/dist/ui/loading/apple-unlock.d.ts +4 -0
- package/dist/ui/loading/arc-tracer.d.ts +2 -0
- package/dist/ui/loading/bar-cascade.d.ts +2 -0
- package/dist/ui/loading/bar-sweep.d.ts +2 -0
- package/dist/ui/loading/bobbing-dots.d.ts +2 -0
- package/dist/ui/loading/bounce-dots.d.ts +2 -0
- package/dist/ui/loading/bouncing-bars.d.ts +2 -0
- package/dist/ui/loading/bouncing-dots.d.ts +2 -0
- package/dist/ui/loading/bouncing-lines.d.ts +2 -0
- package/dist/ui/loading/bouncing-square.d.ts +2 -0
- package/dist/ui/loading/breathe-ring.d.ts +2 -0
- package/dist/ui/loading/breathing-glow.d.ts +2 -0
- package/dist/ui/loading/breathing-square.d.ts +2 -0
- package/dist/ui/loading/circular-bars.d.ts +2 -0
- package/dist/ui/loading/classic-spinner.d.ts +2 -0
- package/dist/ui/loading/clock-spinner.d.ts +2 -0
- package/dist/ui/loading/comet-spinner.d.ts +2 -0
- package/dist/ui/loading/concentric-pulse.d.ts +2 -0
- package/dist/ui/loading/concentric-ring.d.ts +2 -0
- package/dist/ui/loading/concentric-squares.d.ts +2 -0
- package/dist/ui/loading/conveyor-loop.d.ts +2 -0
- package/dist/ui/loading/cross-spinner.d.ts +2 -0
- package/dist/ui/loading/cube-flip-spring.d.ts +2 -0
- package/dist/ui/loading/dash-ring.d.ts +2 -0
- package/dist/ui/loading/dashed-spiral.d.ts +2 -0
- package/dist/ui/loading/diamond-grid.d.ts +2 -0
- package/dist/ui/loading/diamond-rotate-spring.d.ts +2 -0
- package/dist/ui/loading/dot-spinner.d.ts +2 -0
- package/dist/ui/loading/dots-ring.d.ts +2 -0
- package/dist/ui/loading/double-ring.d.ts +2 -0
- package/dist/ui/loading/drop-dot.d.ts +2 -0
- package/dist/ui/loading/dual-arc.d.ts +2 -0
- package/dist/ui/loading/dynamic-island.d.ts +2 -0
- package/dist/ui/loading/elastic-bars.d.ts +2 -0
- package/dist/ui/loading/elastic-square.d.ts +2 -0
- package/dist/ui/loading/expanding-cross.d.ts +2 -0
- package/dist/ui/loading/face-id-scan.d.ts +2 -0
- package/dist/ui/loading/fade-arc.d.ts +2 -0
- package/dist/ui/loading/fade-dots.d.ts +2 -0
- package/dist/ui/loading/flip-square.d.ts +2 -0
- package/dist/ui/loading/floating-diamonds.d.ts +2 -0
- package/dist/ui/loading/fluid-bars.d.ts +2 -0
- package/dist/ui/loading/fluid-diamond.d.ts +2 -0
- package/dist/ui/loading/fluid-dot-orbit.d.ts +2 -0
- package/dist/ui/loading/fluid-skeleton.d.ts +2 -0
- package/dist/ui/loading/gears.d.ts +2 -0
- package/dist/ui/loading/glassmorphic-card.d.ts +2 -0
- package/dist/ui/loading/gradient-arc.d.ts +2 -0
- package/dist/ui/loading/grid-dots.d.ts +2 -0
- package/dist/ui/loading/haptic-ring.d.ts +2 -0
- package/dist/ui/loading/heartbeat.d.ts +2 -0
- package/dist/ui/loading/hexagon-spinner.d.ts +2 -0
- package/dist/ui/loading/hourglass.d.ts +2 -0
- package/dist/ui/loading/infinity-path.d.ts +2 -0
- package/dist/ui/loading/intersecting-rings.d.ts +2 -0
- package/dist/ui/loading/ios-spinner.d.ts +2 -0
- package/dist/ui/loading/line-spinner.d.ts +2 -0
- package/dist/ui/loading/liquid-dots.d.ts +2 -0
- package/dist/ui/loading/mac-terminal.d.ts +2 -0
- package/dist/ui/loading/magnetic-dots.d.ts +2 -0
- package/dist/ui/loading/minimal-triangle.d.ts +2 -0
- package/dist/ui/loading/morph-dot-ring.d.ts +2 -0
- package/dist/ui/loading/morph-loader.d.ts +8 -0
- package/dist/ui/loading/morphing-bars.d.ts +2 -0
- package/dist/ui/loading/morphing-infinity.d.ts +2 -0
- package/dist/ui/loading/morphing-ring.d.ts +2 -0
- package/dist/ui/loading/morphing-shape.d.ts +2 -0
- package/dist/ui/loading/newtons-cradle.d.ts +2 -0
- package/dist/ui/loading/offset-rings.d.ts +2 -0
- package/dist/ui/loading/orbiting-circles.d.ts +2 -0
- package/dist/ui/loading/orbiting-dot.d.ts +2 -0
- package/dist/ui/loading/origami-shape.d.ts +2 -0
- package/dist/ui/loading/pendulum.d.ts +2 -0
- package/dist/ui/loading/pulsating-dots.d.ts +2 -0
- package/dist/ui/loading/pulse-dot.d.ts +2 -0
- package/dist/ui/loading/pulse-dots.d.ts +2 -0
- package/dist/ui/loading/pulse-square.d.ts +2 -0
- package/dist/ui/loading/pulse.d.ts +8 -0
- package/dist/ui/loading/pumping-heart.d.ts +2 -0
- package/dist/ui/loading/radar-sweep.d.ts +4 -0
- package/dist/ui/loading/ring-sweep.d.ts +2 -0
- package/dist/ui/loading/ripple-effect.d.ts +2 -0
- package/dist/ui/loading/rotating-cross.d.ts +2 -0
- package/dist/ui/loading/rotating-triangle.d.ts +2 -0
- package/dist/ui/loading/shape-shift-grid.d.ts +2 -0
- package/dist/ui/loading/shimmer-line.d.ts +2 -0
- package/dist/ui/loading/siri-wave.d.ts +2 -0
- package/dist/ui/loading/skeleton-loader.d.ts +2 -0
- package/dist/ui/loading/skeleton.d.ts +7 -0
- package/dist/ui/loading/sliding-bars.d.ts +2 -0
- package/dist/ui/loading/smooth-dot-shift.d.ts +2 -0
- package/dist/ui/loading/smooth-ring.d.ts +2 -0
- package/dist/ui/loading/smooth-rounded-square.d.ts +2 -0
- package/dist/ui/loading/spinning-squares.d.ts +2 -0
- package/dist/ui/loading/spiral-spinner.d.ts +2 -0
- package/dist/ui/loading/spring-bars.d.ts +2 -0
- package/dist/ui/loading/spring-dot-matrix.d.ts +2 -0
- package/dist/ui/loading/spring-hexagon.d.ts +2 -0
- package/dist/ui/loading/spring-ring-expand.d.ts +2 -0
- package/dist/ui/loading/spring-text-pop.d.ts +2 -0
- package/dist/ui/loading/square-accordion.d.ts +2 -0
- package/dist/ui/loading/square-grid.d.ts +2 -0
- package/dist/ui/loading/square-snake.d.ts +2 -0
- package/dist/ui/loading/square-spinner.d.ts +2 -0
- package/dist/ui/loading/stacked-bar-pulse.d.ts +2 -0
- package/dist/ui/loading/swapping-dots.d.ts +2 -0
- package/dist/ui/loading/swirling-spinner.d.ts +2 -0
- package/dist/ui/loading/symmetric-wave.d.ts +2 -0
- package/dist/ui/loading/terminal-loader.d.ts +2 -0
- package/dist/ui/loading/text-blink.d.ts +2 -0
- package/dist/ui/loading/text-dots.d.ts +2 -0
- package/dist/ui/loading/text-morph.d.ts +2 -0
- package/dist/ui/loading/text-shimmer-wave.d.ts +2 -0
- package/dist/ui/loading/text-shimmer.d.ts +2 -0
- package/dist/ui/loading/trailing-dots.d.ts +2 -0
- package/dist/ui/loading/triple-dot-spinner.d.ts +2 -0
- package/dist/ui/loading/twin-orbit.d.ts +2 -0
- package/dist/ui/loading/typing-indicator.d.ts +2 -0
- package/dist/ui/loading/typing.d.ts +2 -0
- package/dist/ui/loading/wandering-cube.d.ts +2 -0
- package/dist/ui/loading/watch-spinner.d.ts +2 -0
- package/dist/ui/loading/wave-dots.d.ts +2 -0
- package/dist/ui/loading/wave-physics-loader.d.ts +3 -0
- package/dist/ui/loading/waveform-loader.d.ts +2 -0
- package/dist/ui/loading/zig-zag-pulse.d.ts +2 -0
- package/dist/ui/scroll/progress-indicator.d.ts +8 -0
- package/dist/ui/scroll/scroll-reveal.d.ts +11 -0
- package/dist/ui/scroll/sticky-reveal.d.ts +11 -0
- package/dist/ui/text/blur-text.d.ts +10 -0
- package/dist/ui/text/character-stagger.d.ts +10 -0
- package/dist/ui/text/text-reveal.d.ts +9 -0
- package/dist/ui/text/word-reveal.d.ts +9 -0
- package/dist/ui/toggles/classic-toggle.d.ts +2 -0
- package/dist/ui/transitions/page-transition.d.ts +9 -0
- package/package.json +27 -0
- package/registry/accordion-loader.json +8 -0
- package/registry/app-icon-load.json +8 -0
- package/registry/apple-breathe.json +8 -0
- package/registry/apple-equalizer.json +8 -0
- package/registry/apple-icon-morph.json +8 -0
- package/registry/apple-pulse-dots.json +8 -0
- package/registry/apple-scale-pulse.json +8 -0
- package/registry/apple-sound-wave.json +8 -0
- package/registry/apple-text-reveal.json +8 -0
- package/registry/apple-unlock.json +8 -0
- package/registry/arc-tracer.json +8 -0
- package/registry/bar-cascade.json +8 -0
- package/registry/bar-sweep.json +8 -0
- package/registry/blur-text.json +8 -0
- package/registry/bobbing-dots.json +8 -0
- package/registry/bounce-dots.json +8 -0
- package/registry/bouncing-bars.json +8 -0
- package/registry/bouncing-dots.json +8 -0
- package/registry/bouncing-lines.json +8 -0
- package/registry/bouncing-square.json +8 -0
- package/registry/breathe-ring.json +8 -0
- package/registry/breathing-glow.json +8 -0
- package/registry/breathing-square.json +8 -0
- package/registry/card-hover.json +8 -0
- package/registry/character-stagger.json +8 -0
- package/registry/circular-bars.json +8 -0
- package/registry/classic-spinner.json +8 -0
- package/registry/classic-toggle.json +8 -0
- package/registry/clock-spinner.json +8 -0
- package/registry/comet-spinner.json +8 -0
- package/registry/concentric-pulse.json +8 -0
- package/registry/concentric-ring.json +8 -0
- package/registry/concentric-squares.json +8 -0
- package/registry/conveyor-loop.json +8 -0
- package/registry/cross-spinner.json +8 -0
- package/registry/cube-flip-spring.json +8 -0
- package/registry/cursor-trail.json +8 -0
- package/registry/dash-ring.json +8 -0
- package/registry/dashed-spiral.json +8 -0
- package/registry/diamond-grid.json +8 -0
- package/registry/diamond-rotate-spring.json +8 -0
- package/registry/dot-spinner.json +8 -0
- package/registry/dots-ring.json +8 -0
- package/registry/double-ring.json +8 -0
- package/registry/drop-dot.json +8 -0
- package/registry/dual-arc.json +8 -0
- package/registry/dynamic-island.json +8 -0
- package/registry/elastic-bars.json +8 -0
- package/registry/elastic-square.json +8 -0
- package/registry/expanding-cross.json +8 -0
- package/registry/face-id-scan.json +8 -0
- package/registry/fade-arc.json +6 -0
- package/registry/fade-dots.json +8 -0
- package/registry/fade-down.json +8 -0
- package/registry/fade-in.json +8 -0
- package/registry/fade-up.json +8 -0
- package/registry/flip-square.json +8 -0
- package/registry/floating-diamonds.json +8 -0
- package/registry/fluid-bars.json +8 -0
- package/registry/fluid-diamond.json +8 -0
- package/registry/fluid-dot-orbit.json +8 -0
- package/registry/fluid-skeleton.json +8 -0
- package/registry/gears.json +8 -0
- package/registry/glassmorphic-card.json +8 -0
- package/registry/glow-button.json +8 -0
- package/registry/gradient-arc.json +8 -0
- package/registry/grid-dots.json +8 -0
- package/registry/haptic-ring.json +8 -0
- package/registry/heartbeat.json +8 -0
- package/registry/hexagon-spinner.json +8 -0
- package/registry/hourglass.json +8 -0
- package/registry/infinity-path.json +8 -0
- package/registry/intersecting-rings.json +8 -0
- package/registry/ios-spinner.json +8 -0
- package/registry/line-spinner.json +8 -0
- package/registry/liquid-dots.json +8 -0
- package/registry/mac-terminal.json +8 -0
- package/registry/magnetic-button.json +8 -0
- package/registry/magnetic-dots.json +8 -0
- package/registry/minimal-triangle.json +8 -0
- package/registry/morph-dot-ring.json +8 -0
- package/registry/morph-loader.json +8 -0
- package/registry/morphing-bars.json +8 -0
- package/registry/morphing-infinity.json +8 -0
- package/registry/morphing-ring.json +8 -0
- package/registry/morphing-shape.json +8 -0
- package/registry/mouse-follow.json +8 -0
- package/registry/newtons-cradle.json +8 -0
- package/registry/offset-rings.json +8 -0
- package/registry/orbiting-circles.json +8 -0
- package/registry/orbiting-dot.json +8 -0
- package/registry/origami-shape.json +8 -0
- package/registry/page-transition.json +8 -0
- package/registry/pendulum.json +8 -0
- package/registry/presets.json +6 -0
- package/registry/progress-indicator.json +8 -0
- package/registry/pulsating-dots.json +8 -0
- package/registry/pulse-dot.json +8 -0
- package/registry/pulse-dots.json +8 -0
- package/registry/pulse-square.json +8 -0
- package/registry/pulse.json +8 -0
- package/registry/pumping-heart.json +8 -0
- package/registry/radar-sweep.json +8 -0
- package/registry/ring-sweep.json +8 -0
- package/registry/ripple-effect.json +8 -0
- package/registry/rotating-cross.json +8 -0
- package/registry/rotating-triangle.json +8 -0
- package/registry/scale-in.json +8 -0
- package/registry/scroll-reveal.json +8 -0
- package/registry/shape-shift-grid.json +8 -0
- package/registry/shimmer-line.json +8 -0
- package/registry/siri-wave.json +8 -0
- package/registry/skeleton-loader.json +8 -0
- package/registry/skeleton.json +8 -0
- package/registry/slide-left.json +8 -0
- package/registry/slide-right.json +8 -0
- package/registry/sliding-bars.json +8 -0
- package/registry/smooth-dot-shift.json +8 -0
- package/registry/smooth-ring.json +6 -0
- package/registry/smooth-rounded-square.json +8 -0
- package/registry/spinning-squares.json +8 -0
- package/registry/spiral-spinner.json +8 -0
- package/registry/spotlight.json +8 -0
- package/registry/spring-bars.json +8 -0
- package/registry/spring-dot-matrix.json +8 -0
- package/registry/spring-hexagon.json +8 -0
- package/registry/spring-ring-expand.json +8 -0
- package/registry/spring-text-pop.json +8 -0
- package/registry/square-accordion.json +8 -0
- package/registry/square-grid.json +8 -0
- package/registry/square-snake.json +8 -0
- package/registry/square-spinner.json +8 -0
- package/registry/stacked-bar-pulse.json +8 -0
- package/registry/sticky-reveal.json +8 -0
- package/registry/swapping-dots.json +8 -0
- package/registry/swirling-spinner.json +8 -0
- package/registry/symmetric-wave.json +8 -0
- package/registry/terminal-loader.json +8 -0
- package/registry/text-blink.json +8 -0
- package/registry/text-dots.json +8 -0
- package/registry/text-morph.json +8 -0
- package/registry/text-reveal.json +8 -0
- package/registry/text-shimmer-wave.json +8 -0
- package/registry/text-shimmer.json +8 -0
- package/registry/tilt-card.json +8 -0
- package/registry/trailing-dots.json +8 -0
- package/registry/triple-dot-spinner.json +8 -0
- package/registry/twin-orbit.json +8 -0
- package/registry/typing-indicator.json +8 -0
- package/registry/typing.json +8 -0
- package/registry/use-mouse-position.json +6 -0
- package/registry/use-reduced-motion.json +6 -0
- package/registry/use-scroll-progress.json +6 -0
- package/registry/use-stagger.json +6 -0
- package/registry/use-web-haptics.json +6 -0
- package/registry/utils.json +9 -0
- package/registry/wandering-cube.json +8 -0
- package/registry/watch-spinner.json +8 -0
- package/registry/wave-dots.json +8 -0
- package/registry/wave-physics-loader.json +8 -0
- package/registry/waveform-loader.json +8 -0
- package/registry/word-reveal.json +8 -0
- package/registry/zig-zag-pulse.json +8 -0
- package/registry/zoom-in.json +8 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "spring-ring-expand",
|
|
3
|
+
"file": "spring-ring-expand.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const SpringRingExpand = () => {\n return (\n <div className=\"relative w-12 h-12 flex items-center justify-center\">\n {[0, 1].map((i) => (\n <motion.div\n key={i}\n className=\"absolute w-10 h-10 border-2 border-zinc-800 dark:border-white rounded-full\"\n initial={{ scale: 0.1, opacity: 1 }}\n animate={{ scale: 1.25, opacity: 0 }}\n transition={{\n duration: 1.6,\n repeat: Infinity,\n ease: \"easeOut\",\n delay: i * 0.8,\n }}\n />\n ))}\n </div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "spring-text-pop",
|
|
3
|
+
"file": "spring-text-pop.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const SpringTextPop = () => {\n const text = \"Loading...\";\n return (\n <div className=\"flex font-medium text-sm tracking-widest text-zinc-800 dark:text-white\">\n {text.split(\"\").map((char, i) => (\n <motion.span\n key={i}\n className=\"origin-bottom inline-block\"\n animate={{ y: [0, -6, 0] }}\n transition={{\n duration: 1.2,\n repeat: Infinity,\n ease: \"easeInOut\",\n delay: i * 0.08,\n }}\n >\n {char === \" \" ? \"\\u00A0\" : char}\n </motion.span>\n ))}\n </div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "square-accordion",
|
|
3
|
+
"file": "square-accordion.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const SquareAccordion = () => {\n return (\n <div className=\"flex space-x-1 w-12 h-12 justify-center items-center\">\n {[0, 1, 2].map((i) => (\n <motion.div\n key={i}\n className=\"w-3 bg-zinc-800 dark:bg-white rounded-sm\"\n animate={{ height: [12, 32, 12] }}\n transition={{ duration: 1.5, repeat: Infinity, delay: i * 0.2, ease: \"easeInOut\" }}\n />\n ))}\n </div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "square-grid",
|
|
3
|
+
"file": "square-grid.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const SquareGrid = () => {\n return (\n <div className=\"grid grid-cols-2 gap-1.5\">\n {[0, 1, 2, 3].map((i) => (\n <motion.div\n key={i}\n className=\"w-4 h-4 bg-zinc-800 dark:bg-white rounded-sm\"\n animate={{ scale: [1, 0.5, 1], opacity: [1, 0.3, 1] }}\n transition={{ duration: 1.5, repeat: Infinity, delay: i * 0.2, ease: \"easeInOut\" }}\n />\n ))}\n </div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "square-snake",
|
|
3
|
+
"file": "square-snake.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const SquareSnake = () => {\n return (\n <div className=\"grid grid-cols-3 gap-1 w-10 h-10\">\n {[\n [0,0], [1,0], [2,0],\n [0,1], [1,1], [2,1],\n [0,2], [1,2], [2,2]\n ].map(([x,y], i) => (\n <motion.div\n key={i}\n className=\"bg-zinc-800 dark:bg-white rounded-sm w-full h-full\"\n animate={{ opacity: [0.1, 1, 0.1] }}\n transition={{ duration: 1.5, repeat: Infinity, delay: (x + y) * 0.15, ease: \"easeInOut\" }}\n />\n ))}\n </div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "square-spinner",
|
|
3
|
+
"file": "square-spinner.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const SquareSpinner = () => {\n return (\n <motion.div\n className=\"w-8 h-8 border-2 border-zinc-800 dark:border-zinc-700 flex items-center justify-center\"\n animate={{ rotate: 90 }}\n transition={{ duration: 0.6, repeat: Infinity, ease: \"easeInOut\" }}\n >\n <div className=\"w-2 h-2 bg-zinc-800 dark:bg-white\" />\n </motion.div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "stacked-bar-pulse",
|
|
3
|
+
"file": "stacked-bar-pulse.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const StackedBarPulse = () => (\n <div className=\"flex flex-col space-y-1 w-8 items-center\">\n {[0,1,2].map(i => (\n <motion.div\n key={i}\n className=\"w-full h-1 bg-zinc-800 dark:bg-white rounded-full\"\n animate={{ opacity: [0.2, 1, 0.2], width: ['50%', '100%', '50%'] }}\n transition={{ duration: 1.5, repeat: Infinity, delay: i * 0.2, ease: \"easeInOut\" }}\n />\n ))}\n </div>\n);\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "sticky-reveal",
|
|
3
|
+
"file": "sticky-reveal.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React, { useRef, useState } from 'react';\nimport { motion, useMotionValueEvent, useScroll } from 'framer-motion';\n\ninterface StickyRevealProps {\n content: {\n title: string;\n description: string;\n content?: React.ReactNode;\n }[];\n className?: string;\n}\n\nexport function StickyReveal({\n content,\n className = '',\n}: StickyRevealProps) {\n const [activeCard, setActiveCard] = useState(0);\n const ref = useRef<HTMLDivElement>(null);\n const { scrollYProgress } = useScroll({\n target: ref,\n offset: ['start start', 'end end'],\n });\n \n const cardLength = content.length;\n\n useMotionValueEvent(scrollYProgress, \"change\", (latest) => {\n const cardsBreakpoints = content.map((_, index) => index / cardLength);\n const closestIndex = cardsBreakpoints.reduce((acc, val, index) => {\n if (latest >= val) {\n return index;\n }\n return acc;\n }, 0);\n setActiveCard(closestIndex);\n });\n\n return (\n <div\n ref={ref}\n className={`relative flex justify-between gap-10 max-w-5xl mx-auto py-10 px-4 ${className}`}\n >\n <div className=\"w-1/2 flex flex-col gap-32 py-10\">\n {content.map((item, index) => (\n <div key={index} className=\"min-h-[50vh] flex flex-col justify-center\">\n <motion.h2\n animate={{\n opacity: activeCard === index ? 1 : 0.3,\n }}\n className=\"text-2xl font-bold mb-4\"\n >\n {item.title}\n </motion.h2>\n <motion.p\n animate={{\n opacity: activeCard === index ? 1 : 0.3,\n }}\n className=\"text-neutral-500 dark:text-neutral-450 leading-relaxed\"\n >\n {item.description}\n </motion.p>\n </div>\n ))}\n </div>\n \n <div className=\"sticky top-20 h-[60vh] w-1/2 rounded-2xl bg-neutral-100 dark:bg-neutral-900 border border-neutral-200/10 overflow-hidden flex items-center justify-center\">\n {content.map((item, index) => (\n <motion.div\n key={index}\n initial={{ opacity: 0, scale: 0.9 }}\n animate={{\n opacity: activeCard === index ? 1 : 0,\n scale: activeCard === index ? 1 : 0.9,\n }}\n transition={{ duration: 0.4 }}\n className=\"absolute inset-0 p-6 flex items-center justify-center\"\n >\n {item.content || (\n <div className=\"text-lg font-semibold text-neutral-400\">\n Card {index + 1} Visual\n </div>\n )}\n </motion.div>\n ))}\n </div>\n </div>\n );\n}\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "swapping-dots",
|
|
3
|
+
"file": "swapping-dots.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const SwappingDots = () => {\n return (\n <div className=\"relative w-12 h-4 flex items-center\">\n <motion.div\n className=\"absolute left-0 w-4 h-4 bg-zinc-800 dark:bg-white rounded-full\"\n animate={{ x: [0, 32, 0] }}\n transition={{ duration: 1.5, repeat: Infinity, ease: \"easeInOut\" }}\n />\n <motion.div\n className=\"absolute right-0 w-4 h-4 bg-zinc-400 dark:bg-zinc-200 rounded-full\"\n animate={{ x: [0, -32, 0] }}\n transition={{ duration: 1.5, repeat: Infinity, ease: \"easeInOut\" }}\n />\n </div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "swirling-spinner",
|
|
3
|
+
"file": "swirling-spinner.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const SwirlingSpinner = () => {\n return (\n <div className=\"relative w-10 h-10 flex items-center justify-center\">\n {/* Outer ring */}\n <motion.div\n className=\"absolute inset-0 border-[2.5px] border-t-zinc-800 dark:border-t-white border-r-zinc-800/30 dark:border-r-white/30 border-b-zinc-800/10 dark:border-b-white/10 border-l-transparent rounded-full\"\n animate={{ rotate: 360 }}\n transition={{ duration: 1.3, repeat: Infinity, ease: \"linear\" }}\n />\n {/* Inner ring spinning backwards */}\n <motion.div\n className=\"absolute w-6 h-6 border-[2.5px] border-b-zinc-800 dark:border-b-white border-t-zinc-800/30 dark:border-t-white/30 border-r-zinc-800/10 dark:border-r-white/10 border-l-transparent rounded-full\"\n animate={{ rotate: -360 }}\n transition={{ duration: 0.9, repeat: Infinity, ease: \"linear\" }}\n />\n </div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "symmetric-wave",
|
|
3
|
+
"file": "symmetric-wave.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const SymmetricWave = () => {\n return (\n <div className=\"flex space-x-1.5 h-10 items-center\">\n {[0, 1, 2, 3, 4, 3, 2, 1, 0].map((val, i) => (\n <motion.div\n key={i}\n className=\"w-1.5 bg-zinc-800 dark:bg-white rounded-full\"\n animate={{ height: [8, 24, 8] }}\n transition={{ duration: 1.2, repeat: Infinity, delay: val * 0.1, ease: \"easeInOut\" }}\n />\n ))}\n </div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "terminal-loader",
|
|
3
|
+
"file": "terminal-loader.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const TerminalLoader = () => {\n return (\n <div className=\"bg-zinc-900 dark:bg-white text-zinc-100 font-mono text-[10px] p-3 rounded-md w-full h-16 flex flex-col justify-end overflow-hidden shadow-sm\">\n <div className=\"flex text-zinc-500 dark:text-zinc-300 mb-1 leading-none\">\n <span>$</span>\n <span className=\"ml-2\">loading...</span>\n </div>\n <div className=\"flex items-center leading-none\">\n <span className=\"text-emerald-400\">></span>\n <motion.span\n className=\"ml-2 w-1.5 h-2.5 bg-zinc-100 dark:bg-zinc-800 block\"\n animate={{ opacity: [1, 0, 1] }}\n transition={{ duration: 0.8, repeat: Infinity, ease: \"linear\" }}\n />\n </div>\n </div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "text-blink",
|
|
3
|
+
"file": "text-blink.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const TextBlink = () => {\n return (\n <motion.div\n className=\"text-zinc-900 dark:text-white font-medium text-lg\"\n animate={{ opacity: [1, 0.2, 1] }}\n transition={{ duration: 1.5, repeat: Infinity, ease: \"easeInOut\" }}\n >\n Thinking\n </motion.div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "text-dots",
|
|
3
|
+
"file": "text-dots.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const TextDots = () => {\n return (\n <div className=\"font-medium text-lg text-zinc-900 dark:text-white flex w-24\">\n <span>Thinking</span>\n <span className=\"flex w-6 pl-0.5\">\n <motion.span animate={{ opacity: [0, 1, 1, 0] }} transition={{ duration: 2, repeat: Infinity, times: [0, 0.2, 0.8, 1] }}>.</motion.span>\n <motion.span animate={{ opacity: [0, 0, 1, 0] }} transition={{ duration: 2, repeat: Infinity, times: [0, 0.4, 0.8, 1] }}>.</motion.span>\n <motion.span animate={{ opacity: [0, 0, 1, 0] }} transition={{ duration: 2, repeat: Infinity, times: [0, 0.6, 0.8, 1] }}>.</motion.span>\n </span>\n </div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "text-morph",
|
|
3
|
+
"file": "text-morph.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const TextMorph = () => (\n <div className=\"relative h-6 w-24 flex items-center justify-center font-medium text-sm text-zinc-900 dark:text-white overflow-hidden\">\n <motion.div\n className=\"absolute\"\n animate={{ opacity: [1, 0, 0, 1], y: [0, -16, 16, 0] }}\n transition={{ duration: 3, repeat: Infinity, ease: \"easeInOut\" }}\n >\n Loading\n </motion.div>\n <motion.div\n className=\"absolute\"\n animate={{ opacity: [0, 1, 1, 0], y: [16, 0, 0, -16] }}\n transition={{ duration: 3, repeat: Infinity, ease: \"easeInOut\" }}\n >\n Wait\n </motion.div>\n </div>\n);\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "text-reveal",
|
|
3
|
+
"file": "text-reveal.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion, type Variants } from 'framer-motion';\n\ninterface TextRevealProps {\n text: string;\n duration?: number;\n staggerDelay?: number;\n className?: string;\n}\n\nexport function TextReveal({\n text,\n duration = 0.8,\n staggerDelay = 0.15,\n className = '',\n}: TextRevealProps) {\n const lines = text.split('\\n');\n\n const containerVariants: Variants = {\n hidden: { opacity: 0 },\n visible: {\n opacity: 1,\n transition: {\n staggerChildren: staggerDelay,\n },\n },\n };\n\n const itemVariants: Variants = {\n hidden: { y: '100%' },\n visible: {\n y: 0,\n transition: {\n duration,\n ease: [0.16, 1, 0.3, 1], // easeOutExpo\n },\n },\n };\n\n return (\n <motion.div\n variants={containerVariants}\n initial=\"hidden\"\n whileInView=\"visible\"\n viewport={{ once: true, margin: '-20%' }}\n className={`flex flex-col ${className}`}\n >\n {lines.map((line, index) => (\n <div key={index} className=\"overflow-hidden py-1\">\n <motion.span variants={itemVariants} className=\"block\">\n {line}\n </motion.span>\n </div>\n ))}\n </motion.div>\n );\n}\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "text-shimmer-wave",
|
|
3
|
+
"file": "text-shimmer-wave.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const TextShimmerWave = () => {\n const text = \"Thinking\";\n return (\n <div className=\"flex font-medium text-lg\">\n {text.split(\"\").map((char, i) => (\n <motion.span\n key={i}\n className=\"text-zinc-900 dark:text-white\"\n animate={{ opacity: [0.3, 1, 0.3], y: [0, -2, 0] }}\n transition={{ duration: 1.5, repeat: Infinity, delay: i * 0.1, ease: \"easeInOut\" }}\n >\n {char}\n </motion.span>\n ))}\n </div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "text-shimmer",
|
|
3
|
+
"file": "text-shimmer.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const TextShimmer = () => {\n return (\n <div className=\"relative text-zinc-200 font-medium text-lg\">\n Thinking\n <motion.div\n className=\"absolute inset-0 text-zinc-900 dark:text-white\"\n style={{ maskImage: \"linear-gradient(90deg, transparent 0%, black 50%, transparent 100%)\", maskSize: \"200% 100%\" }}\n animate={{ maskPosition: [\"100% 0%\", \"-100% 0%\"] }}\n transition={{ duration: 1.5, repeat: Infinity, ease: \"linear\" }}\n >\n Thinking\n </motion.div>\n </div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "tilt-card",
|
|
3
|
+
"file": "tilt-card.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React, { useRef, useState } from 'react';\nimport { motion, useMotionValue, useSpring, useTransform } from 'framer-motion';\n\ninterface TiltCardProps {\n children: React.ReactNode;\n maxTilt?: number;\n className?: string;\n cardClassName?: string;\n}\n\nexport function TiltCard({\n children,\n maxTilt = 15,\n className = '',\n cardClassName = '',\n}: TiltCardProps) {\n const cardRef = useRef<HTMLDivElement>(null);\n const [isHovered, setIsHovered] = useState(false);\n\n // Motion values for x/y mouse offset relative to card center (-0.5 to 0.5)\n const x = useMotionValue(0);\n const y = useMotionValue(0);\n\n // Springs for smooth movement\n const springConfig = { damping: 20, stiffness: 200, mass: 0.5 };\n const rotateX = useSpring(useTransform(y, [-0.5, 0.5], [maxTilt, -maxTilt]), springConfig);\n const rotateY = useSpring(useTransform(x, [-0.5, 0.5], [-maxTilt, maxTilt]), springConfig);\n\n const handleMouseMove = (event: React.MouseEvent<HTMLDivElement>) => {\n if (!cardRef.current) return;\n const rect = cardRef.current.getBoundingClientRect();\n \n // Calculate normalized position relative to center (-0.5 to 0.5)\n const relativeX = (event.clientX - rect.left) / rect.width - 0.5;\n const relativeY = (event.clientY - rect.top) / rect.height - 0.5;\n\n x.set(relativeX);\n y.set(relativeY);\n };\n\n const handleMouseLeave = () => {\n setIsHovered(false);\n x.set(0);\n y.set(0);\n };\n\n return (\n <div\n ref={cardRef}\n onMouseMove={handleMouseMove}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={handleMouseLeave}\n className={`relative w-full aspect-[4/3] max-w-[320px] cursor-pointer ${className}`}\n style={{ perspective: '800px' }}\n >\n <motion.div\n style={{\n rotateX,\n rotateY,\n transformStyle: 'preserve-3d',\n }}\n className={`w-full h-full rounded-2xl bg-gradient-to-br from-neutral-100 to-neutral-250 dark:from-neutral-850 dark:to-neutral-900 border border-neutral-200/20 shadow-lg flex items-center justify-center p-6 select-none ${cardClassName}`}\n >\n <div style={{ transform: 'translateZ(40px)', transformStyle: 'preserve-3d' }} className=\"w-full h-full flex flex-col justify-center items-center\">\n {children}\n </div>\n </motion.div>\n </div>\n );\n}\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "trailing-dots",
|
|
3
|
+
"file": "trailing-dots.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const TrailingDots = () => (\n <div className=\"relative w-10 h-10\">\n {[0,1,2,3,4].map((i) => (\n <motion.div\n key={i}\n className=\"absolute inset-0\"\n animate={{ rotate: 360 }}\n transition={{ duration: 1.5, repeat: Infinity, delay: i * 0.1, ease: \"easeInOut\" }}\n >\n <div className={`w-2 h-2 rounded-full absolute top-0 left-1/2 -ml-1 ${i === 0 ? 'bg-zinc-800 dark:bg-white' : 'bg-zinc-400 dark:bg-zinc-200'}`} style={{ opacity: 1 - i * 0.2 }} />\n </motion.div>\n ))}\n </div>\n);\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "triple-dot-spinner",
|
|
3
|
+
"file": "triple-dot-spinner.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const TripleDotSpinner = () => {\n return (\n <motion.div \n className=\"relative w-10 h-10\"\n animate={{ rotate: 360 }}\n transition={{ duration: 2, repeat: Infinity, ease: \"linear\" }}\n >\n {[0, 1, 2].map((i) => (\n <div\n key={i}\n className=\"absolute top-0 left-1/2 w-2 h-2 bg-zinc-800 dark:bg-white rounded-full -ml-1 origin-[4px_20px]\"\n style={{ transform: `rotate(${i * 120}deg)` }}\n />\n ))}\n </motion.div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "twin-orbit",
|
|
3
|
+
"file": "twin-orbit.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const TwinOrbit = () => {\n return (\n <div className=\"relative w-12 h-12\">\n <motion.div\n className=\"absolute inset-0 border-2 border-zinc-800 dark:border-zinc-700 rounded-full border-b-transparent border-r-transparent\"\n animate={{ rotate: 360 }}\n transition={{ duration: 1.5, repeat: Infinity, ease: \"linear\" }}\n />\n <motion.div\n className=\"absolute inset-2 border-2 border-zinc-400 rounded-full border-t-transparent border-l-transparent\"\n animate={{ rotate: -360 }}\n transition={{ duration: 1.5, repeat: Infinity, ease: \"linear\" }}\n />\n </div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "typing-indicator",
|
|
3
|
+
"file": "typing-indicator.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const TypingIndicator = () => {\n return (\n <div className=\"flex items-center justify-center px-4 py-2 bg-zinc-100 dark:bg-zinc-800 rounded-full space-x-1\">\n {[0, 1, 2].map((i) => (\n <motion.div\n key={i}\n className=\"w-1.5 h-1.5 bg-zinc-500 dark:bg-zinc-350 rounded-full\"\n animate={{ y: [0, -4, 0] }}\n transition={{ duration: 0.6, repeat: Infinity, delay: i * 0.15, ease: \"easeInOut\" }}\n />\n ))}\n </div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "typing",
|
|
3
|
+
"file": "typing.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const Typing = () => {\n return (\n <div className=\"flex items-center text-zinc-900 dark:text-white font-medium text-lg w-20\">\n Loading\n <motion.span\n className=\"w-1.5 h-4 bg-zinc-900 dark:bg-white ml-1 inline-block\"\n animate={{ opacity: [1, 0, 1] }}\n transition={{ duration: 0.8, repeat: Infinity, ease: \"linear\" }}\n />\n </div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "use-mouse-position",
|
|
3
|
+
"file": "use-mouse-position.ts",
|
|
4
|
+
"dependencies": [],
|
|
5
|
+
"content": "\"use client\";\nimport { useEffect, useState, RefObject } from 'react';\n\nexport interface MousePosition {\n x: number;\n y: number;\n elementX: number;\n elementY: number;\n}\n\nexport function useMousePosition(ref?: RefObject<HTMLElement | null>) {\n const [position, setPosition] = useState<MousePosition>({\n x: 0,\n y: 0,\n elementX: 0,\n elementY: 0,\n });\n\n useEffect(() => {\n const handleMouseMove = (event: MouseEvent) => {\n let elementX = 0;\n let elementY = 0;\n\n if (ref && ref.current) {\n const rect = ref.current.getBoundingClientRect();\n elementX = event.clientX - rect.left;\n elementY = event.clientY - rect.top;\n }\n\n setPosition({\n x: event.clientX,\n y: event.clientY,\n elementX,\n elementY,\n });\n };\n\n window.addEventListener('mousemove', handleMouseMove, { passive: true });\n return () => {\n window.removeEventListener('mousemove', handleMouseMove);\n };\n }, [ref]);\n\n return position;\n}\n"
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "use-reduced-motion",
|
|
3
|
+
"file": "use-reduced-motion.ts",
|
|
4
|
+
"dependencies": [],
|
|
5
|
+
"content": "\"use client\";\nimport { useState, useEffect } from 'react';\n\nexport function useReducedMotion() {\n const [shouldReduceMotion, setShouldReduceMotion] = useState(false);\n\n useEffect(() => {\n const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');\n setShouldReduceMotion(mediaQuery.matches);\n\n const handleMediaChange = (event: MediaQueryListEvent) => {\n setShouldReduceMotion(event.matches);\n };\n\n mediaQuery.addEventListener('change', handleMediaChange);\n return () => {\n mediaQuery.removeEventListener('change', handleMediaChange);\n };\n }, []);\n\n return shouldReduceMotion;\n}\n"
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "use-scroll-progress",
|
|
3
|
+
"file": "use-scroll-progress.ts",
|
|
4
|
+
"dependencies": [],
|
|
5
|
+
"content": "\"use client\";\nimport { useEffect, useState, RefObject } from 'react';\n\nexport function useScrollProgress(ref?: RefObject<HTMLElement | null>) {\n const [progress, setProgress] = useState(0);\n\n useEffect(() => {\n const handleScroll = () => {\n if (ref && ref.current) {\n const element = ref.current;\n const totalHeight = element.scrollHeight - element.clientHeight;\n if (totalHeight === 0) {\n setProgress(0);\n } else {\n setProgress(element.scrollTop / totalHeight);\n }\n } else {\n const totalHeight = document.documentElement.scrollHeight - window.innerHeight;\n if (totalHeight === 0) {\n setProgress(0);\n } else {\n setProgress(window.scrollY / totalHeight);\n }\n }\n };\n\n const target = ref && ref.current ? ref.current : window;\n target.addEventListener('scroll', handleScroll, { passive: true });\n handleScroll();\n\n return () => {\n target.removeEventListener('scroll', handleScroll);\n };\n }, [ref]);\n\n return progress;\n}\n"
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "use-stagger",
|
|
3
|
+
"file": "use-stagger.ts",
|
|
4
|
+
"dependencies": [],
|
|
5
|
+
"content": "\"use client\";\nimport { useMemo } from 'react';\n\ninterface StaggerOptions {\n baseDelay?: number;\n staggerDelay?: number;\n from?: 'first' | 'last' | 'center' | number;\n}\n\nexport function useStagger(count: number, options: StaggerOptions = {}) {\n const { baseDelay = 0, staggerDelay = 0.05, from = 'first' } = options;\n\n const delays = useMemo(() => {\n const list = Array.from({ length: count });\n \n let centerIndex = 0;\n if (from === 'center') {\n centerIndex = (count - 1) / 2;\n } else if (from === 'last') {\n centerIndex = count - 1;\n } else if (typeof from === 'number') {\n centerIndex = from;\n }\n\n return list.map((_, index) => {\n let distance = 0;\n if (from === 'first') {\n distance = index;\n } else if (from === 'last') {\n distance = count - 1 - index;\n } else {\n distance = Math.abs(index - centerIndex);\n }\n return baseDelay + distance * staggerDelay;\n });\n }, [count, baseDelay, staggerDelay, from]);\n\n return delays;\n}\n"
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "use-web-haptics",
|
|
3
|
+
"file": "use-web-haptics.ts",
|
|
4
|
+
"dependencies": [],
|
|
5
|
+
"content": "\"use client\";\nimport { useCallback } from 'react';\n\nexport type HapticsType = 'light' | 'medium' | 'heavy' | 'success' | 'warning' | 'error';\n\nexport function useWebHaptics() {\n const trigger = useCallback((type: HapticsType = 'light') => {\n if (typeof window === 'undefined' || !window.navigator || !window.navigator.vibrate) {\n return false;\n }\n\n try {\n switch (type) {\n case 'light':\n return window.navigator.vibrate(10);\n case 'medium':\n return window.navigator.vibrate(25);\n case 'heavy':\n return window.navigator.vibrate(50);\n case 'success':\n return window.navigator.vibrate([15, 60, 15]);\n case 'warning':\n return window.navigator.vibrate([30, 60, 30]);\n case 'error':\n return window.navigator.vibrate([60, 60, 60, 60, 60]);\n default:\n return window.navigator.vibrate(type as any);\n }\n } catch (e) {\n console.warn('Vibration API error:', e);\n return false;\n }\n }, []);\n\n return { trigger };\n}\n"
|
|
6
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "utils",
|
|
3
|
+
"file": "utils.ts",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"clsx",
|
|
6
|
+
"tailwind-merge"
|
|
7
|
+
],
|
|
8
|
+
"content": "\"use client\";\nimport { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\n// Utility to map a value from one range to another (helpful for mouse following animations)\nexport function mapRange(\n value: number,\n inMin: number,\n inMax: number,\n outMin: number,\n outMax: number\n): number {\n return ((value - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;\n}\n"
|
|
9
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "wandering-cube",
|
|
3
|
+
"file": "wandering-cube.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const WanderingCube = () => {\n return (\n <div className=\"relative w-10 h-10\">\n <motion.div\n className=\"absolute top-0 left-0 w-4 h-4 bg-zinc-800 dark:bg-white rounded-sm\"\n animate={{ \n x: [0, 24, 24, 0, 0],\n y: [0, 0, 24, 24, 0],\n rotate: [0, -90, -180, -270, -360]\n }}\n transition={{ duration: 2.5, repeat: Infinity, ease: \"easeInOut\" }}\n />\n </div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "watch-spinner",
|
|
3
|
+
"file": "watch-spinner.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const WatchSpinner = () => (\n <div className=\"relative w-12 h-12 flex items-center justify-center\">\n {[0, 1, 2].map(i => (\n <motion.div\n key={i}\n className=\"absolute rounded-full border-[3px] border-transparent border-t-zinc-800 dark:border-t-white\"\n style={{ width: 44 - i * 12, height: 44 - i * 12 }}\n animate={{ rotate: 360 }}\n transition={{ duration: 1 + i * 0.5, repeat: Infinity, ease: \"easeInOut\" }}\n />\n ))}\n </div>\n);\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "wave-dots",
|
|
3
|
+
"file": "wave-dots.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const WaveDots = () => {\n return (\n <div className=\"flex space-x-1.5 h-6 items-center\">\n {[0, 1, 2, 3, 4].map((i) => (\n <motion.div\n key={i}\n className=\"w-2 h-2 bg-zinc-800 dark:bg-white rounded-full\"\n animate={{ y: [4, -4, 4] }}\n transition={{ duration: 1, repeat: Infinity, delay: i * 0.15, ease: \"easeInOut\" }}\n />\n ))}\n </div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "wave-physics-loader",
|
|
3
|
+
"file": "wave-physics-loader.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport { motion } from 'framer-motion';\nimport { useMemo } from 'react';\n\nexport function WavePhysicsLoader({ theme = 'light' }: { theme?: 'light' | 'dark' }) {\n const numBars = 15;\n const barWidth = 12; \n const barGap = 8; \n const barTotalWidth = barWidth + barGap;\n \n const numFrames = 201;\n const B = 4; \n const maxBounce = 60; \n const baseBarH = 16;\n const wavePeakH = 48; \n\n const { bars, ballX, ballY, ballScaleX, ballScaleY, times } = useMemo(() => {\n const barsData = Array.from({ length: numBars }).map(() => ({ \n heights: [] as string[],\n colors: [] as string[],\n }));\n const bX: string[] = [];\n const bY: string[] = [];\n const bScaleX: number[] = [];\n const bScaleY: number[] = [];\n const tArr: number[] = [];\n \n for (let k = 0; k < numFrames; k++) {\n const t = k / (numFrames - 1);\n tArr.push(t);\n \n const x_frac = t < 0.5 ? t / 0.5 : (1 - t) / 0.5;\n const ball_idx = x_frac * (numBars - 1);\n \n bX.push(`${ball_idx * barTotalWidth}px`);\n \n let bounce_f = (x_frac * B) % 1.0;\n if (x_frac === 1 || x_frac === 0) bounce_f = 0;\n \n const bounce_h = 4 * bounce_f * (1 - bounce_f);\n const height_factor = Math.max(0, 1 - bounce_h * 2);\n \n const ball_indent = height_factor * 20; \n const ball_y = (baseBarH + wavePeakH - ball_indent) + bounce_h * maxBounce;\n bY.push(`-${ball_y}px`);\n \n const squish = height_factor; \n bScaleY.push(1 - squish * 0.3);\n bScaleX.push(1 + squish * 0.25);\n \n for (let i = 0; i < numBars; i++) {\n const dist = Math.abs(i - ball_idx);\n \n let wave_val = 0;\n if (dist < 3) {\n wave_val = Math.cos((dist / 3) * (Math.PI / 2));\n }\n \n let indent = 0;\n if (dist < 1.5) {\n const indent_dist = Math.cos((dist / 1.5) * (Math.PI / 2));\n indent = indent_dist * height_factor * 20;\n }\n \n const bar_h = baseBarH + wave_val * wavePeakH - indent;\n barsData[i].heights.push(`${Math.max(4, bar_h)}px`); \n \n // Colors for Light Theme: zinc-200 to zinc-800\n const isDark = theme === 'dark';\n let r, g, b;\n if (isDark) {\n r = Math.round(39 + wave_val * (228 - 39));\n g = Math.round(39 + wave_val * (228 - 39));\n b = Math.round(42 + wave_val * (231 - 42));\n } else {\n r = Math.round(228 - wave_val * (228 - 39));\n g = Math.round(228 - wave_val * (228 - 39));\n b = Math.round(231 - wave_val * (231 - 42));\n }\n barsData[i].colors.push(`rgb(${r}, ${g}, ${b})`);\n }\n }\n \n return { bars: barsData, ballX: bX, ballY: bY, ballScaleX: bScaleX, ballScaleY: bScaleY, times: tArr };\n }, [theme]);\n\n return (\n <div className=\"relative flex flex-col items-center justify-center w-full scale-[0.6] sm:scale-75 md:scale-100\">\n <div className=\"relative flex items-end justify-start h-48 space-x-2 w-[292px]\">\n {bars.map((bar, i) => (\n <motion.div\n key={i}\n className=\"w-3 rounded-full origin-bottom\"\n style={{ height: '16px', backgroundColor: theme === 'dark' ? 'rgb(39, 39, 42)' : 'rgb(228, 228, 231)' }}\n animate={{\n height: bar.heights,\n backgroundColor: bar.colors,\n }}\n transition={{\n duration: 4,\n repeat: Infinity,\n times: times,\n ease: 'linear',\n }}\n />\n ))}\n \n <motion.div\n className=\"absolute w-3 h-3 bg-zinc-900 dark:bg-white rounded-full z-10 shadow-sm\"\n style={{ bottom: 0, left: 0, transformOrigin: 'bottom center' }}\n animate={{\n x: ballX,\n y: ballY,\n scaleX: ballScaleX,\n scaleY: ballScaleY,\n }}\n transition={{\n duration: 4,\n repeat: Infinity,\n times: times,\n ease: 'linear',\n }}\n />\n </div>\n </div>\n );\n}\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "waveform-loader",
|
|
3
|
+
"file": "waveform-loader.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const WaveformLoader = () => (\n <div className=\"flex items-center space-x-0.5 h-8\">\n {Array.from({ length: 8 }).map((_, i) => (\n <motion.div\n key={i}\n className=\"w-1 bg-zinc-800 dark:bg-white rounded-full\"\n animate={{ height: [4, 24, 4] }}\n transition={{ duration: 1, repeat: Infinity, delay: Math.sin(i) * 0.5, ease: \"easeInOut\" }}\n />\n ))}\n </div>\n);\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "word-reveal",
|
|
3
|
+
"file": "word-reveal.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion, type Variants } from 'framer-motion';\n\ninterface WordRevealProps {\n text: string;\n duration?: number;\n staggerDelay?: number;\n className?: string;\n}\n\nexport function WordReveal({\n text,\n duration = 0.5,\n staggerDelay = 0.04,\n className = '',\n}: WordRevealProps) {\n const words = text.split(/\\s+/);\n\n const containerVariants: Variants = {\n hidden: { opacity: 0 },\n visible: {\n opacity: 1,\n transition: {\n staggerChildren: staggerDelay,\n },\n },\n };\n\n const wordVariants: Variants = {\n hidden: { opacity: 0, y: 15, scale: 0.9 },\n visible: {\n opacity: 1,\n y: 0,\n scale: 1,\n transition: {\n duration,\n ease: [0.215, 0.61, 0.355, 1], // easeOutCubic\n },\n },\n };\n\n return (\n <motion.div\n variants={containerVariants}\n initial=\"hidden\"\n whileInView=\"visible\"\n viewport={{ once: true, margin: '-10%' }}\n className={`flex flex-wrap gap-x-2 gap-y-1.5 ${className}`}\n >\n {words.map((word, index) => (\n <motion.span\n key={index}\n variants={wordVariants}\n className=\"inline-block\"\n >\n {word}\n </motion.span>\n ))}\n </motion.div>\n );\n}\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "zig-zag-pulse",
|
|
3
|
+
"file": "zig-zag-pulse.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\nexport const ZigZagPulse = () => {\n return (\n <div className=\"grid grid-cols-3 gap-2 w-12 h-12\">\n {[\n [0, 0], [1, 1], [2, 0],\n [0, 2], [1, 1], [2, 2]\n ].map(([col, row], i) => (\n <motion.div\n key={i}\n className=\"w-2.5 h-2.5 bg-zinc-800 dark:bg-white rounded-full\"\n style={{ gridColumn: col + 1, gridRow: row + 1 }}\n animate={{ opacity: [0.2, 1, 0.2] }}\n transition={{ duration: 1.2, repeat: Infinity, delay: i * 0.1, ease: \"easeInOut\" }}\n />\n ))}\n </div>\n );\n};\n"
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "zoom-in",
|
|
3
|
+
"file": "zoom-in.tsx",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"framer-motion"
|
|
6
|
+
],
|
|
7
|
+
"content": "\"use client\";\nimport React from 'react';\nimport { motion } from 'framer-motion';\n\ninterface ZoomInProps {\n children: React.ReactNode;\n duration?: number;\n delay?: number;\n initialScale?: number;\n initialBlur?: string;\n className?: string;\n}\n\nexport function ZoomIn({\n children,\n duration = 0.7,\n delay = 0,\n initialScale = 0.85,\n initialBlur = '12px',\n className = '',\n}: ZoomInProps) {\n return (\n <motion.div\n initial={{ opacity: 0, scale: initialScale, filter: `blur(${initialBlur})` }}\n animate={{ opacity: 1, scale: 1, filter: 'blur(0px)' }}\n transition={{\n duration,\n delay,\n ease: [0.16, 1, 0.3, 1], // easeOutExpo\n }}\n className={className}\n >\n {children}\n </motion.div>\n );\n}\n"
|
|
8
|
+
}
|