blocks-dusted 0.1.9 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (248) hide show
  1. package/README.md +35 -0
  2. package/package.json +1 -1
  3. package/src/utils/paths.js +13 -13
  4. package/templates/blocks/DD-Accordion/Component.tsx +229 -0
  5. package/templates/blocks/DD-Accordion/README.md +3 -0
  6. package/templates/blocks/DD-Accordion/config.ts +73 -0
  7. package/templates/blocks/DD-Accordion/manifest.json +75 -0
  8. package/templates/blocks/DD-AnimText/Component.tsx +788 -0
  9. package/templates/blocks/DD-AnimText/README.md +3 -0
  10. package/templates/blocks/DD-AnimText/config.ts +295 -0
  11. package/templates/blocks/DD-AnimText/manifest.json +85 -0
  12. package/templates/blocks/DD-AsideNav/Component.tsx +321 -0
  13. package/templates/blocks/DD-AsideNav/config.ts +204 -0
  14. package/templates/blocks/DD-AsideNav/manifest.json +80 -0
  15. package/templates/blocks/DD-Banner/Component.tsx +51 -0
  16. package/templates/blocks/DD-Banner/config.ts +57 -0
  17. package/templates/blocks/DD-Banner/manifest.json +72 -0
  18. package/templates/blocks/DD-BgLightning/Component.tsx +44 -0
  19. package/templates/blocks/DD-BgLightning/README.md +3 -0
  20. package/templates/blocks/DD-BgLightning/config.ts +97 -0
  21. package/templates/blocks/DD-BgLightning/manifest.json +79 -0
  22. package/templates/blocks/DD-BookCall/Component.tsx +10 -11
  23. package/templates/blocks/DD-BookCall/config.ts +238 -238
  24. package/templates/blocks/DD-ButtonPop/Component.tsx +117 -0
  25. package/templates/blocks/DD-ButtonPop/config.ts +105 -0
  26. package/templates/blocks/DD-ButtonPop/manifest.json +88 -0
  27. package/templates/blocks/DD-ButtonPop/svg-icons/Dust2.tsx +167 -0
  28. package/templates/blocks/DD-Card/Component.tsx +251 -0
  29. package/templates/blocks/DD-Card/README.md +4 -0
  30. package/templates/blocks/DD-Card/config.ts +154 -0
  31. package/templates/blocks/DD-Card/manifest.json +82 -0
  32. package/templates/blocks/DD-CardTemplate01/Component.tsx +5 -6
  33. package/templates/blocks/DD-CardTemplate01/config.ts +106 -106
  34. package/templates/blocks/DD-Carousel-A/Component.tsx +249 -249
  35. package/templates/blocks/DD-Carousel-B/Component.tsx +403 -403
  36. package/templates/blocks/DD-Chip/Component.tsx +250 -0
  37. package/templates/blocks/DD-Chip/EXAMPLES.md +313 -0
  38. package/templates/blocks/DD-Chip/README.md +202 -0
  39. package/templates/blocks/DD-Chip/config.ts +369 -0
  40. package/templates/blocks/DD-Chip/manifest.json +74 -0
  41. package/templates/blocks/DD-ComparisonTable/Component.tsx +256 -256
  42. package/templates/blocks/DD-Contact/Component.tsx +434 -434
  43. package/templates/blocks/DD-Contact/config.ts +22 -22
  44. package/templates/blocks/DD-Counter/Component.tsx +190 -0
  45. package/templates/blocks/DD-Counter/README.md +4 -0
  46. package/templates/blocks/DD-Counter/config.ts +291 -0
  47. package/templates/blocks/DD-Counter/manifest.json +74 -0
  48. package/templates/blocks/DD-CustomCSS/Component.tsx +8 -0
  49. package/templates/blocks/DD-CustomCSS/README.md +4 -0
  50. package/templates/blocks/DD-CustomCSS/addToLayout.md +5 -0
  51. package/templates/blocks/DD-CustomCSS/config.ts +22 -0
  52. package/templates/blocks/DD-CustomCSS/manifest.json +72 -0
  53. package/templates/blocks/DD-CustomCSS/renderCustomCSS.md +7 -0
  54. package/templates/blocks/DD-FeatCat/Component.tsx +302 -302
  55. package/templates/blocks/DD-FeatCat/config.ts +201 -201
  56. package/templates/blocks/DD-FeatStrip/Component.tsx +585 -585
  57. package/templates/blocks/DD-FeatStrip/config.ts +134 -134
  58. package/templates/blocks/DD-FluidBtn/ButtonsEyeCatching.tsx +628 -0
  59. package/templates/blocks/DD-FluidBtn/Component.tsx +43 -0
  60. package/templates/blocks/DD-FluidBtn/README.md +6 -0
  61. package/templates/blocks/DD-FluidBtn/config.ts +102 -0
  62. package/templates/blocks/DD-FluidBtn/manifest.json +86 -0
  63. package/templates/blocks/DD-GooeyInfo/Component.tsx +149 -0
  64. package/templates/blocks/DD-GooeyInfo/config.ts +135 -0
  65. package/templates/blocks/DD-GooeyInfo/manifest.json +72 -0
  66. package/templates/blocks/DD-Hero/Component.tsx +40 -17
  67. package/templates/blocks/DD-Hero/config.ts +267 -267
  68. package/templates/blocks/DD-HorizontalScroll/Component.tsx +4 -2
  69. package/templates/blocks/DD-HorizontalScroll/config.ts +231 -231
  70. package/templates/blocks/DD-Icon/Component.tsx +287 -0
  71. package/templates/blocks/DD-Icon/README.md +4 -0
  72. package/templates/blocks/DD-Icon/config.ts +258 -0
  73. package/templates/blocks/DD-Icon/hooks/revalidateBlockIds.ts +66 -0
  74. package/templates/blocks/DD-Icon/manifest.json +82 -0
  75. package/templates/blocks/DD-IconButton/Component.tsx +455 -0
  76. package/templates/blocks/DD-IconButton/README.md +326 -0
  77. package/templates/blocks/DD-IconButton/config.ts +239 -0
  78. package/templates/blocks/DD-IconButton/manifest.json +85 -0
  79. package/templates/blocks/DD-IdTag/Component.tsx +21 -0
  80. package/templates/blocks/DD-IdTag/README.md +4 -0
  81. package/templates/blocks/DD-IdTag/config.ts +41 -0
  82. package/templates/blocks/DD-IdTag/manifest.json +72 -0
  83. package/templates/blocks/DD-Iframe/Component.tsx +45 -0
  84. package/templates/blocks/DD-Iframe/README.md +4 -0
  85. package/templates/blocks/DD-Iframe/config.ts +47 -0
  86. package/templates/blocks/DD-Iframe/manifest.json +72 -0
  87. package/templates/blocks/DD-IframeMedia/Component.tsx +129 -0
  88. package/templates/blocks/DD-IframeMedia/README.md +4 -0
  89. package/templates/blocks/DD-IframeMedia/config.ts +79 -0
  90. package/templates/blocks/DD-IframeMedia/manifest.json +72 -0
  91. package/templates/blocks/DD-LineAnim/Component.tsx +36 -0
  92. package/templates/blocks/DD-LineAnim/README.md +4 -0
  93. package/templates/blocks/DD-LineAnim/config.ts +90 -0
  94. package/templates/blocks/DD-LineAnim/manifest.json +80 -0
  95. package/templates/blocks/DD-LinkGrid/Component.tsx +119 -0
  96. package/templates/blocks/DD-LinkGrid/README.md +4 -0
  97. package/templates/blocks/DD-LinkGrid/config.ts +51 -0
  98. package/templates/blocks/DD-LinkGrid/manifest.json +74 -0
  99. package/templates/blocks/DD-LogoMarq/Component.tsx +132 -0
  100. package/templates/blocks/DD-LogoMarq/README.md +4 -0
  101. package/templates/blocks/DD-LogoMarq/config.ts +264 -0
  102. package/templates/blocks/DD-LogoMarq/manifest.json +82 -0
  103. package/templates/blocks/DD-Lottie/Component.tsx +459 -0
  104. package/templates/blocks/DD-Lottie/README.md +4 -0
  105. package/templates/blocks/DD-Lottie/config.ts +379 -0
  106. package/templates/blocks/DD-Lottie/index.tsx +28 -0
  107. package/templates/blocks/DD-Lottie/manifest.json +83 -0
  108. package/templates/blocks/DD-MagicBento/Component.tsx +777 -0
  109. package/templates/blocks/DD-MagicBento/README.md +4 -0
  110. package/templates/blocks/DD-MagicBento/config.ts +264 -0
  111. package/templates/blocks/DD-MagicBento/manifest.json +74 -0
  112. package/templates/blocks/DD-MasonaryMedia/Component.tsx +547 -545
  113. package/templates/blocks/DD-MasonaryMedia/config.ts +2 -2
  114. package/templates/blocks/DD-MasonaryMedia/vendor.d.ts +2 -2
  115. package/templates/blocks/DD-Masonry/Component.tsx +645 -0
  116. package/templates/blocks/DD-Masonry/README.md +4 -0
  117. package/templates/blocks/DD-Masonry/config.ts +475 -0
  118. package/templates/blocks/DD-Masonry/manifest.json +82 -0
  119. package/templates/blocks/DD-Pricing/Component.tsx +372 -372
  120. package/templates/blocks/DD-Process/Component.tsx +149 -149
  121. package/templates/blocks/DD-Process/config.ts +150 -150
  122. package/templates/blocks/DD-Progress/Component.tsx +141 -0
  123. package/templates/blocks/DD-Progress/README.md +4 -0
  124. package/templates/blocks/DD-Progress/config.ts +175 -0
  125. package/templates/blocks/DD-Progress/manifest.json +74 -0
  126. package/templates/blocks/DD-ProjHeader/Component.tsx +91 -0
  127. package/templates/blocks/DD-ProjHeader/README.md +4 -0
  128. package/templates/blocks/DD-ProjHeader/config.ts +96 -0
  129. package/templates/blocks/DD-ProjHeader/manifest.json +72 -0
  130. package/templates/blocks/DD-ProjSlider/Component.tsx +123 -0
  131. package/templates/blocks/DD-ProjSlider/README.md +4 -0
  132. package/templates/blocks/DD-ProjSlider/config.ts +64 -0
  133. package/templates/blocks/DD-ProjSlider/manifest.json +72 -0
  134. package/templates/blocks/DD-ScrollText/Component.tsx +114 -0
  135. package/templates/blocks/DD-ScrollText/README.md +4 -0
  136. package/templates/blocks/DD-ScrollText/config.ts +58 -0
  137. package/templates/blocks/DD-ScrollText/manifest.json +72 -0
  138. package/templates/blocks/DD-Section/Component.tsx +266 -266
  139. package/templates/blocks/DD-Separator/Component.tsx +66 -0
  140. package/templates/blocks/DD-Separator/README.md +4 -0
  141. package/templates/blocks/DD-Separator/config.ts +58 -0
  142. package/templates/blocks/DD-Separator/manifest.json +72 -0
  143. package/templates/blocks/DD-Services/Component.tsx +176 -176
  144. package/templates/blocks/DD-Services/config.ts +149 -149
  145. package/templates/blocks/DD-ShowcaseGrid/Component.tsx +307 -307
  146. package/templates/blocks/DD-Slider-A/Component.tsx +237 -237
  147. package/templates/blocks/DD-StackCards/Component.tsx +473 -473
  148. package/templates/blocks/DD-StackCards/config.ts +399 -399
  149. package/templates/blocks/DD-Team/Component.tsx +247 -247
  150. package/templates/blocks/DD-Team/config.ts +173 -173
  151. package/templates/blocks/DD-TeamCards/Component.tsx +251 -0
  152. package/templates/blocks/DD-TeamCards/README.md +4 -0
  153. package/templates/blocks/DD-TeamCards/config.ts +302 -0
  154. package/templates/blocks/DD-TeamCards/manifest.json +74 -0
  155. package/templates/blocks/DD-TechStack/Component.tsx +168 -162
  156. package/templates/blocks/DD-TechStack/config.ts +153 -153
  157. package/templates/blocks/DD-TestMarq/Component.tsx +132 -0
  158. package/templates/blocks/DD-TestMarq/README.md +4 -0
  159. package/templates/blocks/DD-TestMarq/RowLabel.tsx +9 -0
  160. package/templates/blocks/DD-TestMarq/config.ts +88 -0
  161. package/templates/blocks/DD-TestMarq/manifest.json +72 -0
  162. package/templates/blocks/DD-Testim/Component.tsx +247 -0
  163. package/templates/blocks/DD-Testim/README.md +4 -0
  164. package/templates/blocks/DD-Testim/config.ts +101 -0
  165. package/templates/blocks/DD-Testim/manifest.json +75 -0
  166. package/templates/blocks/DD-Testim2/Component.tsx +256 -0
  167. package/templates/blocks/DD-Testim2/README.md +4 -0
  168. package/templates/blocks/DD-Testim2/config.ts +100 -0
  169. package/templates/blocks/DD-Testim2/manifest.json +74 -0
  170. package/templates/blocks/DD-Testimonials/Component.tsx +147 -147
  171. package/templates/blocks/DD-Testimonials/config.ts +120 -120
  172. package/templates/blocks/DD-TextMarq/Component.tsx +157 -0
  173. package/templates/blocks/DD-TextMarq/README.md +4 -0
  174. package/templates/blocks/DD-TextMarq/config.ts +237 -0
  175. package/templates/blocks/DD-TextMarq/manifest.json +82 -0
  176. package/templates/blocks/DD-Thanks/Component.tsx +500 -0
  177. package/templates/blocks/DD-Thanks/README.md +4 -0
  178. package/templates/blocks/DD-Thanks/config.ts +224 -0
  179. package/templates/blocks/DD-Thanks/manifest.json +72 -0
  180. package/templates/blocks/DD-VertMarq/Component.tsx +154 -0
  181. package/templates/blocks/DD-VertMarq/README.md +4 -0
  182. package/templates/blocks/DD-VertMarq/config.ts +236 -0
  183. package/templates/blocks/DD-VertMarq/dist/index.css +6 -0
  184. package/templates/blocks/DD-VertMarq/dist/index.min.css +1 -0
  185. package/templates/blocks/DD-VertMarq/manifest.json +74 -0
  186. package/templates/blocks/DD-Work/Component.tsx +318 -315
  187. package/templates/blocks/DD-Work/config.ts +165 -165
  188. package/templates/blocks/DD-Work-B/Component.tsx +294 -294
  189. package/templates/blocks/DDHG-CTASection2/Component.tsx +185 -0
  190. package/templates/blocks/DDHG-CTASection2/config.ts +140 -0
  191. package/templates/blocks/DDHG-CTASection2/manifest.json +45 -0
  192. package/templates/blocks/DDHG-HighlightArc/Component.tsx +243 -0
  193. package/templates/blocks/DDHG-HighlightArc/config.ts +85 -0
  194. package/templates/blocks/DDHG-HighlightArc/manifest.json +46 -0
  195. package/templates/blocks/DDHG-LogoMarquee/Component.tsx +93 -0
  196. package/templates/blocks/DDHG-LogoMarquee/config.ts +66 -0
  197. package/templates/blocks/DDHG-LogoMarquee/manifest.json +39 -0
  198. package/templates/blocks/DDHG-NavCodeGrid/Component.tsx +213 -0
  199. package/templates/blocks/DDHG-NavCodeGrid/config.ts +64 -0
  200. package/templates/blocks/DDHG-NavCodeGrid/manifest.json +45 -0
  201. package/templates/blocks/DDHG-ProcessSec/Component.tsx +575 -0
  202. package/templates/blocks/DDHG-ProcessSec/config.ts +170 -0
  203. package/templates/blocks/DDHG-ProcessSec/manifest.json +56 -0
  204. package/templates/blocks/DDHG-ServiceDetails/Component.tsx +164 -0
  205. package/templates/blocks/DDHG-ServiceDetails/ServiceDetailCard.tsx +394 -0
  206. package/templates/blocks/DDHG-ServiceDetails/config.ts +77 -0
  207. package/templates/blocks/DDHG-ServiceDetails/manifest.json +50 -0
  208. package/templates/blocks/DDHG-ServiceHero/Component.tsx +234 -0
  209. package/templates/blocks/DDHG-ServiceHero/config.ts +49 -0
  210. package/templates/blocks/DDHG-ServiceHero/manifest.json +26 -0
  211. package/templates/blocks/DDHG-ServiceOverview/Component.tsx +277 -0
  212. package/templates/blocks/DDHG-ServiceOverview/config.ts +64 -0
  213. package/templates/blocks/DDHG-ServiceOverview/manifest.json +44 -0
  214. package/templates/blocks/DDHG-StatsFAQ/Component.tsx +389 -0
  215. package/templates/blocks/DDHG-StatsFAQ/config.ts +204 -0
  216. package/templates/blocks/DDHG-StatsFAQ/manifest.json +45 -0
  217. package/templates/blocks/DDHG-TeamCards/Component.tsx +131 -0
  218. package/templates/blocks/DDHG-TeamCards/config.ts +48 -0
  219. package/templates/blocks/DDHG-TeamCards/manifest.json +29 -0
  220. package/templates/components/HeaderDD02/MobileBottomNav/index.tsx +352 -257
  221. package/templates/components/HeaderDD02/index.tsx +313 -229
  222. package/templates/shared/src/components/BgLightning/index.tsx +242 -0
  223. package/templates/shared/src/components/ui/ShareButton/index.tsx +80 -0
  224. package/templates/shared/src/components/ui/anims/FadeOnScroll.tsx +48 -0
  225. package/templates/shared/src/components/ui/anims/FadeUpOnInView.tsx +63 -0
  226. package/templates/shared/src/components/ui/anims/GlareHover.tsx +111 -0
  227. package/templates/shared/src/components/ui/anims/LineAnims.tsx +81 -0
  228. package/templates/shared/src/components/ui/anims/TitleAnims01.tsx +54 -0
  229. package/templates/shared/src/components/ui/anims/animation-container.tsx +29 -0
  230. package/templates/shared/src/components/ui/anims/blur-in.tsx +26 -0
  231. package/templates/shared/src/components/ui/anims/counter.tsx +53 -0
  232. package/templates/shared/src/components/ui/anims/fade.tsx +83 -0
  233. package/templates/shared/src/components/ui/anims/gradual-spacing.tsx +39 -0
  234. package/templates/shared/src/components/ui/anims/pull-up.tsx +93 -0
  235. package/templates/shared/src/components/ui/anims/reveal-text.tsx +76 -0
  236. package/templates/shared/src/components/ui/anims/rotate-words.tsx +43 -0
  237. package/templates/shared/src/components/ui/anims/shiny-text.tsx +58 -0
  238. package/templates/shared/src/components/ui/anims/shuffle-text.tsx +85 -0
  239. package/templates/shared/src/components/ui/anims/split-text.tsx +211 -0
  240. package/templates/shared/src/components/ui/anims/staggered-fade.tsx +133 -0
  241. package/templates/shared/src/components/ui/anims/text-scroll.tsx +111 -0
  242. package/templates/shared/src/components/ui/anims/typing-effect.tsx +112 -0
  243. package/templates/shared/src/components/ui/button-dusted-fluid/index.tsx +1521 -0
  244. package/templates/shared/src/components/ui/separator.tsx +85 -0
  245. package/templates/shared/src/hooks/useBodyScrollLock.ts +97 -0
  246. package/templates/shared/src/hooks/useClickOutside.ts +28 -0
  247. package/templates/shared/src/utilities/renderCustomCSS.ts +5 -0
  248. 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
+ }