@nastechai-research/ui 0.18.2

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 (352) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +21 -0
  3. package/dist/assets/filler-bg0.webp +0 -0
  4. package/dist/assets.d.ts +38 -0
  5. package/dist/fonts/Collapse-Bold.woff2 +0 -0
  6. package/dist/fonts/Collapse-BoldItalic.woff2 +0 -0
  7. package/dist/fonts/Collapse-Italic.woff2 +0 -0
  8. package/dist/fonts/Collapse-Light.woff2 +0 -0
  9. package/dist/fonts/Collapse-LightItalic.woff2 +0 -0
  10. package/dist/fonts/Collapse-Regular.woff2 +0 -0
  11. package/dist/fonts/Collapse-Thin.woff2 +0 -0
  12. package/dist/fonts/Collapse-ThinItalic.woff2 +0 -0
  13. package/dist/fonts/Mondwest-Regular.woff2 +0 -0
  14. package/dist/fonts/Neuebit-Bold.woff2 +0 -0
  15. package/dist/fonts/RulesCompressed-Medium.woff2 +0 -0
  16. package/dist/fonts/RulesCompressed-Regular.woff2 +0 -0
  17. package/dist/fonts/RulesExpanded-Bold.woff2 +0 -0
  18. package/dist/fonts/RulesExpanded-Regular.woff2 +0 -0
  19. package/dist/fonts.d.ts +6 -0
  20. package/dist/fonts.js +6 -0
  21. package/dist/hooks/use-below-breakpoint.d.ts +2 -0
  22. package/dist/hooks/use-below-breakpoint.js +17 -0
  23. package/dist/hooks/use-capped-frame.d.ts +2 -0
  24. package/dist/hooks/use-capped-frame.js +15 -0
  25. package/dist/hooks/use-confirm-delete.d.ts +10 -0
  26. package/dist/hooks/use-confirm-delete.js +35 -0
  27. package/dist/hooks/use-css-var-dims.d.ts +1 -0
  28. package/dist/hooks/use-css-var-dims.js +29 -0
  29. package/dist/hooks/use-gpu-tier.d.ts +34 -0
  30. package/dist/hooks/use-gpu-tier.js +111 -0
  31. package/dist/hooks/use-render-loop.d.ts +41 -0
  32. package/dist/hooks/use-render-loop.js +63 -0
  33. package/dist/hooks/use-smooth-controls.d.ts +16 -0
  34. package/dist/hooks/use-smooth-controls.js +217 -0
  35. package/dist/hooks/use-toast.d.ts +7 -0
  36. package/dist/hooks/use-toast.js +21 -0
  37. package/dist/index.d.ts +79 -0
  38. package/dist/index.js +107 -0
  39. package/dist/ui/basic-page.d.ts +7 -0
  40. package/dist/ui/basic-page.js +18 -0
  41. package/dist/ui/build.css +4 -0
  42. package/dist/ui/components/animated-count.d.ts +10 -0
  43. package/dist/ui/components/animated-count.js +113 -0
  44. package/dist/ui/components/ascii.d.ts +10 -0
  45. package/dist/ui/components/ascii.js +79 -0
  46. package/dist/ui/components/badge.d.ts +6 -0
  47. package/dist/ui/components/badge.js +40 -0
  48. package/dist/ui/components/badges/nous-girl.d.ts +2 -0
  49. package/dist/ui/components/badges/nous-girl.js +83 -0
  50. package/dist/ui/components/blend-mode.d.ts +28 -0
  51. package/dist/ui/components/blend-mode.js +69 -0
  52. package/dist/ui/components/blink.d.ts +6 -0
  53. package/dist/ui/components/blink.js +17 -0
  54. package/dist/ui/components/bottom-sheet.d.ts +15 -0
  55. package/dist/ui/components/bottom-sheet.js +192 -0
  56. package/dist/ui/components/button.d.ts +14 -0
  57. package/dist/ui/components/button.js +147 -0
  58. package/dist/ui/components/card.d.ts +5 -0
  59. package/dist/ui/components/card.js +74 -0
  60. package/dist/ui/components/checkbox.d.ts +2 -0
  61. package/dist/ui/components/checkbox.js +27 -0
  62. package/dist/ui/components/command-block.d.ts +24 -0
  63. package/dist/ui/components/command-block.js +56 -0
  64. package/dist/ui/components/confirm-dialog.d.ts +13 -0
  65. package/dist/ui/components/confirm-dialog.js +113 -0
  66. package/dist/ui/components/cursor.d.ts +3 -0
  67. package/dist/ui/components/cursor.js +97 -0
  68. package/dist/ui/components/dialog.d.ts +15 -0
  69. package/dist/ui/components/dialog.js +171 -0
  70. package/dist/ui/components/dropdown-menu.d.ts +12 -0
  71. package/dist/ui/components/dropdown-menu.js +102 -0
  72. package/dist/ui/components/fit-text/fit-text.css +42 -0
  73. package/dist/ui/components/fit-text/index.d.ts +9 -0
  74. package/dist/ui/components/fit-text/index.js +25 -0
  75. package/dist/ui/components/graphs/bar-chart.d.ts +12 -0
  76. package/dist/ui/components/graphs/bar-chart.js +129 -0
  77. package/dist/ui/components/graphs/index.d.ts +3 -0
  78. package/dist/ui/components/graphs/index.js +4 -0
  79. package/dist/ui/components/graphs/line-chart.d.ts +14 -0
  80. package/dist/ui/components/graphs/line-chart.js +175 -0
  81. package/dist/ui/components/graphs/utils.d.ts +52 -0
  82. package/dist/ui/components/graphs/utils.js +162 -0
  83. package/dist/ui/components/grid/grid.css +79 -0
  84. package/dist/ui/components/grid/index.d.ts +2 -0
  85. package/dist/ui/components/grid/index.js +17 -0
  86. package/dist/ui/components/hover-bg.d.ts +1 -0
  87. package/dist/ui/components/hover-bg.js +14 -0
  88. package/dist/ui/components/icons/arrow.d.ts +6 -0
  89. package/dist/ui/components/icons/arrow.js +44 -0
  90. package/dist/ui/components/icons/check.d.ts +2 -0
  91. package/dist/ui/components/icons/check.js +13 -0
  92. package/dist/ui/components/icons/chevron.d.ts +6 -0
  93. package/dist/ui/components/icons/chevron.js +51 -0
  94. package/dist/ui/components/icons/discord.d.ts +2 -0
  95. package/dist/ui/components/icons/discord.js +15 -0
  96. package/dist/ui/components/icons/eye.d.ts +2 -0
  97. package/dist/ui/components/icons/eye.js +8 -0
  98. package/dist/ui/components/icons/gear.d.ts +6 -0
  99. package/dist/ui/components/icons/gear.js +30 -0
  100. package/dist/ui/components/icons/github.d.ts +2 -0
  101. package/dist/ui/components/icons/github.js +15 -0
  102. package/dist/ui/components/icons/hamburger.d.ts +6 -0
  103. package/dist/ui/components/icons/hamburger.js +56 -0
  104. package/dist/ui/components/icons/heart.d.ts +2 -0
  105. package/dist/ui/components/icons/heart.js +11 -0
  106. package/dist/ui/components/icons/index.d.ts +12 -0
  107. package/dist/ui/components/icons/index.js +13 -0
  108. package/dist/ui/components/icons/link.d.ts +2 -0
  109. package/dist/ui/components/icons/link.js +13 -0
  110. package/dist/ui/components/icons/minus.d.ts +2 -0
  111. package/dist/ui/components/icons/minus.js +13 -0
  112. package/dist/ui/components/icons/search.d.ts +2 -0
  113. package/dist/ui/components/icons/search.js +33 -0
  114. package/dist/ui/components/image-distortion.d.ts +21 -0
  115. package/dist/ui/components/image-distortion.js +398 -0
  116. package/dist/ui/components/input.d.ts +1 -0
  117. package/dist/ui/components/input.js +21 -0
  118. package/dist/ui/components/label.d.ts +1 -0
  119. package/dist/ui/components/label.js +18 -0
  120. package/dist/ui/components/leva-client.d.ts +1 -0
  121. package/dist/ui/components/leva-client.js +12 -0
  122. package/dist/ui/components/list-item.d.ts +6 -0
  123. package/dist/ui/components/list-item.js +27 -0
  124. package/dist/ui/components/overlays/blend-modes.d.ts +1 -0
  125. package/dist/ui/components/overlays/blend-modes.js +14 -0
  126. package/dist/ui/components/overlays/glitch.d.ts +6 -0
  127. package/dist/ui/components/overlays/glitch.js +209 -0
  128. package/dist/ui/components/overlays/greys.d.ts +6 -0
  129. package/dist/ui/components/overlays/greys.js +339 -0
  130. package/dist/ui/components/overlays/index.d.ts +14 -0
  131. package/dist/ui/components/overlays/index.js +34 -0
  132. package/dist/ui/components/overlays/lens-layers.d.ts +14 -0
  133. package/dist/ui/components/overlays/lens-layers.js +95 -0
  134. package/dist/ui/components/overlays/lens.d.ts +44 -0
  135. package/dist/ui/components/overlays/lens.js +60 -0
  136. package/dist/ui/components/overlays/noise.d.ts +6 -0
  137. package/dist/ui/components/overlays/noise.js +136 -0
  138. package/dist/ui/components/overlays/vignette.d.ts +6 -0
  139. package/dist/ui/components/overlays/vignette.js +47 -0
  140. package/dist/ui/components/poster.d.ts +62 -0
  141. package/dist/ui/components/poster.js +256 -0
  142. package/dist/ui/components/progress.d.ts +9 -0
  143. package/dist/ui/components/progress.js +53 -0
  144. package/dist/ui/components/scene-canvas.d.ts +23 -0
  145. package/dist/ui/components/scene-canvas.js +179 -0
  146. package/dist/ui/components/scramble.d.ts +9 -0
  147. package/dist/ui/components/scramble.js +63 -0
  148. package/dist/ui/components/segmented.d.ts +20 -0
  149. package/dist/ui/components/segmented.js +51 -0
  150. package/dist/ui/components/select.d.ts +18 -0
  151. package/dist/ui/components/select.js +215 -0
  152. package/dist/ui/components/selection-switcher.d.ts +1 -0
  153. package/dist/ui/components/selection-switcher.js +34 -0
  154. package/dist/ui/components/separator.d.ts +5 -0
  155. package/dist/ui/components/separator.js +22 -0
  156. package/dist/ui/components/shader.d.ts +7 -0
  157. package/dist/ui/components/shader.js +60 -0
  158. package/dist/ui/components/socials.d.ts +20 -0
  159. package/dist/ui/components/socials.js +21 -0
  160. package/dist/ui/components/spinner.d.ts +20 -0
  161. package/dist/ui/components/spinner.js +38 -0
  162. package/dist/ui/components/stats.d.ts +16 -0
  163. package/dist/ui/components/stats.js +36 -0
  164. package/dist/ui/components/switch.d.ts +7 -0
  165. package/dist/ui/components/switch.js +37 -0
  166. package/dist/ui/components/tabs.d.ts +14 -0
  167. package/dist/ui/components/tabs.js +44 -0
  168. package/dist/ui/components/terminal-demo.d.ts +32 -0
  169. package/dist/ui/components/terminal-demo.js +125 -0
  170. package/dist/ui/components/theme-toggle.d.ts +6 -0
  171. package/dist/ui/components/theme-toggle.js +66 -0
  172. package/dist/ui/components/tier-card.d.ts +53 -0
  173. package/dist/ui/components/tier-card.js +146 -0
  174. package/dist/ui/components/toast.d.ts +8 -0
  175. package/dist/ui/components/toast.js +39 -0
  176. package/dist/ui/components/tv.d.ts +3 -0
  177. package/dist/ui/components/tv.js +239 -0
  178. package/dist/ui/components/typography/h1.d.ts +11 -0
  179. package/dist/ui/components/typography/h1.js +18 -0
  180. package/dist/ui/components/typography/h2.d.ts +11 -0
  181. package/dist/ui/components/typography/h2.js +18 -0
  182. package/dist/ui/components/typography/index.d.ts +15 -0
  183. package/dist/ui/components/typography/index.js +41 -0
  184. package/dist/ui/components/typography/legend.d.ts +6 -0
  185. package/dist/ui/components/typography/legend.js +20 -0
  186. package/dist/ui/components/typography/small.d.ts +2 -0
  187. package/dist/ui/components/typography/small.js +9 -0
  188. package/dist/ui/components/watchlist.d.ts +11 -0
  189. package/dist/ui/components/watchlist.js +80 -0
  190. package/dist/ui/fonts.css +63 -0
  191. package/dist/ui/footer.d.ts +20 -0
  192. package/dist/ui/footer.js +65 -0
  193. package/dist/ui/globals.css +395 -0
  194. package/dist/ui/header.d.ts +41 -0
  195. package/dist/ui/header.js +270 -0
  196. package/dist/ui/layout-wrapper.d.ts +1 -0
  197. package/dist/ui/layout-wrapper.js +7 -0
  198. package/dist/utils/color.d.ts +4 -0
  199. package/dist/utils/color.js +14 -0
  200. package/dist/utils/index.d.ts +15 -0
  201. package/dist/utils/index.js +48 -0
  202. package/dist/utils/poly.d.ts +8 -0
  203. package/dist/utils/poly.js +3 -0
  204. package/package.json +120 -0
  205. package/src/assets/filler-bg0.webp +0 -0
  206. package/src/assets.d.ts +38 -0
  207. package/src/fonts/Collapse-Bold.woff2 +0 -0
  208. package/src/fonts/Collapse-BoldItalic.woff2 +0 -0
  209. package/src/fonts/Collapse-Italic.woff2 +0 -0
  210. package/src/fonts/Collapse-Light.woff2 +0 -0
  211. package/src/fonts/Collapse-LightItalic.woff2 +0 -0
  212. package/src/fonts/Collapse-Regular.woff2 +0 -0
  213. package/src/fonts/Collapse-Thin.woff2 +0 -0
  214. package/src/fonts/Collapse-ThinItalic.woff2 +0 -0
  215. package/src/fonts/Mondwest-Regular.woff2 +0 -0
  216. package/src/fonts/Neuebit-Bold.woff2 +0 -0
  217. package/src/fonts/RulesCompressed-Medium.woff2 +0 -0
  218. package/src/fonts/RulesCompressed-Regular.woff2 +0 -0
  219. package/src/fonts/RulesExpanded-Bold.woff2 +0 -0
  220. package/src/fonts/RulesExpanded-Regular.woff2 +0 -0
  221. package/src/fonts.ts +6 -0
  222. package/src/hooks/use-below-breakpoint.ts +21 -0
  223. package/src/hooks/use-capped-frame.ts +18 -0
  224. package/src/hooks/use-confirm-delete.ts +43 -0
  225. package/src/hooks/use-css-var-dims.ts +39 -0
  226. package/src/hooks/use-gpu-tier.ts +190 -0
  227. package/src/hooks/use-render-loop.ts +121 -0
  228. package/src/hooks/use-smooth-controls.ts +318 -0
  229. package/src/hooks/use-toast.ts +29 -0
  230. package/src/index.ts +130 -0
  231. package/src/ui/basic-page.tsx +34 -0
  232. package/src/ui/build.css +4 -0
  233. package/src/ui/components/animated-count.stories.tsx +67 -0
  234. package/src/ui/components/animated-count.tsx +168 -0
  235. package/src/ui/components/ascii.stories.tsx +30 -0
  236. package/src/ui/components/ascii.tsx +110 -0
  237. package/src/ui/components/badge.stories.tsx +31 -0
  238. package/src/ui/components/badge.tsx +60 -0
  239. package/src/ui/components/badges/nous-girl.tsx +52 -0
  240. package/src/ui/components/blend-mode.stories.tsx +33 -0
  241. package/src/ui/components/blend-mode.tsx +129 -0
  242. package/src/ui/components/blink.stories.tsx +32 -0
  243. package/src/ui/components/blink.tsx +21 -0
  244. package/src/ui/components/bottom-sheet.stories.tsx +43 -0
  245. package/src/ui/components/bottom-sheet.tsx +227 -0
  246. package/src/ui/components/button.stories.tsx +68 -0
  247. package/src/ui/components/button.tsx +170 -0
  248. package/src/ui/components/card.stories.tsx +63 -0
  249. package/src/ui/components/card.tsx +85 -0
  250. package/src/ui/components/checkbox.stories.tsx +113 -0
  251. package/src/ui/components/checkbox.tsx +36 -0
  252. package/src/ui/components/command-block.stories.tsx +52 -0
  253. package/src/ui/components/command-block.tsx +86 -0
  254. package/src/ui/components/confirm-dialog.stories.tsx +91 -0
  255. package/src/ui/components/confirm-dialog.tsx +130 -0
  256. package/src/ui/components/cursor.tsx +115 -0
  257. package/src/ui/components/dialog.stories.tsx +169 -0
  258. package/src/ui/components/dialog.tsx +177 -0
  259. package/src/ui/components/dropdown-menu.stories.tsx +52 -0
  260. package/src/ui/components/dropdown-menu.tsx +117 -0
  261. package/src/ui/components/fit-text/fit-text.css +42 -0
  262. package/src/ui/components/fit-text/index.stories.tsx +33 -0
  263. package/src/ui/components/fit-text/index.tsx +45 -0
  264. package/src/ui/components/forms.stories.tsx +173 -0
  265. package/src/ui/components/graphs/bar-chart.tsx +153 -0
  266. package/src/ui/components/graphs/index.stories.tsx +64 -0
  267. package/src/ui/components/graphs/index.tsx +4 -0
  268. package/src/ui/components/graphs/line-chart.tsx +213 -0
  269. package/src/ui/components/graphs/utils.tsx +265 -0
  270. package/src/ui/components/grid/grid.css +79 -0
  271. package/src/ui/components/grid/index.tsx +19 -0
  272. package/src/ui/components/hover-bg.stories.tsx +29 -0
  273. package/src/ui/components/hover-bg.tsx +15 -0
  274. package/src/ui/components/icons/arrow.tsx +42 -0
  275. package/src/ui/components/icons/check.tsx +14 -0
  276. package/src/ui/components/icons/chevron.tsx +45 -0
  277. package/src/ui/components/icons/discord.tsx +16 -0
  278. package/src/ui/components/icons/eye.tsx +12 -0
  279. package/src/ui/components/icons/gear.tsx +51 -0
  280. package/src/ui/components/icons/github.tsx +16 -0
  281. package/src/ui/components/icons/hamburger.tsx +52 -0
  282. package/src/ui/components/icons/heart.tsx +12 -0
  283. package/src/ui/components/icons/index.ts +12 -0
  284. package/src/ui/components/icons/link.tsx +14 -0
  285. package/src/ui/components/icons/minus.tsx +14 -0
  286. package/src/ui/components/icons/search.tsx +28 -0
  287. package/src/ui/components/image-distortion.stories.tsx +120 -0
  288. package/src/ui/components/image-distortion.tsx +499 -0
  289. package/src/ui/components/input.stories.tsx +39 -0
  290. package/src/ui/components/input.tsx +20 -0
  291. package/src/ui/components/label.stories.tsx +26 -0
  292. package/src/ui/components/label.tsx +16 -0
  293. package/src/ui/components/leva-client.tsx +14 -0
  294. package/src/ui/components/list-item.stories.tsx +83 -0
  295. package/src/ui/components/list-item.tsx +37 -0
  296. package/src/ui/components/overlays/blend-modes.ts +13 -0
  297. package/src/ui/components/overlays/glitch.tsx +243 -0
  298. package/src/ui/components/overlays/greys.tsx +386 -0
  299. package/src/ui/components/overlays/index.tsx +47 -0
  300. package/src/ui/components/overlays/lens-layers.tsx +121 -0
  301. package/src/ui/components/overlays/lens.ts +91 -0
  302. package/src/ui/components/overlays/noise.tsx +174 -0
  303. package/src/ui/components/overlays/vignette.tsx +60 -0
  304. package/src/ui/components/poster.stories.tsx +513 -0
  305. package/src/ui/components/poster.tsx +411 -0
  306. package/src/ui/components/progress.stories.tsx +48 -0
  307. package/src/ui/components/progress.tsx +56 -0
  308. package/src/ui/components/scene-canvas.tsx +254 -0
  309. package/src/ui/components/scramble.stories.tsx +49 -0
  310. package/src/ui/components/scramble.tsx +95 -0
  311. package/src/ui/components/segmented.stories.tsx +101 -0
  312. package/src/ui/components/segmented.tsx +81 -0
  313. package/src/ui/components/select.stories.tsx +88 -0
  314. package/src/ui/components/select.tsx +267 -0
  315. package/src/ui/components/selection-switcher.tsx +44 -0
  316. package/src/ui/components/separator.stories.tsx +33 -0
  317. package/src/ui/components/separator.tsx +24 -0
  318. package/src/ui/components/shader.tsx +83 -0
  319. package/src/ui/components/socials.tsx +42 -0
  320. package/src/ui/components/spinner.stories.tsx +101 -0
  321. package/src/ui/components/spinner.tsx +60 -0
  322. package/src/ui/components/stats.stories.tsx +24 -0
  323. package/src/ui/components/stats.tsx +53 -0
  324. package/src/ui/components/switch.stories.tsx +77 -0
  325. package/src/ui/components/switch.tsx +48 -0
  326. package/src/ui/components/tabs.stories.tsx +101 -0
  327. package/src/ui/components/tabs.tsx +66 -0
  328. package/src/ui/components/terminal-demo.stories.tsx +67 -0
  329. package/src/ui/components/terminal-demo.tsx +189 -0
  330. package/src/ui/components/theme-toggle.stories.tsx +47 -0
  331. package/src/ui/components/theme-toggle.tsx +66 -0
  332. package/src/ui/components/tier-card.stories.tsx +217 -0
  333. package/src/ui/components/tier-card.tsx +190 -0
  334. package/src/ui/components/toast.stories.tsx +55 -0
  335. package/src/ui/components/toast.tsx +49 -0
  336. package/src/ui/components/tv.stories.tsx +37 -0
  337. package/src/ui/components/tv.tsx +257 -0
  338. package/src/ui/components/typography/h1.tsx +18 -0
  339. package/src/ui/components/typography/h2.tsx +18 -0
  340. package/src/ui/components/typography/index.tsx +54 -0
  341. package/src/ui/components/typography/legend.tsx +24 -0
  342. package/src/ui/components/typography/small.tsx +11 -0
  343. package/src/ui/components/watchlist.stories.tsx +33 -0
  344. package/src/ui/components/watchlist.tsx +105 -0
  345. package/src/ui/fonts.css +63 -0
  346. package/src/ui/footer.tsx +111 -0
  347. package/src/ui/globals.css +395 -0
  348. package/src/ui/header.tsx +398 -0
  349. package/src/ui/layout-wrapper.tsx +11 -0
  350. package/src/utils/color.ts +21 -0
  351. package/src/utils/index.ts +62 -0
  352. package/src/utils/poly.ts +26 -0
@@ -0,0 +1,257 @@
1
+ 'use client'
2
+
3
+ import { useEffect, useRef } from 'react'
4
+
5
+ const VERT = /* glsl */ `attribute vec2 a;void main(){gl_Position=vec4(a,0,1);}`
6
+
7
+ const FRAG = /* glsl */ `precision highp float;
8
+ uniform float t;
9
+ uniform vec2 r;
10
+
11
+ const float FBM_STR = .08;
12
+
13
+ float h(vec2 p) { return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453); }
14
+
15
+ float n2(vec2 p) {
16
+ vec2 i = floor(p), f = fract(p);
17
+ f = f * f * (3. - 2. * f);
18
+
19
+ return mix(
20
+ mix(h(i), h(i + vec2(1, 0)), f.x),
21
+ mix(h(i + vec2(0, 1)), h(i + vec2(1, 1)), f.x),
22
+ f.y
23
+ );
24
+ }
25
+
26
+ float fbm(vec2 p) {
27
+ float v = 0., a = .5;
28
+
29
+ for (int i = 0; i < 4; i++) {
30
+ v += a * n2(p);
31
+ p *= 2.1;
32
+ a *= .45;
33
+ }
34
+
35
+ return v;
36
+ }
37
+
38
+ float drift(float speed, float s) {
39
+ return fract(t * speed + s + .02 * sin(t * .4 + s * 3.));
40
+ }
41
+
42
+ float brushAt(vec2 uv, float y, float th, float s) {
43
+ float hw = .34 + .08 * h(vec2(s, 77.));
44
+ float cx = .5;
45
+ float xn = (uv.x - (cx - hw)) / (2. * hw);
46
+ float env = smoothstep(0., .03, xn) * smoothstep(1., .97, xn);
47
+ float localTh = th * env;
48
+
49
+ if (localTh < .002) return 0.;
50
+
51
+ float morph = floor(t * 8.) * .7 + s;
52
+ float top = y - localTh * .5 + fbm(vec2(uv.x * 6., morph)) * FBM_STR;
53
+ float bot = y + localTh * .5 - fbm(vec2(uv.x * 6., morph + 30.)) * FBM_STR;
54
+ float x0 = cx - hw + fbm(vec2(uv.y * 8., morph + 60.)) * FBM_STR;
55
+ float x1 = cx + hw - fbm(vec2(uv.y * 8., morph + 90.)) * FBM_STR;
56
+
57
+ float dMin = min(min(uv.y - top, bot - uv.y), min(uv.x - x0, x1 - uv.x));
58
+
59
+ float bristle = n2(vec2(uv.x * 60., uv.y * 8. + s)) * .4
60
+ + n2(vec2(uv.x * 25., (uv.y - y) * 120. + s)) * .35
61
+ + n2(vec2(uv.x * 90., uv.y * 3. + s * 2.)) * .25;
62
+
63
+ float eaten = smoothstep(.03, 0., dMin) * (1. - smoothstep(.2, .5, bristle));
64
+
65
+ return clamp(smoothstep(0., .003, dMin) * (1. - eaten), 0., 1.);
66
+ }
67
+
68
+ void main() {
69
+ vec2 uv = gl_FragCoord.xy / r;
70
+ uv = vec2(uv.x * cos(.095) - uv.y * sin(.095), uv.x * sin(.095) + uv.y * cos(.095));
71
+ uv += vec2(fbm(uv * 4. + t * .06), fbm(uv * 4. + 8. + t * .05)) * .012;
72
+
73
+ vec3 c = vec3(.992, .992, .051);
74
+
75
+ float smScroll = -drift(.04, 5.) * 2.;
76
+ float sm = 0.;
77
+
78
+ for (int i = 0; i < 20; i++) {
79
+ sm = max(sm, brushAt(uv, mod(float(i) * .1 + smScroll, 2.) - .5, .04, float(i) + 10.));
80
+ }
81
+
82
+ float d1 = drift(.15, 1.), d2 = drift(.15, 1.37), d3 = drift(.15, 1.58), d4 = drift(.15, 1.82);
83
+ float big = max(
84
+ max(brushAt(uv, 1.1 - d1 * 1.4, .28, 1.), brushAt(uv, 1.1 - d2 * 1.4, .18, 2.)),
85
+ max(brushAt(uv, 1.1 - d3 * 1.4, .3, 3.), brushAt(uv, 1.1 - d4 * 1.4, .15, 4.))
86
+ );
87
+
88
+ c = mix(c, vec3(0.), clamp(max(sm, big), 0., 1.));
89
+ c *= .94 + .06 * sin(uv.y * r.y * 6.283);
90
+
91
+ vec2 raw = gl_FragCoord.xy / r;
92
+ float dx = min(raw.x - .22, .90 - raw.x);
93
+ float dy = min(raw.y - .29, .86 - raw.y);
94
+ float cycle = floor(t * .4);
95
+ float edge = mix(smoothstep(.22, 0., max(min(dx, dy), 0.)), 1., step(.75, h(vec2(cycle, 13.))))
96
+ * smoothstep(.85, 1., sin(t * 2.5) * .5 + .5)
97
+ * (.7 + .3 * h(vec2(cycle, 7.)));
98
+
99
+ float scanY = floor(gl_FragCoord.y);
100
+ float rowNoise = h(vec2(scanY, floor(t * 30.)));
101
+ c *= 1. - edge * max(step(.45, rowNoise), step(.3, h(vec2(gl_FragCoord.x + scanY * 7., floor(t * 45.)))) * step(.2, rowNoise));
102
+
103
+ gl_FragColor = vec4(clamp(c, 0., 1.), 1.);
104
+ }`
105
+
106
+ function useGL(ref: React.RefObject<HTMLCanvasElement | null>) {
107
+ const raf = useRef(0)
108
+
109
+ useEffect(() => {
110
+ const c = ref.current
111
+
112
+ if (!c) {
113
+ return
114
+ }
115
+
116
+ const gl = c.getContext('webgl')
117
+
118
+ if (!gl) {
119
+ return
120
+ }
121
+
122
+ const sh = (type: number, src: string) => {
123
+ const s = gl.createShader(type)!
124
+ gl.shaderSource(s, src)
125
+ gl.compileShader(s)
126
+
127
+ return s
128
+ }
129
+
130
+ const p = gl.createProgram()!
131
+ gl.attachShader(p, sh(gl.VERTEX_SHADER, VERT))
132
+ gl.attachShader(p, sh(gl.FRAGMENT_SHADER, FRAG))
133
+ gl.linkProgram(p)
134
+ gl.useProgram(p)
135
+
136
+ gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer())
137
+ gl.bufferData(
138
+ gl.ARRAY_BUFFER,
139
+ new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]),
140
+ gl.STATIC_DRAW
141
+ )
142
+
143
+ const a = gl.getAttribLocation(p, 'a')
144
+ gl.enableVertexAttribArray(a)
145
+ gl.vertexAttribPointer(a, 2, gl.FLOAT, false, 0, 0)
146
+
147
+ const uT = gl.getUniformLocation(p, 't')
148
+ const uR = gl.getUniformLocation(p, 'r')
149
+
150
+ const resize = () => {
151
+ const rect = c.getBoundingClientRect()
152
+ const dpr = Math.min(devicePixelRatio, 2)
153
+
154
+ c.width = rect.width * dpr
155
+ c.height = rect.height * dpr
156
+
157
+ gl.viewport(0, 0, c.width, c.height)
158
+ }
159
+
160
+ resize()
161
+
162
+ const ro = new ResizeObserver(resize)
163
+ ro.observe(c)
164
+
165
+ const t0 = performance.now()
166
+
167
+ let visible = !document.hidden
168
+ let inView = true
169
+ let raf2 = 0
170
+
171
+ const tick = () => {
172
+ gl.uniform1f(uT, (performance.now() - t0) / 1e3)
173
+ gl.uniform2f(uR, c.width, c.height)
174
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)
175
+
176
+ raf2 = requestAnimationFrame(tick)
177
+ }
178
+
179
+ const start = () => {
180
+ if (visible && inView && !raf2) {
181
+ raf2 = requestAnimationFrame(tick)
182
+ }
183
+ }
184
+
185
+ const stop = () => {
186
+ if (raf2) {
187
+ cancelAnimationFrame(raf2)
188
+ raf2 = 0
189
+ }
190
+ }
191
+
192
+ const onVisibility = () => {
193
+ visible = !document.hidden
194
+ visible ? start() : stop()
195
+ }
196
+
197
+ const io = new IntersectionObserver(
198
+ entries => {
199
+ inView = entries.some(e => e.isIntersecting)
200
+ inView ? start() : stop()
201
+ },
202
+ { threshold: 0 }
203
+ )
204
+
205
+ io.observe(c)
206
+ document.addEventListener('visibilitychange', onVisibility)
207
+
208
+ start()
209
+ raf.current = raf2
210
+
211
+ return () => {
212
+ stop()
213
+ io.disconnect()
214
+ document.removeEventListener('visibilitychange', onVisibility)
215
+ ro.disconnect()
216
+ }
217
+ }, [ref])
218
+ }
219
+
220
+ export function TV({ className }: { className?: string }) {
221
+ const canvasRef = useRef<HTMLCanvasElement>(null)
222
+ useGL(canvasRef)
223
+
224
+ return (
225
+ <div className={['relative', className].filter(Boolean).join(' ')}>
226
+ <svg className="relative h-full w-full" fill="none" viewBox="0 0 210 173">
227
+ <path
228
+ d="M30.8342 2.44471 6.08268 36.683c-.24437.338-.38254.7412-.39689 1.158L1.57754 157.126c-.03891 1.129.82339 2.087 1.95096 2.167l162.4835 11.463c.433.031.866-.074 1.238-.3l35.718-21.69c.607-.369.986-1.02 1.008-1.73l4.102-130.9871c.035-1.1269-.826-2.0806-1.951-2.1604L32.6847 1.58029c-.7248-.05144-1.4247.27551-1.8505.86442Z"
229
+ fill="#FDFD0D"
230
+ stroke="#FDFD0D"
231
+ strokeWidth="3.15"
232
+ />
233
+
234
+ <path
235
+ d="M203.09 17.1483 35.6844 5.83395l-4.2 121.94805 168.4906 13.076z"
236
+ fill="#000"
237
+ stroke="#FDFD0D"
238
+ strokeWidth="4.2"
239
+ />
240
+
241
+ <path
242
+ d="M190.491 29.7483 48.2859 18.434l-4.2 98.848 143.2901 10.976z"
243
+ fill="#FDFD0D"
244
+ />
245
+ </svg>
246
+
247
+ <canvas
248
+ className="absolute inset-0 h-full w-full"
249
+ ref={canvasRef}
250
+ style={{
251
+ clipPath:
252
+ 'polygon(23% 10.65%, 90.71% 17.2%, 89.23% 74.13%, 20.99% 67.79%)'
253
+ }}
254
+ />
255
+ </div>
256
+ )
257
+ }
@@ -0,0 +1,18 @@
1
+ import { forwardRef } from 'react'
2
+
3
+ import { cn } from '../../../utils'
4
+
5
+ import { Typography, type TypographyProps } from '.'
6
+
7
+ export const H1 = forwardRef<HTMLHeadingElement, TypographyProps<'h1'>>(
8
+ ({ className, ...props }, ref) => {
9
+ return (
10
+ <Typography
11
+ as="h1"
12
+ className={cn('font-bold', className)}
13
+ variant="xl"
14
+ {...{ ref, ...props }}
15
+ />
16
+ )
17
+ }
18
+ )
@@ -0,0 +1,18 @@
1
+ import { forwardRef } from 'react'
2
+
3
+ import { cn } from '../../../utils'
4
+
5
+ import { Typography, type TypographyProps } from '.'
6
+
7
+ export const H2 = forwardRef<HTMLHeadingElement, TypographyProps<'h2'>>(
8
+ ({ className, ...props }, ref) => {
9
+ return (
10
+ <Typography
11
+ as="h2"
12
+ className={cn('font-bold', className)}
13
+ variant="lg"
14
+ {...{ ref, ...props }}
15
+ />
16
+ )
17
+ }
18
+ )
@@ -0,0 +1,54 @@
1
+ import { cva, type VariantProps } from 'class-variance-authority'
2
+ import { createElement } from 'react'
3
+
4
+ import { cn, type PolyProps, polyRef } from '../../../utils'
5
+
6
+ const typographyVariants = cva('font-sans', {
7
+ variants: {
8
+ compressed: { true: 'font-compressed' },
9
+ courier: { true: 'font-courier' },
10
+ expanded: { true: 'font-expanded' },
11
+ mondwest: { true: 'font-mondwest tracking-[0.1875rem]' },
12
+ mono: { true: 'font-mono' },
13
+ sans: { true: 'font-sans' },
14
+ variant: {
15
+ lg: 'text-[2.625rem] leading-[1] tracking-[0.0525rem]',
16
+ md: 'text-[2.625rem] leading-[1] tracking-[0.0525rem]',
17
+ sm: 'leading-1.4 text-[.9375rem] tracking-[0.1875rem]',
18
+ xl: 'text-[4.5rem] leading-[1] tracking-[0.135rem]'
19
+ }
20
+ }
21
+ })
22
+
23
+ export const Typography = polyRef<'span', OwnProps>(
24
+ (
25
+ {
26
+ as,
27
+ className,
28
+ compressed,
29
+ courier,
30
+ expanded,
31
+ mondwest,
32
+ mono,
33
+ variant,
34
+ ...rest
35
+ },
36
+ ref
37
+ ) => {
38
+ const fonts = { compressed, courier, expanded, mondwest, mono }
39
+ const fontVariant = { ...fonts, sans: !Object.values(fonts).some(Boolean) }
40
+
41
+ return createElement((as ?? 'span') as React.ElementType, {
42
+ ...rest,
43
+ className: cn(typographyVariants({ ...fontVariant, variant }), className),
44
+ ref
45
+ })
46
+ }
47
+ )
48
+
49
+ type OwnProps = VariantProps<typeof typographyVariants>
50
+
51
+ export type TypographyProps<T extends React.ElementType = 'span'> = PolyProps<
52
+ T,
53
+ OwnProps
54
+ >
@@ -0,0 +1,24 @@
1
+ import { cn } from '../../../utils'
2
+
3
+ import { Small } from './small'
4
+
5
+ export function Legend({
6
+ children,
7
+ className,
8
+ label,
9
+ sub,
10
+ ...props
11
+ }: LegendProps) {
12
+ return (
13
+ <hgroup className={cn('flex flex-col gap-2', className)} {...props}>
14
+ <Small>{label}</Small>
15
+ {sub && <Small className="opacity-50">- {sub}</Small>}
16
+ {children}
17
+ </hgroup>
18
+ )
19
+ }
20
+
21
+ interface LegendProps extends React.ComponentProps<'hgroup'> {
22
+ label: React.ReactNode
23
+ sub?: React.ReactNode
24
+ }
@@ -0,0 +1,11 @@
1
+ import { forwardRef } from 'react'
2
+
3
+ import { Typography, type TypographyProps } from '.'
4
+
5
+ export const Small = forwardRef<HTMLSpanElement, TypographyProps<any>>(
6
+ (props, ref) => {
7
+ return (
8
+ <Typography as="small" mondwest variant="sm" {...{ ref, ...props }} />
9
+ )
10
+ }
11
+ )
@@ -0,0 +1,33 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite'
2
+
3
+ import { Watchlist } from './watchlist'
4
+
5
+ const ADDRESSES = [
6
+ ['0x7a16fF8270133F063aAb6C9977183D9e72835428', '0.50%'],
7
+ ['0xd4e96eF8eEE8678dBFF4d535E015d1a77e7Cc62c', '1.20%'],
8
+ ['0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF', '3.00%'],
9
+ ['0x8ba1f109551bD432803012645Ac136ddd64DBA72', '4.10%']
10
+ ].map(([label, right]) => ({ label, right, url: '#' }))
11
+
12
+ const meta = {
13
+ component: Watchlist,
14
+ title: 'Components/Data Display/Watchlist'
15
+ } satisfies Meta<typeof Watchlist>
16
+
17
+ export default meta
18
+
19
+ type Story = StoryObj<typeof meta>
20
+
21
+ export const WithCounterAndScramble: Story = {
22
+ args: { counter: true, items: ADDRESSES, scramble: true }
23
+ }
24
+
25
+ export const Simple: Story = {
26
+ args: {
27
+ items: [
28
+ { label: 'One', right: '11%' },
29
+ { label: 'Two', right: '22%' },
30
+ { label: 'Three', right: '33%' }
31
+ ]
32
+ }
33
+ }
@@ -0,0 +1,105 @@
1
+ 'use client'
2
+
3
+ import { cn } from '../../utils'
4
+
5
+ import { Scramble } from './ascii'
6
+ import { LinkIcon } from './icons'
7
+ import { Typography } from './typography'
8
+
9
+ const ETH_RE = /^0x[a-fA-F0-9]{40}$/
10
+ const truncate = (a: string) => `${a.slice(0, 6)}${'·'.repeat(8)}${a.slice(-4)}`
11
+
12
+ export function Watchlist({
13
+ className,
14
+ counter = false,
15
+ items,
16
+ scramble = false,
17
+ ...props
18
+ }: WatchlistProps) {
19
+ return (
20
+ <div className={cn('flex flex-col gap-3', className)} {...props}>
21
+ {items.map(({ label, right, url }, i) => {
22
+ const isStr = typeof label === 'string'
23
+ const eth = isStr && ETH_RE.test(label)
24
+ const text = eth ? truncate(label) : (label as string)
25
+
26
+ return (
27
+ <a
28
+ className={cn(
29
+ 'grid items-center gap-2.5 px-2.5 py-1.5',
30
+ 'text-display leading-[1.4]',
31
+ 'hover:bg-midground/10! hover:ring-2 hover:ring-current/20',
32
+ 'transition-all duration-500 hover:duration-0',
33
+ 'opacity-(--midground-alpha)'
34
+ )}
35
+ href={url}
36
+ key={i}
37
+ rel="noopener noreferrer"
38
+ style={{
39
+ background: `color-mix(in oklch, var(--color-midground) ${10 * Math.max(0, 1 - i / 9)}%, transparent)`,
40
+ gridTemplateColumns: [
41
+ counter && 'auto auto',
42
+ '1fr',
43
+ right && 'auto',
44
+ url && 'auto auto'
45
+ ]
46
+ .filter(Boolean)
47
+ .join(' ')
48
+ }}
49
+ target="_blank"
50
+ >
51
+ {counter && (
52
+ <>
53
+ <Typography
54
+ className="text-lg tracking-[0.35em] opacity-40"
55
+ compressed
56
+ >
57
+ {String(i + 1).padStart(2, '0')}
58
+ </Typography>
59
+
60
+ <span className="text-[0.8125rem] font-bold tracking-[0.4em] opacity-20">
61
+ :
62
+ </span>
63
+ </>
64
+ )}
65
+
66
+ {isStr ? (
67
+ <Typography
68
+ className="min-w-0 overflow-hidden text-lg font-bold tracking-[0.35em]"
69
+ {...(eth ? { mono: true } : { compressed: true })}
70
+ >
71
+ {scramble ? <Scramble delay={i * 80} text={text} /> : text}
72
+ </Typography>
73
+ ) : (
74
+ label
75
+ )}
76
+
77
+ {right && (
78
+ <Typography
79
+ className="text-right text-sm tracking-widest opacity-40"
80
+ mono
81
+ >
82
+ {right}
83
+ </Typography>
84
+ )}
85
+
86
+ {url && (
87
+ <>
88
+ <span className="text-[0.8125rem] tracking-[0.4em] opacity-20">
89
+ :
90
+ </span>
91
+ <LinkIcon className="text-midground size-3.5" />
92
+ </>
93
+ )}
94
+ </a>
95
+ )
96
+ })}
97
+ </div>
98
+ )
99
+ }
100
+
101
+ interface WatchlistProps extends React.ComponentProps<'div'> {
102
+ counter?: boolean
103
+ items: { label?: React.ReactNode; right?: React.ReactNode; url?: string }[]
104
+ scramble?: boolean
105
+ }
@@ -0,0 +1,63 @@
1
+ @font-face {
2
+ font-family: 'Collapse';
3
+ font-style: normal;
4
+ font-weight: 400;
5
+ font-display: swap;
6
+ src: url('../fonts/Collapse-Regular.woff2') format('woff2');
7
+ }
8
+
9
+ @font-face {
10
+ font-family: 'Collapse';
11
+ font-style: normal;
12
+ font-weight: 700;
13
+ font-display: swap;
14
+ src: url('../fonts/Collapse-Bold.woff2') format('woff2');
15
+ }
16
+
17
+ @font-face {
18
+ font-family: 'Rules Compressed';
19
+ font-style: normal;
20
+ font-weight: 400;
21
+ font-display: swap;
22
+ src: url('../fonts/RulesCompressed-Regular.woff2') format('woff2');
23
+ }
24
+
25
+ @font-face {
26
+ font-family: 'Rules Compressed';
27
+ font-style: normal;
28
+ font-weight: 600;
29
+ font-display: swap;
30
+ src: url('../fonts/RulesCompressed-Medium.woff2') format('woff2');
31
+ }
32
+
33
+ @font-face {
34
+ font-family: 'Rules Expanded';
35
+ font-style: normal;
36
+ font-weight: 400;
37
+ font-display: swap;
38
+ src: url('../fonts/RulesExpanded-Regular.woff2') format('woff2');
39
+ }
40
+
41
+ @font-face {
42
+ font-family: 'Rules Expanded';
43
+ font-style: normal;
44
+ font-weight: 700;
45
+ font-display: swap;
46
+ src: url('../fonts/RulesExpanded-Bold.woff2') format('woff2');
47
+ }
48
+
49
+ @font-face {
50
+ font-family: 'Mondwest';
51
+ font-style: normal;
52
+ font-weight: 400;
53
+ font-display: swap;
54
+ src: url('../fonts/Mondwest-Regular.woff2') format('woff2');
55
+ }
56
+
57
+ :root {
58
+ --font-sans: 'Collapse', sans-serif;
59
+ --font-mono: 'Courier Prime', monospace;
60
+ --font-rules-compressed: 'Rules Compressed', sans-serif;
61
+ --font-rules-expanded: 'Rules Expanded', sans-serif;
62
+ --font-mondwest: 'Mondwest', sans-serif;
63
+ }
@@ -0,0 +1,111 @@
1
+ 'use client'
2
+
3
+ import { useRef } from 'react'
4
+
5
+ import { useCssVarDims } from '../hooks/use-css-var-dims'
6
+ import { Cell, Grid } from './components/grid'
7
+ import { Socials, type SocialLink } from './components/socials'
8
+ import { ThemeToggle } from './components/theme-toggle'
9
+ import { Small } from './components/typography/small'
10
+
11
+ const DEFAULT_GROUPS: FooterGroup[] = [
12
+ { label: 'Product', links: ['Overview', 'Features', 'Pricing'] },
13
+ { label: 'Resources', links: ['Docs', 'Blog', 'Support'] },
14
+ { label: 'Company', links: ['About', 'Careers', 'Contact'] },
15
+ { label: 'Legal', links: ['Privacy', 'Terms', 'License'] }
16
+ ]
17
+
18
+ export function Footer({
19
+ className,
20
+ groups = DEFAULT_GROUPS,
21
+ LinkComponent = 'a',
22
+ socials,
23
+ socialsLabel = 'Socials',
24
+ style,
25
+ themeLabel = 'Theme',
26
+ themeToggle = false
27
+ }: FooterProps) {
28
+ const ref = useRef<HTMLElement>(null)
29
+ useCssVarDims('footer', ref)
30
+
31
+ const hasSocials = (socials?.length ?? 0) > 0
32
+ const hasChrome = hasSocials || themeToggle
33
+
34
+ return (
35
+ <footer className={className} ref={ref} style={style}>
36
+ <Grid>
37
+ <Cell>
38
+ <Small className="opacity-50">&copy;{new Date().getFullYear()}</Small>
39
+ </Cell>
40
+
41
+ {groups.map(({ label, links }) => (
42
+ <Cell key={label}>
43
+ <Small className="opacity-50">{label}</Small>
44
+
45
+ <nav className="mt-3 flex flex-col gap-2">
46
+ {links.map(link => {
47
+ const href = typeof link === 'string'
48
+ ? `/${link.toLowerCase()}`
49
+ : link.href
50
+
51
+ const label = typeof link === 'string' ? link : link.label
52
+
53
+ return (
54
+ <Small
55
+ as={LinkComponent}
56
+ className="underline"
57
+ href={href}
58
+ key={label}
59
+ >
60
+ {label}
61
+ </Small>
62
+ )
63
+ })}
64
+ </nav>
65
+ </Cell>
66
+ ))}
67
+ </Grid>
68
+
69
+ {hasChrome && (
70
+ <Grid>
71
+ {hasSocials && (
72
+ <Cell className="flex items-start justify-between">
73
+ <Small className="opacity-50">{socialsLabel}</Small>
74
+
75
+ <Socials items={socials!} />
76
+ </Cell>
77
+ )}
78
+
79
+ {themeToggle && (
80
+ <Cell className="flex items-start justify-between">
81
+ <Small className="opacity-50">{themeLabel}</Small>
82
+
83
+ <ThemeToggle />
84
+ </Cell>
85
+ )}
86
+ </Grid>
87
+ )}
88
+ </footer>
89
+ )
90
+ }
91
+
92
+ export interface FooterGroup {
93
+ label: string
94
+ links: (FooterLink | string)[]
95
+ }
96
+
97
+ export interface FooterLink {
98
+ href: string
99
+ label: string
100
+ }
101
+
102
+ export interface FooterProps {
103
+ className?: string
104
+ groups?: FooterGroup[]
105
+ LinkComponent?: React.ElementType
106
+ socials?: SocialLink[]
107
+ socialsLabel?: string
108
+ style?: React.CSSProperties
109
+ themeLabel?: string
110
+ themeToggle?: boolean
111
+ }