@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,76 @@
1
+ import type { Instance } from '../core/types';
2
+
3
+ /*
4
+ * Base for motion-kit custom elements (Astro / plain HTML). Light DOM only, so
5
+ * themes and project CSS reach the markup. Attributes map to engine options
6
+ * (kebab-case → camelCase); the engine is created on connect, recreated when an
7
+ * observed attribute changes, and destroyed on disconnect.
8
+ */
9
+
10
+ export type OptionType = 'string' | 'number' | 'boolean' | 'list' | 'json';
11
+
12
+ /** `HTMLElement` in the browser; an empty class during SSR so importing never throws. */
13
+ export const SafeHTMLElement = (typeof HTMLElement === 'undefined' ? class {} : HTMLElement) as typeof HTMLElement;
14
+
15
+ const kebab = (name: string) => name.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
16
+
17
+ export abstract class MkElement<I extends Instance = Instance> extends SafeHTMLElement {
18
+ /** Option name (camelCase) → how to read its attribute. */
19
+ static options: Record<string, OptionType> = {};
20
+
21
+ static get observedAttributes() {
22
+ return Object.keys(this.options).map(kebab);
23
+ }
24
+
25
+ /** The live engine (null while disconnected). */
26
+ instance: I | null = null;
27
+
28
+ protected abstract create(options: Record<string, unknown>): I;
29
+
30
+ /** Options read from the attributes now. */
31
+ get options(): Record<string, unknown> {
32
+ const types = (this.constructor as typeof MkElement).options;
33
+ const options: Record<string, unknown> = {};
34
+ for (const [name, type] of Object.entries(types)) {
35
+ const raw = this.getAttribute(kebab(name));
36
+ if (type === 'boolean') {
37
+ if (raw !== null) options[name] = raw !== 'false';
38
+ continue;
39
+ }
40
+ if (raw === null) continue;
41
+ if (type === 'number') {
42
+ const value = Number(raw);
43
+ if (Number.isFinite(value)) options[name] = value;
44
+ } else if (type === 'list') options[name] = raw.split(',').map((item) => item.trim()).filter(Boolean);
45
+ else if (type === 'json') {
46
+ try {
47
+ options[name] = JSON.parse(raw);
48
+ } catch {
49
+ // Ignore malformed JSON: the engine keeps its default.
50
+ }
51
+ } else options[name] = raw;
52
+ }
53
+ return options;
54
+ }
55
+
56
+ connectedCallback() {
57
+ if (!this.instance) this.instance = this.create(this.options);
58
+ }
59
+
60
+ disconnectedCallback() {
61
+ this.instance?.destroy();
62
+ this.instance = null;
63
+ }
64
+
65
+ attributeChangedCallback(_name: string, previous: string | null, next: string | null) {
66
+ if (previous === next || !this.isConnected || !this.instance) return;
67
+ this.instance.destroy();
68
+ this.instance = this.create(this.options);
69
+ }
70
+ }
71
+
72
+ /** customElements.define once; later calls with the same name are ignored. */
73
+ export function defineElement(name: string, ctor: CustomElementConstructor) {
74
+ if (typeof customElements === 'undefined' || customElements.get(name)) return;
75
+ customElements.define(name, ctor);
76
+ }
@@ -0,0 +1,48 @@
1
+ import { defineElement } from './base';
2
+ import { MkThemePickerElement } from '../components/theme-picker/element';
3
+ import { MkDialogElement } from '../components/dialog/element';
4
+ import { MkMenuElement } from '../components/menu/element';
5
+ import { MkToasterElement } from '../components/toast/element';
6
+ import { MkChatBackgroundElement } from '../components/chat-background/element';
7
+ import { MkChatElement } from '../components/chat/element';
8
+ import { MkNavElement } from '../components/nav/element';
9
+ import { MkStepsElement } from '../components/steps/element';
10
+ import { MkCursorElement } from '../components/cursor/element';
11
+ import { MkIslandElement } from '../components/island/element';
12
+ // new-component:imports (scripts/new-component.mjs inserts above this line)
13
+
14
+ export { MkElement, SafeHTMLElement, defineElement, type OptionType } from './base';
15
+ export { MkThemePickerElement } from '../components/theme-picker/element';
16
+ export { MkDialogElement } from '../components/dialog/element';
17
+ export { MkMenuElement } from '../components/menu/element';
18
+ export { MkToasterElement } from '../components/toast/element';
19
+ export { MkChatBackgroundElement } from '../components/chat-background/element';
20
+ export { MkChatElement } from '../components/chat/element';
21
+ export { MkNavElement } from '../components/nav/element';
22
+ export { MkStepsElement } from '../components/steps/element';
23
+ export { MkCursorElement } from '../components/cursor/element';
24
+ export { toast } from '../components/toast/store';
25
+ export { MkIslandElement } from '../components/island/element';
26
+ // new-component:exports
27
+
28
+ /** Tag name → element class, for every component. */
29
+ export const ELEMENTS = {
30
+ 'mk-theme-picker': MkThemePickerElement,
31
+ 'mk-dialog': MkDialogElement,
32
+ 'mk-menu': MkMenuElement,
33
+ 'mk-toaster': MkToasterElement,
34
+ 'mk-chat-background': MkChatBackgroundElement,
35
+ 'mk-chat': MkChatElement,
36
+ 'mk-nav': MkNavElement,
37
+ 'mk-steps': MkStepsElement,
38
+ 'mk-cursor': MkCursorElement,
39
+ 'mk-island': MkIslandElement,
40
+ // new-component:entries
41
+ } as const;
42
+
43
+ export type ElementName = keyof typeof ELEMENTS;
44
+
45
+ /** Register every motion-kit element (or the ones named). Safe to call more than once. */
46
+ export function defineElements(names: ElementName[] = Object.keys(ELEMENTS) as ElementName[]) {
47
+ for (const name of names) defineElement(name, ELEMENTS[name]);
48
+ }
@@ -0,0 +1,15 @@
1
+ /*
2
+ * motion-kit/gl — optional WebGL effects. A separate entry so pages that never
3
+ * draw on the GPU never load these shaders.
4
+ */
5
+ export {
6
+ createParticleHero,
7
+ type ParticleHeroOptions,
8
+ type ParticleHeroInstance,
9
+ type ParticleHeroMode,
10
+ } from './particle-hero/create-particle-hero';
11
+ export { createLiquidBlend, type LiquidBlendOptions, type LiquidBlendInstance } from './liquid-blend/create-liquid-blend';
12
+ export { createMatcap, type MatcapOptions, type MatcapInstance } from './matcap/create-matcap';
13
+ export { createShaderGrain, type ShaderGrainOptions, type ShaderGrainInstance } from './shader-grain/create-shader-grain';
14
+ export { createShaderBlur, type ShaderBlurOptions, type ShaderBlurInstance } from './shader-blur/create-shader-blur';
15
+ export type { ShaderEffectOptions, ShaderEffectInstance } from './shared/create-shader-effect';
@@ -0,0 +1,23 @@
1
+ # liquid-blend
2
+
3
+ Mezcla de dos texturas con deformación UV (OFFFICE, adaptación).
4
+
5
+ ```ts
6
+ import { createLiquidBlend } from '@yewdiel21/motion-kit/gl';
7
+ import { useLiquidBlend } from '@yewdiel21/motion-kit/react';
8
+ import '@yewdiel21/motion-kit/css';
9
+ const effect = createLiquidBlend(root);
10
+ effect.setProgress(.5);
11
+ effect.setAmount(.15);
12
+ effect.destroy();
13
+ ```
14
+
15
+ Opciones compartidas: `images?: HTMLImageElement[]` (por defecto las dos primeras imágenes de root; una se repite), `progress` 0–1, `amount`, `maxDpr` 1.5. Las imágenes pueden terminar de cargar después de crear la instancia. Recursos del mismo origen o con CORS configurado antes de cargar la imagen. El kit no descarga imágenes. Root debe tener dimensiones; el canvas decorativo cubre su caja y deja el HTML accesible debajo.
16
+
17
+ Controles: `setProgress(0..1)`, `setAmount(0..100)`, `pause()`, `resume()`, `mode: 'webgl' | 'none'`, `destroy()`. React: `useLiquidBlend(ref, options, deps)`, ref a la instancia. No usa `autoInit`: importar explícitamente desde `/gl` conserva la separación de GPU del paquete principal.
18
+
19
+ Pausa fuera de pantalla y con pestaña oculta. Movimiento reducido: frame fijo, con controles manuales. Sin WebGL, error de textura o contexto perdido: canvas oculto, HTML original disponible. Contexto restaurado: recompila y vuelve a cargar texturas. Destroy libera texturas, buffer, shaders y programa, desconecta observers y restaura la clase original.
20
+
21
+ OFFFICE `liquid-swap`: mezcla de las imágenes renderizadas, UV deformadas en torno al centro. Adaptación: dos texturas de imagen y ondas propias, sin modelos, ruido cnoise ni render targets. Amount .15; progreso 0/1 conserva exactamente la primera/segunda imagen.
22
+
23
+ Desde 0.9.0. Fuentes de parámetros: `REA - Dousan OFFFICE Siena/`. Shaders originales, sin redistribuir código ni assets de terceros.
@@ -0,0 +1,7 @@
1
+ import { createShaderEffect, type ShaderEffectInstance, type ShaderEffectOptions } from '../shared/create-shader-effect';
2
+ import { liquidFragment } from './shader';
3
+
4
+ export type LiquidBlendOptions = ShaderEffectOptions;
5
+ export type LiquidBlendInstance = ShaderEffectInstance;
6
+ export const createLiquidBlend = (root: HTMLElement | null, options: LiquidBlendOptions = {}): LiquidBlendInstance =>
7
+ createShaderEffect(root, liquidFragment, { amount: 0.15, ...options });
@@ -0,0 +1,9 @@
1
+ export const liquidFragment = `
2
+ void main() {
3
+ float center = 1. - smoothstep(0., .5, distance(vUv, vec2(.5)));
4
+ vec2 wave = vec2(sin(vUv.y * 18. + uTime), cos(vUv.x * 20. - uTime));
5
+ vec2 distortion = wave * center * uAmount;
6
+ vec2 currentUv = cover(vUv + distortion * uProgress, uImageSize0);
7
+ vec2 nextUv = cover(vUv - distortion * (1. - uProgress), uImageSize1);
8
+ gl_FragColor = mix(texture2D(uImage0, currentUv), texture2D(uImage1, nextUv), uProgress);
9
+ }`;
@@ -0,0 +1,23 @@
1
+ # matcap
2
+
3
+ Superficie esférica iluminada con matcap y hemisferio (OFFFICE, adaptación).
4
+
5
+ ```ts
6
+ import { createMatcap } from '@yewdiel21/motion-kit/gl';
7
+ import { useMatcap } from '@yewdiel21/motion-kit/react';
8
+ import '@yewdiel21/motion-kit/css';
9
+ const effect = createMatcap(root);
10
+ effect.setProgress(.5);
11
+ effect.setAmount(.15);
12
+ effect.destroy();
13
+ ```
14
+
15
+ Opciones compartidas: `images?: HTMLImageElement[]` (por defecto las dos primeras imágenes de root; una se repite), `progress` 0–1, `amount`, `maxDpr` 1.5. Las imágenes pueden terminar de cargar después de crear la instancia. Recursos del mismo origen o con CORS configurado antes de cargar la imagen. El kit no descarga imágenes. Root debe tener dimensiones; el canvas decorativo cubre su caja y deja el HTML accesible debajo.
16
+
17
+ Controles: `setProgress(0..1)`, `setAmount(0..100)`, `pause()`, `resume()`, `mode: 'webgl' | 'none'`, `destroy()`. React: `useMatcap(ref, options, deps)`, ref a la instancia. No usa `autoInit`: importar explícitamente desde `/gl` conserva la separación de GPU del paquete principal.
18
+
19
+ Pausa fuera de pantalla y con pestaña oculta. Movimiento reducido: frame fijo, con controles manuales. Sin WebGL, error de textura o contexto perdido: canvas oculto, HTML original disponible. Contexto restaurado: recompila y vuelve a cargar texturas. Destroy libera texturas, buffer, shaders y programa, desconecta observers y restaura la clase original.
20
+
21
+ OFFFICE `matcap`: normales en UV .495+.5, hemisferio y ganancia .15. Adaptación: esfera analítica y luz propia si no hay imagen; una imagen opcional actúa como matcap. Progreso gira el matcap; amount regula el brillo. No es un cargador de modelos ni reflexión de escena.
22
+
23
+ Desde 0.9.0. Fuentes de parámetros: `REA - Dousan OFFFICE Siena/`. Shaders originales, sin redistribuir código ni assets de terceros.
@@ -0,0 +1,7 @@
1
+ import { createShaderEffect, type ShaderEffectInstance, type ShaderEffectOptions } from '../shared/create-shader-effect';
2
+ import { matcapFragment } from './shader';
3
+
4
+ export type MatcapOptions = ShaderEffectOptions;
5
+ export type MatcapInstance = ShaderEffectInstance;
6
+ export const createMatcap = (root: HTMLElement | null, options: MatcapOptions = {}): MatcapInstance =>
7
+ createShaderEffect(root, matcapFragment, { amount: 0.15, ...options });
@@ -0,0 +1,16 @@
1
+ export const matcapFragment = `
2
+ void main() {
3
+ vec2 point = (vUv - .5) * 2.5;
4
+ point.x *= uSize.x / uSize.y;
5
+ float radius = length(point);
6
+ if (radius > 1.) { gl_FragColor = vec4(.04, .06, .08, 1.); return; }
7
+ vec3 normal = normalize(vec3(point, sqrt(max(0., 1. - dot(point, point)))));
8
+ float angle = uTime * .2 + uProgress * 6.28318;
9
+ vec2 rotated = mat2(cos(angle), -sin(angle), sin(angle), cos(angle)) * normal.xy;
10
+ vec2 matcapUv = rotated * .495 + .5;
11
+ float hemisphere = clamp(1. - dot(normalize(vec3(1., -1., 1.)), normal), 0., 1.);
12
+ vec3 metal = mix(vec3(.1), vec3(1.), hemisphere) + pow(normal.z, 24.) * uAmount;
13
+ vec3 mapped = texture2D(uImage0, matcapUv).rgb;
14
+ metal = mix(metal, mapped + metal * .15, uHasImage);
15
+ gl_FragColor = vec4(metal, 1.);
16
+ }`;
@@ -0,0 +1,41 @@
1
+ # particle-hero
2
+
3
+ Una nube de puntos simulada en la GPU que se posa sobre las líneas de un patrón de interferencia que cambia solo (modos de Chladni de [3, 5, 7] cada 6–12 s, frecuencia 20–45 cada 5–10 s, distorsión 0–5 en 1.2–3 s) mientras una parte de los puntos (40–80 %) se va a dibujar una palabra y luego vuelve. El puntero los empuja según su velocidad. Aparece en 1 s tras 0.3 s.
4
+
5
+ Origen: iyo.ai, hero de la home (escena `wK`, sistema `YW`, simulación `dE`): dos texturas de estado RGBA alternadas (posición XY, velocidad ZW), proyección tipo Newton hacia los ceros del campo, destino por hash estable según `texturePercent`, repulsión del puntero, ciclo de palabras en cuatro fases. Es una **implementación propia**: iyo mueve 1 638 400 puntos con Three.js y nueve imágenes de palabras; aquí son `size²` puntos (16 384 por defecto, hasta 65 536), palabras dibujadas en local con `system-ui`, tres campos base y tiempos aproximados. Sin WebGL2 con texturas float cae a unos 1800 puntos en un canvas 2D (un círculo que respira, sin Chladni); sin canvas no hace nada.
6
+
7
+ Vive en la entrada opcional `@yewdiel21/motion-kit/gl`, así las páginas sin él no cargan sus shaders.
8
+
9
+ ## HTML / Astro
10
+
11
+ ```html
12
+ <section id="hero" style="height: 80vh; background: #15130f">
13
+ <h1>Objetos que escuchan</h1>
14
+ </section>
15
+ <script>
16
+ import { createParticleHero } from '@yewdiel21/motion-kit/gl';
17
+ const hero = createParticleHero(document.getElementById('hero'), { words: ['ESCUCHA', 'CREA'] });
18
+ // hero.setWord('HOLA'); hero.setTextureMix(0.7); hero.setPattern(1); hero.destroy();
19
+ </script>
20
+ ```
21
+
22
+ El anfitrión fija la altura y el fondo; el canvas se coloca debajo de su contenido (`.mk-particle-hero`).
23
+
24
+ ## React
25
+
26
+ ```tsx
27
+ const ref = useRef<HTMLElement>(null);
28
+ const hero = useParticleHero(ref, { words: ['ESCUCHA', 'CREA'], size: 128 });
29
+ ```
30
+
31
+ ## API
32
+
33
+ `createParticleHero(root, { words, size, pointSize, color, seed, forceFallback, onMode })` → `{ mode, setWord(text), setTextureMix(0…1 | null), setPattern(0|1|2), pause(), resume(), destroy }`. `mode`: `webgl2`, `canvas2d` o `none`; también en `data-mk-mode` de la raíz (`context-lost` si la GPU pierde el contexto: desmonta y vuelve a montar). Una segunda llamada con la misma raíz devuelve la misma instancia.
34
+
35
+ ## Rendimiento
36
+
37
+ El estado ocupa `size² × 16` bytes por textura (256 KB con 128). DPR limitado a 1.5. Corre en el ticker compartido solo mientras el hero está cerca de la pantalla y la pestaña visible. Mide en las GPU de tu público antes de subir `size`.
38
+
39
+ ## Accesibilidad
40
+
41
+ El canvas es decorativo (`aria-hidden`): el texto y el nombre del hero van en HTML. Con movimiento reducido dibuja una composición quieta (la palabra formada) sin bucle.