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
@@ -1,266 +1,266 @@
1
- 'use client'
2
- import React from 'react'
3
- import Link from 'next/link'
4
- import Image from 'next/image'
5
- import { ArrowUpRight, CheckCheck } from 'lucide-react'
6
- import { motion, type Variants } from 'framer-motion'
7
- import * as LucideIcons from 'lucide-react'
8
- export type DDSectionProps = Record<string, any>
9
- type ServiceItem = {
10
- id?: string | null
11
- iconName?: string | null
12
- title?: string | null
13
- description?: string | null
14
- }
15
- type ButtonItem = { href?: string | null; class?: string | null; label?: string | null }
16
-
17
- function isLocalImageSrc(src?: string | null): src is string {
18
- return typeof src === 'string' && src.startsWith('/api/media/file/')
19
- }
20
-
21
- function SectionImagePlaceholder() {
22
- return (
23
- <svg
24
- aria-hidden="true"
25
- className="h-full w-full"
26
- viewBox="0 0 900 700"
27
- preserveAspectRatio="none"
28
- >
29
- <defs>
30
- <linearGradient id="dd-section-placeholder" x1="0" y1="0" x2="1" y2="1">
31
- <stop offset="0%" stopColor="#111827" />
32
- <stop offset="50%" stopColor="#251644" />
33
- <stop offset="100%" stopColor="#09090b" />
34
- </linearGradient>
35
- <pattern id="dd-section-grid" width="72" height="72" patternUnits="userSpaceOnUse">
36
- <path d="M 72 0 L 0 0 0 72" fill="none" stroke="#ffffff" strokeOpacity="0.07" />
37
- </pattern>
38
- </defs>
39
- <rect width="900" height="700" fill="url(#dd-section-placeholder)" />
40
- <rect width="900" height="700" fill="url(#dd-section-grid)" />
41
- <rect x="155" y="150" width="590" height="360" rx="32" fill="#ffffff" fillOpacity="0.08" />
42
- <rect x="210" y="215" width="270" height="28" rx="14" fill="#ffffff" fillOpacity="0.18" />
43
- <rect x="210" y="275" width="430" height="22" rx="11" fill="#ffffff" fillOpacity="0.12" />
44
- <rect x="210" y="325" width="360" height="22" rx="11" fill="#ffffff" fillOpacity="0.1" />
45
- <rect x="210" y="410" width="150" height="46" rx="23" fill="#a3e635" fillOpacity="0.16" />
46
- </svg>
47
- )
48
- }
49
-
50
- const containerVariants: Variants = {
51
- hidden: {},
52
- show: { transition: { staggerChildren: 0.1, delayChildren: 0.05 } },
53
- }
54
-
55
- const itemVariants: Variants = {
56
- hidden: { opacity: 0, y: 20 },
57
- show: { opacity: 1, y: 0, transition: { duration: 0.45, ease: 'easeOut' } },
58
- }
59
-
60
- function DynamicIcon({
61
- name,
62
- ...props
63
- }: { name?: string | null } & Omit<LucideIcons.LucideProps, 'name'>) {
64
- if (!name) return null
65
- const Icon = (LucideIcons as unknown as Record<string, React.FC<LucideIcons.LucideProps>>)[name]
66
- if (!Icon) return null
67
- return <Icon {...props} />
68
- }
69
-
70
- export const DDSection: React.FC<DDSectionProps> = ({
71
- eyebrow,
72
- headlineMain,
73
- headlineAccent,
74
- description,
75
- ctaLabel,
76
- ctaHref,
77
- services,
78
- image,
79
- imageFallbackUrl,
80
- imageAlt,
81
- badgeTitle,
82
- badgeSubtitle,
83
- showBadge,
84
- sectionId,
85
- customCSS,
86
- showButtons = true,
87
- buttons = [
88
- { variant: 'v1', icon: 'Goal', label: 'Choose Lane' },
89
- { variant: 'v1', icon: 'Feather', label: 'How it works' },
90
- ],
91
- }) => {
92
- const serviceItems = (services ?? []) as ServiceItem[]
93
- const buttonItems = buttons as ButtonItem[]
94
- const imgSrc =
95
- image && typeof image === 'object' && 'url' in image && image.url
96
- ? image.url
97
- : (imageFallbackUrl ?? '')
98
- const safeImgSrc = isLocalImageSrc(imgSrc) ? imgSrc : null
99
-
100
- return (
101
- <>
102
- {customCSS && <style dangerouslySetInnerHTML={{ __html: customCSS }} />}
103
-
104
- <div id={sectionId ?? 'studio-section'} className="py-24 overflow-hidden">
105
- #BlockName-DDSection
106
- <div className="max-w-6xl lg:max-w-7xl mx-auto px-4 md:px-6">
107
- <div className="grid grid-cols-1 lg:grid-cols-2 gap-16 items-center">
108
- {/* Left Content */}
109
- <motion.div
110
- variants={containerVariants}
111
- initial="hidden"
112
- whileInView="show"
113
- viewport={{ once: false, amount: 0.15 }}
114
- >
115
- {eyebrow && (
116
- <motion.p
117
- variants={itemVariants}
118
- className="text-[11.5px] font-semibold text-stone-400 tracking-widest uppercase mb-3 top-caption"
119
- >
120
- {eyebrow}
121
- </motion.p>
122
- )}
123
-
124
- <motion.h2
125
- variants={itemVariants}
126
- className="text-3d text-4xl md:text-5xl font-bold text-stone-900 dark:text-stone-50 leading-tight mb-6"
127
- >
128
- {headlineMain}
129
- <br />
130
- <span className="text-stone-400">{headlineAccent}</span>
131
- </motion.h2>
132
-
133
- {description && (
134
- <motion.p
135
- variants={itemVariants}
136
- className="text-stone-700 dark:text-stone-300 text-base leading-relaxed mb-10"
137
- >
138
- {description}
139
- </motion.p>
140
- )}
141
-
142
- {serviceItems.length > 0 && (
143
- <motion.div
144
- variants={containerVariants}
145
- className="grid grid-cols-1 sm:grid-cols-2 gap-5 mb-10"
146
- >
147
- {serviceItems.map((svc) => (
148
- <motion.div
149
- key={svc.id ?? svc.title}
150
- variants={itemVariants}
151
- className="flex gap-3"
152
- >
153
- <div className="w-8 h-8 flex items-center justify-center rounded-lg bg-stone-200/50 dark:bg-stone-800/50 text-stone-400 shrink-0 mt-0.5 border border-stone-200 dark:border-stone-600 hover:border-lime-500 duration-150">
154
- <DynamicIcon className="text-stone-400" name={svc.iconName} size={14} />
155
- </div>
156
- <div>
157
- <h3 className="text-sm font-semibold text-stone-800 dark:text-stone-50 mb-1">
158
- {svc.title}
159
- </h3>
160
- <p className="text-sm text-stone-700 dark:text-stone-300 leading-relaxed">
161
- {svc.description}
162
- </p>
163
- </div>
164
- </motion.div>
165
- ))}
166
- </motion.div>
167
- )}
168
-
169
- {/* {ctaLabel && ctaHref && (
170
- <motion.div variants={itemVariants}>
171
- <Link
172
- href={ctaHref}
173
- className="inline-flex items-center gap-2 bg-stone-50 text-stone-900 px-6 py-3 rounded-lg text-sm font-semibold hover:bg-stone-100 transition-colors cursor-pointer whitespace-nowrap"
174
- >
175
- {ctaLabel}
176
- <ArrowUpRight size={15} />
177
- </Link>
178
- </motion.div>
179
- )} */}
180
-
181
- {/* Dusted CTA Buttons */}
182
- {showButtons && buttonItems.length > 0 && (
183
- <motion.div
184
- className="dusted-hero-cta-col flex col-start-2 col-span-2 gap-4"
185
- variants={itemVariants}
186
- >
187
- {buttonItems.map((button, index) => (
188
- <a
189
- key={index}
190
- href={(button as any).href ?? '#'}
191
- className={
192
- button.class ??
193
- 'inline-flex items-center gap-1.5 bg-indigo-700 text-stone-50 text-xs font-semibold px-3 py-1.5 rounded-lg hover:bg-indigo-600 group-hover:scale-[1.05] hover:shadow-xl transition-all duration-150 whitespace-nowrap'
194
- }
195
- style={{ cornerShape: 'squircle' } as React.CSSProperties}
196
- >
197
- {/* TODO: Reconnect ButtonDustedFluid if this project provides it. */}
198
- {button.label || 'Button'}
199
- </a>
200
- ))}
201
- </motion.div>
202
- )}
203
- </motion.div>
204
-
205
- {/* Right Image */}
206
- {(safeImgSrc || imgSrc) && (
207
- <motion.div
208
- className="relative"
209
- initial={{ opacity: 0, x: 40 }}
210
- whileInView={{ opacity: 1, x: 0 }}
211
- viewport={{ once: false, amount: 0.15 }}
212
- transition={{ duration: 0.6, ease: 'easeOut' }}
213
- >
214
- <div
215
- className="rounded-3xl overflow-hidden w-full h-125 relative shadow-xl"
216
- style={{ cornerShape: 'squircle' } as React.CSSProperties}
217
- >
218
- {safeImgSrc ? (
219
- <Image
220
- src={safeImgSrc}
221
- alt={imageAlt ?? 'DesignsDusted Studio'}
222
- fill
223
- sizes="(max-width: 768px) 100vw, 50vw"
224
- className="object-cover object-top squircle"
225
- style={{ cornerShape: 'squircle' } as React.CSSProperties}
226
- />
227
- ) : (
228
- <SectionImagePlaceholder />
229
- )}
230
- <div
231
- className="absolute inset-0 bg-linear-to-t from-stone-950/70 via-transparent to-transparent rounded-2xl"
232
- style={{ cornerShape: 'squircle' } as React.CSSProperties}
233
- />
234
- </div>
235
-
236
- {showBadge && (
237
- <div
238
- className="absolute bottom-6 left-6 right-6 bg-indigo-900/50 shadow-inner backdrop-blur-sm rounded-2xl p-4 border border-indigo-700"
239
- style={{ cornerShape: 'squircle' } as React.CSSProperties}
240
- >
241
- <div className="flex items-center gap-3">
242
- <div className="w-10 h-10 flex items-center justify-center rounded-lg bg-stone-50 text-stone-900 shrink-0">
243
- <CheckCheck size={16} />
244
- </div>
245
- <div>
246
- {badgeTitle && (
247
- <div className="text-sm font-semibold text-stone-50 dark:text-stone-50">
248
- {badgeTitle}
249
- </div>
250
- )}
251
- {badgeSubtitle && (
252
- <div className="text-xs text-stone-300">{badgeSubtitle}</div>
253
- )}
254
- </div>
255
- <div className="ml-auto w-2 h-2 rounded-full bg-lime-400 animate-pulse shrink-0" />
256
- </div>
257
- </div>
258
- )}
259
- </motion.div>
260
- )}
261
- </div>
262
- </div>
263
- </div>
264
- </>
265
- )
266
- }
1
+ 'use client'
2
+ import React from 'react'
3
+ import Link from 'next/link'
4
+ import Image from 'next/image'
5
+ import { ArrowUpRight, CheckCheck } from 'lucide-react'
6
+ import { motion, type Variants } from 'framer-motion'
7
+ import * as LucideIcons from 'lucide-react'
8
+ export type DDSectionProps = Record<string, any>
9
+ type ServiceItem = {
10
+ id?: string | null
11
+ iconName?: string | null
12
+ title?: string | null
13
+ description?: string | null
14
+ }
15
+ type ButtonItem = { href?: string | null; class?: string | null; label?: string | null }
16
+
17
+ function isLocalImageSrc(src?: string | null): src is string {
18
+ return typeof src === 'string' && src.startsWith('/api/media/file/')
19
+ }
20
+
21
+ function SectionImagePlaceholder() {
22
+ return (
23
+ <svg
24
+ aria-hidden="true"
25
+ className="h-full w-full"
26
+ viewBox="0 0 900 700"
27
+ preserveAspectRatio="none"
28
+ >
29
+ <defs>
30
+ <linearGradient id="dd-section-placeholder" x1="0" y1="0" x2="1" y2="1">
31
+ <stop offset="0%" stopColor="#111827" />
32
+ <stop offset="50%" stopColor="#251644" />
33
+ <stop offset="100%" stopColor="#09090b" />
34
+ </linearGradient>
35
+ <pattern id="dd-section-grid" width="72" height="72" patternUnits="userSpaceOnUse">
36
+ <path d="M 72 0 L 0 0 0 72" fill="none" stroke="#ffffff" strokeOpacity="0.07" />
37
+ </pattern>
38
+ </defs>
39
+ <rect width="900" height="700" fill="url(#dd-section-placeholder)" />
40
+ <rect width="900" height="700" fill="url(#dd-section-grid)" />
41
+ <rect x="155" y="150" width="590" height="360" rx="32" fill="#ffffff" fillOpacity="0.08" />
42
+ <rect x="210" y="215" width="270" height="28" rx="14" fill="#ffffff" fillOpacity="0.18" />
43
+ <rect x="210" y="275" width="430" height="22" rx="11" fill="#ffffff" fillOpacity="0.12" />
44
+ <rect x="210" y="325" width="360" height="22" rx="11" fill="#ffffff" fillOpacity="0.1" />
45
+ <rect x="210" y="410" width="150" height="46" rx="23" fill="#a3e635" fillOpacity="0.16" />
46
+ </svg>
47
+ )
48
+ }
49
+
50
+ const containerVariants: Variants = {
51
+ hidden: {},
52
+ show: { transition: { staggerChildren: 0.1, delayChildren: 0.05 } },
53
+ }
54
+
55
+ const itemVariants: Variants = {
56
+ hidden: { opacity: 0, y: 20 },
57
+ show: { opacity: 1, y: 0, transition: { duration: 0.45, ease: 'easeOut' } },
58
+ }
59
+
60
+ function DynamicIcon({
61
+ name,
62
+ ...props
63
+ }: { name?: string | null } & Omit<LucideIcons.LucideProps, 'name'>) {
64
+ if (!name) return null
65
+ const Icon = (LucideIcons as unknown as Record<string, React.FC<LucideIcons.LucideProps>>)[name]
66
+ if (!Icon) return null
67
+ return <Icon {...props} />
68
+ }
69
+
70
+ export const DDSection: React.FC<DDSectionProps> = ({
71
+ eyebrow,
72
+ headlineMain,
73
+ headlineAccent,
74
+ description,
75
+ ctaLabel,
76
+ ctaHref,
77
+ services,
78
+ image,
79
+ imageFallbackUrl,
80
+ imageAlt,
81
+ badgeTitle,
82
+ badgeSubtitle,
83
+ showBadge,
84
+ sectionId,
85
+ customCSS,
86
+ showButtons = true,
87
+ buttons = [
88
+ { variant: 'v1', icon: 'Goal', label: 'Choose Lane' },
89
+ { variant: 'v1', icon: 'Feather', label: 'How it works' },
90
+ ],
91
+ }) => {
92
+ const serviceItems = (services ?? []) as ServiceItem[]
93
+ const buttonItems = buttons as ButtonItem[]
94
+ const imgSrc =
95
+ image && typeof image === 'object' && 'url' in image && image.url
96
+ ? image.url
97
+ : (imageFallbackUrl ?? '')
98
+ const safeImgSrc = isLocalImageSrc(imgSrc) ? imgSrc : null
99
+
100
+ return (
101
+ <>
102
+ {customCSS && <style dangerouslySetInnerHTML={{ __html: customCSS }} />}
103
+
104
+ <div id={sectionId ?? 'studio-section'} className="py-24 overflow-hidden">
105
+ #BlockName-DDSection
106
+ <div className="max-w-6xl lg:max-w-7xl mx-auto px-4 md:px-6">
107
+ <div className="grid grid-cols-1 lg:grid-cols-2 gap-16 items-center">
108
+ {/* Left Content */}
109
+ <motion.div
110
+ variants={containerVariants}
111
+ initial="hidden"
112
+ whileInView="show"
113
+ viewport={{ once: false, amount: 0.15 }}
114
+ >
115
+ {eyebrow && (
116
+ <motion.p
117
+ variants={itemVariants}
118
+ className="text-[11.5px] font-semibold text-stone-400 tracking-widest uppercase mb-3 top-caption"
119
+ >
120
+ {eyebrow}
121
+ </motion.p>
122
+ )}
123
+
124
+ <motion.h2
125
+ variants={itemVariants}
126
+ className="text-3d text-4xl md:text-5xl font-bold text-stone-900 dark:text-stone-50 leading-tight mb-6"
127
+ >
128
+ {headlineMain}
129
+ <br />
130
+ <span className="text-stone-400">{headlineAccent}</span>
131
+ </motion.h2>
132
+
133
+ {description && (
134
+ <motion.p
135
+ variants={itemVariants}
136
+ className="text-stone-700 dark:text-stone-300 text-base leading-relaxed mb-10"
137
+ >
138
+ {description}
139
+ </motion.p>
140
+ )}
141
+
142
+ {serviceItems.length > 0 && (
143
+ <motion.div
144
+ variants={containerVariants}
145
+ className="grid grid-cols-1 sm:grid-cols-2 gap-5 mb-10"
146
+ >
147
+ {serviceItems.map((svc) => (
148
+ <motion.div
149
+ key={svc.id ?? svc.title}
150
+ variants={itemVariants}
151
+ className="flex gap-3"
152
+ >
153
+ <div className="w-8 h-8 flex items-center justify-center rounded-lg bg-stone-200/50 dark:bg-stone-800/50 text-stone-400 shrink-0 mt-0.5 border border-stone-200 dark:border-stone-600 hover:border-lime-500 duration-150">
154
+ <DynamicIcon className="text-stone-400" name={svc.iconName} size={14} />
155
+ </div>
156
+ <div>
157
+ <h3 className="text-sm font-semibold text-stone-800 dark:text-stone-50 mb-1">
158
+ {svc.title}
159
+ </h3>
160
+ <p className="text-sm text-stone-700 dark:text-stone-300 leading-relaxed">
161
+ {svc.description}
162
+ </p>
163
+ </div>
164
+ </motion.div>
165
+ ))}
166
+ </motion.div>
167
+ )}
168
+
169
+ {/* {ctaLabel && ctaHref && (
170
+ <motion.div variants={itemVariants}>
171
+ <Link
172
+ href={ctaHref}
173
+ className="inline-flex items-center gap-2 bg-stone-50 text-stone-900 px-6 py-3 rounded-lg text-sm font-semibold hover:bg-stone-100 transition-colors cursor-pointer whitespace-nowrap"
174
+ >
175
+ {ctaLabel}
176
+ <ArrowUpRight size={15} />
177
+ </Link>
178
+ </motion.div>
179
+ )} */}
180
+
181
+ {/* Dusted CTA Buttons */}
182
+ {showButtons && buttonItems.length > 0 && (
183
+ <motion.div
184
+ className="dusted-hero-cta-col flex col-start-2 col-span-2 gap-4"
185
+ variants={itemVariants}
186
+ >
187
+ {buttonItems.map((button, index) => (
188
+ <a
189
+ key={index}
190
+ href={(button as any).href ?? '#'}
191
+ className={
192
+ button.class ??
193
+ 'inline-flex items-center gap-1.5 bg-indigo-700 text-stone-50 text-xs font-semibold px-3 py-1.5 rounded-lg hover:bg-indigo-600 group-hover:scale-[1.05] hover:shadow-xl transition-all duration-150 whitespace-nowrap'
194
+ }
195
+ style={{ cornerShape: 'squircle' } as React.CSSProperties}
196
+ >
197
+ {/* TODO: Reconnect ButtonDustedFluid if this project provides it. */}
198
+ {button.label || 'Button'}
199
+ </a>
200
+ ))}
201
+ </motion.div>
202
+ )}
203
+ </motion.div>
204
+
205
+ {/* Right Image */}
206
+ {(safeImgSrc || imgSrc) && (
207
+ <motion.div
208
+ className="relative"
209
+ initial={{ opacity: 0, x: 40 }}
210
+ whileInView={{ opacity: 1, x: 0 }}
211
+ viewport={{ once: false, amount: 0.15 }}
212
+ transition={{ duration: 0.6, ease: 'easeOut' }}
213
+ >
214
+ <div
215
+ className="rounded-3xl overflow-hidden w-full h-125 relative shadow-xl"
216
+ style={{ cornerShape: 'squircle' } as React.CSSProperties}
217
+ >
218
+ {safeImgSrc ? (
219
+ <Image
220
+ src={safeImgSrc}
221
+ alt={imageAlt ?? 'DesignsDusted Studio'}
222
+ fill
223
+ sizes="(max-width: 768px) 100vw, 50vw"
224
+ className="object-cover object-top squircle"
225
+ style={{ cornerShape: 'squircle' } as React.CSSProperties}
226
+ />
227
+ ) : (
228
+ <SectionImagePlaceholder />
229
+ )}
230
+ <div
231
+ className="absolute inset-0 bg-linear-to-t from-stone-950/70 via-transparent to-transparent rounded-2xl"
232
+ style={{ cornerShape: 'squircle' } as React.CSSProperties}
233
+ />
234
+ </div>
235
+
236
+ {showBadge && (
237
+ <div
238
+ className="absolute bottom-6 left-6 right-6 bg-indigo-900/50 shadow-inner backdrop-blur-sm rounded-2xl p-4 border border-indigo-700"
239
+ style={{ cornerShape: 'squircle' } as React.CSSProperties}
240
+ >
241
+ <div className="flex items-center gap-3">
242
+ <div className="w-10 h-10 flex items-center justify-center rounded-lg bg-stone-50 text-stone-900 shrink-0">
243
+ <CheckCheck size={16} />
244
+ </div>
245
+ <div>
246
+ {badgeTitle && (
247
+ <div className="text-sm font-semibold text-stone-50 dark:text-stone-50">
248
+ {badgeTitle}
249
+ </div>
250
+ )}
251
+ {badgeSubtitle && (
252
+ <div className="text-xs text-stone-300">{badgeSubtitle}</div>
253
+ )}
254
+ </div>
255
+ <div className="ml-auto w-2 h-2 rounded-full bg-lime-400 animate-pulse shrink-0" />
256
+ </div>
257
+ </div>
258
+ )}
259
+ </motion.div>
260
+ )}
261
+ </div>
262
+ </div>
263
+ </div>
264
+ </>
265
+ )
266
+ }
@@ -0,0 +1,66 @@
1
+ import React from 'react'
2
+ import { cn } from '@/utilities/ui'
3
+
4
+ export interface SeparatorGradientProps {
5
+ /**
6
+ * @default ""
7
+ */
8
+ label?: React.ReactNode
9
+ /**
10
+ * @default false
11
+ */
12
+ gradient?: boolean
13
+ className?: string
14
+ labelClassName?: string
15
+ }
16
+ //======================================
17
+ export const DDSeparator = ({
18
+ label,
19
+ labelClassName,
20
+ gradient = false,
21
+ className
22
+ }: SeparatorGradientProps) => {
23
+ if (label) {
24
+ return (
25
+ <div className="separator-container flex items-center w-full max-w-full overflow-hidden">
26
+ <div
27
+ className={cn(
28
+ 'rounded-full w-full h-[1px]',
29
+ gradient
30
+ ? 'bg-gradient-to-l from-zinc-500 dark:from-zinc-200 to-transparent dark:to-zinc-700'
31
+ : 'bg-zinc-300 dark:bg-zinc-800',
32
+ className
33
+ )}
34
+ ></div>
35
+ <div
36
+ className={cn(
37
+ labelClassName,
38
+ 'text-black/80 uppercase w-fit dark:text-stone-200/80 text-nowrap px-4'
39
+ )}
40
+ >
41
+ {label}
42
+ </div>
43
+ <div
44
+ className={cn(
45
+ 'rounded-full w-full h-[1px]',
46
+ gradient
47
+ ? 'bg-gradient-to-r from-zinc-500 dark:from-zinc-200 to-transparent dark:to-zinc-700'
48
+ : 'bg-zinc-300 dark:bg-zinc-800',
49
+ className
50
+ )}
51
+ ></div>
52
+ </div>
53
+ )
54
+ }
55
+ return (
56
+ <div
57
+ className={cn(
58
+ 'rounded-full w-full h-[1px]',
59
+ gradient
60
+ ? 'bg-gradient-to-r from-transparent via-zinc-500 dark:via-zinc-200 to-transparent dark:from-zinc-800 dark:to-zinc-700'
61
+ : 'bg-zinc-300 dark:bg-zinc-800',
62
+ className
63
+ )}
64
+ />
65
+ )
66
+ }
@@ -0,0 +1,4 @@
1
+ # DD-Separator
2
+
3
+ Portable first-pass conversion of `SeparatorGradient` from ROUND-TWO-CONVERSION. Project-specific roots and nested unconverted block dependencies were intentionally replaced with local rendering so the template can install into a clean Payload project.
4
+
@@ -0,0 +1,58 @@
1
+ import type { Block } from 'payload'
2
+
3
+ export const DDSeparator: Block = {
4
+ slug: 'DD-Separator',
5
+ interfaceName: 'DDSeparator',
6
+ labels: {
7
+ singular: 'Separator',
8
+ plural: 'Separators'
9
+ },
10
+ fields: [
11
+ {
12
+ name: 'gradient', // ✅ FIXED: Changed from 'gradientDivider' to 'gradient'
13
+ label: 'Gradient Divider',
14
+ type: 'checkbox',
15
+ defaultValue: false,
16
+ admin: {
17
+ description: 'Enable gradient divider effect.'
18
+ }
19
+ },
20
+ {
21
+ name: 'label',
22
+ label: 'Label (Optional)',
23
+ type: 'text',
24
+ required: false,
25
+ admin: {
26
+ description: 'Optional text label in the middle of the separator.'
27
+ }
28
+ },
29
+ {
30
+ admin: {
31
+ initCollapsed: true,
32
+ className: 'custom-css-class'
33
+ },
34
+ type: 'collapsible',
35
+ label: 'Custom Class',
36
+ fields: [
37
+ {
38
+ name: 'labelClassName',
39
+ label: 'Label Class',
40
+ type: 'text',
41
+ required: false,
42
+ admin: {
43
+ description: 'Additional Tailwind or custom CSS classes for the label.'
44
+ }
45
+ },
46
+ {
47
+ name: 'className',
48
+ label: 'Separator Class',
49
+ type: 'text',
50
+ required: false,
51
+ admin: {
52
+ description: 'Additional Tailwind or custom CSS classes.'
53
+ }
54
+ }
55
+ ]
56
+ }
57
+ ]
58
+ }