blocks-dusted 0.1.12 → 0.1.13
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/package.json +1 -1
- package/src/installers/patchRenderBlocks.js +1 -1
- package/src/registry/validateTemplateManifest.js +2 -1
- package/templates/blocks/BannerDD790432/Component.tsx +63 -0
- package/templates/blocks/BannerDD790432/config.ts +54 -0
- package/templates/blocks/BannerDD790432/manifest.json +80 -0
- package/templates/blocks/Button47/Component.tsx +124 -0
- package/templates/blocks/Button47/config.ts +75 -0
- package/templates/blocks/Button47/link.ts +22 -0
- package/templates/blocks/Button47/manifest.json +105 -0
- package/templates/blocks/Button47/styles.module.scss +75 -0
- package/templates/blocks/DD-Accordion/Component.tsx +55 -36
- package/templates/blocks/DD-Accordion/config.ts +71 -59
- package/templates/blocks/DD-AnimText/Component.tsx +50 -32
- package/templates/blocks/DD-AnimText/config.ts +296 -295
- package/templates/blocks/DD-AsideNav/Component.tsx +323 -319
- package/templates/blocks/DD-Banner/Component.tsx +54 -51
- package/templates/blocks/DD-BookCall/Component.tsx +535 -535
- package/templates/blocks/DD-ButtonPop/Component.tsx +118 -117
- package/templates/blocks/DD-Card/Component.tsx +4 -4
- package/templates/blocks/DD-CardTemplate01/Component.tsx +139 -140
- package/templates/blocks/DD-CardsWithVariantV3/Component.tsx +472 -0
- package/templates/blocks/DD-CardsWithVariantV3/ElectricBorder/index.tsx +203 -0
- package/templates/blocks/DD-CardsWithVariantV3/ElectricBorder/styles.ts +87 -0
- package/templates/blocks/DD-CardsWithVariantV3/ElectricBorder/useInjectStyle.ts +39 -0
- package/templates/blocks/DD-CardsWithVariantV3/config.ts +326 -0
- package/templates/blocks/DD-CardsWithVariantV3/manifest.json +110 -0
- package/templates/blocks/DD-Carousel-A/Component.tsx +251 -249
- package/templates/blocks/DD-Carousel-B/Component.tsx +405 -403
- package/templates/blocks/DD-ComparisonTable/Component.tsx +255 -256
- package/templates/blocks/DD-Contact/Component.tsx +433 -435
- package/templates/blocks/DD-Counter/Component.tsx +11 -6
- package/templates/blocks/DD-DeliCard/Component.tsx +303 -0
- package/templates/blocks/DD-DeliCard/config.ts +186 -0
- package/templates/blocks/DD-DeliCard/manifest.json +94 -0
- package/templates/blocks/DD-FeatCat/Component.tsx +302 -302
- package/templates/blocks/DD-FeatProd/CircularGallery.tsx +1179 -0
- package/templates/blocks/DD-FeatProd/Component.tsx +484 -0
- package/templates/blocks/DD-FeatProd/config.ts +173 -0
- package/templates/blocks/DD-FeatProd/manifest.json +93 -0
- package/templates/blocks/DD-FeatServ/Component.tsx +607 -0
- package/templates/blocks/DD-FeatServ/config.ts +213 -0
- package/templates/blocks/DD-FeatServ/manifest.json +113 -0
- package/templates/blocks/DD-FeatStrip/Component.tsx +584 -585
- package/templates/blocks/DD-FluidBtn/ButtonsEyeCatching.tsx +627 -628
- package/templates/blocks/DD-FluidBtn/Component.tsx +46 -43
- package/templates/blocks/DD-GooeyInfo/Component.tsx +150 -149
- package/templates/blocks/DD-GooeyInfo/config.ts +136 -135
- package/templates/blocks/DD-Hero/Component.tsx +296 -297
- package/templates/blocks/DD-HeroPlas/Component.tsx +50 -0
- package/templates/blocks/DD-HeroPlas/ThreeScene.tsx +109 -0
- package/templates/blocks/DD-HeroPlas/config.ts +33 -0
- package/templates/blocks/DD-HeroPlas/manifest.json +88 -0
- package/templates/blocks/DD-HorizontalScroll/Component.tsx +937 -936
- package/templates/blocks/DD-Icon/Component.tsx +46 -81
- package/templates/blocks/DD-IconButton/Component.tsx +13 -20
- package/templates/blocks/DD-IdTag/Component.tsx +22 -21
- package/templates/blocks/DD-LineAnim/Component.tsx +42 -36
- package/templates/blocks/DD-LogoMarq/Component.tsx +38 -48
- package/templates/blocks/DD-Lottie/Component.tsx +11 -3
- package/templates/blocks/DD-MasonaryMedia/Component.tsx +544 -545
- package/templates/blocks/DD-MasonaryMedia/config.ts +389 -389
- package/templates/blocks/DD-Masonry/Component.tsx +654 -644
- package/templates/blocks/DD-Masonry/config.ts +475 -475
- package/templates/blocks/DD-MaterialSwatches/Component.tsx +85 -0
- package/templates/blocks/DD-MaterialSwatches/config.ts +232 -0
- package/templates/blocks/DD-MaterialSwatches/manifest.json +84 -0
- package/templates/blocks/DD-MaterialSwatches/material.ts +107 -0
- package/templates/blocks/DD-NineCanvas/Component.tsx +129 -0
- package/templates/blocks/DD-NineCanvas/RenderBlocks.tsx +244 -0
- package/templates/blocks/DD-NineCanvas/allowedCanvasBlocks.ts +6 -0
- package/templates/blocks/DD-NineCanvas/blockComponents.tsx +8 -0
- package/templates/blocks/DD-NineCanvas/canvas/CanvasGrid.tsx +316 -0
- package/templates/blocks/DD-NineCanvas/canvas/RadialNav.tsx +432 -0
- package/templates/blocks/DD-NineCanvas/canvas/canvas-panels.css +889 -0
- package/templates/blocks/DD-NineCanvas/canvas/icons/custom-icons.tsx +364 -0
- package/templates/blocks/DD-NineCanvas/config.ts +61 -0
- package/templates/blocks/DD-NineCanvas/manifest.json +165 -0
- package/templates/blocks/DD-NineCanvas/styles.scss +152 -0
- package/templates/blocks/DD-NineCanvas/tooltip/get-strict-context.tsx +26 -0
- package/templates/blocks/DD-NineCanvas/tooltip/primitives.tsx +178 -0
- package/templates/blocks/DD-NineCanvas/tooltip/tooltip.tsx +71 -0
- package/templates/blocks/DD-NineCanvas/tooltip/use-controlled-state.tsx +33 -0
- package/templates/blocks/DD-NineCanvas/utilities/FadeOnScroll.tsx +68 -0
- package/templates/blocks/DD-NineCanvas/utilities/ParallaxWrapper.tsx +157 -0
- package/templates/blocks/DD-NineCanvas/utilities/renderCustomCSS.ts +5 -0
- package/templates/blocks/DD-NineCanvas/utilities/webglCleanup.ts +27 -0
- package/templates/blocks/DD-PayloadAIAssistant/Component.tsx +78 -0
- package/templates/blocks/DD-PayloadAIAssistant/DustedBot.tsx +590 -0
- package/templates/blocks/DD-PayloadAIAssistant/config.ts +37 -0
- package/templates/blocks/DD-PayloadAIAssistant/demo.css +125 -0
- package/templates/blocks/DD-PayloadAIAssistant/manifest.json +93 -0
- package/templates/blocks/DD-PayloadAIAssistant/source-defaults.ts +17 -0
- package/templates/blocks/DD-PayloadAIAssistant/styles.ts +306 -0
- package/templates/blocks/DD-Pricing/Component.tsx +2 -3
- package/templates/blocks/DD-Pricing/config.ts +215 -215
- package/templates/blocks/DD-Process/Component.tsx +2 -2
- package/templates/blocks/DD-ProjHeader/Component.tsx +93 -91
- package/templates/blocks/DD-ProjSlider/Component.tsx +1 -1
- package/templates/blocks/DD-Section/Component.tsx +265 -266
- package/templates/blocks/DD-Separator/Component.tsx +66 -66
- package/templates/blocks/DD-Services/Component.tsx +176 -176
- package/templates/blocks/DD-ShowcaseGrid/Component.tsx +306 -307
- package/templates/blocks/DD-Slider-A/Component.tsx +2 -2
- package/templates/blocks/DD-StackCards/Component.tsx +172 -171
- package/templates/blocks/DD-Team/Component.tsx +247 -247
- package/templates/blocks/DD-TeamCards/Component.tsx +251 -251
- package/templates/blocks/DD-TechStack/Component.tsx +173 -174
- package/templates/blocks/DD-TestMarq/Component.tsx +158 -132
- package/templates/blocks/DD-Testim/Component.tsx +247 -247
- package/templates/blocks/DD-Testim2/Component.tsx +265 -256
- package/templates/blocks/DD-Testimonials/Component.tsx +139 -139
- package/templates/blocks/DD-Thanks/Component.tsx +1 -1
- package/templates/blocks/DD-Work/Component.tsx +318 -318
- package/templates/blocks/DD-Work-B/Component.tsx +294 -294
- package/templates/blocks/DDHG-CTASection2/Component.tsx +183 -184
- package/templates/blocks/DDHG-HighlightArc/Component.tsx +6 -3
- package/templates/blocks/DDHG-LogoMarquee/Component.tsx +45 -8
- package/templates/blocks/DDHG-NavCodeGrid/Component.tsx +1 -3
- package/templates/blocks/DDHG-ServiceDetails/ServiceDetailCard.tsx +9 -22
- package/templates/blocks/DDHG-ServiceHero/Component.tsx +10 -10
- package/templates/blocks/DDHG-TeamCards/Component.tsx +6 -35
- package/templates/blocks/Form/Checkbox/index.tsx +45 -0
- package/templates/blocks/Form/Component.tsx +163 -0
- package/templates/blocks/Form/Country/index.tsx +65 -0
- package/templates/blocks/Form/Country/options.ts +982 -0
- package/templates/blocks/Form/Email/index.tsx +38 -0
- package/templates/blocks/Form/Error/index.tsx +15 -0
- package/templates/blocks/Form/Message/index.tsx +13 -0
- package/templates/blocks/Form/Number/index.tsx +36 -0
- package/templates/blocks/Form/Select/index.tsx +63 -0
- package/templates/blocks/Form/State/index.tsx +64 -0
- package/templates/blocks/Form/State/options.ts +52 -0
- package/templates/blocks/Form/Text/index.tsx +32 -0
- package/templates/blocks/Form/Textarea/index.tsx +40 -0
- package/templates/blocks/Form/Width/index.tsx +13 -0
- package/templates/blocks/Form/config.ts +51 -0
- package/templates/blocks/Form/fields.tsx +21 -0
- package/templates/blocks/Form/manifest.json +168 -0
- package/templates/blocks/MediaBlock/Component.tsx +67 -0
- package/templates/blocks/MediaBlock/config.ts +14 -0
- package/templates/blocks/MediaBlock/manifest.json +92 -0
- package/templates/blocks/TransitionsDustedShowcase/Component.tsx +9 -0
- package/templates/blocks/TransitionsDustedShowcase/config.ts +13 -0
- package/templates/blocks/TransitionsDustedShowcase/manifest.json +80 -0
- package/templates/blocks/rawHtml/Component.tsx +25 -0
- package/templates/blocks/rawHtml/config.ts +56 -0
- package/templates/blocks/rawHtml/manifest.json +80 -0
|
@@ -1,117 +1,118 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import React, { useState, useRef } from 'react'
|
|
4
|
-
import { motion, AnimatePresence } from 'framer-motion'
|
|
5
|
-
import { useClickOutside } from '@/hooks/useClickOutside'
|
|
6
|
-
import { useBodyScrollLock } from '@/hooks/useBodyScrollLock'
|
|
7
|
-
import { cn } from '@/utilities/ui'
|
|
8
|
-
import RichText from '@/components/RichText'
|
|
9
|
-
import DustSvg from './svg-icons/Dust2'
|
|
10
|
-
|
|
11
|
-
interface PopButtonProps {
|
|
12
|
-
buttonLabel: string
|
|
13
|
-
richTextData: any
|
|
14
|
-
width?: string
|
|
15
|
-
height?: string
|
|
16
|
-
position?: 'left' | 'center' | 'right'
|
|
17
|
-
openMode?: 'popover' | 'modal'
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export const DDButtonPop: React.FC<PopButtonProps> = ({
|
|
21
|
-
buttonLabel,
|
|
22
|
-
richTextData,
|
|
23
|
-
width = '360px',
|
|
24
|
-
height = '240px',
|
|
25
|
-
position = 'center',
|
|
26
|
-
openMode = 'popover'
|
|
27
|
-
}) => {
|
|
28
|
-
const [open, setOpen] = useState(false)
|
|
29
|
-
const wrapperRef = useRef<HTMLDivElement>(null) as React.RefObject<HTMLDivElement>
|
|
30
|
-
|
|
31
|
-
useClickOutside(wrapperRef, () => setOpen(false))
|
|
32
|
-
|
|
33
|
-
// Lock body scroll when modal mode is open
|
|
34
|
-
useBodyScrollLock(open && openMode === 'modal', 'buttonPopScrollY')
|
|
35
|
-
|
|
36
|
-
const alignmentClass =
|
|
37
|
-
position === 'left' ? 'justify-start' : position === 'right' ? 'justify-end' : 'justify-center'
|
|
38
|
-
|
|
39
|
-
return (
|
|
40
|
-
<div
|
|
41
|
-
className={cn('relative flex', alignmentClass)}
|
|
42
|
-
style={{ paddingBottom: open ? '50vh' : '1rem' }}
|
|
43
|
-
>
|
|
44
|
-
<motion.button
|
|
45
|
-
key={buttonLabel} // Fixed: Use buttonLabel as key instead of undefined idx
|
|
46
|
-
onClick={() => setOpen(true)}
|
|
47
|
-
className="rounded-md border bg-card px-4 py-2 text-sm font-medium shadow"
|
|
48
|
-
>
|
|
49
|
-
{buttonLabel}
|
|
50
|
-
</motion.button>
|
|
51
|
-
|
|
52
|
-
<AnimatePresence>
|
|
53
|
-
{open &&
|
|
54
|
-
(openMode === 'popover' ? (
|
|
55
|
-
<>
|
|
56
|
-
<motion.div
|
|
57
|
-
ref={wrapperRef}
|
|
58
|
-
key="popover"
|
|
59
|
-
initial={{ opacity: 0, y: -10 }}
|
|
60
|
-
animate={{ opacity: 1, y: 0 }}
|
|
61
|
-
exit={{ opacity: 0, y: -10 }}
|
|
62
|
-
transition={{ duration: 0.2 }}
|
|
63
|
-
className={cn(
|
|
64
|
-
'absolute z-20 rounded-sm bg-card p-4 shadow-lg border border-border'
|
|
65
|
-
)}
|
|
66
|
-
style={{ width, height, maxWidth: '100%', maxHeight: '100%' }}
|
|
67
|
-
>
|
|
68
|
-
<RichText data={richTextData} enableGutter={false} />
|
|
69
|
-
</motion.div>
|
|
70
|
-
{/* <TextFade direction="up" className="absolute z-10 w-full max-w-[8rem] h-auto"> */}
|
|
71
|
-
{/* <LottieFeathers className="absolute right-0 -top-[80px] z-0 rotate-[80deg] lottie-wrapper lottie popper-lottie" /> */}
|
|
72
|
-
{/* </TextFade> */}
|
|
73
|
-
</>
|
|
74
|
-
) : (
|
|
75
|
-
<>
|
|
76
|
-
<motion.div
|
|
77
|
-
ref={wrapperRef}
|
|
78
|
-
key="modal"
|
|
79
|
-
initial={{ opacity: 0 }}
|
|
80
|
-
animate={{ opacity: 1 }}
|
|
81
|
-
exit={{ opacity: 0 }}
|
|
82
|
-
transition={{ duration: 0.2 }}
|
|
83
|
-
className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4"
|
|
84
|
-
style={{ backdropFilter: 'blur(4px)' }}
|
|
85
|
-
>
|
|
86
|
-
<div className="card-wrapper relative flex
|
|
87
|
-
<div
|
|
88
|
-
className="pop-modal-card transition-all duration-300 ease-in-out group relative"
|
|
89
|
-
style={{
|
|
90
|
-
width: width || '80%',
|
|
91
|
-
maxWidth: '500px',
|
|
92
|
-
maxHeight: '90vh',
|
|
93
|
-
overflowY: 'auto'
|
|
94
|
-
}}
|
|
95
|
-
>
|
|
96
|
-
<button
|
|
97
|
-
onClick={() => setOpen(false)}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import React, { useState, useRef } from 'react'
|
|
4
|
+
import { motion, AnimatePresence } from 'framer-motion'
|
|
5
|
+
import { useClickOutside } from '@/hooks/useClickOutside'
|
|
6
|
+
import { useBodyScrollLock } from '@/hooks/useBodyScrollLock'
|
|
7
|
+
import { cn } from '@/utilities/ui'
|
|
8
|
+
import RichText from '@/components/RichText'
|
|
9
|
+
import DustSvg from './svg-icons/Dust2'
|
|
10
|
+
|
|
11
|
+
interface PopButtonProps {
|
|
12
|
+
buttonLabel: string
|
|
13
|
+
richTextData: any
|
|
14
|
+
width?: string
|
|
15
|
+
height?: string
|
|
16
|
+
position?: 'left' | 'center' | 'right'
|
|
17
|
+
openMode?: 'popover' | 'modal'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const DDButtonPop: React.FC<PopButtonProps> = ({
|
|
21
|
+
buttonLabel,
|
|
22
|
+
richTextData,
|
|
23
|
+
width = '360px',
|
|
24
|
+
height = '240px',
|
|
25
|
+
position = 'center',
|
|
26
|
+
openMode = 'popover',
|
|
27
|
+
}) => {
|
|
28
|
+
const [open, setOpen] = useState(false)
|
|
29
|
+
const wrapperRef = useRef<HTMLDivElement>(null) as React.RefObject<HTMLDivElement>
|
|
30
|
+
|
|
31
|
+
useClickOutside(wrapperRef, () => setOpen(false))
|
|
32
|
+
|
|
33
|
+
// Lock body scroll when modal mode is open
|
|
34
|
+
useBodyScrollLock(open && openMode === 'modal', 'buttonPopScrollY')
|
|
35
|
+
|
|
36
|
+
const alignmentClass =
|
|
37
|
+
position === 'left' ? 'justify-start' : position === 'right' ? 'justify-end' : 'justify-center'
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div
|
|
41
|
+
className={cn('relative flex', alignmentClass)}
|
|
42
|
+
style={{ paddingBottom: open ? '50vh' : '1rem' }}
|
|
43
|
+
>
|
|
44
|
+
<motion.button
|
|
45
|
+
key={buttonLabel} // Fixed: Use buttonLabel as key instead of undefined idx
|
|
46
|
+
onClick={() => setOpen(true)}
|
|
47
|
+
className="rounded-md border bg-card px-4 py-2 text-sm font-medium shadow"
|
|
48
|
+
>
|
|
49
|
+
{buttonLabel}
|
|
50
|
+
</motion.button>
|
|
51
|
+
|
|
52
|
+
<AnimatePresence>
|
|
53
|
+
{open &&
|
|
54
|
+
(openMode === 'popover' ? (
|
|
55
|
+
<>
|
|
56
|
+
<motion.div
|
|
57
|
+
ref={wrapperRef}
|
|
58
|
+
key="popover"
|
|
59
|
+
initial={{ opacity: 0, y: -10 }}
|
|
60
|
+
animate={{ opacity: 1, y: 0 }}
|
|
61
|
+
exit={{ opacity: 0, y: -10 }}
|
|
62
|
+
transition={{ duration: 0.2 }}
|
|
63
|
+
className={cn(
|
|
64
|
+
'absolute z-20 rounded-sm bg-card p-4 shadow-lg border border-border',
|
|
65
|
+
)}
|
|
66
|
+
style={{ width, height, maxWidth: '100%', maxHeight: '100%' }}
|
|
67
|
+
>
|
|
68
|
+
<RichText data={richTextData} enableGutter={false} />
|
|
69
|
+
</motion.div>
|
|
70
|
+
{/* <TextFade direction="up" className="absolute z-10 w-full max-w-[8rem] h-auto"> */}
|
|
71
|
+
{/* <LottieFeathers className="absolute right-0 -top-[80px] z-0 rotate-[80deg] lottie-wrapper lottie popper-lottie" /> */}
|
|
72
|
+
{/* </TextFade> */}
|
|
73
|
+
</>
|
|
74
|
+
) : (
|
|
75
|
+
<>
|
|
76
|
+
<motion.div
|
|
77
|
+
ref={wrapperRef}
|
|
78
|
+
key="modal"
|
|
79
|
+
initial={{ opacity: 0 }}
|
|
80
|
+
animate={{ opacity: 1 }}
|
|
81
|
+
exit={{ opacity: 0 }}
|
|
82
|
+
transition={{ duration: 0.2 }}
|
|
83
|
+
className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4"
|
|
84
|
+
style={{ backdropFilter: 'blur(4px)' }}
|
|
85
|
+
>
|
|
86
|
+
<div className="card-wrapper relative flex justify-center mx-4 backdrop-blur-md rounded-lg min-h-fit items-start overflow-clip bg-[var(--background)] p-0">
|
|
87
|
+
<div
|
|
88
|
+
className="pop-modal-card transition-all duration-300 ease-in-out group relative p-4"
|
|
89
|
+
style={{
|
|
90
|
+
width: width || '80%',
|
|
91
|
+
maxWidth: '500px',
|
|
92
|
+
maxHeight: '90vh',
|
|
93
|
+
overflowY: 'auto',
|
|
94
|
+
}}
|
|
95
|
+
>
|
|
96
|
+
<button
|
|
97
|
+
onClick={() => setOpen(false)}
|
|
98
|
+
|
|
99
|
+
className="relative right-0 ml-auto flex justify-end text-sm text-gray-500 cursor-pointer rounded-[14px] border-0 bg-[#00000091] px-1 py-0.5 hover:text-[#af0000] backdrop-blur-[10px] drop-shadow-[2px_4px_6px_black] transition-colors duration-150"
|
|
100
|
+
style={{ background: 'none', border: 'none', cursor: 'pointer' }}
|
|
101
|
+
>
|
|
102
|
+
Close
|
|
103
|
+
</button>
|
|
104
|
+
<RichText
|
|
105
|
+
data={richTextData}
|
|
106
|
+
className="pop-modal-richtext"
|
|
107
|
+
enableGutter={false}
|
|
108
|
+
/>
|
|
109
|
+
<DustSvg className="dustsvg dust-svg-modal absolute opacity-0 -z-10 -mt-24 ml-32 scale-0 transition-all duration-300 ease-in-out group-hover:scale-[3] group-hover:opacity-100" />
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
</motion.div>
|
|
113
|
+
</>
|
|
114
|
+
))}
|
|
115
|
+
</AnimatePresence>
|
|
116
|
+
</div>
|
|
117
|
+
)
|
|
118
|
+
}
|
|
@@ -146,7 +146,7 @@ export const DDCard: React.FC<CardBlockProps> = ({
|
|
|
146
146
|
}) => {
|
|
147
147
|
if (!cards || cards.length === 0) return null
|
|
148
148
|
|
|
149
|
-
const baseClasses = ['card-block', '
|
|
149
|
+
const baseClasses = ['card-block', 'mx-auto', 'grid', 'w-full', 'max-w-7xl', 'grid-cols-1', 'gap-6', 'sm:grid-cols-2', 'lg:grid-cols-3']
|
|
150
150
|
const customBlockClasses = cards
|
|
151
151
|
.map((card) => card.cardBlockClass || '')
|
|
152
152
|
.join(' ')
|
|
@@ -166,7 +166,7 @@ export const DDCard: React.FC<CardBlockProps> = ({
|
|
|
166
166
|
const CardContent = (
|
|
167
167
|
<motion.div
|
|
168
168
|
className={cn(
|
|
169
|
-
'border-0 mt-2 mb-2
|
|
169
|
+
'border-0 mt-2 mb-2 w-full overflow-hidden rounded-lg bg-card shadow-md transition-all duration-300 hover:cursor-pointer hover:scale-[1.02] hover:shadow-lg',
|
|
170
170
|
card.customClass || card.cardBlockClass
|
|
171
171
|
)}
|
|
172
172
|
initial={{ opacity: 0, y: 40 }}
|
|
@@ -216,7 +216,7 @@ export const DDCard: React.FC<CardBlockProps> = ({
|
|
|
216
216
|
<Link
|
|
217
217
|
key={`card-link-${index}`}
|
|
218
218
|
href={linkUrl}
|
|
219
|
-
className="card-block-content block"
|
|
219
|
+
className="card-block-content block w-full"
|
|
220
220
|
style={{ textDecoration: 'none' }}
|
|
221
221
|
>
|
|
222
222
|
<motion.div data-scroll data-scroll-speed={cardScrollSpeed} className="card-wrapper">
|
|
@@ -235,7 +235,7 @@ export const DDCard: React.FC<CardBlockProps> = ({
|
|
|
235
235
|
href={linkUrl}
|
|
236
236
|
target="_blank"
|
|
237
237
|
rel="noopener noreferrer"
|
|
238
|
-
className="card-external-content block"
|
|
238
|
+
className="card-external-content block w-full"
|
|
239
239
|
style={{ textDecoration: 'none' }}
|
|
240
240
|
>
|
|
241
241
|
<motion.div data-scroll data-scroll-speed={cardScrollSpeed} className="card-wrapper">
|
|
@@ -1,140 +1,139 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
import React, { useRef, useState } from 'react'
|
|
3
|
-
import * as LucideIcons from 'lucide-react'
|
|
4
|
-
import { cn } from '@/utilities/ui'
|
|
5
|
-
export type DDCardTemplate01Props = Record<string, any>
|
|
6
|
-
|
|
7
|
-
// ─── SpotlightCard ────────────────────────────────────────────────────────────
|
|
8
|
-
interface SpotlightCardProps {
|
|
9
|
-
children: React.ReactNode
|
|
10
|
-
className?: string
|
|
11
|
-
spotlightColor?: string
|
|
12
|
-
enableTilt?: boolean
|
|
13
|
-
style?: React.CSSProperties
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function SpotlightCard({
|
|
17
|
-
children,
|
|
18
|
-
className,
|
|
19
|
-
spotlightColor = 'rgba(214,211,209,0.08)',
|
|
20
|
-
enableTilt = true,
|
|
21
|
-
style,
|
|
22
|
-
}: SpotlightCardProps) {
|
|
23
|
-
const cardRef = useRef<HTMLDivElement>(null)
|
|
24
|
-
const [pos, setPos] = useState<{ x: number; y: number } | null>(null)
|
|
25
|
-
const [tilt, setTilt] = useState({ rx: 0, ry: 0 })
|
|
26
|
-
|
|
27
|
-
const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
|
|
28
|
-
if (!cardRef.current) return
|
|
29
|
-
const rect = cardRef.current.getBoundingClientRect()
|
|
30
|
-
const x = e.clientX - rect.left
|
|
31
|
-
const y = e.clientY - rect.top
|
|
32
|
-
setPos({ x, y })
|
|
33
|
-
if (enableTilt) {
|
|
34
|
-
const rx = (y / rect.height - 0.5) * -10
|
|
35
|
-
const ry = (x / rect.width - 0.5) * 10
|
|
36
|
-
setTilt({ rx, ry })
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const handleMouseLeave = () => {
|
|
41
|
-
setPos(null)
|
|
42
|
-
setTilt({ rx: 0, ry: 0 })
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<div
|
|
47
|
-
ref={cardRef}
|
|
48
|
-
className={cn('relative overflow-hidden', className)}
|
|
49
|
-
onMouseMove={handleMouseMove}
|
|
50
|
-
onMouseLeave={handleMouseLeave}
|
|
51
|
-
style={
|
|
52
|
-
enableTilt
|
|
53
|
-
? {
|
|
54
|
-
...style,
|
|
55
|
-
transform: `perspective(800px) rotateX(${tilt.rx}deg) rotateY(${tilt.ry}deg)`,
|
|
56
|
-
transition: 'transform 0.1s ease',
|
|
57
|
-
}
|
|
58
|
-
: style
|
|
59
|
-
}
|
|
60
|
-
>
|
|
61
|
-
{pos && (
|
|
62
|
-
<div
|
|
63
|
-
className="pointer-events-none absolute inset-0 z-0 transition-opacity duration-300"
|
|
64
|
-
style={{
|
|
65
|
-
background: `radial-gradient(400px circle at ${pos.x}px ${pos.y}px, ${spotlightColor}, transparent 60%)`,
|
|
66
|
-
}}
|
|
67
|
-
/>
|
|
68
|
-
)}
|
|
69
|
-
<div className="relative z-10">{children}</div>
|
|
70
|
-
</div>
|
|
71
|
-
)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// ─── Dynamic Icon ─────────────────────────────────────────────────────────────
|
|
75
|
-
function DynamicIcon({
|
|
76
|
-
name,
|
|
77
|
-
...props
|
|
78
|
-
}: { name?: string | null } & Omit<LucideIcons.LucideProps, 'name'>) {
|
|
79
|
-
if (!name) return null
|
|
80
|
-
const Icon = (LucideIcons as unknown as Record<string, React.FC<LucideIcons.LucideProps>>)[name]
|
|
81
|
-
if (!Icon) return null
|
|
82
|
-
return <Icon {...props} />
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// ─── Component ────────────────────────────────────────────────────────────────
|
|
86
|
-
export const DDCardTemplate01: React.FC<DDCardTemplate01Props> = ({
|
|
87
|
-
eyebrow,
|
|
88
|
-
headline,
|
|
89
|
-
description,
|
|
90
|
-
iconName = 'ShieldCheck',
|
|
91
|
-
glowColor = 'rgba(214,211,209,0.08)',
|
|
92
|
-
enableTilt = true,
|
|
93
|
-
minHeight = '220px',
|
|
94
|
-
className,
|
|
95
|
-
sectionId,
|
|
96
|
-
customCSS,
|
|
97
|
-
}) => {
|
|
98
|
-
return (
|
|
99
|
-
<div id={sectionId ?? undefined} className="spotlight-card overflow-clip py-8">
|
|
100
|
-
{customCSS && <style dangerouslySetInnerHTML={{ __html: customCSS }} />}
|
|
101
|
-
<SpotlightCard
|
|
102
|
-
spotlightColor={glowColor ?? undefined}
|
|
103
|
-
enableTilt={enableTilt ?? true}
|
|
104
|
-
className={cn(
|
|
105
|
-
'border border-stone-50 dark:border-stone-950 bg-stone-100 dark:bg-stone-900 hover:shadow-2xl transition-all hover:transition-all duration-900 hover:duration-900 flex flex-col justify-between p-6 max-w-[100rem] mx-auto',
|
|
106
|
-
className,
|
|
107
|
-
)}
|
|
108
|
-
style={{ minHeight: minHeight ?? '220px' }}
|
|
109
|
-
>
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
export default DDCardTemplate01
|
|
1
|
+
'use client'
|
|
2
|
+
import React, { useRef, useState } from 'react'
|
|
3
|
+
import * as LucideIcons from 'lucide-react'
|
|
4
|
+
import { cn } from '@/utilities/ui'
|
|
5
|
+
export type DDCardTemplate01Props = Record<string, any>
|
|
6
|
+
|
|
7
|
+
// ─── SpotlightCard ────────────────────────────────────────────────────────────
|
|
8
|
+
interface SpotlightCardProps {
|
|
9
|
+
children: React.ReactNode
|
|
10
|
+
className?: string
|
|
11
|
+
spotlightColor?: string
|
|
12
|
+
enableTilt?: boolean
|
|
13
|
+
style?: React.CSSProperties
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function SpotlightCard({
|
|
17
|
+
children,
|
|
18
|
+
className,
|
|
19
|
+
spotlightColor = 'rgba(214,211,209,0.08)',
|
|
20
|
+
enableTilt = true,
|
|
21
|
+
style,
|
|
22
|
+
}: SpotlightCardProps) {
|
|
23
|
+
const cardRef = useRef<HTMLDivElement>(null)
|
|
24
|
+
const [pos, setPos] = useState<{ x: number; y: number } | null>(null)
|
|
25
|
+
const [tilt, setTilt] = useState({ rx: 0, ry: 0 })
|
|
26
|
+
|
|
27
|
+
const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
|
|
28
|
+
if (!cardRef.current) return
|
|
29
|
+
const rect = cardRef.current.getBoundingClientRect()
|
|
30
|
+
const x = e.clientX - rect.left
|
|
31
|
+
const y = e.clientY - rect.top
|
|
32
|
+
setPos({ x, y })
|
|
33
|
+
if (enableTilt) {
|
|
34
|
+
const rx = (y / rect.height - 0.5) * -10
|
|
35
|
+
const ry = (x / rect.width - 0.5) * 10
|
|
36
|
+
setTilt({ rx, ry })
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const handleMouseLeave = () => {
|
|
41
|
+
setPos(null)
|
|
42
|
+
setTilt({ rx: 0, ry: 0 })
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<div
|
|
47
|
+
ref={cardRef}
|
|
48
|
+
className={cn('relative overflow-hidden', className)}
|
|
49
|
+
onMouseMove={handleMouseMove}
|
|
50
|
+
onMouseLeave={handleMouseLeave}
|
|
51
|
+
style={
|
|
52
|
+
enableTilt
|
|
53
|
+
? {
|
|
54
|
+
...style,
|
|
55
|
+
transform: `perspective(800px) rotateX(${tilt.rx}deg) rotateY(${tilt.ry}deg)`,
|
|
56
|
+
transition: 'transform 0.1s ease',
|
|
57
|
+
}
|
|
58
|
+
: style
|
|
59
|
+
}
|
|
60
|
+
>
|
|
61
|
+
{pos && (
|
|
62
|
+
<div
|
|
63
|
+
className="pointer-events-none absolute inset-0 z-0 transition-opacity duration-300"
|
|
64
|
+
style={{
|
|
65
|
+
background: `radial-gradient(400px circle at ${pos.x}px ${pos.y}px, ${spotlightColor}, transparent 60%)`,
|
|
66
|
+
}}
|
|
67
|
+
/>
|
|
68
|
+
)}
|
|
69
|
+
<div className="relative z-10">{children}</div>
|
|
70
|
+
</div>
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ─── Dynamic Icon ─────────────────────────────────────────────────────────────
|
|
75
|
+
function DynamicIcon({
|
|
76
|
+
name,
|
|
77
|
+
...props
|
|
78
|
+
}: { name?: string | null } & Omit<LucideIcons.LucideProps, 'name'>) {
|
|
79
|
+
if (!name) return null
|
|
80
|
+
const Icon = (LucideIcons as unknown as Record<string, React.FC<LucideIcons.LucideProps>>)[name]
|
|
81
|
+
if (!Icon) return null
|
|
82
|
+
return <Icon {...props} />
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ─── Component ────────────────────────────────────────────────────────────────
|
|
86
|
+
export const DDCardTemplate01: React.FC<DDCardTemplate01Props> = ({
|
|
87
|
+
eyebrow,
|
|
88
|
+
headline,
|
|
89
|
+
description,
|
|
90
|
+
iconName = 'ShieldCheck',
|
|
91
|
+
glowColor = 'rgba(214,211,209,0.08)',
|
|
92
|
+
enableTilt = true,
|
|
93
|
+
minHeight = '220px',
|
|
94
|
+
className,
|
|
95
|
+
sectionId,
|
|
96
|
+
customCSS,
|
|
97
|
+
}) => {
|
|
98
|
+
return (
|
|
99
|
+
<div id={sectionId ?? undefined} className="spotlight-card overflow-clip py-8">
|
|
100
|
+
{customCSS && <style dangerouslySetInnerHTML={{ __html: customCSS }} />}
|
|
101
|
+
<SpotlightCard
|
|
102
|
+
spotlightColor={glowColor ?? undefined}
|
|
103
|
+
enableTilt={enableTilt ?? true}
|
|
104
|
+
className={cn(
|
|
105
|
+
'border border-stone-50 dark:border-stone-950 bg-stone-100 dark:bg-stone-900 hover:shadow-2xl transition-all hover:transition-all duration-900 hover:duration-900 flex flex-col justify-between p-6 max-w-[100rem] mx-auto',
|
|
106
|
+
className,
|
|
107
|
+
)}
|
|
108
|
+
style={{ minHeight: minHeight ?? '220px' }}
|
|
109
|
+
>
|
|
110
|
+
<div className="w-11 h-11 flex items-center justify-center rounded-xl border border-stone-300 text-stone-300 mb-6">
|
|
111
|
+
<DynamicIcon
|
|
112
|
+
className="text-stone-600 dark:text-stone-300"
|
|
113
|
+
name={iconName ?? 'ShieldCheck'}
|
|
114
|
+
size={20}
|
|
115
|
+
/>
|
|
116
|
+
</div>
|
|
117
|
+
<div>
|
|
118
|
+
{eyebrow && (
|
|
119
|
+
<p className="text-xs font-semibold text-stone-600 dark:text-stone-400 tracking-widest uppercase mb-2">
|
|
120
|
+
{eyebrow}
|
|
121
|
+
</p>
|
|
122
|
+
)}
|
|
123
|
+
{headline && (
|
|
124
|
+
<h3 className="text-2xl font-semibold text-stone-900 dark:text-stone-50 mb-3">
|
|
125
|
+
{headline}
|
|
126
|
+
</h3>
|
|
127
|
+
)}
|
|
128
|
+
{description && (
|
|
129
|
+
<p className="text-sm text-stone-600 dark:text-stone-400 leading-relaxed max-w-md">
|
|
130
|
+
{description}
|
|
131
|
+
</p>
|
|
132
|
+
)}
|
|
133
|
+
</div>
|
|
134
|
+
</SpotlightCard>
|
|
135
|
+
</div>
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export default DDCardTemplate01
|