blocks-dusted 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/README.md +35 -0
  2. package/package.json +5 -2
  3. package/src/cli.js +39 -3
  4. package/src/commands/shop.js +59 -0
  5. package/src/commands/warehouse.js +73 -0
  6. package/src/utils/paths.js +13 -13
  7. package/templates/blocks/DD-Accordion/Component.tsx +229 -0
  8. package/templates/blocks/DD-Accordion/README.md +3 -0
  9. package/templates/blocks/DD-Accordion/config.ts +73 -0
  10. package/templates/blocks/DD-Accordion/manifest.json +75 -0
  11. package/templates/blocks/DD-AnimText/Component.tsx +788 -0
  12. package/templates/blocks/DD-AnimText/README.md +3 -0
  13. package/templates/blocks/DD-AnimText/config.ts +295 -0
  14. package/templates/blocks/DD-AnimText/manifest.json +85 -0
  15. package/templates/blocks/DD-AsideNav/Component.tsx +321 -0
  16. package/templates/blocks/DD-AsideNav/config.ts +204 -0
  17. package/templates/blocks/DD-AsideNav/manifest.json +80 -0
  18. package/templates/blocks/DD-Banner/Component.tsx +51 -0
  19. package/templates/blocks/DD-Banner/config.ts +57 -0
  20. package/templates/blocks/DD-Banner/manifest.json +72 -0
  21. package/templates/blocks/DD-BgLightning/Component.tsx +44 -0
  22. package/templates/blocks/DD-BgLightning/README.md +3 -0
  23. package/templates/blocks/DD-BgLightning/config.ts +97 -0
  24. package/templates/blocks/DD-BgLightning/manifest.json +79 -0
  25. package/templates/blocks/DD-BookCall/Component.tsx +535 -535
  26. package/templates/blocks/DD-BookCall/config.ts +238 -238
  27. package/templates/blocks/DD-ButtonPop/Component.tsx +117 -0
  28. package/templates/blocks/DD-ButtonPop/config.ts +105 -0
  29. package/templates/blocks/DD-ButtonPop/manifest.json +88 -0
  30. package/templates/blocks/DD-ButtonPop/svg-icons/Dust2.tsx +167 -0
  31. package/templates/blocks/DD-Card/Component.tsx +251 -0
  32. package/templates/blocks/DD-Card/README.md +4 -0
  33. package/templates/blocks/DD-Card/config.ts +154 -0
  34. package/templates/blocks/DD-Card/manifest.json +82 -0
  35. package/templates/blocks/DD-CardTemplate01/Component.tsx +140 -140
  36. package/templates/blocks/DD-CardTemplate01/config.ts +106 -106
  37. package/templates/blocks/DD-Carousel-A/Component.tsx +249 -249
  38. package/templates/blocks/DD-Carousel-B/Component.tsx +403 -403
  39. package/templates/blocks/DD-Chip/Component.tsx +250 -0
  40. package/templates/blocks/DD-Chip/EXAMPLES.md +313 -0
  41. package/templates/blocks/DD-Chip/README.md +202 -0
  42. package/templates/blocks/DD-Chip/config.ts +369 -0
  43. package/templates/blocks/DD-Chip/manifest.json +74 -0
  44. package/templates/blocks/DD-ComparisonTable/Component.tsx +256 -256
  45. package/templates/blocks/DD-Contact/Component.tsx +435 -434
  46. package/templates/blocks/DD-Contact/config.ts +22 -22
  47. package/templates/blocks/DD-Counter/Component.tsx +190 -0
  48. package/templates/blocks/DD-Counter/README.md +4 -0
  49. package/templates/blocks/DD-Counter/config.ts +291 -0
  50. package/templates/blocks/DD-Counter/manifest.json +74 -0
  51. package/templates/blocks/DD-CustomCSS/Component.tsx +8 -0
  52. package/templates/blocks/DD-CustomCSS/README.md +4 -0
  53. package/templates/blocks/DD-CustomCSS/addToLayout.md +5 -0
  54. package/templates/blocks/DD-CustomCSS/config.ts +22 -0
  55. package/templates/blocks/DD-CustomCSS/manifest.json +72 -0
  56. package/templates/blocks/DD-CustomCSS/renderCustomCSS.md +7 -0
  57. package/templates/blocks/DD-FeatCat/Component.tsx +302 -302
  58. package/templates/blocks/DD-FeatCat/config.ts +201 -201
  59. package/templates/blocks/DD-FeatStrip/Component.tsx +585 -585
  60. package/templates/blocks/DD-FeatStrip/config.ts +134 -134
  61. package/templates/blocks/DD-FluidBtn/ButtonsEyeCatching.tsx +628 -0
  62. package/templates/blocks/DD-FluidBtn/Component.tsx +43 -0
  63. package/templates/blocks/DD-FluidBtn/README.md +6 -0
  64. package/templates/blocks/DD-FluidBtn/config.ts +102 -0
  65. package/templates/blocks/DD-FluidBtn/manifest.json +86 -0
  66. package/templates/blocks/DD-GooeyInfo/Component.tsx +149 -0
  67. package/templates/blocks/DD-GooeyInfo/config.ts +135 -0
  68. package/templates/blocks/DD-GooeyInfo/manifest.json +72 -0
  69. package/templates/blocks/DD-Hero/Component.tsx +297 -297
  70. package/templates/blocks/DD-Hero/config.ts +267 -267
  71. package/templates/blocks/DD-HorizontalScroll/Component.tsx +936 -936
  72. package/templates/blocks/DD-HorizontalScroll/config.ts +231 -231
  73. package/templates/blocks/DD-Icon/Component.tsx +287 -0
  74. package/templates/blocks/DD-Icon/README.md +4 -0
  75. package/templates/blocks/DD-Icon/config.ts +258 -0
  76. package/templates/blocks/DD-Icon/hooks/revalidateBlockIds.ts +66 -0
  77. package/templates/blocks/DD-Icon/manifest.json +82 -0
  78. package/templates/blocks/DD-IconButton/Component.tsx +455 -0
  79. package/templates/blocks/DD-IconButton/README.md +326 -0
  80. package/templates/blocks/DD-IconButton/config.ts +239 -0
  81. package/templates/blocks/DD-IconButton/manifest.json +85 -0
  82. package/templates/blocks/DD-IdTag/Component.tsx +21 -0
  83. package/templates/blocks/DD-IdTag/README.md +4 -0
  84. package/templates/blocks/DD-IdTag/config.ts +41 -0
  85. package/templates/blocks/DD-IdTag/manifest.json +72 -0
  86. package/templates/blocks/DD-Iframe/Component.tsx +45 -0
  87. package/templates/blocks/DD-Iframe/README.md +4 -0
  88. package/templates/blocks/DD-Iframe/config.ts +47 -0
  89. package/templates/blocks/DD-Iframe/manifest.json +72 -0
  90. package/templates/blocks/DD-IframeMedia/Component.tsx +133 -0
  91. package/templates/blocks/DD-IframeMedia/README.md +4 -0
  92. package/templates/blocks/DD-IframeMedia/config.ts +79 -0
  93. package/templates/blocks/DD-IframeMedia/manifest.json +72 -0
  94. package/templates/blocks/DD-LineAnim/Component.tsx +36 -0
  95. package/templates/blocks/DD-LineAnim/README.md +4 -0
  96. package/templates/blocks/DD-LineAnim/config.ts +90 -0
  97. package/templates/blocks/DD-LineAnim/manifest.json +80 -0
  98. package/templates/blocks/DD-LinkGrid/Component.tsx +119 -0
  99. package/templates/blocks/DD-LinkGrid/README.md +4 -0
  100. package/templates/blocks/DD-LinkGrid/config.ts +51 -0
  101. package/templates/blocks/DD-LinkGrid/manifest.json +74 -0
  102. package/templates/blocks/DD-LogoMarq/Component.tsx +132 -0
  103. package/templates/blocks/DD-LogoMarq/README.md +4 -0
  104. package/templates/blocks/DD-LogoMarq/config.ts +264 -0
  105. package/templates/blocks/DD-LogoMarq/manifest.json +82 -0
  106. package/templates/blocks/DD-Lottie/Component.tsx +459 -0
  107. package/templates/blocks/DD-Lottie/README.md +4 -0
  108. package/templates/blocks/DD-Lottie/config.ts +379 -0
  109. package/templates/blocks/DD-Lottie/index.tsx +28 -0
  110. package/templates/blocks/DD-Lottie/manifest.json +83 -0
  111. package/templates/blocks/DD-MagicBento/Component.tsx +777 -0
  112. package/templates/blocks/DD-MagicBento/README.md +4 -0
  113. package/templates/blocks/DD-MagicBento/config.ts +264 -0
  114. package/templates/blocks/DD-MagicBento/manifest.json +74 -0
  115. package/templates/blocks/DD-MasonaryMedia/Component.tsx +545 -545
  116. package/templates/blocks/DD-MasonaryMedia/config.ts +2 -2
  117. package/templates/blocks/DD-MasonaryMedia/vendor.d.ts +2 -2
  118. package/templates/blocks/DD-Masonry/Component.tsx +645 -0
  119. package/templates/blocks/DD-Masonry/README.md +4 -0
  120. package/templates/blocks/DD-Masonry/config.ts +475 -0
  121. package/templates/blocks/DD-Masonry/manifest.json +82 -0
  122. package/templates/blocks/DD-Pricing/Component.tsx +2 -5
  123. package/templates/blocks/DD-Process/Component.tsx +2 -4
  124. package/templates/blocks/DD-Process/config.ts +150 -150
  125. package/templates/blocks/DD-Progress/Component.tsx +156 -0
  126. package/templates/blocks/DD-Progress/README.md +4 -0
  127. package/templates/blocks/DD-Progress/config.ts +175 -0
  128. package/templates/blocks/DD-Progress/manifest.json +74 -0
  129. package/templates/blocks/DD-ProjHeader/Component.tsx +91 -0
  130. package/templates/blocks/DD-ProjHeader/README.md +4 -0
  131. package/templates/blocks/DD-ProjHeader/config.ts +96 -0
  132. package/templates/blocks/DD-ProjHeader/manifest.json +72 -0
  133. package/templates/blocks/DD-ProjSlider/Component.tsx +123 -0
  134. package/templates/blocks/DD-ProjSlider/README.md +4 -0
  135. package/templates/blocks/DD-ProjSlider/config.ts +64 -0
  136. package/templates/blocks/DD-ProjSlider/manifest.json +72 -0
  137. package/templates/blocks/DD-ScrollText/Component.tsx +114 -0
  138. package/templates/blocks/DD-ScrollText/README.md +4 -0
  139. package/templates/blocks/DD-ScrollText/config.ts +58 -0
  140. package/templates/blocks/DD-ScrollText/manifest.json +72 -0
  141. package/templates/blocks/DD-Section/Component.tsx +266 -266
  142. package/templates/blocks/DD-Separator/Component.tsx +66 -0
  143. package/templates/blocks/DD-Separator/README.md +4 -0
  144. package/templates/blocks/DD-Separator/config.ts +58 -0
  145. package/templates/blocks/DD-Separator/manifest.json +72 -0
  146. package/templates/blocks/DD-Services/Component.tsx +176 -176
  147. package/templates/blocks/DD-Services/config.ts +149 -149
  148. package/templates/blocks/DD-ShowcaseGrid/Component.tsx +307 -307
  149. package/templates/blocks/DD-Slider-A/Component.tsx +1 -1
  150. package/templates/blocks/DD-StackCards/Component.tsx +1 -1
  151. package/templates/blocks/DD-StackCards/config.ts +399 -399
  152. package/templates/blocks/DD-Team/Component.tsx +247 -247
  153. package/templates/blocks/DD-Team/config.ts +173 -173
  154. package/templates/blocks/DD-TeamCards/Component.tsx +251 -0
  155. package/templates/blocks/DD-TeamCards/README.md +4 -0
  156. package/templates/blocks/DD-TeamCards/config.ts +302 -0
  157. package/templates/blocks/DD-TeamCards/manifest.json +74 -0
  158. package/templates/blocks/DD-TechStack/Component.tsx +174 -174
  159. package/templates/blocks/DD-TechStack/config.ts +153 -153
  160. package/templates/blocks/DD-TestMarq/Component.tsx +132 -0
  161. package/templates/blocks/DD-TestMarq/README.md +4 -0
  162. package/templates/blocks/DD-TestMarq/RowLabel.tsx +9 -0
  163. package/templates/blocks/DD-TestMarq/config.ts +88 -0
  164. package/templates/blocks/DD-TestMarq/manifest.json +72 -0
  165. package/templates/blocks/DD-Testim/Component.tsx +247 -0
  166. package/templates/blocks/DD-Testim/README.md +4 -0
  167. package/templates/blocks/DD-Testim/config.ts +101 -0
  168. package/templates/blocks/DD-Testim/manifest.json +75 -0
  169. package/templates/blocks/DD-Testim2/Component.tsx +256 -0
  170. package/templates/blocks/DD-Testim2/README.md +4 -0
  171. package/templates/blocks/DD-Testim2/config.ts +100 -0
  172. package/templates/blocks/DD-Testim2/manifest.json +74 -0
  173. package/templates/blocks/DD-Testimonials/Component.tsx +139 -147
  174. package/templates/blocks/DD-Testimonials/config.ts +120 -120
  175. package/templates/blocks/DD-TextMarq/Component.tsx +157 -0
  176. package/templates/blocks/DD-TextMarq/README.md +4 -0
  177. package/templates/blocks/DD-TextMarq/config.ts +237 -0
  178. package/templates/blocks/DD-TextMarq/manifest.json +82 -0
  179. package/templates/blocks/DD-Thanks/Component.tsx +501 -0
  180. package/templates/blocks/DD-Thanks/README.md +4 -0
  181. package/templates/blocks/DD-Thanks/config.ts +224 -0
  182. package/templates/blocks/DD-Thanks/manifest.json +72 -0
  183. package/templates/blocks/DD-VertMarq/Component.tsx +154 -0
  184. package/templates/blocks/DD-VertMarq/README.md +4 -0
  185. package/templates/blocks/DD-VertMarq/config.ts +236 -0
  186. package/templates/blocks/DD-VertMarq/dist/index.css +6 -0
  187. package/templates/blocks/DD-VertMarq/dist/index.min.css +1 -0
  188. package/templates/blocks/DD-VertMarq/manifest.json +74 -0
  189. package/templates/blocks/DD-Work/Component.tsx +318 -315
  190. package/templates/blocks/DD-Work/config.ts +165 -165
  191. package/templates/blocks/DD-Work-B/Component.tsx +294 -294
  192. package/templates/blocks/DDHG-CTASection2/Component.tsx +185 -0
  193. package/templates/blocks/DDHG-CTASection2/config.ts +140 -0
  194. package/templates/blocks/DDHG-CTASection2/manifest.json +45 -0
  195. package/templates/blocks/DDHG-HighlightArc/Component.tsx +243 -0
  196. package/templates/blocks/DDHG-HighlightArc/config.ts +85 -0
  197. package/templates/blocks/DDHG-HighlightArc/manifest.json +46 -0
  198. package/templates/blocks/DDHG-LogoMarquee/Component.tsx +143 -0
  199. package/templates/blocks/DDHG-LogoMarquee/config.ts +154 -0
  200. package/templates/blocks/DDHG-LogoMarquee/manifest.json +39 -0
  201. package/templates/blocks/DDHG-NavCodeGrid/Component.tsx +227 -0
  202. package/templates/blocks/DDHG-NavCodeGrid/config.ts +64 -0
  203. package/templates/blocks/DDHG-NavCodeGrid/manifest.json +45 -0
  204. package/templates/blocks/DDHG-ProcessSec/Component.tsx +574 -0
  205. package/templates/blocks/DDHG-ProcessSec/config.ts +170 -0
  206. package/templates/blocks/DDHG-ProcessSec/manifest.json +56 -0
  207. package/templates/blocks/DDHG-ServiceDetails/Component.tsx +164 -0
  208. package/templates/blocks/DDHG-ServiceDetails/ServiceDetailCard.tsx +390 -0
  209. package/templates/blocks/DDHG-ServiceDetails/config.ts +77 -0
  210. package/templates/blocks/DDHG-ServiceDetails/manifest.json +50 -0
  211. package/templates/blocks/DDHG-ServiceHero/Component.tsx +234 -0
  212. package/templates/blocks/DDHG-ServiceHero/config.ts +49 -0
  213. package/templates/blocks/DDHG-ServiceHero/manifest.json +26 -0
  214. package/templates/blocks/DDHG-ServiceOverview/Component.tsx +277 -0
  215. package/templates/blocks/DDHG-ServiceOverview/config.ts +64 -0
  216. package/templates/blocks/DDHG-ServiceOverview/manifest.json +44 -0
  217. package/templates/blocks/DDHG-StatsFAQ/Component.tsx +389 -0
  218. package/templates/blocks/DDHG-StatsFAQ/config.ts +204 -0
  219. package/templates/blocks/DDHG-StatsFAQ/manifest.json +45 -0
  220. package/templates/blocks/DDHG-TeamCards/Component.tsx +169 -0
  221. package/templates/blocks/DDHG-TeamCards/config.ts +48 -0
  222. package/templates/blocks/DDHG-TeamCards/manifest.json +29 -0
  223. package/templates/shared/src/components/BgLightning/index.tsx +242 -0
  224. package/templates/shared/src/components/ui/ShareButton/index.tsx +80 -0
  225. package/templates/shared/src/components/ui/anims/FadeOnScroll.tsx +48 -0
  226. package/templates/shared/src/components/ui/anims/FadeUpOnInView.tsx +63 -0
  227. package/templates/shared/src/components/ui/anims/GlareHover.tsx +111 -0
  228. package/templates/shared/src/components/ui/anims/LineAnims.tsx +81 -0
  229. package/templates/shared/src/components/ui/anims/TitleAnims01.tsx +54 -0
  230. package/templates/shared/src/components/ui/anims/animation-container.tsx +29 -0
  231. package/templates/shared/src/components/ui/anims/blur-in.tsx +26 -0
  232. package/templates/shared/src/components/ui/anims/counter.tsx +53 -0
  233. package/templates/shared/src/components/ui/anims/fade.tsx +83 -0
  234. package/templates/shared/src/components/ui/anims/gradual-spacing.tsx +39 -0
  235. package/templates/shared/src/components/ui/anims/pull-up.tsx +93 -0
  236. package/templates/shared/src/components/ui/anims/reveal-text.tsx +76 -0
  237. package/templates/shared/src/components/ui/anims/rotate-words.tsx +43 -0
  238. package/templates/shared/src/components/ui/anims/shiny-text.tsx +58 -0
  239. package/templates/shared/src/components/ui/anims/shuffle-text.tsx +85 -0
  240. package/templates/shared/src/components/ui/anims/split-text.tsx +211 -0
  241. package/templates/shared/src/components/ui/anims/staggered-fade.tsx +133 -0
  242. package/templates/shared/src/components/ui/anims/text-scroll.tsx +111 -0
  243. package/templates/shared/src/components/ui/anims/typing-effect.tsx +112 -0
  244. package/templates/shared/src/components/ui/button-dusted-fluid/index.tsx +1521 -0
  245. package/templates/shared/src/components/ui/separator.tsx +85 -0
  246. package/templates/shared/src/hooks/useBodyScrollLock.ts +97 -0
  247. package/templates/shared/src/hooks/useClickOutside.ts +28 -0
  248. package/templates/shared/src/utilities/renderCustomCSS.ts +5 -0
  249. package/templates/shared/src/utilities/smoothScroll.ts +65 -0
@@ -0,0 +1,455 @@
1
+ 'use client'
2
+
3
+ import React from 'react'
4
+ import { cn } from '@/utilities/ui'
5
+ import Link from 'next/link'
6
+ import * as LucideIcons from 'lucide-react'
7
+ import type { Page, Post } from '@/payload-types'
8
+ import { ShareButton } from '@/components/ui/ShareButton'
9
+ import { smoothScrollTo, isAnchorLink } from '@/utilities/smoothScroll'
10
+ import { usePathname, useRouter } from 'next/navigation'
11
+
12
+ const useDrawerClose = () => undefined
13
+
14
+ type DisplayMode = 'iconWithLabel' | 'iconOnly' | 'labelOnly' | 'share'
15
+ type ButtonStyle =
16
+ | 'default'
17
+ | 'primary'
18
+ | 'secondary'
19
+ | 'outline'
20
+ | 'ghost'
21
+ | 'destructive'
22
+ | 'v1'
23
+ | 'v2'
24
+ | 'v3'
25
+ | 'v4'
26
+ | 'v5'
27
+ | 'v6'
28
+ | 'v7'
29
+ | 'v8'
30
+ type ButtonSize = 'small' | 'medium' | 'large'
31
+ type IconPosition = 'before' | 'after'
32
+
33
+ type LinkReference =
34
+ | { relationTo: 'pages'; value: number | Page }
35
+ | { relationTo: 'posts'; value: number | Post }
36
+
37
+ export type LinkType = {
38
+ type?: 'reference' | 'custom' | null
39
+ url?: string | null
40
+ reference?: LinkReference | null
41
+ label: string
42
+ newTab?: boolean | null
43
+ appearance?: 'default' | 'outline' | null
44
+ icon?: string | null
45
+ }
46
+
47
+ export type ButtonWithIconProps = {
48
+ iconButtonContainerClass?: string
49
+ enableGutter?: boolean
50
+ buttonText?: string
51
+ buttonStyle?: ButtonStyle
52
+ displayMode?: DisplayMode
53
+ iconName?: string
54
+ iconPosition?: IconPosition
55
+ link?: LinkType | string
56
+ size?: ButtonSize
57
+ overrideSizeClasses?: string
58
+ onToggle?: () => void
59
+ scrollDuration?: number
60
+ scrollOffset?: number
61
+ closeDrawerOnClick?: boolean
62
+ }
63
+
64
+ export const DDIconButton: React.FC<ButtonWithIconProps> = ({
65
+ iconButtonContainerClass,
66
+ enableGutter = true,
67
+ buttonText,
68
+ buttonStyle = 'primary',
69
+ displayMode = 'iconWithLabel',
70
+ iconName,
71
+ iconPosition = 'before',
72
+ link,
73
+ size = 'medium',
74
+ overrideSizeClasses,
75
+ onToggle,
76
+ scrollDuration = 1,
77
+ scrollOffset = 80,
78
+ closeDrawerOnClick = true
79
+ }) => {
80
+ const pathname = usePathname()
81
+ const router = useRouter()
82
+ const isNavigating = false
83
+ const closeDrawer = useDrawerClose?.() || (() => {})
84
+
85
+ const toPascalCase = (value: string): string => {
86
+ const parts = value
87
+ .trim()
88
+ .split(/[^a-zA-Z0-9]+/)
89
+ .filter(Boolean)
90
+
91
+ return parts
92
+ .map((part) => {
93
+ if (/^\d+$/.test(part)) return part
94
+ return part.charAt(0).toUpperCase() + part.slice(1)
95
+ })
96
+ .join('')
97
+ }
98
+
99
+ const resolveLucideIconComponent = (name?: string | null) => {
100
+ if (!name) return null
101
+
102
+ const trimmed = name.trim()
103
+ if (!trimmed) return null
104
+
105
+ const candidates = [
106
+ trimmed,
107
+ trimmed.charAt(0).toUpperCase() + trimmed.slice(1),
108
+ toPascalCase(trimmed)
109
+ ]
110
+
111
+ for (const candidate of candidates) {
112
+ const maybe = (LucideIcons as unknown as Record<string, unknown>)[candidate]
113
+
114
+ const isComponent =
115
+ typeof maybe === 'function' ||
116
+ (typeof maybe === 'object' && maybe !== null && '$$typeof' in (maybe as any))
117
+
118
+ if (isComponent) return maybe as React.ComponentType<{ className?: string }>
119
+ }
120
+
121
+ return null
122
+ }
123
+
124
+ const effectiveIconName = typeof link === 'object' && link?.icon ? link.icon : iconName
125
+ const IconComponent = resolveLucideIconComponent(effectiveIconName)
126
+
127
+ const handleNavigation = (href: string, e?: React.MouseEvent) => {
128
+ e?.preventDefault()
129
+
130
+ if (closeDrawerOnClick) {
131
+ closeDrawer()
132
+ }
133
+
134
+ setTimeout(
135
+ () => {
136
+ router.push(href)
137
+ },
138
+ closeDrawerOnClick ? 150 : 0
139
+ )
140
+ }
141
+
142
+ const handleClick = (href: string, e?: React.MouseEvent) => {
143
+ const hashIndex = href.indexOf('#')
144
+ const hasHash = hashIndex >= 0
145
+ const basePath = hasHash ? href.slice(0, hashIndex) : href
146
+ const hash = hasHash ? href.slice(hashIndex) : ''
147
+
148
+ const normalise = (p?: string) => (p ? p.replace(/\/$/, '') : '')
149
+ const isSamePageHash =
150
+ hasHash && (basePath === '' || normalise(basePath) === normalise(pathname))
151
+
152
+ if (isAnchorLink(href) || isSamePageHash) {
153
+ e?.preventDefault()
154
+
155
+ if (closeDrawerOnClick) {
156
+ closeDrawer()
157
+ }
158
+
159
+ const target = hash || href
160
+
161
+ smoothScrollTo(target, {
162
+ duration: scrollDuration,
163
+ offsetY: scrollOffset,
164
+ ease: 'power2.out'
165
+ })
166
+
167
+ onToggle?.()
168
+ return
169
+ }
170
+
171
+ if (href && href !== '#') {
172
+ handleNavigation(href, e)
173
+ }
174
+
175
+ onToggle?.()
176
+ }
177
+
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 => {
184
+ if (typeof doc === 'number') return null
185
+
186
+ const anyDoc = doc as any
187
+ const slug = anyDoc?.slug as string | undefined
188
+
189
+ if (!slug) return null
190
+ if (slug === 'home' || slug === '') return '/home'
191
+
192
+ return slug.startsWith('/') ? slug : `/${slug}`
193
+ }
194
+
195
+ const isExternalUrl = (url: string): boolean => {
196
+ return (
197
+ url.startsWith('http://') ||
198
+ url.startsWith('https://') ||
199
+ url.startsWith('mailto:') ||
200
+ url.startsWith('tel:')
201
+ )
202
+ }
203
+
204
+ let href = '#'
205
+ let target: string | undefined
206
+ let rel: string | undefined
207
+
208
+ if (!link) {
209
+ href = '#'
210
+ } else if (typeof link === 'string') {
211
+ href = link
212
+ } else {
213
+ const isExternal = link.type === 'custom'
214
+
215
+ if (isExternal && link.url) {
216
+ href = link.url
217
+
218
+ if (isAnchorLink(link.url)) {
219
+ target = undefined
220
+ rel = undefined
221
+ } else if (isExternalUrl(link.url)) {
222
+ target = link.newTab !== false ? '_blank' : undefined
223
+ rel = link.newTab !== false ? 'noopener noreferrer' : undefined
224
+ } else {
225
+ target = link.newTab ? '_blank' : undefined
226
+ rel = link.newTab ? 'noopener noreferrer' : undefined
227
+ }
228
+ } else if (!isExternal && link.reference) {
229
+ const { relationTo, value } = link.reference
230
+
231
+ if (relationTo === 'pages') {
232
+ const pageHref = getPageURLFromDoc(value as Page | number)
233
+ 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
+ }
241
+
242
+ target = link.newTab ? '_blank' : undefined
243
+ rel = link.newTab ? 'noopener noreferrer' : undefined
244
+ }
245
+ }
246
+
247
+ const sizeClasses: Record<ButtonSize, string> = {
248
+ small: overrideSizeClasses || 'px-3 py-2 text-sm',
249
+ medium: overrideSizeClasses || 'px-4 py-2 text-base',
250
+ large: overrideSizeClasses || 'px-6 py-3 text-lg'
251
+ }
252
+
253
+ const styleClasses: Record<ButtonStyle, string> = {
254
+ default:
255
+ 'bg-transparent text-[aliceblue] rounded-2xl squircle shadow-[var(--shadow-md)] border-2 border-[aliceblue] border-[ridge] brightness-100 max-h-fit transition-all duration-300 hover:brightness-110 hover:text-[var(--accent)] hover:border hover:border-[outset] hover:border-[var(--accent)] hover:shadow-[var(--shadow-xl)] [&_svg]:scale-100 [&_svg]:transition-all [&_svg]:duration-300 hover:[&_svg]:scale-110',
256
+
257
+ primary:
258
+ 'bg-[#242845] text-[aliceblue] rounded-2xl squircle border border-[outset] border-[rgba(253,253,253,0.2)] brightness-100 max-h-fit !no-underline transition-all duration-300 hover:bg-[rgba(253,253,253,0.7)] hover:text-[#242845] hover:brightness-100 hover:[&_svg]:!text-[#242845]',
259
+
260
+ secondary:
261
+ 'bg-[rgba(253,253,253,0.7)] text-[#242845] rounded-2xl squircle border border-[outset] border-[rgba(253,253,253,0.2)] brightness-100 max-h-fit !no-underline transition-all duration-300 [&_svg]:!text-[#242845] hover:bg-[#242845] hover:text-[aliceblue] hover:brightness-100 hover:[&_svg]:!text-[aliceblue]',
262
+
263
+ outline:
264
+ 'bg-transparent text-[aliceblue] rounded-2xl squircle shadow-[var(--shadow-md)] border-2 border-[aliceblue] border-[ridge] brightness-100 max-h-fit transition-all duration-300 hover:brightness-110 hover:text-[var(--accent)] hover:border hover:border-[outset] hover:border-[var(--accent)] hover:shadow-[var(--shadow-xl)] [&_svg]:scale-100 [&_svg]:transition-all [&_svg]:duration-300 hover:[&_svg]:scale-110',
265
+
266
+ ghost:
267
+ 'bg-transparent text-[var(--text)] !border-0 max-h-fit transition-all duration-300 hover:text-[var(--accent)] hover:font-medium',
268
+
269
+ 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",
271
+
272
+ 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
+ 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',
274
+ v3: 'relative overflow-hidden group hover:ring-2 hover:ring-offset-2 ease-out hover:bg-gradient-to-r bg-zinc-900 hover:from-zinc-800 hover:to-zinc-700 text-zinc-50 hover:ring-zinc-900 dark:bg-zinc-50 dark:hover:from-zinc-50 dark:hover:to-zinc-100 dark:text-zinc-800 dark:hover:ring-white dark:ring-offset-black px-3 py-1',
275
+ v4: 'group relative overflow-hidden rounded-md text-zinc-50 bg-gradient-to-tr duration-300 ease-in-out active:translate-y-0.5 active:scale-100 active:shadow-none from-zinc-800 to-zinc-700 shadow-[0px_3px_0px_rgba(82,82,91,0.9)] dark:active:shadow-none dark:from-zinc-50 dark:to-zinc-100 dark:shadow-[0px_3px_0px_rgba(161,161,170,0.9)] px-3 py-1',
276
+ v5: 'relative overflow-hidden border shadow group invert-[1] border-stone-300 text-zinc-800 bg-zinc-50 dark:border-stone-700 dark:text-zinc-100 dark:bg-zinc-950 px-3 py-1',
277
+ v6: 'relative rounded-sm border dark:border-stone-200 border-stone-600 group scale-y-[.88] scale-x-[0.97] group-hover:scale-100 duration-300 font-semibold transition dark:bg-zinc-50 bg-zinc-950 text-zinc-100 dark:text-zinc-800 px-3 py-1',
278
+ v7: "relative hover:no-underline px-[1px] pb-0 ease-in after:absolute after:bottom-0 after:left-0 after:h-0.5 after:w-full after:translate-y-[3px] after:rounded-full after:dark:bg-zinc-50 after:bg-zinc-800 after:opacity-0 after:duration-300 after:content-[''] hover:after:-translate-y-1 hover:after:opacity-100 px-3 py-1",
279
+ v8: 'shadow-embossed hover:shadow-none ease-out hover:scale-100 dark:bg-[#121212] dark:text-[#999999] bg-zinc-50 text-stone-900 px-3 py-1'
280
+ }
281
+
282
+ const iconSizeClasses: Record<ButtonSize, string> = {
283
+ small: 'w-4 h-4',
284
+ medium: 'w-4 h-4',
285
+ large: 'w-6 h-6'
286
+ }
287
+
288
+ const buttonContent = () => {
289
+ switch (displayMode) {
290
+ case 'iconOnly':
291
+ return IconComponent ? (
292
+ <IconComponent className={iconSizeClasses[size]} />
293
+ ) : (
294
+ <span>No Icon</span>
295
+ )
296
+
297
+ case 'labelOnly':
298
+ return buttonText || 'Button'
299
+
300
+ case 'share':
301
+ return null
302
+
303
+ case 'iconWithLabel':
304
+ default:
305
+ return (
306
+ <div className="flex items-center justify-center gap-2">
307
+ {IconComponent && iconPosition === 'before' && (
308
+ <IconComponent className={iconSizeClasses[size]} />
309
+ )}
310
+ <span>{buttonText || 'Button'}</span>
311
+ {IconComponent && iconPosition === 'after' && (
312
+ <IconComponent className={iconSizeClasses[size]} />
313
+ )}
314
+ </div>
315
+ )
316
+ }
317
+ }
318
+
319
+ const getButtonContent = () => {
320
+ const baseContent = buttonContent()
321
+
322
+ switch (buttonStyle) {
323
+ case 'v2':
324
+ return (
325
+ <>
326
+ <span className="relative">{baseContent}</span>
327
+ <span
328
+ className="absolute inset-0 flex size-full justify-center [transform:skew(-14deg)_translateX(-100%)] group-hover:duration-1000 group-hover:[transform:skew(-14deg)_translateX(100%)]"
329
+ style={{ width: '200% !important' }}
330
+ aria-hidden="true"
331
+ >
332
+ <span className="relative h-full w-32 scale-200 bg-black/20 dark:bg-black/10" />
333
+ </span>
334
+ </>
335
+ )
336
+
337
+ case 'v3':
338
+ return (
339
+ <>
340
+ <span
341
+ className="absolute right-0 w-8 h-32 -mt-12 transition-all duration-1000 transform translate-x-12 bg-white/80 dark:bg-zinc-900 opacity-10 rotate-12 group-hover:-translate-x-60 ease"
342
+ aria-hidden="true"
343
+ />
344
+ <span className="relative">{baseContent}</span>
345
+ </>
346
+ )
347
+
348
+ case 'v4':
349
+ return (
350
+ <>
351
+ <span
352
+ className="absolute size-0 rounded-md bg-white/80 dark:bg-black/80 opacity-10 transition-all duration-300 ease-out group-hover:size-full !text-white !dark:text-black"
353
+ aria-hidden="true"
354
+ />
355
+ <span className="relative text-white dark:text-black">{baseContent}</span>
356
+ </>
357
+ )
358
+
359
+ default:
360
+ return <span className="relative">{baseContent}</span>
361
+ }
362
+ }
363
+
364
+ const buttonClasses = cn(
365
+ 'inline-flex items-center justify-center font-medium transition-colors',
366
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
367
+ 'disabled:pointer-events-none disabled:opacity-50',
368
+ 'min-w-36 flex justify-center items-center [&_span]:tracking-[0.2em]',
369
+ !buttonStyle?.startsWith('v') && sizeClasses[size],
370
+ styleClasses[buttonStyle],
371
+ displayMode === 'iconOnly' && 'aspect-square'
372
+ )
373
+
374
+ const shareButtonContent = (
375
+ <ShareButton
376
+ links={[
377
+ {
378
+ icon: LucideIcons.Share2,
379
+ onClick: () => {
380
+ if (closeDrawerOnClick) closeDrawer()
381
+ window.open('https://twitter.com/share')
382
+ }
383
+ },
384
+ {
385
+ icon: LucideIcons.Share,
386
+ onClick: () => {
387
+ if (closeDrawerOnClick) closeDrawer()
388
+ window.open('https://facebook.com/share')
389
+ }
390
+ },
391
+ {
392
+ icon: LucideIcons.Link,
393
+ onClick: () => {
394
+ if (closeDrawerOnClick) closeDrawer()
395
+ window.open('https://linkedin.com/share')
396
+ }
397
+ },
398
+ {
399
+ icon: LucideIcons.Link2,
400
+ onClick: () => {
401
+ if (closeDrawerOnClick) closeDrawer()
402
+ navigator.clipboard.writeText(window.location.href)
403
+ }
404
+ }
405
+ ]}
406
+ >
407
+ {IconComponent && iconPosition === 'before' && (
408
+ <IconComponent className={iconSizeClasses[size]} />
409
+ )}
410
+ <span>{buttonText || 'Share'}</span>
411
+ {IconComponent && iconPosition === 'after' && (
412
+ <IconComponent className={iconSizeClasses[size]} />
413
+ )}
414
+ </ShareButton>
415
+ )
416
+
417
+ const standardButtonContent =
418
+ href && href !== '#' ? (
419
+ <button
420
+ className={cn(buttonClasses, isNavigating ? 'pointer-events-none opacity-50' : '')}
421
+ type="button"
422
+ onClick={(e) => handleClick(href, e)}
423
+ disabled={isNavigating}
424
+ >
425
+ {getButtonContent()}
426
+ </button>
427
+ ) : (
428
+ <button className={buttonClasses} type="button" onClick={(e) => handleClick(href, e)}>
429
+ {getButtonContent()}
430
+ </button>
431
+ )
432
+
433
+ const content = displayMode === 'share' ? shareButtonContent : standardButtonContent
434
+
435
+ return (
436
+ <div
437
+ className={cn(
438
+ 'flex',
439
+ iconButtonContainerClass,
440
+ enableGutter && 'w-fit',
441
+ !enableGutter && 'py-4'
442
+ )}
443
+ >
444
+ {displayMode === 'share' ? (
445
+ content
446
+ ) : href && href !== '#' ? (
447
+ <Link href={href} target={target} rel={rel} onClick={(e) => handleClick(href, e)}>
448
+ {content}
449
+ </Link>
450
+ ) : (
451
+ content
452
+ )}
453
+ </div>
454
+ )
455
+ }