blocks-dusted 0.1.10 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -0
- package/package.json +1 -1
- 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 +10 -11
- 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 +5 -6
- 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 +434 -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 +40 -17
- package/templates/blocks/DD-Hero/config.ts +267 -267
- package/templates/blocks/DD-HorizontalScroll/Component.tsx +4 -2
- 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 +129 -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 +547 -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 +372 -372
- package/templates/blocks/DD-Process/Component.tsx +149 -149
- package/templates/blocks/DD-Process/config.ts +150 -150
- package/templates/blocks/DD-Progress/Component.tsx +141 -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 +237 -237
- package/templates/blocks/DD-StackCards/Component.tsx +473 -473
- 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 +168 -162
- 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 +147 -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 +500 -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 +93 -0
- package/templates/blocks/DDHG-LogoMarquee/config.ts +66 -0
- package/templates/blocks/DDHG-LogoMarquee/manifest.json +39 -0
- package/templates/blocks/DDHG-NavCodeGrid/Component.tsx +213 -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 +575 -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 +394 -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 +131 -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
|
@@ -1,247 +1,247 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import React from 'react'
|
|
4
|
-
import Image from 'next/image'
|
|
5
|
-
import { FaGithub, FaLinkedin, FaTwitter } from 'react-icons/fa'
|
|
6
|
-
import { motion, type Variants } from 'framer-motion'
|
|
7
|
-
export type DDTeamProps = Record<string, any>
|
|
8
|
-
type Media = { url?: string | null }
|
|
9
|
-
type SkillItem = { skill?: string | null }
|
|
10
|
-
type MemberItem = {
|
|
11
|
-
id?: string | null
|
|
12
|
-
name?: string | null
|
|
13
|
-
role?: string | null
|
|
14
|
-
bio?: string | null
|
|
15
|
-
photo?: Media | string | null
|
|
16
|
-
fallbackPhotoUrl?: string | null
|
|
17
|
-
skills?: SkillItem[] | null
|
|
18
|
-
twitterUrl?: string | null
|
|
19
|
-
githubUrl?: string | null
|
|
20
|
-
linkedinUrl?: string | null
|
|
21
|
-
}
|
|
22
|
-
type ClientItem = { name?: string | null }
|
|
23
|
-
|
|
24
|
-
function isLocalImageSrc(src?: string | null): src is string {
|
|
25
|
-
return typeof src === 'string' && src.startsWith('/api/media/file/')
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function TeamPhotoPlaceholder({ name }: { name: string }) {
|
|
29
|
-
const initials = name
|
|
30
|
-
.split(' ')
|
|
31
|
-
.map((part) => part[0])
|
|
32
|
-
.join('')
|
|
33
|
-
.slice(0, 2)
|
|
34
|
-
.toUpperCase()
|
|
35
|
-
|
|
36
|
-
return (
|
|
37
|
-
<div className="w-full h-64 overflow-hidden relative bg-[#12151f]">
|
|
38
|
-
<svg
|
|
39
|
-
aria-hidden="true"
|
|
40
|
-
className="absolute inset-0 h-full w-full"
|
|
41
|
-
viewBox="0 0 600 520"
|
|
42
|
-
preserveAspectRatio="none"
|
|
43
|
-
>
|
|
44
|
-
<defs>
|
|
45
|
-
<linearGradient id="dd-team-placeholder" x1="0" y1="0" x2="1" y2="1">
|
|
46
|
-
<stop offset="0%" stopColor="#111827" />
|
|
47
|
-
<stop offset="50%" stopColor="#251644" />
|
|
48
|
-
<stop offset="100%" stopColor="#09090b" />
|
|
49
|
-
</linearGradient>
|
|
50
|
-
<pattern id="dd-team-grid" width="56" height="56" patternUnits="userSpaceOnUse">
|
|
51
|
-
<path d="M 56 0 L 0 0 0 56" fill="none" stroke="#ffffff" strokeOpacity="0.07" />
|
|
52
|
-
</pattern>
|
|
53
|
-
</defs>
|
|
54
|
-
<rect width="600" height="520" fill="url(#dd-team-placeholder)" />
|
|
55
|
-
<rect width="600" height="520" fill="url(#dd-team-grid)" />
|
|
56
|
-
<circle cx="300" cy="210" r="92" fill="#ffffff" fillOpacity="0.1" />
|
|
57
|
-
<path d="M 150 485 C 180 350 420 350 450 485 Z" fill="#ffffff" fillOpacity="0.1" />
|
|
58
|
-
</svg>
|
|
59
|
-
<div className="absolute inset-0 flex items-center justify-center text-4xl font-semibold text-stone-200/80">
|
|
60
|
-
{initials || 'DD'}
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
63
|
-
)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const containerVariants: Variants = {
|
|
67
|
-
hidden: {},
|
|
68
|
-
show: { transition: { staggerChildren: 0.1, delayChildren: 0.05 } },
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const cardVariants: Variants = {
|
|
72
|
-
hidden: { opacity: 0, y: 28 },
|
|
73
|
-
show: { opacity: 1, y: 0, transition: { duration: 0.5, ease: 'easeOut' } },
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export const DDTeam: React.FC<DDTeamProps> = ({
|
|
77
|
-
eyebrow,
|
|
78
|
-
headlineMain,
|
|
79
|
-
headlineAccent,
|
|
80
|
-
description,
|
|
81
|
-
members,
|
|
82
|
-
showClients,
|
|
83
|
-
clientsLabel,
|
|
84
|
-
clients,
|
|
85
|
-
sectionId,
|
|
86
|
-
customCSS,
|
|
87
|
-
}) => {
|
|
88
|
-
const memberItems = (members ?? []) as MemberItem[]
|
|
89
|
-
const clientItems = (clients ?? []) as ClientItem[]
|
|
90
|
-
|
|
91
|
-
return (
|
|
92
|
-
<>
|
|
93
|
-
{customCSS && <style dangerouslySetInnerHTML={{ __html: customCSS }} />}
|
|
94
|
-
|
|
95
|
-
<div id={sectionId ?? 'team'} className="py-24">
|
|
96
|
-
<div className="max-w-6xl lg:max-w-7xl mx-auto px-4 md:px-6">
|
|
97
|
-
{/* Header */}
|
|
98
|
-
<div className="text-center max-w-2xl mx-auto mb-16">
|
|
99
|
-
{eyebrow && (
|
|
100
|
-
<p className="text-[11.5px] font-semibold text-stone-400 tracking-widest uppercase mb-3 top-caption">
|
|
101
|
-
{eyebrow}
|
|
102
|
-
</p>
|
|
103
|
-
)}
|
|
104
|
-
<h2 className="text-3d text-4xl md:text-5xl font-bold text-stone-900 dark:text-stone-50 leading-tight mb-5">
|
|
105
|
-
{headlineMain}
|
|
106
|
-
<br />
|
|
107
|
-
<span className="text-stone-400">{headlineAccent}</span>
|
|
108
|
-
</h2>
|
|
109
|
-
{description && (
|
|
110
|
-
<p className="text-stone-700 dark:text-stone-300 text-base leading-relaxed">
|
|
111
|
-
{description}
|
|
112
|
-
</p>
|
|
113
|
-
)}
|
|
114
|
-
</div>
|
|
115
|
-
{/* Team Cards */}
|
|
116
|
-
{memberItems.length > 0 && (
|
|
117
|
-
<motion.div
|
|
118
|
-
className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-20"
|
|
119
|
-
variants={containerVariants}
|
|
120
|
-
initial="hidden"
|
|
121
|
-
whileInView="show"
|
|
122
|
-
viewport={{ once: false, amount: 0.15 }}
|
|
123
|
-
>
|
|
124
|
-
{memberItems.map((member, i) => {
|
|
125
|
-
const memberName = member.name ?? ''
|
|
126
|
-
const photoUrl =
|
|
127
|
-
typeof member.photo === 'object' && member.photo?.url
|
|
128
|
-
? member.photo.url
|
|
129
|
-
: (member.fallbackPhotoUrl ?? null)
|
|
130
|
-
const safePhotoUrl = isLocalImageSrc(photoUrl) ? photoUrl : null
|
|
131
|
-
|
|
132
|
-
return (
|
|
133
|
-
<motion.div
|
|
134
|
-
key={member.id ?? i}
|
|
135
|
-
className="rounded-2xl bg-stone-100/50 dark:bg-stone-800/50 border border-stone-200 dark:border-stone-700 overflow-hidden group hover:shadow-2xl transition-all duration-300"
|
|
136
|
-
variants={cardVariants}
|
|
137
|
-
>
|
|
138
|
-
{/* Photo */}
|
|
139
|
-
{safePhotoUrl ? (
|
|
140
|
-
<div className="w-full h-64 overflow-hidden relative">
|
|
141
|
-
<Image
|
|
142
|
-
src={safePhotoUrl}
|
|
143
|
-
alt={memberName}
|
|
144
|
-
fill
|
|
145
|
-
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
|
|
146
|
-
className="object-cover object-top group-hover:scale-105 transition-transform duration-500 studio-card-image"
|
|
147
|
-
/>
|
|
148
|
-
</div>
|
|
149
|
-
) : (
|
|
150
|
-
<TeamPhotoPlaceholder name={memberName} />
|
|
151
|
-
)}
|
|
152
|
-
|
|
153
|
-
{/* Info */}
|
|
154
|
-
<div className="p-6">
|
|
155
|
-
<h3 className="text-base font-semibold text-stone-900 dark:text-stone-50 mb-0.5">
|
|
156
|
-
{memberName}
|
|
157
|
-
</h3>
|
|
158
|
-
<p className="text-xs text-stone-700 dark:text-stone-400 mb-6">
|
|
159
|
-
{member.role}
|
|
160
|
-
</p>
|
|
161
|
-
{member.bio && (
|
|
162
|
-
<p className="text-sm text-stone-700 dark:text-stone-300 leading-relaxed mb-4">
|
|
163
|
-
{member.bio}
|
|
164
|
-
</p>
|
|
165
|
-
)}
|
|
166
|
-
|
|
167
|
-
{/* Skills */}
|
|
168
|
-
{member.skills && member.skills.length > 0 && (
|
|
169
|
-
<div className="flex flex-wrap gap-1.5 mb-4">
|
|
170
|
-
{member.skills.map((s, si) => (
|
|
171
|
-
<span
|
|
172
|
-
key={si}
|
|
173
|
-
className="text-[11.5px] mt-4 px-2.5 py-0.5 rounded-full bg-stone-50 dark:bg-stone-700 text-stone-700 dark:text-stone-300 border border-stone-200 dark:border-stone-600"
|
|
174
|
-
>
|
|
175
|
-
{s.skill}
|
|
176
|
-
</span>
|
|
177
|
-
))}
|
|
178
|
-
</div>
|
|
179
|
-
)}
|
|
180
|
-
|
|
181
|
-
{/* Social */}
|
|
182
|
-
<div className="relative flex items-center justify-end gap-2">
|
|
183
|
-
{member.twitterUrl && (
|
|
184
|
-
<a
|
|
185
|
-
href={member.twitterUrl}
|
|
186
|
-
rel="nofollow noreferrer"
|
|
187
|
-
target="_blank"
|
|
188
|
-
aria-label={`Follow ${memberName} on Twitter`}
|
|
189
|
-
className="w-7 h-7 flex items-center justify-center rounded-lg dark:bg-stone-700 text-stone-500 dark:text-stone-400 hover:text-stone-50 hover:bg-stone-600 transition-all duration-150 border border-stone-200 dark:border-stone-600"
|
|
190
|
-
>
|
|
191
|
-
<FaTwitter size={12} />
|
|
192
|
-
</a>
|
|
193
|
-
)}
|
|
194
|
-
{member.githubUrl && (
|
|
195
|
-
<a
|
|
196
|
-
href={member.githubUrl}
|
|
197
|
-
rel="nofollow noreferrer"
|
|
198
|
-
target="_blank"
|
|
199
|
-
aria-label={`View ${memberName}'s GitHub profile`}
|
|
200
|
-
className="w-7 h-7 flex items-center justify-center rounded-lg dark:bg-stone-700 text-stone-500 dark:text-stone-400 hover:text-stone-50 hover:bg-stone-600 transition-all duration-150 border border-stone-200 dark:border-stone-600"
|
|
201
|
-
>
|
|
202
|
-
<FaGithub size={12} />
|
|
203
|
-
</a>
|
|
204
|
-
)}
|
|
205
|
-
{member.linkedinUrl && (
|
|
206
|
-
<a
|
|
207
|
-
href={member.linkedinUrl}
|
|
208
|
-
rel="nofollow noreferrer"
|
|
209
|
-
target="_blank"
|
|
210
|
-
aria-label={`Connect with ${memberName} on LinkedIn`}
|
|
211
|
-
className="w-7 h-7 flex items-center justify-center rounded-lg dark:bg-stone-700 text-stone-500 dark:text-stone-400 hover:text-stone-50 hover:bg-stone-600 transition-all duration-150 border border-stone-200 dark:border-stone-600"
|
|
212
|
-
>
|
|
213
|
-
<FaLinkedin size={12} />
|
|
214
|
-
</a>
|
|
215
|
-
)}
|
|
216
|
-
</div>
|
|
217
|
-
</div>
|
|
218
|
-
</motion.div>
|
|
219
|
-
)
|
|
220
|
-
})}
|
|
221
|
-
</motion.div>
|
|
222
|
-
)}
|
|
223
|
-
{/* Clients */}
|
|
224
|
-
{showClients && clientItems.length > 0 && (
|
|
225
|
-
<div className="border-t border-stone-200 dark:border-stone-700 pt-12">
|
|
226
|
-
{clientsLabel && (
|
|
227
|
-
<p className="text-xs font-semibold text-stone-400 tracking-widest uppercase text-center mb-8">
|
|
228
|
-
{clientsLabel}
|
|
229
|
-
</p>
|
|
230
|
-
)}
|
|
231
|
-
<div className="flex flex-wrap items-center justify-center gap-x-10 gap-y-0">
|
|
232
|
-
{clientItems.map((c, i) => (
|
|
233
|
-
<span
|
|
234
|
-
key={i}
|
|
235
|
-
className="-mt-4 text-4xl font-semibold text-stone-500 hover:text-stone-300 transition-colors cursor-default"
|
|
236
|
-
>
|
|
237
|
-
{c.name}
|
|
238
|
-
</span>
|
|
239
|
-
))}
|
|
240
|
-
</div>
|
|
241
|
-
</div>
|
|
242
|
-
)}
|
|
243
|
-
</div>
|
|
244
|
-
</div>
|
|
245
|
-
</>
|
|
246
|
-
)
|
|
247
|
-
}
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import Image from 'next/image'
|
|
5
|
+
import { FaGithub, FaLinkedin, FaTwitter } from 'react-icons/fa'
|
|
6
|
+
import { motion, type Variants } from 'framer-motion'
|
|
7
|
+
export type DDTeamProps = Record<string, any>
|
|
8
|
+
type Media = { url?: string | null }
|
|
9
|
+
type SkillItem = { skill?: string | null }
|
|
10
|
+
type MemberItem = {
|
|
11
|
+
id?: string | null
|
|
12
|
+
name?: string | null
|
|
13
|
+
role?: string | null
|
|
14
|
+
bio?: string | null
|
|
15
|
+
photo?: Media | string | null
|
|
16
|
+
fallbackPhotoUrl?: string | null
|
|
17
|
+
skills?: SkillItem[] | null
|
|
18
|
+
twitterUrl?: string | null
|
|
19
|
+
githubUrl?: string | null
|
|
20
|
+
linkedinUrl?: string | null
|
|
21
|
+
}
|
|
22
|
+
type ClientItem = { name?: string | null }
|
|
23
|
+
|
|
24
|
+
function isLocalImageSrc(src?: string | null): src is string {
|
|
25
|
+
return typeof src === 'string' && src.startsWith('/api/media/file/')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function TeamPhotoPlaceholder({ name }: { name: string }) {
|
|
29
|
+
const initials = name
|
|
30
|
+
.split(' ')
|
|
31
|
+
.map((part) => part[0])
|
|
32
|
+
.join('')
|
|
33
|
+
.slice(0, 2)
|
|
34
|
+
.toUpperCase()
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<div className="w-full h-64 overflow-hidden relative bg-[#12151f]">
|
|
38
|
+
<svg
|
|
39
|
+
aria-hidden="true"
|
|
40
|
+
className="absolute inset-0 h-full w-full"
|
|
41
|
+
viewBox="0 0 600 520"
|
|
42
|
+
preserveAspectRatio="none"
|
|
43
|
+
>
|
|
44
|
+
<defs>
|
|
45
|
+
<linearGradient id="dd-team-placeholder" x1="0" y1="0" x2="1" y2="1">
|
|
46
|
+
<stop offset="0%" stopColor="#111827" />
|
|
47
|
+
<stop offset="50%" stopColor="#251644" />
|
|
48
|
+
<stop offset="100%" stopColor="#09090b" />
|
|
49
|
+
</linearGradient>
|
|
50
|
+
<pattern id="dd-team-grid" width="56" height="56" patternUnits="userSpaceOnUse">
|
|
51
|
+
<path d="M 56 0 L 0 0 0 56" fill="none" stroke="#ffffff" strokeOpacity="0.07" />
|
|
52
|
+
</pattern>
|
|
53
|
+
</defs>
|
|
54
|
+
<rect width="600" height="520" fill="url(#dd-team-placeholder)" />
|
|
55
|
+
<rect width="600" height="520" fill="url(#dd-team-grid)" />
|
|
56
|
+
<circle cx="300" cy="210" r="92" fill="#ffffff" fillOpacity="0.1" />
|
|
57
|
+
<path d="M 150 485 C 180 350 420 350 450 485 Z" fill="#ffffff" fillOpacity="0.1" />
|
|
58
|
+
</svg>
|
|
59
|
+
<div className="absolute inset-0 flex items-center justify-center text-4xl font-semibold text-stone-200/80">
|
|
60
|
+
{initials || 'DD'}
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const containerVariants: Variants = {
|
|
67
|
+
hidden: {},
|
|
68
|
+
show: { transition: { staggerChildren: 0.1, delayChildren: 0.05 } },
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const cardVariants: Variants = {
|
|
72
|
+
hidden: { opacity: 0, y: 28 },
|
|
73
|
+
show: { opacity: 1, y: 0, transition: { duration: 0.5, ease: 'easeOut' } },
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export const DDTeam: React.FC<DDTeamProps> = ({
|
|
77
|
+
eyebrow,
|
|
78
|
+
headlineMain,
|
|
79
|
+
headlineAccent,
|
|
80
|
+
description,
|
|
81
|
+
members,
|
|
82
|
+
showClients,
|
|
83
|
+
clientsLabel,
|
|
84
|
+
clients,
|
|
85
|
+
sectionId,
|
|
86
|
+
customCSS,
|
|
87
|
+
}) => {
|
|
88
|
+
const memberItems = (members ?? []) as MemberItem[]
|
|
89
|
+
const clientItems = (clients ?? []) as ClientItem[]
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<>
|
|
93
|
+
{customCSS && <style dangerouslySetInnerHTML={{ __html: customCSS }} />}
|
|
94
|
+
|
|
95
|
+
<div id={sectionId ?? 'team'} className="py-24">
|
|
96
|
+
<div className="max-w-6xl lg:max-w-7xl mx-auto px-4 md:px-6">
|
|
97
|
+
{/* Header */}
|
|
98
|
+
<div className="text-center max-w-2xl mx-auto mb-16">
|
|
99
|
+
{eyebrow && (
|
|
100
|
+
<p className="text-[11.5px] font-semibold text-stone-400 tracking-widest uppercase mb-3 top-caption">
|
|
101
|
+
{eyebrow}
|
|
102
|
+
</p>
|
|
103
|
+
)}
|
|
104
|
+
<h2 className="text-3d text-4xl md:text-5xl font-bold text-stone-900 dark:text-stone-50 leading-tight mb-5">
|
|
105
|
+
{headlineMain}
|
|
106
|
+
<br />
|
|
107
|
+
<span className="text-stone-400">{headlineAccent}</span>
|
|
108
|
+
</h2>
|
|
109
|
+
{description && (
|
|
110
|
+
<p className="text-stone-700 dark:text-stone-300 text-base leading-relaxed">
|
|
111
|
+
{description}
|
|
112
|
+
</p>
|
|
113
|
+
)}
|
|
114
|
+
</div>
|
|
115
|
+
{/* Team Cards */}
|
|
116
|
+
{memberItems.length > 0 && (
|
|
117
|
+
<motion.div
|
|
118
|
+
className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-20"
|
|
119
|
+
variants={containerVariants}
|
|
120
|
+
initial="hidden"
|
|
121
|
+
whileInView="show"
|
|
122
|
+
viewport={{ once: false, amount: 0.15 }}
|
|
123
|
+
>
|
|
124
|
+
{memberItems.map((member, i) => {
|
|
125
|
+
const memberName = member.name ?? ''
|
|
126
|
+
const photoUrl =
|
|
127
|
+
typeof member.photo === 'object' && member.photo?.url
|
|
128
|
+
? member.photo.url
|
|
129
|
+
: (member.fallbackPhotoUrl ?? null)
|
|
130
|
+
const safePhotoUrl = isLocalImageSrc(photoUrl) ? photoUrl : null
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<motion.div
|
|
134
|
+
key={member.id ?? i}
|
|
135
|
+
className="rounded-2xl bg-stone-100/50 dark:bg-stone-800/50 border border-stone-200 dark:border-stone-700 overflow-hidden group hover:shadow-2xl transition-all duration-300"
|
|
136
|
+
variants={cardVariants}
|
|
137
|
+
>
|
|
138
|
+
{/* Photo */}
|
|
139
|
+
{safePhotoUrl ? (
|
|
140
|
+
<div className="w-full h-64 overflow-hidden relative">
|
|
141
|
+
<Image
|
|
142
|
+
src={safePhotoUrl}
|
|
143
|
+
alt={memberName}
|
|
144
|
+
fill
|
|
145
|
+
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
|
|
146
|
+
className="object-cover object-top group-hover:scale-105 transition-transform duration-500 studio-card-image"
|
|
147
|
+
/>
|
|
148
|
+
</div>
|
|
149
|
+
) : (
|
|
150
|
+
<TeamPhotoPlaceholder name={memberName} />
|
|
151
|
+
)}
|
|
152
|
+
|
|
153
|
+
{/* Info */}
|
|
154
|
+
<div className="p-6">
|
|
155
|
+
<h3 className="text-base font-semibold text-stone-900 dark:text-stone-50 mb-0.5">
|
|
156
|
+
{memberName}
|
|
157
|
+
</h3>
|
|
158
|
+
<p className="text-xs text-stone-700 dark:text-stone-400 mb-6">
|
|
159
|
+
{member.role}
|
|
160
|
+
</p>
|
|
161
|
+
{member.bio && (
|
|
162
|
+
<p className="text-sm text-stone-700 dark:text-stone-300 leading-relaxed mb-4">
|
|
163
|
+
{member.bio}
|
|
164
|
+
</p>
|
|
165
|
+
)}
|
|
166
|
+
|
|
167
|
+
{/* Skills */}
|
|
168
|
+
{member.skills && member.skills.length > 0 && (
|
|
169
|
+
<div className="flex flex-wrap gap-1.5 mb-4">
|
|
170
|
+
{member.skills.map((s, si) => (
|
|
171
|
+
<span
|
|
172
|
+
key={si}
|
|
173
|
+
className="text-[11.5px] mt-4 px-2.5 py-0.5 rounded-full bg-stone-50 dark:bg-stone-700 text-stone-700 dark:text-stone-300 border border-stone-200 dark:border-stone-600"
|
|
174
|
+
>
|
|
175
|
+
{s.skill}
|
|
176
|
+
</span>
|
|
177
|
+
))}
|
|
178
|
+
</div>
|
|
179
|
+
)}
|
|
180
|
+
|
|
181
|
+
{/* Social */}
|
|
182
|
+
<div className="relative flex items-center justify-end gap-2">
|
|
183
|
+
{member.twitterUrl && (
|
|
184
|
+
<a
|
|
185
|
+
href={member.twitterUrl}
|
|
186
|
+
rel="nofollow noreferrer"
|
|
187
|
+
target="_blank"
|
|
188
|
+
aria-label={`Follow ${memberName} on Twitter`}
|
|
189
|
+
className="w-7 h-7 flex items-center justify-center rounded-lg dark:bg-stone-700 text-stone-500 dark:text-stone-400 hover:text-stone-50 hover:bg-stone-600 transition-all duration-150 border border-stone-200 dark:border-stone-600"
|
|
190
|
+
>
|
|
191
|
+
<FaTwitter size={12} />
|
|
192
|
+
</a>
|
|
193
|
+
)}
|
|
194
|
+
{member.githubUrl && (
|
|
195
|
+
<a
|
|
196
|
+
href={member.githubUrl}
|
|
197
|
+
rel="nofollow noreferrer"
|
|
198
|
+
target="_blank"
|
|
199
|
+
aria-label={`View ${memberName}'s GitHub profile`}
|
|
200
|
+
className="w-7 h-7 flex items-center justify-center rounded-lg dark:bg-stone-700 text-stone-500 dark:text-stone-400 hover:text-stone-50 hover:bg-stone-600 transition-all duration-150 border border-stone-200 dark:border-stone-600"
|
|
201
|
+
>
|
|
202
|
+
<FaGithub size={12} />
|
|
203
|
+
</a>
|
|
204
|
+
)}
|
|
205
|
+
{member.linkedinUrl && (
|
|
206
|
+
<a
|
|
207
|
+
href={member.linkedinUrl}
|
|
208
|
+
rel="nofollow noreferrer"
|
|
209
|
+
target="_blank"
|
|
210
|
+
aria-label={`Connect with ${memberName} on LinkedIn`}
|
|
211
|
+
className="w-7 h-7 flex items-center justify-center rounded-lg dark:bg-stone-700 text-stone-500 dark:text-stone-400 hover:text-stone-50 hover:bg-stone-600 transition-all duration-150 border border-stone-200 dark:border-stone-600"
|
|
212
|
+
>
|
|
213
|
+
<FaLinkedin size={12} />
|
|
214
|
+
</a>
|
|
215
|
+
)}
|
|
216
|
+
</div>
|
|
217
|
+
</div>
|
|
218
|
+
</motion.div>
|
|
219
|
+
)
|
|
220
|
+
})}
|
|
221
|
+
</motion.div>
|
|
222
|
+
)}
|
|
223
|
+
{/* Clients */}
|
|
224
|
+
{showClients && clientItems.length > 0 && (
|
|
225
|
+
<div className="border-t border-stone-200 dark:border-stone-700 pt-12">
|
|
226
|
+
{clientsLabel && (
|
|
227
|
+
<p className="text-xs font-semibold text-stone-400 tracking-widest uppercase text-center mb-8">
|
|
228
|
+
{clientsLabel}
|
|
229
|
+
</p>
|
|
230
|
+
)}
|
|
231
|
+
<div className="flex flex-wrap items-center justify-center gap-x-10 gap-y-0">
|
|
232
|
+
{clientItems.map((c, i) => (
|
|
233
|
+
<span
|
|
234
|
+
key={i}
|
|
235
|
+
className="-mt-4 text-4xl font-semibold text-stone-500 hover:text-stone-300 transition-colors cursor-default"
|
|
236
|
+
>
|
|
237
|
+
{c.name}
|
|
238
|
+
</span>
|
|
239
|
+
))}
|
|
240
|
+
</div>
|
|
241
|
+
</div>
|
|
242
|
+
)}
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
245
|
+
</>
|
|
246
|
+
)
|
|
247
|
+
}
|