@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.
- package/LICENSE +21 -0
- package/README.md +637 -0
- package/branding/dist/ico/typeflow-logo-16x16.ico +0 -0
- package/branding/dist/ico/typeflow-logo-256x256.ico +0 -0
- package/branding/dist/ico/typeflow-logo-32x32.ico +0 -0
- package/branding/dist/ico/typeflow-logo-48x48.ico +0 -0
- package/branding/dist/png/typeflow-logo-1024x1024.png +0 -0
- package/branding/dist/png/typeflow-logo-128x128.png +0 -0
- package/branding/dist/png/typeflow-logo-16x16.png +0 -0
- package/branding/dist/png/typeflow-logo-256x256.png +0 -0
- package/branding/dist/png/typeflow-logo-512x512.png +0 -0
- package/branding/dist/png/typeflow-logo-64x64.png +0 -0
- package/branding/dist/webp/typeflow-logo-1024x1024.webp +0 -0
- package/branding/dist/webp/typeflow-logo-128x128.webp +0 -0
- package/branding/dist/webp/typeflow-logo-16x16.webp +0 -0
- package/branding/dist/webp/typeflow-logo-256x256.webp +0 -0
- package/branding/dist/webp/typeflow-logo-32x32.webp +0 -0
- package/branding/dist/webp/typeflow-logo-48x48.webp +0 -0
- package/branding/dist/webp/typeflow-logo-512x512.webp +0 -0
- package/branding/dist/webp/typeflow-logo-64x64.webp +0 -0
- package/branding/gen-logo.ps1 +14 -0
- package/branding/typeflow-logo.svg +162 -0
- package/dist/typeflow/LICENSE +21 -0
- package/dist/typeflow/README.md +231 -0
- package/dist/typeflow/branding/dist/ico/typeflow-logo-16x16.ico +0 -0
- package/dist/typeflow/branding/dist/ico/typeflow-logo-256x256.ico +0 -0
- package/dist/typeflow/branding/dist/ico/typeflow-logo-32x32.ico +0 -0
- package/dist/typeflow/branding/dist/ico/typeflow-logo-48x48.ico +0 -0
- package/dist/typeflow/branding/dist/png/typeflow-logo-1024x1024.png +0 -0
- package/dist/typeflow/branding/dist/png/typeflow-logo-128x128.png +0 -0
- package/dist/typeflow/branding/dist/png/typeflow-logo-16x16.png +0 -0
- package/dist/typeflow/branding/dist/png/typeflow-logo-256x256.png +0 -0
- package/dist/typeflow/branding/dist/png/typeflow-logo-512x512.png +0 -0
- package/dist/typeflow/branding/dist/png/typeflow-logo-64x64.png +0 -0
- package/dist/typeflow/branding/dist/webp/typeflow-logo-1024x1024.webp +0 -0
- package/dist/typeflow/branding/dist/webp/typeflow-logo-128x128.webp +0 -0
- package/dist/typeflow/branding/dist/webp/typeflow-logo-16x16.webp +0 -0
- package/dist/typeflow/branding/dist/webp/typeflow-logo-256x256.webp +0 -0
- package/dist/typeflow/branding/dist/webp/typeflow-logo-32x32.webp +0 -0
- package/dist/typeflow/branding/dist/webp/typeflow-logo-48x48.webp +0 -0
- package/dist/typeflow/branding/dist/webp/typeflow-logo-512x512.webp +0 -0
- package/dist/typeflow/branding/dist/webp/typeflow-logo-64x64.webp +0 -0
- package/dist/typeflow/branding/gen-logo.ps1 +14 -0
- package/dist/typeflow/branding/typeflow-logo.svg +162 -0
- package/dist/typeflow/dist/typeflow-caret.cjs +47 -0
- package/dist/typeflow/dist/typeflow-caret.cjs.map +1 -0
- package/dist/typeflow/dist/typeflow-caret.esm.js +47 -0
- package/dist/typeflow/dist/typeflow-caret.esm.js.map +1 -0
- package/dist/typeflow/dist/typeflow-caret.esm.min.js +2 -0
- package/dist/typeflow/dist/typeflow-caret.esm.min.js.map +1 -0
- package/dist/typeflow/dist/typeflow-caret.js +47 -0
- package/dist/typeflow/dist/typeflow-caret.js.map +1 -0
- package/dist/typeflow/dist/typeflow-caret.min.js +2 -0
- package/dist/typeflow/dist/typeflow-caret.min.js.map +1 -0
- package/dist/typeflow/dist/typeflow-caret.mjs +47 -0
- package/dist/typeflow/dist/typeflow-caret.mjs.map +1 -0
- package/dist/typeflow/dist/typeflow-debug.cjs +109 -0
- package/dist/typeflow/dist/typeflow-debug.cjs.map +1 -0
- package/dist/typeflow/dist/typeflow-debug.esm.js +109 -0
- package/dist/typeflow/dist/typeflow-debug.esm.js.map +1 -0
- package/dist/typeflow/dist/typeflow-debug.esm.min.js +2 -0
- package/dist/typeflow/dist/typeflow-debug.esm.min.js.map +1 -0
- package/dist/typeflow/dist/typeflow-debug.js +109 -0
- package/dist/typeflow/dist/typeflow-debug.js.map +1 -0
- package/dist/typeflow/dist/typeflow-debug.min.js +2 -0
- package/dist/typeflow/dist/typeflow-debug.min.js.map +1 -0
- package/dist/typeflow/dist/typeflow-debug.mjs +109 -0
- package/dist/typeflow/dist/typeflow-debug.mjs.map +1 -0
- package/dist/typeflow/dist/typeflow-extchars.cjs +66 -0
- package/dist/typeflow/dist/typeflow-extchars.cjs.map +1 -0
- package/dist/typeflow/dist/typeflow-extchars.esm.js +66 -0
- package/dist/typeflow/dist/typeflow-extchars.esm.js.map +1 -0
- package/dist/typeflow/dist/typeflow-extchars.esm.min.js +2 -0
- package/dist/typeflow/dist/typeflow-extchars.esm.min.js.map +1 -0
- package/dist/typeflow/dist/typeflow-extchars.js +66 -0
- package/dist/typeflow/dist/typeflow-extchars.js.map +1 -0
- package/dist/typeflow/dist/typeflow-extchars.min.js +2 -0
- package/dist/typeflow/dist/typeflow-extchars.min.js.map +1 -0
- package/dist/typeflow/dist/typeflow-extchars.mjs +66 -0
- package/dist/typeflow/dist/typeflow-extchars.mjs.map +1 -0
- package/dist/typeflow/dist/typeflow-keystroke.cjs +47 -0
- package/dist/typeflow/dist/typeflow-keystroke.cjs.map +1 -0
- package/dist/typeflow/dist/typeflow-keystroke.esm.js +47 -0
- package/dist/typeflow/dist/typeflow-keystroke.esm.js.map +1 -0
- package/dist/typeflow/dist/typeflow-keystroke.esm.min.js +2 -0
- package/dist/typeflow/dist/typeflow-keystroke.esm.min.js.map +1 -0
- package/dist/typeflow/dist/typeflow-keystroke.js +47 -0
- package/dist/typeflow/dist/typeflow-keystroke.js.map +1 -0
- package/dist/typeflow/dist/typeflow-keystroke.min.js +2 -0
- package/dist/typeflow/dist/typeflow-keystroke.min.js.map +1 -0
- package/dist/typeflow/dist/typeflow-keystroke.mjs +47 -0
- package/dist/typeflow/dist/typeflow-keystroke.mjs.map +1 -0
- package/dist/typeflow/dist/typeflow-metrics.cjs +76 -0
- package/dist/typeflow/dist/typeflow-metrics.cjs.map +1 -0
- package/dist/typeflow/dist/typeflow-metrics.esm.js +76 -0
- package/dist/typeflow/dist/typeflow-metrics.esm.js.map +1 -0
- package/dist/typeflow/dist/typeflow-metrics.esm.min.js +2 -0
- package/dist/typeflow/dist/typeflow-metrics.esm.min.js.map +1 -0
- package/dist/typeflow/dist/typeflow-metrics.js +76 -0
- package/dist/typeflow/dist/typeflow-metrics.js.map +1 -0
- package/dist/typeflow/dist/typeflow-metrics.min.js +2 -0
- package/dist/typeflow/dist/typeflow-metrics.min.js.map +1 -0
- package/dist/typeflow/dist/typeflow-metrics.mjs +76 -0
- package/dist/typeflow/dist/typeflow-metrics.mjs.map +1 -0
- package/dist/typeflow/dist/typeflow-parallel.cjs +3 -0
- package/dist/typeflow/dist/typeflow-parallel.cjs.map +1 -0
- package/dist/typeflow/dist/typeflow-parallel.esm.js +3 -0
- package/dist/typeflow/dist/typeflow-parallel.esm.js.map +1 -0
- package/dist/typeflow/dist/typeflow-parallel.esm.min.js +2 -0
- package/dist/typeflow/dist/typeflow-parallel.esm.min.js.map +1 -0
- package/dist/typeflow/dist/typeflow-parallel.js +3 -0
- package/dist/typeflow/dist/typeflow-parallel.js.map +1 -0
- package/dist/typeflow/dist/typeflow-parallel.min.js +2 -0
- package/dist/typeflow/dist/typeflow-parallel.min.js.map +1 -0
- package/dist/typeflow/dist/typeflow-parallel.mjs +3 -0
- package/dist/typeflow/dist/typeflow-parallel.mjs.map +1 -0
- package/dist/typeflow/dist/typeflow-webaudio.cjs +81 -0
- package/dist/typeflow/dist/typeflow-webaudio.cjs.map +1 -0
- package/dist/typeflow/dist/typeflow-webaudio.esm.js +81 -0
- package/dist/typeflow/dist/typeflow-webaudio.esm.js.map +1 -0
- package/dist/typeflow/dist/typeflow-webaudio.esm.min.js +2 -0
- package/dist/typeflow/dist/typeflow-webaudio.esm.min.js.map +1 -0
- package/dist/typeflow/dist/typeflow-webaudio.js +81 -0
- package/dist/typeflow/dist/typeflow-webaudio.js.map +1 -0
- package/dist/typeflow/dist/typeflow-webaudio.min.js +2 -0
- package/dist/typeflow/dist/typeflow-webaudio.min.js.map +1 -0
- package/dist/typeflow/dist/typeflow-webaudio.mjs +81 -0
- package/dist/typeflow/dist/typeflow-webaudio.mjs.map +1 -0
- package/dist/typeflow/dist/typeflow.cjs +277 -0
- package/dist/typeflow/dist/typeflow.cjs.map +1 -0
- package/dist/typeflow/dist/typeflow.esm.js +277 -0
- package/dist/typeflow/dist/typeflow.esm.js.map +1 -0
- package/dist/typeflow/dist/typeflow.esm.min.js +2 -0
- package/dist/typeflow/dist/typeflow.esm.min.js.map +1 -0
- package/dist/typeflow/dist/typeflow.js +277 -0
- package/dist/typeflow/dist/typeflow.js.map +1 -0
- package/dist/typeflow/dist/typeflow.min.js +2 -0
- package/dist/typeflow/dist/typeflow.min.js.map +1 -0
- package/dist/typeflow/dist/typeflow.mjs +277 -0
- package/dist/typeflow/dist/typeflow.mjs.map +1 -0
- package/dist/typeflow/jsr.jsonc +27 -0
- package/dist/typeflow/package.json +79 -0
- package/dist/typeflow/src/typeflow-audio-presets.js +137 -0
- package/dist/typeflow/src/typeflow-caret.d.ts +65 -0
- package/dist/typeflow/src/typeflow-caret.js +303 -0
- package/dist/typeflow/src/typeflow-debug.d.ts +34 -0
- package/dist/typeflow/src/typeflow-debug.js +223 -0
- package/dist/typeflow/src/typeflow-extchars.d.ts +28 -0
- package/dist/typeflow/src/typeflow-extchars.js +132 -0
- package/dist/typeflow/src/typeflow-keystroke.d.ts +28 -0
- package/dist/typeflow/src/typeflow-keystroke.js +220 -0
- package/dist/typeflow/src/typeflow-metrics.d.ts +38 -0
- package/dist/typeflow/src/typeflow-metrics.js +556 -0
- package/dist/typeflow/src/typeflow-parallel.d.ts +36 -0
- package/dist/typeflow/src/typeflow-parallel.js +157 -0
- package/dist/typeflow/src/typeflow-webaudio.d.ts +83 -0
- package/dist/typeflow/src/typeflow-webaudio.js +517 -0
- package/dist/typeflow/src/typeflow.d.ts +328 -0
- package/dist/typeflow/src/typeflow.js +2119 -0
- package/jsr.jsonc +27 -0
- package/package.json +133 -0
- package/src/typeflow-audio-presets.js +137 -0
- package/src/typeflow-caret.d.ts +65 -0
- package/src/typeflow-caret.js +303 -0
- package/src/typeflow-debug.d.ts +34 -0
- package/src/typeflow-debug.js +223 -0
- package/src/typeflow-extchars.d.ts +28 -0
- package/src/typeflow-extchars.js +132 -0
- package/src/typeflow-keystroke.d.ts +28 -0
- package/src/typeflow-keystroke.js +220 -0
- package/src/typeflow-metrics.d.ts +38 -0
- package/src/typeflow-metrics.js +556 -0
- package/src/typeflow-parallel.d.ts +36 -0
- package/src/typeflow-parallel.js +157 -0
- package/src/typeflow-webaudio.d.ts +83 -0
- package/src/typeflow-webaudio.js +517 -0
- package/src/typeflow.d.ts +328 -0
- package/src/typeflow.js +2119 -0
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeFlow Metrics - Real-time Performance HUD & Diagnostic Tooltip.
|
|
3
|
+
*/
|
|
4
|
+
export interface TypeFlowMetricsOptions {
|
|
5
|
+
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
6
|
+
detailed?: boolean;
|
|
7
|
+
autoTrack?: boolean;
|
|
8
|
+
updateInterval?: number;
|
|
9
|
+
zIndex?: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface TypeFlowMetricsSnapshot {
|
|
13
|
+
timestamp: string;
|
|
14
|
+
fps: number;
|
|
15
|
+
activeInstances: number;
|
|
16
|
+
totalTyped: number;
|
|
17
|
+
totalErased: number;
|
|
18
|
+
domMutations: number;
|
|
19
|
+
interruptions: number;
|
|
20
|
+
uptimeSeconds: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class TypeFlowMetrics {
|
|
24
|
+
static instance: TypeFlowMetrics | null;
|
|
25
|
+
static mount(options?: TypeFlowMetricsOptions): TypeFlowMetrics;
|
|
26
|
+
static unmount(): void;
|
|
27
|
+
static getStats(): TypeFlowMetricsSnapshot | null;
|
|
28
|
+
|
|
29
|
+
constructor(options?: TypeFlowMetricsOptions);
|
|
30
|
+
toggleModal(forceState?: boolean): void;
|
|
31
|
+
recordTyped(count?: number): void;
|
|
32
|
+
recordErased(count?: number): void;
|
|
33
|
+
recordInterruption(): void;
|
|
34
|
+
resetStats(): void;
|
|
35
|
+
copyStats(): void;
|
|
36
|
+
getSnapshot(): TypeFlowMetricsSnapshot;
|
|
37
|
+
destroy(): void;
|
|
38
|
+
}
|