blocks-dusted 0.1.10 → 0.1.12

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 (249) hide show
  1. package/README.md +35 -0
  2. package/package.json +5 -2
  3. package/src/cli.js +39 -3
  4. package/src/commands/shop.js +59 -0
  5. package/src/commands/warehouse.js +73 -0
  6. package/src/utils/paths.js +13 -13
  7. package/templates/blocks/DD-Accordion/Component.tsx +229 -0
  8. package/templates/blocks/DD-Accordion/README.md +3 -0
  9. package/templates/blocks/DD-Accordion/config.ts +73 -0
  10. package/templates/blocks/DD-Accordion/manifest.json +75 -0
  11. package/templates/blocks/DD-AnimText/Component.tsx +788 -0
  12. package/templates/blocks/DD-AnimText/README.md +3 -0
  13. package/templates/blocks/DD-AnimText/config.ts +295 -0
  14. package/templates/blocks/DD-AnimText/manifest.json +85 -0
  15. package/templates/blocks/DD-AsideNav/Component.tsx +321 -0
  16. package/templates/blocks/DD-AsideNav/config.ts +204 -0
  17. package/templates/blocks/DD-AsideNav/manifest.json +80 -0
  18. package/templates/blocks/DD-Banner/Component.tsx +51 -0
  19. package/templates/blocks/DD-Banner/config.ts +57 -0
  20. package/templates/blocks/DD-Banner/manifest.json +72 -0
  21. package/templates/blocks/DD-BgLightning/Component.tsx +44 -0
  22. package/templates/blocks/DD-BgLightning/README.md +3 -0
  23. package/templates/blocks/DD-BgLightning/config.ts +97 -0
  24. package/templates/blocks/DD-BgLightning/manifest.json +79 -0
  25. package/templates/blocks/DD-BookCall/Component.tsx +535 -535
  26. package/templates/blocks/DD-BookCall/config.ts +238 -238
  27. package/templates/blocks/DD-ButtonPop/Component.tsx +117 -0
  28. package/templates/blocks/DD-ButtonPop/config.ts +105 -0
  29. package/templates/blocks/DD-ButtonPop/manifest.json +88 -0
  30. package/templates/blocks/DD-ButtonPop/svg-icons/Dust2.tsx +167 -0
  31. package/templates/blocks/DD-Card/Component.tsx +251 -0
  32. package/templates/blocks/DD-Card/README.md +4 -0
  33. package/templates/blocks/DD-Card/config.ts +154 -0
  34. package/templates/blocks/DD-Card/manifest.json +82 -0
  35. package/templates/blocks/DD-CardTemplate01/Component.tsx +140 -140
  36. package/templates/blocks/DD-CardTemplate01/config.ts +106 -106
  37. package/templates/blocks/DD-Carousel-A/Component.tsx +249 -249
  38. package/templates/blocks/DD-Carousel-B/Component.tsx +403 -403
  39. package/templates/blocks/DD-Chip/Component.tsx +250 -0
  40. package/templates/blocks/DD-Chip/EXAMPLES.md +313 -0
  41. package/templates/blocks/DD-Chip/README.md +202 -0
  42. package/templates/blocks/DD-Chip/config.ts +369 -0
  43. package/templates/blocks/DD-Chip/manifest.json +74 -0
  44. package/templates/blocks/DD-ComparisonTable/Component.tsx +256 -256
  45. package/templates/blocks/DD-Contact/Component.tsx +435 -434
  46. package/templates/blocks/DD-Contact/config.ts +22 -22
  47. package/templates/blocks/DD-Counter/Component.tsx +190 -0
  48. package/templates/blocks/DD-Counter/README.md +4 -0
  49. package/templates/blocks/DD-Counter/config.ts +291 -0
  50. package/templates/blocks/DD-Counter/manifest.json +74 -0
  51. package/templates/blocks/DD-CustomCSS/Component.tsx +8 -0
  52. package/templates/blocks/DD-CustomCSS/README.md +4 -0
  53. package/templates/blocks/DD-CustomCSS/addToLayout.md +5 -0
  54. package/templates/blocks/DD-CustomCSS/config.ts +22 -0
  55. package/templates/blocks/DD-CustomCSS/manifest.json +72 -0
  56. package/templates/blocks/DD-CustomCSS/renderCustomCSS.md +7 -0
  57. package/templates/blocks/DD-FeatCat/Component.tsx +302 -302
  58. package/templates/blocks/DD-FeatCat/config.ts +201 -201
  59. package/templates/blocks/DD-FeatStrip/Component.tsx +585 -585
  60. package/templates/blocks/DD-FeatStrip/config.ts +134 -134
  61. package/templates/blocks/DD-FluidBtn/ButtonsEyeCatching.tsx +628 -0
  62. package/templates/blocks/DD-FluidBtn/Component.tsx +43 -0
  63. package/templates/blocks/DD-FluidBtn/README.md +6 -0
  64. package/templates/blocks/DD-FluidBtn/config.ts +102 -0
  65. package/templates/blocks/DD-FluidBtn/manifest.json +86 -0
  66. package/templates/blocks/DD-GooeyInfo/Component.tsx +149 -0
  67. package/templates/blocks/DD-GooeyInfo/config.ts +135 -0
  68. package/templates/blocks/DD-GooeyInfo/manifest.json +72 -0
  69. package/templates/blocks/DD-Hero/Component.tsx +297 -297
  70. package/templates/blocks/DD-Hero/config.ts +267 -267
  71. package/templates/blocks/DD-HorizontalScroll/Component.tsx +936 -936
  72. package/templates/blocks/DD-HorizontalScroll/config.ts +231 -231
  73. package/templates/blocks/DD-Icon/Component.tsx +287 -0
  74. package/templates/blocks/DD-Icon/README.md +4 -0
  75. package/templates/blocks/DD-Icon/config.ts +258 -0
  76. package/templates/blocks/DD-Icon/hooks/revalidateBlockIds.ts +66 -0
  77. package/templates/blocks/DD-Icon/manifest.json +82 -0
  78. package/templates/blocks/DD-IconButton/Component.tsx +455 -0
  79. package/templates/blocks/DD-IconButton/README.md +326 -0
  80. package/templates/blocks/DD-IconButton/config.ts +239 -0
  81. package/templates/blocks/DD-IconButton/manifest.json +85 -0
  82. package/templates/blocks/DD-IdTag/Component.tsx +21 -0
  83. package/templates/blocks/DD-IdTag/README.md +4 -0
  84. package/templates/blocks/DD-IdTag/config.ts +41 -0
  85. package/templates/blocks/DD-IdTag/manifest.json +72 -0
  86. package/templates/blocks/DD-Iframe/Component.tsx +45 -0
  87. package/templates/blocks/DD-Iframe/README.md +4 -0
  88. package/templates/blocks/DD-Iframe/config.ts +47 -0
  89. package/templates/blocks/DD-Iframe/manifest.json +72 -0
  90. package/templates/blocks/DD-IframeMedia/Component.tsx +133 -0
  91. package/templates/blocks/DD-IframeMedia/README.md +4 -0
  92. package/templates/blocks/DD-IframeMedia/config.ts +79 -0
  93. package/templates/blocks/DD-IframeMedia/manifest.json +72 -0
  94. package/templates/blocks/DD-LineAnim/Component.tsx +36 -0
  95. package/templates/blocks/DD-LineAnim/README.md +4 -0
  96. package/templates/blocks/DD-LineAnim/config.ts +90 -0
  97. package/templates/blocks/DD-LineAnim/manifest.json +80 -0
  98. package/templates/blocks/DD-LinkGrid/Component.tsx +119 -0
  99. package/templates/blocks/DD-LinkGrid/README.md +4 -0
  100. package/templates/blocks/DD-LinkGrid/config.ts +51 -0
  101. package/templates/blocks/DD-LinkGrid/manifest.json +74 -0
  102. package/templates/blocks/DD-LogoMarq/Component.tsx +132 -0
  103. package/templates/blocks/DD-LogoMarq/README.md +4 -0
  104. package/templates/blocks/DD-LogoMarq/config.ts +264 -0
  105. package/templates/blocks/DD-LogoMarq/manifest.json +82 -0
  106. package/templates/blocks/DD-Lottie/Component.tsx +459 -0
  107. package/templates/blocks/DD-Lottie/README.md +4 -0
  108. package/templates/blocks/DD-Lottie/config.ts +379 -0
  109. package/templates/blocks/DD-Lottie/index.tsx +28 -0
  110. package/templates/blocks/DD-Lottie/manifest.json +83 -0
  111. package/templates/blocks/DD-MagicBento/Component.tsx +777 -0
  112. package/templates/blocks/DD-MagicBento/README.md +4 -0
  113. package/templates/blocks/DD-MagicBento/config.ts +264 -0
  114. package/templates/blocks/DD-MagicBento/manifest.json +74 -0
  115. package/templates/blocks/DD-MasonaryMedia/Component.tsx +545 -545
  116. package/templates/blocks/DD-MasonaryMedia/config.ts +2 -2
  117. package/templates/blocks/DD-MasonaryMedia/vendor.d.ts +2 -2
  118. package/templates/blocks/DD-Masonry/Component.tsx +645 -0
  119. package/templates/blocks/DD-Masonry/README.md +4 -0
  120. package/templates/blocks/DD-Masonry/config.ts +475 -0
  121. package/templates/blocks/DD-Masonry/manifest.json +82 -0
  122. package/templates/blocks/DD-Pricing/Component.tsx +2 -5
  123. package/templates/blocks/DD-Process/Component.tsx +2 -4
  124. package/templates/blocks/DD-Process/config.ts +150 -150
  125. package/templates/blocks/DD-Progress/Component.tsx +156 -0
  126. package/templates/blocks/DD-Progress/README.md +4 -0
  127. package/templates/blocks/DD-Progress/config.ts +175 -0
  128. package/templates/blocks/DD-Progress/manifest.json +74 -0
  129. package/templates/blocks/DD-ProjHeader/Component.tsx +91 -0
  130. package/templates/blocks/DD-ProjHeader/README.md +4 -0
  131. package/templates/blocks/DD-ProjHeader/config.ts +96 -0
  132. package/templates/blocks/DD-ProjHeader/manifest.json +72 -0
  133. package/templates/blocks/DD-ProjSlider/Component.tsx +123 -0
  134. package/templates/blocks/DD-ProjSlider/README.md +4 -0
  135. package/templates/blocks/DD-ProjSlider/config.ts +64 -0
  136. package/templates/blocks/DD-ProjSlider/manifest.json +72 -0
  137. package/templates/blocks/DD-ScrollText/Component.tsx +114 -0
  138. package/templates/blocks/DD-ScrollText/README.md +4 -0
  139. package/templates/blocks/DD-ScrollText/config.ts +58 -0
  140. package/templates/blocks/DD-ScrollText/manifest.json +72 -0
  141. package/templates/blocks/DD-Section/Component.tsx +266 -266
  142. package/templates/blocks/DD-Separator/Component.tsx +66 -0
  143. package/templates/blocks/DD-Separator/README.md +4 -0
  144. package/templates/blocks/DD-Separator/config.ts +58 -0
  145. package/templates/blocks/DD-Separator/manifest.json +72 -0
  146. package/templates/blocks/DD-Services/Component.tsx +176 -176
  147. package/templates/blocks/DD-Services/config.ts +149 -149
  148. package/templates/blocks/DD-ShowcaseGrid/Component.tsx +307 -307
  149. package/templates/blocks/DD-Slider-A/Component.tsx +1 -1
  150. package/templates/blocks/DD-StackCards/Component.tsx +1 -1
  151. package/templates/blocks/DD-StackCards/config.ts +399 -399
  152. package/templates/blocks/DD-Team/Component.tsx +247 -247
  153. package/templates/blocks/DD-Team/config.ts +173 -173
  154. package/templates/blocks/DD-TeamCards/Component.tsx +251 -0
  155. package/templates/blocks/DD-TeamCards/README.md +4 -0
  156. package/templates/blocks/DD-TeamCards/config.ts +302 -0
  157. package/templates/blocks/DD-TeamCards/manifest.json +74 -0
  158. package/templates/blocks/DD-TechStack/Component.tsx +174 -174
  159. package/templates/blocks/DD-TechStack/config.ts +153 -153
  160. package/templates/blocks/DD-TestMarq/Component.tsx +132 -0
  161. package/templates/blocks/DD-TestMarq/README.md +4 -0
  162. package/templates/blocks/DD-TestMarq/RowLabel.tsx +9 -0
  163. package/templates/blocks/DD-TestMarq/config.ts +88 -0
  164. package/templates/blocks/DD-TestMarq/manifest.json +72 -0
  165. package/templates/blocks/DD-Testim/Component.tsx +247 -0
  166. package/templates/blocks/DD-Testim/README.md +4 -0
  167. package/templates/blocks/DD-Testim/config.ts +101 -0
  168. package/templates/blocks/DD-Testim/manifest.json +75 -0
  169. package/templates/blocks/DD-Testim2/Component.tsx +256 -0
  170. package/templates/blocks/DD-Testim2/README.md +4 -0
  171. package/templates/blocks/DD-Testim2/config.ts +100 -0
  172. package/templates/blocks/DD-Testim2/manifest.json +74 -0
  173. package/templates/blocks/DD-Testimonials/Component.tsx +139 -147
  174. package/templates/blocks/DD-Testimonials/config.ts +120 -120
  175. package/templates/blocks/DD-TextMarq/Component.tsx +157 -0
  176. package/templates/blocks/DD-TextMarq/README.md +4 -0
  177. package/templates/blocks/DD-TextMarq/config.ts +237 -0
  178. package/templates/blocks/DD-TextMarq/manifest.json +82 -0
  179. package/templates/blocks/DD-Thanks/Component.tsx +501 -0
  180. package/templates/blocks/DD-Thanks/README.md +4 -0
  181. package/templates/blocks/DD-Thanks/config.ts +224 -0
  182. package/templates/blocks/DD-Thanks/manifest.json +72 -0
  183. package/templates/blocks/DD-VertMarq/Component.tsx +154 -0
  184. package/templates/blocks/DD-VertMarq/README.md +4 -0
  185. package/templates/blocks/DD-VertMarq/config.ts +236 -0
  186. package/templates/blocks/DD-VertMarq/dist/index.css +6 -0
  187. package/templates/blocks/DD-VertMarq/dist/index.min.css +1 -0
  188. package/templates/blocks/DD-VertMarq/manifest.json +74 -0
  189. package/templates/blocks/DD-Work/Component.tsx +318 -315
  190. package/templates/blocks/DD-Work/config.ts +165 -165
  191. package/templates/blocks/DD-Work-B/Component.tsx +294 -294
  192. package/templates/blocks/DDHG-CTASection2/Component.tsx +185 -0
  193. package/templates/blocks/DDHG-CTASection2/config.ts +140 -0
  194. package/templates/blocks/DDHG-CTASection2/manifest.json +45 -0
  195. package/templates/blocks/DDHG-HighlightArc/Component.tsx +243 -0
  196. package/templates/blocks/DDHG-HighlightArc/config.ts +85 -0
  197. package/templates/blocks/DDHG-HighlightArc/manifest.json +46 -0
  198. package/templates/blocks/DDHG-LogoMarquee/Component.tsx +143 -0
  199. package/templates/blocks/DDHG-LogoMarquee/config.ts +154 -0
  200. package/templates/blocks/DDHG-LogoMarquee/manifest.json +39 -0
  201. package/templates/blocks/DDHG-NavCodeGrid/Component.tsx +227 -0
  202. package/templates/blocks/DDHG-NavCodeGrid/config.ts +64 -0
  203. package/templates/blocks/DDHG-NavCodeGrid/manifest.json +45 -0
  204. package/templates/blocks/DDHG-ProcessSec/Component.tsx +574 -0
  205. package/templates/blocks/DDHG-ProcessSec/config.ts +170 -0
  206. package/templates/blocks/DDHG-ProcessSec/manifest.json +56 -0
  207. package/templates/blocks/DDHG-ServiceDetails/Component.tsx +164 -0
  208. package/templates/blocks/DDHG-ServiceDetails/ServiceDetailCard.tsx +390 -0
  209. package/templates/blocks/DDHG-ServiceDetails/config.ts +77 -0
  210. package/templates/blocks/DDHG-ServiceDetails/manifest.json +50 -0
  211. package/templates/blocks/DDHG-ServiceHero/Component.tsx +234 -0
  212. package/templates/blocks/DDHG-ServiceHero/config.ts +49 -0
  213. package/templates/blocks/DDHG-ServiceHero/manifest.json +26 -0
  214. package/templates/blocks/DDHG-ServiceOverview/Component.tsx +277 -0
  215. package/templates/blocks/DDHG-ServiceOverview/config.ts +64 -0
  216. package/templates/blocks/DDHG-ServiceOverview/manifest.json +44 -0
  217. package/templates/blocks/DDHG-StatsFAQ/Component.tsx +389 -0
  218. package/templates/blocks/DDHG-StatsFAQ/config.ts +204 -0
  219. package/templates/blocks/DDHG-StatsFAQ/manifest.json +45 -0
  220. package/templates/blocks/DDHG-TeamCards/Component.tsx +169 -0
  221. package/templates/blocks/DDHG-TeamCards/config.ts +48 -0
  222. package/templates/blocks/DDHG-TeamCards/manifest.json +29 -0
  223. package/templates/shared/src/components/BgLightning/index.tsx +242 -0
  224. package/templates/shared/src/components/ui/ShareButton/index.tsx +80 -0
  225. package/templates/shared/src/components/ui/anims/FadeOnScroll.tsx +48 -0
  226. package/templates/shared/src/components/ui/anims/FadeUpOnInView.tsx +63 -0
  227. package/templates/shared/src/components/ui/anims/GlareHover.tsx +111 -0
  228. package/templates/shared/src/components/ui/anims/LineAnims.tsx +81 -0
  229. package/templates/shared/src/components/ui/anims/TitleAnims01.tsx +54 -0
  230. package/templates/shared/src/components/ui/anims/animation-container.tsx +29 -0
  231. package/templates/shared/src/components/ui/anims/blur-in.tsx +26 -0
  232. package/templates/shared/src/components/ui/anims/counter.tsx +53 -0
  233. package/templates/shared/src/components/ui/anims/fade.tsx +83 -0
  234. package/templates/shared/src/components/ui/anims/gradual-spacing.tsx +39 -0
  235. package/templates/shared/src/components/ui/anims/pull-up.tsx +93 -0
  236. package/templates/shared/src/components/ui/anims/reveal-text.tsx +76 -0
  237. package/templates/shared/src/components/ui/anims/rotate-words.tsx +43 -0
  238. package/templates/shared/src/components/ui/anims/shiny-text.tsx +58 -0
  239. package/templates/shared/src/components/ui/anims/shuffle-text.tsx +85 -0
  240. package/templates/shared/src/components/ui/anims/split-text.tsx +211 -0
  241. package/templates/shared/src/components/ui/anims/staggered-fade.tsx +133 -0
  242. package/templates/shared/src/components/ui/anims/text-scroll.tsx +111 -0
  243. package/templates/shared/src/components/ui/anims/typing-effect.tsx +112 -0
  244. package/templates/shared/src/components/ui/button-dusted-fluid/index.tsx +1521 -0
  245. package/templates/shared/src/components/ui/separator.tsx +85 -0
  246. package/templates/shared/src/hooks/useBodyScrollLock.ts +97 -0
  247. package/templates/shared/src/hooks/useClickOutside.ts +28 -0
  248. package/templates/shared/src/utilities/renderCustomCSS.ts +5 -0
  249. package/templates/shared/src/utilities/smoothScroll.ts +65 -0
@@ -0,0 +1,169 @@
1
+ 'use client'
2
+
3
+ import { useEffect, useRef } from 'react'
4
+ import Image from 'next/image'
5
+ import Link from 'next/link'
6
+ import { Globe, Briefcase, Camera } from 'lucide-react'
7
+ import { cn } from '@/utilities/ui'
8
+ import { getMediaUrl } from '@/utilities/getMediaUrl'
9
+
10
+ type MediaDoc = {
11
+ url?: string | null
12
+ alt?: string | null
13
+ }
14
+
15
+ type TeamMember = {
16
+ name?: string | null
17
+ role?: string | null
18
+ bio?: string | null
19
+ image?: number | MediaDoc | null
20
+ priority?: boolean | null
21
+ facebookUrl?: string | null
22
+ linkedinUrl?: string | null
23
+ instagramUrl?: string | null
24
+ id?: string | null
25
+ }
26
+
27
+ export type DDHGTeamCardsProps = {
28
+ sectionId?: string | null
29
+ customClassName?: string | null
30
+ customCSS?: string | null
31
+ members?: TeamMember[] | null
32
+ }
33
+
34
+ function getMediaDoc(img?: number | MediaDoc | null): MediaDoc | null {
35
+ if (!img || typeof img === 'number') return null
36
+ return img
37
+ }
38
+
39
+ export const DDHGTeamCards: React.FC<DDHGTeamCardsProps> = ({
40
+ sectionId,
41
+ customClassName,
42
+ customCSS,
43
+ members,
44
+ }) => {
45
+ const ref = useRef<HTMLDivElement>(null)
46
+
47
+ useEffect(() => {
48
+ const observer = new IntersectionObserver(
49
+ (entries) => {
50
+ entries.forEach((entry) => {
51
+ if (entry.isIntersecting) {
52
+ entry.target.querySelectorAll<HTMLElement>('.reveal').forEach((el, i) => {
53
+ setTimeout(() => {
54
+ el.style.opacity = '1'
55
+ el.style.transform = 'translateY(0)'
56
+ }, i * 100)
57
+ })
58
+ observer.unobserve(entry.target)
59
+ }
60
+ })
61
+ },
62
+ { threshold: 0.1 },
63
+ )
64
+ if (ref.current) observer.observe(ref.current)
65
+ return () => observer.disconnect()
66
+ }, [])
67
+
68
+ return (
69
+ <div id={sectionId ?? undefined} className={cn('px-5 md:px-8 py-8', customClassName)} ref={ref}>
70
+ {customCSS && <style dangerouslySetInnerHTML={{ __html: customCSS }} />}
71
+ <div className="max-w-7xl mx-auto">
72
+ {members && members.length > 0 && (
73
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5 md:gap-6">
74
+ {members.map((member, i) => {
75
+ const imageDoc = getMediaDoc(member.image)
76
+ const imageUrl = getMediaUrl(imageDoc?.url)
77
+ const socials = [
78
+ { Icon: Globe, url: member.facebookUrl, label: 'Facebook' },
79
+ { Icon: Briefcase, url: member.linkedinUrl, label: 'LinkedIn' },
80
+ { Icon: Camera, url: member.instagramUrl, label: 'Instagram' },
81
+ ].filter((s) => !!s.url)
82
+
83
+ return (
84
+ <div
85
+ key={member.id != null ? `id-${member.id}` : `idx-${i}`}
86
+ className="reveal group relative overflow-hidden cursor-pointer rounded-md squircle border-none border-stone-300/0 bg-stone-100/50 transition-all duration-300 hover:shadow-2xl dark:border-stone-700/0 dark:bg-stone-900/50 h-112 md:h-128"
87
+ style={{
88
+ opacity: 0,
89
+ transform: 'translateY(20px)',
90
+ transition: `opacity 0.9s ease ${i * 0.1}s, transform 0.9s ease ${i * 0.1}s`,
91
+ }}
92
+ >
93
+ {imageDoc && imageUrl && (
94
+ <div className="relative w-full h-full overflow-hidden brightness-100 group-hover:brightness-50 transition-all duration-300">
95
+ <Image
96
+ src={imageUrl}
97
+ alt={imageDoc.alt ?? member.name ?? ''}
98
+ fill
99
+ sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
100
+ priority={Boolean(member.priority)}
101
+ className="team-member object-cover object-top brightness-100 group-hover:brightness-50 group-hover:scale-110 transition-transform duration-500 ease-out"
102
+ />
103
+ </div>
104
+ )}
105
+ <div
106
+ className="pattern-overlay absolute inset-0 opacity-[0.03] pointer-events-none"
107
+ style={{
108
+ backgroundImage:
109
+ 'repeating-linear-gradient(90deg, #000 0px, #000 1px, transparent 1px, transparent 20px)',
110
+ }}
111
+ />
112
+ <div className="gradient-overlay absolute inset-0 bg-linear-to-t from-black/80 via-black/80 to-transparent group-hover:from-black/90 transition-all duration-300 group-hover:backdrop-brightness-50" />
113
+ <div className="content-card absolute inset-0 flex flex-col justify-end p-3 text-white">
114
+ <div className="z-10 text-center mb-3">
115
+ {member.name && (
116
+ <h3
117
+ className="text-xl md:text-2xl font-bold mb-1 text-white drop-shadow-lg"
118
+ style={{ fontFamily: 'Outfit, sans-serif', fontWeight: 700 }}
119
+ >
120
+ {member.name}
121
+ </h3>
122
+ )}
123
+ {member.role && (
124
+ <p
125
+ className="text-xs md:text-sm font-medium uppercase tracking-wider text-stone-200 dark:text-stone-200 drop-shadow-md"
126
+ style={{ fontFamily: "'Inter', sans-serif", fontWeight: 500 }}
127
+ >
128
+ {member.role}
129
+ </p>
130
+ )}
131
+ </div>
132
+ <div
133
+ className="hover-panel transform translate-y-full group-hover:translate-y-0 transition-transform duration-300 ease-out p-4"
134
+ style={{ background: 'rgba(0,0,0,0.4)', backdropFilter: 'blur(8px)' }}
135
+ >
136
+ {member.bio && (
137
+ <p className="text-sm text-white/70 leading-relaxed mb-4 opacity-0 group-hover:opacity-100 transition-all duration-300 delay-100">
138
+ {member.bio}
139
+ </p>
140
+ )}
141
+ {socials.length > 0 && (
142
+ <div className="socials-map flex gap-3 justify-center opacity-0 group-hover:opacity-100 transition-all duration-300 delay-200">
143
+ {socials.map(({ Icon, url, label }) => (
144
+ <Link
145
+ key={label}
146
+ href={url!}
147
+ target="_blank"
148
+ rel="noopener noreferrer"
149
+ aria-label={`${member.name} on ${label}`}
150
+ className="text-white/70 hover:text-white hover:scale-110 transition-all duration-200 p-2 rounded-full bg-white/10 hover:bg-white/20 backdrop-blur-sm"
151
+ >
152
+ <Icon size={14} />
153
+ </Link>
154
+ ))}
155
+ </div>
156
+ )}
157
+ </div>
158
+ </div>
159
+ </div>
160
+ )
161
+ })}
162
+ </div>
163
+ )}
164
+ </div>
165
+ </div>
166
+ )
167
+ }
168
+
169
+ export default DDHGTeamCards
@@ -0,0 +1,48 @@
1
+ import type { Block } from 'payload'
2
+
3
+ export const DDHGTeamCards: Block = {
4
+ slug: 'DDHG-TeamCards',
5
+ interfaceName: 'DDHGTeamCards',
6
+ labels: { singular: 'Team Cards', plural: 'Team Cards' },
7
+ fields: [
8
+ {
9
+ type: 'tabs',
10
+ tabs: [
11
+ {
12
+ label: 'Team Members',
13
+ fields: [
14
+ {
15
+ name: 'members',
16
+ type: 'array',
17
+ label: 'Team Members',
18
+ fields: [
19
+ { type: 'row', fields: [
20
+ { name: 'name', type: 'text', label: 'Name', required: true, admin: { width: '50%' } },
21
+ { name: 'role', type: 'text', label: 'Role / Title', admin: { width: '50%' } },
22
+ ] },
23
+ { name: 'bio', type: 'textarea', label: 'Bio (shown on hover)' },
24
+ { name: 'image', type: 'upload', relationTo: 'media', label: 'Photo' },
25
+ { name: 'priority', type: 'checkbox', label: 'High Priority', defaultValue: false, admin: { description: 'Enable for above-the-fold media.' } },
26
+ { type: 'row', fields: [
27
+ { name: 'linkedinUrl', type: 'text', label: 'LinkedIn URL', admin: { width: '33%' } },
28
+ { name: 'instagramUrl', type: 'text', label: 'Instagram URL', admin: { width: '33%' } },
29
+ { name: 'facebookUrl', type: 'text', label: 'Facebook URL', admin: { width: '33%' } },
30
+ ] },
31
+ ],
32
+ },
33
+ ],
34
+ },
35
+ {
36
+ label: 'Advanced',
37
+ fields: [
38
+ { type: 'row', fields: [
39
+ { name: 'sectionId', type: 'text', label: 'Section ID', admin: { width: '50%', description: 'Optional anchor ID' } },
40
+ { name: 'customClassName', type: 'text', label: 'Custom CSS Classes', admin: { width: '50%' } },
41
+ ] },
42
+ { name: 'customCSS', type: 'code', label: 'Custom CSS', admin: { language: 'css', description: 'Injected as a <style> tag. Use with caution.' } },
43
+ ],
44
+ },
45
+ ],
46
+ },
47
+ ],
48
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "type": "block",
3
+ "name": "DDHG-TeamCards",
4
+ "label": "Team Cards",
5
+ "sourceName": "TeamCards",
6
+ "portableName": "DDHG-TeamCards",
7
+ "slug": "DDHG-TeamCards",
8
+ "version": "0.0.1",
9
+ "source": { "repo": "Hadizainal/HeatherGrey2025", "originalPath": "src/blocks/TeamCards", "originalSlug": "teamCards", "originalConfigExport": "TeamCards", "originalComponentExport": "TeamCardsBlock", "originalInterfaceName": "TeamCardsBlockProps" },
10
+ "files": [
11
+ { "from": "Component.tsx", "to": "src/blocks/DDHG-TeamCards/Component.tsx" },
12
+ { "from": "config.ts", "to": "src/blocks/DDHG-TeamCards/config.ts" }
13
+ ],
14
+ "dependencies": [{ "name": "lucide-react" }],
15
+ "sharedFiles": [],
16
+ "requiredProjectFiles": [
17
+ { "path": "src/utilities/ui.ts", "reason": "Component uses the cn utility." },
18
+ { "path": "src/utilities/getMediaUrl.ts", "reason": "Component resolves media URLs through getMediaUrl." }
19
+ ],
20
+ "optionalProjectFiles": [],
21
+ "collectionRegistration": { "enabled": true, "collections": ["Pages", "Posts"] },
22
+ "renderBlocksRegistration": { "enabled": true },
23
+ "renderBlocksBehavior": { "wrapperless": false },
24
+ "pageRouteIntegration": { "required": false, "manualSteps": [] },
25
+ "manualSteps": ["Run payload generate:types after schema changes."],
26
+ "notes": ["Converted from HeatherGrey2025 TeamCards.", "Generated Payload media type dependency replaced with a local structural type.", "Priority loading now follows each member row's priority field.", "Installer must not overwrite existing target files."],
27
+ "exportName": "DDHGTeamCards",
28
+ "interfaceName": "DDHGTeamCards"
29
+ }
@@ -0,0 +1,242 @@
1
+ 'use client'
2
+
3
+ import React, { useRef, useEffect } from 'react'
4
+
5
+ interface BgLightningProps {
6
+ hue?: number
7
+ xOffset?: number
8
+ speed?: number
9
+ intensity?: number
10
+ size?: number
11
+ }
12
+
13
+ const BgLightning: React.FC<BgLightningProps> = ({
14
+ hue = 230,
15
+ xOffset = 0,
16
+ speed = 1,
17
+ intensity = 1,
18
+ size = 1
19
+ }) => {
20
+ const canvasRef = useRef<HTMLCanvasElement>(null)
21
+
22
+ useEffect(() => {
23
+ const canvas = canvasRef.current
24
+ if (!canvas) return
25
+
26
+ let frameId = 0
27
+ let disposed = false
28
+
29
+ const gl = canvas.getContext('webgl', {
30
+ alpha: true,
31
+ premultipliedAlpha: false
32
+ })
33
+
34
+ if (!gl) {
35
+ console.error('WebGL not supported')
36
+ return
37
+ }
38
+
39
+ const resizeCanvas = () => {
40
+ const width = canvas.clientWidth
41
+ const height = canvas.clientHeight
42
+
43
+ if (canvas.width !== width || canvas.height !== height) {
44
+ canvas.width = width
45
+ canvas.height = height
46
+ }
47
+ }
48
+
49
+ resizeCanvas()
50
+ window.addEventListener('resize', resizeCanvas)
51
+
52
+ const vertexShaderSource = `
53
+ attribute vec2 aPosition;
54
+
55
+ void main() {
56
+ gl_Position = vec4(aPosition, 0.0, 1.0);
57
+ }
58
+ `
59
+
60
+ const fragmentShaderSource = `
61
+ precision mediump float;
62
+
63
+ uniform vec2 iResolution;
64
+ uniform float iTime;
65
+ uniform float uHue;
66
+ uniform float uXOffset;
67
+ uniform float uSpeed;
68
+ uniform float uIntensity;
69
+ uniform float uSize;
70
+
71
+ #define OCTAVE_COUNT 10
72
+
73
+ vec3 hsv2rgb(vec3 c) {
74
+ vec3 rgb = clamp(abs(mod(c.x * 6.0 + vec3(0.0,4.0,2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0);
75
+ return c.z * mix(vec3(1.0), rgb, c.y);
76
+ }
77
+
78
+ float hash11(float p) {
79
+ p = fract(p * .1031);
80
+ p *= p + 33.33;
81
+ p *= p + p;
82
+ return fract(p);
83
+ }
84
+
85
+ float hash12(vec2 p) {
86
+ vec3 p3 = fract(vec3(p.xyx) * .1031);
87
+ p3 += dot(p3, p3.yzx + 33.33);
88
+ return fract((p3.x + p3.y) * p3.z);
89
+ }
90
+
91
+ mat2 rotate2d(float theta) {
92
+ float c = cos(theta);
93
+ float s = sin(theta);
94
+ return mat2(c, -s, s, c);
95
+ }
96
+
97
+ float noise(vec2 p) {
98
+ vec2 ip = floor(p);
99
+ vec2 fp = fract(p);
100
+
101
+ float a = hash12(ip);
102
+ float b = hash12(ip + vec2(1.0, 0.0));
103
+ float c = hash12(ip + vec2(0.0, 1.0));
104
+ float d = hash12(ip + vec2(1.0, 1.0));
105
+
106
+ vec2 t = smoothstep(0.0, 1.0, fp);
107
+
108
+ return mix(mix(a, b, t.x), mix(c, d, t.x), t.y);
109
+ }
110
+
111
+ float fbm(vec2 p) {
112
+ float value = 0.0;
113
+ float amplitude = 0.5;
114
+
115
+ for (int i = 0; i < OCTAVE_COUNT; ++i) {
116
+ value += amplitude * noise(p);
117
+ p *= rotate2d(0.45);
118
+ p *= 2.0;
119
+ amplitude *= 0.5;
120
+ }
121
+
122
+ return value;
123
+ }
124
+
125
+ void mainImage(out vec4 fragColor, in vec2 fragCoord) {
126
+ vec2 uv = fragCoord / iResolution.xy;
127
+ uv = 2.0 * uv - 1.0;
128
+ uv.x *= iResolution.x / iResolution.y;
129
+ uv.x += uXOffset;
130
+
131
+ uv += 2.0 * fbm(uv * uSize + 0.8 * iTime * uSpeed) - 1.0;
132
+
133
+ float dist = max(abs(uv.x), 0.001);
134
+ vec3 baseColor = hsv2rgb(vec3(uHue / 360.0, 0.7, 0.8));
135
+ vec3 col = baseColor * pow(mix(0.0, 0.07, hash11(iTime * uSpeed)) / dist, 1.0) * uIntensity;
136
+
137
+ float a = clamp(max(col.r, max(col.g, col.b)), 0.0, 1.0);
138
+ fragColor = vec4(col, a);
139
+ }
140
+
141
+ void main() {
142
+ mainImage(gl_FragColor, gl_FragCoord.xy);
143
+ }
144
+ `
145
+
146
+ const compileShader = (source: string, type: number) => {
147
+ const shader = gl.createShader(type)
148
+ if (!shader) return null
149
+
150
+ gl.shaderSource(shader, source)
151
+ gl.compileShader(shader)
152
+
153
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
154
+ console.error('Shader compile error:', gl.getShaderInfoLog(shader))
155
+ gl.deleteShader(shader)
156
+ return null
157
+ }
158
+
159
+ return shader
160
+ }
161
+
162
+ const vertexShader = compileShader(vertexShaderSource, gl.VERTEX_SHADER)
163
+ const fragmentShader = compileShader(fragmentShaderSource, gl.FRAGMENT_SHADER)
164
+
165
+ if (!vertexShader || !fragmentShader) return
166
+
167
+ const program = gl.createProgram()
168
+ if (!program) return
169
+
170
+ gl.attachShader(program, vertexShader)
171
+ gl.attachShader(program, fragmentShader)
172
+ gl.linkProgram(program)
173
+
174
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
175
+ console.error('Program linking error:', gl.getProgramInfoLog(program))
176
+ gl.deleteProgram(program)
177
+ return
178
+ }
179
+
180
+ const vertices = new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1])
181
+
182
+ const vertexBuffer = gl.createBuffer()
183
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
184
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
185
+
186
+ const aPosition = gl.getAttribLocation(program, 'aPosition')
187
+
188
+ if (aPosition >= 0) {
189
+ gl.useProgram(program)
190
+ gl.enableVertexAttribArray(aPosition)
191
+ gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0)
192
+ }
193
+
194
+ const iResolutionLocation = gl.getUniformLocation(program, 'iResolution')
195
+ const iTimeLocation = gl.getUniformLocation(program, 'iTime')
196
+ const uHueLocation = gl.getUniformLocation(program, 'uHue')
197
+ const uXOffsetLocation = gl.getUniformLocation(program, 'uXOffset')
198
+ const uSpeedLocation = gl.getUniformLocation(program, 'uSpeed')
199
+ const uIntensityLocation = gl.getUniformLocation(program, 'uIntensity')
200
+ const uSizeLocation = gl.getUniformLocation(program, 'uSize')
201
+
202
+ const startTime = performance.now()
203
+
204
+ const render = () => {
205
+ if (disposed) return
206
+
207
+ resizeCanvas()
208
+
209
+ gl.useProgram(program)
210
+ gl.viewport(0, 0, canvas.width, canvas.height)
211
+
212
+ if (iResolutionLocation) gl.uniform2f(iResolutionLocation, canvas.width, canvas.height)
213
+ if (iTimeLocation) gl.uniform1f(iTimeLocation, (performance.now() - startTime) / 1000)
214
+ if (uHueLocation) gl.uniform1f(uHueLocation, hue)
215
+ if (uXOffsetLocation) gl.uniform1f(uXOffsetLocation, xOffset)
216
+ if (uSpeedLocation) gl.uniform1f(uSpeedLocation, speed)
217
+ if (uIntensityLocation) gl.uniform1f(uIntensityLocation, intensity)
218
+ if (uSizeLocation) gl.uniform1f(uSizeLocation, size)
219
+
220
+ gl.drawArrays(gl.TRIANGLES, 0, 6)
221
+
222
+ frameId = requestAnimationFrame(render)
223
+ }
224
+
225
+ frameId = requestAnimationFrame(render)
226
+
227
+ return () => {
228
+ disposed = true
229
+ cancelAnimationFrame(frameId)
230
+ window.removeEventListener('resize', resizeCanvas)
231
+
232
+ gl.deleteBuffer(vertexBuffer)
233
+ gl.deleteShader(vertexShader)
234
+ gl.deleteShader(fragmentShader)
235
+ gl.deleteProgram(program)
236
+ }
237
+ }, [hue, xOffset, speed, intensity, size])
238
+
239
+ return <canvas ref={canvasRef} className="relative h-full w-full" />
240
+ }
241
+
242
+ export default BgLightning
@@ -0,0 +1,80 @@
1
+ 'use client'
2
+
3
+ import React, { useState } from 'react'
4
+ import { LucideIcon } from 'lucide-react'
5
+
6
+ import { cn } from '@/utilities/ui'
7
+ import { Button } from '@/components/ui/button'
8
+
9
+ interface ShareLink {
10
+ icon: LucideIcon
11
+ href?: string
12
+ onClick?: () => void
13
+ label?: string
14
+ }
15
+
16
+ interface ShareButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
17
+ links: ShareLink[]
18
+ children: React.ReactNode
19
+ }
20
+
21
+ export const ShareButton = ({ className, links, children, ...props }: ShareButtonProps) => {
22
+ const [isHovered, setIsHovered] = useState(false)
23
+
24
+ return (
25
+ <div
26
+ className="relative"
27
+ onMouseEnter={() => setIsHovered(true)}
28
+ onMouseLeave={() => setIsHovered(false)}
29
+ >
30
+ <Button
31
+ className={cn(
32
+ 'relative min-w-40 rounded-3xl ',
33
+ 'bg-white dark:bg-black',
34
+ 'hover:bg-gray-50 dark:hover:bg-gray-950',
35
+ 'text-stone-200 dark:text-stone-200',
36
+ 'border border-black/10 dark:border-white/10',
37
+ 'transition-all duration-300',
38
+ isHovered ? 'opacity-0' : 'opacity-100',
39
+ className
40
+ )}
41
+ {...props}
42
+ >
43
+ <span className="flex items-center gap-2">{children}</span>
44
+ </Button>
45
+
46
+ <div className="absolute left-0 top-0 flex h-10">
47
+ {links.map((link, index) => {
48
+ const Icon = link.icon
49
+ return (
50
+ <button
51
+ type="button"
52
+ key={index}
53
+ onClick={link.onClick}
54
+ className={cn(
55
+ 'h-10',
56
+ 'w-10',
57
+ 'flex items-center justify-center',
58
+ 'bg-black dark:bg-white',
59
+ 'text-white dark:text-black',
60
+ 'transition-all duration-300',
61
+ index === 0 && 'rounded-l-3xl',
62
+ index === links.length - 1 && 'rounded-r-3xl',
63
+ 'border-r border-white/10 last:border-r-0 dark:border-black/10',
64
+ 'hover:bg-gray-900 dark:hover:bg-gray-100',
65
+ '',
66
+ isHovered ? 'translate-x-0 opacity-100' : '-translate-x-full opacity-0',
67
+ index === 0 && 'transition-all duration-200',
68
+ index === 1 && 'delay-\\[50ms\\] transition-all duration-200',
69
+ index === 2 && 'transition-all delay-100 duration-200',
70
+ index === 3 && 'transition-all delay-150 duration-200'
71
+ )}
72
+ >
73
+ <Icon className="size-4" />
74
+ </button>
75
+ )
76
+ })}
77
+ </div>
78
+ </div>
79
+ )
80
+ }
@@ -0,0 +1,48 @@
1
+ 'use client'
2
+
3
+ import React, { useEffect, useRef, useState } from 'react'
4
+ import { motion, useScroll, useTransform } from 'framer-motion'
5
+
6
+ interface FadeOnScrollProps {
7
+ children: React.ReactNode
8
+ }
9
+
10
+ export const FadeOnScroll: React.FC<FadeOnScrollProps> = ({ children }) => {
11
+ const containerRef = useRef<HTMLDivElement>(null)
12
+ const [targetRef, setTargetRef] = useState<HTMLElement | null>(null)
13
+
14
+ // Bind scroll tracking only when ready
15
+ const scrollSetupRef = useRef(false)
16
+ const { scrollYProgress } = useScroll({
17
+ target: targetRef ? { current: targetRef } : undefined,
18
+ offset: ['start 50%', 'start 0%'],
19
+ })
20
+
21
+ const opacity = useTransform(scrollYProgress, [0, 1], [1, 0])
22
+
23
+ useEffect(() => {
24
+ if (typeof window === 'undefined') return
25
+
26
+ const container = containerRef.current
27
+ if (!container) return
28
+
29
+ const parent = container.closest('.renderblock-container')
30
+ if (!parent) return
31
+
32
+ let sibling = parent.nextElementSibling as HTMLElement | null
33
+ while (sibling && !sibling.classList.contains('renderblock-container')) {
34
+ sibling = sibling.nextElementSibling as HTMLElement | null
35
+ }
36
+
37
+ if (sibling && !scrollSetupRef.current) {
38
+ setTargetRef(sibling)
39
+ scrollSetupRef.current = true
40
+ }
41
+ }, [])
42
+
43
+ return (
44
+ <motion.div ref={containerRef} style={{ opacity }}>
45
+ {children}
46
+ </motion.div>
47
+ )
48
+ }
@@ -0,0 +1,63 @@
1
+ 'use client'
2
+ import React, { useRef, useEffect, useState, ReactNode } from 'react'
3
+ import { motion } from 'framer-motion'
4
+ import { cn } from '@/utilities/ui'
5
+
6
+ interface FadeUpOnInViewProps {
7
+ children: ReactNode
8
+ delay?: number
9
+ className?: string
10
+ }
11
+
12
+ export const FadeUpOnInView: React.FC<FadeUpOnInViewProps> = ({ children, delay, className }) => {
13
+ const ref = useRef<HTMLDivElement | null>(null)
14
+ const [isVisible, setIsVisible] = useState(false)
15
+
16
+ useEffect(() => {
17
+ if (!ref.current) return
18
+ const target = ref.current
19
+ const observer = new IntersectionObserver(
20
+ (entries) => {
21
+ if (entries && entries.length > 0 && entries[0]) {
22
+ setIsVisible(!!entries[0].isIntersecting)
23
+ }
24
+ },
25
+ {
26
+ root: null,
27
+ rootMargin: '0px',
28
+ threshold: 0.5
29
+ }
30
+ )
31
+ observer.observe(target)
32
+ return () => {
33
+ observer.disconnect()
34
+ }
35
+ }, [])
36
+
37
+ // Defensive: Only allow number and >= 0 for delay
38
+ const animationDelay = typeof delay === 'number' && !isNaN(delay) && delay >= 0 ? delay : 0
39
+
40
+ // Defensive: Only render children if defined
41
+ const safeChildren = children === undefined || children === null ? null : children
42
+
43
+ return (
44
+ <motion.div
45
+ className={cn('fadeupInView', className)}
46
+ ref={ref}
47
+ initial={{ opacity: 0, y: 40 }}
48
+ animate={{
49
+ opacity: isVisible ? 1 : 0,
50
+ y: isVisible ? 0 : 40
51
+ }}
52
+ exit={{ opacity: 0, y: 40 }}
53
+ transition={{
54
+ duration: 0.3,
55
+ delay: animationDelay
56
+ }}
57
+ >
58
+ {safeChildren}
59
+ </motion.div>
60
+ )
61
+ }
62
+
63
+ export default FadeUpOnInView