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
@@ -0,0 +1,432 @@
1
+ /* eslint-disable react-hooks/set-state-in-effect */
2
+ /* eslint-disable @next/next/no-html-link-for-pages */
3
+ 'use client'
4
+
5
+ import * as React from 'react'
6
+ import { createPortal } from 'react-dom'
7
+ import { motion } from 'framer-motion'
8
+ import Link from 'next/link'
9
+ import { Tooltip, TooltipTrigger, TooltipPanel } from '../tooltip/tooltip'
10
+ import { TopLogoBgElement, BottomLogoBgElement } from './icons/custom-icons'
11
+ import { ArrowLeft, Circle } from 'lucide-react'
12
+
13
+ export type RadialNavItem = {
14
+ id: number
15
+ icon: React.ComponentType<{ size?: number; className?: string }>
16
+ label: string
17
+ angle: number
18
+ canvasId: string
19
+ }
20
+
21
+ type RadialNavProps = {
22
+ items: RadialNavItem[]
23
+ activeCanvasId: string
24
+ onCanvasChange: (canvasId: string) => void
25
+ }
26
+
27
+ type RadialNavInnerProps = RadialNavProps & {
28
+ isOpen: boolean
29
+ setIsOpen: React.Dispatch<React.SetStateAction<boolean>>
30
+ }
31
+
32
+ let mountedRadialNavCount = 0
33
+
34
+ function getPolarCoordinates(angleDeg: number, radius: number) {
35
+ const rad = ((angleDeg - 90) * Math.PI) / 180
36
+
37
+ return {
38
+ x: radius * Math.cos(rad),
39
+ y: radius * Math.sin(rad),
40
+ }
41
+ }
42
+
43
+ function useIsTouchMode() {
44
+ const [isTouchMode, setIsTouchMode] = React.useState(false)
45
+
46
+ React.useEffect(() => {
47
+ const checkTouchMode = () => {
48
+ setIsTouchMode(
49
+ window.matchMedia('(hover: none), (pointer: coarse)').matches ||
50
+ navigator.maxTouchPoints > 0,
51
+ )
52
+ }
53
+
54
+ checkTouchMode()
55
+
56
+ window.addEventListener('resize', checkTouchMode)
57
+
58
+ return () => {
59
+ window.removeEventListener('resize', checkTouchMode)
60
+ }
61
+ }, [])
62
+
63
+ return isTouchMode
64
+ }
65
+
66
+ function MorphCenterIcon() {
67
+ return <Circle aria-hidden="true" size={24} />
68
+ }
69
+
70
+ function RadialNavInner({
71
+ items,
72
+ activeCanvasId,
73
+ onCanvasChange,
74
+ isOpen,
75
+ setIsOpen,
76
+ }: RadialNavInnerProps) {
77
+ const size = 200
78
+ const orbitRadius = size / 2 - 2
79
+ const activeItem = items.find((item) => item.canvasId === activeCanvasId)
80
+ const rotateAngle = activeItem?.angle ?? 0
81
+
82
+ const closeTimerRef = React.useRef<number | null>(null)
83
+ const suppressOpenUntilRef = React.useRef(0)
84
+ const isTouchMode = useIsTouchMode()
85
+
86
+ const openRadialNav = () => {
87
+ if (Date.now() < suppressOpenUntilRef.current) return
88
+
89
+ if (closeTimerRef.current) {
90
+ window.clearTimeout(closeTimerRef.current)
91
+ closeTimerRef.current = null
92
+ }
93
+
94
+ setIsOpen(true)
95
+ }
96
+
97
+ const closeRadialNav = () => {
98
+ if (closeTimerRef.current) {
99
+ window.clearTimeout(closeTimerRef.current)
100
+ }
101
+
102
+ closeTimerRef.current = window.setTimeout(() => {
103
+ setIsOpen(false)
104
+ closeTimerRef.current = null
105
+ }, 500)
106
+ }
107
+
108
+ const handleCenterClick = () => {
109
+ if (isTouchMode) {
110
+ if (!isOpen) {
111
+ openRadialNav()
112
+ return
113
+ }
114
+
115
+ onCanvasChange('canvas_05')
116
+ setIsOpen(false)
117
+ return
118
+ }
119
+
120
+ onCanvasChange('canvas_05')
121
+ }
122
+
123
+ React.useEffect(() => {
124
+ return () => {
125
+ if (closeTimerRef.current) {
126
+ window.clearTimeout(closeTimerRef.current)
127
+ }
128
+ }
129
+ }, [])
130
+
131
+ return (
132
+ <>
133
+ <motion.div
134
+ animate={{
135
+ scale: isOpen ? 0.775 : 0.65,
136
+ y: isOpen ? '-1.5rem' : '0rem',
137
+ filter: isOpen ? 'brightness(0.8)' : 'brightness(1)',
138
+ borderWidth: isOpen ? '0px' : '2px',
139
+ borderColor: isOpen ? '#ffffff00' : '#808080',
140
+ borderStyle: 'solid',
141
+ }}
142
+ className={`hzRadialRoot hzRadialRoot--portal origin-center ${isOpen ? 'hzRadialNavIsOpen' : ''}`}
143
+ onBlur={(event) => {
144
+ if (!event.currentTarget.contains(event.relatedTarget as Node | null)) {
145
+ closeRadialNav()
146
+ }
147
+ }}
148
+ onFocus={() => {
149
+ if (!isTouchMode) {
150
+ openRadialNav()
151
+ }
152
+ }}
153
+ onMouseEnter={() => {
154
+ if (!isTouchMode) {
155
+ openRadialNav()
156
+ }
157
+ }}
158
+ onMouseLeave={() => {
159
+ if (!isTouchMode) {
160
+ closeRadialNav()
161
+ }
162
+ }}
163
+ tabIndex={0}
164
+ transition={{ type: 'spring', stiffness: 220, damping: 28 }}
165
+ >
166
+ <div className="radialNav-notification fixed left-1/2 top-1/2 mt-32 z-50 h-fit w-[min(50rem,calc(100vw-2rem))] -translate-x-1/2 translate-y-1/2 origin-center p-4 md:p-6 flex flex-col items-center justify-center rounded-2xl squircle shadow-3xl bg-7 text-md text-stone-200 border border-border">
167
+ <h4 className="tracking-wider font-semibold">NineCanvas layout demo</h4>
168
+ <p className="tracking-wider !text-[1.125rem]">
169
+ Explore all nine panels using the navigation or swipe between adjacent panels. Open the{' '}
170
+ <a
171
+ href="/backend-preview/ninecanvasblock"
172
+ className="text-underline !hover:text-accent font-semibold"
173
+ style={{ textDecoration: 'underline', textUnderlineOffset: '2px' }}
174
+ >
175
+ static configuration preview{' '}
176
+ </a>
177
+ to inspect the layout fields.
178
+ </p>
179
+ <Link
180
+ href="/nine-canvas"
181
+ aria-hidden={!isOpen}
182
+ aria-label="Return to main canvas"
183
+ className="relative w-fit flex gap-2 mt-8 items-center text-lime-500 scale-120 hover:gap-4 duration-300 hover:duration-300 hover:brightness-110"
184
+ onClick={() => {
185
+ onCanvasChange('canvas_05')
186
+ setIsOpen(false)
187
+ }}
188
+ onFocus={() => openRadialNav()}
189
+ onMouseEnter={() => {
190
+ if (!isTouchMode) {
191
+ openRadialNav()
192
+ }
193
+ }}
194
+ tabIndex={isOpen ? 0 : -1}
195
+ >
196
+ <ArrowLeft aria-hidden="true" size={18} strokeWidth={2.25} />
197
+ <span className="text-md font-semibold">Restart demo</span>
198
+ </Link>
199
+ </div>
200
+ <motion.div
201
+ animate={{
202
+ opacity: isOpen ? 0.8 : 0,
203
+ scale: isOpen ? 1.5 : 0.75,
204
+ }}
205
+ className="hzRadialBackdrop"
206
+ transition={{ type: 'spring', stiffness: 220, damping: 26 }}
207
+ />
208
+
209
+ {items.map((item) => {
210
+ const Icon = item.icon
211
+ const { x, y } = getPolarCoordinates(item.angle, orbitRadius)
212
+ const isActive = activeCanvasId === item.canvasId
213
+ const shouldShowActive = isActive || isOpen
214
+ const activeClosedOffsetY = 62
215
+ const activeClosedScale = 1.5
216
+
217
+ return (
218
+ <Tooltip key={item.id}>
219
+ <TooltipTrigger
220
+ render={
221
+ <motion.button
222
+ animate={{
223
+ left: `calc(50% + ${isOpen ? x : 0}px)`,
224
+ top: `calc(50% + ${isOpen ? y : isActive ? activeClosedOffsetY : 0}px)`,
225
+ opacity: shouldShowActive ? 1 : 0,
226
+ scale: isOpen ? 1 : isActive ? activeClosedScale : 0,
227
+ width: 42,
228
+ }}
229
+ aria-label={item.label}
230
+ className={[
231
+ 'hzRadialItem group',
232
+ `hzRadialItem--${item.canvasId}`,
233
+ `hzRadialItem--id-${item.id}`,
234
+ isActive ? 'hzRadialItem--active' : '',
235
+ !isOpen && !isActive ? 'hzRadialItem--closed' : '',
236
+ ]
237
+ .filter(Boolean)
238
+ .join(' ')}
239
+ key={item.id}
240
+ onClick={(event) => {
241
+ event.currentTarget.blur()
242
+ onCanvasChange(item.canvasId)
243
+ suppressOpenUntilRef.current = Date.now() + 700
244
+ setIsOpen(false)
245
+ }}
246
+ transition={{ type: 'spring', stiffness: 220, damping: 28 }}
247
+ type="button"
248
+ >
249
+ <Icon size={16} />
250
+ </motion.button>
251
+ }
252
+ />
253
+
254
+ <TooltipPanel className="hzTooltipPanel">
255
+ <p>{item.label}</p>
256
+ </TooltipPanel>
257
+ </Tooltip>
258
+ )
259
+ })}
260
+
261
+ <Tooltip>
262
+ <TooltipTrigger
263
+ render={
264
+ <button
265
+ aria-expanded={isOpen}
266
+ aria-label={isOpen ? 'Go to Canvas 5' : 'Open Canvas navigation'}
267
+ className={`hzRadialCenterButton ${
268
+ activeCanvasId === 'canvas_05' ? 'hzRadialCenterButton--active' : ''
269
+ }`}
270
+ onClick={handleCenterClick}
271
+ type="button"
272
+ >
273
+ <motion.div
274
+ animate={{ rotate: isOpen ? rotateAngle : 0 }}
275
+ className="hzRadialCenterButtonIcon"
276
+ transition={{ type: 'spring', stiffness: 220, damping: 26 }}
277
+ >
278
+ <MorphCenterIcon />
279
+ </motion.div>
280
+ </button>
281
+ }
282
+ />
283
+
284
+ <TooltipPanel className="hzTooltipPanel">
285
+ <p>Canvas 5</p>
286
+ </TooltipPanel>
287
+ </Tooltip>
288
+
289
+ {/* <motion.div
290
+ animate={{
291
+ opacity: isOpen ? 1 : 0,
292
+ scale: isOpen ? 1 : 0.7,
293
+ y: isOpen ? 0 : -8,
294
+ x: isOpen ? 0 : -32
295
+ }}
296
+ transition={{ type: 'spring', stiffness: 260, damping: 24 }}
297
+ >
298
+ <Link
299
+ href="/nine-canvas"
300
+ aria-hidden={!isOpen}
301
+ aria-label="Return to main canvas"
302
+ className="hzRadialReturnButton hidden md:flex"
303
+ onClick={() => {
304
+ onCanvasChange('canvas_05')
305
+ setIsOpen(false)
306
+ }}
307
+ onFocus={() => openRadialNav()}
308
+ onMouseEnter={() => {
309
+ if (!isTouchMode) {
310
+ openRadialNav()
311
+ }
312
+ }}
313
+ tabIndex={isOpen ? 0 : -1}
314
+ >
315
+ <ArrowLeft aria-hidden="true" size={18} strokeWidth={2.25} />
316
+ <span className="text-xs text-stone-200">Exit Overview-Mode</span>
317
+ </Link>
318
+ </motion.div> */}
319
+ </motion.div>
320
+ </>
321
+ )
322
+ }
323
+
324
+ export function RadialNav(props: RadialNavProps) {
325
+ const [mounted, setMounted] = React.useState(false)
326
+ const [isOpen, setIsOpen] = React.useState(false)
327
+
328
+ const lastScrollYRef = React.useRef(0)
329
+
330
+ React.useEffect(() => {
331
+ setMounted(true)
332
+ lastScrollYRef.current = window.scrollY
333
+
334
+ mountedRadialNavCount += 1
335
+ document.body.classList.add('hasRadialNav')
336
+
337
+ return () => {
338
+ mountedRadialNavCount = Math.max(0, mountedRadialNavCount - 1)
339
+
340
+ if (mountedRadialNavCount === 0) {
341
+ document.body.classList.remove('hasRadialNav')
342
+ document.body.classList.remove('hasRadialNavOpen')
343
+ }
344
+ }
345
+ }, [])
346
+
347
+ React.useEffect(() => {
348
+ if (!mounted) return
349
+
350
+ const desktopMedia = window.matchMedia('(min-width: 768px)')
351
+
352
+ const handleVerticalMotion = (deltaY: number) => {
353
+ if (!desktopMedia.matches) return
354
+
355
+ if (deltaY > 8) {
356
+ setIsOpen(true)
357
+ } else if (deltaY < -8) {
358
+ setIsOpen(false)
359
+ }
360
+ }
361
+
362
+ const handleScroll = () => {
363
+ const scrollY = window.scrollY
364
+ const deltaY = scrollY - lastScrollYRef.current
365
+
366
+ handleVerticalMotion(deltaY)
367
+
368
+ lastScrollYRef.current = Math.max(0, scrollY)
369
+ }
370
+
371
+ const handleWheel = (event: WheelEvent) => {
372
+ handleVerticalMotion(event.deltaY)
373
+ }
374
+
375
+ const handleCanvasScrollDown = () => {
376
+ if (!desktopMedia.matches) return
377
+
378
+ setIsOpen(true)
379
+ }
380
+
381
+ const handleBreakpointChange = () => {
382
+ lastScrollYRef.current = window.scrollY
383
+ }
384
+
385
+ window.addEventListener('scroll', handleScroll, { passive: true })
386
+
387
+ window.addEventListener('hz:canvas-scroll-down', handleCanvasScrollDown)
388
+
389
+ document.addEventListener('wheel', handleWheel, {
390
+ capture: true,
391
+ passive: true,
392
+ })
393
+
394
+ desktopMedia.addEventListener('change', handleBreakpointChange)
395
+
396
+ return () => {
397
+ window.removeEventListener('scroll', handleScroll)
398
+
399
+ window.removeEventListener('hz:canvas-scroll-down', handleCanvasScrollDown)
400
+
401
+ document.removeEventListener('wheel', handleWheel, {
402
+ capture: true,
403
+ })
404
+
405
+ desktopMedia.removeEventListener('change', handleBreakpointChange)
406
+ }
407
+ }, [mounted])
408
+
409
+ React.useEffect(() => {
410
+ if (isOpen) {
411
+ document.body.classList.add('hasRadialNavOpen')
412
+ } else {
413
+ document.body.classList.remove('hasRadialNavOpen')
414
+ }
415
+
416
+ return () => {
417
+ document.body.classList.remove('hasRadialNavOpen')
418
+ }
419
+ }, [isOpen])
420
+
421
+ if (!mounted) return null
422
+
423
+ return createPortal(
424
+ <>
425
+ <TopLogoBgElement />
426
+
427
+ <RadialNavInner {...props} isOpen={isOpen} setIsOpen={setIsOpen} />
428
+ <BottomLogoBgElement />
429
+ </>,
430
+ document.body,
431
+ )
432
+ }