keyvoid 1.0.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/CHANGELOG.md +15 -0
- package/CONTRIBUTING.md +42 -0
- package/LICENSE +21 -0
- package/README.md +233 -0
- package/bin/keyvoid.js +121 -0
- package/package.json +77 -0
- package/src/app.js +294 -0
- package/src/engine/permissions.js +107 -0
- package/src/engine/suppressor/helpers/linux-helper.py +192 -0
- package/src/engine/suppressor/helpers/macos-helper.swift +108 -0
- package/src/engine/suppressor/helpers/macos-pynput-helper.py +179 -0
- package/src/engine/suppressor/helpers/windows-helper.ps1 +144 -0
- package/src/engine/suppressor/index.js +306 -0
- package/src/scripts/postinstall.js +33 -0
- package/src/ui/components/counter.js +64 -0
- package/src/ui/components/header.js +102 -0
- package/src/ui/components/status-bar.js +71 -0
- package/src/ui/components/unvoid-button.js +78 -0
- package/src/ui/mouse.js +97 -0
- package/src/ui/renderer.js +113 -0
- package/src/ui/skins/arcade.js +530 -0
- package/src/ui/skins/cat.js +223 -0
- package/src/ui/skins/clean.js +155 -0
- package/src/ui/skins/hacker.js +194 -0
- package/src/ui/skins/prank.js +195 -0
- package/src/ui/skins/toddler.js +131 -0
- package/src/ui/skins/zen.js +169 -0
- package/src/ui/unlock-sequence.js +105 -0
- package/src/utils/big-digits.js +130 -0
- package/src/utils/colors.js +114 -0
- package/src/utils/terminal.js +119 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// ─── Big Digit Renderer ──────────────────────────────────────────────
|
|
2
|
+
// Renders large 5-line tall digits for the keystroke counter display.
|
|
3
|
+
// Each digit is 6 characters wide. Looks premium in terminal.
|
|
4
|
+
|
|
5
|
+
const DIGIT_PATTERNS = {
|
|
6
|
+
'0': [
|
|
7
|
+
' ████ ',
|
|
8
|
+
'██ ██',
|
|
9
|
+
'██ ██',
|
|
10
|
+
'██ ██',
|
|
11
|
+
' ████ ',
|
|
12
|
+
],
|
|
13
|
+
'1': [
|
|
14
|
+
' ██ ',
|
|
15
|
+
' ███ ',
|
|
16
|
+
' ██ ',
|
|
17
|
+
' ██ ',
|
|
18
|
+
'██████',
|
|
19
|
+
],
|
|
20
|
+
'2': [
|
|
21
|
+
' ████ ',
|
|
22
|
+
'██ ██',
|
|
23
|
+
' ██ ',
|
|
24
|
+
' ██ ',
|
|
25
|
+
'██████',
|
|
26
|
+
],
|
|
27
|
+
'3': [
|
|
28
|
+
'█████ ',
|
|
29
|
+
' ██',
|
|
30
|
+
' ████ ',
|
|
31
|
+
' ██',
|
|
32
|
+
'█████ ',
|
|
33
|
+
],
|
|
34
|
+
'4': [
|
|
35
|
+
'██ ██',
|
|
36
|
+
'██ ██',
|
|
37
|
+
'██████',
|
|
38
|
+
' ██',
|
|
39
|
+
' ██',
|
|
40
|
+
],
|
|
41
|
+
'5': [
|
|
42
|
+
'██████',
|
|
43
|
+
'██ ',
|
|
44
|
+
'█████ ',
|
|
45
|
+
' ██',
|
|
46
|
+
'█████ ',
|
|
47
|
+
],
|
|
48
|
+
'6': [
|
|
49
|
+
' ████ ',
|
|
50
|
+
'██ ',
|
|
51
|
+
'█████ ',
|
|
52
|
+
'██ ██',
|
|
53
|
+
' ████ ',
|
|
54
|
+
],
|
|
55
|
+
'7': [
|
|
56
|
+
'██████',
|
|
57
|
+
' ██ ',
|
|
58
|
+
' ██ ',
|
|
59
|
+
' ██ ',
|
|
60
|
+
' ██ ',
|
|
61
|
+
],
|
|
62
|
+
'8': [
|
|
63
|
+
' ████ ',
|
|
64
|
+
'██ ██',
|
|
65
|
+
' ████ ',
|
|
66
|
+
'██ ██',
|
|
67
|
+
' ████ ',
|
|
68
|
+
],
|
|
69
|
+
'9': [
|
|
70
|
+
' ████ ',
|
|
71
|
+
'██ ██',
|
|
72
|
+
' █████',
|
|
73
|
+
' ██',
|
|
74
|
+
' ████ ',
|
|
75
|
+
],
|
|
76
|
+
',': [
|
|
77
|
+
' ',
|
|
78
|
+
' ',
|
|
79
|
+
' ',
|
|
80
|
+
' ██ ',
|
|
81
|
+
' ██ ',
|
|
82
|
+
],
|
|
83
|
+
'.': [
|
|
84
|
+
' ',
|
|
85
|
+
' ',
|
|
86
|
+
' ',
|
|
87
|
+
' ',
|
|
88
|
+
' ██ ',
|
|
89
|
+
],
|
|
90
|
+
' ': [
|
|
91
|
+
' ',
|
|
92
|
+
' ',
|
|
93
|
+
' ',
|
|
94
|
+
' ',
|
|
95
|
+
' ',
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// Render a number string as big 5-line text
|
|
100
|
+
// Returns an array of 5 strings (one per line)
|
|
101
|
+
export function renderBigNumber(numStr) {
|
|
102
|
+
const digits = String(numStr).split('');
|
|
103
|
+
const lines = ['', '', '', '', ''];
|
|
104
|
+
|
|
105
|
+
for (let i = 0; i < digits.length; i++) {
|
|
106
|
+
const pattern = DIGIT_PATTERNS[digits[i]] || DIGIT_PATTERNS[' '];
|
|
107
|
+
for (let row = 0; row < 5; row++) {
|
|
108
|
+
lines[row] += pattern[row] + (i < digits.length - 1 ? ' ' : '');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return lines;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Get the total visible width of a big number string
|
|
116
|
+
export function bigNumberWidth(numStr) {
|
|
117
|
+
const digits = String(numStr).split('');
|
|
118
|
+
let width = 0;
|
|
119
|
+
for (let i = 0; i < digits.length; i++) {
|
|
120
|
+
const pattern = DIGIT_PATTERNS[digits[i]] || DIGIT_PATTERNS[' '];
|
|
121
|
+
width += pattern[0].length;
|
|
122
|
+
if (i < digits.length - 1) width += 1; // gap
|
|
123
|
+
}
|
|
124
|
+
return width;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Format a number with comma separation for readability
|
|
128
|
+
export function formatCount(n) {
|
|
129
|
+
return n.toLocaleString('en-US');
|
|
130
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// ─── Color Palettes for KeyVoid Skins ────────────────────────────────
|
|
2
|
+
// Each palette is carefully curated for visual harmony and readability.
|
|
3
|
+
|
|
4
|
+
export const palettes = {
|
|
5
|
+
clean: {
|
|
6
|
+
bg: '\x1b[48;2;10;10;18m', // Deep space black
|
|
7
|
+
primary: '\x1b[38;2;0;255;224m', // Electric cyan
|
|
8
|
+
secondary: '\x1b[38;2;180;180;200m', // Soft silver
|
|
9
|
+
accent: '\x1b[38;2;191;64;191m', // Neon purple
|
|
10
|
+
dim: '\x1b[38;2;60;60;80m', // Muted gray
|
|
11
|
+
success: '\x1b[38;2;0;255;136m', // Neon green
|
|
12
|
+
warning: '\x1b[38;2;255;200;0m', // Warm gold
|
|
13
|
+
border: '\x1b[38;2;40;40;60m', // Subtle border
|
|
14
|
+
highlight: '\x1b[38;2;120;120;255m', // Soft blue
|
|
15
|
+
gradientStart:'\x1b[38;2;0;255;224m', // Cyan
|
|
16
|
+
gradientEnd: '\x1b[38;2;191;64;255m', // Purple
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
toddler: {
|
|
20
|
+
bg: '\x1b[48;2;30;15;40m', // Dark purple
|
|
21
|
+
primary: '\x1b[38;2;255;120;200m', // Hot pink
|
|
22
|
+
secondary: '\x1b[38;2;255;220;100m', // Warm yellow
|
|
23
|
+
accent: '\x1b[38;2;100;220;255m', // Sky blue
|
|
24
|
+
dim: '\x1b[38;2;80;50;90m', // Muted purple
|
|
25
|
+
fun1: '\x1b[38;2;255;100;100m', // Coral
|
|
26
|
+
fun2: '\x1b[38;2;100;255;180m', // Mint
|
|
27
|
+
fun3: '\x1b[38;2;200;130;255m', // Lavender
|
|
28
|
+
fun4: '\x1b[38;2;255;180;50m', // Orange
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
cat: {
|
|
32
|
+
bg: '\x1b[48;2;20;14;8m', // Dark charcoal brown
|
|
33
|
+
primary: '\x1b[38;2;255;140;0m', // Warm orange
|
|
34
|
+
secondary: '\x1b[38;2;255;179;0m', // Amber gold
|
|
35
|
+
accent: '\x1b[38;2;255;60;60m', // Alert red
|
|
36
|
+
dim: '\x1b[38;2;80;55;30m', // Muted brown
|
|
37
|
+
fur: '\x1b[38;2;200;150;80m', // Cat fur color
|
|
38
|
+
eyes: '\x1b[38;2;120;255;120m', // Green cat eyes
|
|
39
|
+
whiskers: '\x1b[38;2;180;180;180m', // Silver whiskers
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
prank: {
|
|
43
|
+
bg: '\x1b[48;2;0;120;212m', // Windows blue
|
|
44
|
+
primary: '\x1b[38;2;255;255;255m', // Pure white
|
|
45
|
+
secondary: '\x1b[38;2;200;220;255m', // Light blue-white
|
|
46
|
+
dim: '\x1b[38;2;130;180;240m', // Soft light blue
|
|
47
|
+
progress: '\x1b[38;2;255;255;255m', // White progress
|
|
48
|
+
progressBg: '\x1b[38;2;0;80;160m', // Dark progress bg
|
|
49
|
+
error: '\x1b[38;2;255;200;0m', // Warning yellow
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
hacker: {
|
|
53
|
+
bg: '\x1b[48;2;5;5;5m', // True black/dark grey
|
|
54
|
+
primary: '\x1b[38;2;0;255;0m', // Pure neon green
|
|
55
|
+
secondary: '\x1b[38;2;0;180;0m', // Matrix string green
|
|
56
|
+
accent: '\x1b[38;2;200;255;200m', // White/green flash
|
|
57
|
+
dim: '\x1b[38;2;0;80;0m', // Faded dark green
|
|
58
|
+
error: '\x1b[38;2;255;0;0m', // Fatal red
|
|
59
|
+
terminalBg: '\x1b[48;2;20;20;20m', // Slightly lighter black for "windows"
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
arcade: {
|
|
63
|
+
bg: '\x1b[48;2;10;10;30m', // Deep arcade navy
|
|
64
|
+
primary: '\x1b[38;2;0;255;255m', // Neon cyan
|
|
65
|
+
secondary: '\x1b[38;2;255;0;255m', // Neon magenta
|
|
66
|
+
accent: '\x1b[38;2;255;255;0m', // Neon yellow
|
|
67
|
+
dim: '\x1b[38;2;100;100;150m', // Faded purple/blue
|
|
68
|
+
laser: '\x1b[38;2;255;50;50m', // Bright red laser
|
|
69
|
+
alien: '\x1b[38;2;50;255;50m', // Classic green alien
|
|
70
|
+
explosion: '\x1b[38;2;255;150;0m', // Orange explosion
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
zen: {
|
|
74
|
+
bg: '\x1b[48;2;15;15;25m', // Very dark twilight blue
|
|
75
|
+
primary: '\x1b[38;2;180;180;255m', // Soft lavender
|
|
76
|
+
secondary: '\x1b[38;2;120;200;220m', // Soft teal
|
|
77
|
+
accent: '\x1b[38;2;255;200;200m', // Soft peach
|
|
78
|
+
dim: '\x1b[38;2;60;60;90m', // Faded twilight
|
|
79
|
+
ripple: '\x1b[38;2;255;255;255m', // Bright wave peak
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// Rainbow colors for toddler mode cycling
|
|
84
|
+
export const rainbow = [
|
|
85
|
+
'\x1b[48;2;150;70;70m', // Soft Red
|
|
86
|
+
'\x1b[48;2;150;110;60m', // Soft Orange
|
|
87
|
+
'\x1b[48;2;140;140;60m', // Soft Yellow
|
|
88
|
+
'\x1b[48;2;70;140;70m', // Soft Green
|
|
89
|
+
'\x1b[48;2;70;110;160m', // Soft Blue
|
|
90
|
+
'\x1b[48;2;110;70;150m', // Soft Indigo
|
|
91
|
+
'\x1b[48;2;150;70;120m', // Soft Violet
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
// ANSI reset code
|
|
95
|
+
export const RESET = '\x1b[0m';
|
|
96
|
+
export const BOLD = '\x1b[1m';
|
|
97
|
+
export const DIM = '\x1b[2m';
|
|
98
|
+
export const BLINK = '\x1b[5m';
|
|
99
|
+
|
|
100
|
+
// Gradient interpolation between two RGB colors
|
|
101
|
+
export function interpolateColor(r1, g1, b1, r2, g2, b2, t) {
|
|
102
|
+
const r = Math.round(r1 + (r2 - r1) * t);
|
|
103
|
+
const g = Math.round(g1 + (g2 - g1) * t);
|
|
104
|
+
const b = Math.round(b1 + (b2 - b1) * t);
|
|
105
|
+
return `\x1b[38;2;${r};${g};${b}m`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function bgColor(r, g, b) {
|
|
109
|
+
return `\x1b[48;2;${r};${g};${b}m`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function fgColor(r, g, b) {
|
|
113
|
+
return `\x1b[38;2;${r};${g};${b}m`;
|
|
114
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// ─── Terminal Utilities ──────────────────────────────────────────────
|
|
2
|
+
// Low-level ANSI escape helpers for full-screen terminal control.
|
|
3
|
+
|
|
4
|
+
export const ESC = '\x1b';
|
|
5
|
+
|
|
6
|
+
// Cursor movement
|
|
7
|
+
export const moveTo = (x, y) => `${ESC}[${y};${x}H`;
|
|
8
|
+
export const moveUp = (n = 1) => `${ESC}[${n}A`;
|
|
9
|
+
export const moveDown = (n = 1) => `${ESC}[${n}B`;
|
|
10
|
+
export const moveRight = (n = 1) => `${ESC}[${n}C`;
|
|
11
|
+
export const moveLeft = (n = 1) => `${ESC}[${n}D`;
|
|
12
|
+
|
|
13
|
+
// Screen control
|
|
14
|
+
export const clearScreen = `${ESC}[2J${ESC}[H`;
|
|
15
|
+
export const clearLine = `${ESC}[2K`;
|
|
16
|
+
export const saveCursor = `${ESC}[s`;
|
|
17
|
+
export const restoreCursor = `${ESC}[u`;
|
|
18
|
+
export const hideCursor = `${ESC}[?25l`;
|
|
19
|
+
export const showCursor = `${ESC}[?25h`;
|
|
20
|
+
|
|
21
|
+
// Alternate screen buffer (preserves the user's terminal content)
|
|
22
|
+
export const enterAltScreen = `${ESC}[?1049h`;
|
|
23
|
+
export const exitAltScreen = `${ESC}[?1049l`;
|
|
24
|
+
|
|
25
|
+
// Mouse tracking (SGR extended format for coordinates > 223)
|
|
26
|
+
export const enableMouse = `${ESC}[?1000h${ESC}[?1006h`;
|
|
27
|
+
export const disableMouse = `${ESC}[?1000l${ESC}[?1006l`;
|
|
28
|
+
|
|
29
|
+
// Get terminal dimensions
|
|
30
|
+
export function getSize() {
|
|
31
|
+
return {
|
|
32
|
+
cols: process.stdout.columns || 80,
|
|
33
|
+
rows: process.stdout.rows || 24,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Center text within a given width
|
|
38
|
+
export function centerText(text, width, padChar = ' ') {
|
|
39
|
+
const stripped = stripAnsi(text);
|
|
40
|
+
const pad = Math.max(0, Math.floor((width - stripped.length) / 2));
|
|
41
|
+
return padChar.repeat(pad) + text + padChar.repeat(Math.max(0, width - stripped.length - pad));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Right-align text within a given width
|
|
45
|
+
export function rightAlign(text, width) {
|
|
46
|
+
const stripped = stripAnsi(text);
|
|
47
|
+
const pad = Math.max(0, width - stripped.length);
|
|
48
|
+
return ' '.repeat(pad) + text;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Strip ANSI codes from a string (for measuring visible length)
|
|
52
|
+
export function stripAnsi(str) {
|
|
53
|
+
return str.replace(/\x1b\[[0-9;]*[a-zA-Z]|\x1b\[?[0-9;]*[a-zA-Z]/g, '');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Measure visible length of a string (ignoring ANSI codes)
|
|
57
|
+
export function visibleLength(str) {
|
|
58
|
+
return stripAnsi(str).length;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Pad a string to a visible width (respecting ANSI codes)
|
|
62
|
+
export function padEnd(str, width, char = ' ') {
|
|
63
|
+
const vLen = visibleLength(str);
|
|
64
|
+
return str + char.repeat(Math.max(0, width - vLen));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Create a horizontal line
|
|
68
|
+
export function horizontalLine(width, char = '─') {
|
|
69
|
+
return char.repeat(width);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Write directly to stdout without buffering newlines
|
|
73
|
+
export function write(str) {
|
|
74
|
+
process.stdout.write(str);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Box-drawing characters (Unicode)
|
|
78
|
+
export const box = {
|
|
79
|
+
topLeft: '╭',
|
|
80
|
+
topRight: '╮',
|
|
81
|
+
bottomLeft: '╰',
|
|
82
|
+
bottomRight: '╯',
|
|
83
|
+
horizontal: '─',
|
|
84
|
+
vertical: '│',
|
|
85
|
+
teeRight: '├',
|
|
86
|
+
teeLeft: '┤',
|
|
87
|
+
cross: '┼',
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// Draw a box outline with optional title
|
|
91
|
+
export function drawBox(x, y, width, height, borderColor = '', resetColor = '\x1b[0m') {
|
|
92
|
+
const lines = [];
|
|
93
|
+
// Top
|
|
94
|
+
lines.push(moveTo(x, y) + borderColor + box.topLeft + box.horizontal.repeat(width - 2) + box.topRight + resetColor);
|
|
95
|
+
// Sides
|
|
96
|
+
for (let i = 1; i < height - 1; i++) {
|
|
97
|
+
lines.push(moveTo(x, y + i) + borderColor + box.vertical + resetColor);
|
|
98
|
+
lines.push(moveTo(x + width - 1, y + i) + borderColor + box.vertical + resetColor);
|
|
99
|
+
}
|
|
100
|
+
// Bottom
|
|
101
|
+
lines.push(moveTo(x, y + height - 1) + borderColor + box.bottomLeft + box.horizontal.repeat(width - 2) + box.bottomRight + resetColor);
|
|
102
|
+
return lines.join('');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Smooth block characters for progress bars
|
|
106
|
+
export const blocks = {
|
|
107
|
+
full: '█',
|
|
108
|
+
seven: '▉',
|
|
109
|
+
six: '▊',
|
|
110
|
+
five: '▋',
|
|
111
|
+
four: '▌',
|
|
112
|
+
three: '▍',
|
|
113
|
+
two: '▎',
|
|
114
|
+
one: '▏',
|
|
115
|
+
light: '░',
|
|
116
|
+
medium: '▒',
|
|
117
|
+
dark: '▓',
|
|
118
|
+
empty: ' ',
|
|
119
|
+
};
|