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,185 @@
1
+ 'use client'
2
+
3
+ import { motion } from 'framer-motion'
4
+ import React from 'react'
5
+
6
+ import { cn } from '@/utilities/ui'
7
+
8
+ type PortableDoc = {
9
+ slug?: string | null
10
+ breadcrumbs?: Array<{ url?: string | null }> | null
11
+ [key: string]: unknown
12
+ }
13
+
14
+ type LinkReference =
15
+ | { relationTo: 'pages'; value: number | PortableDoc }
16
+ | { relationTo: 'posts'; value: number | PortableDoc }
17
+ | { relationTo: 'projects'; value: number | PortableDoc }
18
+ | { relationTo: 'thoughts'; value: number | PortableDoc }
19
+
20
+ type BlockLinkField = {
21
+ type?: 'reference' | 'custom' | null
22
+ reference?: LinkReference | null
23
+ url?: string | null
24
+ label?: string | null
25
+ newTab?: boolean | null
26
+ } | null
27
+
28
+ export type DDHGCTASection2Props = {
29
+ sectionId?: string | null
30
+ customClassName?: string | null
31
+ customCSS?: string | null
32
+ blockId?: string | null
33
+ scrollSpeed?: string | number | null
34
+ eyebrowPrefix?: string | null
35
+ eyebrowEmphasis?: string | null
36
+ headingLineOne?: string | null
37
+ headingLineTwo?: string | null
38
+ description?: string | null
39
+ showDivider?: boolean | null
40
+ primaryLink?: BlockLinkField
41
+ secondaryLink?: BlockLinkField
42
+ }
43
+
44
+ function getHref(link?: BlockLinkField): string | null {
45
+ if (!link) return null
46
+
47
+ if (link.type === 'custom' && link.url) return link.url
48
+
49
+ if (link.type === 'reference' && link.reference?.value) {
50
+ const { relationTo, value } = link.reference
51
+ if (typeof value === 'number') return null
52
+
53
+ if (relationTo === 'pages') {
54
+ const crumbs = Array.isArray(value.breadcrumbs) ? value.breadcrumbs : []
55
+ const last = crumbs[crumbs.length - 1]
56
+ if (last?.url) return last.url
57
+
58
+ const slug = value.slug
59
+ if (!slug || slug === 'home') return '/'
60
+ return slug.startsWith('/') ? slug : `/${slug}`
61
+ }
62
+
63
+ const slug = value.slug
64
+ if (!slug) return null
65
+
66
+ if (relationTo === 'projects') return `/archives/${slug}`
67
+ if (relationTo === 'posts' || relationTo === 'thoughts') return `/thoughts/${slug}`
68
+ return `/${slug}`
69
+ }
70
+
71
+ return null
72
+ }
73
+
74
+ function CTAButton({ link, variant }: { link?: BlockLinkField; variant: 'primary' | 'secondary' }) {
75
+ const href = getHref(link)
76
+ if (!href) return null
77
+
78
+ const target = link?.newTab ? '_blank' : undefined
79
+ const rel = link?.newTab ? 'noopener noreferrer' : undefined
80
+
81
+ return (
82
+ <a
83
+ href={href}
84
+ target={target}
85
+ rel={rel}
86
+ className={cn(
87
+ 'inline-flex min-h-10 items-center justify-center px-5 py-2.5 text-sm font-medium transition-all duration-300',
88
+ variant === 'primary'
89
+ ? 'bg-stone-800 text-white hover:bg-stone-700'
90
+ : 'border border-stone-400 text-stone-700 dark:text-stone-200 hover:bg-stone-100'
91
+ )}
92
+ >
93
+ {link?.label || 'Learn More'}
94
+ </a>
95
+ )
96
+ }
97
+
98
+ const revealMotion = {
99
+ initial: { opacity: 0, y: 18 },
100
+ whileInView: { opacity: 1, y: 0 },
101
+ viewport: { once: true, amount: 0.25 },
102
+ transition: { duration: 0.7, ease: [0.22, 1, 0.36, 1] as [number, number, number, number] }
103
+ }
104
+
105
+ export const DDHGCTASection2: React.FC<DDHGCTASection2Props> = ({
106
+ sectionId,
107
+ customClassName,
108
+ customCSS,
109
+ blockId,
110
+ scrollSpeed,
111
+ eyebrowPrefix = 'ready to',
112
+ eyebrowEmphasis = 'begin?',
113
+ headingLineOne = "LET'S BUILD YOUR",
114
+ headingLineTwo = 'NEXT SPACE',
115
+ description = 'Every great space begins with a conversation. Share your vision, and we will map the path from where you are to where you want to be.',
116
+ showDivider = true,
117
+ primaryLink,
118
+ secondaryLink
119
+ }) => {
120
+ const hasButtons = Boolean(getHref(primaryLink) || getHref(secondaryLink))
121
+
122
+ return (
123
+ <div
124
+ id={sectionId ?? undefined}
125
+ data-block-id={blockId ?? undefined}
126
+ data-scroll={scrollSpeed ? true : undefined}
127
+ data-scroll-speed={scrollSpeed ? String(scrollSpeed) : undefined}
128
+ className={cn('mb-10 px-5 py-20 md:px-8', customClassName)}
129
+ >
130
+ {customCSS && <style dangerouslySetInnerHTML={{ __html: customCSS }} />}
131
+
132
+ <div className="mx-auto max-w-7xl">
133
+ <motion.div
134
+ className="z-plane-2 relative overflow-hidden"
135
+ initial={{ opacity: 0, y: 20 }}
136
+ whileInView={{ opacity: 1, y: 0 }}
137
+ viewport={{ once: true, amount: 0.25 }}
138
+ transition={{ duration: 0.9, ease: [0.22, 1, 0.36, 1] }}
139
+ >
140
+ <div className="relative p-8 text-center md:p-12 lg:p-16">
141
+ {(eyebrowPrefix || eyebrowEmphasis) && (
142
+ <p className="mb-4 text-[10px] uppercase tracking-[0.2em] text-stone-600 dark:text-stone-300">
143
+ {eyebrowPrefix && <span className="font-light">{eyebrowPrefix} </span>}
144
+ {eyebrowEmphasis && <span className="font-medium">{eyebrowEmphasis}</span>}
145
+ </p>
146
+ )}
147
+
148
+ <motion.div className="heading" {...revealMotion}>
149
+ {(headingLineOne || headingLineTwo) && (
150
+ <h2 className="mb-4 text-3xl font-medium leading-none tracking-tight text-purple-700 dark:text-purple-500 md:text-5xl">
151
+ {headingLineOne}
152
+ {headingLineOne && headingLineTwo && <br />}
153
+ <span className="font-bold">{headingLineTwo}</span>
154
+ </h2>
155
+ )}
156
+ </motion.div>
157
+
158
+ {showDivider && <div className="mx-auto mb-6 h-px w-12 bg-stone-500" />}
159
+
160
+ <motion.div
161
+ className="description"
162
+ {...revealMotion}
163
+ transition={{ ...revealMotion.transition, delay: 0.08 }}
164
+ >
165
+ {description && (
166
+ <p className="mx-auto mb-8 max-w-lg text-[14px] font-light leading-relaxed text-stone-700 dark:text-stone-200">
167
+ {description}
168
+ </p>
169
+ )}
170
+ </motion.div>
171
+
172
+ {hasButtons && (
173
+ <div className="flex flex-wrap items-center justify-center gap-3">
174
+ <CTAButton link={primaryLink} variant="primary" />
175
+ <CTAButton link={secondaryLink} variant="secondary" />
176
+ </div>
177
+ )}
178
+ </div>
179
+ </motion.div>
180
+ </div>
181
+ </div>
182
+ )
183
+ }
184
+
185
+ export default DDHGCTASection2
@@ -0,0 +1,140 @@
1
+ import type { Block } from 'payload'
2
+
3
+ import { link } from '@/fields/link'
4
+
5
+ export const DDHGCTASection2: Block = {
6
+ slug: 'DDHG-CTASection2',
7
+ interfaceName: 'DDHGCTASection2',
8
+ dbName: 'ddhg_cta_sec_2',
9
+ labels: {
10
+ singular: 'CTA Section 2',
11
+ plural: 'CTA Sections 2',
12
+ },
13
+ fields: [
14
+ {
15
+ type: 'tabs',
16
+ tabs: [
17
+ {
18
+ label: 'Content',
19
+ fields: [
20
+ {
21
+ type: 'row',
22
+ fields: [
23
+ {
24
+ name: 'eyebrowPrefix',
25
+ type: 'text',
26
+ label: 'Eyebrow Prefix',
27
+ defaultValue: 'ready to',
28
+ admin: { width: '50%' },
29
+ },
30
+ {
31
+ name: 'eyebrowEmphasis',
32
+ type: 'text',
33
+ label: 'Eyebrow Emphasis',
34
+ defaultValue: 'begin?',
35
+ admin: { width: '50%' },
36
+ },
37
+ ],
38
+ },
39
+ {
40
+ type: 'row',
41
+ fields: [
42
+ {
43
+ name: 'headingLineOne',
44
+ type: 'text',
45
+ label: 'Heading Line 1',
46
+ defaultValue: "LET'S BUILD YOUR",
47
+ admin: { width: '50%' },
48
+ },
49
+ {
50
+ name: 'headingLineTwo',
51
+ type: 'text',
52
+ label: 'Heading Line 2',
53
+ defaultValue: 'NEXT SPACE',
54
+ admin: { width: '50%' },
55
+ },
56
+ ],
57
+ },
58
+ {
59
+ name: 'description',
60
+ type: 'textarea',
61
+ label: 'Description',
62
+ defaultValue:
63
+ 'Every great space begins with a conversation. Share your vision, and we will map the path from where you are to where you want to be.',
64
+ },
65
+ {
66
+ name: 'showDivider',
67
+ type: 'checkbox',
68
+ label: 'Show Divider',
69
+ defaultValue: true,
70
+ },
71
+ ],
72
+ },
73
+ {
74
+ label: 'Buttons',
75
+ fields: [
76
+ link({
77
+ overrides: {
78
+ name: 'primaryLink',
79
+ label: 'Primary Link',
80
+ defaultValue: {
81
+ type: 'custom',
82
+ url: '/book-a-call',
83
+ label: 'Book a Consultation',
84
+ },
85
+ },
86
+ }),
87
+ link({
88
+ overrides: {
89
+ name: 'secondaryLink',
90
+ label: 'Secondary Link',
91
+ defaultValue: {
92
+ type: 'custom',
93
+ url: '/reach',
94
+ label: 'Get in Touch',
95
+ },
96
+ },
97
+ }),
98
+ ],
99
+ },
100
+ {
101
+ label: 'Advanced',
102
+ fields: [
103
+ {
104
+ type: 'row',
105
+ fields: [
106
+ {
107
+ name: 'sectionId',
108
+ type: 'text',
109
+ label: 'Section ID',
110
+ admin: { width: '50%' },
111
+ },
112
+ {
113
+ name: 'customClassName',
114
+ type: 'text',
115
+ label: 'Custom CSS Classes',
116
+ admin: { width: '50%' },
117
+ },
118
+ ],
119
+ },
120
+ {
121
+ name: 'scrollSpeed',
122
+ type: 'text',
123
+ label: 'Scroll Speed',
124
+ admin: { description: 'Optional data-scroll-speed value.' },
125
+ },
126
+ {
127
+ name: 'customCSS',
128
+ type: 'code',
129
+ label: 'Custom CSS',
130
+ admin: {
131
+ language: 'css',
132
+ description: 'Injected as a style tag. Use with caution.',
133
+ },
134
+ },
135
+ ],
136
+ },
137
+ ],
138
+ },
139
+ ],
140
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "type": "block",
3
+ "name": "DDHG-CTASection2",
4
+ "label": "CTA Section 2",
5
+ "sourceName": "CTASection2",
6
+ "portableName": "DDHG-CTASection2",
7
+ "slug": "DDHG-CTASection2",
8
+ "version": "0.0.1",
9
+ "source": {
10
+ "repo": "Hadizainal/HeatherGrey2025",
11
+ "originalPath": "src/blocks/CTASection2",
12
+ "originalSlug": "ctaSection2",
13
+ "originalConfigExport": "CTASection2",
14
+ "originalComponentExport": "CTASection2Block",
15
+ "originalInterfaceName": "CTASection2BlockProps"
16
+ },
17
+ "files": [
18
+ { "from": "Component.tsx", "to": "src/blocks/DDHG-CTASection2/Component.tsx" },
19
+ { "from": "config.ts", "to": "src/blocks/DDHG-CTASection2/config.ts" }
20
+ ],
21
+ "dependencies": [{ "name": "framer-motion" }],
22
+ "sharedFiles": [],
23
+ "requiredProjectFiles": [
24
+ { "path": "src/fields/link.ts", "reason": "Payload config uses the shared link field." },
25
+ { "path": "src/utilities/ui.ts", "reason": "Component uses the cn utility." }
26
+ ],
27
+ "optionalProjectFiles": [],
28
+ "collectionRegistration": { "enabled": true, "collections": ["Pages", "Posts"] },
29
+ "renderBlocksRegistration": { "enabled": true },
30
+ "renderBlocksBehavior": { "wrapperless": false },
31
+ "pageRouteIntegration": { "required": false, "manualSteps": [] },
32
+ "manualSteps": [
33
+ "Confirm the destination link field supports reference and custom links.",
34
+ "Run payload generate:types after schema changes."
35
+ ],
36
+ "notes": [
37
+ "Converted from HeatherGrey2025 CTASection2.",
38
+ "The top-level dbName was namespaced to ddhg_cta_sec_2 for portability.",
39
+ "ButtonMain and TextFade dependencies were removed; the block now renders standard CTA anchors and uses framer-motion directly.",
40
+ "Generated Payload document types were replaced with portable structural types.",
41
+ "Installer must not overwrite existing target files."
42
+ ],
43
+ "exportName": "DDHGCTASection2",
44
+ "interfaceName": "DDHGCTASection2"
45
+ }
@@ -0,0 +1,243 @@
1
+ 'use client'
2
+
3
+ import { ArrowRight } from 'lucide-react'
4
+ import Image from 'next/image'
5
+ import Link from 'next/link'
6
+ import React, { useState } from 'react'
7
+
8
+ import { cn } from '@/utilities/ui'
9
+
10
+ type PortableDoc = {
11
+ slug?: string | null
12
+ breadcrumbs?: Array<{ url?: string | null }> | null
13
+ [key: string]: unknown
14
+ }
15
+
16
+ type Media = {
17
+ url?: string | null
18
+ alt?: string | null
19
+ [key: string]: unknown
20
+ }
21
+
22
+ type LinkReference =
23
+ | { relationTo: 'pages'; value: number | PortableDoc }
24
+ | { relationTo: 'posts'; value: number | PortableDoc }
25
+ | { relationTo: 'projects'; value: number | PortableDoc }
26
+ | { relationTo: 'thoughts'; value: number | PortableDoc }
27
+
28
+ type HighlightArchiveCardsLink = {
29
+ type?: 'reference' | 'custom' | null
30
+ reference?: LinkReference | null
31
+ url?: string | null
32
+ label?: string | null
33
+ newTab?: boolean | null
34
+ } | null
35
+
36
+ type HighlightArchiveCardsItem = {
37
+ id?: string | null
38
+ code?: string | null
39
+ title?: string | null
40
+ type?: string | null
41
+ bgImage?: number | Media | null
42
+ priority?: boolean | null
43
+ link?: HighlightArchiveCardsLink
44
+ }
45
+
46
+ export type DDHGHighlightArcProps = {
47
+ gridColumns?: '1' | '2' | '3' | '4' | null
48
+ highlights?: HighlightArchiveCardsItem[] | null
49
+ }
50
+
51
+ const getGridClassName = (gridColumns?: DDHGHighlightArcProps['gridColumns']) => {
52
+ switch (gridColumns) {
53
+ case '2':
54
+ return 'grid-cols-1 md:grid-cols-2'
55
+ case '3':
56
+ return 'grid-cols-1 md:grid-cols-2 xl:grid-cols-3'
57
+ case '4':
58
+ return 'grid-cols-1 md:grid-cols-2 xl:grid-cols-4'
59
+ case '1':
60
+ default:
61
+ return 'grid-cols-1'
62
+ }
63
+ }
64
+
65
+ const getPageURLFromDoc = (doc: PortableDoc | number): string | null => {
66
+ if (typeof doc === 'number') return null
67
+
68
+ const crumbs = Array.isArray(doc?.breadcrumbs) ? doc.breadcrumbs : []
69
+ if (crumbs.length) {
70
+ const last = crumbs[crumbs.length - 1]
71
+ if (typeof last?.url === 'string' && last.url) return last.url
72
+ }
73
+
74
+ const slug = doc?.slug
75
+ if (!slug || slug === 'home') return '/'
76
+ return slug.startsWith('/') ? slug : `/${slug}`
77
+ }
78
+
79
+ const getDocumentSlug = (doc: PortableDoc | number): string | null => {
80
+ if (typeof doc === 'number') return null
81
+ return doc?.slug || null
82
+ }
83
+
84
+ const getCollectionPath = (relationTo: LinkReference['relationTo']): string => {
85
+ if (relationTo === 'posts') return 'thoughts'
86
+ if (relationTo === 'thoughts') return 'thoughts'
87
+ if (relationTo === 'projects') return 'archives'
88
+ return ''
89
+ }
90
+
91
+ const resolveHref = (link: HighlightArchiveCardsLink): string | null => {
92
+ if (!link) return null
93
+ if (link.type === 'custom' && link.url) return link.url
94
+
95
+ if (link.type === 'reference' && link.reference?.value) {
96
+ const { relationTo, value } = link.reference
97
+ if (relationTo === 'pages') return getPageURLFromDoc(value)
98
+
99
+ const slug = getDocumentSlug(value)
100
+ if (!slug) return null
101
+ const basePath = getCollectionPath(relationTo)
102
+ return basePath ? `/${basePath}/${slug}` : `/${slug}`
103
+ }
104
+
105
+ return null
106
+ }
107
+
108
+ const isExternalHref = (href: string): boolean =>
109
+ href.startsWith('http://') ||
110
+ href.startsWith('https://') ||
111
+ href.startsWith('mailto:') ||
112
+ href.startsWith('tel:')
113
+
114
+ export const DDHGHighlightArc: React.FC<DDHGHighlightArcProps> = ({
115
+ gridColumns = '1',
116
+ highlights,
117
+ }) => {
118
+ const [hoveredIdx, setHoveredIdx] = useState<number | null>(null)
119
+
120
+ if (!Array.isArray(highlights) || highlights.length === 0) return null
121
+
122
+ return (
123
+ <div className={cn('grid origin-top scale-100 !gap-0', getGridClassName(gridColumns))}>
124
+ {highlights.map((h, i) => {
125
+ const isHovered = hoveredIdx === i
126
+ const bgImage = typeof h.bgImage === 'object' && h.bgImage !== null ? h.bgImage : null
127
+ const href = resolveHref(h.link || null)
128
+ const label = h.link?.label || 'View Archive'
129
+ const target = h.link?.newTab ? '_blank' : undefined
130
+ const rel = h.link?.newTab ? 'noopener noreferrer' : undefined
131
+ const isExternal = href ? isExternalHref(href) : false
132
+ const key = h.id != null ? `id-${h.id}` : `idx-${i}`
133
+
134
+ const cardClassName = cn(
135
+ 'group relative block h-[4rem] overflow-hidden rounded-[0px] border border-border px-5 py-5 !no-underline shadow-[0_18px_60px_rgba(31,31,30,0.12),inset_0_1px_0_rgba(255,255,255,0.62)] transition-all duration-500 ease-out hover:shadow-[0_24px_74px_rgba(31,31,30,0.16),inset_0_1px_0_rgba(255,255,255,0.72)]',
136
+ 'before:pointer-events-none before:absolute before:inset-0 before:z-[1] --before:bg-[linear-gradient(90deg,rgba(255,255,255,0.62),rgba(255,255,255,0.22)_42%,rgba(255,255,255,0.06))] before:transition-opacity before:duration-500',
137
+ 'after:pointer-events-none after:absolute after:inset-0 after:z-[2] after:opacity-[0.08] after:mix-blend-multiply --after:[background-image:radial-gradient(circle_at_20%_30%,rgba(31,31,30,0.5)_0_1px,transparent_1px),--radial-gradient(circle_at_80%_70%,rgba(255,255,255,0.8)_0_1px,transparent_1px)] after:[background-size:14px_14px,19px_19px]',
138
+ href
139
+ ? 'cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-stone-500/40 focus-visible:ring-offset-2'
140
+ : 'cursor-default',
141
+ )
142
+
143
+ const buttonClassName = cn(
144
+ 'inline-flex items-center gap-2 whitespace-nowrap text-xs font-medium tracking-[0.04em] text-stone-700 transition-all duration-300',
145
+ 'group-hover:text-[#1F1F1E]',
146
+ isHovered ? 'translate-x-0 opacity-100' : 'translate-x-2 opacity-100',
147
+ !href && 'opacity-40',
148
+ )
149
+
150
+ const cardContent = (
151
+ <>
152
+ <div className="HighCardsContent absolute inset-0 z-0 bg-transparent opacity-0 transition-opacity duration-500 group-hover:opacity-70" />
153
+
154
+ {bgImage?.url && (
155
+ <div className="HighCardImg absolute inset-0 z-[1] overflow-hidden opacity-0 transition-opacity duration-500 ease-out group-hover:opacity-100">
156
+ <div className="absolute left-0 top-0 h-[260%] w-full transition-transform duration-700 ease-out group-hover:-translate-y-[60%]">
157
+ <Image
158
+ src={bgImage.url}
159
+ alt={bgImage.alt ?? h.title ?? ''}
160
+ fill
161
+ priority={Boolean(h.priority)}
162
+ className="object-cover"
163
+ sizes="(max-width: 768px) 100vw, 400px"
164
+ />
165
+ </div>
166
+
167
+ {h.title && (
168
+ <p className="HighCardTitle absolute left-0 top-0 z-10 px-4 py-4 text-[10px] font-semibold leading-snug text-stone-100 dark:text-stone-100 transition-colors duration-300">
169
+ {h.title}
170
+ </p>
171
+ )}
172
+
173
+ <div className="HighCardImgBg absolute inset-0 z-[2] bg-transparent opacity-0 transition-opacity duration-500 group-hover:opacity-70" />
174
+ <div className="absolute mix-blend-darken inset-0 z-[2] bg-gradient-to-r from-[#151515bf] via-[#20202029] to-[#00000000] opacity-0 transition-opacity duration-500 group-hover:opacity-70" />
175
+ </div>
176
+ )}
177
+
178
+ <div className="card-info relative z-[3] translate-y-0 transition-transform duration-500 group-hover:translate-y-[-7rem]">
179
+ <div className="relative z-10 flex h-full items-start justify-between gap-6">
180
+ <span className="relative w-full ml-auto max-w-fit right-0 -top-2 block origin-top-right scale-80">
181
+ <span className={buttonClassName}>
182
+ <span className="block">{label}</span>
183
+ <ArrowRight
184
+ size={14}
185
+ className="transition-transform duration-300 group-hover:translate-x-1"
186
+ />
187
+ </span>
188
+ </span>
189
+ </div>
190
+ </div>
191
+ </>
192
+ )
193
+
194
+ if (!href) {
195
+ return (
196
+ <article
197
+ key={key}
198
+ className={cardClassName}
199
+ onMouseEnter={() => setHoveredIdx(i)}
200
+ onMouseLeave={() => setHoveredIdx(null)}
201
+ >
202
+ {cardContent}
203
+ </article>
204
+ )
205
+ }
206
+
207
+ if (isExternal) {
208
+ return (
209
+ <a
210
+ key={key}
211
+ href={href}
212
+ target={target}
213
+ rel={rel}
214
+ aria-label={label}
215
+ className={cardClassName}
216
+ onMouseEnter={() => setHoveredIdx(i)}
217
+ onMouseLeave={() => setHoveredIdx(null)}
218
+ >
219
+ {cardContent}
220
+ </a>
221
+ )
222
+ }
223
+
224
+ return (
225
+ <Link
226
+ key={key}
227
+ href={href}
228
+ target={target}
229
+ rel={rel}
230
+ aria-label={label}
231
+ className={cardClassName}
232
+ onMouseEnter={() => setHoveredIdx(i)}
233
+ onMouseLeave={() => setHoveredIdx(null)}
234
+ >
235
+ {cardContent}
236
+ </Link>
237
+ )
238
+ })}
239
+ </div>
240
+ )
241
+ }
242
+
243
+ export default DDHGHighlightArc
@@ -0,0 +1,85 @@
1
+ import type { Block } from 'payload'
2
+
3
+ import { link } from '@/fields/link'
4
+
5
+ export const DDHGHighlightArc: Block = {
6
+ slug: 'DDHG-HighlightArc',
7
+ interfaceName: 'DDHGHighlightArc',
8
+ labels: {
9
+ singular: 'Highlight Archive Cards',
10
+ plural: 'Highlight Archive Cards',
11
+ },
12
+ fields: [
13
+ // DDHG TODO: Re-enable when the archive bundle providing BeforeSidebar is imported.
14
+ // {
15
+ // name: 'beforeSidebar',
16
+ // type: 'ui',
17
+ // admin: {
18
+ // position: 'sidebar',
19
+ // components: {
20
+ // Field: '@/components/Admin/BeforeSidebar',
21
+ // },
22
+ // },
23
+ // },
24
+ {
25
+ name: 'gridColumns',
26
+ type: 'select',
27
+ label: 'Grid Columns',
28
+ defaultValue: '1',
29
+ options: [
30
+ { label: '1 Column', value: '1' },
31
+ { label: '2 Columns', value: '2' },
32
+ { label: '3 Columns', value: '3' },
33
+ { label: '4 Columns', value: '4' },
34
+ ],
35
+ },
36
+ {
37
+ name: 'highlights',
38
+ type: 'array',
39
+ label: 'Highlights',
40
+ minRows: 1,
41
+ fields: [
42
+ {
43
+ name: 'code',
44
+ type: 'text',
45
+ hidden: true,
46
+ label: 'Project Code',
47
+ },
48
+ {
49
+ name: 'title',
50
+ type: 'text',
51
+ label: 'Project Name',
52
+ required: true,
53
+ },
54
+ {
55
+ name: 'type',
56
+ type: 'text',
57
+ hidden: true,
58
+ label: 'Project Type',
59
+ },
60
+ {
61
+ name: 'bgImage',
62
+ type: 'upload',
63
+ relationTo: 'media',
64
+ label: 'Background Image',
65
+ },
66
+ {
67
+ name: 'priority',
68
+ type: 'checkbox',
69
+ label: 'High Priority Image',
70
+ defaultValue: false,
71
+ admin: {
72
+ description: 'Enable only when this card appears above the fold.',
73
+ },
74
+ },
75
+ link({
76
+ appearances: false,
77
+ overrides: {
78
+ name: 'link',
79
+ label: 'Project Code',
80
+ },
81
+ }),
82
+ ],
83
+ },
84
+ ],
85
+ }