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
@@ -4,13 +4,13 @@ import React from 'react'
4
4
  import { motion } from 'framer-motion'
5
5
  import Link from 'next/link'
6
6
  import { usePathname } from 'next/navigation'
7
+ import * as LucideIcons from 'lucide-react'
7
8
 
8
9
  import { cn } from '@/utilities/ui'
9
- import { Media } from '@/components/Media'
10
10
  import { smoothScrollTo, isAnchorLink } from '@/utilities/smoothScroll'
11
11
 
12
12
  export type IconItem = {
13
- icon?: any
13
+ icon?: string | null
14
14
  iconSize?: string
15
15
  customIconSize?: string
16
16
  iconClassName?: string
@@ -19,7 +19,6 @@ export type IconItem = {
19
19
  flexDirection?: 'flex-col' | 'flex-col-reverse' | 'flex-row' | 'flex-row-reverse'
20
20
  flexGap?: string
21
21
  link?: string
22
- imgCustomStyle?: Record<string, any>
23
22
  }
24
23
 
25
24
  export type CustomIconBlockProps = {
@@ -28,19 +27,29 @@ export type CustomIconBlockProps = {
28
27
  icons?: IconItem[]
29
28
  className?: string
30
29
  iconGridClass?: string
31
- imgCustomStyle?: React.CSSProperties
32
30
  priority?: boolean
33
31
  }
34
32
 
33
+ function DynamicIcon({
34
+ name,
35
+ size = 36,
36
+ ...props
37
+ }: { name?: string | null } & Omit<LucideIcons.LucideProps, 'name'>) {
38
+ if (!name) return null
39
+ const Icon = (LucideIcons as unknown as Record<string, React.FC<LucideIcons.LucideProps>>)[name]
40
+ if (!Icon) return null
41
+ return <Icon size={size} {...props} />
42
+ }
43
+
35
44
  const containerVariants = {
36
45
  hidden: { opacity: 0 },
37
46
  visible: {
38
47
  opacity: 1,
39
48
  transition: {
40
49
  staggerChildren: 0.15,
41
- delayChildren: 0.1
42
- }
43
- }
50
+ delayChildren: 0.1,
51
+ },
52
+ },
44
53
  }
45
54
 
46
55
  const itemVariants = {
@@ -51,17 +60,15 @@ const itemVariants = {
51
60
  scale: 1,
52
61
  transition: {
53
62
  duration: 0.4,
54
- ease: [0.4, 0, 0.2, 1] as const
55
- }
56
- }
63
+ ease: [0.4, 0, 0.2, 1] as const,
64
+ },
65
+ },
57
66
  }
58
67
 
59
68
  export const DDIcon: React.FC<CustomIconBlockProps> = ({
60
69
  blockName,
61
70
  icons = [],
62
71
  iconGridClass,
63
- imgCustomStyle: blockImgStyle,
64
- priority = false
65
72
  }) => {
66
73
  const pathname = usePathname()
67
74
  const hasCustomGridClass = iconGridClass && iconGridClass.trim().length > 0
@@ -103,30 +110,11 @@ export const DDIcon: React.FC<CustomIconBlockProps> = ({
103
110
  smoothScrollTo(target, {
104
111
  duration: 1,
105
112
  offsetY: 80,
106
- ease: 'power2.out'
113
+ ease: 'power2.out',
107
114
  })
108
115
  }
109
116
  }
110
117
 
111
- const extractSizeFromClass = (sizeClass: string) => {
112
- const widthMatch = sizeClass.match(/w-(\d+)/)
113
- const heightMatch = sizeClass.match(/h-(\d+)/)
114
-
115
- if (widthMatch && heightMatch) {
116
- const width = parseInt(widthMatch[1], 10) * 4
117
- const height = parseInt(heightMatch[1], 10) * 4
118
-
119
- return {
120
- width: `${width}px`,
121
- height: `${height}px`,
122
- maxWidth: `${width}px`,
123
- maxHeight: `${height}px`
124
- }
125
- }
126
-
127
- return {}
128
- }
129
-
130
118
  return (
131
119
  <motion.div
132
120
  initial="hidden"
@@ -138,58 +126,35 @@ export const DDIcon: React.FC<CustomIconBlockProps> = ({
138
126
  className={cn(
139
127
  'custom-icon-block',
140
128
  !hasCustomGridClass && 'grid grid-cols-3 gap-6 text-center md:grid-cols-4 lg:grid-cols-5',
141
- hasCustomGridClass && iconGridClass
129
+ hasCustomGridClass && iconGridClass,
142
130
  )}
143
131
  >
144
132
  {icons.map((iconItem, index) => {
145
133
  if (!iconItem) return null
146
134
 
147
- const iconKey = `icon-${index}${iconItem.icon?.filename ? `-${iconItem.icon.filename}` : ''}`
148
-
149
- if (!iconItem.icon) {
150
- return (
151
- <motion.div
152
- key={iconKey}
153
- variants={itemVariants}
154
- className="flex flex-col items-center"
155
- >
156
- <div className="flex h-16 w-16 items-center justify-center border-2 border-gray-300 bg-gray-100 p-0 text-xs text-gray-400">
157
- <span>No Icon</span>
158
- </div>
159
-
160
- {iconItem.label && (
161
- <span className="custom-icon-label mt-2 text-center text-xs leading-tight text-gray-600">
162
- {iconItem.label}
163
- </span>
164
- )}
165
- </motion.div>
166
- )
167
- }
168
-
169
- const iconSizeClass =
170
- iconItem.iconSize === 'custom'
171
- ? iconItem.customIconSize || 'h-16 w-16'
172
- : iconItem.iconSize || 'h-16 w-16'
173
-
174
- const sizeStyles = extractSizeFromClass(iconSizeClass)
135
+ const iconKey = `icon-${index}`
136
+ const defaultIcons = [
137
+ 'Code2',
138
+ 'Database',
139
+ 'PanelsTopLeft',
140
+ 'Braces',
141
+ 'Workflow',
142
+ 'GitBranch',
143
+ ]
144
+ const iconName =
145
+ typeof iconItem.icon === 'string'
146
+ ? iconItem.icon
147
+ : defaultIcons[index % defaultIcons.length]
175
148
 
176
149
  const mediaContent = (
177
- <Media
178
- priority={priority ?? false}
179
- resource={iconItem.icon}
150
+ <div
180
151
  className={cn(
181
- 'custom-icon-media flex items-center justify-center p-0 transition-transform',
182
- '[&>picture]:!mb-0 [&>picture]:!mt-0 [&>picture]:flex [&>picture]:h-full [&>picture]:w-full [&>picture]:items-center [&>picture]:justify-center',
183
- '[&>picture>img]:block [&>picture>img]:h-full [&>picture>img]:w-full [&>picture>img]:object-contain',
184
- '[&_img]:block [&_img]:h-full [&_img]:w-full [&_img]:object-contain',
185
- iconSizeClass,
186
- iconItem.iconClassName
152
+ 'custom-icon-media flex h-20 w-20 items-center justify-center rounded-2xl border border-[#2A2A30] bg-linear-to-b from-[#1a1a1f] to-[#0f0f12] p-4 invert-[1] transition-all duration-300 hover:scale-105 hover:shadow-[0_0_30px_rgba(140,138,132,0.15)] dark:invert-[0]',
153
+ iconItem.iconClassName,
187
154
  )}
188
- imgClassName={cn(
189
- 'block h-full w-full object-contain transition-all duration-300',
190
- iconItem.iconClassName
191
- )}
192
- />
155
+ >
156
+ <DynamicIcon className="text-[#9A9790]" name={iconName} size={36} />
157
+ </div>
193
158
  )
194
159
 
195
160
  const wrapperFlexDirection = iconItem.flexDirection || 'flex-col'
@@ -217,7 +182,7 @@ export const DDIcon: React.FC<CustomIconBlockProps> = ({
217
182
  className={cn(
218
183
  'custom-icon-item group flex items-center',
219
184
  wrapperFlexDirection,
220
- wrapperGap
185
+ wrapperGap,
221
186
  )}
222
187
  >
223
188
  {iconItem.link && iconItem.link.trim() ? (
@@ -235,9 +200,9 @@ export const DDIcon: React.FC<CustomIconBlockProps> = ({
235
200
  <a
236
201
  href={href}
237
202
  className={cn(
238
- 'custom-icon-block-link custom-icon-link flex cursor-pointer items-center brightness-100 transition-all duration-300 ease-in-out hover:brightness-110',
203
+ 'custom-icon-block-link custom-icon-link flex cursor-pointer items-center brightness-100 no-underline transition-all duration-300 ease-in-out hover:brightness-110 hover:no-underline',
239
204
  wrapperFlexDirection,
240
- wrapperGap
205
+ wrapperGap,
241
206
  )}
242
207
  onClick={(e) => handleClick(href, e)}
243
208
  aria-label={iconItem.label || 'Navigate to section'}
@@ -254,9 +219,9 @@ export const DDIcon: React.FC<CustomIconBlockProps> = ({
254
219
  <Link
255
220
  href={href}
256
221
  className={cn(
257
- 'custom-icon-block-link custom-icon-link flex items-center brightness-100 transition-all duration-300 ease-in-out hover:brightness-110',
222
+ 'custom-icon-block-link custom-icon-link flex items-center brightness-100 no-underline transition-all duration-300 ease-in-out hover:brightness-110 hover:no-underline',
258
223
  wrapperFlexDirection,
259
- wrapperGap
224
+ wrapperGap,
260
225
  )}
261
226
  target={target}
262
227
  rel={rel}
@@ -271,7 +236,7 @@ export const DDIcon: React.FC<CustomIconBlockProps> = ({
271
236
  className={cn(
272
237
  'custom-icon-wrapper flex items-center brightness-110 text-white/80 dark:text-stone-200/80',
273
238
  wrapperFlexDirection,
274
- wrapperGap
239
+ wrapperGap,
275
240
  )}
276
241
  >
277
242
  {iconContent}
@@ -4,7 +4,7 @@ import React from 'react'
4
4
  import { cn } from '@/utilities/ui'
5
5
  import Link from 'next/link'
6
6
  import * as LucideIcons from 'lucide-react'
7
- import type { Page, Post } from '@/payload-types'
7
+ import type { Page } from '@/payload-types'
8
8
  import { ShareButton } from '@/components/ui/ShareButton'
9
9
  import { smoothScrollTo, isAnchorLink } from '@/utilities/smoothScroll'
10
10
  import { usePathname, useRouter } from 'next/navigation'
@@ -30,9 +30,7 @@ type ButtonStyle =
30
30
  type ButtonSize = 'small' | 'medium' | 'large'
31
31
  type IconPosition = 'before' | 'after'
32
32
 
33
- type LinkReference =
34
- | { relationTo: 'pages'; value: number | Page }
35
- | { relationTo: 'posts'; value: number | Post }
33
+ type LinkReference = { relationTo: 'pages'; value: number | Page }
36
34
 
37
35
  export type LinkType = {
38
36
  type?: 'reference' | 'custom' | null
@@ -175,12 +173,7 @@ export const DDIconButton: React.FC<ButtonWithIconProps> = ({
175
173
  onToggle?.()
176
174
  }
177
175
 
178
- const getDocumentSlug = (doc: Page | Post | number): string | null => {
179
- if (typeof doc === 'number') return null
180
- return (doc as any)?.slug || null
181
- }
182
-
183
- const getPageURLFromDoc = (doc: Page | number): string | null => {
176
+ const getPageURLFromDoc = (doc: Page | number): string | null => {
184
177
  if (typeof doc === 'number') return null
185
178
 
186
179
  const anyDoc = doc as any
@@ -231,12 +224,6 @@ export const DDIconButton: React.FC<ButtonWithIconProps> = ({
231
224
  if (relationTo === 'pages') {
232
225
  const pageHref = getPageURLFromDoc(value as Page | number)
233
226
  if (pageHref) href = pageHref
234
- } else if (relationTo === 'posts') {
235
- const slug = getDocumentSlug(value as Post | number)
236
- if (slug) href = `/thoughts/${slug}`
237
- } else {
238
- const slug = getDocumentSlug(value as any)
239
- if (slug) href = `/${relationTo}/${slug}`
240
227
  }
241
228
 
242
229
  target = link.newTab ? '_blank' : undefined
@@ -267,7 +254,7 @@ export const DDIconButton: React.FC<ButtonWithIconProps> = ({
267
254
  'bg-transparent text-[var(--text)] !border-0 max-h-fit transition-all duration-300 hover:text-[var(--accent)] hover:font-medium',
268
255
 
269
256
  destructive:
270
- "relative z-0 overflow-hidden bg-[var(--error)] !text-white rounded-2xl squircle border border-[outset] border-[var(--color-alt2)] brightness-100 max-h-fit shadow-[inset_0_0_20px_2px_rgb(73_17_10_/_90%),var(--shadow-md)] transition-all duration-300 before:content-[''] before:absolute before:inset-0 before:-z-10 before:bg-[url('/assets/svg/lines.svg')] before:bg-[length:10px_10px] before:bg-repeat before:opacity-100 before:pointer-events-none hover:!text-white hover:shadow-[inset_0_0_30px_2px_rgb(178_20_2),var(--shadow-xl)] hover:brightness-110",
257
+ "relative z-0 overflow-hidden bg-[var(--error)] !text-white rounded-2xl squircle border border-[outset] border-[var(--color-alt2)] brightness-100 max-h-fit shadow-[inset_0_0_20px_2px_rgb(73_17_10_/_90%),var(--shadow-md)] transition-all duration-300 before:content-[''] before:absolute before:inset-0 before:-z-10 before:bg-lines before:bg-[length:10px_10px] before:bg-repeat before:opacity-100 before:pointer-events-none hover:!text-white hover:shadow-[inset_0_0_30px_2px_rgb(178_20_2),var(--shadow-xl)] hover:brightness-110",
271
258
 
272
259
  v1: 'border-[0.5px] rounded-sm bg-transparent duration-200 bg-blur shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] active:shadow-none border-stone-800 text-zinc-800 dark:border-stone-600 dark:shadow-[3px_3px_0px_0px_rgba(255,255,255,0.7)] active:dark:shadow-none dark:text-zinc-50 dark:bg-zinc-950 px-3 py-1',
273
260
  v2: 'group relative justify-center rounded-sm shadow-md overflow-hidden ease-in-out hover:scale-100 hover:shadow-lg text-zinc-50 bg-gradient-to-tr from-zinc-900 to-zinc-700 hover:shadow-zinc-500/30 dark:text-stone-900 dark:bg-gradient-to-tr dark:from-zinc-50 dark:to-zinc-100 dark:hover:shadow-zinc-700/30 px-3 py-1',
@@ -444,12 +431,18 @@ export const DDIconButton: React.FC<ButtonWithIconProps> = ({
444
431
  {displayMode === 'share' ? (
445
432
  content
446
433
  ) : href && href !== '#' ? (
447
- <Link href={href} target={target} rel={rel} onClick={(e) => handleClick(href, e)}>
434
+ <Link
435
+ href={href}
436
+ target={target}
437
+ rel={rel}
438
+ className="!no-underline hover:!no-underline"
439
+ onClick={(e) => handleClick(href, e)}
440
+ >
448
441
  {content}
449
442
  </Link>
450
443
  ) : (
451
444
  content
452
445
  )}
453
446
  </div>
454
- )
455
- }
447
+ )
448
+ }
@@ -1,21 +1,22 @@
1
- import React from 'react'
2
-
3
- type Props = {
4
- idTag: string
5
- offset?: number
6
- }
7
-
8
- export const DDIdTag: React.FC<Props> = ({ idTag, offset = 0 }) => {
9
- return (
10
- <div
11
- id={idTag}
12
- style={{
13
- position: 'relative',
14
- top: `-${offset}px`,
15
- height: 0,
16
- visibility: 'hidden',
17
- }}
18
- aria-hidden="true"
19
- />
20
- )
21
- }
1
+ import React from 'react'
2
+
3
+ type Props = {
4
+ idTag?: string
5
+ id?: string
6
+ offset?: number
7
+ }
8
+
9
+ export const DDIdTag: React.FC<Props> = ({ idTag, id, offset = 0 }) => {
10
+ return (
11
+ <div
12
+ id={idTag || id}
13
+ style={{
14
+ position: 'relative',
15
+ top: `-${offset}px`,
16
+ height: 0,
17
+ visibility: 'hidden',
18
+ }}
19
+ aria-hidden="true"
20
+ />
21
+ )
22
+ }
@@ -1,36 +1,42 @@
1
- 'use client'
2
- import React from 'react'
3
- import LineAnim from '@/components/ui/anims/LineAnims'
4
-
5
- export interface LineAnimBlockProps {
6
- className?: string
7
- direction?: 'left-to-right' | 'right-to-left' | 'top-to-bottom' | 'bottom-to-top'
8
- trigger?: 'scroll' | 'immediate'
9
- duration?: number
10
- delay?: number
11
- customClass?: string
12
- blockType?: string
13
- id?: string
14
- }
15
-
16
- export const DDLineAnim: React.FC<LineAnimBlockProps> = ({
17
- className = '',
18
- direction = 'left-to-right',
19
- trigger = 'scroll',
20
- duration = 1,
21
- delay = 0,
22
- customClass = '',
23
- id
24
- }) => {
25
- return (
26
- <div className={`line-anim-block overflow-hidden ${className} ${customClass}`} id={id}>
27
- <LineAnim
28
- direction={direction}
29
- trigger={trigger}
30
- duration={duration}
31
- delay={delay}
32
- className="bg-gradient-to-r from-gray-400 to-gray-600"
33
- />
34
- </div>
35
- )
36
- }
1
+ 'use client'
2
+ import React from 'react'
3
+ import LineAnim from '@/components/ui/anims/LineAnims'
4
+
5
+ export interface LineAnimBlockProps {
6
+ className?: string
7
+ direction?: 'left-to-right' | 'right-to-left' | 'top-to-bottom' | 'bottom-to-top'
8
+ trigger?: 'scroll' | 'immediate'
9
+ duration?: number
10
+ delay?: number
11
+ customClass?: string
12
+ blockType?: string
13
+ id?: string
14
+ }
15
+
16
+ export const DDLineAnim: React.FC<LineAnimBlockProps> = ({
17
+ className = '',
18
+ direction = 'left-to-right',
19
+ trigger = 'scroll',
20
+ duration = 1,
21
+ delay = 0,
22
+ customClass = '',
23
+ id
24
+ }) => {
25
+ return (
26
+ <div
27
+ className={`line-anim-block flex min-h-[55vh] items-center overflow-hidden rounded-md bg-zinc-100 px-8 dark:bg-zinc-900 ${className} ${customClass}`}
28
+ id={id}
29
+ >
30
+ <span className="mr-6 text-sm font-medium uppercase tracking-wide text-zinc-600 dark:text-zinc-300">
31
+ Line animation
32
+ </span>
33
+ <LineAnim
34
+ direction={direction}
35
+ trigger={trigger}
36
+ duration={duration}
37
+ delay={delay}
38
+ className="h-2 w-full rounded-full bg-gradient-to-r from-gray-400 via-gray-700 to-gray-400"
39
+ />
40
+ </div>
41
+ )
42
+ }
@@ -1,16 +1,10 @@
1
1
  'use client'
2
2
 
3
- import React, { useMemo, useState } from 'react'
4
- import Image from 'next/image'
3
+ import React, { useMemo } from 'react'
4
+ import * as LucideIcons from 'lucide-react'
5
5
  import { cn } from '@/utilities/ui'
6
6
  import { Separator } from '@/components/ui/separator'
7
7
 
8
- const placeholderBlur =
9
- 'data:image/svg+xml;base64,' +
10
- btoa(
11
- '<svg width="160" height="80" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="transparent"/></svg>'
12
- )
13
-
14
8
  export type LogoMarqueeProps = {
15
9
  logos: {
16
10
  image?: {
@@ -20,6 +14,9 @@ export type LogoMarqueeProps = {
20
14
  imageClass?: string
21
15
  imageStyle?: React.CSSProperties
22
16
  imageAltClass?: string
17
+ icon?: string | null
18
+ label?: string | null
19
+ showLabel?: boolean | null
23
20
  }[]
24
21
  speed?: number
25
22
  spacing?: number
@@ -30,29 +27,15 @@ export type LogoMarqueeProps = {
30
27
  customCSS?: string
31
28
  }
32
29
 
33
- const LogoImage: React.FC<{
34
- src: string
35
- alt?: string
36
- customClass?: string
37
- imageStyle?: React.CSSProperties
38
- }> = ({ src, alt, customClass, imageStyle }) => {
39
- const [imageError, setImageError] = useState(false)
40
- const imageSrc = !src || imageError ? placeholderBlur : src
41
-
42
- return (
43
- <Image
44
- src={imageSrc}
45
- alt={alt || 'Logo'}
46
- width={160}
47
- height={72}
48
- priority
49
- className={cn('h-14 w-auto max-w-[140px] object-contain', customClass)}
50
- style={imageStyle}
51
- onError={() => setImageError(true)}
52
- placeholder="blur"
53
- blurDataURL={placeholderBlur}
54
- />
55
- )
30
+ function DynamicIcon({
31
+ name,
32
+ size = 36,
33
+ ...props
34
+ }: { name?: string | null } & Omit<LucideIcons.LucideProps, 'name'>) {
35
+ if (!name) return null
36
+ const Icon = (LucideIcons as unknown as Record<string, React.FC<LucideIcons.LucideProps>>)[name]
37
+ if (!Icon) return null
38
+ return <Icon size={size} {...props} />
56
39
  }
57
40
 
58
41
  export const DDLogoMarq: React.FC<LogoMarqueeProps> = ({
@@ -63,7 +46,7 @@ export const DDLogoMarq: React.FC<LogoMarqueeProps> = ({
63
46
  showBottomDivider = false,
64
47
  containerClass = 'py-8',
65
48
  customCSS,
66
- itemWidth = 190
49
+ itemWidth = 190,
67
50
  }) => {
68
51
  const validLogos = logos || []
69
52
  const marqueeItems = useMemo(() => {
@@ -75,11 +58,12 @@ export const DDLogoMarq: React.FC<LogoMarqueeProps> = ({
75
58
  if (marqueeItems.length === 0) return null
76
59
 
77
60
  const gap = Math.max(16, spacing)
61
+ const defaultIcons = ['Code2', 'Database', 'PanelsTopLeft', 'Braces', 'Workflow', 'GitBranch']
78
62
 
79
63
  const LogoTile = ({
80
64
  logo,
81
65
  index,
82
- duplicate = false
66
+ duplicate = false,
83
67
  }: {
84
68
  logo: (typeof marqueeItems)[number]
85
69
  index: number
@@ -87,18 +71,24 @@ export const DDLogoMarq: React.FC<LogoMarqueeProps> = ({
87
71
  }) => (
88
72
  <div
89
73
  key={(duplicate ? 'duplicate' : 'logo') + '-' + index}
90
- className="marquee-logo-tile flex shrink-0 flex-col items-center justify-center rounded-2xl border border-white/10 bg-white/[0.035] px-5 py-4 shadow-[inset_0_1px_0_rgba(255,255,255,0.08)] backdrop-blur-sm"
74
+ className="marquee-logo-tile flex shrink-0 flex-col items-center justify-center"
91
75
  style={{ width: itemWidth }}
92
76
  >
93
- <LogoImage
94
- src={logo.image?.url || placeholderBlur}
95
- alt={logo.image?.alt}
96
- customClass={logo.imageClass}
97
- imageStyle={logo.imageStyle}
98
- />
99
- {logo.image?.alt && (
100
- <p className={cn('mt-3 text-center text-sm font-medium leading-tight text-white/80', logo.imageAltClass)}>
101
- {logo.image.alt}
77
+ <div className="flex h-20 w-20 items-center justify-center rounded-2xl border border-[#2A2A30] bg-linear-to-b from-[#1a1a1f] to-[#0f0f12] p-4 invert-[1] transition-all duration-300 hover:scale-105 hover:shadow-[0_0_30px_rgba(140,138,132,0.15)] dark:invert-[0]">
78
+ <DynamicIcon
79
+ className="text-[#9A9790]"
80
+ name={logo.icon || defaultIcons[index % defaultIcons.length]}
81
+ size={36}
82
+ />
83
+ </div>
84
+ {logo.showLabel !== false && (logo.label || logo.image?.alt) && (
85
+ <p
86
+ className={cn(
87
+ 'mt-2 text-center text-sm leading-tight text-[#9A9790]',
88
+ logo.imageAltClass,
89
+ )}
90
+ >
91
+ {logo.label || logo.image?.alt}
102
92
  </p>
103
93
  )}
104
94
  </div>
@@ -109,11 +99,11 @@ export const DDLogoMarq: React.FC<LogoMarqueeProps> = ({
109
99
  {showTopDivider && <Separator gradient className="border-seperator" />}
110
100
  <section className="logo-marquee-block mx-auto flex min-h-[280px] w-full max-w-6xl items-center overflow-hidden">
111
101
  {customCSS && <style dangerouslySetInnerHTML={{ __html: customCSS }} />}
112
- <style>{
113
- '@keyframes dd-logo-marquee { from { transform: translate3d(0, 0, 0); } to { transform: translate3d(-50%, 0, 0); } }' +
114
- '.logo-marquee-track { animation: dd-logo-marquee var(--dd-logo-marquee-speed) linear infinite; }' +
115
- '.logo-marquee-block:hover .logo-marquee-track { animation-play-state: paused; }'
116
- }</style>
102
+ <style>
103
+ {'@keyframes dd-logo-marquee { from { transform: translate3d(0, 0, 0); } to { transform: translate3d(-50%, 0, 0); } }' +
104
+ '.logo-marquee-track { animation: dd-logo-marquee var(--dd-logo-marquee-speed) linear infinite; }' +
105
+ '.logo-marquee-block:hover .logo-marquee-track { animation-play-state: paused; }'}
106
+ </style>
117
107
  <div className={cn('relative w-full overflow-hidden', containerClass)}>
118
108
  <div
119
109
  className="logo-marquee-track flex w-max items-center"
@@ -343,6 +343,14 @@ const LottieBlockComponent: React.FC<LottieBlockProps> = ({
343
343
  }
344
344
  }
345
345
 
346
+ if (!fileUrl) {
347
+ return (
348
+ <div className={cn(lottieBaseClass, 'flex min-h-[220px] min-w-[320px] items-center justify-center rounded-md border border-border bg-card p-8 text-center text-sm text-muted-foreground', containerClass)}>
349
+ Lottie animation placeholder
350
+ </div>
351
+ )
352
+ }
353
+
346
354
  const containerStyles: React.CSSProperties = {
347
355
  width: width || 'auto',
348
356
  height: height || 'auto',
@@ -424,7 +432,7 @@ const LottieBlockComponent: React.FC<LottieBlockProps> = ({
424
432
  aria-label="Play animation"
425
433
  type="button"
426
434
  >
427
- ▶️
435
+ ▶️
428
436
  </button>
429
437
  <button
430
438
  onClick={handlePause}
@@ -432,7 +440,7 @@ const LottieBlockComponent: React.FC<LottieBlockProps> = ({
432
440
  aria-label="Pause animation"
433
441
  type="button"
434
442
  >
435
- ⏸️
443
+ ⏸️
436
444
  </button>
437
445
  <button
438
446
  onClick={handleStop}
@@ -440,7 +448,7 @@ const LottieBlockComponent: React.FC<LottieBlockProps> = ({
440
448
  aria-label="Stop animation"
441
449
  type="button"
442
450
  >
443
- ⏹️
451
+ ⏹️
444
452
  </button>
445
453
  </div>
446
454
  )}