@opentui/core 0.1.4 → 0.1.6

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.
@@ -0,0 +1,38 @@
1
+ import type { RGBA } from "../types";
2
+ import { StyledText } from "./styled-text";
3
+ export interface HASTText {
4
+ type: "text";
5
+ value: string;
6
+ }
7
+ export interface HASTElement {
8
+ type: "element";
9
+ tagName: string;
10
+ properties?: {
11
+ className?: string;
12
+ };
13
+ children: HASTNode[];
14
+ }
15
+ export type HASTNode = HASTText | HASTElement;
16
+ export interface StyleDefinition {
17
+ fg?: RGBA;
18
+ bg?: RGBA;
19
+ bold?: boolean;
20
+ italic?: boolean;
21
+ underline?: boolean;
22
+ dim?: boolean;
23
+ }
24
+ interface MergedStyle {
25
+ fg?: RGBA;
26
+ bg?: RGBA;
27
+ attributes: number;
28
+ }
29
+ export declare class SyntaxStyle {
30
+ private styles;
31
+ private mergedStyleCache;
32
+ constructor(styles: Record<string, StyleDefinition>);
33
+ mergeStyles(...styleNames: string[]): MergedStyle;
34
+ clearCache(): void;
35
+ getCacheSize(): number;
36
+ }
37
+ export declare function hastToStyledText(hast: HASTNode, syntaxStyle: SyntaxStyle): StyledText;
38
+ export {};
package/lib/index.d.ts CHANGED
@@ -2,3 +2,4 @@ export * from "./border";
2
2
  export * from "./TrackedNode";
3
3
  export * from "./KeyHandler";
4
4
  export * from "./ascii.font";
5
+ export * from "./hast-styled-text";
@@ -14,11 +14,13 @@ export interface StyleAttrs {
14
14
  }
15
15
  export declare class StyledText {
16
16
  readonly chunks: TextChunk[];
17
- private _length;
18
17
  private _plainText;
19
- constructor(chunks: TextChunk[], length: number, plainText: string);
18
+ constructor(chunks: TextChunk[]);
20
19
  toString(): string;
21
- get length(): number;
20
+ private _chunksToPlainText;
21
+ insert(chunk: TextChunk, index?: number): void;
22
+ remove(chunk: TextChunk): void;
23
+ replace(chunk: TextChunk, oldChunk: TextChunk): void;
22
24
  }
23
25
  export declare function stringToStyledText(content: string): StyledText;
24
26
  export type StylableInput = string | number | boolean | TextChunk;
package/package.json CHANGED
@@ -4,12 +4,13 @@
4
4
  "main": "index.js",
5
5
  "types": "index.d.ts",
6
6
  "type": "module",
7
- "version": "0.1.4",
7
+ "version": "0.1.6",
8
8
  "description": "OpenTUI is a TypeScript library for building terminal user interfaces (TUIs)",
9
9
  "license": "MIT",
10
10
  "repository": {
11
11
  "type": "git",
12
- "url": "https://github.com/sst/opentui"
12
+ "url": "https://github.com/sst/opentui",
13
+ "directory": "packages/core"
13
14
  },
14
15
  "exports": {
15
16
  ".": {
@@ -27,16 +28,22 @@
27
28
  "jimp": "1.6.0",
28
29
  "yoga-layout": "3.2.1"
29
30
  },
31
+ "devDependencies": {
32
+ "@types/bun": "latest",
33
+ "@types/three": "^0.177.0",
34
+ "commander": "^13.1.0",
35
+ "prettier": "3.6.2"
36
+ },
30
37
  "optionalDependencies": {
31
38
  "@dimforge/rapier2d-simd-compat": "^0.17.3",
32
39
  "bun-webgpu": "0.1.3",
33
40
  "planck": "^1.4.2",
34
41
  "three": "0.177.0",
35
- "@opentui/core-darwin-x64": "0.1.4",
36
- "@opentui/core-darwin-arm64": "0.1.4",
37
- "@opentui/core-linux-x64": "0.1.4",
38
- "@opentui/core-linux-arm64": "0.1.4",
39
- "@opentui/core-win32-x64": "0.1.4",
40
- "@opentui/core-win32-arm64": "0.1.4"
42
+ "@opentui/core-darwin-x64": "0.1.6",
43
+ "@opentui/core-darwin-arm64": "0.1.6",
44
+ "@opentui/core-linux-x64": "0.1.6",
45
+ "@opentui/core-linux-arm64": "0.1.6",
46
+ "@opentui/core-win32-x64": "0.1.6",
47
+ "@opentui/core-win32-arm64": "0.1.6"
41
48
  }
42
49
  }
package/utils.d.ts CHANGED
@@ -13,7 +13,3 @@ export declare function createTextAttributes({ bold, italic, underline, dim, bli
13
13
  hidden?: boolean;
14
14
  strikethrough?: boolean;
15
15
  }): number;
16
- export declare function loadTemplate(filePath: string, params: Record<string, string>): Promise<string>;
17
- export declare function fixPaths<T extends {
18
- [key: string]: string;
19
- }>(paths: T): T;
@@ -1,201 +0,0 @@
1
- struct CellResult {
2
- bg: vec4<f32>, // Background RGBA (16 bytes)
3
- fg: vec4<f32>, // Foreground RGBA (16 bytes)
4
- char: u32, // Unicode character code (4 bytes)
5
- _padding1: u32, // Padding (4 bytes)
6
- _padding2: u32, // Extra padding (4 bytes)
7
- _padding3: u32, // Extra padding (4 bytes) - total now 48 bytes (16-byte aligned)
8
- };
9
-
10
- struct CellBuffer {
11
- cells: array<CellResult>
12
- };
13
-
14
- struct SuperSamplingParams {
15
- width: u32, // Canvas width in pixels
16
- height: u32, // Canvas height in pixels
17
- sampleAlgo: u32, // 0 = standard 2x2, 1 = pre-squeezed horizontal blend
18
- _padding: u32, // Padding for 16-byte alignment
19
- };
20
-
21
- @group(0) @binding(0) var inputTexture: texture_2d<f32>;
22
- @group(0) @binding(1) var<storage, read_write> output: CellBuffer;
23
- @group(0) @binding(2) var<uniform> params: SuperSamplingParams;
24
-
25
- // Quadrant character lookup table (same as Zig implementation)
26
- const quadrantChars = array<u32, 16>(
27
- 32u, // ' ' - 0000
28
- 0x2597u, // ▗ - 0001 BR
29
- 0x2596u, // ▖ - 0010 BL
30
- 0x2584u, // ▄ - 0011 Lower Half Block
31
- 0x259Du, // ▝ - 0100 TR
32
- 0x2590u, // ▐ - 0101 Right Half Block
33
- 0x259Eu, // ▞ - 0110 TR+BL
34
- 0x259Fu, // ▟ - 0111 TR+BL+BR
35
- 0x2598u, // ▘ - 1000 TL
36
- 0x259Au, // ▚ - 1001 TL+BR
37
- 0x258Cu, // ▌ - 1010 Left Half Block
38
- 0x2599u, // ▙ - 1011 TL+BL+BR
39
- 0x2580u, // ▀ - 1100 Upper Half Block
40
- 0x259Cu, // ▜ - 1101 TL+TR+BR
41
- 0x259Bu, // ▛ - 1110 TL+TR+BL
42
- 0x2588u // █ - 1111 Full Block
43
- );
44
-
45
- const inv_255: f32 = 1.0 / 255.0;
46
-
47
- fn getPixelColor(pixelX: u32, pixelY: u32) -> vec4<f32> {
48
- if (pixelX >= params.width || pixelY >= params.height) {
49
- return vec4<f32>(0.0, 0.0, 0.0, 1.0); // Black for out-of-bounds
50
- }
51
-
52
- // textureLoad automatically handles format conversion to RGBA
53
- return textureLoad(inputTexture, vec2<i32>(i32(pixelX), i32(pixelY)), 0);
54
- }
55
-
56
- fn colorDistance(a: vec4<f32>, b: vec4<f32>) -> f32 {
57
- let diff = a.rgb - b.rgb;
58
- return dot(diff, diff);
59
- }
60
-
61
- fn luminance(color: vec4<f32>) -> f32 {
62
- return 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
63
- }
64
-
65
- fn closestColorIndex(pixel: vec4<f32>, candA: vec4<f32>, candB: vec4<f32>) -> u32 {
66
- return select(1u, 0u, colorDistance(pixel, candA) <= colorDistance(pixel, candB));
67
- }
68
-
69
- fn averageColor(pixels: array<vec4<f32>, 4>) -> vec4<f32> {
70
- return (pixels[0] + pixels[1] + pixels[2] + pixels[3]) * 0.25;
71
- }
72
-
73
- fn blendColors(color1: vec4<f32>, color2: vec4<f32>) -> vec4<f32> {
74
- let a1 = color1.a;
75
- let a2 = color2.a;
76
-
77
- if (a1 == 0.0 && a2 == 0.0) {
78
- return vec4<f32>(0.0, 0.0, 0.0, 0.0);
79
- }
80
-
81
- let outAlpha = a1 + a2 - a1 * a2;
82
- if (outAlpha == 0.0) {
83
- return vec4<f32>(0.0, 0.0, 0.0, 0.0);
84
- }
85
-
86
- let rgb = (color1.rgb * a1 + color2.rgb * a2 * (1.0 - a1)) / outAlpha;
87
-
88
- return vec4<f32>(rgb, outAlpha);
89
- }
90
-
91
- fn averageColorsWithAlpha(pixels: array<vec4<f32>, 4>) -> vec4<f32> {
92
- let blend1 = blendColors(pixels[0], pixels[1]);
93
- let blend2 = blendColors(pixels[2], pixels[3]);
94
-
95
- return blendColors(blend1, blend2);
96
- }
97
-
98
- fn renderQuadrantBlock(pixels: array<vec4<f32>, 4>) -> CellResult {
99
- var maxDist: f32 = colorDistance(pixels[0], pixels[1]);
100
- var pIdxA: u32 = 0u;
101
- var pIdxB: u32 = 1u;
102
-
103
- for (var i: u32 = 0u; i < 4u; i++) {
104
- for (var j: u32 = i + 1u; j < 4u; j++) {
105
- let dist = colorDistance(pixels[i], pixels[j]);
106
- if (dist > maxDist) {
107
- pIdxA = i;
108
- pIdxB = j;
109
- maxDist = dist;
110
- }
111
- }
112
- }
113
-
114
- let pCandA = pixels[pIdxA];
115
- let pCandB = pixels[pIdxB];
116
-
117
- var chosenDarkColor: vec4<f32>;
118
- var chosenLightColor: vec4<f32>;
119
-
120
- if (luminance(pCandA) <= luminance(pCandB)) {
121
- chosenDarkColor = pCandA;
122
- chosenLightColor = pCandB;
123
- } else {
124
- chosenDarkColor = pCandB;
125
- chosenLightColor = pCandA;
126
- }
127
-
128
- var quadrantBits: u32 = 0u;
129
- let bitValues = array<u32, 4>(8u, 4u, 2u, 1u); // TL, TR, BL, BR
130
-
131
- for (var i: u32 = 0u; i < 4u; i++) {
132
- if (closestColorIndex(pixels[i], chosenDarkColor, chosenLightColor) == 0u) {
133
- quadrantBits |= bitValues[i];
134
- }
135
- }
136
-
137
- // Construct result
138
- var result: CellResult;
139
-
140
- if (quadrantBits == 0u) { // All light
141
- result.char = 32u; // Space character
142
- result.fg = chosenDarkColor;
143
- result.bg = averageColorsWithAlpha(pixels);
144
- } else if (quadrantBits == 15u) { // All dark
145
- result.char = quadrantChars[15]; // Full block
146
- result.fg = averageColorsWithAlpha(pixels);
147
- result.bg = chosenLightColor;
148
- } else { // Mixed pattern
149
- result.char = quadrantChars[quadrantBits];
150
- result.fg = chosenDarkColor;
151
- result.bg = chosenLightColor;
152
- }
153
- result._padding1 = 0u;
154
- result._padding2 = 0u;
155
- result._padding3 = 0u;
156
-
157
- return result;
158
- }
159
-
160
- @compute @workgroup_size(${WORKGROUP_SIZE}, ${WORKGROUP_SIZE}, 1)
161
- fn main(@builtin(global_invocation_id) id: vec3<u32>) {
162
- let cellX = id.x;
163
- let cellY = id.y;
164
- let bufferWidthCells = (params.width + 1u) / 2u;
165
- let bufferHeightCells = (params.height + 1u) / 2u;
166
-
167
- if (cellX >= bufferWidthCells || cellY >= bufferHeightCells) {
168
- return;
169
- }
170
-
171
- let renderX = cellX * 2u;
172
- let renderY = cellY * 2u;
173
-
174
- var pixelsRgba: array<vec4<f32>, 4>;
175
-
176
- if (params.sampleAlgo == 1u) {
177
- let topColor = getPixelColor(renderX, renderY);
178
- let topColor2 = getPixelColor(renderX + 1u, renderY);
179
-
180
- let blendedTop = blendColors(topColor, topColor2);
181
-
182
- let bottomColor = getPixelColor(renderX, renderY + 1u);
183
- let bottomColor2 = getPixelColor(renderX + 1u, renderY + 1u);
184
- let blendedBottom = blendColors(bottomColor, bottomColor2);
185
-
186
- pixelsRgba[0] = blendedTop; // TL
187
- pixelsRgba[1] = blendedTop; // TR
188
- pixelsRgba[2] = blendedBottom; // BL
189
- pixelsRgba[3] = blendedBottom; // BR
190
- } else {
191
- pixelsRgba[0] = getPixelColor(renderX, renderY); // TL
192
- pixelsRgba[1] = getPixelColor(renderX + 1u, renderY); // TR
193
- pixelsRgba[2] = getPixelColor(renderX, renderY + 1u); // BL
194
- pixelsRgba[3] = getPixelColor(renderX + 1u, renderY + 1u); // BR
195
- }
196
-
197
- let cellResult = renderQuadrantBlock(pixelsRgba);
198
-
199
- let outputIndex = cellY * bufferWidthCells + cellX;
200
- output.cells[outputIndex] = cellResult;
201
- }