@vysmo/transitions 0.1.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 (384) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +618 -0
  3. package/dist/index.d.ts +6 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +3 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/inputs/normalize.d.ts +2 -0
  8. package/dist/inputs/normalize.d.ts.map +1 -0
  9. package/dist/inputs/normalize.js +2 -0
  10. package/dist/inputs/normalize.js.map +1 -0
  11. package/dist/runner/gl.d.ts +7 -0
  12. package/dist/runner/gl.d.ts.map +1 -0
  13. package/dist/runner/gl.js +59 -0
  14. package/dist/runner/gl.js.map +1 -0
  15. package/dist/runner/mesh.d.ts +28 -0
  16. package/dist/runner/mesh.d.ts.map +1 -0
  17. package/dist/runner/mesh.js +96 -0
  18. package/dist/runner/mesh.js.map +1 -0
  19. package/dist/runner/runner.d.ts +107 -0
  20. package/dist/runner/runner.d.ts.map +1 -0
  21. package/dist/runner/runner.js +410 -0
  22. package/dist/runner/runner.js.map +1 -0
  23. package/dist/transitions/all.d.ts +9 -0
  24. package/dist/transitions/all.d.ts.map +1 -0
  25. package/dist/transitions/all.js +129 -0
  26. package/dist/transitions/all.js.map +1 -0
  27. package/dist/transitions/bloom-reveal.d.ts +27 -0
  28. package/dist/transitions/bloom-reveal.d.ts.map +1 -0
  29. package/dist/transitions/bloom-reveal.js +106 -0
  30. package/dist/transitions/bloom-reveal.js.map +1 -0
  31. package/dist/transitions/chromatic-pulse.d.ts +4 -0
  32. package/dist/transitions/chromatic-pulse.d.ts.map +1 -0
  33. package/dist/transitions/chromatic-pulse.js +40 -0
  34. package/dist/transitions/chromatic-pulse.js.map +1 -0
  35. package/dist/transitions/clock-wipe.d.ts +6 -0
  36. package/dist/transitions/clock-wipe.d.ts.map +1 -0
  37. package/dist/transitions/clock-wipe.js +33 -0
  38. package/dist/transitions/clock-wipe.js.map +1 -0
  39. package/dist/transitions/color-phase.d.ts +10 -0
  40. package/dist/transitions/color-phase.d.ts.map +1 -0
  41. package/dist/transitions/color-phase.js +24 -0
  42. package/dist/transitions/color-phase.js.map +1 -0
  43. package/dist/transitions/colour-distance.d.ts.map +1 -0
  44. package/dist/transitions/cross-warp.d.ts.map +1 -0
  45. package/dist/transitions/cross-zoom.d.ts +5 -0
  46. package/dist/transitions/cross-zoom.d.ts.map +1 -0
  47. package/dist/transitions/cross-zoom.js +59 -0
  48. package/dist/transitions/cross-zoom.js.map +1 -0
  49. package/dist/transitions/crosshatch.d.ts +12 -0
  50. package/dist/transitions/crosshatch.d.ts.map +1 -0
  51. package/dist/transitions/crosshatch.js +49 -0
  52. package/dist/transitions/crosshatch.js.map +1 -0
  53. package/dist/transitions/define.d.ts +35 -0
  54. package/dist/transitions/define.d.ts.map +1 -0
  55. package/dist/transitions/define.js +37 -0
  56. package/dist/transitions/define.js.map +1 -0
  57. package/dist/transitions/directional-burn.d.ts +14 -0
  58. package/dist/transitions/directional-burn.d.ts.map +1 -0
  59. package/dist/transitions/directional-burn.js +67 -0
  60. package/dist/transitions/directional-burn.js.map +1 -0
  61. package/dist/transitions/directional-warp.d.ts +12 -0
  62. package/dist/transitions/directional-warp.d.ts.map +1 -0
  63. package/dist/transitions/directional-warp.js +46 -0
  64. package/dist/transitions/directional-warp.js.map +1 -0
  65. package/dist/transitions/dissolve.d.ts +2 -0
  66. package/dist/transitions/dissolve.d.ts.map +1 -0
  67. package/dist/transitions/dissolve.js +16 -0
  68. package/dist/transitions/dissolve.js.map +1 -0
  69. package/dist/transitions/dreamy-zoom.d.ts +25 -0
  70. package/dist/transitions/dreamy-zoom.d.ts.map +1 -0
  71. package/dist/transitions/dreamy-zoom.js +66 -0
  72. package/dist/transitions/dreamy-zoom.js.map +1 -0
  73. package/dist/transitions/dreamy.d.ts +8 -0
  74. package/dist/transitions/dreamy.d.ts.map +1 -0
  75. package/dist/transitions/dreamy.js +26 -0
  76. package/dist/transitions/dreamy.js.map +1 -0
  77. package/dist/transitions/drip-wipe.d.ts +22 -0
  78. package/dist/transitions/drip-wipe.d.ts.map +1 -0
  79. package/dist/transitions/drip-wipe.js +109 -0
  80. package/dist/transitions/drip-wipe.js.map +1 -0
  81. package/dist/transitions/ember-scatter.d.ts +22 -0
  82. package/dist/transitions/ember-scatter.d.ts.map +1 -0
  83. package/dist/transitions/ember-scatter.js +94 -0
  84. package/dist/transitions/ember-scatter.js.map +1 -0
  85. package/dist/transitions/film-burn.d.ts +17 -0
  86. package/dist/transitions/film-burn.d.ts.map +1 -0
  87. package/dist/transitions/film-burn.js +101 -0
  88. package/dist/transitions/film-burn.js.map +1 -0
  89. package/dist/transitions/film-grain.d.ts +24 -0
  90. package/dist/transitions/film-grain.d.ts.map +1 -0
  91. package/dist/transitions/film-grain.js +78 -0
  92. package/dist/transitions/film-grain.js.map +1 -0
  93. package/dist/transitions/flow-warp.d.ts +20 -0
  94. package/dist/transitions/flow-warp.d.ts.map +1 -0
  95. package/dist/transitions/flow-warp.js +51 -0
  96. package/dist/transitions/flow-warp.js.map +1 -0
  97. package/dist/transitions/fluid-flow.d.ts +26 -0
  98. package/dist/transitions/fluid-flow.d.ts.map +1 -0
  99. package/dist/transitions/fluid-flow.js +94 -0
  100. package/dist/transitions/fluid-flow.js.map +1 -0
  101. package/dist/transitions/fly-eye.d.ts.map +1 -0
  102. package/dist/transitions/fly-eye.js +58 -0
  103. package/dist/transitions/fly-eye.js.map +1 -0
  104. package/dist/transitions/glass-shatter.d.ts +25 -0
  105. package/dist/transitions/glass-shatter.d.ts.map +1 -0
  106. package/dist/transitions/glass-shatter.js +86 -0
  107. package/dist/transitions/glass-shatter.js.map +1 -0
  108. package/dist/transitions/glitch.d.ts +6 -0
  109. package/dist/transitions/glitch.d.ts.map +1 -0
  110. package/dist/transitions/glitch.js +59 -0
  111. package/dist/transitions/glitch.js.map +1 -0
  112. package/dist/transitions/god-rays-reveal.d.ts +32 -0
  113. package/dist/transitions/god-rays-reveal.d.ts.map +1 -0
  114. package/dist/transitions/god-rays-reveal.js +110 -0
  115. package/dist/transitions/god-rays-reveal.js.map +1 -0
  116. package/dist/transitions/gravity-pull.d.ts +16 -0
  117. package/dist/transitions/gravity-pull.d.ts.map +1 -0
  118. package/dist/transitions/gravity-pull.js +65 -0
  119. package/dist/transitions/gravity-pull.js.map +1 -0
  120. package/dist/transitions/grid-reveal.d.ts +12 -0
  121. package/dist/transitions/grid-reveal.d.ts.map +1 -0
  122. package/dist/transitions/grid-reveal.js +53 -0
  123. package/dist/transitions/grid-reveal.js.map +1 -0
  124. package/dist/transitions/heat-haze.d.ts +13 -0
  125. package/dist/transitions/heat-haze.d.ts.map +1 -0
  126. package/dist/transitions/heat-haze.js +51 -0
  127. package/dist/transitions/heat-haze.js.map +1 -0
  128. package/dist/transitions/index.d.ts +64 -0
  129. package/dist/transitions/index.d.ts.map +1 -0
  130. package/dist/transitions/index.js +63 -0
  131. package/dist/transitions/index.js.map +1 -0
  132. package/dist/transitions/ink-bloom.d.ts +15 -0
  133. package/dist/transitions/ink-bloom.d.ts.map +1 -0
  134. package/dist/transitions/ink-bloom.js +76 -0
  135. package/dist/transitions/ink-bloom.js.map +1 -0
  136. package/dist/transitions/ink-diffuse.d.ts +26 -0
  137. package/dist/transitions/ink-diffuse.d.ts.map +1 -0
  138. package/dist/transitions/ink-diffuse.js +90 -0
  139. package/dist/transitions/ink-diffuse.js.map +1 -0
  140. package/dist/transitions/iris-zoom.d.ts +13 -0
  141. package/dist/transitions/iris-zoom.d.ts.map +1 -0
  142. package/dist/transitions/iris-zoom.js +67 -0
  143. package/dist/transitions/iris-zoom.js.map +1 -0
  144. package/dist/transitions/kinetic-bands.d.ts +7 -0
  145. package/dist/transitions/kinetic-bands.d.ts.map +1 -0
  146. package/dist/transitions/kinetic-bands.js +58 -0
  147. package/dist/transitions/kinetic-bands.js.map +1 -0
  148. package/dist/transitions/lenticular-flip.d.ts +22 -0
  149. package/dist/transitions/lenticular-flip.d.ts.map +1 -0
  150. package/dist/transitions/lenticular-flip.js +73 -0
  151. package/dist/transitions/lenticular-flip.js.map +1 -0
  152. package/dist/transitions/light-leak.d.ts +7 -0
  153. package/dist/transitions/light-leak.d.ts.map +1 -0
  154. package/dist/transitions/light-leak.js +43 -0
  155. package/dist/transitions/light-leak.js.map +1 -0
  156. package/dist/transitions/lightning-strike.d.ts +22 -0
  157. package/dist/transitions/lightning-strike.d.ts.map +1 -0
  158. package/dist/transitions/lightning-strike.js +90 -0
  159. package/dist/transitions/lightning-strike.js.map +1 -0
  160. package/dist/transitions/linear-blur.d.ts +11 -0
  161. package/dist/transitions/linear-blur.d.ts.map +1 -0
  162. package/dist/transitions/linear-blur.js +40 -0
  163. package/dist/transitions/linear-blur.js.map +1 -0
  164. package/dist/transitions/liquid-chrome.d.ts +22 -0
  165. package/dist/transitions/liquid-chrome.d.ts.map +1 -0
  166. package/dist/transitions/liquid-chrome.js +114 -0
  167. package/dist/transitions/liquid-chrome.js.map +1 -0
  168. package/dist/transitions/liquid-morph.d.ts +6 -0
  169. package/dist/transitions/liquid-morph.d.ts.map +1 -0
  170. package/dist/transitions/liquid-morph.js +50 -0
  171. package/dist/transitions/liquid-morph.js.map +1 -0
  172. package/dist/transitions/lumina-melt.d.ts +11 -0
  173. package/dist/transitions/lumina-melt.d.ts.map +1 -0
  174. package/dist/transitions/lumina-melt.js +36 -0
  175. package/dist/transitions/lumina-melt.js.map +1 -0
  176. package/dist/transitions/mosaic.d.ts +13 -0
  177. package/dist/transitions/mosaic.d.ts.map +1 -0
  178. package/dist/transitions/mosaic.js +58 -0
  179. package/dist/transitions/mosaic.js.map +1 -0
  180. package/dist/transitions/noise-dissolve.d.ts +5 -0
  181. package/dist/transitions/noise-dissolve.d.ts.map +1 -0
  182. package/dist/transitions/noise-dissolve.js +41 -0
  183. package/dist/transitions/noise-dissolve.js.map +1 -0
  184. package/dist/transitions/page-curl.d.ts +32 -0
  185. package/dist/transitions/page-curl.d.ts.map +1 -0
  186. package/dist/transitions/page-curl.js +165 -0
  187. package/dist/transitions/page-curl.js.map +1 -0
  188. package/dist/transitions/paint-bleed.d.ts +12 -0
  189. package/dist/transitions/paint-bleed.d.ts.map +1 -0
  190. package/dist/transitions/paint-bleed.js +59 -0
  191. package/dist/transitions/paint-bleed.js.map +1 -0
  192. package/dist/transitions/particle-assemble.d.ts +23 -0
  193. package/dist/transitions/particle-assemble.d.ts.map +1 -0
  194. package/dist/transitions/particle-assemble.js +65 -0
  195. package/dist/transitions/particle-assemble.js.map +1 -0
  196. package/dist/transitions/pinwheel.d.ts +11 -0
  197. package/dist/transitions/pinwheel.d.ts.map +1 -0
  198. package/dist/transitions/pinwheel.js +40 -0
  199. package/dist/transitions/pinwheel.js.map +1 -0
  200. package/dist/transitions/pixelate.d.ts +4 -0
  201. package/dist/transitions/pixelate.d.ts.map +1 -0
  202. package/dist/transitions/pixelate.js +26 -0
  203. package/dist/transitions/pixelate.js.map +1 -0
  204. package/dist/transitions/plasma-pulse.d.ts.map +1 -0
  205. package/dist/transitions/plasma-pulse.js +92 -0
  206. package/dist/transitions/plasma-pulse.js.map +1 -0
  207. package/dist/transitions/polka-dots-curtain.d.ts +13 -0
  208. package/dist/transitions/polka-dots-curtain.d.ts.map +1 -0
  209. package/dist/transitions/polka-dots-curtain.js +46 -0
  210. package/dist/transitions/polka-dots-curtain.js.map +1 -0
  211. package/dist/transitions/polygon-flip.d.ts +27 -0
  212. package/dist/transitions/polygon-flip.d.ts.map +1 -0
  213. package/dist/transitions/polygon-flip.js +97 -0
  214. package/dist/transitions/polygon-flip.js.map +1 -0
  215. package/dist/transitions/portal-dive.d.ts +18 -0
  216. package/dist/transitions/portal-dive.d.ts.map +1 -0
  217. package/dist/transitions/portal-dive.js +83 -0
  218. package/dist/transitions/portal-dive.js.map +1 -0
  219. package/dist/transitions/prism-split.d.ts +12 -0
  220. package/dist/transitions/prism-split.d.ts.map +1 -0
  221. package/dist/transitions/prism-split.js +52 -0
  222. package/dist/transitions/prism-split.js.map +1 -0
  223. package/dist/transitions/push.d.ts +4 -0
  224. package/dist/transitions/push.d.ts.map +1 -0
  225. package/dist/transitions/push.js +34 -0
  226. package/dist/transitions/push.js.map +1 -0
  227. package/dist/transitions/radial-reveal.d.ts +5 -0
  228. package/dist/transitions/radial-reveal.d.ts.map +1 -0
  229. package/dist/transitions/radial-reveal.js +31 -0
  230. package/dist/transitions/radial-reveal.js.map +1 -0
  231. package/dist/transitions/ripple-wave.d.ts +24 -0
  232. package/dist/transitions/ripple-wave.d.ts.map +1 -0
  233. package/dist/transitions/ripple-wave.js +135 -0
  234. package/dist/transitions/ripple-wave.js.map +1 -0
  235. package/dist/transitions/ripple.d.ts +7 -0
  236. package/dist/transitions/ripple.d.ts.map +1 -0
  237. package/dist/transitions/ripple.js +43 -0
  238. package/dist/transitions/ripple.js.map +1 -0
  239. package/dist/transitions/shape-reveal.d.ts +12 -0
  240. package/dist/transitions/shape-reveal.d.ts.map +1 -0
  241. package/dist/transitions/shape-reveal.js +53 -0
  242. package/dist/transitions/shape-reveal.js.map +1 -0
  243. package/dist/transitions/shockwave.d.ts +10 -0
  244. package/dist/transitions/shockwave.d.ts.map +1 -0
  245. package/dist/transitions/shockwave.js +56 -0
  246. package/dist/transitions/shockwave.js.map +1 -0
  247. package/dist/transitions/singularity.d.ts +22 -0
  248. package/dist/transitions/singularity.d.ts.map +1 -0
  249. package/dist/transitions/singularity.js +59 -0
  250. package/dist/transitions/singularity.js.map +1 -0
  251. package/dist/transitions/slide.d.ts +10 -0
  252. package/dist/transitions/slide.d.ts.map +1 -0
  253. package/dist/transitions/slide.js +76 -0
  254. package/dist/transitions/slide.js.map +1 -0
  255. package/dist/transitions/smoldering-edge.d.ts +15 -0
  256. package/dist/transitions/smoldering-edge.d.ts.map +1 -0
  257. package/dist/transitions/smoldering-edge.js +74 -0
  258. package/dist/transitions/smoldering-edge.js.map +1 -0
  259. package/dist/transitions/split.d.ts +14 -0
  260. package/dist/transitions/split.d.ts.map +1 -0
  261. package/dist/transitions/split.js +53 -0
  262. package/dist/transitions/split.js.map +1 -0
  263. package/dist/transitions/swirl.d.ts +12 -0
  264. package/dist/transitions/swirl.d.ts.map +1 -0
  265. package/dist/transitions/swirl.js +42 -0
  266. package/dist/transitions/swirl.js.map +1 -0
  267. package/dist/transitions/tangent-motion-blur.d.ts +13 -0
  268. package/dist/transitions/tangent-motion-blur.d.ts.map +1 -0
  269. package/dist/transitions/tangent-motion-blur.js +58 -0
  270. package/dist/transitions/tangent-motion-blur.js.map +1 -0
  271. package/dist/transitions/tile-scatter.d.ts +22 -0
  272. package/dist/transitions/tile-scatter.d.ts.map +1 -0
  273. package/dist/transitions/tile-scatter.js +122 -0
  274. package/dist/transitions/tile-scatter.js.map +1 -0
  275. package/dist/transitions/tilt-sweep.d.ts +11 -0
  276. package/dist/transitions/tilt-sweep.d.ts.map +1 -0
  277. package/dist/transitions/tilt-sweep.js +31 -0
  278. package/dist/transitions/tilt-sweep.js.map +1 -0
  279. package/dist/transitions/warp-zoom.d.ts +7 -0
  280. package/dist/transitions/warp-zoom.d.ts.map +1 -0
  281. package/dist/transitions/warp-zoom.js +70 -0
  282. package/dist/transitions/warp-zoom.js.map +1 -0
  283. package/dist/transitions/wave-stripes.d.ts +16 -0
  284. package/dist/transitions/wave-stripes.d.ts.map +1 -0
  285. package/dist/transitions/wave-stripes.js +55 -0
  286. package/dist/transitions/wave-stripes.js.map +1 -0
  287. package/dist/transitions/wave-wipe.d.ts +23 -0
  288. package/dist/transitions/wave-wipe.d.ts.map +1 -0
  289. package/dist/transitions/wave-wipe.js +84 -0
  290. package/dist/transitions/wave-wipe.js.map +1 -0
  291. package/dist/transitions/wind.d.ts +9 -0
  292. package/dist/transitions/wind.d.ts.map +1 -0
  293. package/dist/transitions/wind.js +48 -0
  294. package/dist/transitions/wind.js.map +1 -0
  295. package/dist/transitions/window-slice.d.ts +11 -0
  296. package/dist/transitions/window-slice.d.ts.map +1 -0
  297. package/dist/transitions/window-slice.js +34 -0
  298. package/dist/transitions/window-slice.js.map +1 -0
  299. package/dist/transitions/wipe-directional.d.ts +5 -0
  300. package/dist/transitions/wipe-directional.d.ts.map +1 -0
  301. package/dist/transitions/wipe-directional.js +26 -0
  302. package/dist/transitions/wipe-directional.js.map +1 -0
  303. package/dist/types.d.ts +78 -0
  304. package/dist/types.d.ts.map +1 -0
  305. package/dist/types.js +2 -0
  306. package/dist/types.js.map +1 -0
  307. package/package.json +56 -0
  308. package/src/__tests__/__screenshots__/endpoint-correctness.test.ts/endpoint-correctness---every-transition-must-be-pixel-pure-from-to-at-progress-0-1-rippleWave-at-progress-0-is-pure--from--1.png +0 -0
  309. package/src/__tests__/__screenshots__/endpoint-correctness.test.ts/endpoint-correctness---every-transition-must-be-pixel-pure-from-to-at-progress-0-1-rippleWave-at-progress-1-is-pure--to--1.png +0 -0
  310. package/src/__tests__/endpoint-correctness.test.ts +161 -0
  311. package/src/__tests__/readme.test.ts +39 -0
  312. package/src/__tests__/ssr.test.ts +45 -0
  313. package/src/index.ts +75 -0
  314. package/src/inputs/normalize.ts +1 -0
  315. package/src/runner/__tests__/__screenshots__/mesh.test.ts/buildSubdividedPlane-centroid-is-shared-across-a-face-and-equals-mean-of-its-3-positions-1.png +0 -0
  316. package/src/runner/__tests__/__screenshots__/mesh.test.ts/buildSubdividedPlane-uv-matches-aPosition---0-5---0-5-1.png +0 -0
  317. package/src/runner/__tests__/mesh.test.ts +128 -0
  318. package/src/runner/gl.ts +69 -0
  319. package/src/runner/mesh.ts +135 -0
  320. package/src/runner/runner.ts +528 -0
  321. package/src/transitions/all.ts +131 -0
  322. package/src/transitions/bloom-reveal.ts +106 -0
  323. package/src/transitions/chromatic-pulse.ts +40 -0
  324. package/src/transitions/clock-wipe.ts +33 -0
  325. package/src/transitions/color-phase.ts +24 -0
  326. package/src/transitions/cross-zoom.ts +59 -0
  327. package/src/transitions/crosshatch.ts +49 -0
  328. package/src/transitions/define.ts +56 -0
  329. package/src/transitions/directional-burn.ts +67 -0
  330. package/src/transitions/directional-warp.ts +46 -0
  331. package/src/transitions/dissolve.ts +16 -0
  332. package/src/transitions/dreamy-zoom.ts +66 -0
  333. package/src/transitions/dreamy.ts +26 -0
  334. package/src/transitions/drip-wipe.ts +109 -0
  335. package/src/transitions/ember-scatter.ts +94 -0
  336. package/src/transitions/film-burn.ts +101 -0
  337. package/src/transitions/film-grain.ts +78 -0
  338. package/src/transitions/flow-warp.ts +51 -0
  339. package/src/transitions/fluid-flow.ts +94 -0
  340. package/src/transitions/glass-shatter.ts +86 -0
  341. package/src/transitions/glitch.ts +59 -0
  342. package/src/transitions/god-rays-reveal.ts +110 -0
  343. package/src/transitions/gravity-pull.ts +65 -0
  344. package/src/transitions/grid-reveal.ts +53 -0
  345. package/src/transitions/heat-haze.ts +51 -0
  346. package/src/transitions/index.ts +63 -0
  347. package/src/transitions/ink-bloom.ts +76 -0
  348. package/src/transitions/ink-diffuse.ts +90 -0
  349. package/src/transitions/iris-zoom.ts +67 -0
  350. package/src/transitions/kinetic-bands.ts +58 -0
  351. package/src/transitions/lenticular-flip.ts +73 -0
  352. package/src/transitions/light-leak.ts +43 -0
  353. package/src/transitions/linear-blur.ts +40 -0
  354. package/src/transitions/liquid-chrome.ts +114 -0
  355. package/src/transitions/liquid-morph.ts +50 -0
  356. package/src/transitions/lumina-melt.ts +36 -0
  357. package/src/transitions/mosaic.ts +58 -0
  358. package/src/transitions/noise-dissolve.ts +41 -0
  359. package/src/transitions/page-curl.ts +165 -0
  360. package/src/transitions/paint-bleed.ts +59 -0
  361. package/src/transitions/pinwheel.ts +40 -0
  362. package/src/transitions/pixelate.ts +26 -0
  363. package/src/transitions/polka-dots-curtain.ts +46 -0
  364. package/src/transitions/polygon-flip.ts +97 -0
  365. package/src/transitions/portal-dive.ts +83 -0
  366. package/src/transitions/prism-split.ts +52 -0
  367. package/src/transitions/push.ts +34 -0
  368. package/src/transitions/radial-reveal.ts +31 -0
  369. package/src/transitions/ripple-wave.ts +135 -0
  370. package/src/transitions/ripple.ts +43 -0
  371. package/src/transitions/shape-reveal.ts +53 -0
  372. package/src/transitions/shockwave.ts +56 -0
  373. package/src/transitions/singularity.ts +59 -0
  374. package/src/transitions/slide.ts +76 -0
  375. package/src/transitions/smoldering-edge.ts +74 -0
  376. package/src/transitions/split.ts +53 -0
  377. package/src/transitions/swirl.ts +42 -0
  378. package/src/transitions/tangent-motion-blur.ts +58 -0
  379. package/src/transitions/tile-scatter.ts +122 -0
  380. package/src/transitions/warp-zoom.ts +70 -0
  381. package/src/transitions/wave-stripes.ts +55 -0
  382. package/src/transitions/wind.ts +48 -0
  383. package/src/transitions/wipe-directional.ts +26 -0
  384. package/src/types.ts +87 -0
@@ -0,0 +1,73 @@
1
+ import { defineTransition } from "./define.js";
2
+
3
+ /**
4
+ * Hologram-card flip. The frame is divided into vertical strips, each
5
+ * modelled as a narrow rectangle that rotates around its vertical axis
6
+ * from 0 (showing from face-on) through 90° (edge-on — content pinches
7
+ * to zero width) to 180° (showing to face-on). Flip timing is
8
+ * staggered across strips left → right, so a wavefront of flipping
9
+ * strips sweeps across the image.
10
+ *
11
+ * Perspective is faked by compressing strip content to fit the
12
+ * visible half-width |cos(rotation)| · stripWidth/2. When a strip is
13
+ * edge-on, its visible half-width is zero and every pixel falls into
14
+ * the "crease" region, which fills with a mix(from, to, flipT) so
15
+ * the full-frame rule holds (no black cracks).
16
+ *
17
+ * Endpoints: at progress 0 every strip is at flipT=0 (cos=1, full
18
+ * visibility, sampling from at the correct uv). At progress 1 every
19
+ * strip is at flipT=1 (cos=-1, full visibility, sampling to).
20
+ */
21
+ export const lenticularFlip = defineTransition({
22
+ name: "lenticular-flip",
23
+ defaults: {
24
+ stripCount: 22,
25
+ },
26
+ glsl: `
27
+ uniform float uStripCount;
28
+
29
+ vec4 transition(vec2 uv) {
30
+ // stripCount<3 collapses to a single full-canvas flip (1) or a half-and-half
31
+ // (2) — neither reads as "lenticular". Clamp here so the transition is
32
+ // reliable regardless of caller input.
33
+ float stripCount = max(uStripCount, 3.0);
34
+
35
+ float stripF = uv.x * stripCount;
36
+ float stripIdx = floor(stripF);
37
+ float localU = fract(stripF);
38
+
39
+ // Staggered flip timing: each strip flips over a window of 0.5 in
40
+ // progress. The window's start scales from 0 (leftmost strip) to
41
+ // 0.5 (rightmost strip), so the wave finishes exactly at progress 1.
42
+ float stripStart = stripIdx / stripCount;
43
+ float windowStart = stripStart * 0.5;
44
+ float flipT = smoothstep(windowStart, windowStart + 0.5, uProgress);
45
+
46
+ // Strip rotation: 0 at flipT=0, PI at flipT=1.
47
+ float rotAngle = flipT * 3.14159265;
48
+ float cosRot = cos(rotAngle);
49
+ float visibleHalfWidth = abs(cosRot) * 0.5;
50
+
51
+ // Local coord centred in the strip, range [-0.5, 0.5].
52
+ float centered = localU - 0.5;
53
+
54
+ // Decompress: map visible [-vhw, vhw] back to [0, 1] strip-local,
55
+ // clamped so out-of-window pixels sample the strip's edge cleanly
56
+ // (instead of out-of-strip or out-of-canvas).
57
+ float decompressed = clamp((centered / max(visibleHalfWidth, 0.0001) + 1.0) * 0.5, 0.0, 1.0);
58
+ vec2 sampleUv = vec2((stripIdx + decompressed) / stripCount, uv.y);
59
+ vec4 stripColor = cosRot >= 0.0 ? getFromColor(sampleUv) : getToColor(sampleUv);
60
+
61
+ // Crease fallback: outside the visible window, crossfade from→to so
62
+ // we never emit a black pixel. Feather across a small band at the
63
+ // boundary so the spatial edge between "compressed strip sample" and
64
+ // "crossfade crease" doesn't read as a 1-pixel flickering line —
65
+ // those two values are computed from completely different source
66
+ // positions and the hard step between them was the visible artifact.
67
+ vec4 creaseColor = mix(getFromColor(uv), getToColor(uv), flipT);
68
+ float feather = 1.0 / stripCount * 0.04;
69
+ float t = smoothstep(visibleHalfWidth - feather, visibleHalfWidth + feather, abs(centered));
70
+ return mix(stripColor, creaseColor, t);
71
+ }
72
+ `,
73
+ });
@@ -0,0 +1,43 @@
1
+ import { defineTransition } from "./define.js";
2
+
3
+ export const lightLeak = defineTransition({
4
+ name: "light-leak",
5
+ defaults: {
6
+ direction: [1, 0],
7
+ color: [1.0, 0.85, 0.55],
8
+ bandWidth: 0.2,
9
+ intensity: 1.0,
10
+ },
11
+ glsl: `
12
+ uniform vec2 uDirection;
13
+ uniform vec3 uColor;
14
+ uniform float uBandWidth;
15
+ uniform float uIntensity;
16
+
17
+ vec4 transition(vec2 uv) {
18
+ vec2 d = normalize(uDirection);
19
+ // Scale by maxProj so diagonal directions clear corners at endpoints
20
+ // (see paint-bleed.ts).
21
+ float maxProj = max((abs(d.x) + abs(d.y)) * 0.5, 0.0001);
22
+ float projected = dot(uv - 0.5, -d);
23
+
24
+ // Boundary sweeps from just beyond the trailing edge to just beyond the
25
+ // leading edge (offset by bandWidth so the bloom zone clears both edges
26
+ // cleanly at the endpoints).
27
+ float boundary = (maxProj + uBandWidth) * (1.0 - 2.0 * uProgress);
28
+
29
+ // Which side of the boundary? 0 = still from, 1 = already to.
30
+ float sweep = smoothstep(-uBandWidth * 0.5, uBandWidth * 0.5, projected - boundary);
31
+ vec4 baseColor = mix(getFromColor(uv), getToColor(uv), sweep);
32
+
33
+ // Gaussian-ish bloom centered on the boundary, scaled to zero at endpoints.
34
+ float env = 4.0 * uProgress * (1.0 - uProgress);
35
+ float distToBand = abs(projected - boundary);
36
+ float bandX = distToBand / max(uBandWidth, 0.0001);
37
+ float bandIntensity = exp(-bandX * bandX * 4.0) * env * uIntensity;
38
+
39
+ vec3 bloomed = baseColor.rgb + uColor * bandIntensity;
40
+ return vec4(bloomed, baseColor.a);
41
+ }
42
+ `,
43
+ });
@@ -0,0 +1,40 @@
1
+ import { defineTransition } from "./define.js";
2
+
3
+ /**
4
+ * Directional linear blur. 32 samples along a configurable axis, avoiding
5
+ * the 2D grid artifacts that box-blur kernels produce at high displacement.
6
+ * Blur amount peaks at the midpoint (triangular envelope), linear crossfade
7
+ * across the full progress range.
8
+ */
9
+ export const linearBlur = defineTransition({
10
+ name: "linear-blur",
11
+ defaults: {
12
+ direction: [1, 0],
13
+ intensity: 0.1,
14
+ },
15
+ glsl: `
16
+ uniform vec2 uDirection;
17
+ uniform float uIntensity;
18
+
19
+ const int SAMPLES = 32;
20
+
21
+ vec4 transition(vec2 uv) {
22
+ vec2 d = normalize(uDirection);
23
+ // Triangular envelope: zero at endpoints, peaks at p=0.5.
24
+ float disp = uIntensity * (0.5 - distance(0.5, uProgress)) * 2.0;
25
+
26
+ vec4 c1 = vec4(0.0);
27
+ vec4 c2 = vec4(0.0);
28
+ for (int i = 0; i < SAMPLES; i++) {
29
+ float t = (float(i) - float(SAMPLES - 1) * 0.5) / float(SAMPLES - 1);
30
+ vec2 off = d * disp * t;
31
+ c1 += getFromColor(uv + off);
32
+ c2 += getToColor(uv + off);
33
+ }
34
+ c1 /= float(SAMPLES);
35
+ c2 /= float(SAMPLES);
36
+
37
+ return mix(c1, c2, uProgress);
38
+ }
39
+ `,
40
+ });
@@ -0,0 +1,114 @@
1
+ import { defineTransition } from "./define.js";
2
+
3
+ /**
4
+ * A liquid-metal blob expands from the centre, showing `to` through its
5
+ * glossy surface. The silhouette is a three-lobe metaball with small
6
+ * orbital wobbles so the boundary feels organic rather than a clean
7
+ * circle. Inside the blob, a fake specular highlight (overhead-left
8
+ * light) and rim brightening derived from the sampled `to` luminance
9
+ * produce the T-1000 chrome read — all gain derived from sampled content,
10
+ * so the full-frame rule holds (no synthetic white).
11
+ *
12
+ * Sample UVs only ever shift inward, so the clamp stays a no-op (no
13
+ * radial streaks from out-of-bounds reads). Specular + rim + refraction
14
+ * all scale by a `4·p·(1-p)` envelope, so at progress 0 and 1 the
15
+ * mercury shading collapses to pure from/to respectively.
16
+ */
17
+ export const liquidChrome = defineTransition({
18
+ name: "liquid-chrome",
19
+ defaults: {
20
+ shine: 0.9,
21
+ rim: 0.25,
22
+ wobble: 0.12,
23
+ refraction: 0.035,
24
+ reflection: 0.0,
25
+ },
26
+ glsl: `
27
+ uniform float uShine;
28
+ uniform float uRim;
29
+ uniform float uWobble;
30
+ uniform float uRefraction;
31
+ uniform float uReflection;
32
+
33
+ // Polynomial smooth-min for organic metaball union.
34
+ float smin(float a, float b, float k) {
35
+ float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0);
36
+ return mix(b, a, h) - k * h * (1.0 - h);
37
+ }
38
+
39
+ vec4 transition(vec2 uv) {
40
+ float aspect = uResolution.x / uResolution.y;
41
+ vec2 c = vec2(0.5);
42
+ vec2 aDelta = vec2((uv.x - c.x) * aspect, uv.y - c.y);
43
+ float maxR = sqrt(aspect * aspect * 0.25 + 0.25);
44
+
45
+ // Blob radius grows from fully off-frame (negative) to comfortably
46
+ // past the farthest corner — guarantees clean endpoints.
47
+ float blobR = mix(-0.2, maxR + 0.25, uProgress);
48
+
49
+ // Orbital wobble: two small satellite blobs on curved paths. At
50
+ // progress=0 blobR is negative so they're already off-frame; at
51
+ // progress=1 blobR is huge so wobble is subsumed into the main mass.
52
+ float t = uProgress;
53
+ vec2 o1 = vec2(sin(t * 8.0), cos(t * 6.0)) * uWobble;
54
+ vec2 o2 = vec2(cos(t * 7.0), -sin(t * 5.0)) * uWobble;
55
+
56
+ // Three-lobe SDF, union via smooth-min.
57
+ float d1 = length(aDelta) - blobR;
58
+ float d2 = length(aDelta - o1 * 0.35) - blobR * 0.82;
59
+ float d3 = length(aDelta - o2 * 0.35) - blobR * 0.82;
60
+ float d = smin(smin(d1, d2, 0.08), d3, 0.08);
61
+
62
+ // Inside-blob membership, with a narrow soft edge so the silhouette
63
+ // doesn't alias but the body stays crisp.
64
+ float insideMask = 1.0 - smoothstep(-0.006, 0.006, d);
65
+
66
+ // Envelope so all surface shading vanishes at the endpoints.
67
+ float envelope = 4.0 * uProgress * (1.0 - uProgress);
68
+
69
+ // Depth within blob: 0 at centre, 1 at rim.
70
+ float depthT = clamp(1.0 + d / max(blobR, 0.001), 0.0, 1.0);
71
+
72
+ // Radial direction from blob core. Used for both refraction offset
73
+ // and as a cheap surface-normal approximation for shading.
74
+ vec2 nDir = length(aDelta) > 1e-4 ? aDelta / length(aDelta) : vec2(0.0);
75
+
76
+ // Refraction: sample to from slightly inward — depth-T weighted so
77
+ // the centre is undistorted and the rim bends sharpest. Stays in
78
+ // bounds because the shift is always toward the blob core.
79
+ float refract = uRefraction * depthT * envelope;
80
+ vec2 refractOffset = nDir * refract;
81
+ vec2 refractUv = clamp(uv - vec2(refractOffset.x / aspect, refractOffset.y), 0.0, 1.0);
82
+ vec4 toSample = getToColor(refractUv);
83
+
84
+ // Specular: fake overhead-left light bouncing off the "normal".
85
+ vec2 lightDir = vec2(-0.7071, -0.7071);
86
+ float lightDot = max(dot(nDir, lightDir), 0.0);
87
+ float specBand = smoothstep(0.35, 0.95, depthT);
88
+ float spec = pow(lightDot, 6.0) * specBand * envelope;
89
+
90
+ // Rim brightening near the silhouette. Ramp by depthT so only the
91
+ // outer shell of the blob catches the rim.
92
+ float rimShell = smoothstep(0.82, 1.0, depthT);
93
+ float rimAmt = rimShell * envelope * uRim;
94
+
95
+ // Apply gain from sampled luminance — keeps all output within content.
96
+ float lum = dot(toSample.rgb, vec3(0.299, 0.587, 0.114));
97
+ vec3 chromed = toSample.rgb + (1.0 - toSample.rgb) * lum * (spec * uShine + rimAmt);
98
+
99
+ // Environment reflection: sample the env map using the surface normal
100
+ // direction as a (coarse) env lookup, and blend stronger at the rim
101
+ // where fresnel would peak on a real dielectric. Gated by uReflection
102
+ // so the default (0) is a no-op; envelope keeps endpoints clean.
103
+ if (uReflection > 0.0) {
104
+ vec2 envUv = vec2(0.5 + 0.5 * nDir.x, 0.5 - 0.5 * nDir.y);
105
+ vec3 envColor = getEnvironment(envUv).rgb;
106
+ float reflectBand = mix(0.15, 0.9, depthT) * envelope * uReflection;
107
+ chromed = mix(chromed, envColor, reflectBand);
108
+ }
109
+
110
+ vec4 fromColor = getFromColor(uv);
111
+ return mix(fromColor, vec4(chromed, 1.0), insideMask);
112
+ }
113
+ `,
114
+ });
@@ -0,0 +1,50 @@
1
+ import { defineTransition } from "./define.js";
2
+
3
+ export const liquidMorph = defineTransition({
4
+ name: "liquid-morph",
5
+ defaults: {
6
+ scale: 3,
7
+ strength: 0.1,
8
+ flow: 3,
9
+ },
10
+ glsl: `
11
+ uniform float uScale;
12
+ uniform float uStrength;
13
+ uniform float uFlow;
14
+
15
+ float hash21(vec2 p) {
16
+ return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
17
+ }
18
+
19
+ float valueNoise(vec2 p) {
20
+ vec2 i = floor(p);
21
+ vec2 f = fract(p);
22
+ f = f * f * (3.0 - 2.0 * f);
23
+ float a = hash21(i);
24
+ float b = hash21(i + vec2(1.0, 0.0));
25
+ float c = hash21(i + vec2(0.0, 1.0));
26
+ float d = hash21(i + vec2(1.0, 1.0));
27
+ return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
28
+ }
29
+
30
+ // Evolving 2D flow field: noise shifts over progress so the distortion
31
+ // pattern moves, not just scales.
32
+ vec2 flow(vec2 p, float t) {
33
+ float nx = valueNoise(p + vec2(t, 0.0));
34
+ float ny = valueNoise(p + vec2(0.0, t) + vec2(13.7, 7.2));
35
+ return vec2(nx, ny) - 0.5;
36
+ }
37
+
38
+ vec4 transition(vec2 uv) {
39
+ // Envelope zeroes at endpoints, peaks mid-transition.
40
+ float env = 4.0 * uProgress * (1.0 - uProgress);
41
+ vec2 offset = flow(uv * uScale, uProgress * uFlow) * uStrength * env;
42
+
43
+ vec2 fromUv = clamp(uv + offset, 0.0, 1.0);
44
+ vec2 toUv = clamp(uv - offset, 0.0, 1.0);
45
+
46
+ float mixW = smoothstep(0.3, 0.7, uProgress);
47
+ return mix(getFromColor(fromUv), getToColor(toUv), mixW);
48
+ }
49
+ `,
50
+ });
@@ -0,0 +1,36 @@
1
+ import { defineTransition } from "./define.js";
2
+
3
+ /**
4
+ * Inspired by gl-transitions' luminamelt. Content-aware dissolve: each pixel
5
+ * transitions based on its brightness in the "from" image. Brighter pixels
6
+ * transition first, darker pixels last — creating a melt-like effect driven
7
+ * by image content, not a uniform or noise threshold.
8
+ */
9
+ export const luminaMelt = defineTransition({
10
+ name: "lumina-melt",
11
+ defaults: {
12
+ softness: 0.15,
13
+ invert: 0,
14
+ },
15
+ glsl: `
16
+ uniform float uSoftness;
17
+ uniform float uInvert;
18
+
19
+ vec4 transition(vec2 uv) {
20
+ vec4 fromColor = getFromColor(uv);
21
+ vec4 toColor = getToColor(uv);
22
+
23
+ // ITU-R BT.601 luminance.
24
+ float luma = dot(fromColor.rgb, vec3(0.299, 0.587, 0.114));
25
+
26
+ // invert=0: bright pixels transition first (fieldValue = 1 - luma)
27
+ // invert=1: dark pixels transition first (fieldValue = luma)
28
+ float fieldValue = mix(1.0 - luma, luma, uInvert);
29
+
30
+ float threshold = uProgress * (1.0 + 2.0 * uSoftness) - uSoftness;
31
+ float w = smoothstep(threshold - uSoftness, threshold + uSoftness, fieldValue);
32
+ // w=1: pixel hasn't melted yet (still from)
33
+ return mix(toColor, fromColor, w);
34
+ }
35
+ `,
36
+ });
@@ -0,0 +1,58 @@
1
+ import { defineTransition } from "./define.js";
2
+
3
+ /**
4
+ * Tile-shuffle reveal: the frame is partitioned into cells that transition
5
+ * on staggered start times. Each tile picks a random direction; its
6
+ * `from` sample slides OUT in that direction while its `to` sample
7
+ * arrives from the SAME direction — so every tile reads as one continuous
8
+ * flow from a to b instead of reversing at the midpoint.
9
+ */
10
+ export const mosaic = defineTransition({
11
+ name: "mosaic",
12
+ defaults: {
13
+ count: 14,
14
+ jitter: 0.08,
15
+ stagger: 0.4,
16
+ },
17
+ glsl: `
18
+ uniform float uCount;
19
+ uniform float uJitter;
20
+ uniform float uStagger;
21
+
22
+ float hash21(vec2 p) {
23
+ return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
24
+ }
25
+ vec2 hash22(vec2 p) {
26
+ return vec2(
27
+ fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453),
28
+ fract(sin(dot(p, vec2(39.3468, 11.1357))) * 24678.1234)
29
+ );
30
+ }
31
+
32
+ vec4 transition(vec2 uv) {
33
+ // 1×1 = full fade, 2×2 = quad-split — neither reads as "mosaic".
34
+ // Clamp here so the transition is reliable regardless of caller input.
35
+ float count = max(uCount, 3.0);
36
+ vec2 cell = floor(uv * count);
37
+
38
+ // Random unit direction per cell.
39
+ vec2 rawDir = hash22(cell) * 2.0 - 1.0;
40
+ vec2 dir = rawDir / max(length(rawDir), 0.0001);
41
+
42
+ // Staggered per-cell transition, monotonic in uProgress.
43
+ float priority = hash21(cell);
44
+ float start = priority * uStagger;
45
+ float localP = clamp((uProgress - start) / max(1.0 - uStagger, 0.0001), 0.0, 1.0);
46
+
47
+ // One-way flow: from-sample slides out in dir, to-sample arrives from
48
+ // the same dir. Same velocity + direction through the crossfade, so the
49
+ // tile reads as one continuous movement instead of out-and-back.
50
+ // Mirror-sample so out-of-range UVs reflect into in-bounds content
51
+ // instead of clamping into edge-color streaks.
52
+ vec2 fromUv = mirrorUv(uv + dir * uJitter * localP);
53
+ vec2 toUv = mirrorUv(uv + dir * uJitter * (localP - 1.0));
54
+
55
+ return mix(getFromColor(fromUv), getToColor(toUv), localP);
56
+ }
57
+ `,
58
+ });
@@ -0,0 +1,41 @@
1
+ import { defineTransition } from "./define.js";
2
+
3
+ export const noiseDissolve = defineTransition({
4
+ name: "noise-dissolve",
5
+ defaults: {
6
+ scale: 20,
7
+ softness: 0.05,
8
+ },
9
+ glsl: `
10
+ uniform float uScale;
11
+ uniform float uSoftness;
12
+
13
+ float hash21(vec2 p) {
14
+ return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
15
+ }
16
+
17
+ // Bilinearly-smoothed value noise.
18
+ float valueNoise(vec2 p) {
19
+ vec2 i = floor(p);
20
+ vec2 f = fract(p);
21
+ f = f * f * (3.0 - 2.0 * f);
22
+ float a = hash21(i);
23
+ float b = hash21(i + vec2(1.0, 0.0));
24
+ float c = hash21(i + vec2(0.0, 1.0));
25
+ float d = hash21(i + vec2(1.0, 1.0));
26
+ return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
27
+ }
28
+
29
+ vec4 transition(vec2 uv) {
30
+ // Sample a noise field; each pixel gets a "transition time" in [0,1].
31
+ float n = valueNoise(uv * uScale);
32
+
33
+ // Threshold moves from just-below-0 to just-above-1, so the feather
34
+ // is fully off the noise range at the endpoints.
35
+ float threshold = uProgress * (1.0 + 2.0 * uSoftness) - uSoftness;
36
+ float w = smoothstep(threshold - uSoftness, threshold + uSoftness, n);
37
+
38
+ return mix(getToColor(uv), getFromColor(uv), w);
39
+ }
40
+ `,
41
+ });
@@ -0,0 +1,165 @@
1
+ import { defineTransition } from "./define.js";
2
+
3
+ /**
4
+ * Classic book-page curl — impossible in a fragment shader because it
5
+ * needs real geometry deformation, silhouette, and depth-ordered self-
6
+ * occlusion.
7
+ *
8
+ * A tilted hinge line sweeps across the plane. Vertices on the curled
9
+ * side wrap around a cylinder whose effective radius grows with the
10
+ * fraction of the sweep completed (sqrt growth: a real rolled page
11
+ * starts tight and fattens as more length wraps). Front face samples
12
+ * `from` with Lambert-ish shading; back face uses the configurable
13
+ * `backColor` with softened shading so it reads as bright paper even
14
+ * where the key light can't reach.
15
+ *
16
+ * Instance 0 is a back plane showing `to`; it also casts a soft drop
17
+ * shadow from the curl, so the rolled paper visibly floats above the
18
+ * revealed page. Shadow envelope is 4·p·(1-p) so it gates cleanly to
19
+ * zero at both endpoints.
20
+ *
21
+ * Mesh is densely subdivided along the curl direction (128 cells) so
22
+ * the cylinder silhouette reads smooth at typical canvas sizes.
23
+ *
24
+ * Endpoints: progress 0 → every foreground vertex flat at z=0, front-
25
+ * facing, `from` at its uv, vLight=1; shadow mask zero. Pixel-pure
26
+ * from. Progress 1 → every foreground vertex curled past the viewport
27
+ * edge (clipped out), back plane visible with shadow mask zero. Pixel-
28
+ * pure to.
29
+ */
30
+ export const pageCurl = defineTransition({
31
+ name: "page-curl",
32
+ mesh: { subdivisions: [128, 32], instances: 2 },
33
+ defaults: {
34
+ tilt: 0.12,
35
+ backColor: [0.97, 0.96, 0.94] as const,
36
+ },
37
+ vertex: `
38
+ uniform float uTilt;
39
+ const float uRadius = 0.5;
40
+
41
+ out float vLight;
42
+ out float vAlpha;
43
+ flat out int vInstance;
44
+
45
+ #define PI 3.14159265359
46
+
47
+ void main() {
48
+ vInstance = gl_InstanceID;
49
+ vUv = aUv;
50
+
51
+ if (gl_InstanceID == 0) {
52
+ gl_Position = vec4(aPosition, 0.99, 1.0);
53
+ vLight = 1.0;
54
+ vAlpha = 1.0;
55
+ return;
56
+ }
57
+
58
+ vec2 sweepDir = vec2(cos(uTilt), sin(uTilt));
59
+ vec2 hingeDir = vec2(-sweepDir.y, sweepDir.x);
60
+
61
+ float s = dot(aPosition, sweepDir);
62
+ float h = dot(aPosition, hingeDir);
63
+
64
+ float maxExtent = abs(sweepDir.x) + abs(sweepDir.y);
65
+ float hingePos = mix(
66
+ maxExtent + uRadius,
67
+ -maxExtent - 2.0 * uRadius,
68
+ uProgress
69
+ );
70
+
71
+ float d = s - hingePos;
72
+
73
+ if (d <= 0.0) {
74
+ gl_Position = vec4(aPosition, 0.0, 1.0);
75
+ vLight = 1.0;
76
+ vAlpha = 1.0;
77
+ return;
78
+ }
79
+
80
+ float totalTravel = 2.0 * maxExtent + 3.0 * uRadius;
81
+ float traveled = maxExtent + uRadius - hingePos;
82
+ float rEff = uRadius * (0.18 + 0.82 * sqrt(traveled / totalTravel));
83
+
84
+ float theta = d / rEff;
85
+ float newS = hingePos + rEff * sin(theta);
86
+ float newZ = rEff * (cos(theta) - 1.0);
87
+
88
+ vec2 newPos = newS * sweepDir + h * hingeDir;
89
+ gl_Position = vec4(newPos, newZ, 1.0);
90
+
91
+ vec3 normal = vec3(sin(theta) * sweepDir, -cos(theta));
92
+ vec3 lightDir = normalize(vec3(0.35, 0.55, -1.0));
93
+ vLight = clamp(0.5 + 0.55 * dot(normal, lightDir), 0.3, 1.0);
94
+
95
+ vAlpha = 1.0 - smoothstep(PI, PI * 2.0, theta);
96
+ }
97
+ `,
98
+ glsl: `
99
+ uniform float uTilt;
100
+ uniform vec3 uBackColor;
101
+ const float uRadius = 0.5;
102
+
103
+ in float vLight;
104
+ in float vAlpha;
105
+ flat in int vInstance;
106
+
107
+ vec4 transition(vec2 uv) {
108
+ if (vInstance == 0) {
109
+ // Back plane: the destination page, with a soft drop shadow cast
110
+ // by the curl floating above it. Shadow is strongest right past
111
+ // the hinge (where the curl overhangs) and fades over a few
112
+ // effective radii. 4·p·(1-p) envelope keeps endpoints pure.
113
+ vec3 col = getToColor(uv).rgb;
114
+
115
+ vec2 sweepDir = vec2(cos(uTilt), sin(uTilt));
116
+ float maxExtent = abs(sweepDir.x) + abs(sweepDir.y);
117
+ float hingePos = mix(
118
+ maxExtent + uRadius,
119
+ -maxExtent - 2.0 * uRadius,
120
+ uProgress
121
+ );
122
+
123
+ vec2 clipPos = uv * 2.0 - 1.0;
124
+ float s = dot(clipPos, sweepDir);
125
+ float d = s - hingePos;
126
+
127
+ float totalTravel = 2.0 * maxExtent + 3.0 * uRadius;
128
+ float traveled = max(maxExtent + uRadius - hingePos, 0.0);
129
+ float rEff = uRadius * (0.18 + 0.82 * sqrt(traveled / totalTravel));
130
+
131
+ float distPastHinge = max(d, 0.0);
132
+ float shadow = 1.0 - smoothstep(0.0, 3.5 * rEff, distPastHinge);
133
+ float envelope = 4.0 * uProgress * (1.0 - uProgress);
134
+ col *= 1.0 - shadow * 0.55 * envelope;
135
+
136
+ return vec4(col, 1.0);
137
+ }
138
+
139
+ if (vAlpha < 0.01) discard;
140
+
141
+ vec3 col;
142
+ float alpha;
143
+ if (gl_FrontFacing) {
144
+ col = getFromColor(uv).rgb * vLight;
145
+ // Smooth fade on the image side so the seam at the wrap-around
146
+ // (theta ≈ 2π, page disappearing past itself) doesn't read as a
147
+ // hard edge.
148
+ alpha = vAlpha;
149
+ } else {
150
+ // Paper back: author-chosen colour with gentle shading that never
151
+ // drops below ~85%, so the back reads as diffusely lit paper even
152
+ // where the key light can't reach (the far side of the curl).
153
+ float backLight = 0.85 + 0.15 * vLight;
154
+ col = uBackColor * backLight;
155
+ // Always opaque inside the visible mesh — paper isn't transparent.
156
+ // Letting the back's alpha follow vAlpha lets the next page bleed
157
+ // through the back during the wrap-around fade, breaking the
158
+ // illusion of a solid page. Hard discard above (vAlpha < 0.01)
159
+ // already handles culling for fully wrapped vertices.
160
+ alpha = 1.0;
161
+ }
162
+ return vec4(col, alpha);
163
+ }
164
+ `,
165
+ });
@@ -0,0 +1,59 @@
1
+ import { defineTransition } from "./define.js";
2
+
3
+ /**
4
+ * Ink-like directional bleed: a dominant gradient sweeps across, with noise
5
+ * perturbing the wavefront edge so it feels organic (watercolor / ink on
6
+ * paper) rather than a clean wipe or a uniform dissolve.
7
+ */
8
+ export const paintBleed = defineTransition({
9
+ name: "paint-bleed",
10
+ defaults: {
11
+ direction: [-1, 0],
12
+ scale: 10,
13
+ softness: 0.02,
14
+ noiseStrength: 0.35,
15
+ },
16
+ glsl: `
17
+ uniform vec2 uDirection;
18
+ uniform float uScale;
19
+ uniform float uSoftness;
20
+ uniform float uNoiseStrength;
21
+
22
+ float hash21(vec2 p) {
23
+ return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
24
+ }
25
+
26
+ float valueNoise(vec2 p) {
27
+ vec2 i = floor(p);
28
+ vec2 f = fract(p);
29
+ f = f * f * (3.0 - 2.0 * f);
30
+ float a = hash21(i);
31
+ float b = hash21(i + vec2(1.0, 0.0));
32
+ float c = hash21(i + vec2(0.0, 1.0));
33
+ float d = hash21(i + vec2(1.0, 1.0));
34
+ return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
35
+ }
36
+
37
+ vec4 transition(vec2 uv) {
38
+ vec2 d = normalize(uDirection);
39
+ // Max |dot(uv - 0.5, -d)| over uv ∈ [0,1]² is (|dx| + |dy|) * 0.5.
40
+ // Without dividing by it, gradient extends beyond [0, 1] for diagonal
41
+ // directions and the threshold-based smoothstep can't fully reveal the
42
+ // corners at progress=1 — leaving a sliver of the previous image.
43
+ float maxProj = max((abs(d.x) + abs(d.y)) * 0.5, 0.0001);
44
+ float gradient = 0.5 + dot(uv - 0.5, -d) / (2.0 * maxProj);
45
+
46
+ // Noise only perturbs the wavefront edge, not the overall progression.
47
+ float perturbation = (valueNoise(uv * uScale) - 0.5) * uNoiseStrength;
48
+ float fieldValue = gradient + perturbation;
49
+
50
+ // Extend threshold range to accommodate noise extrema → endpoints stay clean.
51
+ float noiseRange = uNoiseStrength * 0.5;
52
+ float totalEdge = uSoftness + noiseRange;
53
+ float threshold = uProgress * (1.0 + 2.0 * totalEdge) - totalEdge;
54
+ float w = smoothstep(threshold - uSoftness, threshold + uSoftness, fieldValue);
55
+
56
+ return mix(getToColor(uv), getFromColor(uv), w);
57
+ }
58
+ `,
59
+ });