blocks-dusted 0.1.10 → 0.1.11

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 (246) hide show
  1. package/README.md +35 -0
  2. package/package.json +1 -1
  3. package/src/utils/paths.js +13 -13
  4. package/templates/blocks/DD-Accordion/Component.tsx +229 -0
  5. package/templates/blocks/DD-Accordion/README.md +3 -0
  6. package/templates/blocks/DD-Accordion/config.ts +73 -0
  7. package/templates/blocks/DD-Accordion/manifest.json +75 -0
  8. package/templates/blocks/DD-AnimText/Component.tsx +788 -0
  9. package/templates/blocks/DD-AnimText/README.md +3 -0
  10. package/templates/blocks/DD-AnimText/config.ts +295 -0
  11. package/templates/blocks/DD-AnimText/manifest.json +85 -0
  12. package/templates/blocks/DD-AsideNav/Component.tsx +321 -0
  13. package/templates/blocks/DD-AsideNav/config.ts +204 -0
  14. package/templates/blocks/DD-AsideNav/manifest.json +80 -0
  15. package/templates/blocks/DD-Banner/Component.tsx +51 -0
  16. package/templates/blocks/DD-Banner/config.ts +57 -0
  17. package/templates/blocks/DD-Banner/manifest.json +72 -0
  18. package/templates/blocks/DD-BgLightning/Component.tsx +44 -0
  19. package/templates/blocks/DD-BgLightning/README.md +3 -0
  20. package/templates/blocks/DD-BgLightning/config.ts +97 -0
  21. package/templates/blocks/DD-BgLightning/manifest.json +79 -0
  22. package/templates/blocks/DD-BookCall/Component.tsx +10 -11
  23. package/templates/blocks/DD-BookCall/config.ts +238 -238
  24. package/templates/blocks/DD-ButtonPop/Component.tsx +117 -0
  25. package/templates/blocks/DD-ButtonPop/config.ts +105 -0
  26. package/templates/blocks/DD-ButtonPop/manifest.json +88 -0
  27. package/templates/blocks/DD-ButtonPop/svg-icons/Dust2.tsx +167 -0
  28. package/templates/blocks/DD-Card/Component.tsx +251 -0
  29. package/templates/blocks/DD-Card/README.md +4 -0
  30. package/templates/blocks/DD-Card/config.ts +154 -0
  31. package/templates/blocks/DD-Card/manifest.json +82 -0
  32. package/templates/blocks/DD-CardTemplate01/Component.tsx +5 -6
  33. package/templates/blocks/DD-CardTemplate01/config.ts +106 -106
  34. package/templates/blocks/DD-Carousel-A/Component.tsx +249 -249
  35. package/templates/blocks/DD-Carousel-B/Component.tsx +403 -403
  36. package/templates/blocks/DD-Chip/Component.tsx +250 -0
  37. package/templates/blocks/DD-Chip/EXAMPLES.md +313 -0
  38. package/templates/blocks/DD-Chip/README.md +202 -0
  39. package/templates/blocks/DD-Chip/config.ts +369 -0
  40. package/templates/blocks/DD-Chip/manifest.json +74 -0
  41. package/templates/blocks/DD-ComparisonTable/Component.tsx +256 -256
  42. package/templates/blocks/DD-Contact/Component.tsx +434 -434
  43. package/templates/blocks/DD-Contact/config.ts +22 -22
  44. package/templates/blocks/DD-Counter/Component.tsx +190 -0
  45. package/templates/blocks/DD-Counter/README.md +4 -0
  46. package/templates/blocks/DD-Counter/config.ts +291 -0
  47. package/templates/blocks/DD-Counter/manifest.json +74 -0
  48. package/templates/blocks/DD-CustomCSS/Component.tsx +8 -0
  49. package/templates/blocks/DD-CustomCSS/README.md +4 -0
  50. package/templates/blocks/DD-CustomCSS/addToLayout.md +5 -0
  51. package/templates/blocks/DD-CustomCSS/config.ts +22 -0
  52. package/templates/blocks/DD-CustomCSS/manifest.json +72 -0
  53. package/templates/blocks/DD-CustomCSS/renderCustomCSS.md +7 -0
  54. package/templates/blocks/DD-FeatCat/Component.tsx +302 -302
  55. package/templates/blocks/DD-FeatCat/config.ts +201 -201
  56. package/templates/blocks/DD-FeatStrip/Component.tsx +585 -585
  57. package/templates/blocks/DD-FeatStrip/config.ts +134 -134
  58. package/templates/blocks/DD-FluidBtn/ButtonsEyeCatching.tsx +628 -0
  59. package/templates/blocks/DD-FluidBtn/Component.tsx +43 -0
  60. package/templates/blocks/DD-FluidBtn/README.md +6 -0
  61. package/templates/blocks/DD-FluidBtn/config.ts +102 -0
  62. package/templates/blocks/DD-FluidBtn/manifest.json +86 -0
  63. package/templates/blocks/DD-GooeyInfo/Component.tsx +149 -0
  64. package/templates/blocks/DD-GooeyInfo/config.ts +135 -0
  65. package/templates/blocks/DD-GooeyInfo/manifest.json +72 -0
  66. package/templates/blocks/DD-Hero/Component.tsx +40 -17
  67. package/templates/blocks/DD-Hero/config.ts +267 -267
  68. package/templates/blocks/DD-HorizontalScroll/Component.tsx +4 -2
  69. package/templates/blocks/DD-HorizontalScroll/config.ts +231 -231
  70. package/templates/blocks/DD-Icon/Component.tsx +287 -0
  71. package/templates/blocks/DD-Icon/README.md +4 -0
  72. package/templates/blocks/DD-Icon/config.ts +258 -0
  73. package/templates/blocks/DD-Icon/hooks/revalidateBlockIds.ts +66 -0
  74. package/templates/blocks/DD-Icon/manifest.json +82 -0
  75. package/templates/blocks/DD-IconButton/Component.tsx +455 -0
  76. package/templates/blocks/DD-IconButton/README.md +326 -0
  77. package/templates/blocks/DD-IconButton/config.ts +239 -0
  78. package/templates/blocks/DD-IconButton/manifest.json +85 -0
  79. package/templates/blocks/DD-IdTag/Component.tsx +21 -0
  80. package/templates/blocks/DD-IdTag/README.md +4 -0
  81. package/templates/blocks/DD-IdTag/config.ts +41 -0
  82. package/templates/blocks/DD-IdTag/manifest.json +72 -0
  83. package/templates/blocks/DD-Iframe/Component.tsx +45 -0
  84. package/templates/blocks/DD-Iframe/README.md +4 -0
  85. package/templates/blocks/DD-Iframe/config.ts +47 -0
  86. package/templates/blocks/DD-Iframe/manifest.json +72 -0
  87. package/templates/blocks/DD-IframeMedia/Component.tsx +129 -0
  88. package/templates/blocks/DD-IframeMedia/README.md +4 -0
  89. package/templates/blocks/DD-IframeMedia/config.ts +79 -0
  90. package/templates/blocks/DD-IframeMedia/manifest.json +72 -0
  91. package/templates/blocks/DD-LineAnim/Component.tsx +36 -0
  92. package/templates/blocks/DD-LineAnim/README.md +4 -0
  93. package/templates/blocks/DD-LineAnim/config.ts +90 -0
  94. package/templates/blocks/DD-LineAnim/manifest.json +80 -0
  95. package/templates/blocks/DD-LinkGrid/Component.tsx +119 -0
  96. package/templates/blocks/DD-LinkGrid/README.md +4 -0
  97. package/templates/blocks/DD-LinkGrid/config.ts +51 -0
  98. package/templates/blocks/DD-LinkGrid/manifest.json +74 -0
  99. package/templates/blocks/DD-LogoMarq/Component.tsx +132 -0
  100. package/templates/blocks/DD-LogoMarq/README.md +4 -0
  101. package/templates/blocks/DD-LogoMarq/config.ts +264 -0
  102. package/templates/blocks/DD-LogoMarq/manifest.json +82 -0
  103. package/templates/blocks/DD-Lottie/Component.tsx +459 -0
  104. package/templates/blocks/DD-Lottie/README.md +4 -0
  105. package/templates/blocks/DD-Lottie/config.ts +379 -0
  106. package/templates/blocks/DD-Lottie/index.tsx +28 -0
  107. package/templates/blocks/DD-Lottie/manifest.json +83 -0
  108. package/templates/blocks/DD-MagicBento/Component.tsx +777 -0
  109. package/templates/blocks/DD-MagicBento/README.md +4 -0
  110. package/templates/blocks/DD-MagicBento/config.ts +264 -0
  111. package/templates/blocks/DD-MagicBento/manifest.json +74 -0
  112. package/templates/blocks/DD-MasonaryMedia/Component.tsx +547 -545
  113. package/templates/blocks/DD-MasonaryMedia/config.ts +2 -2
  114. package/templates/blocks/DD-MasonaryMedia/vendor.d.ts +2 -2
  115. package/templates/blocks/DD-Masonry/Component.tsx +645 -0
  116. package/templates/blocks/DD-Masonry/README.md +4 -0
  117. package/templates/blocks/DD-Masonry/config.ts +475 -0
  118. package/templates/blocks/DD-Masonry/manifest.json +82 -0
  119. package/templates/blocks/DD-Pricing/Component.tsx +372 -372
  120. package/templates/blocks/DD-Process/Component.tsx +149 -149
  121. package/templates/blocks/DD-Process/config.ts +150 -150
  122. package/templates/blocks/DD-Progress/Component.tsx +141 -0
  123. package/templates/blocks/DD-Progress/README.md +4 -0
  124. package/templates/blocks/DD-Progress/config.ts +175 -0
  125. package/templates/blocks/DD-Progress/manifest.json +74 -0
  126. package/templates/blocks/DD-ProjHeader/Component.tsx +91 -0
  127. package/templates/blocks/DD-ProjHeader/README.md +4 -0
  128. package/templates/blocks/DD-ProjHeader/config.ts +96 -0
  129. package/templates/blocks/DD-ProjHeader/manifest.json +72 -0
  130. package/templates/blocks/DD-ProjSlider/Component.tsx +123 -0
  131. package/templates/blocks/DD-ProjSlider/README.md +4 -0
  132. package/templates/blocks/DD-ProjSlider/config.ts +64 -0
  133. package/templates/blocks/DD-ProjSlider/manifest.json +72 -0
  134. package/templates/blocks/DD-ScrollText/Component.tsx +114 -0
  135. package/templates/blocks/DD-ScrollText/README.md +4 -0
  136. package/templates/blocks/DD-ScrollText/config.ts +58 -0
  137. package/templates/blocks/DD-ScrollText/manifest.json +72 -0
  138. package/templates/blocks/DD-Section/Component.tsx +266 -266
  139. package/templates/blocks/DD-Separator/Component.tsx +66 -0
  140. package/templates/blocks/DD-Separator/README.md +4 -0
  141. package/templates/blocks/DD-Separator/config.ts +58 -0
  142. package/templates/blocks/DD-Separator/manifest.json +72 -0
  143. package/templates/blocks/DD-Services/Component.tsx +176 -176
  144. package/templates/blocks/DD-Services/config.ts +149 -149
  145. package/templates/blocks/DD-ShowcaseGrid/Component.tsx +307 -307
  146. package/templates/blocks/DD-Slider-A/Component.tsx +237 -237
  147. package/templates/blocks/DD-StackCards/Component.tsx +473 -473
  148. package/templates/blocks/DD-StackCards/config.ts +399 -399
  149. package/templates/blocks/DD-Team/Component.tsx +247 -247
  150. package/templates/blocks/DD-Team/config.ts +173 -173
  151. package/templates/blocks/DD-TeamCards/Component.tsx +251 -0
  152. package/templates/blocks/DD-TeamCards/README.md +4 -0
  153. package/templates/blocks/DD-TeamCards/config.ts +302 -0
  154. package/templates/blocks/DD-TeamCards/manifest.json +74 -0
  155. package/templates/blocks/DD-TechStack/Component.tsx +168 -162
  156. package/templates/blocks/DD-TechStack/config.ts +153 -153
  157. package/templates/blocks/DD-TestMarq/Component.tsx +132 -0
  158. package/templates/blocks/DD-TestMarq/README.md +4 -0
  159. package/templates/blocks/DD-TestMarq/RowLabel.tsx +9 -0
  160. package/templates/blocks/DD-TestMarq/config.ts +88 -0
  161. package/templates/blocks/DD-TestMarq/manifest.json +72 -0
  162. package/templates/blocks/DD-Testim/Component.tsx +247 -0
  163. package/templates/blocks/DD-Testim/README.md +4 -0
  164. package/templates/blocks/DD-Testim/config.ts +101 -0
  165. package/templates/blocks/DD-Testim/manifest.json +75 -0
  166. package/templates/blocks/DD-Testim2/Component.tsx +256 -0
  167. package/templates/blocks/DD-Testim2/README.md +4 -0
  168. package/templates/blocks/DD-Testim2/config.ts +100 -0
  169. package/templates/blocks/DD-Testim2/manifest.json +74 -0
  170. package/templates/blocks/DD-Testimonials/Component.tsx +147 -147
  171. package/templates/blocks/DD-Testimonials/config.ts +120 -120
  172. package/templates/blocks/DD-TextMarq/Component.tsx +157 -0
  173. package/templates/blocks/DD-TextMarq/README.md +4 -0
  174. package/templates/blocks/DD-TextMarq/config.ts +237 -0
  175. package/templates/blocks/DD-TextMarq/manifest.json +82 -0
  176. package/templates/blocks/DD-Thanks/Component.tsx +500 -0
  177. package/templates/blocks/DD-Thanks/README.md +4 -0
  178. package/templates/blocks/DD-Thanks/config.ts +224 -0
  179. package/templates/blocks/DD-Thanks/manifest.json +72 -0
  180. package/templates/blocks/DD-VertMarq/Component.tsx +154 -0
  181. package/templates/blocks/DD-VertMarq/README.md +4 -0
  182. package/templates/blocks/DD-VertMarq/config.ts +236 -0
  183. package/templates/blocks/DD-VertMarq/dist/index.css +6 -0
  184. package/templates/blocks/DD-VertMarq/dist/index.min.css +1 -0
  185. package/templates/blocks/DD-VertMarq/manifest.json +74 -0
  186. package/templates/blocks/DD-Work/Component.tsx +318 -315
  187. package/templates/blocks/DD-Work/config.ts +165 -165
  188. package/templates/blocks/DD-Work-B/Component.tsx +294 -294
  189. package/templates/blocks/DDHG-CTASection2/Component.tsx +185 -0
  190. package/templates/blocks/DDHG-CTASection2/config.ts +140 -0
  191. package/templates/blocks/DDHG-CTASection2/manifest.json +45 -0
  192. package/templates/blocks/DDHG-HighlightArc/Component.tsx +243 -0
  193. package/templates/blocks/DDHG-HighlightArc/config.ts +85 -0
  194. package/templates/blocks/DDHG-HighlightArc/manifest.json +46 -0
  195. package/templates/blocks/DDHG-LogoMarquee/Component.tsx +93 -0
  196. package/templates/blocks/DDHG-LogoMarquee/config.ts +66 -0
  197. package/templates/blocks/DDHG-LogoMarquee/manifest.json +39 -0
  198. package/templates/blocks/DDHG-NavCodeGrid/Component.tsx +213 -0
  199. package/templates/blocks/DDHG-NavCodeGrid/config.ts +64 -0
  200. package/templates/blocks/DDHG-NavCodeGrid/manifest.json +45 -0
  201. package/templates/blocks/DDHG-ProcessSec/Component.tsx +575 -0
  202. package/templates/blocks/DDHG-ProcessSec/config.ts +170 -0
  203. package/templates/blocks/DDHG-ProcessSec/manifest.json +56 -0
  204. package/templates/blocks/DDHG-ServiceDetails/Component.tsx +164 -0
  205. package/templates/blocks/DDHG-ServiceDetails/ServiceDetailCard.tsx +394 -0
  206. package/templates/blocks/DDHG-ServiceDetails/config.ts +77 -0
  207. package/templates/blocks/DDHG-ServiceDetails/manifest.json +50 -0
  208. package/templates/blocks/DDHG-ServiceHero/Component.tsx +234 -0
  209. package/templates/blocks/DDHG-ServiceHero/config.ts +49 -0
  210. package/templates/blocks/DDHG-ServiceHero/manifest.json +26 -0
  211. package/templates/blocks/DDHG-ServiceOverview/Component.tsx +277 -0
  212. package/templates/blocks/DDHG-ServiceOverview/config.ts +64 -0
  213. package/templates/blocks/DDHG-ServiceOverview/manifest.json +44 -0
  214. package/templates/blocks/DDHG-StatsFAQ/Component.tsx +389 -0
  215. package/templates/blocks/DDHG-StatsFAQ/config.ts +204 -0
  216. package/templates/blocks/DDHG-StatsFAQ/manifest.json +45 -0
  217. package/templates/blocks/DDHG-TeamCards/Component.tsx +131 -0
  218. package/templates/blocks/DDHG-TeamCards/config.ts +48 -0
  219. package/templates/blocks/DDHG-TeamCards/manifest.json +29 -0
  220. package/templates/shared/src/components/BgLightning/index.tsx +242 -0
  221. package/templates/shared/src/components/ui/ShareButton/index.tsx +80 -0
  222. package/templates/shared/src/components/ui/anims/FadeOnScroll.tsx +48 -0
  223. package/templates/shared/src/components/ui/anims/FadeUpOnInView.tsx +63 -0
  224. package/templates/shared/src/components/ui/anims/GlareHover.tsx +111 -0
  225. package/templates/shared/src/components/ui/anims/LineAnims.tsx +81 -0
  226. package/templates/shared/src/components/ui/anims/TitleAnims01.tsx +54 -0
  227. package/templates/shared/src/components/ui/anims/animation-container.tsx +29 -0
  228. package/templates/shared/src/components/ui/anims/blur-in.tsx +26 -0
  229. package/templates/shared/src/components/ui/anims/counter.tsx +53 -0
  230. package/templates/shared/src/components/ui/anims/fade.tsx +83 -0
  231. package/templates/shared/src/components/ui/anims/gradual-spacing.tsx +39 -0
  232. package/templates/shared/src/components/ui/anims/pull-up.tsx +93 -0
  233. package/templates/shared/src/components/ui/anims/reveal-text.tsx +76 -0
  234. package/templates/shared/src/components/ui/anims/rotate-words.tsx +43 -0
  235. package/templates/shared/src/components/ui/anims/shiny-text.tsx +58 -0
  236. package/templates/shared/src/components/ui/anims/shuffle-text.tsx +85 -0
  237. package/templates/shared/src/components/ui/anims/split-text.tsx +211 -0
  238. package/templates/shared/src/components/ui/anims/staggered-fade.tsx +133 -0
  239. package/templates/shared/src/components/ui/anims/text-scroll.tsx +111 -0
  240. package/templates/shared/src/components/ui/anims/typing-effect.tsx +112 -0
  241. package/templates/shared/src/components/ui/button-dusted-fluid/index.tsx +1521 -0
  242. package/templates/shared/src/components/ui/separator.tsx +85 -0
  243. package/templates/shared/src/hooks/useBodyScrollLock.ts +97 -0
  244. package/templates/shared/src/hooks/useClickOutside.ts +28 -0
  245. package/templates/shared/src/utilities/renderCustomCSS.ts +5 -0
  246. package/templates/shared/src/utilities/smoothScroll.ts +65 -0
@@ -0,0 +1,788 @@
1
+ 'use client'
2
+
3
+ import React, { useId, useRef, useEffect, useState, useCallback } from 'react'
4
+
5
+ import { AnimatePresence, motion, useInView } from 'framer-motion'
6
+ import { gsap } from 'gsap'
7
+ import { ScrollTrigger } from 'gsap/ScrollTrigger'
8
+ import { SplitText as GSAPSplitText } from 'gsap/SplitText'
9
+ import { useGSAP } from '@gsap/react'
10
+ import { TextFade } from '@/components/ui/anims/fade'
11
+ import { GradualSpacing } from '@/components/ui/anims/gradual-spacing'
12
+ import { TypingEffect } from '@/components/ui/anims/typing-effect'
13
+ import { StaggeredFade } from '@/components/ui/anims/staggered-fade'
14
+ import { RotateWords } from '@/components/ui/anims/rotate-words'
15
+ import { LettersPullUp, WordsPullUp } from '@/components/ui/anims/pull-up'
16
+ import { BlurIn } from '@/components/ui/anims/blur-in'
17
+ import { ShuffleText } from '@/components/ui/anims/shuffle-text'
18
+ import RichText from '@/components/RichText/index'
19
+ import { cn } from '@/utilities/ui'
20
+ // import './index.scss'
21
+
22
+ // Register GSAP plugins
23
+ gsap.registerPlugin(ScrollTrigger, GSAPSplitText, useGSAP)
24
+
25
+ type Props = {
26
+ animatedText?: string | any
27
+ plainText?: string
28
+ rotateWords?: string
29
+ variation?:
30
+ | 'gradual-spacing'
31
+ | 'typing'
32
+ | 'staggered-fade'
33
+ | 'rotate'
34
+ | 'letters-pull-up'
35
+ | 'words-pull-up'
36
+ | 'blur-in'
37
+ | 'text-fade-up'
38
+ | 'text-fade-down'
39
+ | 'no-animation'
40
+ | 'split-text'
41
+ | 'text-type'
42
+ | 'shuffle-text'
43
+ | 'shiny-text'
44
+ className?: string
45
+ aniTextClass?: string
46
+ aniTextBoxClass?: string
47
+ aniTextBoxContainerClass?: string
48
+ animTextScrollSpeed?: string
49
+ // SplitText props from config
50
+ splitTrigger?: 'view' | 'hover' | 'click'
51
+ splitDelay?: number
52
+ splitDuration?: number
53
+ splitEase?: string
54
+ splitYOffset?: number
55
+ splitOpacity?: boolean
56
+ // TextType props from config
57
+ typeSpeed?: number
58
+ typeDelay?: number
59
+ showCursor?: boolean
60
+ cursorChar?: string
61
+ autoStart?: boolean
62
+ // Shuffle props from config (simplified)
63
+ shuffleDuration?: number
64
+ // Shiny props from config
65
+ shinyDuration?: number
66
+ shinyColor?: string
67
+ }
68
+
69
+ // Staggered Animation Variants
70
+ const containerVariants = {
71
+ hidden: {
72
+ opacity: 0
73
+ },
74
+ visible: {
75
+ opacity: 1,
76
+ transition: {
77
+ staggerChildren: 0.2
78
+ }
79
+ }
80
+ }
81
+
82
+ const childVariants = {
83
+ hidden: {
84
+ opacity: 0,
85
+ y: 20
86
+ },
87
+ visible: {
88
+ opacity: 1,
89
+ y: 0,
90
+ transition: {
91
+ duration: 0.5
92
+ }
93
+ }
94
+ }
95
+
96
+ // Inline SplitText Component with scroll trigger repeat
97
+ interface SplitTextProps {
98
+ text: string
99
+ className?: string
100
+ delay?: number
101
+ duration?: number
102
+ ease?: string
103
+ yOffset?: number
104
+ opacity?: boolean
105
+ trigger?: 'view' | 'hover' | 'click'
106
+ }
107
+
108
+ export const SplitText: React.FC<SplitTextProps> = ({
109
+ text,
110
+ className = '',
111
+ delay = 0.05,
112
+ duration = 0.6,
113
+ ease = 'back.out(1.7)',
114
+ yOffset = 80,
115
+ opacity = true,
116
+ trigger = 'view'
117
+ }) => {
118
+ const ref = useRef<HTMLParagraphElement>(null)
119
+ const [fontsLoaded, setFontsLoaded] = useState<boolean>(false)
120
+
121
+ useEffect(() => {
122
+ if (document.fonts.status === 'loaded') {
123
+ setFontsLoaded(true)
124
+ } else {
125
+ document.fonts.ready.then(() => {
126
+ setFontsLoaded(true)
127
+ })
128
+ }
129
+ }, [])
130
+
131
+ useGSAP(
132
+ () => {
133
+ if (!ref.current || !text || !fontsLoaded) return
134
+
135
+ const el = ref.current as HTMLElement & {
136
+ _rbsplitInstance?: GSAPSplitText
137
+ }
138
+
139
+ if (el._rbsplitInstance) {
140
+ try {
141
+ el._rbsplitInstance.revert()
142
+ } catch (_) {}
143
+ el._rbsplitInstance = undefined
144
+ }
145
+
146
+ const splitInstance = new GSAPSplitText(el, {
147
+ type: 'chars',
148
+ charsClass: 'split-char'
149
+ })
150
+
151
+ const chars = splitInstance.chars || []
152
+
153
+ // Set initial state
154
+ gsap.set(chars, {
155
+ opacity: opacity ? 0 : 1,
156
+ y: yOffset
157
+ })
158
+
159
+ const animateIn = () => {
160
+ gsap.to(chars, {
161
+ opacity: 1,
162
+ y: 0,
163
+ duration,
164
+ ease,
165
+ stagger: delay,
166
+ force3D: true
167
+ })
168
+ }
169
+
170
+ const animateOut = () => {
171
+ gsap.to(chars, {
172
+ opacity: opacity ? 0 : 1,
173
+ y: yOffset,
174
+ duration: duration * 0.5,
175
+ ease: 'power2.in',
176
+ stagger: delay * 0.5
177
+ })
178
+ }
179
+
180
+ if (trigger === 'view') {
181
+ ScrollTrigger.create({
182
+ trigger: el,
183
+ start: 'top 80%',
184
+ end: 'bottom 20%',
185
+ onEnter: animateIn,
186
+ onLeave: animateOut,
187
+ onEnterBack: animateIn,
188
+ onLeaveBack: animateOut
189
+ })
190
+ } else if (trigger === 'hover') {
191
+ el.addEventListener('mouseenter', animateIn)
192
+ el.addEventListener('mouseleave', animateOut)
193
+ } else if (trigger === 'click') {
194
+ el.addEventListener('click', () => {
195
+ animateOut()
196
+ setTimeout(animateIn, duration * 500)
197
+ })
198
+ }
199
+
200
+ el._rbsplitInstance = splitInstance
201
+
202
+ return () => {
203
+ ScrollTrigger.getAll().forEach((st) => {
204
+ if (st.trigger === el) st.kill()
205
+ })
206
+ if (trigger === 'hover') {
207
+ el.removeEventListener('mouseenter', animateIn)
208
+ el.removeEventListener('mouseleave', animateOut)
209
+ }
210
+ try {
211
+ splitInstance.revert()
212
+ } catch (_) {}
213
+ el._rbsplitInstance = undefined
214
+ }
215
+ },
216
+ {
217
+ dependencies: [text, delay, duration, ease, yOffset, opacity, trigger, fontsLoaded],
218
+ scope: ref
219
+ }
220
+ )
221
+
222
+ return (
223
+ <p
224
+ ref={ref}
225
+ className={`split-parent ${className}`}
226
+ style={{
227
+ // Ensure styles are inherited by split characters
228
+ display: 'inline-block'
229
+ }}
230
+ >
231
+ {text}
232
+ </p>
233
+ )
234
+ }
235
+
236
+ // Inline TextType Component with scroll trigger
237
+ interface TextTypeProps {
238
+ text: string
239
+ className?: string
240
+ speed?: number
241
+ delay?: number
242
+ showCursor?: boolean
243
+ cursorChar?: string
244
+ autoStart?: boolean
245
+ }
246
+
247
+ export const TextType: React.FC<TextTypeProps> = ({
248
+ text,
249
+ className = '',
250
+ speed = 100,
251
+ delay = 0,
252
+ showCursor = true,
253
+ cursorChar = '|',
254
+ autoStart = true
255
+ }) => {
256
+ const [displayedText, setDisplayedText] = useState('')
257
+ const [isTyping, setIsTyping] = useState(false)
258
+ const [hasTyped, setHasTyped] = useState(false)
259
+ const cursorRef = useRef<HTMLSpanElement>(null)
260
+ const containerRef = useRef<HTMLDivElement>(null)
261
+ const timeoutRef = useRef<NodeJS.Timeout | null>(null)
262
+
263
+ const startTyping = useCallback(() => {
264
+ if (isTyping || hasTyped) return
265
+ setIsTyping(true)
266
+ setDisplayedText('')
267
+
268
+ let i = 0
269
+ const typeChar = () => {
270
+ if (i < text.length) {
271
+ setDisplayedText(text.slice(0, i + 1))
272
+ i++
273
+ timeoutRef.current = setTimeout(typeChar, speed)
274
+ } else {
275
+ setIsTyping(false)
276
+ setHasTyped(true)
277
+ }
278
+ }
279
+
280
+ timeoutRef.current = setTimeout(typeChar, delay)
281
+ }, [text, speed, delay, isTyping, hasTyped])
282
+
283
+ const resetTyping = useCallback(() => {
284
+ if (timeoutRef.current) {
285
+ clearTimeout(timeoutRef.current)
286
+ }
287
+ setIsTyping(false)
288
+ // Don't reset hasTyped or displayedText to prevent re-typing
289
+ }, [])
290
+
291
+ useEffect(() => {
292
+ if (showCursor && cursorRef.current) {
293
+ gsap.to(cursorRef.current, {
294
+ opacity: 0,
295
+ duration: 0.5,
296
+ repeat: -1,
297
+ yoyo: true,
298
+ ease: 'power2.inOut'
299
+ })
300
+ }
301
+ }, [showCursor])
302
+
303
+ useGSAP(() => {
304
+ if (!containerRef.current) return
305
+
306
+ if (autoStart) {
307
+ ScrollTrigger.create({
308
+ trigger: containerRef.current,
309
+ start: 'top 80%',
310
+ onEnter: startTyping,
311
+ once: true // Only trigger once
312
+ })
313
+ }
314
+
315
+ return () => {
316
+ if (timeoutRef.current) {
317
+ clearTimeout(timeoutRef.current)
318
+ }
319
+ }
320
+ }, [startTyping, autoStart])
321
+
322
+ return (
323
+ <div ref={containerRef} className={`text-type ${className}`}>
324
+ <span className="text-type__content">{displayedText}</span>
325
+ {showCursor && (
326
+ <span ref={cursorRef} className="text-type__cursor">
327
+ {cursorChar}
328
+ </span>
329
+ )}
330
+ </div>
331
+ )
332
+ }
333
+
334
+ // Inline Shuffle Component with scroll trigger
335
+ interface ShuffleProps {
336
+ text: string
337
+ className?: string
338
+ duration?: number
339
+ speed?: number
340
+ chars?: string
341
+ autoStart?: boolean
342
+ }
343
+
344
+ export const Shuffle: React.FC<ShuffleProps> = ({
345
+ text,
346
+ className = 'ShuffleText',
347
+ duration = 600,
348
+ speed = 100,
349
+ chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
350
+ autoStart = false
351
+ }) => {
352
+ const [displayText, setDisplayText] = useState(text)
353
+ const containerRef = useRef<HTMLDivElement>(null)
354
+ const isShufflingRef = useRef(false)
355
+
356
+ const shuffle = useCallback(() => {
357
+ if (isShufflingRef.current) return
358
+ isShufflingRef.current = true
359
+
360
+ const originalText = text
361
+ const iterations = Math.ceil(duration / speed)
362
+ let iteration = 0
363
+
364
+ const shuffleInterval = setInterval(() => {
365
+ setDisplayText(
366
+ originalText
367
+ .split('')
368
+ .map((char, index) => {
369
+ if (index < iteration) {
370
+ return originalText[index]
371
+ }
372
+ return chars[Math.floor(Math.random() * chars.length)]
373
+ })
374
+ .join('')
375
+ )
376
+
377
+ if (iteration >= originalText.length) {
378
+ clearInterval(shuffleInterval)
379
+ setDisplayText(originalText)
380
+ isShufflingRef.current = false
381
+ }
382
+
383
+ iteration += 1 / 3
384
+ }, speed)
385
+ }, [text, duration, speed, chars])
386
+
387
+ const resetText = useCallback(() => {
388
+ isShufflingRef.current = false
389
+ setDisplayText(text)
390
+ }, [text])
391
+
392
+ useGSAP(() => {
393
+ if (!containerRef.current) return
394
+
395
+ if (autoStart) {
396
+ ScrollTrigger.create({
397
+ trigger: containerRef.current,
398
+ start: 'top 80%',
399
+ end: 'bottom 20%',
400
+ onEnter: shuffle,
401
+ onLeave: resetText,
402
+ onEnterBack: shuffle,
403
+ onLeaveBack: resetText
404
+ })
405
+ }
406
+ }, [shuffle, resetText, autoStart])
407
+
408
+ return (
409
+ <div
410
+ ref={containerRef}
411
+ className={`shuffle-text ${className}`}
412
+ onClick={!autoStart ? shuffle : undefined}
413
+ >
414
+ {displayText}
415
+ </div>
416
+ )
417
+ }
418
+
419
+ // Inline ShinyText Component with scroll trigger
420
+ interface ShinyTextProps {
421
+ text: string
422
+ className?: string
423
+ duration?: number
424
+ delay?: number
425
+ repeat?: boolean
426
+ color?: string
427
+ }
428
+
429
+ export const ShinyText: React.FC<ShinyTextProps> = ({
430
+ text,
431
+ className = '',
432
+ duration = 2,
433
+ delay = 0,
434
+ repeat = true,
435
+ color = 'rgba(255, 255, 255, 0.6)'
436
+ }) => {
437
+ const ref = useRef<HTMLDivElement>(null)
438
+ const containerRef = useRef(null)
439
+ const isInView = useInView(containerRef, { once: false })
440
+
441
+ const staggerVariants = {
442
+ hidden: { opacity: 0, y: 20 },
443
+ show: (i: number) => ({
444
+ y: 0,
445
+ opacity: 1,
446
+ transition: { delay: i * 0.1 }
447
+ })
448
+ }
449
+
450
+ const letters = text.split('')
451
+
452
+ // Helper function to convert color to lower opacity
453
+ const getLowOpacityColor = (inputColor: string): string => {
454
+ // Handle hex colors
455
+ if (inputColor.startsWith('#')) {
456
+ const hex = inputColor.replace('#', '')
457
+ const r = parseInt(hex.substring(0, 2), 16)
458
+ const g = parseInt(hex.substring(2, 4), 16)
459
+ const b = parseInt(hex.substring(4, 6), 16)
460
+ return `rgba(${r}, ${g}, ${b}, 0.55)`
461
+ }
462
+
463
+ // Handle rgba colors
464
+ if (inputColor.startsWith('rgba')) {
465
+ const match = inputColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/)
466
+ if (match) {
467
+ return `rgba(${match[1]}, ${match[2]}, ${match[3]}, 0.55)`
468
+ }
469
+ }
470
+
471
+ // Handle rgb colors
472
+ if (inputColor.startsWith('rgb')) {
473
+ const match = inputColor.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/)
474
+ if (match) {
475
+ return `rgba(${match[1]}, ${match[2]}, ${match[3]}, 0.15)`
476
+ }
477
+ }
478
+
479
+ // Fallback to transparent
480
+ return 'transparent'
481
+ }
482
+
483
+ useGSAP(() => {
484
+ if (!ref.current) return
485
+
486
+ const lowOpacityColor = getLowOpacityColor(color)
487
+
488
+ const shine = () => {
489
+ const tl = gsap.timeline({ repeat: repeat ? -1 : 0, delay })
490
+
491
+ tl.set(ref.current, {
492
+ backgroundImage: `linear-gradient(110deg, ${lowOpacityColor} 35%, ${color} 45%, ${color} 55%, ${lowOpacityColor} 65%)`,
493
+ backgroundSize: '200% 100%',
494
+ backgroundPosition: '200% 0',
495
+ WebkitBackgroundClip: 'text',
496
+ backgroundClip: 'text',
497
+ color: 'transparent'
498
+ })
499
+ .to(ref.current, {
500
+ backgroundPosition: '-200% 0',
501
+ duration,
502
+ ease: 'none'
503
+ })
504
+ .set(ref.current, {
505
+ backgroundImage: 'none',
506
+ color: 'inherit'
507
+ })
508
+ }
509
+
510
+ ScrollTrigger.create({
511
+ trigger: ref.current,
512
+ start: 'top 80%',
513
+ end: 'bottom 20%',
514
+ onEnter: shine,
515
+ onEnterBack: shine
516
+ })
517
+ }, [duration, delay, repeat, color])
518
+
519
+ return (
520
+ <motion.span
521
+ ref={containerRef}
522
+ initial="hidden"
523
+ animate={isInView ? 'show' : 'hidden'}
524
+ className={className}
525
+ >
526
+ <BlurIn>
527
+ <div ref={ref} className={`shiny-text ${className}`}>
528
+ {letters.map((char, i) => (
529
+ <motion.span key={`${char}-${i}`} variants={staggerVariants} custom={i}>
530
+ {char}
531
+ </motion.span>
532
+ ))}
533
+ </div>
534
+ </BlurIn>
535
+ </motion.span>
536
+ )
537
+ }
538
+
539
+ export const DDAnimText: React.FC<Props> = ({
540
+ animatedText = '',
541
+ plainText = '',
542
+ rotateWords = '',
543
+ variation = 'text-fade-up',
544
+ className,
545
+ aniTextClass,
546
+ aniTextBoxClass,
547
+ aniTextBoxContainerClass,
548
+ // SplitText props
549
+ splitTrigger = 'view',
550
+ splitDelay = 0.05,
551
+ splitDuration = 0.6,
552
+ splitEase = 'back.out(1.7)',
553
+ splitYOffset = 80,
554
+ splitOpacity = true,
555
+ // TextType props
556
+ typeSpeed = 100,
557
+ typeDelay = 0,
558
+ showCursor = true,
559
+ cursorChar = '|',
560
+ autoStart = true,
561
+ // Shuffle props (simplified)
562
+ shuffleDuration = 0.8,
563
+ // Shiny props
564
+ shinyDuration = 5,
565
+ shinyColor = 'rgba(255, 255, 255, 0.6)'
566
+ }) => {
567
+ // Generate unique ID for this component instance
568
+ const uniqueId = useId()
569
+
570
+ const richText = animatedText || ''
571
+ const textContent = plainText || ''
572
+
573
+ if (!richText && !textContent && !rotateWords) {
574
+ return null
575
+ }
576
+
577
+ // Extract plain text for animations that need raw text
578
+ const extractText = (data: any): string => {
579
+ if (!data) return ''
580
+ if (typeof data === 'string') return data
581
+ if (Array.isArray(data)) {
582
+ return data.map((node) => (typeof node === 'string' ? node : node.text || '')).join(' ')
583
+ }
584
+ return ''
585
+ }
586
+
587
+ const extractedText = textContent || extractText(richText)
588
+ const rotatingWords = rotateWords ? rotateWords.split(',').map((w) => w.trim()) : []
589
+
590
+ return (
591
+ <AnimatePresence initial={true} mode="sync">
592
+ <motion.div
593
+ id={`animated-text-${variation}-${uniqueId}`}
594
+ suppressHydrationWarning
595
+ key={`${variation}-${uniqueId}`}
596
+ variants={containerVariants}
597
+ initial="hidden"
598
+ animate="visible"
599
+ exit="hidden"
600
+ scroll-data="true"
601
+ scroll-data-speed={'0.5'}
602
+ className={cn(
603
+ aniTextBoxClass,
604
+ className,
605
+ aniTextBoxContainerClass,
606
+ 'animated-text-container'
607
+ )}
608
+ >
609
+ {/* Animations that require plain text */}
610
+ {variation === 'gradual-spacing' && (
611
+ <motion.div suppressHydrationWarning variants={childVariants}>
612
+ <GradualSpacing
613
+ text={extractedText}
614
+ className={cn(aniTextBoxClass, className)}
615
+ aniTextClass={aniTextClass}
616
+ />
617
+ </motion.div>
618
+ )}
619
+
620
+ {variation === 'typing' && (
621
+ <motion.div suppressHydrationWarning variants={childVariants}>
622
+ <TypingEffect
623
+ text={extractedText}
624
+ className={cn(aniTextBoxClass, className)}
625
+ aniTextClass={aniTextClass}
626
+ />
627
+ </motion.div>
628
+ )}
629
+
630
+ {variation === 'staggered-fade' && (
631
+ <motion.div suppressHydrationWarning variants={childVariants}>
632
+ <StaggeredFade
633
+ text={extractedText}
634
+ className={cn(aniTextBoxClass, className)}
635
+ aniTextClass={aniTextClass}
636
+ />
637
+ </motion.div>
638
+ )}
639
+
640
+ {variation === 'letters-pull-up' && (
641
+ <motion.div suppressHydrationWarning variants={childVariants}>
642
+ <LettersPullUp
643
+ text={extractedText}
644
+ className={cn(aniTextBoxClass, className)}
645
+ aniTextClass={aniTextClass}
646
+ />
647
+ </motion.div>
648
+ )}
649
+
650
+ {variation === 'words-pull-up' && (
651
+ <motion.div suppressHydrationWarning variants={childVariants}>
652
+ <WordsPullUp
653
+ text={extractedText}
654
+ className={cn(aniTextBoxClass, className)}
655
+ aniTextClass={aniTextClass}
656
+ />
657
+ </motion.div>
658
+ )}
659
+
660
+ {/* Rotate Words requires separate richText for words */}
661
+ {variation === 'rotate' && (
662
+ <motion.div suppressHydrationWarning variants={childVariants}>
663
+ <RotateWords
664
+ text={extractedText}
665
+ words={rotatingWords}
666
+ className={cn(aniTextBoxClass, className)}
667
+ aniTextClass={aniTextClass}
668
+ />
669
+ </motion.div>
670
+ )}
671
+
672
+ {/* GSAP-based animations that use plain text */}
673
+ {variation === 'split-text' && (
674
+ <motion.div suppressHydrationWarning variants={childVariants}>
675
+ <SplitText
676
+ text={extractedText}
677
+ className={cn(aniTextBoxClass, className, aniTextClass)}
678
+ delay={splitDelay}
679
+ duration={splitDuration}
680
+ ease={splitEase}
681
+ yOffset={splitYOffset}
682
+ opacity={splitOpacity}
683
+ trigger={splitTrigger}
684
+ />
685
+ </motion.div>
686
+ )}
687
+
688
+ {variation === 'text-type' && (
689
+ <motion.div suppressHydrationWarning variants={childVariants}>
690
+ <TextType
691
+ text={extractedText}
692
+ className={cn(aniTextBoxClass, className, aniTextClass)}
693
+ speed={typeSpeed}
694
+ delay={typeDelay}
695
+ showCursor={showCursor}
696
+ cursorChar={cursorChar}
697
+ autoStart={autoStart}
698
+ />
699
+ </motion.div>
700
+ )}
701
+
702
+ {variation === 'shuffle-text' && (
703
+ <motion.div suppressHydrationWarning variants={childVariants}>
704
+ <ShuffleText
705
+ text={extractedText}
706
+ className={cn(aniTextBoxClass, className)}
707
+ aniTextClass={aniTextClass}
708
+ duration={shuffleDuration || 0.8}
709
+ delay={0}
710
+ />
711
+ </motion.div>
712
+ )}
713
+
714
+ {variation === 'shiny-text' && (
715
+ <motion.div suppressHydrationWarning variants={childVariants}>
716
+ <ShinyText
717
+ text={extractedText}
718
+ className={cn(aniTextBoxClass, className, aniTextClass)}
719
+ duration={shinyDuration || 2}
720
+ delay={0}
721
+ repeat={true}
722
+ color={shinyColor || 'rgba(255, 255, 255, 0.6)'}
723
+ />
724
+ </motion.div>
725
+ )}
726
+
727
+ {/* Animations that require full RichText content */}
728
+ {variation === 'blur-in' && (
729
+ <motion.div suppressHydrationWarning variants={childVariants}>
730
+ <BlurIn>
731
+ <RichText
732
+ data={richText}
733
+ className={cn('max-w-none', aniTextClass)}
734
+ enableGutter={false}
735
+ />
736
+ </BlurIn>
737
+ </motion.div>
738
+ )}
739
+
740
+ {variation === 'text-fade-up' && (
741
+ <motion.div suppressHydrationWarning variants={childVariants}>
742
+ <TextFade
743
+ direction="up"
744
+ className={cn('p-0 flex flex-col', aniTextBoxClass, className)}
745
+ >
746
+ <RichText
747
+ data={richText}
748
+ className={cn('max-w-none', aniTextClass)}
749
+ enableProse={false}
750
+ enableGutter={false}
751
+ />
752
+ </TextFade>
753
+ </motion.div>
754
+ )}
755
+
756
+ {variation === 'text-fade-down' && (
757
+ <motion.div suppressHydrationWarning variants={childVariants}>
758
+ <TextFade
759
+ direction="down"
760
+ className={cn('p-0 flex flex-col', aniTextBoxClass, className)}
761
+ >
762
+ <RichText
763
+ data={richText}
764
+ className={cn('max-w-none', aniTextClass)}
765
+ enableProse={false}
766
+ enableGutter={false}
767
+ />
768
+ </TextFade>
769
+ </motion.div>
770
+ )}
771
+
772
+ {/* No Animation - just RichText */}
773
+ {variation === 'no-animation' && (
774
+ <motion.div suppressHydrationWarning variants={childVariants}>
775
+ <div className={cn('p-0 flex flex-col', aniTextBoxClass, className)}>
776
+ <RichText
777
+ data={richText}
778
+ className={cn('max-w-none', aniTextClass)}
779
+ enableProse={false}
780
+ enableGutter={false}
781
+ />
782
+ </div>
783
+ </motion.div>
784
+ )}
785
+ </motion.div>
786
+ </AnimatePresence>
787
+ )
788
+ }