tidepool 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/README.md ADDED
@@ -0,0 +1,2 @@
1
+ # 🌊 Tidepool
2
+ A TUI library written in TypeScript.
package/bun.lockb ADDED
Binary file
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TideScreen = exports.Text = exports.Box = void 0;
4
+ const box_1 = require("./objects/box");
5
+ Object.defineProperty(exports, "Box", { enumerable: true, get: function () { return box_1.Box; } });
6
+ const text_1 = require("./objects/text");
7
+ Object.defineProperty(exports, "Text", { enumerable: true, get: function () { return text_1.Text; } });
8
+ const screen_1 = require("./screen");
9
+ Object.defineProperty(exports, "TideScreen", { enumerable: true, get: function () { return screen_1.TideScreen; } });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Box = void 0;
4
+ const util_1 = require("../util");
5
+ class Box {
6
+ constructor(x, y, width, height, color = 'reset', title = '', zIndex = 0) {
7
+ this.x = x;
8
+ this.y = y;
9
+ this.width = width;
10
+ this.height = height;
11
+ this.color = color;
12
+ this.title = title;
13
+ this.contents = [];
14
+ this.zIndex = zIndex;
15
+ }
16
+ addContent(content) {
17
+ this.contents.push(content);
18
+ }
19
+ clear(screen) {
20
+ for (let i = this.y; i < this.y + this.height; i++) {
21
+ for (let j = this.x; j < this.x + this.width; j++) {
22
+ screen[i][j] = ' ';
23
+ }
24
+ }
25
+ }
26
+ draw(screen) {
27
+ this.clear(screen);
28
+ const colorCode = (0, util_1.getColorCode)(this.color);
29
+ const titleColorCode = (0, util_1.getColorCode)('magenta');
30
+ for (let i = this.x + 1; i < this.x + this.width - 1; i++) {
31
+ screen[this.y][i] = `${colorCode}─\x1b[0m`;
32
+ }
33
+ for (let i = this.x + 1; i < this.x + this.width - 1; i++) {
34
+ screen[this.y + this.height - 1][i] = `${colorCode}─\x1b[0m`;
35
+ }
36
+ for (let i = this.y + 1; i < this.y + this.height - 1; i++) {
37
+ screen[i][this.x] = `${colorCode}│\x1b[0m`;
38
+ screen[i][this.x + this.width - 1] = `${colorCode}│\x1b[0m`;
39
+ }
40
+ screen[this.y][this.x] = `${colorCode}┌\x1b[0m`;
41
+ screen[this.y][this.x + this.width - 1] = `${colorCode}┐\x1b[0m`;
42
+ screen[this.y + this.height - 1][this.x] = `${colorCode}└\x1b[0m`;
43
+ screen[this.y + this.height - 1][this.x + this.width - 1] = `${colorCode}┘\x1b[0m`;
44
+ if (this.title) {
45
+ const titlePosition = Math.max(this.x + 2, Math.min(this.x + this.width - 2 - this.title.length, this.x + 2));
46
+ for (let i = 0; i < this.title.length; i++) {
47
+ if (titlePosition + i < screen[0].length && this.y < screen.length) {
48
+ screen[this.y][titlePosition + i] = `${titleColorCode}${this.title[i]}\x1b[0m`;
49
+ }
50
+ }
51
+ }
52
+ for (let content of this.contents) {
53
+ content.draw(screen, this.x + 1, this.y + 1, this.width - 2);
54
+ }
55
+ }
56
+ move(dx, dy) {
57
+ this.x += dx;
58
+ this.y += dy;
59
+ }
60
+ }
61
+ exports.Box = Box;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Text = void 0;
4
+ const util_1 = require("../util");
5
+ class Text {
6
+ constructor(x, y, text, color = 'reset', zIndex = 0) {
7
+ this.relativeX = x;
8
+ this.relativeY = y;
9
+ this.text = text;
10
+ this.color = color;
11
+ this.zIndex = zIndex;
12
+ }
13
+ draw(screen, boxX, boxY, boxWidth) {
14
+ const colorCode = (0, util_1.getColorCode)(this.color);
15
+ const lines = (0, util_1.wrapText)(this.text, boxWidth);
16
+ for (let i = 0; i < lines.length; i++) {
17
+ const line = lines[i];
18
+ for (let j = 0; j < line.length; j++) {
19
+ const screenX = boxX + this.relativeX + j;
20
+ const screenY = boxY + this.relativeY + i;
21
+ if (screenX < screen[0].length && screenY < screen.length) {
22
+ screen[screenY][screenX] = `${colorCode}${line[j]}\x1b[0m`;
23
+ }
24
+ }
25
+ }
26
+ }
27
+ }
28
+ exports.Text = Text;
package/dist/screen.js ADDED
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TideScreen = void 0;
4
+ class TideScreen {
5
+ constructor(width, height) {
6
+ this.fps = null;
7
+ this.updateFunction = null;
8
+ this.width = width;
9
+ this.height = height;
10
+ this.screen = Array.from({ length: height }, () => Array(width).fill(' '));
11
+ this.buffer = Array.from({ length: height }, () => Array(width).fill(' '));
12
+ this.components = [];
13
+ }
14
+ clearScreen() {
15
+ this.screen = Array.from({ length: this.height }, () => Array(this.width).fill(' '));
16
+ }
17
+ clearBuffer() {
18
+ this.buffer = Array.from({ length: this.height }, () => Array(this.width).fill(' '));
19
+ }
20
+ addComponent(component) {
21
+ this.components.push(component);
22
+ }
23
+ renderBuffer() {
24
+ this.clearBuffer();
25
+ this.components.sort((a, b) => b.zIndex - a.zIndex);
26
+ this.components.forEach(component => component.draw(this.buffer));
27
+ }
28
+ render() {
29
+ console.clear();
30
+ const output = this.buffer.map(row => row.join('')).join('\n');
31
+ console.log(output);
32
+ }
33
+ setUpdateFunction(fn) {
34
+ this.updateFunction = fn;
35
+ }
36
+ setFPS(fps) {
37
+ this.fps = fps;
38
+ }
39
+ renderCycle() {
40
+ if (this.fps === null) {
41
+ throw new Error("FPS must be set before starting the render cycle.");
42
+ }
43
+ const interval = 1000 / this.fps;
44
+ const loop = () => {
45
+ if (this.updateFunction) {
46
+ this.updateFunction();
47
+ }
48
+ this.renderBuffer(); // Prepare the buffer with updated content
49
+ this.render(); // Output the buffer to the screen
50
+ setTimeout(loop, interval);
51
+ };
52
+ loop();
53
+ }
54
+ }
55
+ exports.TideScreen = TideScreen;
package/dist/util.js ADDED
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getColorCode = getColorCode;
4
+ exports.wrapText = wrapText;
5
+ function getColorCode(color) {
6
+ const colors = {
7
+ reset: '\x1b[0m',
8
+ black: '\x1b[30m',
9
+ red: '\x1b[31m',
10
+ green: '\x1b[32m',
11
+ yellow: '\x1b[33m',
12
+ blue: '\x1b[34m',
13
+ magenta: '\x1b[35m',
14
+ cyan: '\x1b[36m',
15
+ white: '\x1b[37m',
16
+ };
17
+ return colors[color.toLowerCase()] || colors['reset'];
18
+ }
19
+ function wrapText(text, maxWidth) {
20
+ const lines = [];
21
+ let currentLine = '';
22
+ for (const word of text.split(' ')) {
23
+ if ((currentLine + word).length > maxWidth) {
24
+ lines.push(currentLine.trim());
25
+ currentLine = word + ' ';
26
+ }
27
+ else {
28
+ currentLine += word + ' ';
29
+ }
30
+ }
31
+ lines.push(currentLine.trim());
32
+ return lines;
33
+ }
package/package.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "tidepool",
3
+ "version": "1.0.0",
4
+ "author": "stuncs69",
5
+ "main": "dist/index.js",
6
+ "devDependencies": {
7
+ "@types/node": "^22.2.0",
8
+ "typescript": "^5.5.4"
9
+ },
10
+ "description": "A CLI rendering engine in TypeScript.",
11
+ "license": "ISC",
12
+ "scripts": {
13
+ "test": "echo \"Error: no test specified\" && exit 1"
14
+ }
15
+ }
package/src/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { Box } from "./objects/box";
2
+ import { Text } from "./objects/text";
3
+ import { TideScreen } from "./screen";
4
+
5
+ export { Box, Text, TideScreen };
@@ -0,0 +1,4 @@
1
+ export interface TideObject {
2
+ zIndex: number;
3
+ draw: Function;
4
+ }
@@ -0,0 +1,78 @@
1
+ import { TideObject } from "../interfaces";
2
+ import { getColorCode } from "../util";
3
+
4
+ export class Box implements TideObject {
5
+ x: number;
6
+ y: number;
7
+ width: number;
8
+ height: number;
9
+ color: string;
10
+ title: string;
11
+ contents: TideObject[];
12
+ zIndex: number;
13
+
14
+ constructor(x: number, y: number, width: number, height: number, color = 'reset', title = '', zIndex = 0) {
15
+ this.x = x;
16
+ this.y = y;
17
+ this.width = width;
18
+ this.height = height;
19
+ this.color = color;
20
+ this.title = title;
21
+ this.contents = [];
22
+ this.zIndex = zIndex;
23
+ }
24
+
25
+ addContent(content: TideObject) {
26
+ this.contents.push(content);
27
+ }
28
+
29
+ clear(screen: string[][]) {
30
+ for (let i = this.y; i < this.y + this.height; i++) {
31
+ for (let j = this.x; j < this.x + this.width; j++) {
32
+ screen[i][j] = ' ';
33
+ }
34
+ }
35
+ }
36
+
37
+ draw(screen: string[][]) {
38
+ this.clear(screen);
39
+
40
+ const colorCode = getColorCode(this.color);
41
+ const titleColorCode = getColorCode('magenta');
42
+
43
+ for (let i = this.x + 1; i < this.x + this.width - 1; i++) {
44
+ screen[this.y][i] = `${colorCode}─\x1b[0m`;
45
+ }
46
+ for (let i = this.x + 1; i < this.x + this.width - 1; i++) {
47
+ screen[this.y + this.height - 1][i] = `${colorCode}─\x1b[0m`;
48
+ }
49
+ for (let i = this.y + 1; i < this.y + this.height - 1; i++) {
50
+ screen[i][this.x] = `${colorCode}│\x1b[0m`;
51
+ screen[i][this.x + this.width - 1] = `${colorCode}│\x1b[0m`;
52
+ }
53
+
54
+ screen[this.y][this.x] = `${colorCode}┌\x1b[0m`;
55
+ screen[this.y][this.x + this.width - 1] = `${colorCode}┐\x1b[0m`;
56
+ screen[this.y + this.height - 1][this.x] = `${colorCode}└\x1b[0m`;
57
+ screen[this.y + this.height - 1][this.x + this.width - 1] = `${colorCode}┘\x1b[0m`;
58
+
59
+ if (this.title) {
60
+ const titlePosition = Math.max(this.x + 2, Math.min(this.x + this.width - 2 - this.title.length, this.x + 2));
61
+ for (let i = 0; i < this.title.length; i++) {
62
+ if (titlePosition + i < screen[0].length && this.y < screen.length) {
63
+ screen[this.y][titlePosition + i] = `${titleColorCode}${this.title[i]}\x1b[0m`;
64
+ }
65
+ }
66
+ }
67
+
68
+ for (let content of this.contents) {
69
+ content.draw(screen, this.x + 1, this.y + 1, this.width - 2);
70
+ }
71
+ }
72
+
73
+ move(dx: number, dy: number) {
74
+ this.x += dx;
75
+ this.y += dy;
76
+ }
77
+ }
78
+
@@ -0,0 +1,34 @@
1
+ import { TideObject } from "../interfaces";
2
+ import { getColorCode, wrapText } from "../util";
3
+
4
+ export class Text implements TideObject {
5
+ relativeX: number;
6
+ relativeY: number;
7
+ text: string;
8
+ color: string;
9
+ zIndex: number;
10
+
11
+ constructor(x: number, y: number, text: string, color = 'reset', zIndex = 0) {
12
+ this.relativeX = x;
13
+ this.relativeY = y;
14
+ this.text = text;
15
+ this.color = color;
16
+ this.zIndex = zIndex;
17
+ }
18
+
19
+ draw(screen: string[][], boxX: number, boxY: number, boxWidth: number) {
20
+ const colorCode = getColorCode(this.color);
21
+ const lines = wrapText(this.text, boxWidth);
22
+
23
+ for (let i = 0; i < lines.length; i++) {
24
+ const line = lines[i];
25
+ for (let j = 0; j < line.length; j++) {
26
+ const screenX = boxX + this.relativeX + j;
27
+ const screenY = boxY + this.relativeY + i;
28
+ if (screenX < screen[0].length && screenY < screen.length) {
29
+ screen[screenY][screenX] = `${colorCode}${line[j]}\x1b[0m`;
30
+ }
31
+ }
32
+ }
33
+ }
34
+ }
package/src/screen.ts ADDED
@@ -0,0 +1,70 @@
1
+ import { TideObject } from "./interfaces";
2
+
3
+ export class TideScreen {
4
+ width: number;
5
+ height: number;
6
+ screen: string[][];
7
+ buffer: string[][];
8
+ components: TideObject[];
9
+ fps: number | null = null;
10
+ updateFunction: (() => void) | null = null;
11
+
12
+ constructor(width: number, height: number) {
13
+ this.width = width;
14
+ this.height = height;
15
+ this.screen = Array.from({ length: height }, () => Array(width).fill(' '));
16
+ this.buffer = Array.from({ length: height }, () => Array(width).fill(' '));
17
+ this.components = [];
18
+ }
19
+
20
+ clearScreen() {
21
+ this.screen = Array.from({ length: this.height }, () => Array(this.width).fill(' '));
22
+ }
23
+
24
+ clearBuffer() {
25
+ this.buffer = Array.from({ length: this.height }, () => Array(this.width).fill(' '));
26
+ }
27
+
28
+ addComponent(component: TideObject) {
29
+ this.components.push(component);
30
+ }
31
+
32
+ renderBuffer() {
33
+ this.clearBuffer();
34
+ this.components.sort((a, b) => b.zIndex - a.zIndex);
35
+ this.components.forEach(component => component.draw(this.buffer));
36
+ }
37
+
38
+ render() {
39
+ console.clear();
40
+ const output = this.buffer.map(row => row.join('')).join('\n');
41
+ console.log(output);
42
+ }
43
+
44
+ setUpdateFunction(fn: () => void) {
45
+ this.updateFunction = fn;
46
+ }
47
+
48
+ setFPS(fps: number) {
49
+ this.fps = fps;
50
+ }
51
+
52
+ renderCycle() {
53
+ if (this.fps === null) {
54
+ throw new Error("FPS must be set before starting the render cycle.");
55
+ }
56
+
57
+ const interval = 1000 / this.fps;
58
+
59
+ const loop = () => {
60
+ if (this.updateFunction) {
61
+ this.updateFunction();
62
+ }
63
+ this.renderBuffer(); // Prepare the buffer with updated content
64
+ this.render(); // Output the buffer to the screen
65
+ setTimeout(loop, interval);
66
+ };
67
+
68
+ loop();
69
+ }
70
+ }
package/src/util.ts ADDED
@@ -0,0 +1,32 @@
1
+ export function getColorCode(color: string) {
2
+ const colors: { [key: string]: string } = {
3
+ reset: '\x1b[0m',
4
+ black: '\x1b[30m',
5
+ red: '\x1b[31m',
6
+ green: '\x1b[32m',
7
+ yellow: '\x1b[33m',
8
+ blue: '\x1b[34m',
9
+ magenta: '\x1b[35m',
10
+ cyan: '\x1b[36m',
11
+ white: '\x1b[37m',
12
+ };
13
+
14
+ return colors[color.toLowerCase()] || colors['reset'];
15
+ }
16
+
17
+ export function wrapText(text: string, maxWidth: number) {
18
+ const lines = [];
19
+ let currentLine = '';
20
+
21
+ for (const word of text.split(' ')) {
22
+ if ((currentLine + word).length > maxWidth) {
23
+ lines.push(currentLine.trim());
24
+ currentLine = word + ' ';
25
+ } else {
26
+ currentLine += word + ' ';
27
+ }
28
+ }
29
+ lines.push(currentLine.trim());
30
+
31
+ return lines;
32
+ }