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.
Files changed (148) hide show
  1. package/package.json +1 -1
  2. package/src/installers/patchRenderBlocks.js +1 -1
  3. package/src/registry/validateTemplateManifest.js +2 -1
  4. package/templates/blocks/BannerDD790432/Component.tsx +63 -0
  5. package/templates/blocks/BannerDD790432/config.ts +54 -0
  6. package/templates/blocks/BannerDD790432/manifest.json +80 -0
  7. package/templates/blocks/Button47/Component.tsx +124 -0
  8. package/templates/blocks/Button47/config.ts +75 -0
  9. package/templates/blocks/Button47/link.ts +22 -0
  10. package/templates/blocks/Button47/manifest.json +105 -0
  11. package/templates/blocks/Button47/styles.module.scss +75 -0
  12. package/templates/blocks/DD-Accordion/Component.tsx +55 -36
  13. package/templates/blocks/DD-Accordion/config.ts +71 -59
  14. package/templates/blocks/DD-AnimText/Component.tsx +50 -32
  15. package/templates/blocks/DD-AnimText/config.ts +296 -295
  16. package/templates/blocks/DD-AsideNav/Component.tsx +323 -319
  17. package/templates/blocks/DD-Banner/Component.tsx +54 -51
  18. package/templates/blocks/DD-BookCall/Component.tsx +535 -535
  19. package/templates/blocks/DD-ButtonPop/Component.tsx +118 -117
  20. package/templates/blocks/DD-Card/Component.tsx +4 -4
  21. package/templates/blocks/DD-CardTemplate01/Component.tsx +139 -140
  22. package/templates/blocks/DD-CardsWithVariantV3/Component.tsx +472 -0
  23. package/templates/blocks/DD-CardsWithVariantV3/ElectricBorder/index.tsx +203 -0
  24. package/templates/blocks/DD-CardsWithVariantV3/ElectricBorder/styles.ts +87 -0
  25. package/templates/blocks/DD-CardsWithVariantV3/ElectricBorder/useInjectStyle.ts +39 -0
  26. package/templates/blocks/DD-CardsWithVariantV3/config.ts +326 -0
  27. package/templates/blocks/DD-CardsWithVariantV3/manifest.json +110 -0
  28. package/templates/blocks/DD-Carousel-A/Component.tsx +251 -249
  29. package/templates/blocks/DD-Carousel-B/Component.tsx +405 -403
  30. package/templates/blocks/DD-ComparisonTable/Component.tsx +255 -256
  31. package/templates/blocks/DD-Contact/Component.tsx +433 -435
  32. package/templates/blocks/DD-Counter/Component.tsx +11 -6
  33. package/templates/blocks/DD-DeliCard/Component.tsx +303 -0
  34. package/templates/blocks/DD-DeliCard/config.ts +186 -0
  35. package/templates/blocks/DD-DeliCard/manifest.json +94 -0
  36. package/templates/blocks/DD-FeatCat/Component.tsx +302 -302
  37. package/templates/blocks/DD-FeatProd/CircularGallery.tsx +1179 -0
  38. package/templates/blocks/DD-FeatProd/Component.tsx +484 -0
  39. package/templates/blocks/DD-FeatProd/config.ts +173 -0
  40. package/templates/blocks/DD-FeatProd/manifest.json +93 -0
  41. package/templates/blocks/DD-FeatServ/Component.tsx +607 -0
  42. package/templates/blocks/DD-FeatServ/config.ts +213 -0
  43. package/templates/blocks/DD-FeatServ/manifest.json +113 -0
  44. package/templates/blocks/DD-FeatStrip/Component.tsx +584 -585
  45. package/templates/blocks/DD-FluidBtn/ButtonsEyeCatching.tsx +627 -628
  46. package/templates/blocks/DD-FluidBtn/Component.tsx +46 -43
  47. package/templates/blocks/DD-GooeyInfo/Component.tsx +150 -149
  48. package/templates/blocks/DD-GooeyInfo/config.ts +136 -135
  49. package/templates/blocks/DD-Hero/Component.tsx +296 -297
  50. package/templates/blocks/DD-HeroPlas/Component.tsx +50 -0
  51. package/templates/blocks/DD-HeroPlas/ThreeScene.tsx +109 -0
  52. package/templates/blocks/DD-HeroPlas/config.ts +33 -0
  53. package/templates/blocks/DD-HeroPlas/manifest.json +88 -0
  54. package/templates/blocks/DD-HorizontalScroll/Component.tsx +937 -936
  55. package/templates/blocks/DD-Icon/Component.tsx +46 -81
  56. package/templates/blocks/DD-IconButton/Component.tsx +13 -20
  57. package/templates/blocks/DD-IdTag/Component.tsx +22 -21
  58. package/templates/blocks/DD-LineAnim/Component.tsx +42 -36
  59. package/templates/blocks/DD-LogoMarq/Component.tsx +38 -48
  60. package/templates/blocks/DD-Lottie/Component.tsx +11 -3
  61. package/templates/blocks/DD-MasonaryMedia/Component.tsx +544 -545
  62. package/templates/blocks/DD-MasonaryMedia/config.ts +389 -389
  63. package/templates/blocks/DD-Masonry/Component.tsx +654 -644
  64. package/templates/blocks/DD-Masonry/config.ts +475 -475
  65. package/templates/blocks/DD-MaterialSwatches/Component.tsx +85 -0
  66. package/templates/blocks/DD-MaterialSwatches/config.ts +232 -0
  67. package/templates/blocks/DD-MaterialSwatches/manifest.json +84 -0
  68. package/templates/blocks/DD-MaterialSwatches/material.ts +107 -0
  69. package/templates/blocks/DD-NineCanvas/Component.tsx +129 -0
  70. package/templates/blocks/DD-NineCanvas/RenderBlocks.tsx +244 -0
  71. package/templates/blocks/DD-NineCanvas/allowedCanvasBlocks.ts +6 -0
  72. package/templates/blocks/DD-NineCanvas/blockComponents.tsx +8 -0
  73. package/templates/blocks/DD-NineCanvas/canvas/CanvasGrid.tsx +316 -0
  74. package/templates/blocks/DD-NineCanvas/canvas/RadialNav.tsx +432 -0
  75. package/templates/blocks/DD-NineCanvas/canvas/canvas-panels.css +889 -0
  76. package/templates/blocks/DD-NineCanvas/canvas/icons/custom-icons.tsx +364 -0
  77. package/templates/blocks/DD-NineCanvas/config.ts +61 -0
  78. package/templates/blocks/DD-NineCanvas/manifest.json +165 -0
  79. package/templates/blocks/DD-NineCanvas/styles.scss +152 -0
  80. package/templates/blocks/DD-NineCanvas/tooltip/get-strict-context.tsx +26 -0
  81. package/templates/blocks/DD-NineCanvas/tooltip/primitives.tsx +178 -0
  82. package/templates/blocks/DD-NineCanvas/tooltip/tooltip.tsx +71 -0
  83. package/templates/blocks/DD-NineCanvas/tooltip/use-controlled-state.tsx +33 -0
  84. package/templates/blocks/DD-NineCanvas/utilities/FadeOnScroll.tsx +68 -0
  85. package/templates/blocks/DD-NineCanvas/utilities/ParallaxWrapper.tsx +157 -0
  86. package/templates/blocks/DD-NineCanvas/utilities/renderCustomCSS.ts +5 -0
  87. package/templates/blocks/DD-NineCanvas/utilities/webglCleanup.ts +27 -0
  88. package/templates/blocks/DD-PayloadAIAssistant/Component.tsx +78 -0
  89. package/templates/blocks/DD-PayloadAIAssistant/DustedBot.tsx +590 -0
  90. package/templates/blocks/DD-PayloadAIAssistant/config.ts +37 -0
  91. package/templates/blocks/DD-PayloadAIAssistant/demo.css +125 -0
  92. package/templates/blocks/DD-PayloadAIAssistant/manifest.json +93 -0
  93. package/templates/blocks/DD-PayloadAIAssistant/source-defaults.ts +17 -0
  94. package/templates/blocks/DD-PayloadAIAssistant/styles.ts +306 -0
  95. package/templates/blocks/DD-Pricing/Component.tsx +2 -3
  96. package/templates/blocks/DD-Pricing/config.ts +215 -215
  97. package/templates/blocks/DD-Process/Component.tsx +2 -2
  98. package/templates/blocks/DD-ProjHeader/Component.tsx +93 -91
  99. package/templates/blocks/DD-ProjSlider/Component.tsx +1 -1
  100. package/templates/blocks/DD-Section/Component.tsx +265 -266
  101. package/templates/blocks/DD-Separator/Component.tsx +66 -66
  102. package/templates/blocks/DD-Services/Component.tsx +176 -176
  103. package/templates/blocks/DD-ShowcaseGrid/Component.tsx +306 -307
  104. package/templates/blocks/DD-Slider-A/Component.tsx +2 -2
  105. package/templates/blocks/DD-StackCards/Component.tsx +172 -171
  106. package/templates/blocks/DD-Team/Component.tsx +247 -247
  107. package/templates/blocks/DD-TeamCards/Component.tsx +251 -251
  108. package/templates/blocks/DD-TechStack/Component.tsx +173 -174
  109. package/templates/blocks/DD-TestMarq/Component.tsx +158 -132
  110. package/templates/blocks/DD-Testim/Component.tsx +247 -247
  111. package/templates/blocks/DD-Testim2/Component.tsx +265 -256
  112. package/templates/blocks/DD-Testimonials/Component.tsx +139 -139
  113. package/templates/blocks/DD-Thanks/Component.tsx +1 -1
  114. package/templates/blocks/DD-Work/Component.tsx +318 -318
  115. package/templates/blocks/DD-Work-B/Component.tsx +294 -294
  116. package/templates/blocks/DDHG-CTASection2/Component.tsx +183 -184
  117. package/templates/blocks/DDHG-HighlightArc/Component.tsx +6 -3
  118. package/templates/blocks/DDHG-LogoMarquee/Component.tsx +45 -8
  119. package/templates/blocks/DDHG-NavCodeGrid/Component.tsx +1 -3
  120. package/templates/blocks/DDHG-ServiceDetails/ServiceDetailCard.tsx +9 -22
  121. package/templates/blocks/DDHG-ServiceHero/Component.tsx +10 -10
  122. package/templates/blocks/DDHG-TeamCards/Component.tsx +6 -35
  123. package/templates/blocks/Form/Checkbox/index.tsx +45 -0
  124. package/templates/blocks/Form/Component.tsx +163 -0
  125. package/templates/blocks/Form/Country/index.tsx +65 -0
  126. package/templates/blocks/Form/Country/options.ts +982 -0
  127. package/templates/blocks/Form/Email/index.tsx +38 -0
  128. package/templates/blocks/Form/Error/index.tsx +15 -0
  129. package/templates/blocks/Form/Message/index.tsx +13 -0
  130. package/templates/blocks/Form/Number/index.tsx +36 -0
  131. package/templates/blocks/Form/Select/index.tsx +63 -0
  132. package/templates/blocks/Form/State/index.tsx +64 -0
  133. package/templates/blocks/Form/State/options.ts +52 -0
  134. package/templates/blocks/Form/Text/index.tsx +32 -0
  135. package/templates/blocks/Form/Textarea/index.tsx +40 -0
  136. package/templates/blocks/Form/Width/index.tsx +13 -0
  137. package/templates/blocks/Form/config.ts +51 -0
  138. package/templates/blocks/Form/fields.tsx +21 -0
  139. package/templates/blocks/Form/manifest.json +168 -0
  140. package/templates/blocks/MediaBlock/Component.tsx +67 -0
  141. package/templates/blocks/MediaBlock/config.ts +14 -0
  142. package/templates/blocks/MediaBlock/manifest.json +92 -0
  143. package/templates/blocks/TransitionsDustedShowcase/Component.tsx +9 -0
  144. package/templates/blocks/TransitionsDustedShowcase/config.ts +13 -0
  145. package/templates/blocks/TransitionsDustedShowcase/manifest.json +80 -0
  146. package/templates/blocks/rawHtml/Component.tsx +25 -0
  147. package/templates/blocks/rawHtml/config.ts +56 -0
  148. 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 items-center justify-center mx-4 p-1 bgTransBlur-light rounded-lg ">
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
- className="relative right-0 ml-auto flex justify-end text-sm text-gray-500 transition-colors duration-150 hover:text-gray-700"
99
- style={{ background: 'none', border: 'none', cursor: 'pointer' }}
100
- >
101
- Close
102
- </button>
103
- <RichText
104
- data={richTextData}
105
- className="pop-modal-richtext"
106
- enableGutter={false}
107
- />
108
- <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" />
109
- </div>
110
- </div>
111
- </motion.div>
112
- </>
113
- ))}
114
- </AnimatePresence>
115
- </div>
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', 'flex', 'flex-wrap', 'justify-center', 'gap-0']
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 shadow-md bg-card hover:cursor-pointer overflow-hidden rounded-lg transition-all duration-300 hover:scale-[1.02] hover:shadow-lg w-full max-w-sm mx-auto',
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
- #BlockName-DDCardTemplate01
111
- <div className="w-11 h-11 flex items-center justify-center rounded-xl border border-stone-300 text-stone-300 mb-6">
112
- <DynamicIcon
113
- className="text-stone-600 dark:text-stone-300"
114
- name={iconName ?? 'ShieldCheck'}
115
- size={20}
116
- />
117
- </div>
118
- <div>
119
- {eyebrow && (
120
- <p className="text-xs font-semibold text-stone-600 dark:text-stone-400 tracking-widest uppercase mb-2">
121
- {eyebrow}
122
- </p>
123
- )}
124
- {headline && (
125
- <h3 className="text-2xl font-semibold text-stone-900 dark:text-stone-50 mb-3">
126
- {headline}
127
- </h3>
128
- )}
129
- {description && (
130
- <p className="text-sm text-stone-600 dark:text-stone-400 leading-relaxed max-w-md">
131
- {description}
132
- </p>
133
- )}
134
- </div>
135
- </SpotlightCard>
136
- </div>
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