@staticcanvas/typeflow 0.34.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 (178) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +637 -0
  3. package/branding/dist/ico/typeflow-logo-16x16.ico +0 -0
  4. package/branding/dist/ico/typeflow-logo-256x256.ico +0 -0
  5. package/branding/dist/ico/typeflow-logo-32x32.ico +0 -0
  6. package/branding/dist/ico/typeflow-logo-48x48.ico +0 -0
  7. package/branding/dist/png/typeflow-logo-1024x1024.png +0 -0
  8. package/branding/dist/png/typeflow-logo-128x128.png +0 -0
  9. package/branding/dist/png/typeflow-logo-16x16.png +0 -0
  10. package/branding/dist/png/typeflow-logo-256x256.png +0 -0
  11. package/branding/dist/png/typeflow-logo-512x512.png +0 -0
  12. package/branding/dist/png/typeflow-logo-64x64.png +0 -0
  13. package/branding/dist/webp/typeflow-logo-1024x1024.webp +0 -0
  14. package/branding/dist/webp/typeflow-logo-128x128.webp +0 -0
  15. package/branding/dist/webp/typeflow-logo-16x16.webp +0 -0
  16. package/branding/dist/webp/typeflow-logo-256x256.webp +0 -0
  17. package/branding/dist/webp/typeflow-logo-32x32.webp +0 -0
  18. package/branding/dist/webp/typeflow-logo-48x48.webp +0 -0
  19. package/branding/dist/webp/typeflow-logo-512x512.webp +0 -0
  20. package/branding/dist/webp/typeflow-logo-64x64.webp +0 -0
  21. package/branding/gen-logo.ps1 +14 -0
  22. package/branding/typeflow-logo.svg +162 -0
  23. package/dist/typeflow/LICENSE +21 -0
  24. package/dist/typeflow/README.md +231 -0
  25. package/dist/typeflow/branding/dist/ico/typeflow-logo-16x16.ico +0 -0
  26. package/dist/typeflow/branding/dist/ico/typeflow-logo-256x256.ico +0 -0
  27. package/dist/typeflow/branding/dist/ico/typeflow-logo-32x32.ico +0 -0
  28. package/dist/typeflow/branding/dist/ico/typeflow-logo-48x48.ico +0 -0
  29. package/dist/typeflow/branding/dist/png/typeflow-logo-1024x1024.png +0 -0
  30. package/dist/typeflow/branding/dist/png/typeflow-logo-128x128.png +0 -0
  31. package/dist/typeflow/branding/dist/png/typeflow-logo-16x16.png +0 -0
  32. package/dist/typeflow/branding/dist/png/typeflow-logo-256x256.png +0 -0
  33. package/dist/typeflow/branding/dist/png/typeflow-logo-512x512.png +0 -0
  34. package/dist/typeflow/branding/dist/png/typeflow-logo-64x64.png +0 -0
  35. package/dist/typeflow/branding/dist/webp/typeflow-logo-1024x1024.webp +0 -0
  36. package/dist/typeflow/branding/dist/webp/typeflow-logo-128x128.webp +0 -0
  37. package/dist/typeflow/branding/dist/webp/typeflow-logo-16x16.webp +0 -0
  38. package/dist/typeflow/branding/dist/webp/typeflow-logo-256x256.webp +0 -0
  39. package/dist/typeflow/branding/dist/webp/typeflow-logo-32x32.webp +0 -0
  40. package/dist/typeflow/branding/dist/webp/typeflow-logo-48x48.webp +0 -0
  41. package/dist/typeflow/branding/dist/webp/typeflow-logo-512x512.webp +0 -0
  42. package/dist/typeflow/branding/dist/webp/typeflow-logo-64x64.webp +0 -0
  43. package/dist/typeflow/branding/gen-logo.ps1 +14 -0
  44. package/dist/typeflow/branding/typeflow-logo.svg +162 -0
  45. package/dist/typeflow/dist/typeflow-caret.cjs +47 -0
  46. package/dist/typeflow/dist/typeflow-caret.cjs.map +1 -0
  47. package/dist/typeflow/dist/typeflow-caret.esm.js +47 -0
  48. package/dist/typeflow/dist/typeflow-caret.esm.js.map +1 -0
  49. package/dist/typeflow/dist/typeflow-caret.esm.min.js +2 -0
  50. package/dist/typeflow/dist/typeflow-caret.esm.min.js.map +1 -0
  51. package/dist/typeflow/dist/typeflow-caret.js +47 -0
  52. package/dist/typeflow/dist/typeflow-caret.js.map +1 -0
  53. package/dist/typeflow/dist/typeflow-caret.min.js +2 -0
  54. package/dist/typeflow/dist/typeflow-caret.min.js.map +1 -0
  55. package/dist/typeflow/dist/typeflow-caret.mjs +47 -0
  56. package/dist/typeflow/dist/typeflow-caret.mjs.map +1 -0
  57. package/dist/typeflow/dist/typeflow-debug.cjs +109 -0
  58. package/dist/typeflow/dist/typeflow-debug.cjs.map +1 -0
  59. package/dist/typeflow/dist/typeflow-debug.esm.js +109 -0
  60. package/dist/typeflow/dist/typeflow-debug.esm.js.map +1 -0
  61. package/dist/typeflow/dist/typeflow-debug.esm.min.js +2 -0
  62. package/dist/typeflow/dist/typeflow-debug.esm.min.js.map +1 -0
  63. package/dist/typeflow/dist/typeflow-debug.js +109 -0
  64. package/dist/typeflow/dist/typeflow-debug.js.map +1 -0
  65. package/dist/typeflow/dist/typeflow-debug.min.js +2 -0
  66. package/dist/typeflow/dist/typeflow-debug.min.js.map +1 -0
  67. package/dist/typeflow/dist/typeflow-debug.mjs +109 -0
  68. package/dist/typeflow/dist/typeflow-debug.mjs.map +1 -0
  69. package/dist/typeflow/dist/typeflow-extchars.cjs +66 -0
  70. package/dist/typeflow/dist/typeflow-extchars.cjs.map +1 -0
  71. package/dist/typeflow/dist/typeflow-extchars.esm.js +66 -0
  72. package/dist/typeflow/dist/typeflow-extchars.esm.js.map +1 -0
  73. package/dist/typeflow/dist/typeflow-extchars.esm.min.js +2 -0
  74. package/dist/typeflow/dist/typeflow-extchars.esm.min.js.map +1 -0
  75. package/dist/typeflow/dist/typeflow-extchars.js +66 -0
  76. package/dist/typeflow/dist/typeflow-extchars.js.map +1 -0
  77. package/dist/typeflow/dist/typeflow-extchars.min.js +2 -0
  78. package/dist/typeflow/dist/typeflow-extchars.min.js.map +1 -0
  79. package/dist/typeflow/dist/typeflow-extchars.mjs +66 -0
  80. package/dist/typeflow/dist/typeflow-extchars.mjs.map +1 -0
  81. package/dist/typeflow/dist/typeflow-keystroke.cjs +47 -0
  82. package/dist/typeflow/dist/typeflow-keystroke.cjs.map +1 -0
  83. package/dist/typeflow/dist/typeflow-keystroke.esm.js +47 -0
  84. package/dist/typeflow/dist/typeflow-keystroke.esm.js.map +1 -0
  85. package/dist/typeflow/dist/typeflow-keystroke.esm.min.js +2 -0
  86. package/dist/typeflow/dist/typeflow-keystroke.esm.min.js.map +1 -0
  87. package/dist/typeflow/dist/typeflow-keystroke.js +47 -0
  88. package/dist/typeflow/dist/typeflow-keystroke.js.map +1 -0
  89. package/dist/typeflow/dist/typeflow-keystroke.min.js +2 -0
  90. package/dist/typeflow/dist/typeflow-keystroke.min.js.map +1 -0
  91. package/dist/typeflow/dist/typeflow-keystroke.mjs +47 -0
  92. package/dist/typeflow/dist/typeflow-keystroke.mjs.map +1 -0
  93. package/dist/typeflow/dist/typeflow-metrics.cjs +76 -0
  94. package/dist/typeflow/dist/typeflow-metrics.cjs.map +1 -0
  95. package/dist/typeflow/dist/typeflow-metrics.esm.js +76 -0
  96. package/dist/typeflow/dist/typeflow-metrics.esm.js.map +1 -0
  97. package/dist/typeflow/dist/typeflow-metrics.esm.min.js +2 -0
  98. package/dist/typeflow/dist/typeflow-metrics.esm.min.js.map +1 -0
  99. package/dist/typeflow/dist/typeflow-metrics.js +76 -0
  100. package/dist/typeflow/dist/typeflow-metrics.js.map +1 -0
  101. package/dist/typeflow/dist/typeflow-metrics.min.js +2 -0
  102. package/dist/typeflow/dist/typeflow-metrics.min.js.map +1 -0
  103. package/dist/typeflow/dist/typeflow-metrics.mjs +76 -0
  104. package/dist/typeflow/dist/typeflow-metrics.mjs.map +1 -0
  105. package/dist/typeflow/dist/typeflow-parallel.cjs +3 -0
  106. package/dist/typeflow/dist/typeflow-parallel.cjs.map +1 -0
  107. package/dist/typeflow/dist/typeflow-parallel.esm.js +3 -0
  108. package/dist/typeflow/dist/typeflow-parallel.esm.js.map +1 -0
  109. package/dist/typeflow/dist/typeflow-parallel.esm.min.js +2 -0
  110. package/dist/typeflow/dist/typeflow-parallel.esm.min.js.map +1 -0
  111. package/dist/typeflow/dist/typeflow-parallel.js +3 -0
  112. package/dist/typeflow/dist/typeflow-parallel.js.map +1 -0
  113. package/dist/typeflow/dist/typeflow-parallel.min.js +2 -0
  114. package/dist/typeflow/dist/typeflow-parallel.min.js.map +1 -0
  115. package/dist/typeflow/dist/typeflow-parallel.mjs +3 -0
  116. package/dist/typeflow/dist/typeflow-parallel.mjs.map +1 -0
  117. package/dist/typeflow/dist/typeflow-webaudio.cjs +81 -0
  118. package/dist/typeflow/dist/typeflow-webaudio.cjs.map +1 -0
  119. package/dist/typeflow/dist/typeflow-webaudio.esm.js +81 -0
  120. package/dist/typeflow/dist/typeflow-webaudio.esm.js.map +1 -0
  121. package/dist/typeflow/dist/typeflow-webaudio.esm.min.js +2 -0
  122. package/dist/typeflow/dist/typeflow-webaudio.esm.min.js.map +1 -0
  123. package/dist/typeflow/dist/typeflow-webaudio.js +81 -0
  124. package/dist/typeflow/dist/typeflow-webaudio.js.map +1 -0
  125. package/dist/typeflow/dist/typeflow-webaudio.min.js +2 -0
  126. package/dist/typeflow/dist/typeflow-webaudio.min.js.map +1 -0
  127. package/dist/typeflow/dist/typeflow-webaudio.mjs +81 -0
  128. package/dist/typeflow/dist/typeflow-webaudio.mjs.map +1 -0
  129. package/dist/typeflow/dist/typeflow.cjs +277 -0
  130. package/dist/typeflow/dist/typeflow.cjs.map +1 -0
  131. package/dist/typeflow/dist/typeflow.esm.js +277 -0
  132. package/dist/typeflow/dist/typeflow.esm.js.map +1 -0
  133. package/dist/typeflow/dist/typeflow.esm.min.js +2 -0
  134. package/dist/typeflow/dist/typeflow.esm.min.js.map +1 -0
  135. package/dist/typeflow/dist/typeflow.js +277 -0
  136. package/dist/typeflow/dist/typeflow.js.map +1 -0
  137. package/dist/typeflow/dist/typeflow.min.js +2 -0
  138. package/dist/typeflow/dist/typeflow.min.js.map +1 -0
  139. package/dist/typeflow/dist/typeflow.mjs +277 -0
  140. package/dist/typeflow/dist/typeflow.mjs.map +1 -0
  141. package/dist/typeflow/jsr.jsonc +27 -0
  142. package/dist/typeflow/package.json +79 -0
  143. package/dist/typeflow/src/typeflow-audio-presets.js +137 -0
  144. package/dist/typeflow/src/typeflow-caret.d.ts +65 -0
  145. package/dist/typeflow/src/typeflow-caret.js +303 -0
  146. package/dist/typeflow/src/typeflow-debug.d.ts +34 -0
  147. package/dist/typeflow/src/typeflow-debug.js +223 -0
  148. package/dist/typeflow/src/typeflow-extchars.d.ts +28 -0
  149. package/dist/typeflow/src/typeflow-extchars.js +132 -0
  150. package/dist/typeflow/src/typeflow-keystroke.d.ts +28 -0
  151. package/dist/typeflow/src/typeflow-keystroke.js +220 -0
  152. package/dist/typeflow/src/typeflow-metrics.d.ts +38 -0
  153. package/dist/typeflow/src/typeflow-metrics.js +556 -0
  154. package/dist/typeflow/src/typeflow-parallel.d.ts +36 -0
  155. package/dist/typeflow/src/typeflow-parallel.js +157 -0
  156. package/dist/typeflow/src/typeflow-webaudio.d.ts +83 -0
  157. package/dist/typeflow/src/typeflow-webaudio.js +517 -0
  158. package/dist/typeflow/src/typeflow.d.ts +328 -0
  159. package/dist/typeflow/src/typeflow.js +2119 -0
  160. package/jsr.jsonc +27 -0
  161. package/package.json +133 -0
  162. package/src/typeflow-audio-presets.js +137 -0
  163. package/src/typeflow-caret.d.ts +65 -0
  164. package/src/typeflow-caret.js +303 -0
  165. package/src/typeflow-debug.d.ts +34 -0
  166. package/src/typeflow-debug.js +223 -0
  167. package/src/typeflow-extchars.d.ts +28 -0
  168. package/src/typeflow-extchars.js +132 -0
  169. package/src/typeflow-keystroke.d.ts +28 -0
  170. package/src/typeflow-keystroke.js +220 -0
  171. package/src/typeflow-metrics.d.ts +38 -0
  172. package/src/typeflow-metrics.js +556 -0
  173. package/src/typeflow-parallel.d.ts +36 -0
  174. package/src/typeflow-parallel.js +157 -0
  175. package/src/typeflow-webaudio.d.ts +83 -0
  176. package/src/typeflow-webaudio.js +517 -0
  177. package/src/typeflow.d.ts +328 -0
  178. package/src/typeflow.js +2119 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typeflow.cjs","sources":["../../../src/typeflow.js"],"sourcesContent":["/**\n * TypeFlow - A lightweight, interruptible, framework-agnostic typewriter library\n * @version 2.3.0\n * @license MIT\n *\n * Zero dependencies. Safe by default (no innerHTML string concatenation).\n * Vanilla-first, with Intl.Segmenter support, multi-style reveals, and integrations for React, Vue, Svelte, Solid.js, Alpine.js, and Web Components.\n */\n\n// ============================================================\n// Constants\n// ============================================================\n\nconst SCRAMBLE_CHARSETS = {\n matrix: '01X_#*~<>[]{}',\n ascii: '!@#$%^&*()_+-=[]{}|;:,.<>?',\n 'ascii-extended': '¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿',\n blocks: ' ▂▃▄▅▆▇█░▒▓',\n binary: '01',\n hex: '0123456789ABCDEF',\n braille: '⠁⠃⠇⠏⠟⠿⡿⣿',\n runic: 'ᚠᚡᚢᚣᚤᚥᚦᚧᚨᚩᚪᚫᚬᚭᚮᚯ',\n cyber: '!<>-_\\\\/[]{}—=+*^?#________',\n};\n\nconst PRESETS = {\n cyberpunk: {\n typeStyle: 'scramble',\n scrambleCharset: 'matrix',\n scrambleRounds: 2,\n speed: 40,\n cursor: '|',\n cursorBlink: true,\n audio: 'synth',\n },\n terminal: {\n typeStyle: 'char',\n speed: 32,\n cursor: '█',\n cursorBlink: true,\n audio: 'mechanical',\n },\n writer: {\n naturalCadence: true,\n speed: 52,\n speedVariance: 22,\n cursor: '|',\n cursorBlink: true,\n audio: 'mechanical',\n },\n matrix: {\n typeStyle: 'scramble',\n scrambleCharset: 'matrix',\n scrambleRounds: 3,\n speed: 30,\n cursor: '█',\n cursorBlink: true,\n audio: 'synth',\n },\n blocks: {\n typeStyle: 'scramble',\n scrambleCharset: 'blocks',\n scrambleRounds: 2,\n speed: 45,\n cursor: '█',\n cursorBlink: true,\n },\n subtle: {\n speed: 45,\n cursor: '|',\n cursorBlink: true,\n eraseStyle: 'fade',\n respectReducedMotion: true,\n },\n};\n\nconst TYPE_DEFAULTS = {\n speed: 50,\n delay: 0,\n speedVariance: 0,\n naturalCadence: false,\n granularity: 'grapheme',\n cursor: '|',\n cursorBlink: true,\n html: false,\n mode: 'replace',\n direction: 'left',\n typeStyle: 'char',\n scrambleCharset: 'cyber',\n scrambleGlyphs: '!<>-_\\\\/[]{}—=+*^?#________',\n scrambleRounds: 2,\n audio: null,\n respectReducedMotion: true,\n};\n\nconst ERASE_DEFAULTS = {\n ...TYPE_DEFAULTS,\n speed: 25,\n cursorBlink: false,\n eraseStyle: 'end',\n preserveBaseline: true,\n};\n\nconst VOID_ELEMENTS = new Set([\n 'br',\n 'hr',\n 'img',\n 'input',\n 'wbr',\n 'area',\n 'base',\n 'col',\n 'embed',\n 'link',\n 'meta',\n 'source',\n 'track',\n]);\n\nconst DEFAULT_ALLOWED_TAGS = new Set([\n 'b',\n 'strong',\n 'i',\n 'em',\n 'mark',\n 'span',\n 'small',\n 'sub',\n 'sup',\n 'u',\n 'br',\n 'a',\n 'code',\n]);\n\nconst DEFAULT_ALLOWED_ATTRS = {\n a: new Set(['href', 'title', 'target', 'rel']),\n span: new Set(['class']),\n mark: new Set(['class']),\n '*': new Set(['class']),\n};\n\nconst CURSOR_BLINK_INTERVAL = 530;\nconst DEFAULT_FADE_DURATION = 250;\nconst DEFAULT_WORD_FADE_DURATION = 280;\nconst DEFAULT_WORD_STAGGER = 70;\n// Shared spatial-motion tokens reused by every `float-in-*` and `zoom-in-space`\n// reveal/erase variant so distance, depth, and perspective stay consistent.\nconst DEFAULT_MOTION_DISTANCE = 24;\nconst DEFAULT_MOTION_DEPTH = 160;\nconst DEFAULT_MOTION_SCALE = 0.82;\nconst DEFAULT_MOTION_PERSPECTIVE = 600;\nconst DEFAULT_MOTION_EASING = 'ease';\n\nconst WORD_MOTION_STYLES = new Set([\n 'word-fade',\n 'float-in-top',\n 'float-in-bottom',\n 'float-in-left',\n 'float-in-right',\n 'zoom-in-space',\n]);\n\n// ============================================================\n// Web Audio Micro-Synthesizer\n// ============================================================\n\nlet audioCtx = null;\nfunction getAudioContext() {\n if (typeof window === 'undefined') return null;\n const AudioCtx = window.AudioContext || window.webkitAudioContext;\n if (!AudioCtx) return null;\n if (!audioCtx) {\n try {\n audioCtx = new AudioCtx();\n } catch {\n return null;\n }\n }\n if (audioCtx && audioCtx.state === 'suspended') {\n audioCtx.resume().catch(() => {});\n }\n return audioCtx;\n}\n\nfunction playKeystrokeSound(audioOption) {\n if (!audioOption) return;\n if (typeof audioOption === 'function') {\n try {\n audioOption();\n } catch {\n // Audio callbacks are optional and must not interrupt typing.\n }\n return;\n }\n const type = typeof audioOption === 'string' ? audioOption : 'mechanical';\n try {\n const ctx = getAudioContext();\n if (!ctx) return;\n const now = ctx.currentTime;\n const osc = ctx.createOscillator();\n const gain = ctx.createGain();\n\n if (type === 'beep') {\n osc.type = 'sine';\n osc.frequency.setValueAtTime(880, now);\n gain.gain.setValueAtTime(0.03, now);\n gain.gain.exponentialRampToValueAtTime(0.001, now + 0.035);\n osc.connect(gain);\n gain.connect(ctx.destination);\n osc.start(now);\n osc.stop(now + 0.035);\n } else if (type === 'synth') {\n osc.type = 'sawtooth';\n osc.frequency.setValueAtTime(340, now);\n osc.frequency.exponentialRampToValueAtTime(140, now + 0.04);\n gain.gain.setValueAtTime(0.025, now);\n gain.gain.exponentialRampToValueAtTime(0.001, now + 0.04);\n osc.connect(gain);\n gain.connect(ctx.destination);\n osc.start(now);\n osc.stop(now + 0.04);\n } else {\n // 'mechanical' switch click\n osc.type = 'triangle';\n osc.frequency.setValueAtTime(1100 + Math.random() * 300, now);\n gain.gain.setValueAtTime(0.035, now);\n gain.gain.exponentialRampToValueAtTime(0.001, now + 0.02);\n osc.connect(gain);\n gain.connect(ctx.destination);\n osc.start(now);\n osc.stop(now + 0.02);\n }\n } catch {\n // Audio playback is best effort and may be unavailable in the browser.\n }\n}\n\nfunction stopKeystrokeSound(audioOption) {\n try {\n audioOption.stop();\n } catch {\n // Optional audio cleanup must not interrupt controller cancellation.\n }\n}\n\n// ============================================================\n// Intl.Segmenter Helper & Unit Slicing\n// ============================================================\n\nfunction segmentText(text, granularity = 'grapheme') {\n if (typeof Intl !== 'undefined' && Intl.Segmenter) {\n const segmenter = new Intl.Segmenter(undefined, { granularity });\n return Array.from(segmenter.segment(text), (s) => s.segment);\n }\n if (granularity === 'word') {\n const matches = text.match(/\\s+|\\S+/g);\n return matches ? matches : [text];\n }\n return Array.from(text);\n}\n\nconst SEGMENTED_NODE_CACHE = new WeakMap();\nfunction segmentNodeText(node, granularity = 'grapheme') {\n const text = node.textContent ?? '';\n let entry = SEGMENTED_NODE_CACHE.get(node);\n if (!entry || entry.text !== text) {\n entry = { text, values: new Map() };\n SEGMENTED_NODE_CACHE.set(node, entry);\n }\n if (!entry.values.has(granularity)) entry.values.set(granularity, segmentText(text, granularity));\n return entry.values.get(granularity);\n}\n\nfunction resolveScrambleGlyphs(glyphs, charset) {\n if (charset && SCRAMBLE_CHARSETS[charset]) return SCRAMBLE_CHARSETS[charset];\n if (typeof glyphs === 'string' && SCRAMBLE_CHARSETS[glyphs]) return SCRAMBLE_CHARSETS[glyphs];\n return glyphs ?? SCRAMBLE_CHARSETS.cyber;\n}\n\nfunction getRandomGlyph(glyphs) {\n return glyphs[Math.floor(Math.random() * glyphs.length)];\n}\n\n// ============================================================\n// Sanitization\n// ============================================================\n\nfunction isSafeUrl(value) {\n const v = value.trim().toLowerCase();\n return !v.startsWith('javascript:') && !v.startsWith('data:') && !v.startsWith('vbscript:');\n}\n\nfunction sanitizeElement(el, allowedTags, allowedAttrs) {\n const tag = el.tagName.toLowerCase();\n if (!allowedTags.has(tag)) return null;\n\n const clean = document.createElement(tag);\n const allowedForTag = allowedAttrs[tag] ?? new Set();\n const allowedGlobal = allowedAttrs['*'] ?? new Set();\n\n for (const attr of Array.from(el.attributes)) {\n const name = attr.name.toLowerCase();\n if (name.startsWith('on')) continue;\n if (!allowedForTag.has(name) && !allowedGlobal.has(name)) continue;\n if ((name === 'href' || name === 'src') && !isSafeUrl(attr.value)) continue;\n clean.setAttribute(name, attr.value);\n }\n\n if (tag === 'a' && clean.getAttribute('target') === '_blank') {\n clean.setAttribute('rel', 'noopener noreferrer');\n }\n\n return clean;\n}\n\nfunction buildSourceTree(input, plainText, allowedTags, allowedAttrs) {\n const fragment = document.createDocumentFragment();\n if (plainText) {\n fragment.appendChild(document.createTextNode(input));\n return fragment;\n }\n\n const template = document.createElement('template');\n template.innerHTML = input;\n\n const walk = (source, target) => {\n source.childNodes.forEach((child) => {\n if (child.nodeType === Node.TEXT_NODE) {\n target.appendChild(document.createTextNode(child.textContent ?? ''));\n } else if (child.nodeType === Node.ELEMENT_NODE) {\n const clean = sanitizeElement(child, allowedTags, allowedAttrs);\n if (clean) {\n target.appendChild(clean);\n walk(child, clean);\n } else {\n walk(child, target);\n }\n }\n });\n };\n\n walk(template.content, fragment);\n return fragment;\n}\n\n// ============================================================\n// Reveal Engines (Universal Window Slice)\n// ============================================================\n\nfunction countTextUnits(node, granularity = 'grapheme') {\n if (node.nodeType === 3) {\n return segmentNodeText(node, granularity).length;\n }\n let total = 0;\n node.childNodes.forEach((child) => (total += countTextUnits(child, granularity)));\n return total;\n}\n\nfunction cloneRevealWindow(node, start, end, granularity = 'grapheme', revealOpts = {}) {\n if (node.nodeType === 3) {\n const units = segmentNodeText(node, granularity);\n const len = units.length;\n if (end <= 0 || start >= len) {\n return { clone: null, start: Math.max(0, start - len), end: Math.max(0, end - len) };\n }\n const s = Math.max(0, start);\n const e = Math.min(len, end);\n\n const doc = node?.ownerDocument || (typeof document !== 'undefined' ? document : null);\n if (!doc) return { clone: null, start, end };\n\n if (revealOpts?.scrambleActive && e > s && units[e - 1]?.trim()) {\n const frag = doc.createDocumentFragment();\n if (e - 1 > s) {\n frag.appendChild(doc.createTextNode(units.slice(s, e - 1).join('')));\n }\n const scrambleSpan = doc.createElement('span');\n scrambleSpan.className = 'tf-scramble';\n if (revealOpts.scrambleColor) {\n scrambleSpan.style.color = revealOpts.scrambleColor;\n }\n if (revealOpts.scrambleGradient) {\n scrambleSpan.style.backgroundImage = revealOpts.scrambleGradient;\n scrambleSpan.style.webkitBackgroundImage = revealOpts.scrambleGradient;\n scrambleSpan.style.webkitBackgroundClip = 'text';\n scrambleSpan.style.backgroundClip = 'text';\n scrambleSpan.style.webkitTextFillColor = 'transparent';\n scrambleSpan.style.display = 'inline-block';\n }\n scrambleSpan.textContent = getRandomGlyph(revealOpts.scrambleGlyphs);\n frag.appendChild(scrambleSpan);\n return {\n clone: frag,\n start: Math.max(0, start - len),\n end: Math.max(0, end - len),\n };\n }\n\n const trailLen =\n typeof revealOpts.trailFade === 'number'\n ? revealOpts.trailFade\n : typeof revealOpts.trailingFadeLength === 'number'\n ? revealOpts.trailingFadeLength\n : revealOpts.trailFade\n ? 4\n : 0;\n\n if (trailLen > 0 && e - s >= 1 && !revealOpts.isComplete) {\n const frag = doc.createDocumentFragment();\n const solidEnd = Math.max(s, e - trailLen);\n if (solidEnd > s) {\n frag.appendChild(doc.createTextNode(units.slice(s, solidEnd).join('')));\n }\n const trailCount = e - solidEnd;\n const minOp =\n typeof revealOpts.trailingFadeMinOpacity === 'number'\n ? revealOpts.trailingFadeMinOpacity\n : typeof revealOpts.trailMinOpacity === 'number'\n ? revealOpts.trailMinOpacity\n : 0.18;\n for (let i = 0; i < trailCount; i++) {\n const charIdx = solidEnd + i;\n const charSpan = doc.createElement('span');\n charSpan.className = 'tf-trail';\n const progress = trailCount <= 1 ? 1 : (i + 1) / trailCount;\n const opacity = minOp + (1.0 - minOp) * progress;\n charSpan.style.opacity = opacity.toFixed(3);\n charSpan.textContent = units[charIdx];\n frag.appendChild(charSpan);\n }\n return {\n clone: frag,\n start: Math.max(0, start - len),\n end: Math.max(0, end - len),\n };\n }\n\n const sliced = units.slice(s, e).join('');\n return {\n clone: doc.createTextNode(sliced),\n start: Math.max(0, start - len),\n end: Math.max(0, end - len),\n };\n }\n if (node.nodeType === 1) {\n const el = node;\n const tag = el.tagName.toLowerCase();\n if (VOID_ELEMENTS.has(tag)) {\n if (end <= 0) return { clone: null, start, end };\n return { clone: el.cloneNode(false), start, end };\n }\n const clone = el.cloneNode(false);\n let curStart = start;\n let curEnd = end;\n let appended = false;\n node.childNodes.forEach((child) => {\n const result = cloneRevealWindow(child, curStart, curEnd, granularity, revealOpts);\n if (result.clone) {\n clone.appendChild(result.clone);\n appended = true;\n }\n curStart = result.start;\n curEnd = result.end;\n });\n return { clone: appended ? clone : null, start: curStart, end: curEnd };\n }\n return { clone: null, start, end };\n}\n\nfunction revealWindowFragment(source, start, end, granularity = 'grapheme', revealOpts = {}) {\n const doc = source?.ownerDocument || (typeof document !== 'undefined' ? document : null);\n if (!doc) return null;\n const out = doc.createDocumentFragment();\n let curStart = start;\n let curEnd = end;\n source.childNodes.forEach((child) => {\n const result = cloneRevealWindow(child, curStart, curEnd, granularity, revealOpts);\n if (result.clone) out.appendChild(result.clone);\n curStart = result.start;\n curEnd = result.end;\n });\n return out;\n}\n\nfunction calculateWindowBounds(count, totalUnits, direction, eraseStyle, isErasing) {\n if (isErasing) {\n if (eraseStyle === 'start') {\n return { start: totalUnits - count, end: totalUnits };\n }\n if (eraseStyle === 'center') {\n const s = Math.max(0, Math.floor((totalUnits - count) / 2));\n return {\n start: s,\n end: Math.min(totalUnits, s + count),\n };\n }\n return { start: 0, end: count };\n }\n\n if (direction === 'right') {\n return { start: totalUnits - count, end: totalUnits };\n }\n if (direction === 'center') {\n const s = Math.max(0, Math.floor((totalUnits - count) / 2));\n return {\n start: s,\n end: Math.min(totalUnits, s + count),\n };\n }\n return { start: 0, end: count };\n}\n\n// ============================================================\n// Core Engine\n// ============================================================\n\nfunction resolveTarget(target) {\n const el = resolveMaybeTarget(target);\n if (!el) {\n const desc = target === null ? 'null' : target === undefined ? 'undefined' : String(target);\n throw new Error(`TypeFlow: target element not found (${desc})`);\n }\n return el;\n}\n\nfunction resolveMaybeTarget(target) {\n return typeof target === 'string' ? document.querySelector(target) : target;\n}\n\nfunction normalizeDirection(dir) {\n if (!dir) return 'left';\n const s = String(dir).toLowerCase();\n if (s === 'right' || s === 'rtl' || s === 'end' || s === 'reverse') return 'right';\n if (s === 'center' || s === 'middle' || s === 'expand' || s === 'both') return 'center';\n return 'left';\n}\n\nfunction normalizeTypeStyle(style) {\n if (!style) return 'char';\n const s = String(style).toLowerCase();\n if (s === 'word' || s === 'words' || s === 'stream') return 'word';\n if (s === 'scramble' || s === 'matrix' || s === 'decrypt' || s === 'cyber' || s === 'random')\n return 'scramble';\n if (s === 'fade-trail' || s === 'trail' || s === 'trailing' || s === 'soft') return 'fade-trail';\n if (s === 'word-fade' || s === 'fade-words' || s === 'wordfade') return 'word-fade';\n if (s === 'float-in-top' || s === 'float-top' || s === 'float-down') return 'float-in-top';\n if (s === 'float-in-bottom' || s === 'float-bottom' || s === 'float-up') return 'float-in-bottom';\n if (s === 'float-in-left' || s === 'float-left') return 'float-in-left';\n if (s === 'float-in-right' || s === 'float-right') return 'float-in-right';\n if (s === 'zoom-in-space' || s === 'zoom-in' || s === 'zoom-space') return 'zoom-in-space';\n return 'char';\n}\n\nfunction normalizeEraseStyle(style) {\n if (!style) return 'end';\n const s = String(style).toLowerCase();\n if (s === 'start' || s === 'erosion' || s === 'left' || s === 'forward') return 'start';\n if (s === 'center' || s === 'middle' || s === 'shrink' || s === 'split') return 'center';\n if (s === 'scramble' || s === 'matrix' || s === 'decrypt' || s === 'cyber' || s === 'random')\n return 'scramble';\n if (s === 'fade-trail' || s === 'trail' || s === 'trailing' || s === 'soft') return 'fade-trail';\n if (s === 'fade' || s === 'dissolve' || s === 'crossfade') return 'fade';\n if (s === 'word-fade' || s === 'fade-words' || s === 'wordfade') return 'word-fade';\n if (s === 'float-in-top' || s === 'float-top' || s === 'float-down') return 'float-in-top';\n if (s === 'float-in-bottom' || s === 'float-bottom' || s === 'float-up') return 'float-in-bottom';\n if (s === 'float-in-left' || s === 'float-left') return 'float-in-left';\n if (s === 'float-in-right' || s === 'float-right') return 'float-in-right';\n if (s === 'zoom-in-space' || s === 'zoom-in' || s === 'zoom-space') return 'zoom-in-space';\n if (s === 'instant' || s === 'clear' || s === 'reset' || s === 'immediate') return 'instant';\n return 'end';\n}\n\nfunction normalizeWordOrder(order) {\n const value = String(order ?? 'left-to-right').toLowerCase();\n if (value === 'right-to-left' || value === 'reverse' || value === 'rtl') return 'right-to-left';\n if (value === 'random' || value === 'shuffle') return 'random';\n return 'left-to-right';\n}\n\nfunction createSeededRandom(seed) {\n if (seed === undefined || seed === null) return Math.random;\n const text = String(seed);\n let state = 2166136261;\n for (let index = 0; index < text.length; index += 1) {\n state ^= text.charCodeAt(index);\n state = Math.imul(state, 16777619);\n }\n return () => {\n state += 0x6d2b79f5;\n let value = state;\n value = Math.imul(value ^ (value >>> 15), value | 1);\n value ^= value + Math.imul(value ^ (value >>> 7), value | 61);\n return ((value ^ (value >>> 14)) >>> 0) / 4294967296;\n };\n}\n\nfunction orderWordIndexes(length, order, seed) {\n const indexes = Array.from({ length }, (_, index) => index);\n if (normalizeWordOrder(order) === 'right-to-left') return indexes.reverse();\n if (normalizeWordOrder(order) !== 'random') return indexes;\n\n const random = createSeededRandom(seed);\n for (let index = indexes.length - 1; index > 0; index -= 1) {\n const swapIndex = Math.floor(random() * (index + 1));\n [indexes[index], indexes[swapIndex]] = [indexes[swapIndex], indexes[index]];\n }\n return indexes;\n}\n\nfunction segmentWords(text) {\n if (typeof Intl !== 'undefined' && Intl.Segmenter) {\n return Array.from(new Intl.Segmenter(undefined, { granularity: 'word' }).segment(text));\n }\n return (text.match(/\\s+|\\S+/g) ?? []).map((segment) => ({\n segment,\n isWordLike: !/^\\s+$/u.test(segment),\n }));\n}\n\n/**\n * Resolves the hidden/visible transform pair for a spatial word-motion style.\n * Returns `null` for the plain `word-fade` style, which is opacity-only and\n * needs no transform (so words keep `display: inline` and normal text flow).\n */\nfunction getWordMotionTransforms(motionKind, options) {\n const distance = Math.max(0, Number(options.wordMotionDistance ?? DEFAULT_MOTION_DISTANCE) || 0);\n const depth = Math.max(0, Number(options.wordMotionDepth ?? DEFAULT_MOTION_DEPTH) || 0);\n const scale = Math.min(\n 1,\n Math.max(0.01, Number(options.wordMotionScale ?? DEFAULT_MOTION_SCALE) || DEFAULT_MOTION_SCALE)\n );\n\n switch (motionKind) {\n case 'float-in-top':\n return { hidden: `translateY(-${distance}px)`, visible: 'translateY(0)' };\n case 'float-in-bottom':\n return { hidden: `translateY(${distance}px)`, visible: 'translateY(0)' };\n case 'float-in-left':\n return { hidden: `translateX(-${distance}px)`, visible: 'translateX(0)' };\n case 'float-in-right':\n return { hidden: `translateX(${distance}px)`, visible: 'translateX(0)' };\n case 'zoom-in-space':\n return {\n hidden: `translateZ(-${depth}px) scale(${scale})`,\n visible: 'translateZ(0) scale(1)',\n };\n default:\n return null;\n }\n}\n\nfunction buildWordMotionTree(source, layout = 'opacity', motionKind = 'word-fade') {\n const doc = source?.ownerDocument || (typeof document !== 'undefined' ? document : null);\n if (!doc) return { fragment: null, words: [] };\n const fragment = doc.createDocumentFragment();\n const words = [];\n // Transform has no effect on `display: inline` boxes, so transformed\n // variants promote each word wrapper to `inline-block`.\n const needsTransform = motionKind !== 'word-fade';\n\n const walk = (sourceNode, targetNode) => {\n sourceNode.childNodes.forEach((child) => {\n if (child.nodeType === Node.TEXT_NODE) {\n for (const part of segmentWords(child.textContent ?? '')) {\n if (/^\\s+$/u.test(part.segment)) {\n targetNode.appendChild(doc.createTextNode(part.segment));\n continue;\n }\n\n if (\n part.isWordLike === false &&\n words.length > 0 &&\n words.at(-1).parentNode === targetNode\n ) {\n words.at(-1).appendChild(doc.createTextNode(part.segment));\n continue;\n }\n\n const wrapper = doc.createElement('span');\n wrapper.className = 'tf-word-fade';\n wrapper.dataset.tfWordIndex = String(words.length);\n wrapper.textContent = part.segment;\n wrapper.style.display = needsTransform ? 'inline-block' : 'inline';\n wrapper.style.opacity = '0';\n wrapper.style.willChange = needsTransform ? 'opacity, transform' : 'opacity';\n wrapper.setAttribute('aria-hidden', 'true');\n if (layout === 'placeholder') wrapper.style.visibility = 'hidden';\n words.push(wrapper);\n targetNode.appendChild(wrapper);\n }\n } else if (child.nodeType === Node.ELEMENT_NODE) {\n const clone = child.cloneNode(false);\n targetNode.appendChild(clone);\n walk(child, clone);\n }\n });\n };\n\n walk(source, fragment);\n return { fragment, words };\n}\n\nfunction prefersReducedMotion() {\n return (\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches\n );\n}\n\nfunction calculateCadencePause(text, count) {\n if (count <= 0 || count > text.length) return 0;\n const char = text[count - 1];\n if (char === '.' || char === '!' || char === '?') return 220;\n if (char === ',' || char === ';' || char === ':') return 110;\n if (char === ' ') return 40;\n return 0;\n}\n\n/**\n * Builds a `<span class=\"tf-cursor\">` blinking-cursor element. Shared by the\n * character/window renderer, word-motion renderer, and the {@link Caret} API.\n */\nfunction createCursorSpan(cursorChar, isHidden = false) {\n const span = document.createElement('span');\n span.className = 'tf-cursor';\n span.setAttribute('aria-hidden', 'true');\n span.textContent = cursorChar;\n if (isHidden) span.style.visibility = 'hidden';\n return span;\n}\n\n/**\n * Core animation engine that manages all active TypeFlow instances.\n *\n * Each target element may have at most one active animation at a time.\n * Starting a new animation on an already-animating element stops the previous\n * one before beginning the new one.\n *\n * Accessed via the exported singleton {@link TypeFlow}.\n *\n * @class\n */\nclass TypeFlowEngine {\n active = new Map();\n baselines = new WeakMap();\n cursorIntervals = new Map();\n\n clearCursorInterval(el) {\n const interval = this.cursorIntervals.get(el);\n if (interval) {\n clearInterval(interval);\n this.cursorIntervals.delete(el);\n }\n }\n\n animate(el, sourceTree, totalUnits, options, startCount, endCount, resultText, extra = {}) {\n this.clearCursorInterval(el);\n this.active.get(el)?.stop();\n if (options.ariaLive) el.setAttribute('aria-live', options.ariaLive);\n\n const prefix = extra.prefix ?? [];\n const blinkOnFinish = extra.blinkOnFinish ?? false;\n const direction = endCount >= startCount ? 1 : -1;\n const speed = Math.max(0, Number(options.speed ?? TYPE_DEFAULTS.speed) || 0);\n const granularity = options.granularity ?? TYPE_DEFAULTS.granularity;\n const isScramble = options.typeStyle === 'scramble' || options.eraseStyle === 'scramble';\n const scrambleGlyphs = resolveScrambleGlyphs(\n options.scrambleGlyphs,\n options.scrambleCharset ?? options.scramblePreset\n );\n\n let settled = false;\n let timeoutId = null;\n let resolveFn = null;\n const incrementalPlainText =\n extra.plainText === true &&\n direction === 1 &&\n options.direction === 'left' &&\n !isScramble &&\n options.typeStyle !== 'fade-trail' &&\n options.trailFade === undefined &&\n options.trailingFadeLength === undefined;\n // Plain-text source trees always contain one text node, including empty input.\n const plainUnits = incrementalPlainText\n ? segmentNodeText(sourceTree.firstChild, granularity)\n : null;\n const incrementalTextNode = plainUnits ? document.createTextNode('') : null;\n let incrementalCursor = null;\n let lastIncrementalCount = 0;\n\n const clearTimers = () => {\n if (timeoutId !== null) clearTimeout(timeoutId);\n this.clearCursorInterval(el);\n timeoutId = null;\n };\n\n const render = (unitCount, cursorChar, scrambleActive = false, cursorHidden = false) => {\n if (incrementalTextNode && !scrambleActive) {\n if (unitCount === lastIncrementalCount + 1)\n incrementalTextNode.data += plainUnits[lastIncrementalCount] ?? '';\n else if (unitCount !== lastIncrementalCount)\n incrementalTextNode.data = plainUnits.slice(0, unitCount).join('');\n lastIncrementalCount = unitCount;\n if (!incrementalTextNode.parentNode) el.replaceChildren(...prefix, incrementalTextNode);\n if (cursorChar) {\n if (!incrementalCursor) incrementalCursor = createCursorSpan(cursorChar, cursorHidden);\n incrementalCursor.textContent = cursorChar;\n incrementalCursor.style.visibility = cursorHidden ? 'hidden' : 'visible';\n if (!incrementalCursor.parentNode) el.appendChild(incrementalCursor);\n } else if (incrementalCursor?.parentNode) {\n incrementalCursor.remove();\n }\n return;\n }\n const bounds = calculateWindowBounds(\n unitCount,\n totalUnits,\n options.direction ?? 'left',\n options.eraseStyle ?? 'end',\n extra.isErasing ?? false\n );\n const isTrailFade =\n (options.trailFade !== null && options.trailFade !== undefined) ||\n (options.trailingFadeLength !== null && options.trailingFadeLength !== undefined) ||\n options.typeStyle === 'fade-trail' ||\n options.eraseStyle === 'fade-trail';\n const trailLen =\n typeof options.trailFade === 'number'\n ? options.trailFade\n : typeof options.trailingFadeLength === 'number'\n ? options.trailingFadeLength\n : isTrailFade\n ? (options.trailingFadeLength ?? 4)\n : 0;\n const trailMinOpacity =\n typeof options.trailingFadeMinOpacity === 'number'\n ? options.trailingFadeMinOpacity\n : typeof options.trailMinOpacity === 'number'\n ? options.trailMinOpacity\n : 0.18;\n\n el.replaceChildren(\n ...prefix,\n revealWindowFragment(sourceTree, bounds.start, bounds.end, granularity, {\n scrambleActive,\n scrambleGlyphs,\n scrambleColor: options.scrambleColor,\n scrambleGradient: options.scrambleGradient,\n trailFade: trailLen,\n trailingFadeLength: trailLen,\n trailingFadeMinOpacity: trailMinOpacity,\n isComplete: unitCount === endCount && !scrambleActive,\n })\n );\n if (cursorChar) {\n el.appendChild(createCursorSpan(cursorChar, cursorHidden));\n }\n };\n\n const settle = (completed) => {\n if (settled) return;\n settled = true;\n clearTimers();\n this.active.delete(el);\n if (completed) {\n if (blinkOnFinish && options.cursor && options.cursorBlink) {\n let visible = true;\n render(endCount, options.cursor, false, false);\n const intervalId = setInterval(() => {\n visible = !visible;\n render(endCount, options.cursor, false, !visible);\n }, CURSOR_BLINK_INTERVAL);\n intervalId.unref?.();\n this.cursorIntervals.set(el, intervalId);\n } else {\n render(endCount, '', false);\n }\n options.onComplete?.(resultText);\n } else {\n this.clearCursorInterval(el);\n stopKeystrokeSound(options.audio);\n options.onInterrupt?.();\n }\n resolveFn?.({ completed, text: resultText });\n };\n\n const controller = {\n stop: () => settle(false),\n promise: new Promise((resolve) => {\n resolveFn = resolve;\n }),\n };\n this.active.set(el, controller);\n\n const shouldReduceMotion = options.respectReducedMotion === true && prefersReducedMotion();\n\n if (shouldReduceMotion) {\n settle(true);\n return controller;\n }\n\n let scrambleStep = 0;\n const scrambleRounds = options.scrambleRounds ?? TYPE_DEFAULTS.scrambleRounds;\n\n const step = (count) => {\n if (options.audio) playKeystrokeSound(options.audio);\n\n if (isScramble && scrambleStep < scrambleRounds && count !== endCount) {\n render(count, options.cursor ?? '', true);\n scrambleStep++;\n timeoutId = setTimeout(() => step(count), Math.max(10, speed / 2));\n return;\n }\n scrambleStep = 0;\n\n render(count, options.cursor ?? '', false);\n if (count === endCount) {\n settle(true);\n return;\n }\n\n const jitter = options.speedVariance ? (Math.random() * 2 - 1) * options.speedVariance : 0;\n const cadencePause = options.naturalCadence ? calculateCadencePause(resultText, count) : 0;\n const delayMs = Math.max(0, speed + jitter + cadencePause);\n\n timeoutId = setTimeout(() => step(count + direction), delayMs);\n };\n\n options.onStart?.();\n timeoutId = setTimeout(() => step(startCount), options.delay ?? 0);\n return controller;\n }\n\n animateWordMotion(el, sourceTree, options, extra = {}) {\n this.clearCursorInterval(el);\n this.active.get(el)?.stop();\n if (options.ariaLive) el.setAttribute('aria-live', options.ariaLive);\n\n const prefix = extra.prefix ?? [];\n const isErasing = extra.isErasing === true;\n const motionKind = extra.motionKind ?? 'word-fade';\n const layout = options.wordLayout === 'placeholder' ? 'placeholder' : 'opacity';\n const duration = Math.max(\n 0,\n Number(options.wordFadeDuration ?? DEFAULT_WORD_FADE_DURATION) || 0\n );\n const stagger = Math.max(\n 0,\n Number(options.wordStagger ?? options.speed ?? DEFAULT_WORD_STAGGER) || 0\n );\n const transforms = getWordMotionTransforms(motionKind, options);\n const needsPerspective = motionKind === 'zoom-in-space';\n const { fragment, words } = buildWordMotionTree(sourceTree, layout, motionKind);\n const order = orderWordIndexes(words.length, options.wordOrder, options.wordSeed);\n order.forEach((wordIndex, sequenceIndex) => {\n words[wordIndex].dataset.tfWordOrder = String(sequenceIndex);\n });\n const timers = new Set();\n let frameId = null;\n let settled = false;\n let resolveFn = null;\n\n const easing =\n typeof options.wordMotionEasing === 'string' && options.wordMotionEasing.trim()\n ? options.wordMotionEasing.trim()\n : DEFAULT_MOTION_EASING;\n\n words.forEach((word) => {\n word.style.transition = transforms\n ? `opacity ${duration}ms ${easing}, transform ${duration}ms ${easing}`\n : `opacity ${duration}ms ${easing}`;\n if (transforms) word.style.transform = transforms.hidden;\n if (isErasing) {\n word.style.opacity = '1';\n word.style.visibility = 'visible';\n word.removeAttribute('aria-hidden');\n if (transforms) word.style.transform = transforms.visible;\n }\n });\n if (needsPerspective) {\n el.style.perspective = `${Math.max(0, Number(options.wordMotionPerspective ?? DEFAULT_MOTION_PERSPECTIVE) || 0)}px`;\n el.style.transformStyle = 'preserve-3d';\n }\n el.replaceChildren(...prefix, fragment);\n el.setAttribute('aria-busy', 'true');\n\n const schedule = (callback, delay) => {\n const id = setTimeout(() => {\n timers.delete(id);\n callback();\n }, delay);\n timers.add(id);\n };\n const clearScheduledWork = () => {\n timers.forEach((id) => clearTimeout(id));\n timers.clear();\n if (frameId !== null && typeof cancelAnimationFrame === 'function')\n cancelAnimationFrame(frameId);\n frameId = null;\n };\n const appendCursor = () => {\n if (!options.cursor) return;\n const cursor = createCursorSpan(options.cursor);\n el.appendChild(cursor);\n if (options.cursorBlink) {\n let visible = true;\n const intervalId = setInterval(() => {\n visible = !visible;\n cursor.style.visibility = visible ? 'visible' : 'hidden';\n }, CURSOR_BLINK_INTERVAL);\n intervalId.unref?.();\n this.cursorIntervals.set(el, intervalId);\n }\n };\n const settle = (completed) => {\n if (settled) return;\n settled = true;\n clearScheduledWork();\n this.active.delete(el);\n el.removeAttribute('aria-busy');\n if (needsPerspective) {\n el.style.removeProperty('perspective');\n el.style.removeProperty('transform-style');\n }\n\n if (completed) {\n if (isErasing) {\n el.replaceChildren(...prefix);\n options.onComplete?.('');\n } else {\n el.replaceChildren(...prefix, sourceTree.cloneNode(true));\n appendCursor();\n options.onComplete?.(extra.resultText ?? '');\n }\n } else {\n // Word-motion lays out the complete source before animating it, so an\n // interrupted operation can restore semantic source nodes without\n // losing partially constructed text or retaining presentation spans.\n el.replaceChildren(...prefix, sourceTree.cloneNode(true));\n stopKeystrokeSound(options.audio);\n options.onInterrupt?.();\n }\n resolveFn?.({ completed, text: isErasing ? '' : (extra.resultText ?? '') });\n };\n const controller = {\n stop: () => settle(false),\n promise: new Promise((resolve) => {\n resolveFn = resolve;\n }),\n };\n this.active.set(el, controller);\n\n if (options.respectReducedMotion === true && prefersReducedMotion()) {\n settle(true);\n return controller;\n }\n\n options.onStart?.();\n const begin = () => {\n frameId = requestAnimationFrame(() => {\n frameId = null;\n if (words.length === 0) {\n settle(true);\n return;\n }\n let sequenceIndex = 0;\n const revealNextWord = () => {\n const word = words[order[sequenceIndex]];\n if (options.audio) playKeystrokeSound(options.audio);\n if (isErasing) {\n word.style.opacity = '0';\n if (transforms) word.style.transform = transforms.hidden;\n word.setAttribute('aria-hidden', 'true');\n } else {\n word.style.visibility = 'visible';\n word.removeAttribute('aria-hidden');\n word.style.opacity = '1';\n if (transforms) word.style.transform = transforms.visible;\n }\n\n sequenceIndex += 1;\n if (sequenceIndex < words.length) schedule(revealNextWord, stagger);\n else schedule(() => settle(true), duration);\n };\n revealNextWord();\n });\n };\n\n schedule(begin, Math.max(0, Number(options.delay) || 0));\n return controller;\n }\n\n eraseFade(el, erasableLive, baseline, options) {\n this.clearCursorInterval(el);\n this.active.get(el)?.stop();\n\n const wrapper = document.createElement('span');\n erasableLive.forEach((n) => wrapper.appendChild(n));\n el.replaceChildren(...baseline, wrapper);\n\n const duration = options.duration ?? DEFAULT_FADE_DURATION;\n let settled = false;\n let timeoutId = null;\n let resolveFn = null;\n\n const settle = (completed) => {\n if (settled) return;\n settled = true;\n if (timeoutId !== null) clearTimeout(timeoutId);\n this.clearCursorInterval(el);\n this.active.delete(el);\n if (completed) {\n el.replaceChildren(...baseline);\n options.onComplete?.('');\n } else {\n stopKeystrokeSound(options.audio);\n options.onInterrupt?.();\n }\n resolveFn?.({ completed, text: '' });\n };\n\n const controller = {\n stop: () => settle(false),\n promise: new Promise((resolve) => {\n resolveFn = resolve;\n }),\n };\n this.active.set(el, controller);\n\n if (options.respectReducedMotion && prefersReducedMotion()) {\n settle(true);\n return controller;\n }\n\n requestAnimationFrame(() => {\n wrapper.style.transition = `opacity ${duration}ms ease`;\n wrapper.style.opacity = '0';\n });\n timeoutId = setTimeout(() => settle(true), duration);\n return controller;\n }\n\n instantClear(el, baseline, options) {\n this.clearCursorInterval(el);\n this.active.get(el)?.stop();\n el.replaceChildren(...baseline);\n options.onComplete?.('');\n return { stop: () => {}, promise: Promise.resolve({ completed: true, text: '' }) };\n }\n\n /**\n * Types text or sanitized HTML into the target element character by character\n * (or word by word when `typeStyle: 'word'`).\n *\n * Any animation currently running on `target` is stopped before the new one\n * starts. If `prefers-reduced-motion: reduce` is active and\n * `respectReducedMotion` is `true` (the default), the full text is rendered\n * immediately without animation.\n *\n * @param {Element | string} target\n * A DOM element or a CSS selector string resolved via `document.querySelector`.\n * @param {string} text\n * The text or HTML string to type. When `config.html` is `false` (default)\n * the string is treated as plain text and no parsing is performed.\n * @param {Partial<TypeFlowConfig>} [config={}]\n * Optional configuration overrides. See {@link TypeFlowConfig} for the full\n * option set. Merged with {@link TYPE_DEFAULTS}.\n * @returns {TypeFlowController}\n * A controller object with a `stop()` method and a `promise` that resolves\n * to `{ completed: boolean, text: string }`.\n *\n * @example\n * const controller = TypeFlow.type('#headline', 'Hello <strong>World</strong>', {\n * html: true,\n * speed: 45,\n * cursor: '|',\n * cursorBlink: true,\n * onComplete: (text) => console.log('Done:', text),\n * });\n *\n * // Abort mid-animation\n * button.addEventListener('click', () => controller.stop());\n */\n type(target, text, config = {}) {\n const el = resolveTarget(target);\n const options = { ...TYPE_DEFAULTS, ...config };\n if (Object.prototype.hasOwnProperty.call(config, 'scrambleGlyphs')) {\n options.scrambleCharset = undefined;\n }\n options.direction = normalizeDirection(options.direction);\n options.typeStyle = normalizeTypeStyle(options.typeStyle);\n if (options.typeStyle === 'word') options.granularity = 'word';\n\n const allowedTags = new Set([...DEFAULT_ALLOWED_TAGS, ...(options.allowedTags ?? [])]);\n const allowedAttrs = { ...DEFAULT_ALLOWED_ATTRS };\n if (options.allowedAttributes) {\n for (const [tag, attrs] of Object.entries(options.allowedAttributes)) {\n allowedAttrs[tag] = new Set([...(allowedAttrs[tag] ?? []), ...attrs]);\n }\n }\n\n let sourceText = text === null ? '' : text === undefined ? '' : String(text);\n if (options.html && options.sanitizer) sourceText = options.sanitizer(sourceText);\n const sourceTree = buildSourceTree(sourceText, !options.html, allowedTags, allowedAttrs);\n const totalUnits = countTextUnits(sourceTree, options.granularity);\n\n const prefix = options.mode === 'append' ? Array.from(el.childNodes) : [];\n if (options.mode === 'append') this.baselines.set(el, prefix);\n else this.baselines.delete(el);\n\n if (WORD_MOTION_STYLES.has(options.typeStyle)) {\n return this.animateWordMotion(el, sourceTree, options, {\n prefix,\n resultText: sourceText,\n isErasing: false,\n motionKind: options.typeStyle,\n });\n }\n\n return this.animate(el, sourceTree, totalUnits, options, 0, totalUnits, sourceText, {\n prefix,\n blinkOnFinish: true,\n isErasing: false,\n plainText: !options.html,\n });\n }\n\n erase(target, config = {}) {\n const el = resolveTarget(target);\n const options = { ...ERASE_DEFAULTS, ...config };\n if (Object.prototype.hasOwnProperty.call(config, 'scrambleGlyphs')) {\n options.scrambleCharset = undefined;\n }\n options.eraseStyle = normalizeEraseStyle(options.eraseStyle);\n\n const baseline = options.preserveBaseline ? (this.baselines.get(el) ?? []) : [];\n const allChildren = Array.from(el.childNodes);\n const erasableLive = baseline.length\n ? allChildren.filter((n) => !baseline.includes(n))\n : allChildren;\n\n if (options.eraseStyle === 'instant') return this.instantClear(el, baseline, options);\n if (options.eraseStyle === 'fade') return this.eraseFade(el, erasableLive, baseline, options);\n\n const sourceTree = document.createDocumentFragment();\n erasableLive.forEach((n) => sourceTree.appendChild(n.cloneNode(true)));\n const totalUnits = countTextUnits(sourceTree, options.granularity);\n\n if (WORD_MOTION_STYLES.has(options.eraseStyle)) {\n return this.animateWordMotion(el, sourceTree, options, {\n prefix: baseline,\n isErasing: true,\n motionKind: options.eraseStyle,\n });\n }\n\n return this.animate(el, sourceTree, totalUnits, options, totalUnits, 0, '', {\n prefix: baseline,\n isErasing: true,\n });\n }\n\n /**\n * Smart Diff Morphing: compares the existing text content of `target` with `nextText`,\n * erases only the mismatched trailing characters, and types the replacement text.\n *\n * @param {Element | string} target - Target element or CSS selector string.\n * @param {string} nextText - Destination text.\n * @param {Partial<TypeFlowConfig>} [options={}] - Animation options.\n * @returns {Promise<{ completed: boolean, text: string }>}\n */\n morph(target, nextText, options = {}) {\n const el = resolveTarget(target);\n const currentText = el.textContent ?? '';\n const targetText = nextText === null ? '' : nextText === undefined ? '' : String(nextText);\n\n let prefixLen = 0;\n const max = Math.min(currentText.length, targetText.length);\n while (prefixLen < max && currentText[prefixLen] === targetText[prefixLen]) {\n prefixLen++;\n }\n\n const eraseCount = currentText.length - prefixLen;\n const appendText = targetText.slice(prefixLen);\n\n const steps = [];\n if (eraseCount > 0) {\n steps.push(\n seq.call(() => {\n const sourceTree = document.createDocumentFragment();\n sourceTree.appendChild(document.createTextNode(currentText));\n const totalUnits = currentText.length;\n return this.animate(\n el,\n sourceTree,\n totalUnits,\n {\n ...ERASE_DEFAULTS,\n ...options,\n speed: options.eraseSpeed ?? options.speed ?? ERASE_DEFAULTS.speed,\n },\n totalUnits,\n prefixLen,\n currentText.slice(0, prefixLen),\n { prefix: [], isErasing: true }\n ).promise;\n })\n );\n }\n if (appendText.length > 0) {\n steps.push(\n seq.type(el, appendText, {\n ...options,\n mode: 'append',\n })\n );\n }\n\n return this.sequence(steps);\n }\n\n /**\n * Creates a streaming chunk consumer for real-time LLM token ingestion.\n *\n * @param {Element | string} target - Target element or CSS selector.\n * @param {Partial<TypeFlowConfig> & { onChunk?: (chunk: string, fullText: string) => void }} [options={}]\n * @returns {{ push: (chunk: string) => void, stop: () => void, clear: () => void }}\n */\n stream(target, options = {}) {\n const el = resolveTarget(target);\n let queue = [];\n let isProcessing = false;\n\n const processNext = () => {\n if (queue.length === 0) {\n isProcessing = false;\n return;\n }\n isProcessing = true;\n const chunk = queue.shift();\n this.type(el, chunk, {\n ...options,\n mode: 'append',\n onComplete: (text) => {\n options.onChunk?.(chunk, text);\n processNext();\n },\n });\n };\n\n return {\n push: (chunk) => {\n if (chunk !== null && chunk !== undefined && String(chunk).length > 0) {\n queue.push(String(chunk));\n if (!isProcessing) processNext();\n }\n },\n stop: () => {\n queue = [];\n this.stop(el);\n isProcessing = false;\n },\n clear: () => {\n queue = [];\n this.stop(el);\n isProcessing = false;\n el.replaceChildren();\n },\n };\n }\n\n /**\n * Returns a complete pre-configured options object for common typewriter profiles.\n *\n * @param {'cyberpunk' | 'terminal' | 'writer' | 'matrix' | 'blocks' | 'subtle'} name\n * @param {Partial<TypeFlowConfig>} [overrides={}]\n * @returns {TypeFlowConfig}\n */\n preset(name, overrides = {}) {\n const base = PRESETS[name] ?? PRESETS.writer;\n return { ...base, ...overrides };\n }\n\n /**\n * Executes an ordered list of animation steps sequentially, waiting for each\n * step to complete before advancing to the next one.\n *\n * Supported step kinds (created via the {@link seq} helper):\n * - `seq.type(target, text, config)` — Types text into a target element.\n * - `seq.erase(target, config)` — Erases content from a target element.\n * - `seq.pause(duration)` — Waits `duration` milliseconds.\n * - `seq.call(fn)` — Invokes an async or sync function.\n * - `seq.visible(target, threshold)` — Waits until the target is visible.\n *\n * If any step's animation is interrupted (via `controller.stop()`), the\n * entire sequence halts immediately.\n *\n * @param {Array<SequenceStep>} steps\n * An ordered array of step descriptors. Use the {@link seq} helper to\n * construct them.\n * @param {{ repeat?: number, target?: Element | string }} [seqConfig={}]\n * Optional sequence-level configuration.\n * - `repeat` — Number of times to repeat the full sequence. Use `Infinity`\n * for indefinite repetition. Defaults to `1`.\n * - `target` — A default target element applied to steps that do not\n * specify one individually.\n * @returns {TypeFlowController}\n * A controller with `stop()` and a `promise` resolving to\n * `{ completed: boolean, text: '' }`.\n *\n * @example\n * import { TypeFlow, seq } from '@staticcanvas/typeflow';\n *\n * TypeFlow.sequence([\n * seq.type('#output', 'Step 1 complete.'),\n * seq.pause(600),\n * seq.call(() => triggerSoundEffect()),\n * seq.erase('#output'),\n * seq.type('#output', 'Step 2 starting...'),\n * ], { repeat: 1 });\n */\n sequence(steps, seqConfig = {}) {\n if (!Array.isArray(steps) || steps.length === 0) {\n return { stop: () => {}, promise: Promise.resolve({ completed: true, text: '' }) };\n }\n\n let isInterrupted = false;\n let currentSub = null;\n let cancelPause = null;\n let cancelObserver = null;\n\n const resolveStepTarget = (step) => {\n const target = step.target ?? seqConfig.target;\n if (!target) {\n throw new Error(\n 'TypeFlow: a sequence step is missing a target, and no default `target` was set on the sequence config.'\n );\n }\n return target;\n };\n\n const controller = {\n stop: () => {\n if (isInterrupted) return;\n isInterrupted = true;\n currentSub?.stop();\n cancelPause?.();\n cancelObserver?.();\n },\n promise: null,\n };\n\n const runOnce = async () => {\n for (const step of steps) {\n if (isInterrupted) return false;\n\n if (step.kind === 'type') {\n currentSub = this.type(resolveStepTarget(step), step.text, step.config);\n if (!(await currentSub.promise).completed) return false;\n } else if (step.kind === 'erase') {\n currentSub = this.erase(resolveStepTarget(step), step.config);\n if (!(await currentSub.promise).completed) return false;\n } else if (step.kind === 'pause') {\n const finishedNaturally = await new Promise((resolve) => {\n const id = setTimeout(() => resolve(true), step.duration);\n cancelPause = () => {\n clearTimeout(id);\n resolve(false);\n };\n });\n cancelPause = null;\n if (!finishedNaturally) return false;\n } else if (step.kind === 'visible') {\n const targetEl = resolveTarget(resolveStepTarget(step));\n const isVisible = await new Promise((resolve) => {\n if (typeof IntersectionObserver === 'undefined') {\n resolve(true);\n return;\n }\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries.some((e) => e.isIntersecting)) {\n observer.disconnect();\n resolve(true);\n }\n },\n { threshold: step.threshold ?? 0.1 }\n );\n cancelObserver = () => {\n observer.disconnect();\n resolve(false);\n };\n observer.observe(targetEl);\n });\n cancelObserver = null;\n if (!isVisible) return false;\n } else if (step.kind === 'call') {\n try {\n await step.fn();\n } catch (err) {\n console.error('TypeFlow: error in seq.call step:', err);\n }\n }\n\n if (isInterrupted) return false;\n }\n return true;\n };\n\n controller.promise = (async () => {\n const repeat = seqConfig.repeat ?? 1;\n for (let i = 0; repeat === Infinity || i < repeat; i++) {\n if (!(await runOnce())) return { completed: false, text: '' };\n }\n return { completed: true, text: '' };\n })();\n\n return controller;\n }\n\n /**\n * Cyclically types and erases an array of strings in sequence.\n *\n * Internally delegates to {@link TypeFlowEngine#sequence}, constructing a\n * step list of: `type → pause (holdDuration) → erase → pause (pauseBetween)`\n * for each word.\n *\n * @param {Element | string} target\n * A DOM element or a CSS selector string.\n * @param {string[]} words\n * An ordered array of strings to rotate through.\n * @param {RotateConfig} [config={}]\n * Optional rotation configuration.\n * @param {Partial<TypeFlowConfig>} [config.typeConfig={}]\n * Config options applied to every `type` step.\n * @param {Partial<TypeFlowConfig>} [config.eraseConfig={}]\n * Config options applied to every `erase` step.\n * @param {number} [config.holdDuration=1200]\n * Milliseconds to hold each fully-typed word before erasing.\n * @param {number} [config.pauseBetween=200]\n * Milliseconds to wait after erasing before typing the next word.\n * @param {number | typeof Infinity} [config.repeat=Infinity]\n * Number of full rotation cycles. Use `Infinity` for indefinite rotation.\n * @returns {TypeFlowController}\n * A controller with `stop()` and a resolving `promise`.\n *\n * @example\n * TypeFlow.rotate('#rotating', ['Fast', 'Lightweight', 'Reliable'], {\n * holdDuration: 1200,\n * pauseBetween: 200,\n * repeat: Infinity,\n * });\n */\n rotate(target, words, config = {}) {\n const {\n typeConfig = {},\n eraseConfig = {},\n holdDuration = 1200,\n pauseBetween = 200,\n repeat = Infinity,\n } = config;\n\n const steps = [];\n words.forEach((word) => {\n steps.push({ kind: 'type', target, text: word, config: typeConfig });\n steps.push({ kind: 'pause', duration: holdDuration });\n steps.push({ kind: 'erase', target, config: eraseConfig });\n steps.push({ kind: 'pause', duration: pauseBetween });\n });\n\n return this.sequence(steps, { repeat });\n }\n\n /**\n * Staggers typing across multiple DOM elements with an offset delay between each item.\n *\n * @param {Element[] | NodeList | string} targets\n * A CSS selector string matching multiple elements, or an array / NodeList of elements.\n * @param {string | string[] | ((el: Element, index: number) => string)} [textOrTexts]\n * A string, an array of strings (one per target), or a resolver callback.\n * If omitted, reads each element's existing textContent.\n * @param {Partial<TypeFlowConfig> & { stagger?: number }} [config={}]\n * TypeFlow options merged with `stagger` offset delay in ms (default: `150`).\n * @returns {TypeFlowController}\n *\n * @example\n * TypeFlow.stagger('.prompt-line', [\n * 'npm install @staticcanvas/typeflow',\n * 'npm run build',\n * 'typeflow start --port=3000',\n * 'Ready on http://localhost:3000'\n * ], {\n * speed: 30,\n * stagger: 250,\n * cursor: '|'\n * });\n */\n stagger(targets, textOrTexts, config = {}) {\n let elements = [];\n if (typeof targets === 'string') {\n elements =\n typeof document !== 'undefined' ? Array.from(document.querySelectorAll(targets)) : [];\n } else if (Array.isArray(targets)) {\n elements = targets\n .map((t) => {\n try {\n return resolveTarget(t);\n } catch {\n return null;\n }\n })\n .filter(Boolean);\n } else if (targets && typeof targets[Symbol.iterator] === 'function') {\n elements = Array.from(targets)\n .map((t) => {\n try {\n return resolveTarget(t);\n } catch {\n return null;\n }\n })\n .filter(Boolean);\n } else {\n try {\n const single = resolveTarget(targets);\n if (single) elements = [single];\n } catch {\n // Ignore invalid targets while resolving a stagger collection.\n }\n }\n\n if (elements.length === 0) {\n return { stop: () => {}, promise: Promise.resolve({ completed: true, text: '' }) };\n }\n\n const staggerDelay = config.stagger ?? 150;\n const controllers = [];\n let stopped = false;\n\n const promises = elements.map((el, index) => {\n let text = '';\n if (typeof textOrTexts === 'function') {\n text = textOrTexts(el, index);\n } else if (Array.isArray(textOrTexts)) {\n text = textOrTexts[index] !== undefined ? textOrTexts[index] : '';\n } else if (typeof textOrTexts === 'string') {\n text = textOrTexts;\n } else {\n text = el.textContent || '';\n }\n\n const itemDelay = (config.delay ?? 0) + index * staggerDelay;\n const itemConfig = { ...config, delay: itemDelay };\n const ctrl = this.type(el, text, itemConfig);\n controllers.push(ctrl);\n return ctrl.promise;\n });\n\n const combinedPromise = Promise.all(promises).then((results) => {\n const allCompleted = results.every((r) => r.completed);\n return {\n completed: !stopped && allCompleted,\n text: results.map((r) => r.text).join('\\n'),\n };\n });\n\n return {\n stop: () => {\n stopped = true;\n controllers.forEach((c) => c.stop());\n },\n promise: combinedPromise,\n };\n }\n\n /**\n * Observes a DOM subtree for mutations and invokes `callback` whenever\n * elements matching `childSelector` are added to the tree. Also invokes the\n * callback immediately for any pre-existing matching elements inside\n * `container`.\n *\n * Useful for animating dynamically injected content (e.g. chat messages,\n * feed items, server-streamed responses) without polling.\n *\n * @param {Element | string} container\n * The root element whose subtree is observed.\n * @param {string} childSelector\n * A CSS selector string. Newly added elements matching this selector\n * will trigger `callback`.\n * @param {(el: Element) => void} callback\n * Function invoked with each matching element. Runs synchronously for\n * pre-existing matches and on the microtask after each mutation.\n * @returns {{ disconnect: () => void }}\n * An object with a `disconnect()` method that stops observation.\n *\n * @example\n * const watcher = TypeFlow.watch('#feed', '.item-title', (el) => {\n * const text = el.textContent;\n * el.textContent = '';\n * TypeFlow.type(el, text, { speed: 20 });\n * });\n *\n * // Stop observing when the container is destroyed\n * watcher.disconnect();\n */\n watch(container, childSelector, callback) {\n const root = resolveTarget(container);\n root.querySelectorAll(childSelector).forEach(callback);\n\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n mutation.addedNodes.forEach((node) => {\n if (node.nodeType !== Node.ELEMENT_NODE) return;\n const el = node;\n if (el.matches(childSelector)) callback(el);\n el.querySelectorAll(childSelector).forEach(callback);\n });\n }\n });\n\n observer.observe(root, { childList: true, subtree: true });\n return { disconnect: () => observer.disconnect() };\n }\n\n /**\n * Layout stabilization helper that measures a list of rotating candidate\n * phrases and locks the target container's inline dimensions to prevent\n * Cumulative Layout Shift (CLS).\n *\n * @param {Element | string} target\n * A DOM element or a CSS selector string.\n * @param {string[]} candidates\n * An array of strings/phrases that will rotate inside this container.\n * @returns {void}\n *\n * @example\n * TypeFlow.fit('#slogan', ['short', 'very long phrase that wraps']);\n */\n fit(target, candidates = []) {\n const el = resolveTarget(target);\n if (!Array.isArray(candidates) || !candidates.length || typeof document === 'undefined') return;\n\n const probe = document.createElement('span');\n probe.style.cssText =\n 'position:absolute;visibility:hidden;opacity:0;pointer-events:none;white-space:nowrap;';\n const cs =\n typeof window !== 'undefined' && window.getComputedStyle ? window.getComputedStyle(el) : null;\n if (cs) {\n probe.style.font = cs.font;\n probe.style.fontSize = cs.fontSize;\n probe.style.fontWeight = cs.fontWeight;\n probe.style.letterSpacing = cs.letterSpacing;\n probe.style.textTransform = cs.textTransform;\n }\n document.body.appendChild(probe);\n\n let maxW = 0;\n candidates.forEach((phrase) => {\n probe.textContent = String(phrase).replace(/<[^>]*>/g, '');\n maxW = Math.max(maxW, probe.getBoundingClientRect().width);\n });\n probe.remove();\n\n if (maxW > 0) {\n el.style.display = 'inline-block';\n el.style.minWidth = `${Math.ceil(maxW)}px`;\n }\n }\n\n /**\n * Stops any animation currently running on `target`. If no animation is\n * active on the element this method is a no-op.\n *\n * Equivalent to calling `controller.stop()` on the controller returned by\n * the originating `type()`, `erase()`, `sequence()`, or `rotate()` call.\n *\n * @param {Element | string} target - Target element or CSS selector string.\n * @returns {void}\n *\n * @example\n * TypeFlow.type('#el', 'Long text...');\n * // Stop from another handler without keeping a reference to the controller\n * TypeFlow.stop('#el');\n */\n stop(target) {\n const el = resolveTarget(target);\n if (!el) return;\n this.clearCursorInterval(el);\n this.active.get(el)?.stop();\n }\n\n /**\n * Stops all animations currently managed by this engine instance.\n *\n * @returns {void}\n *\n * @example\n * // Clean up all running animations on page unload\n * window.addEventListener('pagehide', () => TypeFlow.stopAll());\n */\n stopAll() {\n this.cursorIntervals.forEach((id) => clearInterval(id));\n this.cursorIntervals.clear();\n Array.from(this.active.values()).forEach((c) => c.stop());\n }\n\n /**\n * Returns `true` when `target` has an active animation managed by this\n * engine instance.\n *\n * @param {Element | string} target - Target element or CSS selector string.\n * @returns {boolean}\n *\n * @example\n * if (!TypeFlow.isTyping('#el')) {\n * TypeFlow.type('#el', 'Now available.');\n * }\n */\n isTyping(target) {\n const el = resolveMaybeTarget(target);\n return !!el && this.active.has(el);\n }\n}\n\n// ============================================================\n// Vanilla Public API (Singleton)\n// ============================================================\n\n/**\n * The global singleton instance of {@link TypeFlowEngine}.\n *\n * Import this in ESM environments:\n * ```javascript\n * import { TypeFlow } from '@staticcanvas/typeflow';\n * ```\n *\n * In UMD/script-tag environments the singleton is available as `window.TypeFlow`.\n *\n * @type {TypeFlowEngine}\n */\nexport const TypeFlow = new TypeFlowEngine();\nexport default TypeFlow;\n\n/**\n * Factory helpers for constructing {@link TypeFlowEngine#sequence} step\n * descriptors. Use these instead of building plain objects manually to ensure\n * correct `kind` values and type safety.\n *\n * @namespace seq\n *\n * @example\n * import { TypeFlow, seq } from '@staticcanvas/typeflow';\n *\n * TypeFlow.sequence([\n * seq.type('#out', 'Hello.'),\n * seq.pause(500),\n * seq.erase('#out'),\n * ]);\n */\nexport const seq = {\n /**\n * Creates a `type` step that types `text` into `target`.\n * @param {Element | string} target\n * @param {string} [text='']\n * @param {Partial<TypeFlowConfig>} [config]\n * @returns {SequenceStep}\n */\n type: (target, text = '', config) => ({ kind: 'type', target, text, config }),\n\n /**\n * Creates an `erase` step that erases content from `target`.\n * @param {Element | string} target\n * @param {Partial<TypeFlowConfig>} [config]\n * @returns {SequenceStep}\n */\n erase: (target, config) => ({ kind: 'erase', target, config }),\n\n /**\n * Creates a `pause` step that waits `duration` milliseconds.\n * @param {number} duration - Wait time in milliseconds.\n * @returns {SequenceStep}\n */\n pause: (duration) => ({ kind: 'pause', duration }),\n\n /**\n * Creates a `visible` step that waits until `target` enters the viewport.\n * @param {Element | string} target\n * @param {number} [threshold=0.1] - Intersection threshold (0–1).\n * @returns {SequenceStep}\n */\n visible: (target, threshold) => ({ kind: 'visible', target, threshold }),\n\n /**\n * Creates a `call` step that invokes `fn`. May be async.\n * @param {() => void | Promise<void>} fn\n * @returns {SequenceStep}\n */\n call: (fn) => ({ kind: 'call', fn }),\n};\n\nif (typeof window !== 'undefined') {\n window.TypeFlow = TypeFlow;\n window.TypeFlowSeq = seq;\n}\n\n// ============================================================\n// React Adapter\n// ============================================================\n\nexport function createTypeFlowReact(React) {\n return function useTypeFlow(text, config = {}) {\n const ref = React.useRef(null);\n React.useEffect(() => {\n if (!ref.current) return;\n const controller = TypeFlow.type(ref.current, text, config);\n return () => controller.stop();\n }, [text]);\n return ref;\n };\n}\n\nexport function createTypeFlowSequenceReact(React) {\n return function useTypeFlowSequence(buildSteps, deps) {\n React.useEffect(() => {\n const controller = TypeFlow.sequence(buildSteps());\n return () => controller.stop();\n }, deps);\n };\n}\n\n// ============================================================\n// Vue Adapter\n// ============================================================\n\nexport function createTypeFlowVue(Vue) {\n return function useTypeFlow(getText, config = {}) {\n const el = Vue.ref(null);\n let controller = null;\n Vue.watch(\n getText,\n () => {\n if (!el.value) return;\n controller = TypeFlow.type(el.value, getText(), config);\n },\n { immediate: true }\n );\n Vue.onBeforeUnmount(() => controller?.stop());\n return el;\n };\n}\n\nexport function createTypeFlowSequenceVue(Vue) {\n return function useTypeFlowSequence(buildSteps) {\n let controller = null;\n const run = () => {\n controller?.stop();\n controller = TypeFlow.sequence(buildSteps());\n };\n Vue.onBeforeUnmount(() => controller?.stop());\n return run;\n };\n}\n\n// ============================================================\n// Svelte Adapter (Action)\n// ============================================================\n\nexport function createTypeFlowSvelte() {\n return function typeflowAction(node, params) {\n let controller = null;\n\n const start = (currentParams) => {\n controller?.stop();\n const text = typeof currentParams === 'string' ? currentParams : currentParams.text;\n const config = typeof currentParams === 'object' ? currentParams.config : {};\n controller = TypeFlow.type(node, text, config);\n };\n\n start(params);\n\n return {\n update(newParams) {\n start(newParams);\n },\n destroy() {\n controller?.stop();\n },\n };\n };\n}\n\n// ============================================================\n// Solid.js Adapter\n// ============================================================\n\nexport function createTypeFlowSolid(Solid) {\n return function useTypeFlow(getText, config = {}) {\n let el;\n let controller = null;\n\n Solid.createEffect(() => {\n const text = typeof getText === 'function' ? getText() : getText;\n if (!el) return;\n controller?.stop();\n controller = TypeFlow.type(el, text, config);\n });\n\n Solid.onCleanup(() => {\n controller?.stop();\n });\n\n return (element) => {\n el = element;\n };\n };\n}\n\n// ============================================================\n// Alpine.js Adapter\n// ============================================================\n\nexport function createTypeFlowAlpine(Alpine) {\n if (!Alpine || typeof Alpine.directive !== 'function') {\n throw new Error(\n '[TypeFlow] createTypeFlowAlpine requires an Alpine instance with directive() support.'\n );\n }\n\n Alpine.directive('typeflow', (el, { expression }, { evaluateLater, effect, cleanup }) => {\n const evaluate = evaluateLater(expression);\n let controller = null;\n\n effect(() => {\n evaluate((value) => {\n controller?.stop();\n if (value === null || value === undefined) return;\n const text =\n typeof value === 'object' && value !== null ? (value.text ?? '') : String(value);\n const config = typeof value === 'object' && value !== null ? (value.config ?? {}) : {};\n controller = TypeFlow.type(el, text, config);\n });\n });\n\n if (typeof cleanup === 'function') {\n cleanup(() => controller?.stop());\n }\n });\n}\n\n// ============================================================\n// Web Components / Custom Element Adapter\n// ============================================================\n\nexport function defineTypeFlowElement(\n customElementsRegistry = typeof customElements !== 'undefined' ? customElements : null\n) {\n if (!customElementsRegistry || customElementsRegistry.get('type-flow')) return;\n\n class TypeFlowCustomElement extends HTMLElement {\n #controller = null;\n\n static get observedAttributes() {\n return [\n 'text',\n 'speed',\n 'direction',\n 'cursor',\n 'type-style',\n 'erase-style',\n 'scramble-charset',\n 'audio',\n ];\n }\n\n connectedCallback() {\n this.#render();\n }\n\n disconnectedCallback() {\n this.#controller?.stop();\n }\n\n attributeChangedCallback(_name, oldValue, newValue) {\n if (this.isConnected && oldValue !== newValue) {\n this.#render();\n }\n }\n\n #render() {\n this.#controller?.stop();\n const text = this.getAttribute('text') ?? this.textContent ?? '';\n const speed = this.hasAttribute('speed') ? Number(this.getAttribute('speed')) : 40;\n const direction = this.getAttribute('direction') || 'left';\n const cursor = this.getAttribute('cursor') ?? '|';\n const typeStyle = this.getAttribute('type-style') || 'char';\n const eraseStyle = this.getAttribute('erase-style') || 'end';\n const scrambleCharset = this.getAttribute('scramble-charset') || 'matrix';\n const audio = this.getAttribute('audio') || undefined;\n\n this.#controller = TypeFlow.type(this, text, {\n speed,\n direction,\n cursor,\n typeStyle,\n eraseStyle,\n scrambleCharset,\n audio,\n });\n }\n\n stop() {\n this.#controller?.stop();\n }\n }\n\n customElementsRegistry.define('type-flow', TypeFlowCustomElement);\n}\n"],"names":["SCRAMBLE_CHARSETS","matrix","ascii","blocks","binary","hex","braille","runic","cyber","PRESETS","cyberpunk","typeStyle","scrambleCharset","scrambleRounds","speed","cursor","cursorBlink","audio","terminal","writer","naturalCadence","speedVariance","subtle","eraseStyle","respectReducedMotion","TYPE_DEFAULTS","delay","granularity","html","mode","direction","scrambleGlyphs","ERASE_DEFAULTS","__spreadProps","preserveBaseline","VOID_ELEMENTS","Set","DEFAULT_ALLOWED_TAGS","DEFAULT_ALLOWED_ATTRS","a","span","mark","WORD_MOTION_STYLES","audioCtx","playKeystrokeSound","audioOption","e","type","ctx","window","AudioCtx","AudioContext","webkitAudioContext","state","resume","catch","getAudioContext","now","currentTime","osc","createOscillator","gain","createGain","frequency","setValueAtTime","exponentialRampToValueAtTime","connect","destination","start","stop","Math","random","stopKeystrokeSound","SEGMENTED_NODE_CACHE","WeakMap","segmentNodeText","node","text","_a","textContent","entry","get","values","Map","set","has","Intl","Segmenter","segmenter","Array","from","segment","s","match","segmentText","isSafeUrl","value","v","trim","toLowerCase","startsWith","buildSourceTree","input","plainText","allowedTags","allowedAttrs","fragment","document","createDocumentFragment","appendChild","createTextNode","template","createElement","innerHTML","walk","source","target","childNodes","forEach","child","nodeType","Node","TEXT_NODE","ELEMENT_NODE","clean","el","tag","tagName","allowedForTag","allowedGlobal","_b","attr","attributes","name","setAttribute","getAttribute","sanitizeElement","content","countTextUnits","length","total","cloneRevealWindow","end","revealOpts","glyphs","units","len","clone","max","min","doc","ownerDocument","scrambleActive","frag","slice","join","scrambleSpan","className","scrambleColor","style","color","scrambleGradient","backgroundImage","webkitBackgroundImage","webkitBackgroundClip","backgroundClip","webkitTextFillColor","display","floor","trailLen","trailFade","trailingFadeLength","isComplete","solidEnd","trailCount","minOp","trailingFadeMinOpacity","trailMinOpacity","i","charIdx","charSpan","opacity","toFixed","sliced","cloneNode","curStart","curEnd","appended","result","resolveTarget","resolveMaybeTarget","desc","String","Error","querySelector","normalizeWordOrder","order","orderWordIndexes","seed","indexes","_","index","reverse","charCodeAt","imul","createSeededRandom","swapIndex","buildWordMotionTree","layout","motionKind","words","needsTransform","sourceNode","targetNode","part","map","isWordLike","test","segmentWords","at","parentNode","wrapper","dataset","tfWordIndex","willChange","visibility","push","prefersReducedMotion","matchMedia","matches","createCursorSpan","cursorChar","isHidden","TypeFlow","constructor","__publicField","this","clearCursorInterval","interval","cursorIntervals","clearInterval","delete","animate","sourceTree","totalUnits","options","startCount","endCount","resultText","extra","active","ariaLive","prefix","blinkOnFinish","_c","Number","_d","_e","isScramble","charset","_f","scramblePreset","settled","timeoutId","resolveFn","plainUnits","firstChild","incrementalTextNode","incrementalCursor","lastIncrementalCount","clearTimers","clearTimeout","render","unitCount","cursorHidden","data","replaceChildren","remove","bounds","count","isErasing","calculateWindowBounds","isTrailFade","out","revealWindowFragment","settle","completed","visible","intervalId","setInterval","unref","call","onComplete","onInterrupt","controller","promise","Promise","resolve","scrambleStep","_g","step","setTimeout","jitter","cadencePause","char","calculateCadencePause","delayMs","_h","onStart","_i","animateWordMotion","wordLayout","duration","wordFadeDuration","stagger","wordStagger","transforms","distance","wordMotionDistance","depth","wordMotionDepth","scale","wordMotionScale","hidden","getWordMotionTransforms","needsPerspective","wordOrder","wordSeed","wordIndex","sequenceIndex","tfWordOrder","timers","frameId","easing","wordMotionEasing","word","transition","transform","removeAttribute","perspective","wordMotionPerspective","transformStyle","schedule","callback","id","add","appendCursor","clear","cancelAnimationFrame","removeProperty","requestAnimationFrame","revealNextWord","eraseFade","erasableLive","baseline","n","instantClear","config","__spreadValues","Object","prototype","hasOwnProperty","dir","normalizeDirection","normalizeTypeStyle","allowedAttributes","attrs","entries","sourceText","sanitizer","baselines","erase","normalizeEraseStyle","allChildren","filter","includes","morph","nextText","currentText","targetText","prefixLen","eraseCount","appendText","steps","seq","eraseSpeed","sequence","stream","queue","isProcessing","processNext","chunk","shift","onChunk","preset","overrides","base","seqConfig","isArray","isInterrupted","currentSub","cancelPause","cancelObserver","resolveStepTarget","runOnce","__async","kind","finishedNaturally","targetEl","isVisible","IntersectionObserver","observer","some","isIntersecting","disconnect","threshold","observe","fn","err","console","error","repeat","Infinity","rotate","typeConfig","eraseConfig","holdDuration","pauseBetween","targets","textOrTexts","elements","querySelectorAll","t","Boolean","Symbol","iterator","single","staggerDelay","controllers","stopped","promises","itemDelay","itemConfig","ctrl","c","all","then","results","allCompleted","every","r","watch","container","childSelector","root","MutationObserver","mutations","mutation","addedNodes","childList","subtree","fit","candidates","probe","cssText","cs","getComputedStyle","font","fontSize","fontWeight","letterSpacing","textTransform","body","maxW","phrase","replace","getBoundingClientRect","width","minWidth","ceil","stopAll","isTyping","pause","TypeFlowSeq","Alpine","directive","expression","evaluateLater","effect","cleanup","evaluate","React","ref","useRef","useEffect","current","buildSteps","deps","Vue","onBeforeUnmount","Solid","getText","createEffect","onCleanup","element","params","currentParams","update","newParams","destroy","immediate","customElementsRegistry","customElements","TypeFlowCustomElement","HTMLElement","super","arguments","__privateAdd","_TypeFlowCustomElement_instances","_controller","observedAttributes","connectedCallback","__privateMethod","render_fn","disconnectedCallback","__privateGet","attributeChangedCallback","_name","oldValue","newValue","isConnected","WeakSet","hasAttribute","define"],"mappings":"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"}