voonex 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +223 -0
  3. package/dist/components/Box.d.ts +33 -0
  4. package/dist/components/Box.js +242 -0
  5. package/dist/components/Button.d.ts +23 -0
  6. package/dist/components/Button.js +76 -0
  7. package/dist/components/Checkbox.d.ts +20 -0
  8. package/dist/components/Checkbox.js +40 -0
  9. package/dist/components/Input.d.ts +23 -0
  10. package/dist/components/Input.js +79 -0
  11. package/dist/components/Menu.d.ts +27 -0
  12. package/dist/components/Menu.js +93 -0
  13. package/dist/components/Popup.d.ts +7 -0
  14. package/dist/components/Popup.js +50 -0
  15. package/dist/components/ProgressBar.d.ts +28 -0
  16. package/dist/components/ProgressBar.js +47 -0
  17. package/dist/components/Radio.d.ts +22 -0
  18. package/dist/components/Radio.js +64 -0
  19. package/dist/components/Select.d.ts +24 -0
  20. package/dist/components/Select.js +126 -0
  21. package/dist/components/Tab.d.ts +24 -0
  22. package/dist/components/Tab.js +72 -0
  23. package/dist/components/Table.d.ts +25 -0
  24. package/dist/components/Table.js +116 -0
  25. package/dist/components/Textarea.d.ts +26 -0
  26. package/dist/components/Textarea.js +176 -0
  27. package/dist/components/Tree.d.ts +33 -0
  28. package/dist/components/Tree.js +166 -0
  29. package/dist/core/Component.d.ts +6 -0
  30. package/dist/core/Component.js +5 -0
  31. package/dist/core/Cursor.d.ts +7 -0
  32. package/dist/core/Cursor.js +59 -0
  33. package/dist/core/Events.d.ts +11 -0
  34. package/dist/core/Events.js +37 -0
  35. package/dist/core/Focus.d.ts +16 -0
  36. package/dist/core/Focus.js +69 -0
  37. package/dist/core/Input.d.ts +13 -0
  38. package/dist/core/Input.js +88 -0
  39. package/dist/core/Layout.d.ts +18 -0
  40. package/dist/core/Layout.js +65 -0
  41. package/dist/core/Screen.d.ts +78 -0
  42. package/dist/core/Screen.js +373 -0
  43. package/dist/core/Styler.d.ts +71 -0
  44. package/dist/core/Styler.js +157 -0
  45. package/dist/index.d.ts +25 -0
  46. package/dist/index.js +41 -0
  47. package/package.json +29 -0
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ // ==========================================
3
+ // CORE: CURSOR MANAGEMENT
4
+ // ==========================================
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.Cursor = void 0;
40
+ const readline = __importStar(require("readline"));
41
+ class Cursor {
42
+ static hide() {
43
+ process.stdout.write('\x1b[?25l');
44
+ }
45
+ static show() {
46
+ process.stdout.write('\x1b[?25h');
47
+ }
48
+ static moveTo(x, y) {
49
+ readline.cursorTo(process.stdout, x, y);
50
+ }
51
+ static clearLine() {
52
+ readline.clearLine(process.stdout, 0);
53
+ }
54
+ static clearScreen() {
55
+ readline.cursorTo(process.stdout, 0, 0);
56
+ readline.clearScreenDown(process.stdout);
57
+ }
58
+ }
59
+ exports.Cursor = Cursor;
@@ -0,0 +1,11 @@
1
+ export type EventHandler = (data?: any) => void;
2
+ export declare class EventManager {
3
+ private static instance;
4
+ private listeners;
5
+ private constructor();
6
+ static getInstance(): EventManager;
7
+ on(event: string, handler: EventHandler): void;
8
+ off(event: string, handler: EventHandler): void;
9
+ emit(event: string, data?: any): void;
10
+ }
11
+ export declare const Events: EventManager;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ // ==========================================
3
+ // CORE: EVENT MANAGER
4
+ // ==========================================
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Events = exports.EventManager = void 0;
7
+ class EventManager {
8
+ constructor() {
9
+ this.listeners = new Map();
10
+ }
11
+ static getInstance() {
12
+ if (!EventManager.instance) {
13
+ EventManager.instance = new EventManager();
14
+ }
15
+ return EventManager.instance;
16
+ }
17
+ on(event, handler) {
18
+ if (!this.listeners.has(event)) {
19
+ this.listeners.set(event, []);
20
+ }
21
+ this.listeners.get(event).push(handler);
22
+ }
23
+ off(event, handler) {
24
+ if (!this.listeners.has(event))
25
+ return;
26
+ const handlers = this.listeners.get(event);
27
+ this.listeners.set(event, handlers.filter(h => h !== handler));
28
+ }
29
+ emit(event, data) {
30
+ if (!this.listeners.has(event))
31
+ return;
32
+ this.listeners.get(event).forEach(handler => handler(data));
33
+ }
34
+ }
35
+ exports.EventManager = EventManager;
36
+ // Global accessor
37
+ exports.Events = EventManager.getInstance();
@@ -0,0 +1,16 @@
1
+ import * as readline from 'readline';
2
+ export interface Focusable {
3
+ id: string;
4
+ parent?: Focusable;
5
+ focus(): void;
6
+ blur(): void;
7
+ handleKey(key: readline.Key): boolean | void;
8
+ render(): void;
9
+ }
10
+ export declare class FocusManager {
11
+ private components;
12
+ private activeIndex;
13
+ register(component: Focusable): void;
14
+ handleKey(key: readline.Key): void;
15
+ private cycleFocus;
16
+ }
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FocusManager = void 0;
4
+ class FocusManager {
5
+ constructor() {
6
+ this.components = [];
7
+ this.activeIndex = 0;
8
+ }
9
+ register(component) {
10
+ this.components.push(component);
11
+ if (this.components.length === 1) {
12
+ component.focus();
13
+ this.activeIndex = 0;
14
+ }
15
+ }
16
+ handleKey(key) {
17
+ if (this.components.length === 0)
18
+ return;
19
+ // === COMPONENT LOGIC ===
20
+ // Event Bubbling: Child -> Parent -> Root
21
+ let target = this.components[this.activeIndex];
22
+ let consumed = false;
23
+ while (target) {
24
+ const result = target.handleKey(key);
25
+ if (result === true) {
26
+ consumed = true;
27
+ break;
28
+ }
29
+ target = target.parent;
30
+ }
31
+ if (consumed) {
32
+ return;
33
+ }
34
+ // === NAVIGATION LOGIC ===
35
+ // Next: Tab
36
+ if (key.name === 'tab' && !key.shift) {
37
+ this.cycleFocus(false);
38
+ return;
39
+ }
40
+ // Fallback: Down/Right for next (if not consumed by component)
41
+ if (key.name === 'down' || key.name === 'right') {
42
+ this.cycleFocus(false);
43
+ return;
44
+ }
45
+ // Previous: Shift+Tab
46
+ if (key.name === 'tab' && key.shift) {
47
+ this.cycleFocus(true);
48
+ return;
49
+ }
50
+ // Fallback: Up/Left for previous (if not consumed by component)
51
+ if (key.name === 'up' || key.name === 'left') {
52
+ this.cycleFocus(true);
53
+ return;
54
+ }
55
+ }
56
+ cycleFocus(reverse = false) {
57
+ this.components[this.activeIndex].blur();
58
+ this.components[this.activeIndex].render();
59
+ if (reverse) {
60
+ this.activeIndex = (this.activeIndex - 1 + this.components.length) % this.components.length;
61
+ }
62
+ else {
63
+ this.activeIndex = (this.activeIndex + 1) % this.components.length;
64
+ }
65
+ this.components[this.activeIndex].focus();
66
+ this.components[this.activeIndex].render();
67
+ }
68
+ }
69
+ exports.FocusManager = FocusManager;
@@ -0,0 +1,13 @@
1
+ import * as readline from 'readline';
2
+ export type KeyHandler = (key: readline.Key) => boolean | void;
3
+ export declare class Input {
4
+ private static listeners;
5
+ private static initialized;
6
+ static init(): void;
7
+ static onKey(handler: KeyHandler): void;
8
+ static offKey(handler: KeyHandler): void;
9
+ /**
10
+ * Stops listening and restores stdin.
11
+ */
12
+ static reset(): void;
13
+ }
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ // ==========================================
3
+ // CORE: INPUT MANAGER (The "Controller")
4
+ // ==========================================
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.Input = void 0;
40
+ const readline = __importStar(require("readline"));
41
+ const Screen_1 = require("./Screen");
42
+ class Input {
43
+ static init() {
44
+ if (this.initialized)
45
+ return;
46
+ readline.emitKeypressEvents(process.stdin);
47
+ if (process.stdin.isTTY) {
48
+ process.stdin.setRawMode(true);
49
+ }
50
+ process.stdin.on('keypress', (str, key) => {
51
+ // Handle Ctrl+C globally to prevent trapping the user
52
+ if (key.ctrl && key.name === 'c') {
53
+ Screen_1.Screen.leave(); // Restore terminal state
54
+ process.exit();
55
+ }
56
+ // Iterate backwards so newest listeners (e.g. Popups) get first dibs
57
+ for (let i = this.listeners.length - 1; i >= 0; i--) {
58
+ const consumed = this.listeners[i](key);
59
+ if (consumed === true)
60
+ break;
61
+ }
62
+ // Trigger a render check after input handling
63
+ Screen_1.Screen.scheduleRender();
64
+ });
65
+ this.initialized = true;
66
+ }
67
+ static onKey(handler) {
68
+ this.init();
69
+ this.listeners.push(handler);
70
+ }
71
+ static offKey(handler) {
72
+ this.listeners = this.listeners.filter(l => l !== handler);
73
+ }
74
+ /**
75
+ * Stops listening and restores stdin.
76
+ */
77
+ static reset() {
78
+ if (process.stdin.isTTY) {
79
+ process.stdin.setRawMode(false);
80
+ }
81
+ process.stdin.pause();
82
+ this.listeners = [];
83
+ this.initialized = false;
84
+ }
85
+ }
86
+ exports.Input = Input;
87
+ Input.listeners = [];
88
+ Input.initialized = false;
@@ -0,0 +1,18 @@
1
+ import { Rect } from './Screen';
2
+ export { Rect };
3
+ export declare class Layout {
4
+ /**
5
+ * Splits a rectangle vertically (into columns).
6
+ * @param parent The parent rectangle
7
+ * @param weights Array of weights (e.g. [1, 2] means 1/3 and 2/3) or absolute sizes
8
+ */
9
+ static splitVertical(parent: Rect, weights: number[]): Rect[];
10
+ /**
11
+ * Splits a rectangle horizontally (into rows).
12
+ */
13
+ static splitHorizontal(parent: Rect, weights: number[]): Rect[];
14
+ /**
15
+ * Creates a padded inner rectangle.
16
+ */
17
+ static pad(rect: Rect, padding: number): Rect;
18
+ }
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ // ==========================================
3
+ // CORE: LAYOUT ENGINE (The "Architect")
4
+ // ==========================================
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Layout = void 0;
7
+ class Layout {
8
+ /**
9
+ * Splits a rectangle vertically (into columns).
10
+ * @param parent The parent rectangle
11
+ * @param weights Array of weights (e.g. [1, 2] means 1/3 and 2/3) or absolute sizes
12
+ */
13
+ static splitVertical(parent, weights) {
14
+ const totalWeight = weights.reduce((a, b) => a + b, 0);
15
+ let currentX = parent.x;
16
+ return weights.map((w, i) => {
17
+ // Check if it's the last item to fill remaining space (avoid rounding errors)
18
+ const isLast = i === weights.length - 1;
19
+ const width = isLast
20
+ ? parent.width - (currentX - parent.x)
21
+ : Math.floor((w / totalWeight) * parent.width);
22
+ const rect = {
23
+ x: currentX,
24
+ y: parent.y,
25
+ width: width,
26
+ height: parent.height
27
+ };
28
+ currentX += width;
29
+ return rect;
30
+ });
31
+ }
32
+ /**
33
+ * Splits a rectangle horizontally (into rows).
34
+ */
35
+ static splitHorizontal(parent, weights) {
36
+ const totalWeight = weights.reduce((a, b) => a + b, 0);
37
+ let currentY = parent.y;
38
+ return weights.map((w, i) => {
39
+ const isLast = i === weights.length - 1;
40
+ const height = isLast
41
+ ? parent.height - (currentY - parent.y)
42
+ : Math.floor((w / totalWeight) * parent.height);
43
+ const rect = {
44
+ x: parent.x,
45
+ y: currentY,
46
+ width: parent.width,
47
+ height: height
48
+ };
49
+ currentY += height;
50
+ return rect;
51
+ });
52
+ }
53
+ /**
54
+ * Creates a padded inner rectangle.
55
+ */
56
+ static pad(rect, padding) {
57
+ return {
58
+ x: rect.x + padding,
59
+ y: rect.y + padding,
60
+ width: Math.max(0, rect.width - (padding * 2)),
61
+ height: Math.max(0, rect.height - (padding * 2))
62
+ };
63
+ }
64
+ }
65
+ exports.Layout = Layout;
@@ -0,0 +1,78 @@
1
+ export interface Rect {
2
+ x: number;
3
+ y: number;
4
+ width: number;
5
+ height: number;
6
+ }
7
+ export declare class Screen {
8
+ private static isAlternateBuffer;
9
+ private static resizeTimeout;
10
+ private static currentBuffer;
11
+ private static previousBuffer;
12
+ private static dirtyRows;
13
+ private static layerStack;
14
+ private static isDirty;
15
+ private static renderScheduled;
16
+ private static width;
17
+ private static height;
18
+ private static renderRoots;
19
+ /**
20
+ * Enters the Alternate Screen Buffer (like Vim or Nano).
21
+ */
22
+ static enter(): void;
23
+ /**
24
+ * Leaves the Alternate Screen Buffer and restores cursor.
25
+ */
26
+ static leave(): void;
27
+ private static resizeBuffers;
28
+ /**
29
+ * Schedules a render flush in the next tick.
30
+ * Call this whenever a component changes state.
31
+ */
32
+ static scheduleRender(): void;
33
+ /**
34
+ * Writes text at a specific coordinate into the virtual buffer.
35
+ * Handles ANSI escape codes using a state machine parser.
36
+ * Supports clipping region and relative positioning.
37
+ */
38
+ static write(x: number, y: number, text: string, clipRect?: Rect): void;
39
+ /**
40
+ * Pushes the current screen state to a stack.
41
+ */
42
+ static pushLayer(): void;
43
+ /**
44
+ * Restores the screen state from the stack.
45
+ */
46
+ static popLayer(): void;
47
+ /**
48
+ * Clears the virtual buffer.
49
+ */
50
+ static clear(): void;
51
+ /**
52
+ * Registers a root component for the rendering loop (Painter's Algorithm).
53
+ * @param renderFn The function that renders the component
54
+ * @param zIndex Priority (higher draws on top)
55
+ */
56
+ static mount(renderFn: () => void, zIndex?: number): void;
57
+ /**
58
+ * Unregisters a root component from the rendering loop.
59
+ * @param renderFn The function that renders the component
60
+ */
61
+ static unmount(renderFn: () => void): void;
62
+ /**
63
+ * Diffs currentBuffer vs previousBuffer and writes changes to stdout.
64
+ * Optimized with String Batching and Relative Cursor Moves.
65
+ */
66
+ static flush(): void;
67
+ /**
68
+ * Gets current terminal dimensions.
69
+ */
70
+ static get size(): {
71
+ width: number;
72
+ height: number;
73
+ };
74
+ /**
75
+ * Listens for resize events.
76
+ */
77
+ static onResize(callback: () => void): void;
78
+ }