blocks-dusted 0.1.9 → 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 (248) 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/components/HeaderDD02/MobileBottomNav/index.tsx +352 -257
  221. package/templates/components/HeaderDD02/index.tsx +313 -229
  222. package/templates/shared/src/components/BgLightning/index.tsx +242 -0
  223. package/templates/shared/src/components/ui/ShareButton/index.tsx +80 -0
  224. package/templates/shared/src/components/ui/anims/FadeOnScroll.tsx +48 -0
  225. package/templates/shared/src/components/ui/anims/FadeUpOnInView.tsx +63 -0
  226. package/templates/shared/src/components/ui/anims/GlareHover.tsx +111 -0
  227. package/templates/shared/src/components/ui/anims/LineAnims.tsx +81 -0
  228. package/templates/shared/src/components/ui/anims/TitleAnims01.tsx +54 -0
  229. package/templates/shared/src/components/ui/anims/animation-container.tsx +29 -0
  230. package/templates/shared/src/components/ui/anims/blur-in.tsx +26 -0
  231. package/templates/shared/src/components/ui/anims/counter.tsx +53 -0
  232. package/templates/shared/src/components/ui/anims/fade.tsx +83 -0
  233. package/templates/shared/src/components/ui/anims/gradual-spacing.tsx +39 -0
  234. package/templates/shared/src/components/ui/anims/pull-up.tsx +93 -0
  235. package/templates/shared/src/components/ui/anims/reveal-text.tsx +76 -0
  236. package/templates/shared/src/components/ui/anims/rotate-words.tsx +43 -0
  237. package/templates/shared/src/components/ui/anims/shiny-text.tsx +58 -0
  238. package/templates/shared/src/components/ui/anims/shuffle-text.tsx +85 -0
  239. package/templates/shared/src/components/ui/anims/split-text.tsx +211 -0
  240. package/templates/shared/src/components/ui/anims/staggered-fade.tsx +133 -0
  241. package/templates/shared/src/components/ui/anims/text-scroll.tsx +111 -0
  242. package/templates/shared/src/components/ui/anims/typing-effect.tsx +112 -0
  243. package/templates/shared/src/components/ui/button-dusted-fluid/index.tsx +1521 -0
  244. package/templates/shared/src/components/ui/separator.tsx +85 -0
  245. package/templates/shared/src/hooks/useBodyScrollLock.ts +97 -0
  246. package/templates/shared/src/hooks/useClickOutside.ts +28 -0
  247. package/templates/shared/src/utilities/renderCustomCSS.ts +5 -0
  248. package/templates/shared/src/utilities/smoothScroll.ts +65 -0
@@ -0,0 +1,46 @@
1
+ {
2
+ "type": "block",
3
+ "name": "DDHG-HighlightArc",
4
+ "label": "Highlight Archive Cards",
5
+ "sourceName": "HighlightArchiveCards",
6
+ "portableName": "DDHG-HighlightArc",
7
+ "slug": "DDHG-HighlightArc",
8
+ "version": "0.0.1",
9
+ "source": {
10
+ "repo": "Hadizainal/HeatherGrey2025",
11
+ "originalPath": "src/blocks/HighlightArchiveCards",
12
+ "originalSlug": "highlightArchiveCards",
13
+ "originalConfigExport": "HighlightArchiveCards",
14
+ "originalComponentExport": "HighlightArchiveCardsBlock",
15
+ "originalInterfaceName": "HighlightArchiveCardsBlock"
16
+ },
17
+ "files": [
18
+ { "from": "Component.tsx", "to": "src/blocks/DDHG-HighlightArc/Component.tsx" },
19
+ { "from": "config.ts", "to": "src/blocks/DDHG-HighlightArc/config.ts" }
20
+ ],
21
+ "dependencies": [{ "name": "lucide-react" }],
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
+ { "path": "src/components/Admin/BeforeSidebar", "reason": "Archive bundle admin UI field is currently commented out and can be restored when that bundle is imported." }
29
+ ],
30
+ "collectionRegistration": { "enabled": true, "collections": ["Pages", "Posts"] },
31
+ "renderBlocksRegistration": { "enabled": true },
32
+ "renderBlocksBehavior": { "wrapperless": false },
33
+ "pageRouteIntegration": { "required": false, "manualSteps": [] },
34
+ "manualSteps": [
35
+ "Review this block together with the future archive bundle before re-enabling the BeforeSidebar admin field.",
36
+ "Run payload generate:types after schema changes."
37
+ ],
38
+ "notes": [
39
+ "Converted from HeatherGrey2025 HighlightArchiveCards.",
40
+ "BeforeSidebar is intentionally commented out pending the archive collection bundle review.",
41
+ "Generated Payload document types were replaced with portable structural types.",
42
+ "Installer must not overwrite existing target files."
43
+ ],
44
+ "exportName": "DDHGHighlightArc",
45
+ "interfaceName": "DDHGHighlightArc"
46
+ }
@@ -0,0 +1,93 @@
1
+ 'use client'
2
+
3
+ import React, { useState } from 'react'
4
+ import { motion } from 'framer-motion'
5
+ import Image from 'next/image'
6
+ import { cn } from '@/utilities/ui'
7
+ // DDHG TODO: Re-enable after reviewing the project-specific separator/custom CSS bundle.
8
+ // import { Separator } from '@/components/ui/separator'
9
+ // import { extractCustomCSS } from '@/utilities/renderCustomCSS'
10
+
11
+ const placeholderBlur =
12
+ 'data:image/svg+xml;base64,' +
13
+ btoa(`<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg" style="opacity:0"><rect width="100%" height="100%" fill="transparent" /></svg>`)
14
+
15
+ type LogoItem = {
16
+ image?: { url?: string | null; alt?: string | null } | null
17
+ imageClass?: string | null
18
+ imageStyle?: React.CSSProperties
19
+ imageAltClass?: string | null
20
+ }
21
+
22
+ export type DDHGLogoMarqueeProps = {
23
+ sectionId?: string | null
24
+ logos?: LogoItem[] | null
25
+ speed?: number | null
26
+ spacing?: number | null
27
+ priority?: boolean | null
28
+ showTopDivider?: boolean | null
29
+ showBottomDivider?: boolean | null
30
+ containerClass?: string | null
31
+ itemWidth?: number | null
32
+ enableCustomCSS?: boolean | null
33
+ customCSS?: Array<{ blockType?: string; css?: string }> | string | null
34
+ }
35
+
36
+ const LogoImage: React.FC<{ src: string; alt?: string | null; customClass?: string | null; imageStyle?: React.CSSProperties; priority?: boolean }> = ({ src, alt, customClass, imageStyle, priority = false }) => {
37
+ const [imageError, setImageError] = useState(false)
38
+ const imageSrc = !src || imageError ? placeholderBlur : src
39
+ return <Image src={imageSrc} alt={alt || 'Logo'} width={300} height={300} priority={priority} className={customClass || ''} style={{ objectFit: 'contain', ...(imageStyle && typeof imageStyle === 'object' ? imageStyle : {}) }} onError={() => setImageError(true)} placeholder="blur" blurDataURL={placeholderBlur} />
40
+ }
41
+
42
+ export const DDHGLogoMarquee: React.FC<DDHGLogoMarqueeProps> = ({
43
+ sectionId,
44
+ logos,
45
+ speed = 10,
46
+ spacing = 32,
47
+ priority = false,
48
+ showTopDivider = false,
49
+ showBottomDivider = false,
50
+ containerClass = 'overflow-hidden py-8 bg-transparent',
51
+ enableCustomCSS = false,
52
+ customCSS,
53
+ itemWidth,
54
+ }) => {
55
+ const validLogos = Array.isArray(logos) ? logos : []
56
+ if (validLogos.length === 0) return null
57
+ const calculatedItemWidth = itemWidth || 100
58
+ const totalWidth = validLogos.length * (calculatedItemWidth + (spacing || 0))
59
+
60
+ // DDHG TODO: Re-enable with extractCustomCSS when that bundle is reviewed.
61
+ // const extractedCSS = enableCustomCSS && Array.isArray(customCSS)
62
+ // ? extractCustomCSS(customCSS)
63
+ // : typeof customCSS === 'string'
64
+ // ? customCSS
65
+ // : ''
66
+ const extractedCSS = ''
67
+ void enableCustomCSS
68
+ void customCSS
69
+ void showTopDivider
70
+ void showBottomDivider
71
+
72
+ const renderSet = (suffix = '') => validLogos.map((logo, index) => (
73
+ <div key={`logo-${index}${suffix}`} className="marque-image-container flex-shrink-0 flex flex-col items-center justify-center" style={{ marginRight: `${spacing || 0}px`, ...(itemWidth ? { width: `${calculatedItemWidth}px` } : { minWidth: `${calculatedItemWidth}px` }) }}>
74
+ <LogoImage src={logo.image?.url || placeholderBlur} alt={logo.image?.alt} customClass={logo.imageClass} imageStyle={logo.imageStyle} priority={Boolean(priority)} />
75
+ <p className={cn('text-base text-center', logo.imageAltClass)}>{logo.image?.alt || null}</p>
76
+ </div>
77
+ ))
78
+
79
+ return <>
80
+ {/* DDHG TODO: Re-enable optional Separator rendering after bundle review. */}
81
+ {/* {showTopDivider && <Separator gradient={true} className="border-seperator" />} */}
82
+ <div id={sectionId ?? undefined} className="logo-marquee-block relative mx-auto">
83
+ {extractedCSS && <style dangerouslySetInnerHTML={{ __html: extractedCSS }} />}
84
+ <motion.div className={`${containerClass} flex py-4`} animate={{ x: [0, -totalWidth] }} transition={{ repeat: Infinity, duration: speed || 10, ease: 'linear' }} style={{ width: `${totalWidth * 2}px` }}>
85
+ {renderSet()}
86
+ {renderSet('-duplicate')}
87
+ </motion.div>
88
+ </div>
89
+ {/* {showBottomDivider && <Separator gradient={true} className="border-seperator opacity-20" />} */}
90
+ </>
91
+ }
92
+
93
+ export default DDHGLogoMarquee
@@ -0,0 +1,66 @@
1
+ import type { Block } from 'payload'
2
+ // DDHG TODO: Re-enable with the project-specific CustomCssBlock bundle.
3
+ // import { CustomCSSBlock } from '@/blocks/CustomCssBlock/config'
4
+
5
+ export const DDHGLogoMarquee: Block = {
6
+ slug: 'DDHG-LogoMarquee',
7
+ interfaceName: 'DDHGLogoMarquee',
8
+ labels: { singular: 'Image Marquee', plural: 'Image Marquee' },
9
+ fields: [
10
+ { name: 'sectionId', type: 'text', label: 'Section ID', required: false, admin: { description: 'Optional anchor ID for linking and scroll targets.' } },
11
+ {
12
+ type: 'collapsible', label: 'Block Settings', admin: { initCollapsed: true, className: 'custom-css-class' },
13
+ fields: [
14
+ { type: 'collapsible', label: 'Container Class', admin: { initCollapsed: true, className: 'custom-css-class' }, fields: [
15
+ { name: 'containerClass', label: false, type: 'text', required: false, admin: { description: 'Override the default container class.' } },
16
+ ] },
17
+ { type: 'collapsible', label: 'Marquee Settings', admin: { initCollapsed: true, className: 'custom-group-class' }, fields: [
18
+ { type: 'row', fields: [
19
+ { name: 'speed', type: 'number', label: 'Scroll Speed (seconds)', defaultValue: 10, required: true, admin: { width: '50%' } },
20
+ { name: 'spacing', type: 'number', label: 'Spacing between images (px)', defaultValue: 32, required: true, admin: { width: '50%' } },
21
+ ] },
22
+ ] },
23
+ { name: 'priority', type: 'checkbox', label: 'High Priority Loading', defaultValue: false },
24
+ { type: 'collapsible', label: 'Dividers', admin: { initCollapsed: true, className: 'custom-group-class' }, fields: [
25
+ { name: 'showTopDivider', type: 'checkbox', label: 'Show Top Divider' },
26
+ { name: 'showBottomDivider', type: 'checkbox', label: 'Show Bottom Divider' },
27
+ ] },
28
+ ],
29
+ },
30
+ {
31
+ name: 'logoImages', type: 'upload', relationTo: 'media', hasMany: true, required: false,
32
+ filterOptions: { mimeType: { contains: 'image' } },
33
+ hooks: { beforeChange: [({ value, siblingData }) => {
34
+ if (!Array.isArray(value) || value.length === 0) return value
35
+ const existingLogos = Array.isArray((siblingData as any)?.logos) ? (siblingData as any).logos : []
36
+ const normalizeImageId = (imageValue: unknown): number | string | undefined => {
37
+ if (typeof imageValue === 'number' || typeof imageValue === 'string') return imageValue
38
+ if (imageValue && typeof imageValue === 'object' && 'id' in (imageValue as any)) {
39
+ const maybeId = (imageValue as any).id
40
+ if (typeof maybeId === 'number' || typeof maybeId === 'string') return maybeId
41
+ }
42
+ return undefined
43
+ }
44
+ const existingIds = new Set(existingLogos.map((row: any) => normalizeImageId(row?.image)).filter((id: any) => id !== undefined))
45
+ const newRows = value.map((id) => normalizeImageId(id)).filter((id): id is number | string => id !== undefined).filter((id) => !existingIds.has(id)).map((id) => ({ image: id, imageAltClass: 'hidden', imageClass: '' }))
46
+ ;(siblingData as any).logos = [...existingLogos, ...newRows]
47
+ return []
48
+ }] },
49
+ },
50
+ {
51
+ name: 'logos', type: 'array', label: 'Images', labels: { singular: 'Image', plural: 'Images' },
52
+ fields: [
53
+ { name: 'image', type: 'upload', relationTo: 'media', required: false, filterOptions: { mimeType: { contains: 'image' } } },
54
+ { type: 'collapsible', label: 'Alt Text Class', admin: { initCollapsed: true, className: 'custom-css-class' }, fields: [
55
+ { name: 'imageAltClass', label: false, type: 'text', required: false, defaultValue: 'hidden' },
56
+ ] },
57
+ { type: 'collapsible', label: 'Image Class', admin: { initCollapsed: true, className: 'custom-css-class' }, fields: [
58
+ { name: 'imageClass', label: false, type: 'text', required: false },
59
+ ] },
60
+ ],
61
+ },
62
+ // DDHG TODO: Re-enable custom CSS support after reviewing the CustomCssBlock bundle.
63
+ // { name: 'enableCustomCSS', type: 'checkbox', label: 'Inject Custom CSS', defaultValue: false },
64
+ // { name: 'customCSS', type: 'blocks', label: 'Custom CSS', blocks: [CustomCSSBlock], maxRows: 1, required: false, admin: { initCollapsed: true, className: 'for-devs-class custom-css-class', condition: (_, siblingData) => Boolean(siblingData.enableCustomCSS) } },
65
+ ],
66
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "type": "block",
3
+ "name": "DDHG-LogoMarquee",
4
+ "label": "Logo Marquee",
5
+ "sourceName": "LogoMarquee",
6
+ "portableName": "DDHG-LogoMarquee",
7
+ "slug": "DDHG-LogoMarquee",
8
+ "version": "0.0.1",
9
+ "source": { "repo": "Hadizainal/HeatherGrey2025", "originalPath": "src/blocks/LogoMarquee", "originalSlug": "logoMarquee", "originalConfigExport": "LogoMarquee", "originalComponentExport": "LogoMarquee", "originalInterfaceName": "LogoMarqueeBlock" },
10
+ "files": [
11
+ { "from": "Component.tsx", "to": "src/blocks/DDHG-LogoMarquee/Component.tsx" },
12
+ { "from": "config.ts", "to": "src/blocks/DDHG-LogoMarquee/config.ts" }
13
+ ],
14
+ "dependencies": [{ "name": "framer-motion" }],
15
+ "sharedFiles": [],
16
+ "requiredProjectFiles": [
17
+ { "path": "src/utilities/ui.ts", "reason": "Component uses the cn utility." }
18
+ ],
19
+ "optionalProjectFiles": [
20
+ { "path": "src/blocks/CustomCssBlock/config.ts", "reason": "Custom CSS block support is currently commented out pending deeper review." },
21
+ { "path": "src/components/ui/separator.tsx", "reason": "Optional divider rendering is currently commented out pending deeper review." },
22
+ { "path": "src/utilities/renderCustomCSS.ts", "reason": "Custom CSS extraction is currently commented out pending deeper review." }
23
+ ],
24
+ "collectionRegistration": { "enabled": true, "collections": ["Pages", "Posts"] },
25
+ "renderBlocksRegistration": { "enabled": true },
26
+ "renderBlocksBehavior": { "wrapperless": false },
27
+ "pageRouteIntegration": { "required": false, "manualSteps": [] },
28
+ "manualSteps": [
29
+ "Review CustomCssBlock, Separator and renderCustomCSS together before re-enabling those commented integrations.",
30
+ "Run payload generate:types after schema changes."
31
+ ],
32
+ "notes": [
33
+ "Converted from HeatherGrey2025 LogoMarquee.",
34
+ "Project-specific custom CSS and separator integrations are intentionally commented out pending review.",
35
+ "Installer must not overwrite existing target files."
36
+ ],
37
+ "exportName": "DDHGLogoMarquee",
38
+ "interfaceName": "DDHGLogoMarquee"
39
+ }
@@ -0,0 +1,213 @@
1
+ 'use client'
2
+
3
+ import Image from 'next/image'
4
+ import Link from 'next/link'
5
+ import * as LucideIcons from 'lucide-react'
6
+ import React from 'react'
7
+
8
+ import { getMediaUrl } from '@/utilities/getMediaUrl'
9
+ import { cn } from '@/utilities/ui'
10
+
11
+ type PortableDoc = {
12
+ slug?: string | null
13
+ breadcrumbs?: Array<{ url?: string | null }> | null
14
+ [key: string]: unknown
15
+ }
16
+
17
+ type Media = {
18
+ url?: string | null
19
+ alt?: string | null
20
+ [key: string]: unknown
21
+ }
22
+
23
+ type LinkReference =
24
+ | { relationTo: 'pages'; value: number | PortableDoc }
25
+ | { relationTo: 'posts'; value: number | PortableDoc }
26
+ | { relationTo: 'projects'; value: number | PortableDoc }
27
+ | { relationTo: 'thoughts'; value: number | PortableDoc }
28
+
29
+ type NavCodeGridLink = {
30
+ type?: 'reference' | 'custom' | null
31
+ reference?: LinkReference | null
32
+ url?: string | null
33
+ label?: string | null
34
+ newTab?: boolean | null
35
+ icon?: string | null
36
+ iconPosition?: 'before' | 'after' | null
37
+ customIcon?: number | Media | null
38
+ } | null
39
+
40
+ export type DDHGNavCodeGridItem = {
41
+ id?: string | null
42
+ code?: string | null
43
+ link?: NavCodeGridLink
44
+ }
45
+
46
+ export type DDHGNavCodeGridProps = {
47
+ items?: DDHGNavCodeGridItem[] | null
48
+ defaultHref?: string | null
49
+ containerClassName?: string | null
50
+ gridClassName?: string | null
51
+ cellClassName?: string | null
52
+ showIcons?: boolean | null
53
+ }
54
+
55
+ const getPageURLFromDoc = (doc: PortableDoc | number): string | null => {
56
+ if (typeof doc === 'number') return null
57
+ const crumbs = Array.isArray(doc?.breadcrumbs) ? doc.breadcrumbs : []
58
+ if (crumbs.length) {
59
+ const last = crumbs[crumbs.length - 1]
60
+ if (typeof last?.url === 'string' && last.url) return last.url
61
+ }
62
+ const slug = doc?.slug
63
+ if (!slug || slug === 'home') return '/'
64
+ return slug.startsWith('/') ? slug : `/${slug}`
65
+ }
66
+
67
+ const getDocumentSlug = (doc: PortableDoc | number): string | null => {
68
+ if (typeof doc === 'number') return null
69
+ return doc?.slug || null
70
+ }
71
+
72
+ const getCollectionPath = (relationTo: LinkReference['relationTo']): string => {
73
+ if (relationTo === 'posts') return 'internal-docs'
74
+ if (relationTo === 'thoughts') return 'thoughts'
75
+ if (relationTo === 'projects') return 'archives'
76
+ return ''
77
+ }
78
+
79
+ const isExternalUrl = (href: string): boolean =>
80
+ href.startsWith('http://') ||
81
+ href.startsWith('https://') ||
82
+ href.startsWith('mailto:') ||
83
+ href.startsWith('tel:')
84
+
85
+ const resolveHref = (link: NavCodeGridLink, defaultHref = '/archive'): string => {
86
+ if (!link) return defaultHref
87
+ if (link.type === 'custom' && link.url) return link.url
88
+ if (link.type === 'reference' && link.reference?.value) {
89
+ const { relationTo, value } = link.reference
90
+ if (relationTo === 'pages') return getPageURLFromDoc(value) || defaultHref
91
+ const slug = getDocumentSlug(value)
92
+ if (!slug) return defaultHref
93
+ const basePath = getCollectionPath(relationTo)
94
+ return basePath ? `/${basePath}/${slug}` : `/${slug}`
95
+ }
96
+ return defaultHref
97
+ }
98
+
99
+ const renderIcon = (link: NavCodeGridLink, showIcons = true) => {
100
+ if (!showIcons || !link) return null
101
+
102
+ if (link.customIcon && typeof link.customIcon === 'object') {
103
+ const iconUrl = getMediaUrl(link.customIcon.url)
104
+ if (iconUrl) {
105
+ return (
106
+ <span className="inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center overflow-hidden">
107
+ <Image
108
+ src={iconUrl}
109
+ alt={link.customIcon.alt || ''}
110
+ width={14}
111
+ height={14}
112
+ className="m-0 block h-full w-full object-contain"
113
+ />
114
+ </span>
115
+ )
116
+ }
117
+ }
118
+
119
+ if (link.icon) {
120
+ const LucideIcon = LucideIcons[link.icon as keyof typeof LucideIcons] as
121
+ | React.ComponentType<{ className?: string }>
122
+ | undefined
123
+ if (LucideIcon) {
124
+ return (
125
+ <span className="inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center">
126
+ <LucideIcon className="h-3.5 w-3.5" />
127
+ </span>
128
+ )
129
+ }
130
+ }
131
+
132
+ return null
133
+ }
134
+
135
+ const getDelayClass = (index: number) => {
136
+ const delay = Math.min(index * 40, 320)
137
+ return `[transition-delay:${delay}ms]`
138
+ }
139
+
140
+ export const DDHGNavCodeGrid: React.FC<DDHGNavCodeGridProps> = ({
141
+ items,
142
+ defaultHref = '/archive',
143
+ containerClassName,
144
+ gridClassName,
145
+ cellClassName,
146
+ showIcons = true,
147
+ }) => {
148
+ if (!Array.isArray(items) || items.length === 0) return null
149
+
150
+ return (
151
+ <div className={cn('w-full', containerClassName)}>
152
+ <div className={cn('grid grid-cols-2 border border-border sm:grid-cols-4 !gap-0', gridClassName)}>
153
+ {items.map((item, index) => {
154
+ const link = item.link || null
155
+ const href = resolveHref(link, defaultHref || '/archive')
156
+ const label = link?.label || item.code || 'Archive'
157
+ const icon = renderIcon(link, Boolean(showIcons))
158
+ const iconPosition = link?.iconPosition || 'before'
159
+ const target = link?.newTab ? '_blank' : undefined
160
+ const rel = link?.newTab ? 'noopener noreferrer' : undefined
161
+ const className = cn(
162
+ 'menu-cell-hover group bg-transparent backdrop-blur-2xl border border-[var(--hg-50)] [border-style:outset] [text-shadow:0px_2px_4px_#ffffff45] relative flex items-center justify-center gap-2 py-2.5 text-[10px] font-normal uppercase tracking-[0.1em] text-[#6b6860] transition-all duration-200 hover:text-stone-700 dark:text-stone-200 sm:py-3 sm:text-[10px] md:py-4',
163
+ '--border-r --border-b --border-border',
164
+ (index + 1) % 4 === 0 ? '--sm:border-r-0' : '--border-border ',
165
+ index >= 4 ? '--sm:border-b-0' : '',
166
+ (index + 1) % 2 === 0 ? '--border-r-0' : '--border-r',
167
+ index >= 6 ? '--border-b-0' : '--border-b',
168
+ getDelayClass(index),
169
+ cellClassName,
170
+ )
171
+
172
+ const content = (
173
+ <>
174
+ {icon && iconPosition === 'before' && icon}
175
+ <span className="relative z-10">{label}</span>
176
+ {icon && iconPosition === 'after' && icon}
177
+ </>
178
+ )
179
+
180
+ if (isExternalUrl(href)) {
181
+ return (
182
+ <a
183
+ key={item.id || `${label}-${index}`}
184
+ href={href}
185
+ target={target}
186
+ rel={rel}
187
+ className={className}
188
+ style={{ fontFamily: "'Space Grotesk', sans-serif", fontWeight: 400, position: 'relative', textDecoration: 'none' }}
189
+ >
190
+ {content}
191
+ </a>
192
+ )
193
+ }
194
+
195
+ return (
196
+ <Link
197
+ key={item.id || `${label}-${index}`}
198
+ href={href}
199
+ target={target}
200
+ rel={rel}
201
+ className={className}
202
+ style={{ fontFamily: "'Space Grotesk', sans-serif", fontWeight: 400, position: 'relative', textDecoration: 'none' }}
203
+ >
204
+ {content}
205
+ </Link>
206
+ )
207
+ })}
208
+ </div>
209
+ </div>
210
+ )
211
+ }
212
+
213
+ export default DDHGNavCodeGrid
@@ -0,0 +1,64 @@
1
+ import type { Block } from 'payload'
2
+
3
+ import { link } from '@/fields/link'
4
+
5
+ export const DDHGNavCodeGrid: Block = {
6
+ slug: 'DDHG-NavCodeGrid',
7
+ interfaceName: 'DDHGNavCodeGrid',
8
+ labels: {
9
+ singular: 'Nav Code Grid',
10
+ plural: 'Nav Code Grids',
11
+ },
12
+ fields: [
13
+ {
14
+ name: 'items',
15
+ type: 'array',
16
+ label: 'Navigation Items',
17
+ minRows: 1,
18
+ fields: [
19
+ {
20
+ name: 'code',
21
+ type: 'text',
22
+ label: 'Fallback Code / Label',
23
+ },
24
+ link({
25
+ overrides: {
26
+ name: 'link',
27
+ label: 'Link',
28
+ },
29
+ disableLabel: false,
30
+ appearances: false,
31
+ }),
32
+ ],
33
+ },
34
+ {
35
+ type: 'row',
36
+ fields: [
37
+ {
38
+ name: 'defaultHref',
39
+ type: 'text',
40
+ label: 'Default href',
41
+ defaultValue: '/archive',
42
+ admin: { width: '50%' },
43
+ },
44
+ {
45
+ name: 'showIcons',
46
+ type: 'checkbox',
47
+ label: 'Show icons',
48
+ defaultValue: true,
49
+ admin: { width: '50%' },
50
+ },
51
+ ],
52
+ },
53
+ {
54
+ type: 'collapsible',
55
+ label: 'Classes',
56
+ admin: { initCollapsed: true },
57
+ fields: [
58
+ { name: 'containerClassName', type: 'text', label: 'Container class' },
59
+ { name: 'gridClassName', type: 'text', label: 'Grid class' },
60
+ { name: 'cellClassName', type: 'text', label: 'Cell class' },
61
+ ],
62
+ },
63
+ ],
64
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "type": "block",
3
+ "name": "DDHG-NavCodeGrid",
4
+ "label": "Nav Code Grid",
5
+ "sourceName": "NavCodeGrid",
6
+ "portableName": "DDHG-NavCodeGrid",
7
+ "slug": "DDHG-NavCodeGrid",
8
+ "version": "0.0.1",
9
+ "source": {
10
+ "repo": "Hadizainal/HeatherGrey2025",
11
+ "originalPath": "src/blocks/NavCodeGrid",
12
+ "originalSlug": "navCodeGrid",
13
+ "originalConfigExport": "NavCodeGrid",
14
+ "originalComponentExport": "NavCodeGridBlock",
15
+ "originalInterfaceName": "NavCodeGridBlock"
16
+ },
17
+ "files": [
18
+ { "from": "Component.tsx", "to": "src/blocks/DDHG-NavCodeGrid/Component.tsx" },
19
+ { "from": "config.ts", "to": "src/blocks/DDHG-NavCodeGrid/config.ts" }
20
+ ],
21
+ "dependencies": [{ "name": "lucide-react" }],
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
+ { "path": "src/utilities/getMediaUrl.ts", "reason": "Component resolves custom icon media URLs with getMediaUrl." }
27
+ ],
28
+ "optionalProjectFiles": [],
29
+ "collectionRegistration": { "enabled": true, "collections": ["Pages", "Posts"] },
30
+ "renderBlocksRegistration": { "enabled": true },
31
+ "renderBlocksBehavior": { "wrapperless": false },
32
+ "pageRouteIntegration": { "required": false, "manualSteps": [] },
33
+ "manualSteps": [
34
+ "Confirm the destination link field supports icons, customIcon and reference collections used by this block.",
35
+ "Review the source-specific posts/projects/thoughts route mapping after installation.",
36
+ "Run payload generate:types after schema changes."
37
+ ],
38
+ "notes": [
39
+ "Converted from HeatherGrey2025 NavCodeGrid.",
40
+ "Generated Payload document types were replaced with portable structural types.",
41
+ "Installer must not overwrite existing target files."
42
+ ],
43
+ "exportName": "DDHGNavCodeGrid",
44
+ "interfaceName": "DDHGNavCodeGrid"
45
+ }