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.
- package/README.md +35 -0
- package/package.json +5 -2
- package/src/cli.js +39 -3
- package/src/commands/shop.js +59 -0
- package/src/commands/warehouse.js +73 -0
- package/src/utils/paths.js +13 -13
- package/templates/blocks/DD-Accordion/Component.tsx +229 -0
- package/templates/blocks/DD-Accordion/README.md +3 -0
- package/templates/blocks/DD-Accordion/config.ts +73 -0
- package/templates/blocks/DD-Accordion/manifest.json +75 -0
- package/templates/blocks/DD-AnimText/Component.tsx +788 -0
- package/templates/blocks/DD-AnimText/README.md +3 -0
- package/templates/blocks/DD-AnimText/config.ts +295 -0
- package/templates/blocks/DD-AnimText/manifest.json +85 -0
- package/templates/blocks/DD-AsideNav/Component.tsx +321 -0
- package/templates/blocks/DD-AsideNav/config.ts +204 -0
- package/templates/blocks/DD-AsideNav/manifest.json +80 -0
- package/templates/blocks/DD-Banner/Component.tsx +51 -0
- package/templates/blocks/DD-Banner/config.ts +57 -0
- package/templates/blocks/DD-Banner/manifest.json +72 -0
- package/templates/blocks/DD-BgLightning/Component.tsx +44 -0
- package/templates/blocks/DD-BgLightning/README.md +3 -0
- package/templates/blocks/DD-BgLightning/config.ts +97 -0
- package/templates/blocks/DD-BgLightning/manifest.json +79 -0
- package/templates/blocks/DD-BookCall/Component.tsx +535 -535
- package/templates/blocks/DD-BookCall/config.ts +238 -238
- package/templates/blocks/DD-ButtonPop/Component.tsx +117 -0
- package/templates/blocks/DD-ButtonPop/config.ts +105 -0
- package/templates/blocks/DD-ButtonPop/manifest.json +88 -0
- package/templates/blocks/DD-ButtonPop/svg-icons/Dust2.tsx +167 -0
- package/templates/blocks/DD-Card/Component.tsx +251 -0
- package/templates/blocks/DD-Card/README.md +4 -0
- package/templates/blocks/DD-Card/config.ts +154 -0
- package/templates/blocks/DD-Card/manifest.json +82 -0
- package/templates/blocks/DD-CardTemplate01/Component.tsx +140 -140
- package/templates/blocks/DD-CardTemplate01/config.ts +106 -106
- package/templates/blocks/DD-Carousel-A/Component.tsx +249 -249
- package/templates/blocks/DD-Carousel-B/Component.tsx +403 -403
- package/templates/blocks/DD-Chip/Component.tsx +250 -0
- package/templates/blocks/DD-Chip/EXAMPLES.md +313 -0
- package/templates/blocks/DD-Chip/README.md +202 -0
- package/templates/blocks/DD-Chip/config.ts +369 -0
- package/templates/blocks/DD-Chip/manifest.json +74 -0
- package/templates/blocks/DD-ComparisonTable/Component.tsx +256 -256
- package/templates/blocks/DD-Contact/Component.tsx +435 -434
- package/templates/blocks/DD-Contact/config.ts +22 -22
- package/templates/blocks/DD-Counter/Component.tsx +190 -0
- package/templates/blocks/DD-Counter/README.md +4 -0
- package/templates/blocks/DD-Counter/config.ts +291 -0
- package/templates/blocks/DD-Counter/manifest.json +74 -0
- package/templates/blocks/DD-CustomCSS/Component.tsx +8 -0
- package/templates/blocks/DD-CustomCSS/README.md +4 -0
- package/templates/blocks/DD-CustomCSS/addToLayout.md +5 -0
- package/templates/blocks/DD-CustomCSS/config.ts +22 -0
- package/templates/blocks/DD-CustomCSS/manifest.json +72 -0
- package/templates/blocks/DD-CustomCSS/renderCustomCSS.md +7 -0
- package/templates/blocks/DD-FeatCat/Component.tsx +302 -302
- package/templates/blocks/DD-FeatCat/config.ts +201 -201
- package/templates/blocks/DD-FeatStrip/Component.tsx +585 -585
- package/templates/blocks/DD-FeatStrip/config.ts +134 -134
- package/templates/blocks/DD-FluidBtn/ButtonsEyeCatching.tsx +628 -0
- package/templates/blocks/DD-FluidBtn/Component.tsx +43 -0
- package/templates/blocks/DD-FluidBtn/README.md +6 -0
- package/templates/blocks/DD-FluidBtn/config.ts +102 -0
- package/templates/blocks/DD-FluidBtn/manifest.json +86 -0
- package/templates/blocks/DD-GooeyInfo/Component.tsx +149 -0
- package/templates/blocks/DD-GooeyInfo/config.ts +135 -0
- package/templates/blocks/DD-GooeyInfo/manifest.json +72 -0
- package/templates/blocks/DD-Hero/Component.tsx +297 -297
- package/templates/blocks/DD-Hero/config.ts +267 -267
- package/templates/blocks/DD-HorizontalScroll/Component.tsx +936 -936
- package/templates/blocks/DD-HorizontalScroll/config.ts +231 -231
- package/templates/blocks/DD-Icon/Component.tsx +287 -0
- package/templates/blocks/DD-Icon/README.md +4 -0
- package/templates/blocks/DD-Icon/config.ts +258 -0
- package/templates/blocks/DD-Icon/hooks/revalidateBlockIds.ts +66 -0
- package/templates/blocks/DD-Icon/manifest.json +82 -0
- package/templates/blocks/DD-IconButton/Component.tsx +455 -0
- package/templates/blocks/DD-IconButton/README.md +326 -0
- package/templates/blocks/DD-IconButton/config.ts +239 -0
- package/templates/blocks/DD-IconButton/manifest.json +85 -0
- package/templates/blocks/DD-IdTag/Component.tsx +21 -0
- package/templates/blocks/DD-IdTag/README.md +4 -0
- package/templates/blocks/DD-IdTag/config.ts +41 -0
- package/templates/blocks/DD-IdTag/manifest.json +72 -0
- package/templates/blocks/DD-Iframe/Component.tsx +45 -0
- package/templates/blocks/DD-Iframe/README.md +4 -0
- package/templates/blocks/DD-Iframe/config.ts +47 -0
- package/templates/blocks/DD-Iframe/manifest.json +72 -0
- package/templates/blocks/DD-IframeMedia/Component.tsx +133 -0
- package/templates/blocks/DD-IframeMedia/README.md +4 -0
- package/templates/blocks/DD-IframeMedia/config.ts +79 -0
- package/templates/blocks/DD-IframeMedia/manifest.json +72 -0
- package/templates/blocks/DD-LineAnim/Component.tsx +36 -0
- package/templates/blocks/DD-LineAnim/README.md +4 -0
- package/templates/blocks/DD-LineAnim/config.ts +90 -0
- package/templates/blocks/DD-LineAnim/manifest.json +80 -0
- package/templates/blocks/DD-LinkGrid/Component.tsx +119 -0
- package/templates/blocks/DD-LinkGrid/README.md +4 -0
- package/templates/blocks/DD-LinkGrid/config.ts +51 -0
- package/templates/blocks/DD-LinkGrid/manifest.json +74 -0
- package/templates/blocks/DD-LogoMarq/Component.tsx +132 -0
- package/templates/blocks/DD-LogoMarq/README.md +4 -0
- package/templates/blocks/DD-LogoMarq/config.ts +264 -0
- package/templates/blocks/DD-LogoMarq/manifest.json +82 -0
- package/templates/blocks/DD-Lottie/Component.tsx +459 -0
- package/templates/blocks/DD-Lottie/README.md +4 -0
- package/templates/blocks/DD-Lottie/config.ts +379 -0
- package/templates/blocks/DD-Lottie/index.tsx +28 -0
- package/templates/blocks/DD-Lottie/manifest.json +83 -0
- package/templates/blocks/DD-MagicBento/Component.tsx +777 -0
- package/templates/blocks/DD-MagicBento/README.md +4 -0
- package/templates/blocks/DD-MagicBento/config.ts +264 -0
- package/templates/blocks/DD-MagicBento/manifest.json +74 -0
- package/templates/blocks/DD-MasonaryMedia/Component.tsx +545 -545
- package/templates/blocks/DD-MasonaryMedia/config.ts +2 -2
- package/templates/blocks/DD-MasonaryMedia/vendor.d.ts +2 -2
- package/templates/blocks/DD-Masonry/Component.tsx +645 -0
- package/templates/blocks/DD-Masonry/README.md +4 -0
- package/templates/blocks/DD-Masonry/config.ts +475 -0
- package/templates/blocks/DD-Masonry/manifest.json +82 -0
- package/templates/blocks/DD-Pricing/Component.tsx +2 -5
- package/templates/blocks/DD-Process/Component.tsx +2 -4
- package/templates/blocks/DD-Process/config.ts +150 -150
- package/templates/blocks/DD-Progress/Component.tsx +156 -0
- package/templates/blocks/DD-Progress/README.md +4 -0
- package/templates/blocks/DD-Progress/config.ts +175 -0
- package/templates/blocks/DD-Progress/manifest.json +74 -0
- package/templates/blocks/DD-ProjHeader/Component.tsx +91 -0
- package/templates/blocks/DD-ProjHeader/README.md +4 -0
- package/templates/blocks/DD-ProjHeader/config.ts +96 -0
- package/templates/blocks/DD-ProjHeader/manifest.json +72 -0
- package/templates/blocks/DD-ProjSlider/Component.tsx +123 -0
- package/templates/blocks/DD-ProjSlider/README.md +4 -0
- package/templates/blocks/DD-ProjSlider/config.ts +64 -0
- package/templates/blocks/DD-ProjSlider/manifest.json +72 -0
- package/templates/blocks/DD-ScrollText/Component.tsx +114 -0
- package/templates/blocks/DD-ScrollText/README.md +4 -0
- package/templates/blocks/DD-ScrollText/config.ts +58 -0
- package/templates/blocks/DD-ScrollText/manifest.json +72 -0
- package/templates/blocks/DD-Section/Component.tsx +266 -266
- package/templates/blocks/DD-Separator/Component.tsx +66 -0
- package/templates/blocks/DD-Separator/README.md +4 -0
- package/templates/blocks/DD-Separator/config.ts +58 -0
- package/templates/blocks/DD-Separator/manifest.json +72 -0
- package/templates/blocks/DD-Services/Component.tsx +176 -176
- package/templates/blocks/DD-Services/config.ts +149 -149
- package/templates/blocks/DD-ShowcaseGrid/Component.tsx +307 -307
- package/templates/blocks/DD-Slider-A/Component.tsx +1 -1
- package/templates/blocks/DD-StackCards/Component.tsx +1 -1
- package/templates/blocks/DD-StackCards/config.ts +399 -399
- package/templates/blocks/DD-Team/Component.tsx +247 -247
- package/templates/blocks/DD-Team/config.ts +173 -173
- package/templates/blocks/DD-TeamCards/Component.tsx +251 -0
- package/templates/blocks/DD-TeamCards/README.md +4 -0
- package/templates/blocks/DD-TeamCards/config.ts +302 -0
- package/templates/blocks/DD-TeamCards/manifest.json +74 -0
- package/templates/blocks/DD-TechStack/Component.tsx +174 -174
- package/templates/blocks/DD-TechStack/config.ts +153 -153
- package/templates/blocks/DD-TestMarq/Component.tsx +132 -0
- package/templates/blocks/DD-TestMarq/README.md +4 -0
- package/templates/blocks/DD-TestMarq/RowLabel.tsx +9 -0
- package/templates/blocks/DD-TestMarq/config.ts +88 -0
- package/templates/blocks/DD-TestMarq/manifest.json +72 -0
- package/templates/blocks/DD-Testim/Component.tsx +247 -0
- package/templates/blocks/DD-Testim/README.md +4 -0
- package/templates/blocks/DD-Testim/config.ts +101 -0
- package/templates/blocks/DD-Testim/manifest.json +75 -0
- package/templates/blocks/DD-Testim2/Component.tsx +256 -0
- package/templates/blocks/DD-Testim2/README.md +4 -0
- package/templates/blocks/DD-Testim2/config.ts +100 -0
- package/templates/blocks/DD-Testim2/manifest.json +74 -0
- package/templates/blocks/DD-Testimonials/Component.tsx +139 -147
- package/templates/blocks/DD-Testimonials/config.ts +120 -120
- package/templates/blocks/DD-TextMarq/Component.tsx +157 -0
- package/templates/blocks/DD-TextMarq/README.md +4 -0
- package/templates/blocks/DD-TextMarq/config.ts +237 -0
- package/templates/blocks/DD-TextMarq/manifest.json +82 -0
- package/templates/blocks/DD-Thanks/Component.tsx +501 -0
- package/templates/blocks/DD-Thanks/README.md +4 -0
- package/templates/blocks/DD-Thanks/config.ts +224 -0
- package/templates/blocks/DD-Thanks/manifest.json +72 -0
- package/templates/blocks/DD-VertMarq/Component.tsx +154 -0
- package/templates/blocks/DD-VertMarq/README.md +4 -0
- package/templates/blocks/DD-VertMarq/config.ts +236 -0
- package/templates/blocks/DD-VertMarq/dist/index.css +6 -0
- package/templates/blocks/DD-VertMarq/dist/index.min.css +1 -0
- package/templates/blocks/DD-VertMarq/manifest.json +74 -0
- package/templates/blocks/DD-Work/Component.tsx +318 -315
- package/templates/blocks/DD-Work/config.ts +165 -165
- package/templates/blocks/DD-Work-B/Component.tsx +294 -294
- package/templates/blocks/DDHG-CTASection2/Component.tsx +185 -0
- package/templates/blocks/DDHG-CTASection2/config.ts +140 -0
- package/templates/blocks/DDHG-CTASection2/manifest.json +45 -0
- package/templates/blocks/DDHG-HighlightArc/Component.tsx +243 -0
- package/templates/blocks/DDHG-HighlightArc/config.ts +85 -0
- package/templates/blocks/DDHG-HighlightArc/manifest.json +46 -0
- package/templates/blocks/DDHG-LogoMarquee/Component.tsx +143 -0
- package/templates/blocks/DDHG-LogoMarquee/config.ts +154 -0
- package/templates/blocks/DDHG-LogoMarquee/manifest.json +39 -0
- package/templates/blocks/DDHG-NavCodeGrid/Component.tsx +227 -0
- package/templates/blocks/DDHG-NavCodeGrid/config.ts +64 -0
- package/templates/blocks/DDHG-NavCodeGrid/manifest.json +45 -0
- package/templates/blocks/DDHG-ProcessSec/Component.tsx +574 -0
- package/templates/blocks/DDHG-ProcessSec/config.ts +170 -0
- package/templates/blocks/DDHG-ProcessSec/manifest.json +56 -0
- package/templates/blocks/DDHG-ServiceDetails/Component.tsx +164 -0
- package/templates/blocks/DDHG-ServiceDetails/ServiceDetailCard.tsx +390 -0
- package/templates/blocks/DDHG-ServiceDetails/config.ts +77 -0
- package/templates/blocks/DDHG-ServiceDetails/manifest.json +50 -0
- package/templates/blocks/DDHG-ServiceHero/Component.tsx +234 -0
- package/templates/blocks/DDHG-ServiceHero/config.ts +49 -0
- package/templates/blocks/DDHG-ServiceHero/manifest.json +26 -0
- package/templates/blocks/DDHG-ServiceOverview/Component.tsx +277 -0
- package/templates/blocks/DDHG-ServiceOverview/config.ts +64 -0
- package/templates/blocks/DDHG-ServiceOverview/manifest.json +44 -0
- package/templates/blocks/DDHG-StatsFAQ/Component.tsx +389 -0
- package/templates/blocks/DDHG-StatsFAQ/config.ts +204 -0
- package/templates/blocks/DDHG-StatsFAQ/manifest.json +45 -0
- package/templates/blocks/DDHG-TeamCards/Component.tsx +169 -0
- package/templates/blocks/DDHG-TeamCards/config.ts +48 -0
- package/templates/blocks/DDHG-TeamCards/manifest.json +29 -0
- package/templates/shared/src/components/BgLightning/index.tsx +242 -0
- package/templates/shared/src/components/ui/ShareButton/index.tsx +80 -0
- package/templates/shared/src/components/ui/anims/FadeOnScroll.tsx +48 -0
- package/templates/shared/src/components/ui/anims/FadeUpOnInView.tsx +63 -0
- package/templates/shared/src/components/ui/anims/GlareHover.tsx +111 -0
- package/templates/shared/src/components/ui/anims/LineAnims.tsx +81 -0
- package/templates/shared/src/components/ui/anims/TitleAnims01.tsx +54 -0
- package/templates/shared/src/components/ui/anims/animation-container.tsx +29 -0
- package/templates/shared/src/components/ui/anims/blur-in.tsx +26 -0
- package/templates/shared/src/components/ui/anims/counter.tsx +53 -0
- package/templates/shared/src/components/ui/anims/fade.tsx +83 -0
- package/templates/shared/src/components/ui/anims/gradual-spacing.tsx +39 -0
- package/templates/shared/src/components/ui/anims/pull-up.tsx +93 -0
- package/templates/shared/src/components/ui/anims/reveal-text.tsx +76 -0
- package/templates/shared/src/components/ui/anims/rotate-words.tsx +43 -0
- package/templates/shared/src/components/ui/anims/shiny-text.tsx +58 -0
- package/templates/shared/src/components/ui/anims/shuffle-text.tsx +85 -0
- package/templates/shared/src/components/ui/anims/split-text.tsx +211 -0
- package/templates/shared/src/components/ui/anims/staggered-fade.tsx +133 -0
- package/templates/shared/src/components/ui/anims/text-scroll.tsx +111 -0
- package/templates/shared/src/components/ui/anims/typing-effect.tsx +112 -0
- package/templates/shared/src/components/ui/button-dusted-fluid/index.tsx +1521 -0
- package/templates/shared/src/components/ui/separator.tsx +85 -0
- package/templates/shared/src/hooks/useBodyScrollLock.ts +97 -0
- package/templates/shared/src/hooks/useClickOutside.ts +28 -0
- package/templates/shared/src/utilities/renderCustomCSS.ts +5 -0
- 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,143 @@
|
|
|
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(
|
|
14
|
+
`<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg" style="opacity:0"><rect width="100%" height="100%" fill="transparent" /></svg>`,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
type LogoItem = {
|
|
18
|
+
image?: { url?: string | null; alt?: string | null } | null
|
|
19
|
+
imageClass?: string | null
|
|
20
|
+
imageStyle?: React.CSSProperties
|
|
21
|
+
imageAltClass?: string | null
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type DDHGLogoMarqueeProps = {
|
|
25
|
+
sectionId?: string | null
|
|
26
|
+
logos?: LogoItem[] | null
|
|
27
|
+
speed?: number | null
|
|
28
|
+
spacing?: number | null
|
|
29
|
+
priority?: boolean | null
|
|
30
|
+
showTopDivider?: boolean | null
|
|
31
|
+
showBottomDivider?: boolean | null
|
|
32
|
+
containerClass?: string | null
|
|
33
|
+
itemWidth?: number | null
|
|
34
|
+
enableCustomCSS?: boolean | null
|
|
35
|
+
customCSS?: Array<{ blockType?: string; css?: string }> | string | null
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const LogoImage: React.FC<{
|
|
39
|
+
src: string
|
|
40
|
+
alt?: string | null
|
|
41
|
+
customClass?: string | null
|
|
42
|
+
imageStyle?: React.CSSProperties
|
|
43
|
+
priority?: boolean
|
|
44
|
+
}> = ({ src, alt, customClass, imageStyle, priority = false }) => {
|
|
45
|
+
const [imageError, setImageError] = useState(false)
|
|
46
|
+
const imageSrc = !src || imageError ? placeholderBlur : src
|
|
47
|
+
return (
|
|
48
|
+
<Image
|
|
49
|
+
src={imageSrc}
|
|
50
|
+
alt={alt || 'Logo'}
|
|
51
|
+
width={300}
|
|
52
|
+
height={300}
|
|
53
|
+
priority={priority}
|
|
54
|
+
className={customClass || ''}
|
|
55
|
+
style={{
|
|
56
|
+
objectFit: 'contain',
|
|
57
|
+
...(imageStyle && typeof imageStyle === 'object' ? imageStyle : {}),
|
|
58
|
+
}}
|
|
59
|
+
onError={() => setImageError(true)}
|
|
60
|
+
placeholder="blur"
|
|
61
|
+
blurDataURL={placeholderBlur}
|
|
62
|
+
/>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export const DDHGLogoMarquee: React.FC<DDHGLogoMarqueeProps> = ({
|
|
67
|
+
sectionId,
|
|
68
|
+
logos,
|
|
69
|
+
speed = 10,
|
|
70
|
+
spacing = 32,
|
|
71
|
+
priority = false,
|
|
72
|
+
showTopDivider = false,
|
|
73
|
+
showBottomDivider = false,
|
|
74
|
+
containerClass = 'overflow-hidden py-8 bg-transparent',
|
|
75
|
+
enableCustomCSS = false,
|
|
76
|
+
customCSS,
|
|
77
|
+
itemWidth,
|
|
78
|
+
}) => {
|
|
79
|
+
const validLogos = Array.isArray(logos) ? logos : []
|
|
80
|
+
if (validLogos.length === 0) return null
|
|
81
|
+
const calculatedItemWidth = itemWidth || 100
|
|
82
|
+
const totalWidth = validLogos.length * (calculatedItemWidth + (spacing || 0))
|
|
83
|
+
|
|
84
|
+
// DDHG TODO: Re-enable with extractCustomCSS when that bundle is reviewed.
|
|
85
|
+
// const extractedCSS = enableCustomCSS && Array.isArray(customCSS)
|
|
86
|
+
// ? extractCustomCSS(customCSS)
|
|
87
|
+
// : typeof customCSS === 'string'
|
|
88
|
+
// ? customCSS
|
|
89
|
+
// : ''
|
|
90
|
+
const extractedCSS = ''
|
|
91
|
+
void enableCustomCSS
|
|
92
|
+
void customCSS
|
|
93
|
+
void showTopDivider
|
|
94
|
+
void showBottomDivider
|
|
95
|
+
|
|
96
|
+
const renderSet = (suffix = '') =>
|
|
97
|
+
validLogos.map((logo, index) => (
|
|
98
|
+
<div
|
|
99
|
+
key={`logo-${index}${suffix}`}
|
|
100
|
+
className="marque-image-container shrink-0 flex flex-col items-center justify-center"
|
|
101
|
+
style={{
|
|
102
|
+
marginRight: `${spacing || 0}px`,
|
|
103
|
+
...(itemWidth
|
|
104
|
+
? { width: `${calculatedItemWidth}px` }
|
|
105
|
+
: { minWidth: `${calculatedItemWidth}px` }),
|
|
106
|
+
}}
|
|
107
|
+
>
|
|
108
|
+
<LogoImage
|
|
109
|
+
src={logo.image?.url || placeholderBlur}
|
|
110
|
+
alt={logo.image?.alt}
|
|
111
|
+
customClass={logo.imageClass}
|
|
112
|
+
imageStyle={logo.imageStyle}
|
|
113
|
+
priority={Boolean(priority)}
|
|
114
|
+
/>
|
|
115
|
+
<p className={cn('text-base text-center', logo.imageAltClass)}>{logo.image?.alt || null}</p>
|
|
116
|
+
</div>
|
|
117
|
+
))
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<>
|
|
121
|
+
{/* DDHG TODO: Re-enable optional Separator rendering after bundle review. */}
|
|
122
|
+
{/* {showTopDivider && <Separator gradient={true} className="border-seperator" />} */}
|
|
123
|
+
<div
|
|
124
|
+
id={sectionId ?? undefined}
|
|
125
|
+
className="logo-marquee-block relative mx-auto max-w-screen overflow-x-clip bg-stone-300/20 dark:bg-stone-900/10 top-[20vh]"
|
|
126
|
+
>
|
|
127
|
+
{extractedCSS && <style dangerouslySetInnerHTML={{ __html: extractedCSS }} />}
|
|
128
|
+
<motion.div
|
|
129
|
+
className={`${containerClass} flex py-4`}
|
|
130
|
+
animate={{ x: [0, -totalWidth] }}
|
|
131
|
+
transition={{ repeat: Infinity, duration: speed || 10, ease: 'linear' }}
|
|
132
|
+
style={{ width: `${totalWidth * 2}px` }}
|
|
133
|
+
>
|
|
134
|
+
{renderSet()}
|
|
135
|
+
{renderSet('-duplicate')}
|
|
136
|
+
</motion.div>
|
|
137
|
+
</div>
|
|
138
|
+
{/* {showBottomDivider && <Separator gradient={true} className="border-seperator opacity-20" />} */}
|
|
139
|
+
</>
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export default DDHGLogoMarquee
|
|
@@ -0,0 +1,154 @@
|
|
|
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
|
+
{
|
|
11
|
+
name: 'sectionId',
|
|
12
|
+
type: 'text',
|
|
13
|
+
label: 'Section ID',
|
|
14
|
+
required: false,
|
|
15
|
+
admin: { description: 'Optional anchor ID for linking and scroll targets.' },
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
type: 'collapsible',
|
|
19
|
+
label: 'Block Settings',
|
|
20
|
+
admin: { initCollapsed: true, className: 'custom-css-class' },
|
|
21
|
+
fields: [
|
|
22
|
+
{
|
|
23
|
+
type: 'collapsible',
|
|
24
|
+
label: 'Container Class',
|
|
25
|
+
admin: { initCollapsed: true, className: 'custom-css-class' },
|
|
26
|
+
fields: [
|
|
27
|
+
{
|
|
28
|
+
name: 'containerClass',
|
|
29
|
+
label: false,
|
|
30
|
+
type: 'text',
|
|
31
|
+
required: false,
|
|
32
|
+
admin: { description: 'Override the default container class.' },
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
type: 'collapsible',
|
|
38
|
+
label: 'Marquee Settings',
|
|
39
|
+
admin: { initCollapsed: true, className: 'custom-group-class' },
|
|
40
|
+
fields: [
|
|
41
|
+
{
|
|
42
|
+
type: 'row',
|
|
43
|
+
fields: [
|
|
44
|
+
{
|
|
45
|
+
name: 'speed',
|
|
46
|
+
type: 'number',
|
|
47
|
+
label: 'Scroll Speed (seconds)',
|
|
48
|
+
defaultValue: 10,
|
|
49
|
+
required: true,
|
|
50
|
+
admin: { width: '50%' },
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'spacing',
|
|
54
|
+
type: 'number',
|
|
55
|
+
label: 'Spacing between images (px)',
|
|
56
|
+
defaultValue: 32,
|
|
57
|
+
required: true,
|
|
58
|
+
admin: { width: '50%' },
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
{ name: 'priority', type: 'checkbox', label: 'High Priority Loading', defaultValue: false },
|
|
65
|
+
{
|
|
66
|
+
type: 'collapsible',
|
|
67
|
+
label: 'Dividers',
|
|
68
|
+
admin: { initCollapsed: true, className: 'custom-group-class' },
|
|
69
|
+
fields: [
|
|
70
|
+
{ name: 'showTopDivider', type: 'checkbox', label: 'Show Top Divider' },
|
|
71
|
+
{ name: 'showBottomDivider', type: 'checkbox', label: 'Show Bottom Divider' },
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: 'logoImages',
|
|
78
|
+
type: 'upload',
|
|
79
|
+
relationTo: 'media',
|
|
80
|
+
hasMany: true,
|
|
81
|
+
required: false,
|
|
82
|
+
filterOptions: { mimeType: { contains: 'image' } },
|
|
83
|
+
hooks: {
|
|
84
|
+
beforeChange: [
|
|
85
|
+
({ value, siblingData }) => {
|
|
86
|
+
if (!Array.isArray(value) || value.length === 0) return value
|
|
87
|
+
const existingLogos = Array.isArray((siblingData as any)?.logos)
|
|
88
|
+
? (siblingData as any).logos
|
|
89
|
+
: []
|
|
90
|
+
const normalizeImageId = (imageValue: unknown): number | string | undefined => {
|
|
91
|
+
if (typeof imageValue === 'number' || typeof imageValue === 'string')
|
|
92
|
+
return imageValue
|
|
93
|
+
if (imageValue && typeof imageValue === 'object' && 'id' in (imageValue as any)) {
|
|
94
|
+
const maybeId = (imageValue as any).id
|
|
95
|
+
if (typeof maybeId === 'number' || typeof maybeId === 'string') return maybeId
|
|
96
|
+
}
|
|
97
|
+
return undefined
|
|
98
|
+
}
|
|
99
|
+
const existingIds = new Set(
|
|
100
|
+
existingLogos
|
|
101
|
+
.map((row: any) => normalizeImageId(row?.image))
|
|
102
|
+
.filter((id: any) => id !== undefined),
|
|
103
|
+
)
|
|
104
|
+
const newRows = value
|
|
105
|
+
.map((id) => normalizeImageId(id))
|
|
106
|
+
.filter((id): id is number | string => id !== undefined)
|
|
107
|
+
.filter((id) => !existingIds.has(id))
|
|
108
|
+
.map((id) => ({ image: id, imageAltClass: 'hidden', imageClass: '' }))
|
|
109
|
+
;(siblingData as any).logos = [...existingLogos, ...newRows]
|
|
110
|
+
return []
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: 'logos',
|
|
117
|
+
type: 'array',
|
|
118
|
+
label: 'Images',
|
|
119
|
+
labels: { singular: 'Image', plural: 'Images' },
|
|
120
|
+
fields: [
|
|
121
|
+
{
|
|
122
|
+
name: 'image',
|
|
123
|
+
type: 'upload',
|
|
124
|
+
relationTo: 'media',
|
|
125
|
+
required: false,
|
|
126
|
+
filterOptions: { mimeType: { contains: 'image' } },
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
type: 'collapsible',
|
|
130
|
+
label: 'Alt Text Class',
|
|
131
|
+
admin: { initCollapsed: true, className: 'custom-css-class' },
|
|
132
|
+
fields: [
|
|
133
|
+
{
|
|
134
|
+
name: 'imageAltClass',
|
|
135
|
+
label: false,
|
|
136
|
+
type: 'text',
|
|
137
|
+
required: false,
|
|
138
|
+
defaultValue: 'hidden',
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
type: 'collapsible',
|
|
144
|
+
label: 'Image Class',
|
|
145
|
+
admin: { initCollapsed: true, className: 'custom-css-class' },
|
|
146
|
+
fields: [{ name: 'imageClass', label: false, type: 'text', required: false }],
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
},
|
|
150
|
+
// DDHG TODO: Re-enable custom CSS support after reviewing the CustomCssBlock bundle.
|
|
151
|
+
// { name: 'enableCustomCSS', type: 'checkbox', label: 'Inject Custom CSS', defaultValue: false },
|
|
152
|
+
// { 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) } },
|
|
153
|
+
],
|
|
154
|
+
}
|
|
@@ -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,227 @@
|
|
|
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 }> | undefined
|
|
122
|
+
if (LucideIcon) {
|
|
123
|
+
return (
|
|
124
|
+
<span className="inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center">
|
|
125
|
+
<LucideIcon className="h-3.5 w-3.5" />
|
|
126
|
+
</span>
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return null
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const getDelayClass = (index: number) => {
|
|
135
|
+
const delay = Math.min(index * 40, 320)
|
|
136
|
+
return `[transition-delay:${delay}ms]`
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export const DDHGNavCodeGrid: React.FC<DDHGNavCodeGridProps> = ({
|
|
140
|
+
items,
|
|
141
|
+
defaultHref = '/archive',
|
|
142
|
+
containerClassName,
|
|
143
|
+
gridClassName,
|
|
144
|
+
cellClassName,
|
|
145
|
+
showIcons = true,
|
|
146
|
+
}) => {
|
|
147
|
+
if (!Array.isArray(items) || items.length === 0) return null
|
|
148
|
+
|
|
149
|
+
return (
|
|
150
|
+
<div className={cn('w-full max-w-7xl mx-auto', containerClassName, 'pt-24')}>
|
|
151
|
+
<div
|
|
152
|
+
className={cn(
|
|
153
|
+
'grid grid-cols-2 overflow-hidden bg-stone-100/50 dark:bg-stone-900/50 sm:grid-cols-4 !gap-0 shadow-lg',
|
|
154
|
+
gridClassName,
|
|
155
|
+
)}
|
|
156
|
+
>
|
|
157
|
+
{items.map((item, index) => {
|
|
158
|
+
const link = item.link || null
|
|
159
|
+
const href = resolveHref(link, defaultHref || '/archive')
|
|
160
|
+
const label = link?.label || item.code || 'Archive'
|
|
161
|
+
const icon = renderIcon(link, Boolean(showIcons))
|
|
162
|
+
const iconPosition = link?.iconPosition || 'before'
|
|
163
|
+
const target = link?.newTab ? '_blank' : undefined
|
|
164
|
+
const rel = link?.newTab ? 'noopener noreferrer' : undefined
|
|
165
|
+
const className = cn(
|
|
166
|
+
'menu-cell-hover group relative flex items-center justify-center gap-2 bg-stone-200/50 py-2.5 text-xs font-normal uppercase tracking-[0.1em] text-sm [text-shadow:0px_2px_4px_#ffffff45] backdrop-blur-2xl transition-all duration-300 hover:-translate-y-0.5 hover:bg-stone-200/80 hover:text-stone-700 dark:bg-stone-900/50 dark:text-stone-200 dark:hover:bg-stone-800/70 sm:py-3 sm:text-xs md:py-4 hover:shadow-2xl',
|
|
167
|
+
'border-r border-b border-border',
|
|
168
|
+
(index + 1) % 4 === 0 ? 'sm:border-r-0' : ' ',
|
|
169
|
+
index >= 4 ? 'sm:border-b-0' : '',
|
|
170
|
+
(index + 1) % 2 === 0 ? 'border-r-0' : 'border-r',
|
|
171
|
+
index >= 6 ? 'border-b-0' : 'border-b',
|
|
172
|
+
getDelayClass(index),
|
|
173
|
+
cellClassName,
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
const content = (
|
|
177
|
+
<>
|
|
178
|
+
{icon && iconPosition === 'before' && icon}
|
|
179
|
+
<span className="relative z-10">{label}</span>
|
|
180
|
+
{icon && iconPosition === 'after' && icon}
|
|
181
|
+
</>
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
if (isExternalUrl(href)) {
|
|
185
|
+
return (
|
|
186
|
+
<a
|
|
187
|
+
key={item.id || `${label}-${index}`}
|
|
188
|
+
href={href}
|
|
189
|
+
target={target}
|
|
190
|
+
rel={rel}
|
|
191
|
+
className={className}
|
|
192
|
+
style={{
|
|
193
|
+
fontFamily: "'Space Grotesk', sans-serif",
|
|
194
|
+
fontWeight: 400,
|
|
195
|
+
position: 'relative',
|
|
196
|
+
textDecoration: 'none',
|
|
197
|
+
}}
|
|
198
|
+
>
|
|
199
|
+
{content}
|
|
200
|
+
</a>
|
|
201
|
+
)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return (
|
|
205
|
+
<Link
|
|
206
|
+
key={item.id || `${label}-${index}`}
|
|
207
|
+
href={href}
|
|
208
|
+
target={target}
|
|
209
|
+
rel={rel}
|
|
210
|
+
className={className}
|
|
211
|
+
style={{
|
|
212
|
+
fontFamily: "'Space Grotesk', sans-serif",
|
|
213
|
+
fontWeight: 400,
|
|
214
|
+
position: 'relative',
|
|
215
|
+
textDecoration: 'none',
|
|
216
|
+
}}
|
|
217
|
+
>
|
|
218
|
+
{content}
|
|
219
|
+
</Link>
|
|
220
|
+
)
|
|
221
|
+
})}
|
|
222
|
+
</div>
|
|
223
|
+
</div>
|
|
224
|
+
)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
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
|
+
}
|