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,44 @@
1
+ {
2
+ "type": "block",
3
+ "name": "DDHG-ServiceOverview",
4
+ "label": "Service Overview",
5
+ "sourceName": "ServiceOverview",
6
+ "portableName": "DDHG-ServiceOverview",
7
+ "slug": "DDHG-ServiceOverview",
8
+ "version": "0.0.1",
9
+ "source": {
10
+ "repo": "Hadizainal/HeatherGrey2025",
11
+ "originalPath": "src/blocks/ServiceOverview",
12
+ "originalSlug": "serviceOverview",
13
+ "originalConfigExport": "ServiceOverview",
14
+ "originalComponentExport": "ServiceOverviewBlock",
15
+ "originalInterfaceName": "ServiceOverviewBlockProps"
16
+ },
17
+ "files": [
18
+ { "from": "Component.tsx", "to": "src/blocks/DDHG-ServiceOverview/Component.tsx" },
19
+ { "from": "config.ts", "to": "src/blocks/DDHG-ServiceOverview/config.ts" }
20
+ ],
21
+ "dependencies": [
22
+ { "name": "framer-motion" },
23
+ { "name": "lucide-react" }
24
+ ],
25
+ "sharedFiles": [],
26
+ "requiredProjectFiles": [
27
+ { "path": "src/utilities/ui.ts", "reason": "Component uses the cn utility." }
28
+ ],
29
+ "optionalProjectFiles": [],
30
+ "collectionRegistration": { "enabled": true, "collections": ["Pages", "Posts"] },
31
+ "renderBlocksRegistration": { "enabled": true },
32
+ "renderBlocksBehavior": { "wrapperless": false },
33
+ "pageRouteIntegration": { "required": false, "manualSteps": [] },
34
+ "manualSteps": [
35
+ "Run payload generate:types after schema changes."
36
+ ],
37
+ "notes": [
38
+ "Converted from HeatherGrey2025 ServiceOverview.",
39
+ "dbName namespaced to ddhg_svc_overview.",
40
+ "Installer must not overwrite existing target files."
41
+ ],
42
+ "exportName": "DDHGServiceOverview",
43
+ "interfaceName": "DDHGServiceOverview"
44
+ }
@@ -0,0 +1,389 @@
1
+ 'use client'
2
+
3
+ import { AnimatePresence, motion } from 'framer-motion'
4
+ import {
5
+ CalendarCheck,
6
+ ChevronDown,
7
+ ChevronUp,
8
+ ClipboardList,
9
+ FileText,
10
+ HandHeart,
11
+ RefreshCw,
12
+ ShieldCheck,
13
+ User,
14
+ UserStar,
15
+ } from 'lucide-react'
16
+ import React, { useState } from 'react'
17
+
18
+ import { cn } from '@/utilities/ui'
19
+
20
+ type TrustBadge = {
21
+ icon?:
22
+ | 'shieldCheck'
23
+ | 'calendarCheck'
24
+ | 'userStar'
25
+ | 'fileText'
26
+ | 'refreshCw'
27
+ | 'handHeart'
28
+ | 'clipboardList'
29
+ | null
30
+ title?: string | null
31
+ description?: string | null
32
+ desc?: string | null
33
+ id?: string | null
34
+ }
35
+
36
+ type TestimonialItem = {
37
+ quote?: string | null
38
+ author?: string | null
39
+ role?: string | null
40
+ id?: string | null
41
+ }
42
+
43
+ type FAQItem = {
44
+ question?: string | null
45
+ q?: string | null
46
+ answer?: string | null
47
+ a?: string | null
48
+ id?: string | null
49
+ }
50
+
51
+ export type DDHGStatsFAQProps = {
52
+ sectionId?: string | null
53
+ customClassName?: string | null
54
+ customCSS?: string | null
55
+ blockId?: string | null
56
+ scrollSpeed?: string | number | null
57
+ testimonials?: TestimonialItem[] | null
58
+ commitmentLabel?: string | null
59
+ commitmentHeading?: string | null
60
+ trustBadges?: TrustBadge[] | null
61
+ faqEyebrowPrefix?: string | null
62
+ faqEyebrowEmphasis?: string | null
63
+ faqHeading?: string | null
64
+ showFaqDivider?: boolean | null
65
+ faqs?: FAQItem[] | null
66
+ }
67
+
68
+ const defaultTrustBadges: TrustBadge[] = [
69
+ {
70
+ icon: 'shieldCheck',
71
+ title: 'Transparent Pricing',
72
+ description: 'Every quote is itemized. No hidden fees, no surprise charges at the end.',
73
+ },
74
+ {
75
+ icon: 'calendarCheck',
76
+ title: 'Fixed Timeline Guarantee',
77
+ description: 'We commit to a delivery date and stick to it. If we miss it, you get a credit.',
78
+ },
79
+ {
80
+ icon: 'userStar',
81
+ title: 'Dedicated Project Lead',
82
+ description: 'One senior designer owns your project from kickoff to handover. No handoffs.',
83
+ },
84
+ {
85
+ icon: 'fileText',
86
+ title: 'Full Documentation',
87
+ description: 'Every finish, fixture, and specification is documented for future reference.',
88
+ },
89
+ {
90
+ icon: 'refreshCw',
91
+ title: 'Revision Rounds Included',
92
+ description: 'Three structured revision cycles are included in every engagement.',
93
+ },
94
+ {
95
+ icon: 'handHeart',
96
+ title: 'Post-Completion Support',
97
+ description: '30 days of complimentary support after handover. We stand by our work.',
98
+ },
99
+ ]
100
+
101
+ const defaultTestimonials: TestimonialItem[] = [
102
+ {
103
+ quote:
104
+ 'They delivered exactly what they promised, on the date they promised it, at the price they quoted. That alone is rare in this industry.',
105
+ author: 'Margaret Chen',
106
+ role: 'Director of Operations, Meridian Holdings',
107
+ },
108
+ {
109
+ quote:
110
+ 'The transparency throughout the process was remarkable. We knew exactly where we stood at every phase. No surprises.',
111
+ author: 'James Oduya',
112
+ role: 'Founder, The Atelier Collective',
113
+ },
114
+ ]
115
+
116
+ const defaultFaqs: FAQItem[] = [
117
+ {
118
+ question: 'How long does a typical project take?',
119
+ answer:
120
+ 'Project timelines vary based on scope. A residential interior typically takes 8-16 weeks from concept to completion. Commercial fit-outs range from 12-24 weeks. We provide detailed timelines during our initial consultation.',
121
+ },
122
+ {
123
+ question: 'Do you handle both design and construction?',
124
+ answer:
125
+ 'Yes, our Turn-Key Services cover the complete journey from initial concept through construction to final handover. We coordinate all contractors and trades, ensuring the design vision is executed faithfully.',
126
+ },
127
+ {
128
+ question: 'Can you work with existing furniture and art?',
129
+ answer:
130
+ 'Absolutely. Our Atmospheric Curation service specializes in integrating existing pieces into new designs. We view heirlooms and collected art as anchors of identity within the space.',
131
+ },
132
+ {
133
+ question: 'What is your fee structure?',
134
+ answer:
135
+ 'We offer both fixed-fee and percentage-based pricing depending on project type. Design Consultancy is typically fixed-fee, while Turn-Key projects use a percentage of construction cost. We provide transparent quotes upfront.',
136
+ },
137
+ {
138
+ question: 'Do you offer sustainability-focused design?',
139
+ answer:
140
+ 'Sustainability is woven into our material selection and spatial planning. We prioritize low-VOC finishes, responsibly sourced materials, energy-efficient lighting, and biophilic elements that reduce environmental impact.',
141
+ },
142
+ ]
143
+
144
+ const iconMap = {
145
+ shieldCheck: ShieldCheck,
146
+ calendarCheck: CalendarCheck,
147
+ userStar: UserStar,
148
+ fileText: FileText,
149
+ refreshCw: RefreshCw,
150
+ handHeart: HandHeart,
151
+ clipboardList: ClipboardList,
152
+ }
153
+
154
+ function RevealBlock({
155
+ children,
156
+ className,
157
+ delay = 0,
158
+ }: {
159
+ children: React.ReactNode
160
+ className?: string
161
+ delay?: number
162
+ }) {
163
+ return (
164
+ <motion.div
165
+ className={className}
166
+ initial={{ opacity: 0, y: 20 }}
167
+ whileInView={{ opacity: 1, y: 0 }}
168
+ viewport={{ once: true, amount: 0.18 }}
169
+ transition={{ duration: 0.9, delay, ease: [0.22, 1, 0.36, 1] }}
170
+ >
171
+ {children}
172
+ </motion.div>
173
+ )
174
+ }
175
+
176
+ const getItems = <T,>(items: T[] | null | undefined, fallback: T[]) =>
177
+ Array.isArray(items) && items.length > 0 ? items : fallback
178
+
179
+ export const DDHGStatsFAQ: React.FC<DDHGStatsFAQProps> = ({
180
+ sectionId,
181
+ customClassName,
182
+ customCSS,
183
+ blockId,
184
+ scrollSpeed,
185
+ testimonials,
186
+ commitmentLabel = 'Our Commitment',
187
+ commitmentHeading = 'Why Clients Trust Us',
188
+ trustBadges,
189
+ faqEyebrowPrefix = 'common',
190
+ faqEyebrowEmphasis = 'questions',
191
+ faqHeading = 'FAQ',
192
+ showFaqDivider = true,
193
+ faqs,
194
+ }) => {
195
+ const [openFAQ, setOpenFAQ] = useState<number | null>(null)
196
+ const testimonialItems = getItems(testimonials, defaultTestimonials)
197
+ const badgeItems = getItems(trustBadges, defaultTrustBadges)
198
+ const faqItems = getItems(faqs, defaultFaqs)
199
+
200
+ return (
201
+ <div
202
+ id={sectionId ?? undefined}
203
+ data-block-id={blockId ?? undefined}
204
+ data-scroll={scrollSpeed ? true : undefined}
205
+ data-scroll-speed={scrollSpeed ? String(scrollSpeed) : undefined}
206
+ className={cn('px-5 py-16 md:px-8', customClassName)}
207
+ >
208
+ {customCSS && <style dangerouslySetInnerHTML={{ __html: customCSS }} />}
209
+ <div className="mx-auto max-w-7xl">
210
+ {testimonialItems.length > 0 && (
211
+ <RevealBlock className="testimonial-section mb-16">
212
+ <div className="grid grid-cols-1 gap-6 md:grid-cols-2">
213
+ {testimonialItems.map((testimonial, i) => (
214
+ <div
215
+ key={testimonial.id || `testimonial-${i}`}
216
+ className="z-plane-1 chamfer-accent rounded-md squircle border border-stone-300 bg-stone-100/50 p-6 transition-all duration-300 dark:border-stone-700/10 dark:bg-stone-900/50 md:p-8"
217
+ >
218
+ <div className="mb-4 h-px w-8 bg-[#C4A882]" />
219
+ {testimonial.quote && (
220
+ <p className="mb-6 text-base font-light leading-relaxed text-stone-700 dark:text-stone-200">
221
+ &ldquo;{testimonial.quote}&rdquo;
222
+ </p>
223
+ )}
224
+ <div className="flex items-center gap-3">
225
+ <div
226
+ className="flex h-8 w-8 items-center justify-center bg-stone-500"
227
+ style={{ borderRadius: '6px' }}
228
+ >
229
+ <User className="h-3.5 w-3.5 text-stone-50" strokeWidth={1.6} />
230
+ </div>
231
+ <div>
232
+ {testimonial.author && (
233
+ <p className="text-base font-medium text-stone-700 dark:text-stone-200">
234
+ {testimonial.author}
235
+ </p>
236
+ )}
237
+ {testimonial.role && (
238
+ <p className="text-base text-stone-600 dark:text-stone-300">
239
+ {testimonial.role}
240
+ </p>
241
+ )}
242
+ </div>
243
+ </div>
244
+ </div>
245
+ ))}
246
+ </div>
247
+ </RevealBlock>
248
+ )}
249
+
250
+ {badgeItems.length > 0 && (
251
+ <RevealBlock className="whytrustus-section mb-16">
252
+ <div className="z-plane-1 rounded-md squircle border border-stone-300 bg-stone-100/50 p-6 dark:border-stone-700/10 dark:bg-stone-900/50 md:p-8">
253
+ <div className="mb-6">
254
+ {commitmentLabel && (
255
+ <p className="mb-2 font-mono text-base uppercase tracking-[0.15em] text-stone-600 dark:text-stone-300">
256
+ {commitmentLabel}
257
+ </p>
258
+ )}
259
+ {commitmentHeading && (
260
+ <h3 className="text-xl font-semibold text-purple-700 dark:text-purple-500">
261
+ {commitmentHeading}
262
+ </h3>
263
+ )}
264
+ </div>
265
+ <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
266
+ {badgeItems.map((badge, i) => {
267
+ const Icon = iconMap[badge.icon || 'shieldCheck'] || ShieldCheck
268
+ const description = badge.description || badge.desc || ''
269
+ return (
270
+ <div
271
+ key={badge.id || `${badge.title || 'badge'}-${i}`}
272
+ className="arch-edge-sm flex items-start gap-3 rounded-md squircle border border-stone-300 bg-stone-100/50 p-4 transition-all duration-300 hover:-translate-y-1 hover:shadow-lg dark:border-stone-700/10 dark:bg-stone-900/50"
273
+ >
274
+ <div className="mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center">
275
+ <Icon className="h-4 w-4 text-[#C4A882]" strokeWidth={1.7} />
276
+ </div>
277
+ <div>
278
+ {badge.title && (
279
+ <p className="mb-1 text-base font-medium text-stone-700 dark:text-stone-200">
280
+ {badge.title}
281
+ </p>
282
+ )}
283
+ {description && (
284
+ <p className="text-xs font-light leading-relaxed text-stone-700 dark:text-stone-200">
285
+ {description}
286
+ </p>
287
+ )}
288
+ </div>
289
+ </div>
290
+ )
291
+ })}
292
+ </div>
293
+ </div>
294
+ </RevealBlock>
295
+ )}
296
+
297
+ <RevealBlock className="faq-section max-w-4xl mx-auto mb-10">
298
+ {(faqEyebrowPrefix || faqEyebrowEmphasis) && (
299
+ <p className="mb-2 text-xs uppercase tracking-[0.2em] text-stone-600 dark:text-stone-300">
300
+ {faqEyebrowPrefix && <span className="font-light">{faqEyebrowPrefix} </span>}
301
+ {faqEyebrowEmphasis && <span className="font-medium">{faqEyebrowEmphasis}</span>}
302
+ </p>
303
+ )}
304
+ {faqHeading && (
305
+ <h2 className="mb-3 text-3xl font-medium leading-none tracking-tight text-purple-700 dark:text-purple-500 md:text-4xl">
306
+ {faqHeading}
307
+ </h2>
308
+ )}
309
+ {showFaqDivider && <div className="h-px w-12 bg-stone-500" />}
310
+ </RevealBlock>
311
+
312
+ {faqItems.length > 0 && (
313
+ <div className="faq-wrapper max-w-4xl mx-auto space-y-3">
314
+ {faqItems.map((faq, i) => {
315
+ const isOpen = openFAQ === i
316
+ const question = faq.question || faq.q || ''
317
+ const answer = faq.answer || faq.a || ''
318
+ const ToggleIcon = isOpen ? ChevronUp : ChevronDown
319
+ return (
320
+ <RevealBlock key={faq.id || `${question || 'faq'}-${i}`} delay={i * 0.06}>
321
+ <div
322
+ className={cn(
323
+ 'accordion-card z-plane-1 rounded-md squircle border-border border chamfer-accent bg-stone-100/50 transition-all duration-300 dark:bg-stone-900/50',
324
+ isOpen &&
325
+ 'border-border border z-depth-hover hover:shadow-2xl hover:-translate-y-2',
326
+ )}
327
+ >
328
+ <button
329
+ type="button"
330
+ onClick={() => setOpenFAQ(isOpen ? null : i)}
331
+ className="accordion-btn flex w-full items-center justify-between p-5 text-left md:p-6"
332
+ aria-expanded={isOpen}
333
+ >
334
+ <div className="flex items-center gap-4">
335
+ <span className="font-mono text-base text-stone-600 dark:text-stone-300">
336
+ {String(i + 1).padStart(2, '0')}
337
+ </span>
338
+ {question && (
339
+ <h3 className="text-sm font-medium text-purple-700 dark:text-purple-500">
340
+ {question}
341
+ </h3>
342
+ )}
343
+ </div>
344
+ <div
345
+ className={cn(
346
+ 'ml-4 flex h-6 w-6 shrink-0 items-center justify-center rounded-md squircle border border-stone-300 dark:border-stone-700/10 transition-all duration-300',
347
+ isOpen && 'border-[#292524] bg-[#292524]',
348
+ )}
349
+ style={{ borderRadius: '6px' }}
350
+ >
351
+ <ToggleIcon
352
+ className={cn(
353
+ 'h-3 w-3',
354
+ isOpen ? 'text-[#F5F3EF]' : 'text-stone-600 dark:text-stone-300',
355
+ )}
356
+ strokeWidth={1.8}
357
+ />
358
+ </div>
359
+ </button>
360
+ <AnimatePresence initial={false}>
361
+ {isOpen && answer && (
362
+ <motion.div
363
+ initial={{ height: 0, opacity: 0 }}
364
+ animate={{ height: 'auto', opacity: 1 }}
365
+ exit={{ height: 0, opacity: 0 }}
366
+ transition={{ duration: 0.45, ease: [0.22, 1, 0.36, 1] }}
367
+ className="overflow-hidden"
368
+ >
369
+ <div className="px-5 pb-5 pl-14 md:px-6 md:pb-6 md:pl-16">
370
+ <div className="mb-4 h-px w-full bg-stone-500" />
371
+ <p className="text-base font-light leading-relaxed text-stone-700 dark:text-stone-200">
372
+ {answer}
373
+ </p>
374
+ </div>
375
+ </motion.div>
376
+ )}
377
+ </AnimatePresence>
378
+ </div>
379
+ </RevealBlock>
380
+ )
381
+ })}
382
+ </div>
383
+ )}
384
+ </div>
385
+ </div>
386
+ )
387
+ }
388
+
389
+ export default DDHGStatsFAQ
@@ -0,0 +1,204 @@
1
+ import type { Block } from 'payload'
2
+
3
+ export const DDHGStatsFAQ: Block = {
4
+ slug: 'DDHG-StatsFAQ',
5
+ interfaceName: 'DDHGStatsFAQ',
6
+ dbName: 'ddhg_stats_faq',
7
+ labels: {
8
+ singular: 'Stats FAQ',
9
+ plural: 'Stats FAQs',
10
+ },
11
+ fields: [
12
+ {
13
+ type: 'tabs',
14
+ tabs: [
15
+ {
16
+ label: 'Testimonials',
17
+ fields: [
18
+ {
19
+ name: 'testimonials',
20
+ type: 'array',
21
+ label: 'Testimonials',
22
+ dbName: 'quotes',
23
+ labels: { singular: 'Testimonial', plural: 'Testimonials' },
24
+ fields: [
25
+ { name: 'quote', type: 'textarea', label: 'Quote', required: true },
26
+ {
27
+ type: 'row',
28
+ fields: [
29
+ {
30
+ name: 'author',
31
+ type: 'text',
32
+ label: 'Author',
33
+ required: true,
34
+ admin: { width: '50%' },
35
+ },
36
+ {
37
+ name: 'role',
38
+ type: 'text',
39
+ label: 'Role / Company',
40
+ admin: { width: '50%' },
41
+ },
42
+ ],
43
+ },
44
+ ],
45
+ },
46
+ ],
47
+ },
48
+ {
49
+ label: 'Trust Badges',
50
+ fields: [
51
+ {
52
+ type: 'row',
53
+ fields: [
54
+ {
55
+ name: 'commitmentLabel',
56
+ type: 'text',
57
+ label: 'Commitment Label',
58
+ defaultValue: 'Our Commitment',
59
+ admin: { width: '50%' },
60
+ },
61
+ {
62
+ name: 'commitmentHeading',
63
+ type: 'text',
64
+ label: 'Commitment Heading',
65
+ defaultValue: 'Why Clients Trust Us',
66
+ admin: { width: '50%' },
67
+ },
68
+ ],
69
+ },
70
+ {
71
+ name: 'trustBadges',
72
+ type: 'array',
73
+ label: 'Trust Badges',
74
+ dbName: 'badges',
75
+ labels: { singular: 'Trust Badge', plural: 'Trust Badges' },
76
+ fields: [
77
+ {
78
+ type: 'row',
79
+ fields: [
80
+ {
81
+ name: 'icon',
82
+ type: 'select',
83
+ label: 'Icon',
84
+ defaultValue: 'shieldCheck',
85
+ admin: { width: '33.33%' },
86
+ options: [
87
+ { label: 'Shield Check', value: 'shieldCheck' },
88
+ { label: 'Calendar Check', value: 'calendarCheck' },
89
+ { label: 'User Star', value: 'userStar' },
90
+ { label: 'File Text', value: 'fileText' },
91
+ { label: 'Refresh', value: 'refreshCw' },
92
+ { label: 'Hand Heart', value: 'handHeart' },
93
+ { label: 'Clipboard List', value: 'clipboardList' },
94
+ ],
95
+ },
96
+ {
97
+ name: 'title',
98
+ type: 'text',
99
+ label: 'Title',
100
+ required: true,
101
+ admin: { width: '66.66%' },
102
+ },
103
+ ],
104
+ },
105
+ { name: 'description', type: 'textarea', label: 'Description' },
106
+ ],
107
+ },
108
+ ],
109
+ },
110
+ {
111
+ label: 'FAQ',
112
+ fields: [
113
+ {
114
+ type: 'row',
115
+ fields: [
116
+ {
117
+ name: 'faqEyebrowPrefix',
118
+ type: 'text',
119
+ label: 'FAQ Eyebrow Prefix',
120
+ defaultValue: 'common',
121
+ admin: { width: '50%' },
122
+ },
123
+ {
124
+ name: 'faqEyebrowEmphasis',
125
+ type: 'text',
126
+ label: 'FAQ Eyebrow Emphasis',
127
+ defaultValue: 'questions',
128
+ admin: { width: '50%' },
129
+ },
130
+ ],
131
+ },
132
+ {
133
+ type: 'row',
134
+ fields: [
135
+ {
136
+ name: 'faqHeading',
137
+ type: 'text',
138
+ label: 'FAQ Heading',
139
+ defaultValue: 'FAQ',
140
+ admin: { width: '75%' },
141
+ },
142
+ {
143
+ name: 'showFaqDivider',
144
+ type: 'checkbox',
145
+ label: 'Show Divider',
146
+ defaultValue: true,
147
+ admin: { width: '25%' },
148
+ },
149
+ ],
150
+ },
151
+ {
152
+ name: 'faqs',
153
+ type: 'array',
154
+ label: 'FAQ Items',
155
+ dbName: 'faqs',
156
+ labels: { singular: 'FAQ Item', plural: 'FAQ Items' },
157
+ fields: [
158
+ { name: 'question', type: 'text', label: 'Question', required: true },
159
+ { name: 'answer', type: 'textarea', label: 'Answer', required: true },
160
+ ],
161
+ },
162
+ ],
163
+ },
164
+ {
165
+ label: 'Advanced',
166
+ fields: [
167
+ {
168
+ type: 'row',
169
+ fields: [
170
+ {
171
+ name: 'sectionId',
172
+ type: 'text',
173
+ label: 'Section ID',
174
+ admin: { width: '50%' },
175
+ },
176
+ {
177
+ name: 'customClassName',
178
+ type: 'text',
179
+ label: 'Custom CSS Classes',
180
+ admin: { width: '50%' },
181
+ },
182
+ ],
183
+ },
184
+ {
185
+ name: 'scrollSpeed',
186
+ type: 'text',
187
+ label: 'Scroll Speed',
188
+ admin: { description: 'Optional data-scroll-speed value.' },
189
+ },
190
+ {
191
+ name: 'customCSS',
192
+ type: 'code',
193
+ label: 'Custom CSS',
194
+ admin: {
195
+ language: 'css',
196
+ description: 'Injected as a style tag. Use with caution.',
197
+ },
198
+ },
199
+ ],
200
+ },
201
+ ],
202
+ },
203
+ ],
204
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "type": "block",
3
+ "name": "DDHG-StatsFAQ",
4
+ "label": "Stats FAQ",
5
+ "sourceName": "StatsFAQ",
6
+ "portableName": "DDHG-StatsFAQ",
7
+ "slug": "DDHG-StatsFAQ",
8
+ "version": "0.0.1",
9
+ "source": {
10
+ "repo": "Hadizainal/HeatherGrey2025",
11
+ "originalPath": "src/blocks/StatsFAQ",
12
+ "originalSlug": "statsFAQ",
13
+ "originalConfigExport": "StatsFAQ",
14
+ "originalComponentExport": "StatsFAQBlock",
15
+ "originalInterfaceName": "StatsFAQBlockProps"
16
+ },
17
+ "files": [
18
+ { "from": "Component.tsx", "to": "src/blocks/DDHG-StatsFAQ/Component.tsx" },
19
+ { "from": "config.ts", "to": "src/blocks/DDHG-StatsFAQ/config.ts" }
20
+ ],
21
+ "dependencies": [
22
+ { "name": "framer-motion" },
23
+ { "name": "lucide-react" }
24
+ ],
25
+ "sharedFiles": [],
26
+ "requiredProjectFiles": [
27
+ { "path": "src/utilities/ui.ts", "reason": "Component uses the cn utility." }
28
+ ],
29
+ "optionalProjectFiles": [],
30
+ "collectionRegistration": { "enabled": true, "collections": ["Pages", "Posts"] },
31
+ "renderBlocksRegistration": { "enabled": true },
32
+ "renderBlocksBehavior": { "wrapperless": false },
33
+ "pageRouteIntegration": { "required": false, "manualSteps": [] },
34
+ "manualSteps": [
35
+ "Review HeatherGrey-specific utility classes such as z-plane, chamfer and arch-edge in the destination theme.",
36
+ "Run payload generate:types after schema changes."
37
+ ],
38
+ "notes": [
39
+ "Converted from HeatherGrey2025 StatsFAQ.",
40
+ "The top-level dbName was namespaced to ddhg_stats_faq for portability.",
41
+ "Installer must not overwrite existing target files."
42
+ ],
43
+ "exportName": "DDHGStatsFAQ",
44
+ "interfaceName": "DDHGStatsFAQ"
45
+ }