trama-ui 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 (285) hide show
  1. package/CATALOG.md +1237 -0
  2. package/LICENSE +21 -0
  3. package/README.md +78 -0
  4. package/THIRD-PARTY.md +4 -0
  5. package/assets/pixel/kenney-pixel-ui/9-slice/Ancient/brown.png +0 -0
  6. package/assets/pixel/kenney-pixel-ui/9-slice/Ancient/brown_inlay.png +0 -0
  7. package/assets/pixel/kenney-pixel-ui/9-slice/Ancient/brown_pressed.png +0 -0
  8. package/assets/pixel/kenney-pixel-ui/9-slice/Ancient/grey.png +0 -0
  9. package/assets/pixel/kenney-pixel-ui/9-slice/Ancient/grey_inlay.png +0 -0
  10. package/assets/pixel/kenney-pixel-ui/9-slice/Ancient/grey_pressed.png +0 -0
  11. package/assets/pixel/kenney-pixel-ui/9-slice/Ancient/tan.png +0 -0
  12. package/assets/pixel/kenney-pixel-ui/9-slice/Ancient/tan_inlay.png +0 -0
  13. package/assets/pixel/kenney-pixel-ui/9-slice/Ancient/tan_pressed.png +0 -0
  14. package/assets/pixel/kenney-pixel-ui/9-slice/Ancient/white.png +0 -0
  15. package/assets/pixel/kenney-pixel-ui/9-slice/Ancient/white_inlay.png +0 -0
  16. package/assets/pixel/kenney-pixel-ui/9-slice/Ancient/white_pressed.png +0 -0
  17. package/assets/pixel/kenney-pixel-ui/9-slice/Colored/blue.png +0 -0
  18. package/assets/pixel/kenney-pixel-ui/9-slice/Colored/blue_pressed.png +0 -0
  19. package/assets/pixel/kenney-pixel-ui/9-slice/Colored/green.png +0 -0
  20. package/assets/pixel/kenney-pixel-ui/9-slice/Colored/green_pressed.png +0 -0
  21. package/assets/pixel/kenney-pixel-ui/9-slice/Colored/grey.png +0 -0
  22. package/assets/pixel/kenney-pixel-ui/9-slice/Colored/grey_pressed.png +0 -0
  23. package/assets/pixel/kenney-pixel-ui/9-slice/Colored/red.png +0 -0
  24. package/assets/pixel/kenney-pixel-ui/9-slice/Colored/red_pressed.png +0 -0
  25. package/assets/pixel/kenney-pixel-ui/9-slice/Colored/yellow.png +0 -0
  26. package/assets/pixel/kenney-pixel-ui/9-slice/Colored/yellow_pressed.png +0 -0
  27. package/assets/pixel/kenney-pixel-ui/9-slice/Outline/blue.png +0 -0
  28. package/assets/pixel/kenney-pixel-ui/9-slice/Outline/blue_pressed.png +0 -0
  29. package/assets/pixel/kenney-pixel-ui/9-slice/Outline/green.png +0 -0
  30. package/assets/pixel/kenney-pixel-ui/9-slice/Outline/green_pressed.png +0 -0
  31. package/assets/pixel/kenney-pixel-ui/9-slice/Outline/red.png +0 -0
  32. package/assets/pixel/kenney-pixel-ui/9-slice/Outline/red_pressed.png +0 -0
  33. package/assets/pixel/kenney-pixel-ui/9-slice/Outline/yellow.png +0 -0
  34. package/assets/pixel/kenney-pixel-ui/9-slice/Outline/yellow_pressed.png +0 -0
  35. package/assets/pixel/kenney-pixel-ui/9-slice/list.png +0 -0
  36. package/assets/pixel/kenney-pixel-ui/9-slice/space.png +0 -0
  37. package/assets/pixel/kenney-pixel-ui/9-slice/space_inlay.png +0 -0
  38. package/assets/pixel/kenney-pixel-ui/License.txt +23 -0
  39. package/assets/pixel/kenney-pixel-ui/spritesheet/sheet.png +0 -0
  40. package/bin/trama-ui.mjs +27 -0
  41. package/dist/components/ui/Accordion.d.ts +12 -0
  42. package/dist/components/ui/Accordion.js +12 -0
  43. package/dist/components/ui/Alert.d.ts +15 -0
  44. package/dist/components/ui/Alert.js +15 -0
  45. package/dist/components/ui/ArticlesSection.d.ts +30 -0
  46. package/dist/components/ui/ArticlesSection.js +18 -0
  47. package/dist/components/ui/AsciiBackground.d.ts +58 -0
  48. package/dist/components/ui/AsciiBackground.js +173 -0
  49. package/dist/components/ui/AsciiCard.d.ts +78 -0
  50. package/dist/components/ui/AsciiCard.js +253 -0
  51. package/dist/components/ui/AsciiChart.d.ts +18 -0
  52. package/dist/components/ui/AsciiChart.js +47 -0
  53. package/dist/components/ui/Badge.d.ts +15 -0
  54. package/dist/components/ui/Badge.js +8 -0
  55. package/dist/components/ui/BitmapText.d.ts +25 -0
  56. package/dist/components/ui/BitmapText.js +21 -0
  57. package/dist/components/ui/BlogCard.d.ts +33 -0
  58. package/dist/components/ui/BlogCard.js +13 -0
  59. package/dist/components/ui/Breadcrumbs.d.ts +9 -0
  60. package/dist/components/ui/Breadcrumbs.js +7 -0
  61. package/dist/components/ui/Button.d.ts +74 -0
  62. package/dist/components/ui/Button.js +48 -0
  63. package/dist/components/ui/CTASection.d.ts +13 -0
  64. package/dist/components/ui/CTASection.js +7 -0
  65. package/dist/components/ui/Carousel.d.ts +30 -0
  66. package/dist/components/ui/Carousel.js +80 -0
  67. package/dist/components/ui/CheckboxGroup.d.ts +11 -0
  68. package/dist/components/ui/CheckboxGroup.js +20 -0
  69. package/dist/components/ui/CodeBlock.d.ts +11 -0
  70. package/dist/components/ui/CodeBlock.js +20 -0
  71. package/dist/components/ui/ContactForm.d.ts +25 -0
  72. package/dist/components/ui/ContactForm.js +26 -0
  73. package/dist/components/ui/CrtOverlay.d.ts +10 -0
  74. package/dist/components/ui/CrtOverlay.js +5 -0
  75. package/dist/components/ui/Divider.d.ts +12 -0
  76. package/dist/components/ui/Divider.js +7 -0
  77. package/dist/components/ui/Drawer.d.ts +16 -0
  78. package/dist/components/ui/Drawer.js +25 -0
  79. package/dist/components/ui/Dropdown.d.ts +10 -0
  80. package/dist/components/ui/Dropdown.js +21 -0
  81. package/dist/components/ui/FAQSection.d.ts +14 -0
  82. package/dist/components/ui/FAQSection.js +7 -0
  83. package/dist/components/ui/FeatureGrid.d.ts +18 -0
  84. package/dist/components/ui/FeatureGrid.js +14 -0
  85. package/dist/components/ui/Footer.d.ts +14 -0
  86. package/dist/components/ui/Footer.js +16 -0
  87. package/dist/components/ui/GlyphCursor.d.ts +22 -0
  88. package/dist/components/ui/GlyphCursor.js +50 -0
  89. package/dist/components/ui/GridBackground.d.ts +15 -0
  90. package/dist/components/ui/GridBackground.js +6 -0
  91. package/dist/components/ui/Hero.d.ts +21 -0
  92. package/dist/components/ui/Hero.js +12 -0
  93. package/dist/components/ui/HoverFX.d.ts +29 -0
  94. package/dist/components/ui/HoverFX.js +75 -0
  95. package/dist/components/ui/Icon.d.ts +33 -0
  96. package/dist/components/ui/Icon.js +29 -0
  97. package/dist/components/ui/ImageGallery.d.ts +31 -0
  98. package/dist/components/ui/ImageGallery.js +79 -0
  99. package/dist/components/ui/LogoCloud.d.ts +12 -0
  100. package/dist/components/ui/LogoCloud.js +9 -0
  101. package/dist/components/ui/MagneticButton.d.ts +12 -0
  102. package/dist/components/ui/MagneticButton.js +49 -0
  103. package/dist/components/ui/Marquee.d.ts +29 -0
  104. package/dist/components/ui/Marquee.js +15 -0
  105. package/dist/components/ui/Modal.d.ts +40 -0
  106. package/dist/components/ui/Modal.js +51 -0
  107. package/dist/components/ui/NavBar.d.ts +14 -0
  108. package/dist/components/ui/NavBar.js +12 -0
  109. package/dist/components/ui/NeonSign.d.ts +14 -0
  110. package/dist/components/ui/NeonSign.js +7 -0
  111. package/dist/components/ui/OtpInput.d.ts +9 -0
  112. package/dist/components/ui/OtpInput.js +27 -0
  113. package/dist/components/ui/Pagination.d.ts +10 -0
  114. package/dist/components/ui/Pagination.js +24 -0
  115. package/dist/components/ui/Panel.d.ts +21 -0
  116. package/dist/components/ui/Panel.js +8 -0
  117. package/dist/components/ui/PixelFrame.d.ts +61 -0
  118. package/dist/components/ui/PixelFrame.js +29 -0
  119. package/dist/components/ui/Presence.d.ts +51 -0
  120. package/dist/components/ui/Presence.js +343 -0
  121. package/dist/components/ui/PricingCard.d.ts +30 -0
  122. package/dist/components/ui/PricingCard.js +21 -0
  123. package/dist/components/ui/PricingSection.d.ts +35 -0
  124. package/dist/components/ui/PricingSection.js +21 -0
  125. package/dist/components/ui/Progress.d.ts +17 -0
  126. package/dist/components/ui/Progress.js +9 -0
  127. package/dist/components/ui/RadioGroup.d.ts +10 -0
  128. package/dist/components/ui/RadioGroup.js +11 -0
  129. package/dist/components/ui/RangeSlider.d.ts +14 -0
  130. package/dist/components/ui/RangeSlider.js +11 -0
  131. package/dist/components/ui/Reveal.d.ts +48 -0
  132. package/dist/components/ui/Reveal.js +181 -0
  133. package/dist/components/ui/SceneFlash.d.ts +14 -0
  134. package/dist/components/ui/SceneFlash.js +51 -0
  135. package/dist/components/ui/ScrambleText.d.ts +31 -0
  136. package/dist/components/ui/ScrambleText.js +51 -0
  137. package/dist/components/ui/ScrollArea.d.ts +15 -0
  138. package/dist/components/ui/ScrollArea.js +18 -0
  139. package/dist/components/ui/SectionHeader.d.ts +12 -0
  140. package/dist/components/ui/SectionHeader.js +6 -0
  141. package/dist/components/ui/Select.d.ts +17 -0
  142. package/dist/components/ui/Select.js +31 -0
  143. package/dist/components/ui/Skeleton.d.ts +12 -0
  144. package/dist/components/ui/Skeleton.js +18 -0
  145. package/dist/components/ui/Spinner.d.ts +15 -0
  146. package/dist/components/ui/Spinner.js +24 -0
  147. package/dist/components/ui/Spotlight.d.ts +16 -0
  148. package/dist/components/ui/Spotlight.js +16 -0
  149. package/dist/components/ui/Sprite.d.ts +27 -0
  150. package/dist/components/ui/Sprite.js +19 -0
  151. package/dist/components/ui/StatCounter.d.ts +24 -0
  152. package/dist/components/ui/StatCounter.js +70 -0
  153. package/dist/components/ui/StatsSection.d.ts +14 -0
  154. package/dist/components/ui/StatsSection.js +13 -0
  155. package/dist/components/ui/Stepper.d.ts +10 -0
  156. package/dist/components/ui/Stepper.js +7 -0
  157. package/dist/components/ui/Table.d.ts +10 -0
  158. package/dist/components/ui/Table.js +8 -0
  159. package/dist/components/ui/Tabs.d.ts +12 -0
  160. package/dist/components/ui/Tabs.js +18 -0
  161. package/dist/components/ui/TeamSection.d.ts +18 -0
  162. package/dist/components/ui/TeamSection.js +19 -0
  163. package/dist/components/ui/TerminalTyper.d.ts +20 -0
  164. package/dist/components/ui/TerminalTyper.js +45 -0
  165. package/dist/components/ui/Testimonial.d.ts +19 -0
  166. package/dist/components/ui/Testimonial.js +9 -0
  167. package/dist/components/ui/TestimonialSection.d.ts +20 -0
  168. package/dist/components/ui/TestimonialSection.js +15 -0
  169. package/dist/components/ui/TextField.d.ts +26 -0
  170. package/dist/components/ui/TextField.js +13 -0
  171. package/dist/components/ui/TextmodeBackground.d.ts +52 -0
  172. package/dist/components/ui/TextmodeBackground.js +83 -0
  173. package/dist/components/ui/Timeline.d.ts +13 -0
  174. package/dist/components/ui/Timeline.js +8 -0
  175. package/dist/components/ui/Toast.d.ts +30 -0
  176. package/dist/components/ui/Toast.js +47 -0
  177. package/dist/components/ui/Toggle.d.ts +13 -0
  178. package/dist/components/ui/Toggle.js +10 -0
  179. package/dist/components/ui/Tooltip.d.ts +20 -0
  180. package/dist/components/ui/Tooltip.js +20 -0
  181. package/dist/components/ui/Typewriter.d.ts +20 -0
  182. package/dist/components/ui/Typewriter.js +46 -0
  183. package/dist/components/ui/VideoPlayer.d.ts +81 -0
  184. package/dist/components/ui/VideoPlayer.js +379 -0
  185. package/dist/components/ui/fill.d.ts +32 -0
  186. package/dist/components/ui/fill.js +27 -0
  187. package/dist/components/ui/intent.d.ts +20 -0
  188. package/dist/components/ui/intent.js +23 -0
  189. package/dist/components/ui/styles/kit.css +31 -0
  190. package/dist/components/ui/styles/ui-carousel.css +113 -0
  191. package/dist/components/ui/styles/ui-kit.css +1135 -0
  192. package/dist/components/ui/styles/ui-video.css +75 -0
  193. package/dist/components/ui/swiperCss.d.ts +15 -0
  194. package/dist/components/ui/swiperCss.js +15 -0
  195. package/dist/components/ui/variants.d.ts +12 -0
  196. package/dist/components/ui/variants.js +10 -0
  197. package/dist/index.d.ts +77 -0
  198. package/dist/index.js +77 -0
  199. package/dist/lib/asciify/painters.d.ts +25 -0
  200. package/dist/lib/asciify/painters.js +604 -0
  201. package/dist/lib/asciify/pointer.d.ts +12 -0
  202. package/dist/lib/asciify/pointer.js +54 -0
  203. package/dist/lib/asciify/shape-painters.d.ts +44 -0
  204. package/dist/lib/asciify/shape-painters.js +335 -0
  205. package/dist/lib/asciify/theme-painters.d.ts +8 -0
  206. package/dist/lib/asciify/theme-painters.js +437 -0
  207. package/dist/lib/cells.d.ts +46 -0
  208. package/dist/lib/cells.js +114 -0
  209. package/dist/lib/scroll/store.d.ts +21 -0
  210. package/dist/lib/scroll/store.js +25 -0
  211. package/dist/lib/sketches/aurora.d.ts +3 -0
  212. package/dist/lib/sketches/aurora.js +42 -0
  213. package/dist/lib/sketches/fire.d.ts +3 -0
  214. package/dist/lib/sketches/fire.js +80 -0
  215. package/dist/lib/sketches/flow.d.ts +3 -0
  216. package/dist/lib/sketches/flow.js +70 -0
  217. package/dist/lib/sketches/life.d.ts +3 -0
  218. package/dist/lib/sketches/life.js +107 -0
  219. package/dist/lib/sketches/matrix.d.ts +3 -0
  220. package/dist/lib/sketches/matrix.js +64 -0
  221. package/dist/lib/sketches/ocean.d.ts +3 -0
  222. package/dist/lib/sketches/ocean.js +56 -0
  223. package/dist/lib/sketches/plasma.d.ts +3 -0
  224. package/dist/lib/sketches/plasma.js +29 -0
  225. package/dist/lib/sketches/registry.d.ts +6 -0
  226. package/dist/lib/sketches/registry.js +60 -0
  227. package/dist/lib/sketches/ripples.d.ts +3 -0
  228. package/dist/lib/sketches/ripples.js +84 -0
  229. package/dist/lib/sketches/scroll-assemble.d.ts +8 -0
  230. package/dist/lib/sketches/scroll-assemble.js +90 -0
  231. package/dist/lib/sketches/scroll-parallax.d.ts +6 -0
  232. package/dist/lib/sketches/scroll-parallax.js +76 -0
  233. package/dist/lib/sketches/scroll-rain.d.ts +6 -0
  234. package/dist/lib/sketches/scroll-rain.js +82 -0
  235. package/dist/lib/sketches/scroll-stats.d.ts +7 -0
  236. package/dist/lib/sketches/scroll-stats.js +81 -0
  237. package/dist/lib/sketches/scroll-terminal.d.ts +6 -0
  238. package/dist/lib/sketches/scroll-terminal.js +87 -0
  239. package/dist/lib/sketches/scroll-zoom.d.ts +7 -0
  240. package/dist/lib/sketches/scroll-zoom.js +49 -0
  241. package/dist/lib/sketches/starfield.d.ts +3 -0
  242. package/dist/lib/sketches/starfield.js +54 -0
  243. package/dist/lib/sketches/text-3d.d.ts +6 -0
  244. package/dist/lib/sketches/text-3d.js +62 -0
  245. package/dist/lib/sketches/text-combo-figlet.d.ts +6 -0
  246. package/dist/lib/sketches/text-combo-figlet.js +91 -0
  247. package/dist/lib/sketches/text-glitch.d.ts +3 -0
  248. package/dist/lib/sketches/text-glitch.js +57 -0
  249. package/dist/lib/sketches/text-marquee.d.ts +3 -0
  250. package/dist/lib/sketches/text-marquee.js +35 -0
  251. package/dist/lib/sketches/text-particles.d.ts +9 -0
  252. package/dist/lib/sketches/text-particles.js +91 -0
  253. package/dist/lib/sketches/text-rain.d.ts +3 -0
  254. package/dist/lib/sketches/text-rain.js +73 -0
  255. package/dist/lib/sketches/text-scramble.d.ts +6 -0
  256. package/dist/lib/sketches/text-scramble.js +49 -0
  257. package/dist/lib/sketches/text-wave.d.ts +3 -0
  258. package/dist/lib/sketches/text-wave.js +43 -0
  259. package/dist/lib/sketches/theme-orbit.d.ts +6 -0
  260. package/dist/lib/sketches/theme-orbit.js +119 -0
  261. package/dist/lib/sketches/theme-pulse.d.ts +7 -0
  262. package/dist/lib/sketches/theme-pulse.js +84 -0
  263. package/dist/lib/sketches/tunnel.d.ts +3 -0
  264. package/dist/lib/sketches/tunnel.js +28 -0
  265. package/dist/lib/text/banner.d.ts +5 -0
  266. package/dist/lib/text/banner.js +35 -0
  267. package/dist/lib/text/mask.d.ts +40 -0
  268. package/dist/lib/text/mask.js +143 -0
  269. package/dist/lib/text/store.d.ts +23 -0
  270. package/dist/lib/text/store.js +86 -0
  271. package/dist/lib/ui/card-fields.d.ts +52 -0
  272. package/dist/lib/ui/card-fields.js +193 -0
  273. package/dist/lib/ui/fonts.d.ts +56 -0
  274. package/dist/lib/ui/fonts.js +94 -0
  275. package/dist/lib/ui/fx.d.ts +42 -0
  276. package/dist/lib/ui/fx.js +162 -0
  277. package/dist/lib/ui/icons.d.ts +437 -0
  278. package/dist/lib/ui/icons.js +314 -0
  279. package/dist/lib/ui/placeholder.d.ts +11 -0
  280. package/dist/lib/ui/placeholder.js +65 -0
  281. package/dist/lib/ui/tokens.d.ts +49 -0
  282. package/dist/lib/ui/tokens.js +129 -0
  283. package/dist/lib/ui/useTokens.d.ts +10 -0
  284. package/dist/lib/ui/useTokens.js +32 -0
  285. package/package.json +80 -0
@@ -0,0 +1,42 @@
1
+ import { clamp01, eachCell, hash2, hsv } from "../cells.js";
2
+ /** Aurora boreal: cortinas de ruido sobre un cielo estrellado y montañas. */
3
+ export function aurora(t) {
4
+ const ramp = t.createGlyphRamp(" .:;+*#%");
5
+ t.draw(() => {
6
+ const s = t.secs;
7
+ const rows = t.grid.rows;
8
+ const top = -Math.floor(rows / 2);
9
+ t.background(0);
10
+ eachCell(t, (x, y) => {
11
+ const yy = (y - top) / rows; // 0 arriba, 1 abajo
12
+ const ridge = 0.8 + 0.1 * t.noise(x * 0.03, 9) + 0.06 * t.noise(x * 0.11, 3);
13
+ if (yy > ridge) {
14
+ t.char(" ");
15
+ t.cellColor(3, 4, 8 + (yy - ridge) * 20);
16
+ return;
17
+ }
18
+ t.cellColor(2, 5, 14 + yy * 26);
19
+ // El pliegue de la cortina ondula en horizontal y se desplaza con el tiempo
20
+ const center = 0.2 + 0.3 * t.noise(x * 0.022, s * 0.06) + 0.07 * Math.sin(x * 0.035 + s * 0.45);
21
+ const fall = Math.exp(-(((yy - center) / 0.17) ** 2));
22
+ const rays = 0.45 + 0.75 * t.noise(x * 0.35, s * 0.3);
23
+ const body = 0.6 + 0.6 * t.noise(x * 0.05, yy * 2.2, s * 0.15);
24
+ const power = clamp01(fall * rays * body);
25
+ if (power > 0.05) {
26
+ const above = clamp01((center - yy) / 0.3);
27
+ const hue = 0.34 + 0.44 * above;
28
+ t.char(ramp.at(power));
29
+ t.charColor(...hsv(hue, 0.6, 0.35 + 0.65 * power));
30
+ t.cellColor(...hsv(hue, 0.9, 0.05 + 0.25 * power));
31
+ }
32
+ else if (hash2(x, y) > 0.988) {
33
+ const tw = Math.sin(s * 2.2 + hash2(y, x) * 60) * 0.5 + 0.5;
34
+ t.char(tw > 0.6 ? "*" : ".");
35
+ t.charColor(255, 255, 255, 90 + 165 * tw);
36
+ }
37
+ else {
38
+ t.char(" ");
39
+ }
40
+ });
41
+ });
42
+ }
@@ -0,0 +1,3 @@
1
+ import type { Textmodifier } from "textmode.js";
2
+ /** Fuego estilo Doom. El puntero es una antorcha; pulsar la convierte en un soplete. */
3
+ export declare function fire(t: Textmodifier): void;
@@ -0,0 +1,80 @@
1
+ import { aspect, createPointer, gridOrigin, mix, plot } from "../cells.js";
2
+ /** Paleta negro → rojo → naranja → amarillo → blanco */
3
+ function fireColor(h) {
4
+ if (h < 0.35) {
5
+ const k = h / 0.35;
6
+ return [mix(10, 200, k), mix(0, 30, k), mix(0, 10, k)];
7
+ }
8
+ if (h < 0.7) {
9
+ const k = (h - 0.35) / 0.35;
10
+ return [mix(200, 255, k), mix(30, 170, k), mix(10, 20, k)];
11
+ }
12
+ const k = (h - 0.7) / 0.3;
13
+ return [255, mix(170, 255, k), mix(20, 210, k)];
14
+ }
15
+ /** Fuego estilo Doom. El puntero es una antorcha; pulsar la convierte en un soplete. */
16
+ export function fire(t) {
17
+ const ramp = t.createGlyphRamp(" .:-=+*#%@");
18
+ const ptr = createPointer(t);
19
+ let W = 0;
20
+ let H = 0;
21
+ let heat = new Float32Array(0);
22
+ const rebuild = () => {
23
+ W = t.grid.cols;
24
+ H = t.grid.rows;
25
+ heat = new Float32Array(W * H);
26
+ };
27
+ t.draw(() => {
28
+ if (W !== t.grid.cols || H !== t.grid.rows)
29
+ rebuild();
30
+ ptr.update();
31
+ const { x0, y0 } = gridOrigin(t);
32
+ if (t.frameCount % 2 === 0) {
33
+ // Combustible con lenguas de distinta altura, moduladas por ruido
34
+ for (let x = 0; x < W; x++) {
35
+ const fuel = t.noise(x * 0.09, t.secs * 0.5);
36
+ heat[(H - 1) * W + x] = Math.min(1, 0.35 + fuel * 1.1 + Math.random() * 0.1);
37
+ }
38
+ const r = ptr.pressed ? 9 : 4;
39
+ const asp = aspect(t);
40
+ const rx = Math.ceil(r * asp);
41
+ const gx = Math.round(ptr.x - x0);
42
+ const gy = Math.round(ptr.y - y0);
43
+ if (ptr.hovering) {
44
+ for (let dy = -r; dy <= r; dy++) {
45
+ for (let dx = -rx; dx <= rx; dx++) {
46
+ const x = gx + dx;
47
+ const y = gy + dy;
48
+ if (x < 0 || y < 0 || x >= W || y >= H)
49
+ continue;
50
+ if (Math.hypot(dx / asp, dy) <= r)
51
+ heat[y * W + x] = 1;
52
+ }
53
+ }
54
+ }
55
+ const decay = 1.9 / H;
56
+ const wind = Math.sin(t.secs * 0.4) * 0.6;
57
+ for (let y = 0; y < H - 1; y++) {
58
+ for (let x = 0; x < W; x++) {
59
+ // Cada celda toma calor de la de abajo, ladeada al azar y por el viento
60
+ const sx = Math.min(W - 1, Math.max(0, x + Math.round(Math.random() * 2 - 1 + wind)));
61
+ const src = (heat[(y + 1) * W + sx] * 2 + heat[(y + 1) * W + x]) / 3;
62
+ heat[y * W + x] = Math.max(0, src - decay * (0.5 + Math.random()));
63
+ }
64
+ }
65
+ }
66
+ t.background(8, 4, 8);
67
+ for (let y = 0; y < H; y++) {
68
+ for (let x = 0; x < W; x++) {
69
+ const h = heat[y * W + x];
70
+ if (h < 0.03)
71
+ continue;
72
+ const [r, g, b] = fireColor(h);
73
+ t.char(ramp.at(h));
74
+ t.charColor(Math.min(255, r * 1.25), Math.min(255, g * 1.2 + 20), b);
75
+ t.cellColor(r * 0.45, g * 0.4, b * 0.4);
76
+ plot(t, x0 + x, y0 + y);
77
+ }
78
+ }
79
+ });
80
+ }
@@ -0,0 +1,3 @@
1
+ import type { Textmodifier } from "textmode.js";
2
+ /** Partículas sobre un campo de flujo de ruido. El puntero las atrae; pulsar las repele. */
3
+ export declare function flow(t: Textmodifier): void;
@@ -0,0 +1,70 @@
1
+ import { aspect, createPointer, gridOrigin, hsv, plot } from "../cells.js";
2
+ const TRAIL = 9;
3
+ /** Partículas sobre un campo de flujo de ruido. El puntero las atrae; pulsar las repele. */
4
+ export function flow(t) {
5
+ const ptr = createPointer(t);
6
+ const ramp = t.createGlyphRamp(" .:-=+*#");
7
+ const particles = [];
8
+ const respawn = (p) => {
9
+ const { cols, rows, x0, y0 } = gridOrigin(t);
10
+ p.x = x0 + Math.random() * cols;
11
+ p.y = y0 + Math.random() * rows;
12
+ p.age = 0;
13
+ p.life = 120 + Math.random() * 260;
14
+ p.trail = [];
15
+ };
16
+ // La rejilla no existe hasta el primer fotograma, así que las partículas se crean allí
17
+ const init = () => {
18
+ for (let i = 0; i < 800; i++) {
19
+ const p = { x: 0, y: 0, age: 0, life: 0, trail: [] };
20
+ respawn(p);
21
+ p.age = Math.random() * p.life;
22
+ particles.push(p);
23
+ }
24
+ };
25
+ t.draw(() => {
26
+ if (particles.length === 0)
27
+ init();
28
+ ptr.update();
29
+ const s = t.secs;
30
+ const asp = aspect(t);
31
+ const { cols, rows, x0, y0 } = gridOrigin(t);
32
+ const sign = ptr.pressed ? -1 : 1;
33
+ t.background(5, 6, 14);
34
+ for (const p of particles) {
35
+ const n = t.noise(p.x * 0.025, p.y * 0.025 * asp, s * 0.07);
36
+ const ang = n * Math.PI * 4;
37
+ let vx = Math.cos(ang) * 0.5;
38
+ let vy = (Math.sin(ang) * 0.5) / asp;
39
+ const dx = ptr.x - p.x;
40
+ const dy = (ptr.y - p.y) * asp;
41
+ const d = Math.hypot(dx, dy) + 0.001;
42
+ if (d < 34) {
43
+ const pull = ((34 - d) / 34) * 0.9 * sign;
44
+ vx += (dx / d) * pull;
45
+ vy += ((dy / d) * pull) / asp;
46
+ }
47
+ p.x += vx;
48
+ p.y += vy;
49
+ p.age++;
50
+ if (p.age % 2 === 0) {
51
+ p.trail.push(p.x, p.y);
52
+ if (p.trail.length > TRAIL * 2)
53
+ p.trail.splice(0, 2);
54
+ }
55
+ if (p.age > p.life || p.x < x0 - 2 || p.x > x0 + cols + 2 || p.y < y0 - 2 || p.y > y0 + rows + 2) {
56
+ respawn(p);
57
+ continue;
58
+ }
59
+ const hue = 0.52 + (ang / (Math.PI * 4)) * 0.4;
60
+ const len = p.trail.length / 2;
61
+ for (let k = 0; k < len; k++) {
62
+ const f = (k + 1) / len;
63
+ t.char(ramp.at(f));
64
+ t.charColor(...hsv(hue, 0.65, 0.25 + 0.75 * f));
65
+ t.cellColor(...hsv(hue, 0.8, 0.06 * f));
66
+ plot(t, Math.round(p.trail[k * 2]), Math.round(p.trail[k * 2 + 1]));
67
+ }
68
+ }
69
+ });
70
+ }
@@ -0,0 +1,3 @@
1
+ import type { Textmodifier } from "textmode.js";
2
+ /** Juego de la vida toroidal. Mover el puntero siembra células; pulsar siembra en grande. */
3
+ export declare function life(t: Textmodifier): void;
@@ -0,0 +1,107 @@
1
+ import { aspect, createPointer, gridOrigin, hsv, plot } from "../cells.js";
2
+ /** Juego de la vida toroidal. Mover el puntero siembra células; pulsar siembra en grande. */
3
+ export function life(t) {
4
+ const ptr = createPointer(t);
5
+ let W = 0;
6
+ let H = 0;
7
+ let alive = new Uint8Array(0);
8
+ let scratch = new Uint8Array(0);
9
+ let age = new Uint16Array(0);
10
+ let ghost = new Float32Array(0);
11
+ let steps = 0;
12
+ const seed = (density, keep = false) => {
13
+ for (let i = 0; i < W * H; i++) {
14
+ if (keep && alive[i])
15
+ continue;
16
+ if (Math.random() < density)
17
+ alive[i] = 1;
18
+ }
19
+ };
20
+ const rebuild = () => {
21
+ W = t.grid.cols;
22
+ H = t.grid.rows;
23
+ alive = new Uint8Array(W * H);
24
+ scratch = new Uint8Array(W * H);
25
+ age = new Uint16Array(W * H);
26
+ ghost = new Float32Array(W * H);
27
+ seed(0.2);
28
+ };
29
+ const step = () => {
30
+ let pop = 0;
31
+ for (let y = 0; y < H; y++) {
32
+ const ym = ((y + H - 1) % H) * W;
33
+ const yp = ((y + 1) % H) * W;
34
+ for (let x = 0; x < W; x++) {
35
+ const xm = (x + W - 1) % W;
36
+ const xp = (x + 1) % W;
37
+ const n = alive[ym + xm] + alive[ym + x] + alive[ym + xp] +
38
+ alive[y * W + xm] + alive[y * W + xp] +
39
+ alive[yp + xm] + alive[yp + x] + alive[yp + xp];
40
+ const i = y * W + x;
41
+ const live = alive[i] ? n === 2 || n === 3 : n === 3;
42
+ scratch[i] = live ? 1 : 0;
43
+ if (live) {
44
+ age[i] = alive[i] ? Math.min(age[i] + 1, 60) : 0;
45
+ pop++;
46
+ }
47
+ else if (alive[i]) {
48
+ ghost[i] = 1;
49
+ }
50
+ }
51
+ }
52
+ [alive, scratch] = [scratch, alive];
53
+ steps++;
54
+ if (pop < W * H * 0.012)
55
+ seed(0.2);
56
+ else if (steps % 500 === 0)
57
+ seed(0.03, true);
58
+ };
59
+ t.draw(() => {
60
+ if (W !== t.grid.cols || H !== t.grid.rows)
61
+ rebuild();
62
+ ptr.update();
63
+ const { x0, y0 } = gridOrigin(t);
64
+ if (ptr.raw) {
65
+ const r = ptr.pressed ? 6 : 2;
66
+ const p = ptr.pressed ? 0.6 : 0.3;
67
+ const asp = aspect(t);
68
+ const rx = Math.ceil(r * asp);
69
+ const gx = Math.round(ptr.raw.x - x0);
70
+ const gy = Math.round(ptr.raw.y - y0);
71
+ for (let dy = -r; dy <= r; dy++) {
72
+ for (let dx = -rx; dx <= rx; dx++) {
73
+ if (Math.hypot(dx / asp, dy) > r)
74
+ continue;
75
+ const x = gx + dx;
76
+ const y = gy + dy;
77
+ if (x < 0 || y < 0 || x >= W || y >= H)
78
+ continue;
79
+ if (Math.random() < p)
80
+ alive[y * W + x] = 1;
81
+ }
82
+ }
83
+ }
84
+ if (t.frameCount % 4 === 0)
85
+ step();
86
+ t.background(4, 5, 12);
87
+ for (let y = 0; y < H; y++) {
88
+ for (let x = 0; x < W; x++) {
89
+ const i = y * W + x;
90
+ if (alive[i]) {
91
+ const a = age[i];
92
+ t.char(a < 2 ? "@" : a < 8 ? "O" : a < 24 ? "o" : "+");
93
+ t.charColor(...hsv(0.5 + Math.min(a, 40) * 0.006, 0.55, a < 2 ? 1 : 0.85));
94
+ t.cellColor(...hsv(0.55, 0.7, 0.14 + (a < 2 ? 0.14 : 0)));
95
+ plot(t, x0 + x, y0 + y);
96
+ }
97
+ else if (ghost[i] > 0.05) {
98
+ ghost[i] *= 0.9;
99
+ t.char(".");
100
+ t.charColor(...hsv(0.85, 0.6, ghost[i] * 0.9));
101
+ t.cellColor(4, 5, 12);
102
+ plot(t, x0 + x, y0 + y);
103
+ }
104
+ }
105
+ }
106
+ });
107
+ }
@@ -0,0 +1,3 @@
1
+ import type { Textmodifier } from "textmode.js";
2
+ /** Lluvia digital. Las columnas cercanas al puntero se vuelven cian, aceleran y se descomponen. */
3
+ export declare function matrix(t: Textmodifier): void;
@@ -0,0 +1,64 @@
1
+ import { aspect, createPointer, gridOrigin, plot } from "../cells.js";
2
+ const GLYPHS = "01ABCDEFGHIJKLMNOPQRSTUVWXYZ<>{}[]/\\|+=*:;#$%&@";
3
+ /** Lluvia digital. Las columnas cercanas al puntero se vuelven cian, aceleran y se descomponen. */
4
+ export function matrix(t) {
5
+ const ptr = createPointer(t);
6
+ let columns = [];
7
+ let W = 0;
8
+ let H = 0;
9
+ const glyph = () => GLYPHS[Math.floor(Math.random() * GLYPHS.length)];
10
+ const spawn = (initial) => {
11
+ const len = 8 + Math.random() * 22;
12
+ return {
13
+ head: initial ? Math.random() * H * 1.4 - H * 0.2 : -len - Math.random() * H * 0.5,
14
+ speed: 0.12 + Math.random() * 0.5,
15
+ len,
16
+ chars: Array.from({ length: H + 48 }, glyph),
17
+ };
18
+ };
19
+ const rebuild = () => {
20
+ W = t.grid.cols;
21
+ H = t.grid.rows;
22
+ columns = Array.from({ length: W }, () => spawn(true));
23
+ };
24
+ t.draw(() => {
25
+ if (W !== t.grid.cols || H !== t.grid.rows)
26
+ rebuild();
27
+ ptr.update();
28
+ const asp = aspect(t);
29
+ const { x0, y0 } = gridOrigin(t);
30
+ const R = 11 + (ptr.pressed ? 10 : 0);
31
+ t.background(0, 6, 2);
32
+ for (let i = 0; i < W; i++) {
33
+ const c = columns[i];
34
+ const x = x0 + i;
35
+ const headY = y0 + c.head;
36
+ const near = Math.hypot(x - ptr.x, (headY - ptr.y) * asp) < R;
37
+ c.head += c.speed * (near ? 2.4 : 1);
38
+ if (Math.random() < 0.06)
39
+ c.chars[Math.floor(Math.random() * c.chars.length)] = glyph();
40
+ if (c.head - c.len > H)
41
+ columns[i] = spawn(false);
42
+ for (let k = 0; k < c.len; k++) {
43
+ const row = Math.floor(c.head) - k;
44
+ if (row < 0 || row >= H)
45
+ continue;
46
+ const fade = 1 - k / c.len;
47
+ const y = y0 + row;
48
+ const hot = Math.hypot(x - ptr.x, (y - ptr.y) * asp) < R;
49
+ t.char(hot && Math.random() < 0.4 ? glyph() : c.chars[row % c.chars.length]);
50
+ if (k === 0) {
51
+ t.charColor(hot ? 210 : 200, 255, hot ? 255 : 220);
52
+ }
53
+ else if (hot) {
54
+ t.charColor(40 * fade, 220 * fade + 30, 255 * fade + 20);
55
+ }
56
+ else {
57
+ t.charColor(0, 60 + 195 * fade * fade, 40 * fade);
58
+ }
59
+ t.cellColor(0, 8 + 14 * fade, 4);
60
+ plot(t, x, y);
61
+ }
62
+ }
63
+ });
64
+ }
@@ -0,0 +1,3 @@
1
+ import type { Textmodifier } from "textmode.js";
2
+ /** Atardecer sobre el mar: cielo degradado, sol y reflejo que centellea entre las olas. */
3
+ export declare function ocean(t: Textmodifier): void;
@@ -0,0 +1,56 @@
1
+ import { aspect, clamp01, eachCell, hash2, mix, smoothstep } from "../cells.js";
2
+ /** Atardecer sobre el mar: cielo degradado, sol y reflejo que centellea entre las olas. */
3
+ export function ocean(t) {
4
+ t.draw(() => {
5
+ const s = t.secs;
6
+ const asp = aspect(t);
7
+ const rows = t.grid.rows;
8
+ const horizon = Math.round(rows * 0.08); // fila (coordenada Y) del horizonte
9
+ const top = -Math.floor(rows / 2);
10
+ const bottom = top + rows;
11
+ const sunR = Math.max(6, rows * 0.16);
12
+ t.background(0);
13
+ eachCell(t, (x, y) => {
14
+ if (y < horizon) {
15
+ // Cielo
16
+ const k = (y - top) / (horizon - top);
17
+ const dx = x;
18
+ const dy = (y - (horizon - sunR * 0.55)) * asp;
19
+ const d = Math.hypot(dx, dy);
20
+ const glow = Math.exp(-d / (sunR * 2.2)) * 0.9;
21
+ let r = mix(24, 255, k * k) + glow * 90;
22
+ let g = mix(14, 120, k * k * k) + glow * 70;
23
+ let b = mix(60, 110, k) + glow * 10;
24
+ t.cellColor(r, g, b);
25
+ if (d < sunR) {
26
+ t.char(" ");
27
+ t.cellColor(255, 220 - d * 4, 130 - d * 5);
28
+ t.charColor(255, 240, 190);
29
+ }
30
+ else if (k < 0.5 && hash2(x, y) > 0.985) {
31
+ t.char(Math.sin(s * 2 + hash2(y, x) * 40) > 0 ? "*" : ".");
32
+ t.charColor(255, 255, 255, (1 - k * 2) * 255);
33
+ }
34
+ else {
35
+ t.char(" ");
36
+ }
37
+ return;
38
+ }
39
+ // Agua
40
+ const depth = clamp01((y - horizon) / (bottom - horizon));
41
+ const k = 0.12 + 0.55 * (1 - depth);
42
+ const wave = Math.sin(x * k + s * (1 + depth * 2.5) + Math.sin(y * 0.7 + s * 0.6) * 0.8) * 0.5 + 0.5;
43
+ const sunSpread = 3 + depth * 26;
44
+ const glitter = Math.exp(-(x * x) / (sunSpread * sunSpread)) * smoothstep(0.35, 0.9, wave);
45
+ t.cellColor(mix(70, 6, depth) + glitter * 190, mix(30, 14, depth) + glitter * 130, mix(90, 40, depth) + glitter * 20);
46
+ if (glitter > 0.25) {
47
+ t.char("=");
48
+ t.charColor(255, 235, 180);
49
+ }
50
+ else {
51
+ t.char(wave > 0.8 ? "~" : wave > 0.5 ? "-" : " ");
52
+ t.charColor(mix(190, 90, depth), mix(90, 110, depth), mix(150, 190, depth));
53
+ }
54
+ });
55
+ });
56
+ }
@@ -0,0 +1,3 @@
1
+ import type { Textmodifier } from "textmode.js";
2
+ /** Plasma con rampa de glifos. El puntero deforma el campo; al pulsar la onda crece. */
3
+ export declare function plasma(t: Textmodifier): void;
@@ -0,0 +1,29 @@
1
+ import { aspect, clamp01, createPointer, eachCell, hsv } from "../cells.js";
2
+ /** Plasma con rampa de glifos. El puntero deforma el campo; al pulsar la onda crece. */
3
+ export function plasma(t) {
4
+ const ramp = t.createGlyphRamp(" .:-=+*#%@");
5
+ const ptr = createPointer(t);
6
+ t.draw(() => {
7
+ ptr.update();
8
+ const s = t.secs;
9
+ const asp = aspect(t);
10
+ const radius = ptr.pressed ? 900 : 260;
11
+ t.background(0);
12
+ eachCell(t, (x, y) => {
13
+ const yy = y * asp;
14
+ let v = Math.sin(x * 0.09 + s) +
15
+ Math.sin(yy * 0.13 - s * 1.3) +
16
+ Math.sin((x + yy) * 0.06 + s * 0.7) +
17
+ Math.sin(Math.hypot(x * 0.8, yy) * 0.08 - s * 1.1);
18
+ const dx = x - ptr.x;
19
+ const dy = (y - ptr.y) * asp;
20
+ const d2 = dx * dx + dy * dy;
21
+ v += 3 * Math.exp(-d2 / radius) * Math.sin(s * 4 - Math.sqrt(d2) * 0.5);
22
+ const n = clamp01((v + 4) / 8);
23
+ const hue = n * 0.55 + s * 0.02 + 0.55;
24
+ t.char(ramp.at(n));
25
+ t.charColor(...hsv(hue, 0.75, 0.3 + 0.7 * n));
26
+ t.cellColor(...hsv(hue, 0.85, 0.05 + 0.13 * n));
27
+ });
28
+ });
29
+ }
@@ -0,0 +1,6 @@
1
+ import type { Textmodifier } from "textmode.js";
2
+ export type Sketch = {
3
+ fontSize: number;
4
+ setup: (t: Textmodifier) => void;
5
+ };
6
+ export declare const sketches: Record<string, Sketch>;
@@ -0,0 +1,60 @@
1
+ import { aurora } from "./aurora.js";
2
+ import { fire } from "./fire.js";
3
+ import { flow } from "./flow.js";
4
+ import { life } from "./life.js";
5
+ import { matrix } from "./matrix.js";
6
+ import { ocean } from "./ocean.js";
7
+ import { plasma } from "./plasma.js";
8
+ import { ripples } from "./ripples.js";
9
+ import { starfield } from "./starfield.js";
10
+ import { tunnel } from "./tunnel.js";
11
+ import { scAssemble } from "./scroll-assemble.js";
12
+ import { scParallax } from "./scroll-parallax.js";
13
+ import { scRain } from "./scroll-rain.js";
14
+ import { scStats } from "./scroll-stats.js";
15
+ import { scTerminal } from "./scroll-terminal.js";
16
+ import { scZoom } from "./scroll-zoom.js";
17
+ import { tx3d } from "./text-3d.js";
18
+ import { txScramble } from "./text-scramble.js";
19
+ import { thOrbit } from "./theme-orbit.js";
20
+ import { thPulse } from "./theme-pulse.js";
21
+ import { txComboFiglet } from "./text-combo-figlet.js";
22
+ import { txGlitch } from "./text-glitch.js";
23
+ import { txMarquee } from "./text-marquee.js";
24
+ import { txParticles } from "./text-particles.js";
25
+ import { txRain } from "./text-rain.js";
26
+ import { txWave } from "./text-wave.js";
27
+ export const sketches = {
28
+ plasma: { fontSize: 16, setup: plasma },
29
+ matrix: { fontSize: 16, setup: matrix },
30
+ starfield: { fontSize: 14, setup: starfield },
31
+ ripples: { fontSize: 14, setup: ripples },
32
+ life: { fontSize: 14, setup: life },
33
+ flow: { fontSize: 14, setup: flow },
34
+ fire: { fontSize: 14, setup: fire },
35
+ ocean: { fontSize: 16, setup: ocean },
36
+ tunnel: { fontSize: 16, setup: tunnel },
37
+ aurora: { fontSize: 16, setup: aurora },
38
+ // Demos de texto (leen lo que se escribe en el cajón de la interfaz)
39
+ "tx-wave": { fontSize: 12, setup: txWave },
40
+ "tx-particles": { fontSize: 12, setup: txParticles },
41
+ "tx-glitch": { fontSize: 12, setup: txGlitch },
42
+ "tx-rain": { fontSize: 14, setup: txRain },
43
+ "tx-marquee": { fontSize: 16, setup: txMarquee },
44
+ "tx-combo-figlet": { fontSize: 14, setup: txComboFiglet },
45
+ "tx-scramble": { fontSize: 12, setup: txScramble },
46
+ "tx-3d": { fontSize: 12, setup: tx3d },
47
+ // Demos con scroll (300vh): leen scrollState
48
+ "sc-zoom": { fontSize: 12, setup: scZoom },
49
+ "sc-assemble": { fontSize: 12, setup: (t) => scAssemble(t) },
50
+ "sc-rain": { fontSize: 14, setup: scRain },
51
+ "sc-parallax": { fontSize: 14, setup: scParallax },
52
+ "sc-terminal": { fontSize: 20, setup: scTerminal },
53
+ "sc-stats": { fontSize: 10, setup: scStats },
54
+ "sc-combo": { fontSize: 12, setup: (t) => scAssemble(t, { transparent: true }) },
55
+ // Fondos de las landings temáticas
56
+ "th-orbit": { fontSize: 14, setup: thOrbit },
57
+ "th-pulse": { fontSize: 14, setup: thPulse },
58
+ // Capa superior del combo: partículas de texto sin fondo, fusionadas con la capa de asciify
59
+ "tx-combo-layers": { fontSize: 12, setup: (t) => txParticles(t, { transparent: true }) },
60
+ };
@@ -0,0 +1,3 @@
1
+ import type { Textmodifier } from "textmode.js";
2
+ /** Agua. Cada movimiento del puntero lanza ondas; pulsar deja caer una gota grande. */
3
+ export declare function ripples(t: Textmodifier): void;
@@ -0,0 +1,84 @@
1
+ import { aspect, clamp01, createPointer, gridOrigin, plot } from "../cells.js";
2
+ /** Agua. Cada movimiento del puntero lanza ondas; pulsar deja caer una gota grande. */
3
+ export function ripples(t) {
4
+ const ramp = t.createGlyphRamp(" .,:;+*#@");
5
+ const ptr = createPointer(t);
6
+ let W = 0;
7
+ let H = 0;
8
+ let cur = new Float32Array(0);
9
+ let prev = new Float32Array(0);
10
+ let next = new Float32Array(0);
11
+ const rebuild = () => {
12
+ W = t.grid.cols;
13
+ H = t.grid.rows;
14
+ cur = new Float32Array(W * H);
15
+ prev = new Float32Array(W * H);
16
+ next = new Float32Array(W * H);
17
+ };
18
+ const drop = (cx, cy, r, amp) => {
19
+ const asp = aspect(t);
20
+ const ry = Math.ceil(r);
21
+ const rx = Math.ceil(r * asp);
22
+ for (let dy = -ry; dy <= ry; dy++) {
23
+ for (let dx = -rx; dx <= rx; dx++) {
24
+ const x = cx + dx;
25
+ const y = cy + dy;
26
+ if (x < 1 || y < 1 || x >= W - 1 || y >= H - 1)
27
+ continue;
28
+ const f = Math.max(0, 1 - Math.hypot(dx, dy * asp) / (r * asp + 0.5));
29
+ cur[y * W + x] += amp * f;
30
+ }
31
+ }
32
+ };
33
+ let wasPressed = false;
34
+ t.draw(() => {
35
+ if (W !== t.grid.cols || H !== t.grid.rows)
36
+ rebuild();
37
+ ptr.update();
38
+ const { x0, y0 } = gridOrigin(t);
39
+ // Entradas: puntero y lluvia ocasional
40
+ if (ptr.raw) {
41
+ const gx = ptr.raw.x - x0;
42
+ const gy = ptr.raw.y - y0;
43
+ if (ptr.pressed && !wasPressed)
44
+ drop(gx, gy, 4, 6);
45
+ else if (Math.abs(ptr.vx) + Math.abs(ptr.vy) > 0.15)
46
+ drop(gx, gy, 1, 1.4);
47
+ }
48
+ wasPressed = ptr.pressed;
49
+ if (t.frameCount % 45 === 0) {
50
+ drop(2 + Math.floor(Math.random() * (W - 4)), 2 + Math.floor(Math.random() * (H - 4)), 2, 3);
51
+ }
52
+ // Ecuación de ondas anisótropa: las celdas son ~2 veces más altas que anchas
53
+ const asp = aspect(t);
54
+ const kx = 1;
55
+ const ky = 1 / (asp * asp);
56
+ const a = 0.92 / (kx + ky); // condición de estabilidad: a·(kx+ky) < 1
57
+ for (let y = 1; y < H - 1; y++) {
58
+ for (let x = 1; x < W - 1; x++) {
59
+ const i = y * W + x;
60
+ const u = cur[i];
61
+ const lap = kx * (cur[i - 1] + cur[i + 1] - 2 * u) + ky * (cur[i - W] + cur[i + W] - 2 * u);
62
+ next[i] = (2 * u - prev[i] + a * lap) * 0.99;
63
+ }
64
+ }
65
+ [prev, cur, next] = [cur, next, prev];
66
+ t.background(3, 10, 24);
67
+ for (let y = 0; y < H; y++) {
68
+ for (let x = 0; x < W; x++) {
69
+ const v = cur[y * W + x];
70
+ const m = Math.abs(v);
71
+ if (m < 0.04)
72
+ continue;
73
+ const n = clamp01(m * 0.9);
74
+ t.char(ramp.at(n));
75
+ if (v > 0)
76
+ t.charColor(120 + 135 * n, 210 + 45 * n, 255);
77
+ else
78
+ t.charColor(20 + 40 * n, 90 + 90 * n, 200 + 50 * n);
79
+ t.cellColor(4 + 20 * n, 16 + 60 * n, 40 + 90 * n);
80
+ plot(t, x0 + x, y0 + y);
81
+ }
82
+ }
83
+ });
84
+ }
@@ -0,0 +1,8 @@
1
+ import type { Textmodifier } from "textmode.js";
2
+ /**
3
+ * Ensamblaje: las partículas empiezan dispersas, se agrupan formando tu texto a medida
4
+ * que bajas y estallan hacia fuera al final del recorrido.
5
+ */
6
+ export declare function scAssemble(t: Textmodifier, opts?: {
7
+ transparent?: boolean;
8
+ }): void;