@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,34 @@
1
+ /**
2
+ * TypeFlow Debug - Diagnostic Tracing and LogCAD Integration.
3
+ */
4
+ export interface TypeFlowDebugOptions {
5
+ logcad?: boolean;
6
+ console?: boolean;
7
+ maxHistory?: number;
8
+ traceFrames?: boolean;
9
+ }
10
+
11
+ export interface TypeFlowDebugEntry {
12
+ timestamp: string;
13
+ level: 'info' | 'warn' | 'error' | 'debug' | 'trace';
14
+ message: string;
15
+ data: Record<string, any>;
16
+ }
17
+
18
+ export class TypeFlowDebug {
19
+ static enabled: boolean;
20
+ static options: TypeFlowDebugOptions;
21
+ static history: TypeFlowDebugEntry[];
22
+
23
+ static enable(options?: TypeFlowDebugOptions): void;
24
+ static disable(): void;
25
+ static log(
26
+ level: 'info' | 'warn' | 'error' | 'debug' | 'trace',
27
+ message: string,
28
+ data?: Record<string, any>
29
+ ): void;
30
+ static trace<T>(controller: T, label?: string): T;
31
+ static getHistory(): TypeFlowDebugEntry[];
32
+ static clearHistory(): void;
33
+ static exportLog(): string;
34
+ }
@@ -0,0 +1,223 @@
1
+ /** * * * * * * * * * * * * * * * * * * * * * * * * * * **
2
+ * @description TypeFlow Debug - Diagnostic Tracing and LogCAD Integration.
3
+ * Provides lifecycle telemetry, animation step timings, event hooks, and structured
4
+ * logger integration for TypeFlow applications.
5
+ *
6
+ * @module @staticcanvas/typeflow/debug
7
+ */
8
+
9
+ export class TypeFlowDebug {
10
+ static enabled = false;
11
+ static options = {
12
+ logcad: true,
13
+ console: true,
14
+ maxHistory: 200,
15
+ traceFrames: false,
16
+ };
17
+ static history = [];
18
+ static originalType = null;
19
+ static originalErase = null;
20
+
21
+ /** * * * * * * * * * * * * * * * * * * * * * * * * * * **
22
+ * @description Enables diagnostic telemetry tracing across TypeFlow animation lifecycles.
23
+ * @param {Object} [opts={}] - Configuration options for the debug session.
24
+ * @returns {void}
25
+ *
26
+ * -------------
27
+ *
28
+ * @Properties
29
+ * @param {boolean} [opts.logcad=true] - Whether to route logs through @staticcanvas/logcad if available.
30
+ * @param {boolean} [opts.console=true] - Whether to output styled colored logs to the browser console.
31
+ * @param {number} [opts.maxHistory=200] - Maximum number of recent log entries to retain in memory.
32
+ * @param {boolean} [opts.traceFrames=false] - Whether to log every individual frame render tick.
33
+ *
34
+ * -------------
35
+ *
36
+ * @example
37
+ *
38
+ * // Enable debugging with default settings
39
+ * TypeFlowDebug.enable();
40
+ *
41
+ * // Enable with custom history size and disabled console output
42
+ * TypeFlowDebug.enable({
43
+ * logcad: true,
44
+ * console: false,
45
+ * maxHistory: 500,
46
+ * });
47
+ */
48
+ static enable(opts = {}) {
49
+ TypeFlowDebug.options = { ...TypeFlowDebug.options, ...opts };
50
+ TypeFlowDebug.enabled = true;
51
+ TypeFlowDebug.log('info', 'TypeFlowDebug enabled', { options: TypeFlowDebug.options });
52
+ }
53
+
54
+ /** * * * * * * * * * * * * * * * * * * * * * * * * * * **
55
+ * @description Disables diagnostic tracing and halts active logging.
56
+ * @returns {void}
57
+ *
58
+ * -------------
59
+ *
60
+ * @example
61
+ * TypeFlowDebug.disable();
62
+ */
63
+ static disable() {
64
+ TypeFlowDebug.enabled = false;
65
+ TypeFlowDebug.log('info', 'TypeFlowDebug disabled');
66
+ }
67
+
68
+ /** * * * * * * * * * * * * * * * * * * * * * * * * * * **
69
+ * @description Internal logging bridge supporting @staticcanvas/logcad and styled console messages.
70
+ * @param {'info' | 'warn' | 'error' | 'debug' | 'trace'} level - Severity level of the log entry.
71
+ * @param {string} message - Human-readable summary of the event.
72
+ * @param {Object} [data={}] - Contextual payload data to associate with the event.
73
+ * @returns {void}
74
+ *
75
+ * -------------
76
+ *
77
+ * @Properties
78
+ * @param {string} level - Severity level ('info', 'warn', 'error', 'debug', 'trace').
79
+ * @param {string} message - The message text to record.
80
+ * @param {Object} [data={}] - Arbitrary metadata object (timings, diffs, controllers).
81
+ *
82
+ * -------------
83
+ *
84
+ * @example
85
+ * TypeFlowDebug.log('info', 'Sequence step completed', { step: 1, duration: 45 });
86
+ * TypeFlowDebug.log('warn', 'Frame drop detected', { expectedMs: 16, actualMs: 34 });
87
+ */
88
+ static log(level, message, data = {}) {
89
+ if (!TypeFlowDebug.enabled && level !== 'error') return;
90
+
91
+ const entry = {
92
+ timestamp: new Date().toISOString(),
93
+ level,
94
+ message,
95
+ data,
96
+ };
97
+
98
+ TypeFlowDebug.history.push(entry);
99
+ if (TypeFlowDebug.history.length > TypeFlowDebug.options.maxHistory) {
100
+ TypeFlowDebug.history.shift();
101
+ }
102
+
103
+ // 1. Integration with @staticcanvas/logcad if available globally or via module
104
+ if (TypeFlowDebug.options.logcad && typeof globalThis !== 'undefined' && globalThis.logcad) {
105
+ try {
106
+ const logger = globalThis.logcad.getLogger?.('TypeFlow') || globalThis.logcad;
107
+ if (typeof logger[level] === 'function') {
108
+ logger[level](message, data);
109
+ return;
110
+ }
111
+ } catch {
112
+ // Fallback to console
113
+ }
114
+ }
115
+
116
+ // 2. Structured fallback console output with CSS colors
117
+ if (TypeFlowDebug.options.console && typeof console !== 'undefined') {
118
+ const colors = {
119
+ info: 'color: #38bdf8; font-weight: bold;',
120
+ warn: 'color: #f59e0b; font-weight: bold;',
121
+ error: 'color: #ef4444; font-weight: bold;',
122
+ debug: 'color: #ff6b2b; font-weight: bold;',
123
+ trace: 'color: #94a3b8; font-weight: normal;',
124
+ };
125
+
126
+ const tag = `%c[TypeFlow:${level.toUpperCase()}]`;
127
+ const style = colors[level] || colors.info;
128
+
129
+ if (Object.keys(data).length > 0) {
130
+ console[level === 'trace' ? 'debug' : level] || console.log(tag, style, message, data);
131
+ } else {
132
+ console[level === 'trace' ? 'debug' : level] || console.log(tag, style, message);
133
+ }
134
+ }
135
+ }
136
+
137
+ /** * * * * * * * * * * * * * * * * * * * * * * * * * * **
138
+ * @description Tracks a specific TypeFlow animation controller and logs lifecycle events upon resolution or rejection.
139
+ * @param {Object} controller - Active TypeFlow controller instance.
140
+ * @param {string} [label='Animation'] - Descriptive name for the tracked target.
141
+ * @returns {Object} The passed-in controller for chaining.
142
+ *
143
+ * -------------
144
+ *
145
+ * @Properties
146
+ * @param {Object} controller - The TypeFlow controller returned by TypeFlow.type() / TypeFlow.erase().
147
+ * @param {Promise} controller.promise - The underlying completion promise.
148
+ * @param {Function} controller.stop - Method to abort the animation.
149
+ * @param {string} [label='Animation'] - Label displayed in log output.
150
+ *
151
+ * -------------
152
+ *
153
+ * @example
154
+ * const ctrl = TypeFlow.type('#headline', 'Hello World');
155
+ * TypeFlowDebug.trace(ctrl, 'Hero Headline');
156
+ */
157
+ static trace(controller, label = 'Animation') {
158
+ if (!TypeFlowDebug.enabled || !controller) return controller;
159
+
160
+ const start = performance.now();
161
+ TypeFlowDebug.log('debug', `[${label}] Started animation`, { controller });
162
+
163
+ if (controller.promise) {
164
+ controller.promise.then(
165
+ (res) => {
166
+ const duration = (performance.now() - start).toFixed(2);
167
+ TypeFlowDebug.log('info', `[${label}] Resolved (${duration}ms)`, res);
168
+ },
169
+ (err) => {
170
+ const duration = (performance.now() - start).toFixed(2);
171
+ TypeFlowDebug.log('error', `[${label}] Rejected (${duration}ms)`, err);
172
+ }
173
+ );
174
+ }
175
+
176
+ return controller;
177
+ }
178
+
179
+ /** * * * * * * * * * * * * * * * * * * * * * * * * * * **
180
+ * @description Returns a shallow copy of the recorded event history.
181
+ * @returns {Array<Object>} List of history entry objects.
182
+ *
183
+ * -------------
184
+ *
185
+ * @example
186
+ * const history = TypeFlowDebug.getHistory();
187
+ * console.log('Total recorded events:', history.length);
188
+ */
189
+ static getHistory() {
190
+ return [...TypeFlowDebug.history];
191
+ }
192
+
193
+ /** * * * * * * * * * * * * * * * * * * * * * * * * * * **
194
+ * @description Clears the current event history ring buffer.
195
+ * @returns {void}
196
+ *
197
+ * -------------
198
+ *
199
+ * @example
200
+ * TypeFlowDebug.clearHistory();
201
+ */
202
+ static clearHistory() {
203
+ TypeFlowDebug.history = [];
204
+ }
205
+
206
+ /** * * * * * * * * * * * * * * * * * * * * * * * * * * **
207
+ * @description Exports recorded telemetry event history as a formatted JSON string.
208
+ * @returns {string} Serialized JSON representation of debug history.
209
+ *
210
+ * -------------
211
+ *
212
+ * @example
213
+ * const jsonReport = TypeFlowDebug.exportLog();
214
+ * navigator.clipboard.writeText(jsonReport);
215
+ */
216
+ static exportLog() {
217
+ return JSON.stringify(TypeFlowDebug.history, null, 2);
218
+ }
219
+ }
220
+
221
+ if (typeof window !== 'undefined') {
222
+ window.TypeFlowDebug = TypeFlowDebug;
223
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * TypeFlow ExtChars - Extended Unicode Glyph Presets & Scramble Pools.
3
+ */
4
+ export const EXT_CHARSETS: {
5
+ hieroglyphs: string;
6
+ runic: string;
7
+ ogham: string;
8
+ coptic: string;
9
+ katakana: string;
10
+ cyberMatrix: string;
11
+ blocks: string;
12
+ boxDrawing: string;
13
+ mathSymbols: string;
14
+ braille: string;
15
+ astronomical: string;
16
+ geometric: string;
17
+ glitch: string;
18
+ };
19
+
20
+ export class TypeFlowExtChars {
21
+ static charsets: Record<string, string>;
22
+ static getCharset(name: string): string;
23
+ static registerCharset(name: string, glyphs: string): void;
24
+ static combineCharsets(...names: string[]): string;
25
+ static randomGlyph(charsetOrName: string): string;
26
+ }
27
+
28
+ export function getExtendedCharset(name: string): string;
@@ -0,0 +1,132 @@
1
+ /** * * * * * * * * * * * * * * * * * * * * * * * * * * **
2
+ * @description TypeFlow ExtChars - Extended Unicode Glyph Presets & Scramble Pools.
3
+ * Provides specialized ancient alphabets, mathematical operators, Katakana,
4
+ * box-drawing frames, astrological runes, and cyber glitch character sets.
5
+ *
6
+ * @module @staticcanvas/typeflow/extchars
7
+ */
8
+
9
+ export const EXT_CHARSETS = {
10
+ // Ancient & Sacred Scripts
11
+ hieroglyphs: '𓀀𓀁𓀂𓀃𓀄𓀅𓀆𓀇𓀈𓀉𓀊𓀋𓀌𓀍𓀎𓀏𓀐𓀑𓀒𓀓𓀔𓀕𓀖𓀗𓀘𓀙𓀚𓀛𓀜𓀝𓀞𓀟𓀠𓀡𓀢𓀣𓀤𓀥𓀦𓀧𓀨𓀩𓀪𓀫𓀬𓀭𓀮𓀯𓀰𓀱𓀲𓀳𓀴𓀵𓀶𓀷𓀸𓀹𓀺𓀻',
12
+ runic: 'ᚠᚡᚢᚣᚤᚥᚦᚧᚨᚩᚪᚫᚬᚭᚮᚯᚰᚱᚲᚳᚴᚵᚶᚷᚸᚹᚺᚻᚼᚽᚾᚿᛀᛁᛂᛃᛄᛅᛆᛇᛈᛉᛊᛋᛌᛍᛎᛏᛐᛑᛒᛓᛔᛕᛖᛗᛘᛙᛚᛛᛜᛝᛞᛟᛠᛡᛢᛣᛤᛥᛦᛧᛨᛩᛪ',
13
+ ogham: 'ᚁᚂᚃᚄᚅᚆᚇᚈᚉᚊᚋᚌᚍᚎᚏᚐᚑᚒᚓᚔᚕᚖᚗᚘᚙᚚ',
14
+ coptic: 'ⲀⲂⲄⲆⲈⲊⲌⲎⲐⲒⲔⲖⲘⲚⲜⲞⲠⲢⲤⲦⲨPhiⲬⲮⲰϢϤϦϨϪϬϮ',
15
+
16
+ // Cyber & Terminal
17
+ katakana: 'ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン',
18
+ cyberMatrix: '01010101_#@!<>[]{}/*+=~-アイウエオカキクケコサシスセソタチツテト01',
19
+ blocks: '█▓▒░▀▄▌▐■□▢▣▤▥▦▧▨▩',
20
+ boxDrawing:
21
+ '─━│┃┄┅┆┇┈┉┊┋┌┍┎┏┐┑┒┓└┕┖┗┘┙┚┛├┝┞┟┠┡┢┣┤┥┦┧┨┩┪┫┬┭┮┯┰┱┲┳┴┵┶┷┸┹┺┻┼┽┾┿╀╁╂╃╄╅╆╇╈╉╊╋═║╔╗╚╝╠╣╦╩╬',
22
+
23
+ // Mathematical & Technical
24
+ mathSymbols:
25
+ '∀∁∂∃∄∅∆∇∈∉∊∋∌∍∎∏∐∑−∓∔∕∖∗∘∙√∛∜∝∞∟∠∡∢∣∤∥∦∧∨∩∪∫∬∭∮∯∰∱∲∳∴∵∶∷∸∹∺∻∼∽∾∿≀≁≂≃≄≅≆≇≈≉≊≋≌≍≎≏≐≑≒≓≔≕≖≗≘≙≚≛≜≝≞≟≠≡≢≣≤≥≦≧≨≩≪≫≬≭≮≯',
26
+ braille: '⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏⠐⠑⠒⠓⠔⠕⠖⠗⠘⠙⠚⠛⠜⠝⠞⠟⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫⠬⠭⠮⠯⠰⠱⠲⠳⠴⠵⠶⠷⠸⠹⠺⠻⠼⠽⠾⠿',
27
+ astronomical: '☉☽☿♀♁♂♃♄♅♆♇♈♉♊♋♌♍♎♏♐♑♒♓☄★☆⚡',
28
+ geometric: '▲▼◀▶▲▼◀▶◆◇◈◉◊○●◎◐◑◒◓◔◕◖◗◘◙◜◝◞◟◠◡◢◣◤◥',
29
+
30
+ // Glitch
31
+ glitch: '!<>-_\\/[]{}—=+*^?#________̷̸̡̢̧̨̛̖̗̘̙̜̝̞̟̠',
32
+ };
33
+
34
+ export class TypeFlowExtChars {
35
+ static charsets = { ...EXT_CHARSETS };
36
+
37
+ /** * * * * * * * * * * * * * * * * * * * * * * * * * * **
38
+ * @description Retrieves a character set string by preset name.
39
+ * @param {string} name - The charset identifier ('hieroglyphs', 'runic', 'ogham', 'coptic', 'katakana', 'boxDrawing', 'mathSymbols', 'braille', 'astronomical', 'geometric', 'glitch').
40
+ * @returns {string} String of glyph characters.
41
+ *
42
+ * -------------
43
+ *
44
+ * @Properties
45
+ * @param {string} name - Name of the charset.
46
+ *
47
+ * -------------
48
+ *
49
+ * @example
50
+ * const runes = TypeFlowExtChars.getCharset('runic');
51
+ * console.log('Runic runes:', runes);
52
+ */
53
+ static getCharset(name) {
54
+ return TypeFlowExtChars.charsets[String(name).toLowerCase()] || EXT_CHARSETS.cyberMatrix;
55
+ }
56
+
57
+ /** * * * * * * * * * * * * * * * * * * * * * * * * * * **
58
+ * @description Registers a new custom charset preset globally.
59
+ * @param {string} name - Unique identifier for the custom charset.
60
+ * @param {string} glyphs - Pool of characters to associate with this preset.
61
+ * @returns {void}
62
+ *
63
+ * -------------
64
+ *
65
+ * @Properties
66
+ * @param {string} name - Identifier name.
67
+ * @param {string} glyphs - String of characters.
68
+ *
69
+ * -------------
70
+ *
71
+ * @example
72
+ * TypeFlowExtChars.registerCharset('alchemy', '🜁🜂🜃🜄🜅🜆🜇🜈🜉🜊');
73
+ * const alchemy = TypeFlowExtChars.getCharset('alchemy');
74
+ */
75
+ static registerCharset(name, glyphs) {
76
+ if (typeof name === 'string' && typeof glyphs === 'string') {
77
+ TypeFlowExtChars.charsets[name.toLowerCase()] = glyphs;
78
+ }
79
+ }
80
+
81
+ /** * * * * * * * * * * * * * * * * * * * * * * * * * * **
82
+ * @description Combines multiple charsets into a single merged pool.
83
+ * @param {...string} names - Charset names to concatenate.
84
+ * @returns {string} Merged character string.
85
+ *
86
+ * -------------
87
+ *
88
+ * @example
89
+ * const cyberRunes = TypeFlowExtChars.combineCharsets('cyberMatrix', 'runic', 'katakana');
90
+ */
91
+ static combineCharsets(...names) {
92
+ return names.map((n) => TypeFlowExtChars.getCharset(n)).join('');
93
+ }
94
+
95
+ /** * * * * * * * * * * * * * * * * * * * * * * * * * * **
96
+ * @description Selects a random single glyph from a charset string or preset name.
97
+ * @param {string} charsetOrName - Charset string or registered name.
98
+ * @returns {string} Random single character glyph.
99
+ *
100
+ * -------------
101
+ *
102
+ * @example
103
+ * const rune = TypeFlowExtChars.randomGlyph('runic');
104
+ */
105
+ static randomGlyph(charsetOrName) {
106
+ const pool =
107
+ TypeFlowExtChars.charsets[charsetOrName] || charsetOrName || EXT_CHARSETS.cyberMatrix;
108
+ const chars = Array.from(pool);
109
+ return chars[Math.floor(Math.random() * chars.length)] || '#';
110
+ }
111
+ }
112
+
113
+ /** * * * * * * * * * * * * * * * * * * * * * * * * * * **
114
+ * @description Helper function returning an extended charset string by name.
115
+ * @param {string} name - Charset identifier.
116
+ * @returns {string}
117
+ *
118
+ * -------------
119
+ *
120
+ * @example
121
+ * import { getExtendedCharset } from '@staticcanvas/typeflow/extchars';
122
+ * const hieroglyphs = getExtendedCharset('hieroglyphs');
123
+ */
124
+ export function getExtendedCharset(name) {
125
+ return TypeFlowExtChars.getCharset(name);
126
+ }
127
+
128
+ if (typeof window !== 'undefined') {
129
+ window.TypeFlowExtChars = TypeFlowExtChars;
130
+ window.EXT_CHARSETS = EXT_CHARSETS;
131
+ window.getExtendedCharset = getExtendedCharset;
132
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * TypeFlow Keystroke - Human Cadence, Finger Distance & Typo Simulation Engine.
3
+ */
4
+ export interface KeystrokeDelayOptions {
5
+ baseSpeed?: number;
6
+ fatigueIndex?: number;
7
+ fatigueRate?: number;
8
+ }
9
+
10
+ export interface HumanizeOptions {
11
+ errorRate?: number;
12
+ hesitationMs?: number;
13
+ }
14
+
15
+ export interface HumanizeAction {
16
+ type: 'type' | 'erase' | 'pause';
17
+ char?: string;
18
+ count?: number;
19
+ duration?: number;
20
+ isTypo?: boolean;
21
+ }
22
+
23
+ export function calculateKeyDistance(keyA: string, keyB: string): number;
24
+
25
+ export class TypeFlowKeystroke {
26
+ static getDelay(prevChar: string, nextChar: string, options?: KeystrokeDelayOptions): number;
27
+ static humanize(text: string, options?: HumanizeOptions): HumanizeAction[];
28
+ }
@@ -0,0 +1,220 @@
1
+ /** * * * * * * * * * * * * * * * * * * * * * * * * * * **
2
+ * @description TypeFlow Keystroke - Human Cadence, Finger Distance & Typo Simulation Engine.
3
+ * Models physical QWERTY coordinate finger travel, burstiness, thought pauses,
4
+ * fatigue deceleration, and realistic typo injection with backspace auto-correction.
5
+ *
6
+ * @module @staticcanvas/typeflow/keystroke
7
+ */
8
+
9
+ // QWERTY keyboard physical coordinates (row, col)
10
+ const QWERTY_COORDS = {
11
+ '`': [0, 0],
12
+ 1: [0, 1],
13
+ 2: [0, 2],
14
+ 3: [0, 3],
15
+ 4: [0, 4],
16
+ 5: [0, 5],
17
+ 6: [0, 6],
18
+ 7: [0, 7],
19
+ 8: [0, 8],
20
+ 9: [0, 9],
21
+ 0: [0, 10],
22
+ '-': [0, 11],
23
+ '=': [0, 12],
24
+ q: [1, 1.5],
25
+ w: [1, 2.5],
26
+ e: [1, 3.5],
27
+ r: [1, 4.5],
28
+ t: [1, 5.5],
29
+ y: [1, 6.5],
30
+ u: [1, 7.5],
31
+ i: [1, 8.5],
32
+ o: [1, 9.5],
33
+ p: [1, 10.5],
34
+ '[': [1, 11.5],
35
+ ']': [1, 12.5],
36
+ a: [2, 1.8],
37
+ s: [2, 2.8],
38
+ d: [2, 3.8],
39
+ f: [2, 4.8],
40
+ g: [2, 5.8],
41
+ h: [2, 6.8],
42
+ j: [2, 7.8],
43
+ k: [2, 8.8],
44
+ l: [2, 9.8],
45
+ ';': [2, 10.8],
46
+ "'": [2, 11.8],
47
+ z: [3, 2.2],
48
+ x: [3, 3.2],
49
+ c: [3, 4.2],
50
+ v: [3, 5.2],
51
+ b: [3, 6.2],
52
+ n: [3, 7.2],
53
+ m: [3, 8.2],
54
+ ',': [3, 9.2],
55
+ '.': [3, 10.2],
56
+ '/': [3, 11.2],
57
+ ' ': [4, 6.0],
58
+ };
59
+
60
+ // Adjacent key neighborhood for realistic typo generation
61
+ const QWERTY_NEIGHBORS = {
62
+ a: ['s', 'q', 'z', 'w'],
63
+ b: ['v', 'g', 'h', 'n'],
64
+ c: ['x', 'd', 'f', 'v'],
65
+ d: ['s', 'e', 'r', 'f', 'c', 'x'],
66
+ e: ['w', 's', 'd', 'r'],
67
+ f: ['d', 'r', 't', 'g', 'v', 'c'],
68
+ g: ['f', 't', 'y', 'h', 'b', 'v'],
69
+ h: ['g', 'y', 'u', 'j', 'n', 'b'],
70
+ i: ['u', 'j', 'k', 'o'],
71
+ j: ['h', 'u', 'i', 'k', 'm', 'n'],
72
+ k: ['j', 'i', 'o', 'l', 'm'],
73
+ l: ['k', 'o', 'p', ';'],
74
+ m: ['n', 'j', 'k'],
75
+ n: ['b', 'h', 'j', 'm'],
76
+ o: ['i', 'k', 'l', 'p'],
77
+ p: ['o', 'l', '['],
78
+ q: ['1', '2', 'w', 'a'],
79
+ r: ['e', 'd', 'f', 't'],
80
+ s: ['a', 'w', 'e', 'd', 'x', 'z'],
81
+ t: ['r', 'f', 'g', 'y'],
82
+ u: ['y', 'h', 'j', 'i'],
83
+ v: ['c', 'f', 'g', 'b'],
84
+ w: ['q', 'a', 's', 'e'],
85
+ x: ['z', 's', 'd', 'c'],
86
+ y: ['t', 'g', 'h', 'u'],
87
+ z: ['a', 's', 'x'],
88
+ };
89
+
90
+ /** * * * * * * * * * * * * * * * * * * * * * * * * * * **
91
+ * @description Calculates Euclidean physical key distance on a standard QWERTY keyboard layout.
92
+ * @param {string} keyA - Starting character or key.
93
+ * @param {string} keyB - Target character or key.
94
+ * @returns {number} Physical distance in key coordinate units (approx 1.0 to 12.0).
95
+ *
96
+ * -------------
97
+ *
98
+ * @Properties
99
+ * @param {string} keyA - First key name or character.
100
+ * @param {string} keyB - Second key name or character.
101
+ *
102
+ * -------------
103
+ *
104
+ * @example
105
+ * const distAdjacent = calculateKeyDistance('e', 'r'); // ~1.0
106
+ * const distFar = calculateKeyDistance('q', 'p'); // ~9.0
107
+ */
108
+ export function calculateKeyDistance(keyA, keyB) {
109
+ const a = QWERTY_COORDS[String(keyA).toLowerCase()] || [2, 5];
110
+ const b = QWERTY_COORDS[String(keyB).toLowerCase()] || [2, 5];
111
+ const dy = b[0] - a[0];
112
+ const dx = b[1] - a[1];
113
+ return Math.sqrt(dx * dx + dy * dy);
114
+ }
115
+
116
+ export class TypeFlowKeystroke {
117
+ /** * * * * * * * * * * * * * * * * * * * * * * * * * * **
118
+ * @description Computes dynamic typing delay between two consecutive characters based on physical distance, fatigue, and punctuation.
119
+ * @param {string} prevChar - Previously typed character.
120
+ * @param {string} nextChar - Character about to be typed.
121
+ * @param {Object} [options={}] - Cadence calculation options.
122
+ * @returns {number} Calculated delay in milliseconds.
123
+ *
124
+ * -------------
125
+ *
126
+ * @Properties
127
+ * @param {string} prevChar - The last typed character.
128
+ * @param {string} nextChar - The next character to type.
129
+ * @param {number} [options.baseSpeed=45] - Base typing speed in milliseconds per unit.
130
+ * @param {number} [options.fatigueIndex=0] - Character index counter in active passage.
131
+ * @param {number} [options.fatigueRate=0.0001] - Gradual deceleration coefficient per character.
132
+ *
133
+ * -------------
134
+ *
135
+ * @example
136
+ * const delay = TypeFlowKeystroke.getDelay('a', 'b', { baseSpeed: 40 });
137
+ * const pauseAfterPeriod = TypeFlowKeystroke.getDelay('.', 'T', { baseSpeed: 40 });
138
+ */
139
+ static getDelay(prevChar, nextChar, options = {}) {
140
+ const base = options.baseSpeed || 45;
141
+ const fatigue = 1 + (options.fatigueIndex || 0) * (options.fatigueRate || 0.0001);
142
+
143
+ // 1. Distance multiplier (farther keys take slightly longer)
144
+ const dist = calculateKeyDistance(prevChar, nextChar);
145
+ const distFactor = 1 + Math.min(0.6, dist * 0.06);
146
+
147
+ // 2. Natural Punctuation Hesitations
148
+ let pause = 0;
149
+ if (prevChar === '.' || prevChar === '!' || prevChar === '?') pause = 240;
150
+ else if (prevChar === ',' || prevChar === ';' || prevChar === ':') pause = 120;
151
+ else if (prevChar === ' ' || prevChar === '\n') pause = 35;
152
+
153
+ // 3. Random Gaussian jitter (±15%)
154
+ const jitter = 0.85 + Math.random() * 0.3;
155
+
156
+ return Math.round((base * distFactor * fatigue + pause) * jitter);
157
+ }
158
+
159
+ /** * * * * * * * * * * * * * * * * * * * * * * * * * * **
160
+ * @description Transforms plain text into a sequence of typing, hesitation pauses, adjacent-key typos, and backspace corrections.
161
+ * @param {string} text - Source text string to humanize.
162
+ * @param {Object} [options={}] - Typo and cadence simulation settings.
163
+ * @returns {Array<Object>} List of step actions ({ type: 'type' | 'erase' | 'pause', char?, duration?, isTypo? }).
164
+ *
165
+ * -------------
166
+ *
167
+ * @Properties
168
+ * @param {string} text - The input text.
169
+ * @param {number} [options.errorRate=0.04] - Probability of introducing an adjacent-key typo (0.04 = 4%).
170
+ * @param {number} [options.hesitationMs=180] - Pause duration in ms when a typo is made before backspacing.
171
+ *
172
+ * -------------
173
+ *
174
+ * @example
175
+ * const actions = TypeFlowKeystroke.humanize('Fast, resilient, zero dependencies.', {
176
+ * errorRate: 0.05,
177
+ * hesitationMs: 200,
178
+ * });
179
+ */
180
+ static humanize(text, options = {}) {
181
+ const errorRate = options.errorRate ?? 0.04;
182
+ const actions = [];
183
+
184
+ for (let i = 0; i < text.length; i++) {
185
+ const char = text[i];
186
+ const lower = char.toLowerCase();
187
+ const neighbors = QWERTY_NEIGHBORS[lower];
188
+
189
+ // Introduce typo if character has neighbors and probability hits
190
+ if (
191
+ neighbors &&
192
+ neighbors.length > 0 &&
193
+ Math.random() < errorRate &&
194
+ char !== ' ' &&
195
+ char !== '\n'
196
+ ) {
197
+ const typoChar = neighbors[Math.floor(Math.random() * neighbors.length)];
198
+ const isUpper = char !== lower;
199
+ const insertedTypo = isUpper ? typoChar.toUpperCase() : typoChar;
200
+
201
+ // 1. Type the typo
202
+ actions.push({ type: 'type', char: insertedTypo, isTypo: true });
203
+ // 2. Realize mistake hesitation
204
+ actions.push({ type: 'pause', duration: options.hesitationMs || 180 });
205
+ // 3. Backspace typo
206
+ actions.push({ type: 'erase', count: 1 });
207
+ // 4. Type correct character
208
+ actions.push({ type: 'type', char, isTypo: false });
209
+ } else {
210
+ actions.push({ type: 'type', char, isTypo: false });
211
+ }
212
+ }
213
+
214
+ return actions;
215
+ }
216
+ }
217
+
218
+ if (typeof window !== 'undefined') {
219
+ window.TypeFlowKeystroke = TypeFlowKeystroke;
220
+ }