linecraft 0.1.0 → 0.2.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 +1 -1
- package/README.md +313 -64
- package/lib/api/color.d.ts +6 -0
- package/lib/api/color.d.ts.map +1 -0
- package/lib/api/color.js +9 -0
- package/lib/api/color.js.map +1 -0
- package/lib/api/color.test.d.ts +2 -0
- package/lib/api/color.test.d.ts.map +1 -0
- package/lib/api/color.test.js +23 -0
- package/lib/api/color.test.js.map +1 -0
- package/lib/api/flex.d.ts +55 -0
- package/lib/api/flex.d.ts.map +1 -0
- package/lib/api/flex.js +86 -0
- package/lib/api/flex.js.map +1 -0
- package/lib/api/flex.test.d.ts +2 -0
- package/lib/api/flex.test.d.ts.map +1 -0
- package/lib/api/flex.test.js +82 -0
- package/lib/api/flex.test.js.map +1 -0
- package/lib/api/grid.d.ts +22 -0
- package/lib/api/grid.d.ts.map +1 -0
- package/lib/api/grid.js +65 -0
- package/lib/api/grid.js.map +1 -0
- package/lib/api/grid.test.d.ts +2 -0
- package/lib/api/grid.test.d.ts.map +1 -0
- package/lib/api/grid.test.js +48 -0
- package/lib/api/grid.test.js.map +1 -0
- package/lib/components/base.d.ts +53 -0
- package/lib/components/base.d.ts.map +1 -0
- package/lib/components/base.js +47 -0
- package/lib/components/base.js.map +1 -0
- package/lib/components/col.d.ts +35 -0
- package/lib/components/col.d.ts.map +1 -0
- package/lib/components/col.js +168 -0
- package/lib/components/col.js.map +1 -0
- package/lib/components/col.test.d.ts +2 -0
- package/lib/components/col.test.d.ts.map +1 -0
- package/lib/components/col.test.js +96 -0
- package/lib/components/col.test.js.map +1 -0
- package/lib/components/index.d.ts +3 -0
- package/lib/components/index.d.ts.map +1 -0
- package/lib/components/index.js +5 -0
- package/lib/components/index.js.map +1 -0
- package/lib/components/progress-bar-grid.d.ts +20 -0
- package/lib/components/progress-bar-grid.d.ts.map +1 -0
- package/lib/components/progress-bar-grid.js +44 -0
- package/lib/components/progress-bar-grid.js.map +1 -0
- package/lib/components/progress-bar-grid.test.d.ts +2 -0
- package/lib/components/progress-bar-grid.test.d.ts.map +1 -0
- package/lib/components/progress-bar-grid.test.js +101 -0
- package/lib/components/progress-bar-grid.test.js.map +1 -0
- package/lib/components/progress-bar.d.ts +26 -3
- package/lib/components/progress-bar.d.ts.map +1 -1
- package/lib/components/progress-bar.js +62 -6
- package/lib/components/progress-bar.js.map +1 -1
- package/lib/components/progress-bar.test.d.ts +2 -0
- package/lib/components/progress-bar.test.d.ts.map +1 -0
- package/lib/components/progress-bar.test.js +153 -0
- package/lib/components/progress-bar.test.js.map +1 -0
- package/lib/components/prompt.d.ts +14 -0
- package/lib/components/prompt.d.ts.map +1 -0
- package/lib/components/prompt.js +77 -0
- package/lib/components/prompt.js.map +1 -0
- package/lib/components/renderable.d.ts +42 -0
- package/lib/components/renderable.d.ts.map +1 -0
- package/lib/components/renderable.js +225 -0
- package/lib/components/renderable.js.map +1 -0
- package/lib/components/spinner.d.ts +2 -2
- package/lib/components/spinner.d.ts.map +1 -1
- package/lib/components/spinner.js +3 -1
- package/lib/components/spinner.js.map +1 -1
- package/lib/components/spinner.test.d.ts +2 -0
- package/lib/components/spinner.test.d.ts.map +1 -0
- package/lib/components/spinner.test.js +168 -0
- package/lib/components/spinner.test.js.map +1 -0
- package/lib/components/style.d.ts +16 -0
- package/lib/components/style.d.ts.map +1 -0
- package/lib/components/style.js +72 -0
- package/lib/components/style.js.map +1 -0
- package/lib/components/style.test.d.ts +2 -0
- package/lib/components/style.test.d.ts.map +1 -0
- package/lib/components/style.test.js +135 -0
- package/lib/components/style.test.js.map +1 -0
- package/lib/components/text.d.ts +24 -0
- package/lib/components/text.d.ts.map +1 -0
- package/lib/components/text.js +65 -0
- package/lib/components/text.js.map +1 -0
- package/lib/drawing/boxes.d.ts +33 -0
- package/lib/drawing/boxes.d.ts.map +1 -0
- package/lib/drawing/boxes.js +76 -0
- package/lib/drawing/boxes.js.map +1 -0
- package/lib/index.d.ts +18 -11
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +21 -10
- package/lib/index.js.map +1 -1
- package/lib/index.test.d.ts +2 -0
- package/lib/index.test.d.ts.map +1 -0
- package/lib/index.test.js +80 -0
- package/lib/index.test.js.map +1 -0
- package/lib/layout/flex.d.ts +39 -0
- package/lib/layout/flex.d.ts.map +1 -0
- package/lib/layout/flex.js +300 -0
- package/lib/layout/flex.js.map +1 -0
- package/lib/layout/flex.test.d.ts +2 -0
- package/lib/layout/flex.test.d.ts.map +1 -0
- package/lib/layout/flex.test.js +206 -0
- package/lib/layout/flex.test.js.map +1 -0
- package/lib/layout/grid.d.ts +53 -0
- package/lib/layout/grid.d.ts.map +1 -0
- package/lib/layout/grid.js +421 -0
- package/lib/layout/grid.js.map +1 -0
- package/lib/layout/grid.test.d.ts +2 -0
- package/lib/layout/grid.test.d.ts.map +1 -0
- package/lib/layout/grid.test.js +139 -0
- package/lib/layout/grid.test.js.map +1 -0
- package/lib/native/ansi.d.ts +104 -0
- package/lib/native/ansi.d.ts.map +1 -0
- package/lib/native/ansi.js +120 -0
- package/lib/native/ansi.js.map +1 -0
- package/lib/native/ansi.test.d.ts +2 -0
- package/lib/native/ansi.test.d.ts.map +1 -0
- package/lib/native/ansi.test.js +57 -0
- package/lib/native/ansi.test.js.map +1 -0
- package/lib/native/buffer.d.ts +32 -0
- package/lib/native/buffer.d.ts.map +1 -0
- package/lib/native/buffer.js +49 -0
- package/lib/native/buffer.js.map +1 -0
- package/lib/native/buffer.test.d.ts +2 -0
- package/lib/native/buffer.test.d.ts.map +1 -0
- package/lib/native/buffer.test.js +64 -0
- package/lib/native/buffer.test.js.map +1 -0
- package/lib/native/diff.d.ts +20 -0
- package/lib/native/diff.d.ts.map +1 -0
- package/lib/native/diff.js +33 -0
- package/lib/native/diff.js.map +1 -0
- package/lib/native/diff.test.d.ts +2 -0
- package/lib/native/diff.test.d.ts.map +1 -0
- package/lib/native/diff.test.js +106 -0
- package/lib/native/diff.test.js.map +1 -0
- package/lib/native/region-old.d.ts +117 -0
- package/lib/native/region-old.d.ts.map +1 -0
- package/lib/native/region-old.js +539 -0
- package/lib/native/region-old.js.map +1 -0
- package/lib/native/region-renderer.d.ts +167 -0
- package/lib/native/region-renderer.d.ts.map +1 -0
- package/lib/native/region-renderer.js +1238 -0
- package/lib/native/region-renderer.js.map +1 -0
- package/lib/native/region-simple.d.ts +44 -0
- package/lib/native/region-simple.d.ts.map +1 -0
- package/lib/native/region-simple.js +290 -0
- package/lib/native/region-simple.js.map +1 -0
- package/lib/native/region.d.ts +53 -0
- package/lib/native/region.d.ts.map +1 -0
- package/lib/native/region.js +426 -0
- package/lib/native/region.js.map +1 -0
- package/lib/native/region.test.d.ts +2 -0
- package/lib/native/region.test.d.ts.map +1 -0
- package/lib/native/region.test.js +248 -0
- package/lib/native/region.test.js.map +1 -0
- package/lib/native/throttle.d.ts +29 -0
- package/lib/native/throttle.d.ts.map +1 -0
- package/lib/native/throttle.js +57 -0
- package/lib/native/throttle.js.map +1 -0
- package/lib/native/throttle.test.d.ts +2 -0
- package/lib/native/throttle.test.d.ts.map +1 -0
- package/lib/native/throttle.test.js +86 -0
- package/lib/native/throttle.test.js.map +1 -0
- package/lib/native.d.ts +5 -11
- package/lib/native.d.ts.map +1 -1
- package/lib/native.js +8 -64
- package/lib/native.js.map +1 -1
- package/lib/region.d.ts +48 -5
- package/lib/region.d.ts.map +1 -1
- package/lib/region.js +474 -36
- package/lib/region.js.map +1 -1
- package/lib/region.test.d.ts +2 -0
- package/lib/region.test.d.ts.map +1 -0
- package/lib/region.test.js +227 -0
- package/lib/region.test.js.map +1 -0
- package/lib/region.visual.test.d.ts +2 -0
- package/lib/region.visual.test.d.ts.map +1 -0
- package/lib/region.visual.test.js +55 -0
- package/lib/region.visual.test.js.map +1 -0
- package/lib/test-helpers/capturable-terminal.d.ts +61 -0
- package/lib/test-helpers/capturable-terminal.d.ts.map +1 -0
- package/lib/test-helpers/capturable-terminal.js +113 -0
- package/lib/test-helpers/capturable-terminal.js.map +1 -0
- package/lib/test-helpers/capturable-terminal.test.d.ts +2 -0
- package/lib/test-helpers/capturable-terminal.test.d.ts.map +1 -0
- package/lib/test-helpers/capturable-terminal.test.js +45 -0
- package/lib/test-helpers/capturable-terminal.test.js.map +1 -0
- package/lib/test-helpers/mock-region.d.ts +21 -0
- package/lib/test-helpers/mock-region.d.ts.map +1 -0
- package/lib/test-helpers/mock-region.js +37 -0
- package/lib/test-helpers/mock-region.js.map +1 -0
- package/lib/test-helpers/virtual-terminal-diff-reflow.test.d.ts +2 -0
- package/lib/test-helpers/virtual-terminal-diff-reflow.test.d.ts.map +1 -0
- package/lib/test-helpers/virtual-terminal-diff-reflow.test.js +256 -0
- package/lib/test-helpers/virtual-terminal-diff-reflow.test.js.map +1 -0
- package/lib/test-helpers/virtual-terminal-flex-resize.test.d.ts +2 -0
- package/lib/test-helpers/virtual-terminal-flex-resize.test.d.ts.map +1 -0
- package/lib/test-helpers/virtual-terminal-flex-resize.test.js +438 -0
- package/lib/test-helpers/virtual-terminal-flex-resize.test.js.map +1 -0
- package/lib/test-helpers/virtual-terminal.d.ts +176 -0
- package/lib/test-helpers/virtual-terminal.d.ts.map +1 -0
- package/lib/test-helpers/virtual-terminal.js +492 -0
- package/lib/test-helpers/virtual-terminal.js.map +1 -0
- package/lib/test-helpers/virtual-terminal.test.d.ts +2 -0
- package/lib/test-helpers/virtual-terminal.test.d.ts.map +1 -0
- package/lib/test-helpers/virtual-terminal.test.js +219 -0
- package/lib/test-helpers/virtual-terminal.test.js.map +1 -0
- package/lib/ts/components/spinner.test.d.ts +2 -0
- package/lib/ts/components/spinner.test.d.ts.map +1 -0
- package/lib/ts/components/spinner.test.js +168 -0
- package/lib/ts/components/spinner.test.js.map +1 -0
- package/lib/ts/utils/colors.test.d.ts +2 -0
- package/lib/ts/utils/colors.test.d.ts.map +1 -0
- package/lib/ts/utils/colors.test.js +87 -0
- package/lib/ts/utils/colors.test.js.map +1 -0
- package/lib/types.d.ts +8 -2
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js.map +1 -1
- package/lib/utils/colors-simple.d.ts +51 -0
- package/lib/utils/colors-simple.d.ts.map +1 -0
- package/lib/utils/colors-simple.js +59 -0
- package/lib/utils/colors-simple.js.map +1 -0
- package/lib/utils/colors.d.ts +1 -1
- package/lib/utils/colors.d.ts.map +1 -1
- package/lib/utils/colors.js.map +1 -1
- package/lib/utils/colors.test.d.ts +2 -0
- package/lib/utils/colors.test.d.ts.map +1 -0
- package/lib/utils/colors.test.js +87 -0
- package/lib/utils/colors.test.js.map +1 -0
- package/lib/utils/cursor-position.d.ts +22 -0
- package/lib/utils/cursor-position.d.ts.map +1 -0
- package/lib/utils/cursor-position.js +139 -0
- package/lib/utils/cursor-position.js.map +1 -0
- package/lib/utils/debug-log.d.ts +2 -0
- package/lib/utils/debug-log.d.ts.map +1 -0
- package/lib/utils/debug-log.js +36 -0
- package/lib/utils/debug-log.js.map +1 -0
- package/lib/utils/terminal.d.ts +27 -0
- package/lib/utils/terminal.d.ts.map +1 -0
- package/lib/utils/terminal.js +116 -0
- package/lib/utils/terminal.js.map +1 -0
- package/lib/utils/text.d.ts +21 -0
- package/lib/utils/text.d.ts.map +1 -0
- package/lib/utils/text.js +82 -0
- package/lib/utils/text.js.map +1 -0
- package/lib/utils/wait-for-spacebar.d.ts +10 -0
- package/lib/utils/wait-for-spacebar.d.ts.map +1 -0
- package/lib/utils/wait-for-spacebar.js +71 -0
- package/lib/utils/wait-for-spacebar.js.map +1 -0
- package/package.json +31 -28
- package/.cursor/plan.md +0 -952
- package/TESTING.md +0 -102
- package/build.zig +0 -100
- package/examples/basic-progress.ts +0 -21
- package/examples/multi-lane.ts +0 -29
- package/examples/spinner.ts +0 -20
- package/examples/test-basic.ts +0 -23
- package/src/ts/components/progress-bar.ts +0 -53
- package/src/ts/components/spinner.ts +0 -56
- package/src/ts/index.ts +0 -37
- package/src/ts/native.ts +0 -86
- package/src/ts/region.ts +0 -89
- package/src/ts/types/ffi-napi.d.ts +0 -11
- package/src/ts/types/ref-napi.d.ts +0 -5
- package/src/ts/types.ts +0 -53
- package/src/ts/utils/colors.ts +0 -72
- package/src/zig/ansi.zig +0 -21
- package/src/zig/buffer.zig +0 -37
- package/src/zig/diff.zig +0 -43
- package/src/zig/region.zig +0 -292
- package/src/zig/renderer.zig +0 -92
- package/src/zig/test_ansi.zig +0 -66
- package/src/zig/test_buffer.zig +0 -82
- package/src/zig/test_diff.zig +0 -220
- package/src/zig/test_integration.zig +0 -76
- package/src/zig/test_region.zig +0 -191
- package/src/zig/test_runner.zig +0 -27
- package/src/zig/test_throttle.zig +0 -59
- package/src/zig/throttle.zig +0 -38
- package/tsconfig.json +0 -21
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
2
|
+
import { RegionRenderer } from './region-renderer';
|
|
3
|
+
describe('RegionRenderer', () => {
|
|
4
|
+
let mockStdout;
|
|
5
|
+
let writeSyncSpy;
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
writeSyncSpy = vi.fn();
|
|
8
|
+
const writeSpy = vi.fn();
|
|
9
|
+
const eventHandlers = new Map();
|
|
10
|
+
mockStdout = {
|
|
11
|
+
writeSync: writeSyncSpy,
|
|
12
|
+
write: writeSpy,
|
|
13
|
+
isTTY: true,
|
|
14
|
+
columns: 80,
|
|
15
|
+
rows: 24,
|
|
16
|
+
on: (event, handler) => {
|
|
17
|
+
if (!eventHandlers.has(event)) {
|
|
18
|
+
eventHandlers.set(event, new Set());
|
|
19
|
+
}
|
|
20
|
+
eventHandlers.get(event).add(handler);
|
|
21
|
+
return mockStdout;
|
|
22
|
+
},
|
|
23
|
+
off: (event, handler) => {
|
|
24
|
+
eventHandlers.get(event)?.delete(handler);
|
|
25
|
+
return mockStdout;
|
|
26
|
+
},
|
|
27
|
+
removeListener: (event, handler) => {
|
|
28
|
+
eventHandlers.get(event)?.delete(handler);
|
|
29
|
+
return mockStdout;
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
afterEach(() => {
|
|
34
|
+
vi.clearAllMocks();
|
|
35
|
+
});
|
|
36
|
+
describe('initialization', () => {
|
|
37
|
+
it('should create region with correct dimensions', () => {
|
|
38
|
+
const region = new RegionRenderer({
|
|
39
|
+
width: 80,
|
|
40
|
+
height: 5,
|
|
41
|
+
stdout: mockStdout,
|
|
42
|
+
disableRendering: true,
|
|
43
|
+
});
|
|
44
|
+
expect(region.getWidth()).toBe(80);
|
|
45
|
+
expect(region.getHeight()).toBe(5);
|
|
46
|
+
});
|
|
47
|
+
it('should use default values', () => {
|
|
48
|
+
const region = new RegionRenderer({
|
|
49
|
+
stdout: mockStdout,
|
|
50
|
+
disableRendering: true,
|
|
51
|
+
});
|
|
52
|
+
expect(region.getWidth()).toBeGreaterThan(0);
|
|
53
|
+
expect(region.getHeight()).toBe(1);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe('setLine', () => {
|
|
57
|
+
it('should expand automatically when needed', () => {
|
|
58
|
+
const region = new RegionRenderer({
|
|
59
|
+
width: 80,
|
|
60
|
+
height: 1,
|
|
61
|
+
stdout: mockStdout,
|
|
62
|
+
disableRendering: true,
|
|
63
|
+
});
|
|
64
|
+
region.setLine(1, 'line1');
|
|
65
|
+
expect(region.getHeight()).toBe(1);
|
|
66
|
+
region.setLine(5, 'line5');
|
|
67
|
+
expect(region.getHeight()).toBeGreaterThanOrEqual(5);
|
|
68
|
+
});
|
|
69
|
+
it('should reject line 0', () => {
|
|
70
|
+
const region = new RegionRenderer({
|
|
71
|
+
stdout: mockStdout,
|
|
72
|
+
disableRendering: true,
|
|
73
|
+
});
|
|
74
|
+
expect(() => region.setLine(0, 'invalid')).toThrow('Line numbers start at 1');
|
|
75
|
+
});
|
|
76
|
+
it('should handle empty string', () => {
|
|
77
|
+
const region = new RegionRenderer({
|
|
78
|
+
width: 80,
|
|
79
|
+
height: 2,
|
|
80
|
+
stdout: mockStdout,
|
|
81
|
+
disableRendering: true,
|
|
82
|
+
});
|
|
83
|
+
region.setLine(1, 'test');
|
|
84
|
+
region.setLine(1, '');
|
|
85
|
+
// Should not throw and should clear the line
|
|
86
|
+
expect(region.getHeight()).toBeGreaterThanOrEqual(1);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
describe('set', () => {
|
|
90
|
+
it('should split content by newlines correctly', () => {
|
|
91
|
+
const region = new RegionRenderer({
|
|
92
|
+
width: 80,
|
|
93
|
+
height: 1,
|
|
94
|
+
stdout: mockStdout,
|
|
95
|
+
disableRendering: true,
|
|
96
|
+
});
|
|
97
|
+
region.set('line1\nline2\nline3');
|
|
98
|
+
expect(region.getHeight()).toBeGreaterThanOrEqual(3);
|
|
99
|
+
});
|
|
100
|
+
it('should handle empty content', () => {
|
|
101
|
+
const region = new RegionRenderer({
|
|
102
|
+
width: 80,
|
|
103
|
+
height: 1,
|
|
104
|
+
stdout: mockStdout,
|
|
105
|
+
disableRendering: true,
|
|
106
|
+
});
|
|
107
|
+
region.set('');
|
|
108
|
+
expect(region.getHeight()).toBeGreaterThanOrEqual(1);
|
|
109
|
+
});
|
|
110
|
+
it('should handle single line (no newline)', () => {
|
|
111
|
+
const region = new RegionRenderer({
|
|
112
|
+
width: 80,
|
|
113
|
+
height: 1,
|
|
114
|
+
stdout: mockStdout,
|
|
115
|
+
disableRendering: true,
|
|
116
|
+
});
|
|
117
|
+
region.set('single line');
|
|
118
|
+
expect(region.getHeight()).toBeGreaterThanOrEqual(1);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
describe('clearLine', () => {
|
|
122
|
+
it('should clear individual lines', () => {
|
|
123
|
+
const region = new RegionRenderer({
|
|
124
|
+
width: 80,
|
|
125
|
+
height: 3,
|
|
126
|
+
stdout: mockStdout,
|
|
127
|
+
disableRendering: true,
|
|
128
|
+
});
|
|
129
|
+
region.setLine(2, 'test');
|
|
130
|
+
region.clearLine(2);
|
|
131
|
+
// Should not throw
|
|
132
|
+
expect(region.getHeight()).toBeGreaterThanOrEqual(2);
|
|
133
|
+
});
|
|
134
|
+
it('should reject line 0', () => {
|
|
135
|
+
const region = new RegionRenderer({
|
|
136
|
+
stdout: mockStdout,
|
|
137
|
+
disableRendering: true,
|
|
138
|
+
});
|
|
139
|
+
expect(() => region.clearLine(0)).toThrow('Line numbers start at 1');
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
describe('clear', () => {
|
|
143
|
+
it('should clear all lines', () => {
|
|
144
|
+
const region = new RegionRenderer({
|
|
145
|
+
width: 80,
|
|
146
|
+
height: 3,
|
|
147
|
+
stdout: mockStdout,
|
|
148
|
+
disableRendering: true,
|
|
149
|
+
});
|
|
150
|
+
region.setLine(1, 'line1');
|
|
151
|
+
region.setLine(2, 'line2');
|
|
152
|
+
region.setLine(3, 'line3');
|
|
153
|
+
region.clear();
|
|
154
|
+
// Should not throw
|
|
155
|
+
expect(region.getHeight()).toBeGreaterThanOrEqual(3);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
describe('setThrottleFps', () => {
|
|
159
|
+
it('should set FPS correctly', () => {
|
|
160
|
+
const region = new RegionRenderer({
|
|
161
|
+
stdout: mockStdout,
|
|
162
|
+
disableRendering: true,
|
|
163
|
+
});
|
|
164
|
+
// setThrottleFps doesn't exist on native region - throttle is managed internally
|
|
165
|
+
// The high-level TerminalRegion has setThrottle() which is a no-op for now
|
|
166
|
+
// Just verify the region exists
|
|
167
|
+
expect(region).toBeDefined();
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
describe('multiple setLine calls', () => {
|
|
171
|
+
it('should handle multiple updates', () => {
|
|
172
|
+
const region = new RegionRenderer({
|
|
173
|
+
width: 80,
|
|
174
|
+
height: 1,
|
|
175
|
+
stdout: mockStdout,
|
|
176
|
+
disableRendering: true,
|
|
177
|
+
});
|
|
178
|
+
region.setLine(1, 'line1');
|
|
179
|
+
region.setLine(2, 'line2');
|
|
180
|
+
region.setLine(3, 'line3');
|
|
181
|
+
expect(region.getHeight()).toBeGreaterThanOrEqual(3);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
describe('destroy', () => {
|
|
185
|
+
it('should clean up resources', () => {
|
|
186
|
+
const region = new RegionRenderer({
|
|
187
|
+
stdout: mockStdout,
|
|
188
|
+
disableRendering: true,
|
|
189
|
+
});
|
|
190
|
+
region.setLine(1, 'test');
|
|
191
|
+
region.destroy();
|
|
192
|
+
// Should not throw
|
|
193
|
+
expect(region).toBeDefined();
|
|
194
|
+
});
|
|
195
|
+
it('should automatically call destroy on process exit', () => {
|
|
196
|
+
// Track process.once calls to capture exit handlers
|
|
197
|
+
const exitHandlers = [];
|
|
198
|
+
const sigintHandlers = [];
|
|
199
|
+
const sigtermHandlers = [];
|
|
200
|
+
const originalOnce = process.once.bind(process);
|
|
201
|
+
const onceSpy = vi.spyOn(process, 'once').mockImplementation((event, handler) => {
|
|
202
|
+
const eventStr = String(event);
|
|
203
|
+
if (eventStr === 'exit') {
|
|
204
|
+
exitHandlers.push(handler);
|
|
205
|
+
}
|
|
206
|
+
else if (eventStr === 'SIGINT') {
|
|
207
|
+
sigintHandlers.push(handler);
|
|
208
|
+
}
|
|
209
|
+
else if (eventStr === 'SIGTERM') {
|
|
210
|
+
sigtermHandlers.push(handler);
|
|
211
|
+
}
|
|
212
|
+
// Call original to actually register the handler
|
|
213
|
+
return originalOnce(event, handler);
|
|
214
|
+
});
|
|
215
|
+
// Create a region (this will set up exit handlers)
|
|
216
|
+
const region = new RegionRenderer({
|
|
217
|
+
stdout: mockStdout,
|
|
218
|
+
disableRendering: false, // Need rendering enabled to set up exit handlers
|
|
219
|
+
});
|
|
220
|
+
// Spy on destroy method
|
|
221
|
+
const destroySpy = vi.spyOn(region, 'destroy');
|
|
222
|
+
// Verify exit handlers were registered
|
|
223
|
+
expect(exitHandlers.length).toBeGreaterThan(0);
|
|
224
|
+
expect(sigintHandlers.length).toBeGreaterThan(0);
|
|
225
|
+
expect(sigtermHandlers.length).toBeGreaterThan(0);
|
|
226
|
+
// Manually trigger exit handler (simulating process exit)
|
|
227
|
+
exitHandlers.forEach(handler => handler());
|
|
228
|
+
// Verify destroy was called
|
|
229
|
+
expect(destroySpy).toHaveBeenCalled();
|
|
230
|
+
// Clean up
|
|
231
|
+
onceSpy.mockRestore();
|
|
232
|
+
destroySpy.mockRestore();
|
|
233
|
+
});
|
|
234
|
+
it('should not set up exit handlers when disableRendering is true', () => {
|
|
235
|
+
const onceSpy = vi.spyOn(process, 'once');
|
|
236
|
+
const region = new RegionRenderer({
|
|
237
|
+
stdout: mockStdout,
|
|
238
|
+
disableRendering: true, // Exit handlers should NOT be set up
|
|
239
|
+
});
|
|
240
|
+
// Verify exit handlers were NOT registered
|
|
241
|
+
// (once should not have been called with 'exit', 'SIGINT', or 'SIGTERM')
|
|
242
|
+
const exitCalls = onceSpy.mock.calls.filter(call => call[0] === 'exit' || call[0] === 'SIGINT' || call[0] === 'SIGTERM');
|
|
243
|
+
expect(exitCalls.length).toBe(0);
|
|
244
|
+
onceSpy.mockRestore();
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
//# sourceMappingURL=region.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"region.test.js","sourceRoot":"","sources":["../../src/native/region.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Throttle class for limiting render frequency.
|
|
3
|
+
* Uses high-resolution time (hrtime) for accurate throttling.
|
|
4
|
+
*/
|
|
5
|
+
export declare class Throttle {
|
|
6
|
+
private lastFrameTime;
|
|
7
|
+
private minFrameInterval;
|
|
8
|
+
private fps;
|
|
9
|
+
constructor(fps?: number);
|
|
10
|
+
/**
|
|
11
|
+
* Update the target FPS
|
|
12
|
+
*/
|
|
13
|
+
setFps(fps: number): void;
|
|
14
|
+
/**
|
|
15
|
+
* Check if we should render now based on throttle settings.
|
|
16
|
+
* Returns true if enough time has passed since last render.
|
|
17
|
+
*/
|
|
18
|
+
shouldRender(): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Get time remaining until next frame can be rendered (in milliseconds).
|
|
21
|
+
* Useful for scheduling the next render.
|
|
22
|
+
*/
|
|
23
|
+
timeUntilNextFrame(): number;
|
|
24
|
+
/**
|
|
25
|
+
* Reset the throttle (useful for testing or after long pauses)
|
|
26
|
+
*/
|
|
27
|
+
reset(): void;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=throttle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"throttle.d.ts","sourceRoot":"","sources":["../../src/native/throttle.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,aAAa,CAAc;IACnC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,GAAG,CAAS;gBAER,GAAG,GAAE,MAAW;IAM5B;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAKzB;;;OAGG;IACH,YAAY,IAAI,OAAO;IAYvB;;;OAGG;IACH,kBAAkB,IAAI,MAAM;IAa5B;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Throttling for frame rate limiting - TypeScript implementation
|
|
2
|
+
// Optimized for Node.js high-resolution timing
|
|
3
|
+
/**
|
|
4
|
+
* Throttle class for limiting render frequency.
|
|
5
|
+
* Uses high-resolution time (hrtime) for accurate throttling.
|
|
6
|
+
*/
|
|
7
|
+
export class Throttle {
|
|
8
|
+
lastFrameTime = 0n;
|
|
9
|
+
minFrameInterval; // nanoseconds
|
|
10
|
+
fps;
|
|
11
|
+
constructor(fps = 60) {
|
|
12
|
+
this.fps = fps;
|
|
13
|
+
// Calculate interval in nanoseconds: 1 second / fps
|
|
14
|
+
this.minFrameInterval = BigInt(Math.floor(1_000_000_000 / fps));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Update the target FPS
|
|
18
|
+
*/
|
|
19
|
+
setFps(fps) {
|
|
20
|
+
this.fps = fps;
|
|
21
|
+
this.minFrameInterval = BigInt(Math.floor(1_000_000_000 / fps));
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Check if we should render now based on throttle settings.
|
|
25
|
+
* Returns true if enough time has passed since last render.
|
|
26
|
+
*/
|
|
27
|
+
shouldRender() {
|
|
28
|
+
const now = process.hrtime.bigint();
|
|
29
|
+
const elapsed = now - this.lastFrameTime;
|
|
30
|
+
if (elapsed >= this.minFrameInterval) {
|
|
31
|
+
this.lastFrameTime = now;
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get time remaining until next frame can be rendered (in milliseconds).
|
|
38
|
+
* Useful for scheduling the next render.
|
|
39
|
+
*/
|
|
40
|
+
timeUntilNextFrame() {
|
|
41
|
+
const now = process.hrtime.bigint();
|
|
42
|
+
const elapsed = now - this.lastFrameTime;
|
|
43
|
+
const remaining = this.minFrameInterval - elapsed;
|
|
44
|
+
if (remaining <= 0) {
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
// Convert nanoseconds to milliseconds
|
|
48
|
+
return Number(remaining) / 1_000_000;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Reset the throttle (useful for testing or after long pauses)
|
|
52
|
+
*/
|
|
53
|
+
reset() {
|
|
54
|
+
this.lastFrameTime = 0n;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=throttle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"throttle.js","sourceRoot":"","sources":["../../src/native/throttle.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,+CAA+C;AAE/C;;;GAGG;AACH,MAAM,OAAO,QAAQ;IACX,aAAa,GAAW,EAAE,CAAC;IAC3B,gBAAgB,CAAS,CAAC,cAAc;IACxC,GAAG,CAAS;IAEpB,YAAY,MAAc,EAAE;QAC1B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,oDAAoD;QACpD,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,GAAG,CAAC,CAAC,CAAC;IAClE,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,GAAW;QAChB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,GAAG,CAAC,CAAC,CAAC;IAClE,CAAC;IAED;;;OAGG;IACH,YAAY;QACV,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC;QAEzC,IAAI,OAAO,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACrC,IAAI,CAAC,aAAa,GAAG,GAAG,CAAC;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;OAGG;IACH,kBAAkB;QAChB,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC;QACzC,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC;QAElD,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;YACnB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,sCAAsC;QACtC,OAAO,MAAM,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;IAC1B,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"throttle.test.d.ts","sourceRoot":"","sources":["../../src/native/throttle.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { Throttle } from './throttle';
|
|
3
|
+
describe('Throttle', () => {
|
|
4
|
+
describe('initialization', () => {
|
|
5
|
+
it('should initialize with correct FPS', () => {
|
|
6
|
+
const throttle = new Throttle(60);
|
|
7
|
+
expect(throttle['fps']).toBe(60);
|
|
8
|
+
expect(throttle['minFrameInterval']).toBeGreaterThan(0n);
|
|
9
|
+
});
|
|
10
|
+
it('should calculate correct interval for 60 FPS', () => {
|
|
11
|
+
const throttle = new Throttle(60);
|
|
12
|
+
// 1 second / 60 = ~16.67ms = ~16,666,667 nanoseconds
|
|
13
|
+
const expectedInterval = BigInt(Math.floor(1_000_000_000 / 60));
|
|
14
|
+
expect(throttle['minFrameInterval']).toBe(expectedInterval);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
describe('setFps', () => {
|
|
18
|
+
it('should change FPS correctly', () => {
|
|
19
|
+
const throttle = new Throttle(30);
|
|
20
|
+
throttle.setFps(120);
|
|
21
|
+
expect(throttle['fps']).toBe(120);
|
|
22
|
+
const expectedInterval = BigInt(Math.floor(1_000_000_000 / 120));
|
|
23
|
+
expect(throttle['minFrameInterval']).toBe(expectedInterval);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
describe('shouldRender', () => {
|
|
27
|
+
it('should allow first frame', () => {
|
|
28
|
+
const throttle = new Throttle(60);
|
|
29
|
+
const should = throttle.shouldRender();
|
|
30
|
+
expect(should).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
it('should respect interval and block immediate second frame', () => {
|
|
33
|
+
const throttle = new Throttle(1000); // 1 FPS = 1 second interval
|
|
34
|
+
throttle.shouldRender(); // First frame
|
|
35
|
+
// Immediately after, should not render (hrtime has nanosecond precision)
|
|
36
|
+
const should = throttle.shouldRender();
|
|
37
|
+
expect(should).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
it('should allow render after interval passes', async () => {
|
|
40
|
+
const throttle = new Throttle(10); // 10 FPS = 100ms interval
|
|
41
|
+
throttle.shouldRender(); // First frame
|
|
42
|
+
// Wait for interval to pass
|
|
43
|
+
await new Promise(resolve => setTimeout(resolve, 110));
|
|
44
|
+
const should = throttle.shouldRender();
|
|
45
|
+
expect(should).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
describe('timeUntilNextFrame', () => {
|
|
49
|
+
it('should calculate remaining time correctly', () => {
|
|
50
|
+
const throttle = new Throttle(10); // 10 FPS = 100ms interval
|
|
51
|
+
throttle.shouldRender();
|
|
52
|
+
const remaining = throttle.timeUntilNextFrame();
|
|
53
|
+
expect(remaining).toBeGreaterThan(0);
|
|
54
|
+
expect(remaining).toBeLessThanOrEqual(100); // Should be <= 100ms
|
|
55
|
+
});
|
|
56
|
+
it('should return 0 if interval has passed', async () => {
|
|
57
|
+
const throttle = new Throttle(10);
|
|
58
|
+
throttle.shouldRender();
|
|
59
|
+
await new Promise(resolve => setTimeout(resolve, 110));
|
|
60
|
+
const remaining = throttle.timeUntilNextFrame();
|
|
61
|
+
expect(remaining).toBe(0);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
describe('edge cases', () => {
|
|
65
|
+
it('should handle very high FPS', () => {
|
|
66
|
+
const throttle = new Throttle(1000); // 1000 FPS
|
|
67
|
+
expect(throttle['fps']).toBe(1000);
|
|
68
|
+
expect(throttle['minFrameInterval']).toBeGreaterThan(0n);
|
|
69
|
+
});
|
|
70
|
+
it('should handle very low FPS', () => {
|
|
71
|
+
const throttle = new Throttle(1); // 1 FPS
|
|
72
|
+
expect(throttle['fps']).toBe(1);
|
|
73
|
+
const expectedInterval = BigInt(1_000_000_000); // 1 second
|
|
74
|
+
expect(throttle['minFrameInterval']).toBe(expectedInterval);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
describe('reset', () => {
|
|
78
|
+
it('should reset the throttle', () => {
|
|
79
|
+
const throttle = new Throttle(60);
|
|
80
|
+
throttle.shouldRender();
|
|
81
|
+
throttle.reset();
|
|
82
|
+
expect(throttle['lastFrameTime']).toBe(0n);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
//# sourceMappingURL=throttle.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"throttle.test.js","sourceRoot":"","sources":["../../src/native/throttle.test.ts"],"names":[],"mappings":"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"}
|
package/lib/native.d.ts
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
clearLine(handle: number, lineNumber: number): void;
|
|
7
|
-
clearRegion(handle: number): void;
|
|
8
|
-
flush(handle: number): void;
|
|
9
|
-
setThrottleFps(handle: number, fps: number): void;
|
|
10
|
-
}
|
|
11
|
-
export declare const native: NativeRegion;
|
|
1
|
+
export { RegionRenderer as NativeRegion } from './native/region-renderer';
|
|
2
|
+
export * from './native/diff';
|
|
3
|
+
export * from './native/ansi';
|
|
4
|
+
export * from './native/buffer';
|
|
5
|
+
export * from './native/throttle';
|
|
12
6
|
//# sourceMappingURL=native.d.ts.map
|
package/lib/native.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../src/
|
|
1
|
+
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,IAAI,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC1E,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC"}
|
package/lib/native.js
CHANGED
|
@@ -1,65 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const platform = process.platform;
|
|
10
|
-
if (platform === 'darwin') {
|
|
11
|
-
return join(__dirname, '../../zig-out/lib/libechokit.dylib');
|
|
12
|
-
}
|
|
13
|
-
else if (platform === 'win32') {
|
|
14
|
-
return join(__dirname, '../../zig-out/lib/echokit.dll');
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
return join(__dirname, '../../zig-out/lib/libechokit.so');
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
// Load the Zig library using FFI
|
|
21
|
-
const lib = Library(getLibraryPath(), {
|
|
22
|
-
create_region: ['uint64', ['uint32', 'uint32', 'uint32', 'uint32']],
|
|
23
|
-
destroy_region: ['void', ['uint64']],
|
|
24
|
-
set_line: ['void', ['uint64', 'uint32', 'pointer', 'size_t']],
|
|
25
|
-
set: ['void', ['uint64', 'pointer', 'size_t']],
|
|
26
|
-
clear_line: ['void', ['uint64', 'uint32']],
|
|
27
|
-
clear_region: ['void', ['uint64']],
|
|
28
|
-
flush: ['void', ['uint64']],
|
|
29
|
-
set_throttle_fps: ['void', ['uint64', 'uint32']],
|
|
30
|
-
});
|
|
31
|
-
export const native = {
|
|
32
|
-
createRegion: (x, y, width, height) => {
|
|
33
|
-
return Number(lib.create_region(x, y, width, height));
|
|
34
|
-
},
|
|
35
|
-
destroyRegion: (handle) => {
|
|
36
|
-
lib.destroy_region(BigInt(handle));
|
|
37
|
-
},
|
|
38
|
-
setLine: (handle, lineNumber, content) => {
|
|
39
|
-
const buf = Buffer.from(content, 'utf8');
|
|
40
|
-
// Allocate a buffer and copy the string data
|
|
41
|
-
const ptr = ref.alloc(buf.length);
|
|
42
|
-
buf.copy(ptr);
|
|
43
|
-
lib.set_line(BigInt(handle), lineNumber, ptr, buf.length);
|
|
44
|
-
},
|
|
45
|
-
set: (handle, content) => {
|
|
46
|
-
const buf = Buffer.from(content, 'utf8');
|
|
47
|
-
// Allocate a buffer and copy the string data
|
|
48
|
-
const ptr = ref.alloc(buf.length);
|
|
49
|
-
buf.copy(ptr);
|
|
50
|
-
lib.set(BigInt(handle), ptr, buf.length);
|
|
51
|
-
},
|
|
52
|
-
clearLine: (handle, lineNumber) => {
|
|
53
|
-
lib.clear_line(BigInt(handle), lineNumber);
|
|
54
|
-
},
|
|
55
|
-
clearRegion: (handle) => {
|
|
56
|
-
lib.clear_region(BigInt(handle));
|
|
57
|
-
},
|
|
58
|
-
flush: (handle) => {
|
|
59
|
-
lib.flush(BigInt(handle));
|
|
60
|
-
},
|
|
61
|
-
setThrottleFps: (handle, fps) => {
|
|
62
|
-
lib.set_throttle_fps(BigInt(handle), fps);
|
|
63
|
-
},
|
|
64
|
-
};
|
|
1
|
+
// Pure TypeScript implementation - no FFI dependencies
|
|
2
|
+
// This file is kept for backward compatibility but now just re-exports
|
|
3
|
+
// the native TypeScript implementation
|
|
4
|
+
export { RegionRenderer as NativeRegion } from './native/region-renderer';
|
|
5
|
+
export * from './native/diff';
|
|
6
|
+
export * from './native/ansi';
|
|
7
|
+
export * from './native/buffer';
|
|
8
|
+
export * from './native/throttle';
|
|
65
9
|
//# sourceMappingURL=native.js.map
|
package/lib/native.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native.js","sourceRoot":"","sources":["../src/
|
|
1
|
+
{"version":3,"file":"native.js","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,uEAAuE;AACvE,uCAAuC;AAEvC,OAAO,EAAE,cAAc,IAAI,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC1E,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC"}
|
package/lib/region.d.ts
CHANGED
|
@@ -1,17 +1,60 @@
|
|
|
1
|
-
import type { RegionOptions, LineContent } from './types
|
|
1
|
+
import type { RegionOptions, LineContent } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* TerminalRegion - High-level API for terminal region management
|
|
4
|
+
*
|
|
5
|
+
* This is the public API that wraps the low-level RegionRenderer.
|
|
6
|
+
* It adds component orchestration, grid layout, and styling support.
|
|
7
|
+
*/
|
|
2
8
|
export declare class TerminalRegion {
|
|
3
|
-
private
|
|
9
|
+
private renderer;
|
|
4
10
|
private _width;
|
|
5
11
|
private _height;
|
|
12
|
+
private allComponentDescriptors;
|
|
13
|
+
private regionLines;
|
|
14
|
+
private isReRendering;
|
|
6
15
|
constructor(options?: RegionOptions);
|
|
7
16
|
get width(): number;
|
|
8
17
|
get height(): number;
|
|
18
|
+
getLine(lineNumber: number): string;
|
|
19
|
+
/**
|
|
20
|
+
* Set a single line (1-based line numbers)
|
|
21
|
+
*
|
|
22
|
+
* Note: With auto-wrap disabled globally, we manage all wrapping ourselves.
|
|
23
|
+
* This method sets a single line - if content needs to wrap, it should
|
|
24
|
+
* be handled by the component layer (grid, style, etc.) before calling this.
|
|
25
|
+
* Content that exceeds the region width will be truncated by the terminal.
|
|
26
|
+
*
|
|
27
|
+
* The region will automatically expand if lineNumber exceeds current height.
|
|
28
|
+
*/
|
|
9
29
|
setLine(lineNumber: number, content: string | LineContent): void;
|
|
10
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Set content in the region, replacing all existing content.
|
|
32
|
+
* This always does a full replace - if the new content is the same length,
|
|
33
|
+
* it will overwrite the existing lines. If it's a different length, it will
|
|
34
|
+
* resize the region accordingly.
|
|
35
|
+
*/
|
|
36
|
+
set(content: string | LineContent[] | any, ...additionalLines: any[]): void;
|
|
37
|
+
/**
|
|
38
|
+
* Add content to the region, appending it after existing content.
|
|
39
|
+
* This is useful for adding multiple sections without overwriting previous content.
|
|
40
|
+
*/
|
|
41
|
+
add(content: string | LineContent[] | any, ...additionalLines: any[]): void;
|
|
11
42
|
clearLine(lineNumber: number): void;
|
|
12
43
|
clear(): void;
|
|
13
|
-
flush(): void
|
|
44
|
+
flush(): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Re-render the last content that was set
|
|
47
|
+
* This re-renders all components (grid) with the current width
|
|
48
|
+
* Used by resize handler and keep-alive to prevent auto-reflow
|
|
49
|
+
* The region orchestrates this - components don't manage their own re-rendering
|
|
50
|
+
*
|
|
51
|
+
* CRITICAL: Re-renders the entire region, including:
|
|
52
|
+
* - Component lines (grid)
|
|
53
|
+
* - Static lines (waitForSpacebar, whitespace)
|
|
54
|
+
* This ensures everything is in the correct position
|
|
55
|
+
*/
|
|
56
|
+
reRenderLastContent(): void;
|
|
14
57
|
setThrottle(fps: number): void;
|
|
15
|
-
destroy(): void
|
|
58
|
+
destroy(clearFirst?: boolean): Promise<void>;
|
|
16
59
|
}
|
|
17
60
|
//# sourceMappingURL=region.d.ts.map
|
package/lib/region.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"region.d.ts","sourceRoot":"","sources":["../src/
|
|
1
|
+
{"version":3,"file":"region.d.ts","sourceRoot":"","sources":["../src/region.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAI1D;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;IAGxB,OAAO,CAAC,uBAAuB,CAAa;IAG5C,OAAO,CAAC,WAAW,CAAkF;IAErG,OAAO,CAAC,aAAa,CAAkB;gBAE3B,OAAO,GAAE,aAAkB;IAwBvC,IAAI,KAAK,IAAI,MAAM,CAIlB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAInC;;;;;;;;;OASG;IACH,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAgChE;;;;;OAKG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,GAAG,GAAG,EAAE,GAAG,eAAe,EAAE,GAAG,EAAE,GAAG,IAAI;IAqJ3E;;;OAGG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,GAAG,GAAG,EAAE,GAAG,eAAe,EAAE,GAAG,EAAE,GAAG,IAAI;IAuL3E,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAOnC,KAAK,IAAI,IAAI;IAIP,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B;;;;;;;;;;OAUG;IACH,mBAAmB,IAAI,IAAI;IAiI3B,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAKxB,OAAO,CAAC,UAAU,GAAE,OAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CAG1D"}
|