@yewdiel21/motion-kit 0.0.0-stage → 0.9.0

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 (391) hide show
  1. package/NOTICE +38 -0
  2. package/README.md +80 -2
  3. package/bin/motion-kit.mjs +242 -0
  4. package/css.d.ts +2 -0
  5. package/dist/auto/index.d.ts +63 -0
  6. package/dist/auto/index.js +207 -0
  7. package/dist/auto/index.js.map +1 -0
  8. package/dist/chunk-2BQGFOA7.js +177 -0
  9. package/dist/chunk-2BQGFOA7.js.map +1 -0
  10. package/dist/chunk-34XYOXHG.js +2374 -0
  11. package/dist/chunk-34XYOXHG.js.map +1 -0
  12. package/dist/chunk-6OJAP6ZL.js +832 -0
  13. package/dist/chunk-6OJAP6ZL.js.map +1 -0
  14. package/dist/chunk-ABNRDDO7.js +28 -0
  15. package/dist/chunk-ABNRDDO7.js.map +1 -0
  16. package/dist/chunk-FS2HJVVY.js +3320 -0
  17. package/dist/chunk-FS2HJVVY.js.map +1 -0
  18. package/dist/chunk-J27KH2A2.js +157 -0
  19. package/dist/chunk-J27KH2A2.js.map +1 -0
  20. package/dist/chunk-KLY5BRRI.js +18 -0
  21. package/dist/chunk-KLY5BRRI.js.map +1 -0
  22. package/dist/chunk-Q4LVFNLN.js +1617 -0
  23. package/dist/chunk-Q4LVFNLN.js.map +1 -0
  24. package/dist/chunk-RFDIZYFX.js +304 -0
  25. package/dist/chunk-RFDIZYFX.js.map +1 -0
  26. package/dist/chunk-TGV27ZWM.js +17 -0
  27. package/dist/chunk-TGV27ZWM.js.map +1 -0
  28. package/dist/confetti-BSX1CLLV.d.ts +41 -0
  29. package/dist/css/components/chat-background.css +87 -0
  30. package/dist/css/components/chat.css +237 -0
  31. package/dist/css/components/cursor.css +178 -0
  32. package/dist/css/components/dialog.css +259 -0
  33. package/dist/css/components/island.css +301 -0
  34. package/dist/css/components/menu.css +105 -0
  35. package/dist/css/components/nav.css +1054 -0
  36. package/dist/css/components/steps.css +50 -0
  37. package/dist/css/components/theme-picker.css +115 -0
  38. package/dist/css/components/toast.css +115 -0
  39. package/dist/css/controls.css +950 -0
  40. package/dist/css/effects.css +587 -0
  41. package/dist/css/fonts.css +3 -0
  42. package/dist/css/themes/black-green.css +126 -0
  43. package/dist/css/themes/black.css +126 -0
  44. package/dist/css/themes/blue.css +126 -0
  45. package/dist/css/themes/brown.css +126 -0
  46. package/dist/css/themes/cold-blue.css +126 -0
  47. package/dist/css/themes/funny.css +126 -0
  48. package/dist/css/themes/gray.css +126 -0
  49. package/dist/css/themes/green.css +126 -0
  50. package/dist/css/themes/modern-1.css +126 -0
  51. package/dist/css/themes/neogreen.css +126 -0
  52. package/dist/css/themes/new.css +126 -0
  53. package/dist/css/themes/new2.css +126 -0
  54. package/dist/css/themes/oled.css +126 -0
  55. package/dist/css/themes/orange.css +126 -0
  56. package/dist/css/themes/pastel-pink.css +126 -0
  57. package/dist/css/themes/pink.css +126 -0
  58. package/dist/css/themes/purple.css +126 -0
  59. package/dist/css/themes/red.css +126 -0
  60. package/dist/css/themes/super-blue.css +126 -0
  61. package/dist/css/themes.css +2431 -0
  62. package/dist/css/tokens.css +452 -0
  63. package/dist/elements/index.d.ts +183 -0
  64. package/dist/elements/index.js +472 -0
  65. package/dist/elements/index.js.map +1 -0
  66. package/dist/engine-CUr9QijM.d.ts +46 -0
  67. package/dist/gl/index.d.ts +61 -0
  68. package/dist/gl/index.js +18 -0
  69. package/dist/gl/index.js.map +1 -0
  70. package/dist/index.css +5296 -0
  71. package/dist/index.d.ts +440 -0
  72. package/dist/index.js +390 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/react/index.d.ts +476 -0
  75. package/dist/react/index.js +969 -0
  76. package/dist/react/index.js.map +1 -0
  77. package/dist/reduced-BM4Ls0g5.d.ts +566 -0
  78. package/dist/reveal-WFUWDrei.d.ts +416 -0
  79. package/dist/store-Bqy_obnD.d.ts +195 -0
  80. package/dist/theme/generate.d.ts +18 -0
  81. package/dist/theme/generate.js +64 -0
  82. package/dist/theme/generate.js.map +1 -0
  83. package/dist/theme/index.d.ts +17 -0
  84. package/dist/theme/index.js +32 -0
  85. package/dist/theme/index.js.map +1 -0
  86. package/dist/theme-BFMoCzi6.d.ts +158 -0
  87. package/dist/types-BkS_raL8.d.ts +7 -0
  88. package/package.json +114 -3
  89. package/registry.json +469 -0
  90. package/skills/motion-kit/SKILL.md +189 -0
  91. package/skills/motion-kit/reference/components.md +86 -0
  92. package/skills/motion-kit/reference/design.md +92 -0
  93. package/skills/motion-kit/reference/recipes.md +172 -0
  94. package/src/auto/auto-init.ts +151 -0
  95. package/src/auto/index.ts +3 -0
  96. package/src/auto/parse-options.ts +68 -0
  97. package/src/components/chat/README.md +90 -0
  98. package/src/components/chat/chat.css +236 -0
  99. package/src/components/chat/element.ts +98 -0
  100. package/src/components/chat/engine.ts +295 -0
  101. package/src/components/chat/react.tsx +196 -0
  102. package/src/components/chat-background/README.md +50 -0
  103. package/src/components/chat-background/audio.ts +56 -0
  104. package/src/components/chat-background/chat-background.css +86 -0
  105. package/src/components/chat-background/element.ts +31 -0
  106. package/src/components/chat-background/engine.ts +108 -0
  107. package/src/components/chat-background/react.tsx +36 -0
  108. package/src/components/cursor/README.md +53 -0
  109. package/src/components/cursor/cursor.css +177 -0
  110. package/src/components/cursor/element.ts +23 -0
  111. package/src/components/cursor/engine.ts +254 -0
  112. package/src/components/cursor/react.tsx +26 -0
  113. package/src/components/dialog/README.md +106 -0
  114. package/src/components/dialog/dialog.css +258 -0
  115. package/src/components/dialog/element.ts +118 -0
  116. package/src/components/dialog/engine.ts +432 -0
  117. package/src/components/dialog/react.tsx +200 -0
  118. package/src/components/icon.tsx +10 -0
  119. package/src/components/icons.ts +24 -0
  120. package/src/components/island/README.md +91 -0
  121. package/src/components/island/element.ts +45 -0
  122. package/src/components/island/engine.ts +200 -0
  123. package/src/components/island/island.css +300 -0
  124. package/src/components/island/react.tsx +115 -0
  125. package/src/components/menu/README.md +67 -0
  126. package/src/components/menu/element.ts +55 -0
  127. package/src/components/menu/engine.ts +142 -0
  128. package/src/components/menu/menu.css +104 -0
  129. package/src/components/menu/react.tsx +82 -0
  130. package/src/components/nav/README.md +85 -0
  131. package/src/components/nav/element.ts +39 -0
  132. package/src/components/nav/engine.ts +164 -0
  133. package/src/components/nav/nav.css +1053 -0
  134. package/src/components/nav/react.tsx +90 -0
  135. package/src/components/steps/README.md +70 -0
  136. package/src/components/steps/element.ts +43 -0
  137. package/src/components/steps/engine.ts +185 -0
  138. package/src/components/steps/react.tsx +91 -0
  139. package/src/components/steps/steps.css +49 -0
  140. package/src/components/theme-picker/README.md +57 -0
  141. package/src/components/theme-picker/element.ts +20 -0
  142. package/src/components/theme-picker/engine.ts +91 -0
  143. package/src/components/theme-picker/react.tsx +31 -0
  144. package/src/components/theme-picker/theme-picker.css +114 -0
  145. package/src/components/toast/README.md +60 -0
  146. package/src/components/toast/element.ts +25 -0
  147. package/src/components/toast/engine.ts +483 -0
  148. package/src/components/toast/react.tsx +22 -0
  149. package/src/components/toast/store.ts +122 -0
  150. package/src/components/toast/toast.css +114 -0
  151. package/src/core/channels.ts +165 -0
  152. package/src/core/curves.ts +35 -0
  153. package/src/core/frame.ts +12 -0
  154. package/src/core/gsap.ts +65 -0
  155. package/src/core/loop.ts +44 -0
  156. package/src/core/math.ts +9 -0
  157. package/src/core/physics-spring.ts +59 -0
  158. package/src/core/pointer.ts +63 -0
  159. package/src/core/reduced.ts +21 -0
  160. package/src/core/scope.ts +70 -0
  161. package/src/core/scroll-track.ts +106 -0
  162. package/src/core/split.ts +68 -0
  163. package/src/core/spring.ts +22 -0
  164. package/src/core/styles.ts +31 -0
  165. package/src/core/timing.ts +204 -0
  166. package/src/core/types.ts +20 -0
  167. package/src/core/visible.ts +19 -0
  168. package/src/css/base.css +142 -0
  169. package/src/css/controls/README.md +122 -0
  170. package/src/css/controls/burger.css +67 -0
  171. package/src/css/controls/button.css +226 -0
  172. package/src/css/controls/checkbox.css +53 -0
  173. package/src/css/controls/chip.css +85 -0
  174. package/src/css/controls/field.css +124 -0
  175. package/src/css/controls/glass.css +220 -0
  176. package/src/css/controls/icon.css +26 -0
  177. package/src/css/controls/segmented.css +60 -0
  178. package/src/css/controls/switch.css +72 -0
  179. package/src/css/default-theme.css +123 -0
  180. package/src/css/effects/README.md +134 -0
  181. package/src/css/effects/anim.css +224 -0
  182. package/src/css/effects/fade.css +15 -0
  183. package/src/css/effects/float.css +64 -0
  184. package/src/css/effects/frost.css +62 -0
  185. package/src/css/effects/grain.css +58 -0
  186. package/src/css/effects/loading.css +60 -0
  187. package/src/css/effects/success.css +22 -0
  188. package/src/css/effects/text.css +67 -0
  189. package/src/css/fonts.css +3 -0
  190. package/src/css/states.css +51 -0
  191. package/src/css/themes/black-green.css +126 -0
  192. package/src/css/themes/black.css +126 -0
  193. package/src/css/themes/blue.css +126 -0
  194. package/src/css/themes/brown.css +126 -0
  195. package/src/css/themes/cold-blue.css +126 -0
  196. package/src/css/themes/funny.css +126 -0
  197. package/src/css/themes/gray.css +126 -0
  198. package/src/css/themes/green.css +126 -0
  199. package/src/css/themes/modern-1.css +126 -0
  200. package/src/css/themes/neogreen.css +126 -0
  201. package/src/css/themes/new.css +126 -0
  202. package/src/css/themes/new2.css +126 -0
  203. package/src/css/themes/oled.css +126 -0
  204. package/src/css/themes/orange.css +126 -0
  205. package/src/css/themes/pastel-pink.css +126 -0
  206. package/src/css/themes/pink.css +126 -0
  207. package/src/css/themes/purple.css +126 -0
  208. package/src/css/themes/red.css +126 -0
  209. package/src/css/themes/super-blue.css +126 -0
  210. package/src/css/tokens.css +182 -0
  211. package/src/elements/base.ts +76 -0
  212. package/src/elements/index.ts +48 -0
  213. package/src/gl/index.ts +15 -0
  214. package/src/gl/liquid-blend/README.md +23 -0
  215. package/src/gl/liquid-blend/create-liquid-blend.ts +7 -0
  216. package/src/gl/liquid-blend/shader.ts +9 -0
  217. package/src/gl/matcap/README.md +23 -0
  218. package/src/gl/matcap/create-matcap.ts +7 -0
  219. package/src/gl/matcap/shader.ts +16 -0
  220. package/src/gl/particle-hero/README.md +41 -0
  221. package/src/gl/particle-hero/create-particle-hero.ts +544 -0
  222. package/src/gl/particle-hero/particle-hero.css +19 -0
  223. package/src/gl/particle-hero/shaders.ts +84 -0
  224. package/src/gl/shader-blur/README.md +23 -0
  225. package/src/gl/shader-blur/create-shader-blur.ts +7 -0
  226. package/src/gl/shader-blur/shader.ts +11 -0
  227. package/src/gl/shader-grain/README.md +23 -0
  228. package/src/gl/shader-grain/create-shader-grain.ts +7 -0
  229. package/src/gl/shader-grain/shader.ts +6 -0
  230. package/src/gl/shared/create-shader-effect.ts +186 -0
  231. package/src/gl/shared/shader.css +3 -0
  232. package/src/gl/shared/shaders.ts +30 -0
  233. package/src/index.ts +177 -0
  234. package/src/motion/anchor.ts +45 -0
  235. package/src/motion/chat.ts +97 -0
  236. package/src/motion/confetti.ts +130 -0
  237. package/src/motion/count.ts +95 -0
  238. package/src/motion/details.ts +70 -0
  239. package/src/motion/drag-dismiss.ts +231 -0
  240. package/src/motion/effects.ts +81 -0
  241. package/src/motion/entrances.ts +27 -0
  242. package/src/motion/floating.ts +389 -0
  243. package/src/motion/flow.ts +115 -0
  244. package/src/motion/indicator.ts +44 -0
  245. package/src/motion/layout.ts +39 -0
  246. package/src/motion/liquid.ts +227 -0
  247. package/src/motion/morph.ts +540 -0
  248. package/src/motion/reveal.ts +112 -0
  249. package/src/motion/sheet.ts +65 -0
  250. package/src/motion/surface.ts +108 -0
  251. package/src/react/animated-number.tsx +30 -0
  252. package/src/react/flip-group.tsx +44 -0
  253. package/src/react/frost.tsx +33 -0
  254. package/src/react/index.ts +80 -0
  255. package/src/react/slot-text.tsx +44 -0
  256. package/src/react/theme-provider.tsx +42 -0
  257. package/src/react/use-card-dock.ts +9 -0
  258. package/src/react/use-cascade.ts +9 -0
  259. package/src/react/use-contrast.ts +9 -0
  260. package/src/react/use-counter.ts +8 -0
  261. package/src/react/use-curved-carousel.ts +10 -0
  262. package/src/react/use-depth-grid.ts +9 -0
  263. package/src/react/use-details.ts +7 -0
  264. package/src/react/use-dock-pill.ts +10 -0
  265. package/src/react/use-drag-ruler.ts +10 -0
  266. package/src/react/use-fill-text.ts +9 -0
  267. package/src/react/use-fit-text.ts +8 -0
  268. package/src/react/use-flow.ts +8 -0
  269. package/src/react/use-frame-zoom.ts +9 -0
  270. package/src/react/use-infinite-reel.ts +8 -0
  271. package/src/react/use-letters.ts +9 -0
  272. package/src/react/use-liquid-blend.ts +8 -0
  273. package/src/react/use-marquee.ts +9 -0
  274. package/src/react/use-mask-text.ts +9 -0
  275. package/src/react/use-matcap.ts +8 -0
  276. package/src/react/use-parallax.ts +9 -0
  277. package/src/react/use-particle-hero.ts +9 -0
  278. package/src/react/use-pile.ts +8 -0
  279. package/src/react/use-pop.ts +8 -0
  280. package/src/react/use-radial-menu.ts +10 -0
  281. package/src/react/use-recipe.ts +38 -0
  282. package/src/react/use-reflow.ts +9 -0
  283. package/src/react/use-repel-bento.ts +8 -0
  284. package/src/react/use-reveal.ts +8 -0
  285. package/src/react/use-rotator.ts +10 -0
  286. package/src/react/use-shader-blur.ts +8 -0
  287. package/src/react/use-shader-grain.ts +8 -0
  288. package/src/react/use-slot-text.ts +17 -0
  289. package/src/react/use-snap-strip.ts +9 -0
  290. package/src/react/use-sortable.ts +14 -0
  291. package/src/react/use-spring-cards.ts +8 -0
  292. package/src/react/use-stretch-footer.ts +20 -0
  293. package/src/react/use-tabs.ts +10 -0
  294. package/src/react/use-text-roll.ts +9 -0
  295. package/src/react/use-ticket-menu.ts +15 -0
  296. package/src/react/use-words.ts +8 -0
  297. package/src/recipes/card-dock/README.md +36 -0
  298. package/src/recipes/card-dock/card-dock.css +178 -0
  299. package/src/recipes/card-dock/create-card-dock.ts +97 -0
  300. package/src/recipes/cascade/README.md +33 -0
  301. package/src/recipes/cascade/create-cascade.ts +111 -0
  302. package/src/recipes/contrast/README.md +29 -0
  303. package/src/recipes/contrast/create-contrast.ts +68 -0
  304. package/src/recipes/counter/README.md +42 -0
  305. package/src/recipes/counter/create-counter.ts +84 -0
  306. package/src/recipes/curved-carousel/README.md +50 -0
  307. package/src/recipes/curved-carousel/carousel-math.ts +20 -0
  308. package/src/recipes/curved-carousel/create-curved-carousel.ts +257 -0
  309. package/src/recipes/curved-carousel/curved-carousel.css +50 -0
  310. package/src/recipes/depth-grid/README.md +30 -0
  311. package/src/recipes/depth-grid/create-depth-grid.ts +120 -0
  312. package/src/recipes/details/README.md +31 -0
  313. package/src/recipes/details/create-details.ts +27 -0
  314. package/src/recipes/dock-pill/README.md +23 -0
  315. package/src/recipes/dock-pill/create-dock-pill.ts +68 -0
  316. package/src/recipes/dock-pill/dock-pill.css +5 -0
  317. package/src/recipes/drag-ruler/README.md +21 -0
  318. package/src/recipes/drag-ruler/create-drag-ruler.ts +95 -0
  319. package/src/recipes/drag-ruler/drag-ruler.css +16 -0
  320. package/src/recipes/fill-text/README.md +27 -0
  321. package/src/recipes/fill-text/create-fill-text.ts +93 -0
  322. package/src/recipes/fit-text/README.md +37 -0
  323. package/src/recipes/fit-text/create-fit-text.ts +55 -0
  324. package/src/recipes/fit-text/fit-text.css +6 -0
  325. package/src/recipes/flow/README.md +46 -0
  326. package/src/recipes/flow/create-flow.ts +55 -0
  327. package/src/recipes/frame-zoom/README.md +29 -0
  328. package/src/recipes/frame-zoom/create-frame-zoom.ts +91 -0
  329. package/src/recipes/infinite-reel/README.md +23 -0
  330. package/src/recipes/infinite-reel/create-infinite-reel.ts +140 -0
  331. package/src/recipes/infinite-reel/infinite-reel.css +8 -0
  332. package/src/recipes/letters/README.md +30 -0
  333. package/src/recipes/letters/create-letters.ts +113 -0
  334. package/src/recipes/marquee/README.md +32 -0
  335. package/src/recipes/marquee/create-marquee.ts +74 -0
  336. package/src/recipes/marquee/marquee.css +41 -0
  337. package/src/recipes/mask-text/README.md +39 -0
  338. package/src/recipes/mask-text/create-mask-text.ts +134 -0
  339. package/src/recipes/parallax/README.md +31 -0
  340. package/src/recipes/parallax/create-parallax.ts +74 -0
  341. package/src/recipes/pile/README.md +48 -0
  342. package/src/recipes/pile/create-pile.ts +50 -0
  343. package/src/recipes/pile/pile-math.ts +27 -0
  344. package/src/recipes/pile/pile.css +63 -0
  345. package/src/recipes/pill/README.md +30 -0
  346. package/src/recipes/pill/pill.css +48 -0
  347. package/src/recipes/pop/README.md +36 -0
  348. package/src/recipes/pop/create-pop.ts +52 -0
  349. package/src/recipes/radial-menu/README.md +44 -0
  350. package/src/recipes/radial-menu/create-radial-menu.ts +96 -0
  351. package/src/recipes/radial-menu/radial-menu.css +45 -0
  352. package/src/recipes/reflow/README.md +47 -0
  353. package/src/recipes/reflow/create-reflow.ts +49 -0
  354. package/src/recipes/repel-bento/README.md +21 -0
  355. package/src/recipes/repel-bento/create-repel-bento.ts +65 -0
  356. package/src/recipes/repel-bento/repel-bento.css +3 -0
  357. package/src/recipes/reveal/README.md +36 -0
  358. package/src/recipes/reveal/create-reveal.ts +48 -0
  359. package/src/recipes/rotator/README.md +21 -0
  360. package/src/recipes/rotator/create-rotator.ts +66 -0
  361. package/src/recipes/rotator/rotator.css +3 -0
  362. package/src/recipes/slot-text/README.md +44 -0
  363. package/src/recipes/slot-text/create-slot-text.ts +244 -0
  364. package/src/recipes/slot-text/slot-text.css +42 -0
  365. package/src/recipes/snap-strip/README.md +31 -0
  366. package/src/recipes/snap-strip/create-snap-strip.ts +133 -0
  367. package/src/recipes/snap-strip/snap-strip.css +23 -0
  368. package/src/recipes/sortable/README.md +88 -0
  369. package/src/recipes/sortable/create-sortable.ts +863 -0
  370. package/src/recipes/sortable/sortable.css +40 -0
  371. package/src/recipes/spring-cards/README.md +48 -0
  372. package/src/recipes/spring-cards/create-spring-cards.ts +140 -0
  373. package/src/recipes/spring-cards/spring-cards.css +23 -0
  374. package/src/recipes/stretch-footer/README.md +44 -0
  375. package/src/recipes/stretch-footer/create-stretch-footer.ts +69 -0
  376. package/src/recipes/stretch-footer/stretch-footer.css +28 -0
  377. package/src/recipes/tabs/README.md +39 -0
  378. package/src/recipes/tabs/create-tabs.ts +91 -0
  379. package/src/recipes/tabs/tabs.css +19 -0
  380. package/src/recipes/text-roll/README.md +35 -0
  381. package/src/recipes/text-roll/create-text-roll.ts +137 -0
  382. package/src/recipes/text-roll/text-roll.css +21 -0
  383. package/src/recipes/ticket-menu/README.md +24 -0
  384. package/src/recipes/ticket-menu/create-ticket-menu.ts +6 -0
  385. package/src/recipes/words/README.md +43 -0
  386. package/src/recipes/words/create-words.ts +114 -0
  387. package/src/theme/css-format.ts +32 -0
  388. package/src/theme/generate.ts +72 -0
  389. package/src/theme/index.ts +15 -0
  390. package/src/theme/presets.ts +79 -0
  391. package/src/theme/theme.ts +119 -0
@@ -0,0 +1,832 @@
1
+ import {
2
+ clamp
3
+ } from "./chunk-KLY5BRRI.js";
4
+ import {
5
+ TIMING,
6
+ createScope,
7
+ reduced,
8
+ whileVisible
9
+ } from "./chunk-RFDIZYFX.js";
10
+ import {
11
+ inert,
12
+ warnOnce
13
+ } from "./chunk-TGV27ZWM.js";
14
+
15
+ // src/gl/shared/shaders.ts
16
+ var fullscreenVertex = `
17
+ attribute vec2 position;
18
+ varying vec2 vUv;
19
+ void main() {
20
+ vUv = position * .5 + .5;
21
+ gl_Position = vec4(position, 0., 1.);
22
+ }`;
23
+ var fragmentHeader = `
24
+ precision highp float;
25
+ varying vec2 vUv;
26
+ uniform sampler2D uImage0;
27
+ uniform sampler2D uImage1;
28
+ uniform vec2 uSize;
29
+ uniform vec2 uImageSize0;
30
+ uniform vec2 uImageSize1;
31
+ uniform float uTime;
32
+ uniform float uProgress;
33
+ uniform float uAmount;
34
+ uniform float uHasImage;
35
+ vec2 cover(vec2 uv, vec2 imageSize) {
36
+ float aspect = uSize.x / uSize.y;
37
+ float imageAspect = imageSize.x / imageSize.y;
38
+ vec2 scale = vec2(min(aspect / imageAspect, 1.), min(imageAspect / aspect, 1.));
39
+ return (uv - .5) * scale + .5;
40
+ }
41
+ float noise(vec2 point) {
42
+ return fract(sin(dot(point, vec2(12.9898, 78.233))) * 43758.5453);
43
+ }
44
+ `;
45
+
46
+ // src/gl/shared/create-shader-effect.ts
47
+ function createRenderer(canvas, fragment, images) {
48
+ const gl = canvas.getContext("webgl", { alpha: true, antialias: false, premultipliedAlpha: false });
49
+ if (!gl) throw new Error("WebGL unavailable");
50
+ const releases = [];
51
+ const destroy = () => {
52
+ releases.splice(0).reverse().forEach((release) => release());
53
+ };
54
+ try {
55
+ const compile = (type, source) => {
56
+ const shader = gl.createShader(type);
57
+ if (!shader) throw new Error("Shader allocation failed");
58
+ releases.push(() => gl.deleteShader(shader));
59
+ gl.shaderSource(shader, source);
60
+ gl.compileShader(shader);
61
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) throw new Error(gl.getShaderInfoLog(shader) ?? "Shader failed");
62
+ return shader;
63
+ };
64
+ const vertex = compile(gl.VERTEX_SHADER, fullscreenVertex);
65
+ const pixel = compile(gl.FRAGMENT_SHADER, fragmentHeader + fragment);
66
+ const program = gl.createProgram();
67
+ if (!program) throw new Error("Program allocation failed");
68
+ releases.push(() => gl.deleteProgram(program));
69
+ gl.attachShader(program, vertex);
70
+ gl.attachShader(program, pixel);
71
+ gl.linkProgram(program);
72
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) throw new Error(gl.getProgramInfoLog(program) ?? "Link failed");
73
+ gl.useProgram(program);
74
+ const buffer = gl.createBuffer();
75
+ if (!buffer) throw new Error("Buffer allocation failed");
76
+ releases.push(() => gl.deleteBuffer(buffer));
77
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
78
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 3, -1, -1, 3]), gl.STATIC_DRAW);
79
+ const attribute = gl.getAttribLocation(program, "position");
80
+ gl.enableVertexAttribArray(attribute);
81
+ gl.vertexAttribPointer(attribute, 2, gl.FLOAT, false, 0, 0);
82
+ const names = ["uSize", "uImageSize0", "uImageSize1", "uTime", "uProgress", "uAmount", "uImage0", "uImage1", "uHasImage"];
83
+ const uniforms = Object.fromEntries(names.map((name) => [name, gl.getUniformLocation(program, name)]));
84
+ const textures = [0, 1].map((index) => {
85
+ const texture = gl.createTexture();
86
+ if (!texture) throw new Error("Texture allocation failed");
87
+ releases.push(() => gl.deleteTexture(texture));
88
+ gl.activeTexture(gl.TEXTURE0 + index);
89
+ gl.bindTexture(gl.TEXTURE_2D, texture);
90
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
91
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
92
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
93
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
94
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([26, 40, 55, 255]));
95
+ gl.uniform1i(uniforms[`uImage${index}`], index);
96
+ return texture;
97
+ });
98
+ const upload = () => {
99
+ if (images.some((image) => !image.complete || !image.naturalWidth)) return false;
100
+ gl.useProgram(program);
101
+ images.slice(0, 2).forEach((image, index) => {
102
+ gl.activeTexture(gl.TEXTURE0 + index);
103
+ gl.bindTexture(gl.TEXTURE_2D, textures[index]);
104
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
105
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
106
+ });
107
+ return true;
108
+ };
109
+ return {
110
+ upload,
111
+ draw(time, progress, amount) {
112
+ gl.viewport(0, 0, canvas.width, canvas.height);
113
+ gl.useProgram(program);
114
+ gl.uniform2f(uniforms.uSize, canvas.width, canvas.height);
115
+ [0, 1].forEach((index) => gl.uniform2f(uniforms[`uImageSize${index}`], images[index]?.naturalWidth || 1, images[index]?.naturalHeight || 1));
116
+ gl.uniform1f(uniforms.uTime, time);
117
+ gl.uniform1f(uniforms.uProgress, progress);
118
+ gl.uniform1f(uniforms.uAmount, amount);
119
+ gl.uniform1f(uniforms.uHasImage, images.length ? 1 : 0);
120
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
121
+ },
122
+ destroy
123
+ };
124
+ } catch (error) {
125
+ destroy();
126
+ throw error;
127
+ }
128
+ }
129
+ function createShaderEffect(root, fragment, options = {}) {
130
+ if (!root) return inert({ mode: "none", setProgress() {
131
+ }, setAmount() {
132
+ }, pause() {
133
+ }, resume() {
134
+ } });
135
+ const scope = createScope();
136
+ const canvas = document.createElement("canvas");
137
+ canvas.className = "mk-shader__canvas";
138
+ canvas.setAttribute("aria-hidden", "true");
139
+ canvas.hidden = true;
140
+ const images = (options.images ?? [...root.querySelectorAll("img")]).slice(0, 2);
141
+ if (images.length === 1) images.push(images[0]);
142
+ let renderer = null;
143
+ let mode = "none";
144
+ let progress = clamp(options.progress ?? 0, 0, 1);
145
+ let amount = clamp(options.amount ?? 1, 0, 100);
146
+ let time = 0;
147
+ let paused = false;
148
+ let ready = false;
149
+ const draw = () => {
150
+ if (!scope.disposed && ready && renderer && mode === "webgl") renderer.draw(time, progress, amount);
151
+ };
152
+ const fallback = () => {
153
+ mode = "none";
154
+ ready = false;
155
+ canvas.hidden = true;
156
+ };
157
+ const load = () => {
158
+ if (scope.disposed || !renderer) return;
159
+ try {
160
+ ready = renderer.upload();
161
+ canvas.hidden = !ready;
162
+ if (ready) mode = "webgl";
163
+ draw();
164
+ } catch {
165
+ fallback();
166
+ }
167
+ };
168
+ const resize = (render = true) => {
169
+ if (scope.disposed) return;
170
+ const rect = root.getBoundingClientRect();
171
+ const dpr = Math.min(typeof devicePixelRatio === "number" ? devicePixelRatio : 1, Math.max(0.5, options.maxDpr ?? 1.5));
172
+ canvas.width = Math.max(1, Math.round(rect.width * dpr));
173
+ canvas.height = Math.max(1, Math.round(rect.height * dpr));
174
+ if (render) draw();
175
+ };
176
+ const initialize = () => {
177
+ renderer?.destroy();
178
+ renderer = null;
179
+ try {
180
+ renderer = createRenderer(canvas, fragment, images);
181
+ mode = "webgl";
182
+ resize(false);
183
+ load();
184
+ return true;
185
+ } catch {
186
+ fallback();
187
+ return false;
188
+ }
189
+ };
190
+ if (!initialize()) {
191
+ scope.dispose();
192
+ return inert({ mode: "none", setProgress() {
193
+ }, setAmount() {
194
+ }, pause() {
195
+ }, resume() {
196
+ } });
197
+ }
198
+ scope.attr(root, "class", `${root.className} mk-shader`.trim());
199
+ root.append(canvas);
200
+ scope.add(() => {
201
+ renderer?.destroy();
202
+ renderer = null;
203
+ canvas.remove();
204
+ mode = "none";
205
+ });
206
+ images.forEach((image) => {
207
+ scope.on(image, "load", load);
208
+ scope.on(image, "error", fallback);
209
+ });
210
+ scope.on(canvas, "webglcontextlost", (event) => {
211
+ event.preventDefault();
212
+ fallback();
213
+ });
214
+ scope.on(canvas, "webglcontextrestored", initialize);
215
+ if (typeof ResizeObserver === "function") scope.observe(new ResizeObserver(() => resize())).observe(root);
216
+ scope.on(window, "resize", () => resize());
217
+ if (!reduced()) scope.add(whileVisible(root, (dt) => {
218
+ if (paused || document.hidden || mode === "none") return;
219
+ time += dt / 60;
220
+ draw();
221
+ }));
222
+ return {
223
+ get mode() {
224
+ return mode;
225
+ },
226
+ setProgress(value) {
227
+ if (scope.disposed || !Number.isFinite(value)) return;
228
+ progress = clamp(value, 0, 1);
229
+ draw();
230
+ },
231
+ setAmount(value) {
232
+ if (scope.disposed || !Number.isFinite(value)) return;
233
+ amount = clamp(value, 0, 100);
234
+ draw();
235
+ },
236
+ pause() {
237
+ paused = true;
238
+ },
239
+ resume() {
240
+ paused = false;
241
+ },
242
+ destroy: () => scope.dispose()
243
+ };
244
+ }
245
+
246
+ // src/gl/liquid-blend/shader.ts
247
+ var liquidFragment = `
248
+ void main() {
249
+ float center = 1. - smoothstep(0., .5, distance(vUv, vec2(.5)));
250
+ vec2 wave = vec2(sin(vUv.y * 18. + uTime), cos(vUv.x * 20. - uTime));
251
+ vec2 distortion = wave * center * uAmount;
252
+ vec2 currentUv = cover(vUv + distortion * uProgress, uImageSize0);
253
+ vec2 nextUv = cover(vUv - distortion * (1. - uProgress), uImageSize1);
254
+ gl_FragColor = mix(texture2D(uImage0, currentUv), texture2D(uImage1, nextUv), uProgress);
255
+ }`;
256
+
257
+ // src/gl/liquid-blend/create-liquid-blend.ts
258
+ var createLiquidBlend = (root, options = {}) => createShaderEffect(root, liquidFragment, { amount: 0.15, ...options });
259
+
260
+ // src/gl/matcap/shader.ts
261
+ var matcapFragment = `
262
+ void main() {
263
+ vec2 point = (vUv - .5) * 2.5;
264
+ point.x *= uSize.x / uSize.y;
265
+ float radius = length(point);
266
+ if (radius > 1.) { gl_FragColor = vec4(.04, .06, .08, 1.); return; }
267
+ vec3 normal = normalize(vec3(point, sqrt(max(0., 1. - dot(point, point)))));
268
+ float angle = uTime * .2 + uProgress * 6.28318;
269
+ vec2 rotated = mat2(cos(angle), -sin(angle), sin(angle), cos(angle)) * normal.xy;
270
+ vec2 matcapUv = rotated * .495 + .5;
271
+ float hemisphere = clamp(1. - dot(normalize(vec3(1., -1., 1.)), normal), 0., 1.);
272
+ vec3 metal = mix(vec3(.1), vec3(1.), hemisphere) + pow(normal.z, 24.) * uAmount;
273
+ vec3 mapped = texture2D(uImage0, matcapUv).rgb;
274
+ metal = mix(metal, mapped + metal * .15, uHasImage);
275
+ gl_FragColor = vec4(metal, 1.);
276
+ }`;
277
+
278
+ // src/gl/matcap/create-matcap.ts
279
+ var createMatcap = (root, options = {}) => createShaderEffect(root, matcapFragment, { amount: 0.15, ...options });
280
+
281
+ // src/gl/shader-grain/shader.ts
282
+ var grainFragment = `
283
+ void main() {
284
+ vec4 color = texture2D(uImage0, cover(vUv, uImageSize0));
285
+ float grain = noise(floor(vUv * uSize) + floor(uTime * 24.)) - .5;
286
+ gl_FragColor = vec4(color.rgb + grain * uAmount, color.a);
287
+ }`;
288
+
289
+ // src/gl/shader-grain/create-shader-grain.ts
290
+ var createShaderGrain = (root, options = {}) => createShaderEffect(root, grainFragment, { amount: 0.07, ...options });
291
+
292
+ // src/gl/shader-blur/shader.ts
293
+ var blurFragment = `
294
+ void main() {
295
+ vec2 uv = cover(vUv, uImageSize0);
296
+ float angle = uProgress * 1.5707963;
297
+ vec2 delta = vec2(cos(angle), sin(angle)) * uAmount / uImageSize0;
298
+ vec4 color = texture2D(uImage0, uv) * .1964825501511404;
299
+ color += (texture2D(uImage0, uv + delta * 1.411764705882353) + texture2D(uImage0, uv - delta * 1.411764705882353)) * .2969069646728344;
300
+ color += (texture2D(uImage0, uv + delta * 3.2941176470588234) + texture2D(uImage0, uv - delta * 3.2941176470588234)) * .09447039785044732;
301
+ color += (texture2D(uImage0, uv + delta * 5.176470588235294) + texture2D(uImage0, uv - delta * 5.176470588235294)) * .010381362401148057;
302
+ gl_FragColor = color;
303
+ }`;
304
+
305
+ // src/gl/shader-blur/create-shader-blur.ts
306
+ var createShaderBlur = (root, options = {}) => createShaderEffect(root, blurFragment, { amount: 5, ...options });
307
+
308
+ // src/gl/particle-hero/shaders.ts
309
+ var fullscreenVertex2 = `#version 300 es
310
+ precision highp float;
311
+ out vec2 vUv;
312
+ void main() {
313
+ vec2 p = vec2((gl_VertexID << 1) & 2, gl_VertexID & 2);
314
+ vUv = p;
315
+ gl_Position = vec4(p * 2. - 1., 0., 1.);
316
+ }`;
317
+ var simulationFragment = `#version 300 es
318
+ precision highp float;
319
+ in vec2 vUv;
320
+ uniform sampler2D uState, uMask;
321
+ uniform float uTime, uDt, uMix, uFrequency, uDistortion, uNoise, uJitter, uMouseSpeed, uAspect;
322
+ uniform vec2 uModes, uMouse;
323
+ uniform int uPattern;
324
+ out vec4 outState;
325
+ float hash(vec2 p) { return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123); }
326
+ float field(vec2 p) {
327
+ float base = sin(length(p) * uFrequency * .35);
328
+ if (uPattern == 1) base = sin(p.x * uFrequency * .35) * sin(p.y * uFrequency * .35);
329
+ if (uPattern == 2) base = sin(max(abs(p.x), abs(p.y)) * uFrequency * .35);
330
+ float chladni = sin(uModes.x * 3.14159265 * (p.x + 1.) * .5) * sin(uModes.y * 3.14159265 * (p.y + 1.) * .5);
331
+ float spots = (hash(floor(p * 12.)) - .5) * uNoise * .08;
332
+ float jitter = sin(uTime * 42. + hash(p * 30.) * 6.283) * uJitter * .015;
333
+ return mix(base, chladni, clamp(uDistortion * .2, 0., .85)) + spots + jitter;
334
+ }
335
+ void main() {
336
+ vec4 state = texture(uState, vUv);
337
+ vec2 pos = state.xy;
338
+ vec2 vel = state.zw;
339
+ vec2 p = (vUv - .5) * 2.;
340
+ for (int i = 0; i < 4; i++) {
341
+ float f = field(p);
342
+ float e = .003;
343
+ vec2 g = vec2(field(p + vec2(e, 0.)) - field(p - vec2(e, 0.)), field(p + vec2(0., e)) - field(p - vec2(0., e))) / (2. * e);
344
+ float q = dot(g, g);
345
+ if (q > .00001) p -= f * g / q * .4;
346
+ }
347
+ vec2 word = texture(uMask, vUv).xy;
348
+ float text = step(hash(vUv), uMix);
349
+ vec2 target = mix(p * .88, word, text);
350
+ target.x *= max(uAspect, 1.);
351
+ float dt60 = uDt * 60.;
352
+ vel *= pow(.91, dt60);
353
+ vec2 delta = target - pos;
354
+ float dist = length(delta);
355
+ if (dist > .004 * (1. - text)) vel += delta / max(dist, .00001) * mix(.0016, .0009, text) * dt60;
356
+ vec2 away = pos - uMouse;
357
+ float r = length(away);
358
+ vel += away / max(r, .0001) * (1. - smoothstep(0., .28, r)) * uMouseSpeed * .017 * dt60;
359
+ vel += vec2(sin(uTime + vUv.x * 400.), cos(uTime + vUv.y * 400.)) * .00003 * dt60;
360
+ pos += vel * dt60;
361
+ outState = vec4(pos, vel);
362
+ }`;
363
+ var pointsVertex = `#version 300 es
364
+ precision highp float;
365
+ uniform sampler2D uState;
366
+ uniform int uSize;
367
+ uniform float uAspect, uDpr, uPointSize;
368
+ void main() {
369
+ ivec2 uv = ivec2(gl_VertexID % uSize, gl_VertexID / uSize);
370
+ vec2 p = texelFetch(uState, uv, 0).xy;
371
+ gl_Position = vec4(p.x / max(uAspect, 1.), p.y, 0., 1.);
372
+ gl_PointSize = uPointSize * uDpr;
373
+ }`;
374
+ var pointsFragment = `#version 300 es
375
+ precision highp float;
376
+ uniform vec3 uColor;
377
+ uniform float uOpacity;
378
+ out vec4 outColor;
379
+ void main() {
380
+ float a = (1. - smoothstep(.12, .5, length(gl_PointCoord - .5))) * .44 * uOpacity;
381
+ outColor = vec4(uColor, a);
382
+ }`;
383
+
384
+ // src/gl/particle-hero/create-particle-hero.ts
385
+ var instances = /* @__PURE__ */ new WeakMap();
386
+ var clamp2 = (x, a, b) => Math.max(a, Math.min(b, x));
387
+ var mix = (a, b, t) => a + (b - a) * t;
388
+ var inOut = (t) => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
389
+ function random(seed) {
390
+ let s = seed >>> 0;
391
+ return () => {
392
+ s = 1664525 * s + 1013904223 >>> 0;
393
+ return s / 4294967296;
394
+ };
395
+ }
396
+ function wordMask(word, count, rng) {
397
+ const result = new Float32Array(count * 4);
398
+ const canvas = document.createElement("canvas");
399
+ canvas.width = 640;
400
+ canvas.height = 320;
401
+ const ctx = canvas.getContext("2d", { willReadFrequently: true });
402
+ const dark = [];
403
+ if (ctx) {
404
+ ctx.fillStyle = "#fff";
405
+ ctx.fillRect(0, 0, 640, 320);
406
+ ctx.fillStyle = "#000";
407
+ ctx.textAlign = "center";
408
+ ctx.textBaseline = "middle";
409
+ let size = 140;
410
+ ctx.font = `600 ${size}px system-ui, sans-serif`;
411
+ while (ctx.measureText(word).width > 590 && size > 16) {
412
+ size -= 4;
413
+ ctx.font = `600 ${size}px system-ui, sans-serif`;
414
+ }
415
+ ctx.fillText(word, 320, 160);
416
+ const pixels = ctx.getImageData(0, 0, 640, 320).data;
417
+ for (let y = 0; y < 320; y += 2) for (let x = 0; x < 640; x += 2) if (pixels[(y * 640 + x) * 4] < 120) dark.push([x, y]);
418
+ }
419
+ for (let i = 0; i < count; i++) {
420
+ const [x, y] = dark.length ? dark[Math.floor(rng() * dark.length)] : [320, 160];
421
+ result[i * 4] = (x / 640 - 0.5) * 1.75 + (rng() - 0.5) * 4e-3;
422
+ result[i * 4 + 1] = (0.5 - y / 320) * 0.9 + (rng() - 0.5) * 4e-3;
423
+ }
424
+ return result;
425
+ }
426
+ function gpuRenderer(canvas, size, pointSize, color, initial, mask) {
427
+ const gl = canvas.getContext("webgl2", { alpha: true, antialias: false, powerPreference: "high-performance", premultipliedAlpha: true });
428
+ if (!gl || !gl.getExtension("EXT_color_buffer_float")) throw new Error("WebGL2 float render targets unavailable");
429
+ const releases = [];
430
+ const release = () => {
431
+ for (const fn of releases.reverse()) fn();
432
+ releases.length = 0;
433
+ };
434
+ try {
435
+ const shader = (type, source) => {
436
+ const s = gl.createShader(type);
437
+ releases.push(() => gl.deleteShader(s));
438
+ gl.shaderSource(s, source);
439
+ gl.compileShader(s);
440
+ if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) throw new Error(gl.getShaderInfoLog(s) ?? "shader");
441
+ return s;
442
+ };
443
+ const program = (vs, fs) => {
444
+ const p = gl.createProgram();
445
+ releases.push(() => gl.deleteProgram(p));
446
+ gl.attachShader(p, shader(gl.VERTEX_SHADER, vs));
447
+ gl.attachShader(p, shader(gl.FRAGMENT_SHADER, fs));
448
+ gl.linkProgram(p);
449
+ if (!gl.getProgramParameter(p, gl.LINK_STATUS)) throw new Error(gl.getProgramInfoLog(p) ?? "program");
450
+ return p;
451
+ };
452
+ const texture = (data) => {
453
+ const tex = gl.createTexture();
454
+ releases.push(() => gl.deleteTexture(tex));
455
+ gl.bindTexture(gl.TEXTURE_2D, tex);
456
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
457
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
458
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
459
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
460
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, size, size, 0, gl.RGBA, gl.FLOAT, data);
461
+ return tex;
462
+ };
463
+ const sim = program(fullscreenVertex2, simulationFragment);
464
+ const draw = program(pointsVertex, pointsFragment);
465
+ const states = [texture(initial), texture(initial)];
466
+ const maskTexture = texture(mask);
467
+ const buffers = states.map((tex) => {
468
+ const fb = gl.createFramebuffer();
469
+ releases.push(() => gl.deleteFramebuffer(fb));
470
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
471
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
472
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) throw new Error("incomplete float framebuffer");
473
+ return fb;
474
+ });
475
+ const vao = gl.createVertexArray();
476
+ releases.push(() => gl.deleteVertexArray(vao));
477
+ const uniforms = (p, names) => Object.fromEntries(names.map((name) => [name, gl.getUniformLocation(p, name)]));
478
+ const simU = uniforms(sim, [
479
+ "uState",
480
+ "uMask",
481
+ "uTime",
482
+ "uDt",
483
+ "uMix",
484
+ "uFrequency",
485
+ "uDistortion",
486
+ "uNoise",
487
+ "uJitter",
488
+ "uMouseSpeed",
489
+ "uAspect",
490
+ "uModes",
491
+ "uMouse",
492
+ "uPattern"
493
+ ]);
494
+ const drawU = uniforms(draw, ["uState", "uSize", "uAspect", "uDpr", "uPointSize", "uColor", "uOpacity"]);
495
+ const bind = (unit, tex) => {
496
+ gl.activeTexture(gl.TEXTURE0 + unit);
497
+ gl.bindTexture(gl.TEXTURE_2D, tex);
498
+ };
499
+ let read = 0;
500
+ return {
501
+ mode: "webgl2",
502
+ render(s, steps = 1) {
503
+ gl.bindVertexArray(vao);
504
+ gl.disable(gl.BLEND);
505
+ gl.useProgram(sim);
506
+ gl.uniform1i(simU.uState, 0);
507
+ gl.uniform1i(simU.uMask, 1);
508
+ gl.uniform1f(simU.uTime, s.time);
509
+ gl.uniform1f(simU.uDt, s.dt);
510
+ gl.uniform1f(simU.uMix, s.mix);
511
+ gl.uniform1f(simU.uFrequency, s.frequency);
512
+ gl.uniform1f(simU.uDistortion, s.distortion);
513
+ gl.uniform1f(simU.uNoise, s.noise);
514
+ gl.uniform1f(simU.uJitter, s.jitter);
515
+ gl.uniform1f(simU.uMouseSpeed, s.mouseSpeed);
516
+ gl.uniform1f(simU.uAspect, s.aspect);
517
+ gl.uniform2f(simU.uModes, s.m, s.n);
518
+ gl.uniform2f(simU.uMouse, s.mouseX, s.mouseY);
519
+ gl.uniform1i(simU.uPattern, s.pattern);
520
+ bind(1, maskTexture);
521
+ for (let i = 0; i < steps; i++) {
522
+ bind(0, states[read]);
523
+ gl.bindFramebuffer(gl.FRAMEBUFFER, buffers[1 - read]);
524
+ gl.viewport(0, 0, size, size);
525
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
526
+ read = 1 - read;
527
+ }
528
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
529
+ gl.viewport(0, 0, canvas.width, canvas.height);
530
+ gl.clearColor(0, 0, 0, 0);
531
+ gl.clear(gl.COLOR_BUFFER_BIT);
532
+ gl.useProgram(draw);
533
+ bind(0, states[read]);
534
+ gl.uniform1i(drawU.uState, 0);
535
+ gl.uniform1i(drawU.uSize, size);
536
+ gl.uniform1f(drawU.uAspect, s.aspect);
537
+ gl.uniform1f(drawU.uDpr, s.dpr);
538
+ gl.uniform1f(drawU.uPointSize, pointSize);
539
+ gl.uniform3fv(drawU.uColor, color);
540
+ gl.uniform1f(drawU.uOpacity, s.opacity);
541
+ gl.enable(gl.BLEND);
542
+ gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
543
+ gl.drawArrays(gl.POINTS, 0, size * size);
544
+ },
545
+ setMask(data) {
546
+ bind(1, maskTexture);
547
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, size, size, gl.RGBA, gl.FLOAT, data);
548
+ },
549
+ destroy: release
550
+ };
551
+ } catch (error) {
552
+ release();
553
+ throw error;
554
+ }
555
+ }
556
+ function canvasRenderer(canvas, size, pointSize, color, initial, mask) {
557
+ const ctx = canvas.getContext("2d");
558
+ if (!ctx) throw new Error("no 2D context");
559
+ const stride = Math.max(1, Math.floor(size * size / 1800));
560
+ const ids = [];
561
+ for (let i = 0; i < size * size; i += stride) ids.push(i);
562
+ const points = Float32Array.from(initial);
563
+ let target = mask;
564
+ const rgb = color.map((c) => Math.round(c * 255)).join(",");
565
+ return {
566
+ mode: "canvas2d",
567
+ setMask(data) {
568
+ target = data;
569
+ },
570
+ render(s, steps = 1) {
571
+ for (let step = 0; step < steps; step++)
572
+ for (const i of ids) {
573
+ const o = i * 4;
574
+ const angle = i * 2.3999632297;
575
+ const radius = 0.3 + 0.52 * Math.sin(angle * 0.025 + s.time * 0.07);
576
+ let x = Math.cos(angle) * radius;
577
+ let y = Math.sin(angle) * radius;
578
+ if (i * 137 % 1e3 / 1e3 < s.mix) {
579
+ x = target[o];
580
+ y = target[o + 1];
581
+ }
582
+ points[o] = points[o] + (x - points[o]) * 0.075;
583
+ points[o + 1] = points[o + 1] + (y - points[o + 1]) * 0.075;
584
+ }
585
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
586
+ ctx.fillStyle = `rgba(${rgb},${0.4 * s.opacity})`;
587
+ for (const i of ids) {
588
+ const x = (points[i * 4] * 0.5 + 0.5) * canvas.width;
589
+ const y = (0.5 - points[i * 4 + 1] * 0.5) * canvas.height;
590
+ ctx.beginPath();
591
+ ctx.arc(x, y, pointSize * s.dpr * 0.55, 0, Math.PI * 2);
592
+ ctx.fill();
593
+ }
594
+ },
595
+ destroy() {
596
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
597
+ }
598
+ };
599
+ }
600
+ var NONE = {
601
+ mode: "none",
602
+ setWord() {
603
+ },
604
+ setTextureMix() {
605
+ },
606
+ setPattern() {
607
+ },
608
+ pause() {
609
+ },
610
+ resume() {
611
+ },
612
+ destroy() {
613
+ }
614
+ };
615
+ function createParticleHero(root, options = {}) {
616
+ if (!root) {
617
+ warnOnce("particle-hero: missing element");
618
+ return NONE;
619
+ }
620
+ const existing = instances.get(root);
621
+ if (existing) return existing;
622
+ const t = TIMING.particleHero;
623
+ const rng = random(options.seed ?? 1907);
624
+ const size = Math.round(clamp2(options.size ?? t.size, 32, 256));
625
+ const pointSize = clamp2(options.pointSize ?? t.pointSize, 1, 8);
626
+ const color = options.color ?? [1, 1, 1];
627
+ const words = options.words?.length ? options.words.map(String) : ["CREATE", "NATURAL", "IDEAS"];
628
+ const count = size * size;
629
+ const still = reduced();
630
+ const initial = new Float32Array(count * 4);
631
+ for (let i = 0; i < count; i++) {
632
+ initial[i * 4] = (rng() - 0.5) * 1.7;
633
+ initial[i * 4 + 1] = (rng() - 0.5) * 1.7;
634
+ }
635
+ let mask = wordMask(words[0], count, rng);
636
+ const makeCanvas = () => {
637
+ const canvas2 = document.createElement("canvas");
638
+ canvas2.className = "mk-particle-hero__canvas";
639
+ canvas2.setAttribute("aria-hidden", "true");
640
+ return canvas2;
641
+ };
642
+ let canvas = makeCanvas();
643
+ let renderer = null;
644
+ if (!options.forceFallback) {
645
+ try {
646
+ renderer = gpuRenderer(canvas, size, pointSize, color, initial, mask);
647
+ } catch {
648
+ canvas = makeCanvas();
649
+ }
650
+ }
651
+ if (!renderer) {
652
+ try {
653
+ renderer = canvasRenderer(canvas, size, pointSize, color, initial, mask);
654
+ } catch {
655
+ warnOnce("particle-hero: no WebGL2 and no 2D canvas \u2014 nothing drawn");
656
+ return NONE;
657
+ }
658
+ }
659
+ const draw = renderer;
660
+ const scope = createScope();
661
+ if (!root.classList.contains("mk-particle-hero")) {
662
+ root.classList.add("mk-particle-hero");
663
+ scope.add(() => {
664
+ root.classList.remove("mk-particle-hero");
665
+ if (root.getAttribute("class") === "") root.removeAttribute("class");
666
+ });
667
+ }
668
+ root.append(canvas);
669
+ scope.add(() => canvas.remove());
670
+ scope.attr(root, "data-mk-mode", draw.mode);
671
+ scope.add(() => draw.destroy());
672
+ const state = {
673
+ time: 0,
674
+ dt: 1 / 60,
675
+ mix: still ? 0.8 : 0,
676
+ frequency: 35,
677
+ distortion: 2.4,
678
+ noise: 0.2,
679
+ jitter: 0.08,
680
+ m: 3,
681
+ n: 5,
682
+ mouseX: 9,
683
+ mouseY: 9,
684
+ mouseSpeed: 0,
685
+ pattern: 0,
686
+ aspect: 1,
687
+ dpr: 1,
688
+ opacity: still ? 1 : 0
689
+ };
690
+ let paused = false;
691
+ let age = 0;
692
+ let wordIndex = 0;
693
+ let manualMix = null;
694
+ let nextFrequency = 5;
695
+ let nextModes = 6;
696
+ let distortion = { from: 2.4, to: rng() * 5, start: 0, end: 2.5 };
697
+ let cycle = { stage: 0, start: 0, duration: 4.2, from: 0, to: 0.65 };
698
+ let pointer = { x: 9, y: 9 };
699
+ let previous = { x: 9, y: 9 };
700
+ const drawStill = () => {
701
+ state.opacity = 1;
702
+ state.mix = manualMix ?? 0.8;
703
+ state.mouseSpeed = 0;
704
+ state.dt = 1 / 60;
705
+ draw.render(state, t.stillSteps);
706
+ };
707
+ const isStill = () => still || paused;
708
+ const resize = () => {
709
+ const box = root.getBoundingClientRect();
710
+ const w = Math.max(1, box.width);
711
+ const h = Math.max(1, box.height);
712
+ state.dpr = Math.min(window.devicePixelRatio || 1, t.maxDpr);
713
+ state.aspect = w / h;
714
+ canvas.width = Math.round(w * state.dpr);
715
+ canvas.height = Math.round(h * state.dpr);
716
+ if (isStill()) drawStill();
717
+ };
718
+ const setWord = (word) => {
719
+ if (scope.disposed) return;
720
+ mask = wordMask(String(word), count, rng);
721
+ draw.setMask(mask);
722
+ if (isStill()) drawStill();
723
+ };
724
+ const tick = (frames) => {
725
+ if (paused || scope.disposed) return;
726
+ const dt = clamp2(frames / 60, 0, 0.05);
727
+ age += dt;
728
+ state.time = age * 4;
729
+ state.dt = dt;
730
+ state.opacity = clamp2((age - t.fadeDelay) / t.fadeIn, 0, 1);
731
+ state.mouseX = mix(state.mouseX, pointer.x, 0.1);
732
+ state.mouseY = mix(state.mouseY, pointer.y, 0.1);
733
+ const speed = Math.min(Math.hypot(state.mouseX - previous.x, state.mouseY - previous.y) * 5, 1);
734
+ state.mouseSpeed = mix(state.mouseSpeed, speed, 0.2);
735
+ previous = { x: state.mouseX, y: state.mouseY };
736
+ if (age >= nextFrequency) {
737
+ state.frequency = 20 + rng() * 25;
738
+ state.jitter = rng() * 0.3;
739
+ state.noise = rng() * 0.5;
740
+ nextFrequency = age + 5 + rng() * 5;
741
+ }
742
+ if (age >= nextModes) {
743
+ const modes = [3, 5, 7];
744
+ state.m = modes[Math.floor(rng() * 3)];
745
+ state.n = modes[Math.floor(rng() * 3)];
746
+ nextModes = age + 6 + rng() * 6;
747
+ }
748
+ if (age >= distortion.end) distortion = { from: state.distortion, to: rng() * 5, start: age, end: age + 1.2 + rng() * 1.8 };
749
+ state.distortion = mix(
750
+ distortion.from,
751
+ distortion.to,
752
+ inOut(clamp2((age - distortion.start) / (distortion.end - distortion.start), 0, 1))
753
+ );
754
+ if (age - cycle.start >= cycle.duration) {
755
+ const stage = (cycle.stage + 1) % 3;
756
+ cycle = { stage, start: age, from: cycle.to, to: 0, duration: 2 + rng() };
757
+ if (stage === 0) {
758
+ wordIndex = (wordIndex + 1) % words.length;
759
+ setWord(words[wordIndex]);
760
+ }
761
+ if (stage !== 2) {
762
+ cycle.to = 0.4 + rng() * 0.4;
763
+ cycle.duration = 2 + rng() * 2;
764
+ }
765
+ }
766
+ state.mix = manualMix ?? mix(cycle.from, cycle.to, inOut(clamp2((age - cycle.start) / cycle.duration, 0, 1)));
767
+ draw.render(state);
768
+ };
769
+ scope.on(
770
+ root,
771
+ "pointermove",
772
+ (event) => {
773
+ const box = root.getBoundingClientRect();
774
+ const e = event;
775
+ pointer = {
776
+ x: ((e.clientX - box.left) / Math.max(box.width, 1) * 2 - 1) * Math.max(state.aspect, 1),
777
+ y: 1 - (e.clientY - box.top) / Math.max(box.height, 1) * 2
778
+ };
779
+ },
780
+ { passive: true }
781
+ );
782
+ scope.on(root, "pointerleave", () => pointer = { x: 9, y: 9 }, { passive: true });
783
+ scope.on(canvas, "webglcontextlost", (event) => {
784
+ event.preventDefault();
785
+ paused = true;
786
+ scope.attr(root, "data-mk-mode", "context-lost");
787
+ });
788
+ if (typeof ResizeObserver === "function") scope.observe(new ResizeObserver(resize)).observe(root);
789
+ else scope.on(window, "resize", resize);
790
+ if (!still) scope.add(whileVisible(root, tick, "100px"));
791
+ const instance = {
792
+ mode: draw.mode,
793
+ setWord,
794
+ setTextureMix(value) {
795
+ if (scope.disposed) return;
796
+ manualMix = value === null ? null : clamp2(Number(value) || 0, 0, 1);
797
+ if (isStill()) drawStill();
798
+ },
799
+ setPattern(value) {
800
+ if (scope.disposed) return;
801
+ state.pattern = clamp2(Math.round(Number(value) || 0), 0, 2);
802
+ if (isStill()) drawStill();
803
+ },
804
+ pause() {
805
+ if (!scope.disposed) paused = true;
806
+ },
807
+ resume() {
808
+ if (scope.disposed) return;
809
+ paused = false;
810
+ if (still) drawStill();
811
+ },
812
+ destroy() {
813
+ if (scope.disposed) return;
814
+ scope.dispose();
815
+ instances.delete(root);
816
+ }
817
+ };
818
+ instances.set(root, instance);
819
+ resize();
820
+ if (still) drawStill();
821
+ options.onMode?.(draw.mode);
822
+ return instance;
823
+ }
824
+
825
+ export {
826
+ createLiquidBlend,
827
+ createMatcap,
828
+ createShaderGrain,
829
+ createShaderBlur,
830
+ createParticleHero
831
+ };
832
+ //# sourceMappingURL=chunk-6OJAP6ZL.js.map