restty 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 (44) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +101 -0
  3. package/dist/app/atlas-builder.d.ts +81 -0
  4. package/dist/app/index.d.ts +3 -0
  5. package/dist/app/types.d.ts +133 -0
  6. package/dist/fonts/index.d.ts +4 -0
  7. package/dist/fonts/manager.d.ts +21 -0
  8. package/dist/fonts/nerd-constraints.d.ts +23 -0
  9. package/dist/fonts/nerd-ranges.d.ts +2 -0
  10. package/dist/fonts/types.d.ts +40 -0
  11. package/dist/grid/grid.d.ts +22 -0
  12. package/dist/grid/index.d.ts +2 -0
  13. package/dist/grid/types.d.ts +24 -0
  14. package/dist/ime/ime.d.ts +14 -0
  15. package/dist/ime/index.d.ts +2 -0
  16. package/dist/ime/types.d.ts +10 -0
  17. package/dist/index.d.ts +16 -0
  18. package/dist/index.js +30821 -0
  19. package/dist/input/index.d.ts +6 -0
  20. package/dist/input/keymap.d.ts +24 -0
  21. package/dist/input/mouse.d.ts +38 -0
  22. package/dist/input/output.d.ts +53 -0
  23. package/dist/input/types.d.ts +159 -0
  24. package/dist/pty/index.d.ts +2 -0
  25. package/dist/pty/pty.d.ts +8 -0
  26. package/dist/pty/types.d.ts +36 -0
  27. package/dist/renderer/box-drawing-map.d.ts +1 -0
  28. package/dist/renderer/index.d.ts +5 -0
  29. package/dist/renderer/shaders.d.ts +7 -0
  30. package/dist/renderer/shapes.d.ts +40 -0
  31. package/dist/renderer/types.d.ts +80 -0
  32. package/dist/renderer/webgpu.d.ts +19 -0
  33. package/dist/restty-input.d.ts +1 -0
  34. package/dist/selection/index.d.ts +2 -0
  35. package/dist/selection/selection.d.ts +13 -0
  36. package/dist/selection/types.d.ts +14 -0
  37. package/dist/theme/builtin-themes.d.ts +3 -0
  38. package/dist/theme/catalog.d.ts +7 -0
  39. package/dist/theme/ghostty.d.ts +23 -0
  40. package/dist/theme/index.d.ts +2 -0
  41. package/dist/wasm/embedded.d.ts +1 -0
  42. package/dist/wasm/index.d.ts +1 -0
  43. package/dist/wasm/runtime.d.ts +155 -0
  44. package/package.json +55 -0
@@ -0,0 +1,6 @@
1
+ import type { InputHandler, InputHandlerOptions } from "./types";
2
+ /**
3
+ * Create a terminal input handler with key, IME, PTY, and mouse support.
4
+ */
5
+ export declare function createInputHandler(options?: InputHandlerOptions): InputHandler;
6
+ export type { CellPosition, CursorPosition, InputHandler, InputHandlerConfig, InputHandlerOptions, MouseMode, MouseStatus, } from "./types";
@@ -0,0 +1,24 @@
1
+ import type { InputHandlerConfig } from "./types";
2
+ /**
3
+ * Standard sequences used by terminal emulators.
4
+ */
5
+ export declare const sequences: {
6
+ enter: string;
7
+ backspace: string;
8
+ delete: string;
9
+ tab: string;
10
+ shiftTab: string;
11
+ escape: string;
12
+ };
13
+ /**
14
+ * Encode a KeyboardEvent into a terminal byte sequence.
15
+ */
16
+ export declare function encodeKeyEvent(event: KeyboardEvent, config?: InputHandlerConfig, kittyFlags?: number): string;
17
+ /**
18
+ * Encode beforeinput events (IME/paste/backspace) into terminal sequences.
19
+ */
20
+ export declare function encodeBeforeInput(event: InputEvent): string;
21
+ /**
22
+ * Map input sequences to PTY expectations (e.g., DEL vs backspace).
23
+ */
24
+ export declare function mapKeyForPty(seq: string): string;
@@ -0,0 +1,38 @@
1
+ import type { CellPosition, MouseMode, MouseStatus } from "./types";
2
+ export type MouseControllerOptions = {
3
+ sendReply: (data: string) => void;
4
+ positionToCell: (event: MouseEvent | PointerEvent | WheelEvent) => CellPosition;
5
+ positionToPixel?: (event: MouseEvent | PointerEvent | WheelEvent) => {
6
+ x: number;
7
+ y: number;
8
+ };
9
+ };
10
+ export declare class MouseController {
11
+ private mode;
12
+ private enabled;
13
+ private format;
14
+ private motion;
15
+ private pressed;
16
+ private button;
17
+ private flags;
18
+ private x10Event;
19
+ private sendReply;
20
+ private positionToCell;
21
+ private positionToPixel?;
22
+ constructor(options: MouseControllerOptions);
23
+ setReplySink(fn: (data: string) => void): void;
24
+ setPositionToCell(fn: (event: MouseEvent | PointerEvent | WheelEvent) => CellPosition): void;
25
+ setPositionToPixel(fn: (event: MouseEvent | PointerEvent | WheelEvent) => {
26
+ x: number;
27
+ y: number;
28
+ }): void;
29
+ setMode(mode: MouseMode): void;
30
+ handleModeSeq(seq: string): boolean;
31
+ isActive(): boolean;
32
+ getStatus(): MouseStatus;
33
+ sendMouseEvent(kind: "down" | "up" | "move" | "wheel", event: PointerEvent | WheelEvent): boolean;
34
+ private updateFlags;
35
+ private isX10EventMode;
36
+ private modifiers;
37
+ private sendMouse;
38
+ }
@@ -0,0 +1,53 @@
1
+ import type { CursorPosition, WindowOp } from "./types";
2
+ import type { MouseController } from "./mouse";
3
+ export type OutputFilterOptions = {
4
+ getCursorPosition: () => CursorPosition;
5
+ sendReply: (data: string) => void;
6
+ mouse: MouseController;
7
+ getDefaultColors?: () => {
8
+ fg?: [number, number, number];
9
+ bg?: [number, number, number];
10
+ cursor?: [number, number, number];
11
+ };
12
+ onClipboardWrite?: (text: string) => void | Promise<void>;
13
+ onClipboardRead?: () => string | null | Promise<string | null>;
14
+ onWindowOp?: (op: WindowOp) => void;
15
+ getWindowMetrics?: () => {
16
+ rows: number;
17
+ cols: number;
18
+ widthPx: number;
19
+ heightPx: number;
20
+ cellWidthPx: number;
21
+ cellHeightPx: number;
22
+ };
23
+ };
24
+ /**
25
+ * Parses output for control queries (CPR/DA) and mouse mode toggles,
26
+ * returning the sanitized output for rendering.
27
+ */
28
+ export declare class OutputFilter {
29
+ private remainder;
30
+ private getCursorPosition;
31
+ private sendReply;
32
+ private mouse;
33
+ private altScreen;
34
+ private bracketedPaste;
35
+ private focusReporting;
36
+ private windowOpHandler?;
37
+ private getWindowMetrics?;
38
+ private clipboardWrite?;
39
+ private clipboardRead?;
40
+ private getDefaultColors?;
41
+ constructor(options: OutputFilterOptions);
42
+ setCursorProvider(fn: () => CursorPosition): void;
43
+ setReplySink(fn: (data: string) => void): void;
44
+ setWindowOpHandler(fn: (op: WindowOp) => void): void;
45
+ isAltScreen(): boolean;
46
+ isBracketedPaste(): boolean;
47
+ isFocusReporting(): boolean;
48
+ private replyOscColor;
49
+ private handleOsc;
50
+ private handleModeSeq;
51
+ private handleWindowOp;
52
+ filter(output: string): string;
53
+ }
@@ -0,0 +1,159 @@
1
+ /**
2
+ * 1-based cursor position (terminal coordinates).
3
+ */
4
+ export type CursorPosition = {
5
+ row: number;
6
+ col: number;
7
+ };
8
+ /**
9
+ * 0-based cell coordinates (grid coordinates).
10
+ */
11
+ export type CellPosition = {
12
+ row: number;
13
+ col: number;
14
+ };
15
+ /**
16
+ * Mouse reporting mode.
17
+ * - auto: follow app requests (DECSET/DECRST)
18
+ * - on: always report mouse
19
+ * - off: never report mouse
20
+ */
21
+ export type MouseMode = "auto" | "on" | "off";
22
+ /**
23
+ * Input handler configuration flags.
24
+ */
25
+ export type InputHandlerConfig = {
26
+ /**
27
+ * Encode Ctrl+<key> combos to control characters (default true).
28
+ */
29
+ enableCtrlCombos?: boolean;
30
+ };
31
+ export type DefaultColors = {
32
+ fg?: [number, number, number];
33
+ bg?: [number, number, number];
34
+ cursor?: [number, number, number];
35
+ };
36
+ export type WindowMetrics = {
37
+ rows: number;
38
+ cols: number;
39
+ widthPx: number;
40
+ heightPx: number;
41
+ cellWidthPx: number;
42
+ cellHeightPx: number;
43
+ };
44
+ export type WindowOp = {
45
+ type: "resize";
46
+ rows: number;
47
+ cols: number;
48
+ params: number[];
49
+ raw: string;
50
+ } | {
51
+ type: "unknown";
52
+ params: number[];
53
+ raw: string;
54
+ };
55
+ /**
56
+ * Input handler construction options.
57
+ */
58
+ export type InputHandlerOptions = {
59
+ /**
60
+ * Configuration knobs for key encoding and feature flags.
61
+ */
62
+ config?: InputHandlerConfig;
63
+ /**
64
+ * Provide the current cursor position for CPR replies.
65
+ */
66
+ getCursorPosition?: () => CursorPosition;
67
+ /**
68
+ * Sink for output replies (CPR/DA/mouse).
69
+ */
70
+ sendReply?: (data: string) => void;
71
+ /**
72
+ * Map pointer events to cell coordinates.
73
+ */
74
+ positionToCell?: (event: MouseEvent | PointerEvent | WheelEvent) => CellPosition;
75
+ /**
76
+ * Map pointer events to pixel coordinates (1-based, terminal space).
77
+ */
78
+ positionToPixel?: (event: MouseEvent | PointerEvent | WheelEvent) => {
79
+ x: number;
80
+ y: number;
81
+ };
82
+ /**
83
+ * Provide default colors for OSC 10/11/12 queries (RGB 0-255).
84
+ */
85
+ getDefaultColors?: () => DefaultColors;
86
+ /**
87
+ * Optional handler for window manipulation sequences (CSI ... t).
88
+ */
89
+ onWindowOp?: (op: WindowOp) => void;
90
+ /**
91
+ * Optional provider for XTWINOPS report queries (CSI 14/16/18 t).
92
+ */
93
+ getWindowMetrics?: () => WindowMetrics;
94
+ /**
95
+ * Optional clipboard handlers for OSC 52.
96
+ */
97
+ onClipboardWrite?: (text: string) => void | Promise<void>;
98
+ onClipboardRead?: () => string | null | Promise<string | null>;
99
+ /**
100
+ * Return active Kitty keyboard protocol flags (CSI ? u query result).
101
+ */
102
+ getKittyKeyboardFlags?: () => number;
103
+ };
104
+ /**
105
+ * Exposed mouse status for UI debugging.
106
+ */
107
+ export type MouseStatus = {
108
+ mode: MouseMode;
109
+ active: boolean;
110
+ detail: "sgr" | "x10" | "utf8" | "urxvt" | "sgr_pixels";
111
+ enabled: boolean;
112
+ };
113
+ /**
114
+ * Public input handler API.
115
+ */
116
+ export type InputHandler = {
117
+ sequences: {
118
+ enter: string;
119
+ backspace: string;
120
+ delete: string;
121
+ tab: string;
122
+ shiftTab: string;
123
+ escape: string;
124
+ };
125
+ /**
126
+ * Encode a KeyboardEvent into a terminal byte sequence.
127
+ */
128
+ encodeKeyEvent: (event: KeyboardEvent) => string;
129
+ /**
130
+ * Encode a beforeinput event into a terminal byte sequence.
131
+ */
132
+ encodeBeforeInput: (event: InputEvent) => string;
133
+ /**
134
+ * Map encoded sequences to PTY-friendly forms.
135
+ */
136
+ mapKeyForPty: (seq: string) => string;
137
+ /**
138
+ * Filter PTY output and handle control queries (CPR/DA/mouse mode).
139
+ */
140
+ filterOutput: (output: string) => string;
141
+ setReplySink: (fn: (data: string) => void) => void;
142
+ setCursorProvider: (fn: () => CursorPosition) => void;
143
+ setPositionToCell: (fn: (event: MouseEvent | PointerEvent | WheelEvent) => CellPosition) => void;
144
+ setPositionToPixel: (fn: (event: MouseEvent | PointerEvent | WheelEvent) => {
145
+ x: number;
146
+ y: number;
147
+ }) => void;
148
+ setWindowOpHandler: (fn: (op: WindowOp) => void) => void;
149
+ setMouseMode: (mode: MouseMode) => void;
150
+ getMouseStatus: () => MouseStatus;
151
+ isMouseActive: () => boolean;
152
+ isBracketedPaste: () => boolean;
153
+ isFocusReporting: () => boolean;
154
+ isAltScreen: () => boolean;
155
+ /**
156
+ * Encode pointer input as terminal mouse events (SGR).
157
+ */
158
+ sendMouseEvent: (kind: "down" | "up" | "move" | "wheel", event: PointerEvent | WheelEvent) => boolean;
159
+ };
@@ -0,0 +1,2 @@
1
+ export * from "./types";
2
+ export * from "./pty";
@@ -0,0 +1,8 @@
1
+ import type { PtyCallbacks, PtyConnectionState } from "./types";
2
+ export declare function decodePtyBinary(decoder: TextDecoder, payload: ArrayBuffer | Uint8Array, stream?: boolean): string;
3
+ export declare function createPtyConnection(): PtyConnectionState;
4
+ export declare function connectPty(state: PtyConnectionState, url: string, callbacks: PtyCallbacks): void;
5
+ export declare function disconnectPty(state: PtyConnectionState): void;
6
+ export declare function sendPtyInput(state: PtyConnectionState, data: string): boolean;
7
+ export declare function sendPtyResize(state: PtyConnectionState, cols: number, rows: number): boolean;
8
+ export declare function isPtyConnected(state: PtyConnectionState): boolean;
@@ -0,0 +1,36 @@
1
+ export type PtyMessage = {
2
+ type: "input";
3
+ data: string;
4
+ } | {
5
+ type: "resize";
6
+ cols: number;
7
+ rows: number;
8
+ };
9
+ export type PtyStatusMessage = {
10
+ type: "status";
11
+ shell?: string;
12
+ };
13
+ export type PtyErrorMessage = {
14
+ type: "error";
15
+ message?: string;
16
+ errors?: string[];
17
+ };
18
+ export type PtyExitMessage = {
19
+ type: "exit";
20
+ code?: number;
21
+ };
22
+ export type PtyServerMessage = PtyStatusMessage | PtyErrorMessage | PtyExitMessage;
23
+ export type PtyConnectionState = {
24
+ socket: WebSocket | null;
25
+ connected: boolean;
26
+ url: string;
27
+ decoder: TextDecoder | null;
28
+ };
29
+ export type PtyCallbacks = {
30
+ onConnect?: () => void;
31
+ onDisconnect?: () => void;
32
+ onData?: (data: string) => void;
33
+ onStatus?: (shell: string) => void;
34
+ onError?: (message: string, errors?: string[]) => void;
35
+ onExit?: (code: number) => void;
36
+ };
@@ -0,0 +1 @@
1
+ export declare const BOX_LINE_MAP: Map<number, [number, number, number, number]>;
@@ -0,0 +1,5 @@
1
+ export * from "./shapes";
2
+ export * from "./types";
3
+ export * from "./shaders";
4
+ export * from "./webgpu";
5
+ export { BOX_LINE_MAP } from "./box-drawing-map";
@@ -0,0 +1,7 @@
1
+ export declare const RECT_SHADER = "\nstruct Uniforms {\n res: vec2f,\n _pad: vec2f,\n blend: vec2f,\n _pad2: vec2f,\n};\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n\nstruct VSIn {\n @location(0) quad: vec2f,\n @location(1) pos: vec2f,\n @location(2) size: vec2f,\n @location(3) color: vec4f,\n};\n\nstruct VSOut {\n @builtin(position) position: vec4f,\n @location(0) color: vec4f,\n};\n\n// sRGB to linear conversion for proper blending\nfn srgbToLinear(c: f32) -> f32 {\n if (c <= 0.04045) {\n return c / 12.92;\n }\n return pow((c + 0.055) / 1.055, 2.4);\n}\n\nfn srgbToLinear3(c: vec3f) -> vec3f {\n return vec3f(srgbToLinear(c.x), srgbToLinear(c.y), srgbToLinear(c.z));\n}\n\n@vertex\nfn vsMain(input: VSIn) -> VSOut {\n let pixel = input.pos + input.quad * input.size;\n let clip = vec2f(\n (pixel.x / uniforms.res.x) * 2.0 - 1.0,\n 1.0 - (pixel.y / uniforms.res.y) * 2.0\n );\n\n var out: VSOut;\n out.position = vec4f(clip.x, clip.y, 0.0, 1.0);\n out.color = input.color;\n return out;\n}\n\n@fragment\nfn fsMain(input: VSOut) -> @location(0) vec4f {\n let useLinear = uniforms.blend.x > 0.5;\n var color = input.color;\n if (useLinear) {\n color = vec4f(srgbToLinear3(color.rgb), color.a);\n }\n color = vec4f(color.rgb * color.a, color.a);\n return color;\n}\n";
2
+ export declare const RECT_SHADER_GL_VERT = "#version 300 es\nprecision highp float;\n\nuniform vec2 u_resolution;\n\nlayout(location = 0) in vec2 a_quad;\nlayout(location = 1) in vec2 a_pos;\nlayout(location = 2) in vec2 a_size;\nlayout(location = 3) in vec4 a_color;\n\nout vec4 v_color;\n\nvoid main() {\n vec2 pixel = a_pos + a_quad * a_size;\n vec2 clip = vec2(\n (pixel.x / u_resolution.x) * 2.0 - 1.0,\n 1.0 - (pixel.y / u_resolution.y) * 2.0\n );\n gl_Position = vec4(clip, 0.0, 1.0);\n v_color = a_color;\n}\n";
3
+ export declare const RECT_SHADER_GL_FRAG = "#version 300 es\nprecision highp float;\n\nuniform vec2 u_blend;\n\nin vec4 v_color;\nout vec4 fragColor;\n\n// sRGB to linear conversion for proper blending\nfloat srgbToLinear(float c) {\n if (c <= 0.04045) {\n return c / 12.92;\n }\n return pow((c + 0.055) / 1.055, 2.4);\n}\n\nvec3 srgbToLinear(vec3 c) {\n return vec3(srgbToLinear(c.r), srgbToLinear(c.g), srgbToLinear(c.b));\n}\n\nvoid main() {\n bool useLinear = u_blend.x > 0.5;\n vec4 color = v_color;\n if (useLinear) {\n color.rgb = srgbToLinear(color.rgb);\n }\n color.rgb *= color.a;\n fragColor = color;\n}\n";
4
+ export declare const GLYPH_SHADER_GL_VERT = "#version 300 es\nprecision highp float;\n\nuniform vec2 u_resolution;\n\nlayout(location = 0) in vec2 a_quad;\nlayout(location = 1) in vec2 a_pos;\nlayout(location = 2) in vec2 a_size;\nlayout(location = 3) in vec2 a_uv0;\nlayout(location = 4) in vec2 a_uv1;\nlayout(location = 5) in vec4 a_color;\nlayout(location = 6) in vec4 a_bg;\nlayout(location = 7) in float a_slant;\nlayout(location = 8) in float a_mode;\n\nout vec2 v_uv;\nout vec4 v_color;\nout vec4 v_bg;\nout float v_mode;\n\nvoid main() {\n vec2 pixel = a_pos + vec2(a_quad.x * a_size.x + a_slant * (1.0 - a_quad.y), a_quad.y * a_size.y);\n vec2 clip = vec2(\n (pixel.x / u_resolution.x) * 2.0 - 1.0,\n 1.0 - (pixel.y / u_resolution.y) * 2.0\n );\n v_uv = a_uv0 + (a_uv1 - a_uv0) * a_quad;\n gl_Position = vec4(clip, 0.0, 1.0);\n v_color = a_color;\n v_bg = a_bg;\n v_mode = a_mode;\n}\n";
5
+ export declare const GLYPH_SHADER_GL_FRAG = "#version 300 es\nprecision highp float;\n\nuniform sampler2D u_atlas;\nuniform vec2 u_blend;\n\nin vec2 v_uv;\nin vec4 v_color;\nin vec4 v_bg;\nin float v_mode;\nout vec4 fragColor;\n\n// sRGB to linear conversion for proper blending\nfloat srgbToLinear(float c) {\n if (c <= 0.04045) {\n return c / 12.92;\n }\n return pow((c + 0.055) / 1.055, 2.4);\n}\n\n// Linear to sRGB conversion\nfloat linearToSrgb(float c) {\n if (c <= 0.0031308) {\n return c * 12.92;\n }\n return 1.055 * pow(c, 1.0 / 2.4) - 0.055;\n}\n\nvec3 srgbToLinear(vec3 c) {\n return vec3(srgbToLinear(c.r), srgbToLinear(c.g), srgbToLinear(c.b));\n}\n\nvec3 linearToSrgb(vec3 c) {\n return vec3(linearToSrgb(c.r), linearToSrgb(c.g), linearToSrgb(c.b));\n}\n\nfloat luminance(vec3 color) {\n return dot(color, vec3(0.2126, 0.7152, 0.0722));\n}\n\nvoid main() {\n vec4 sample = texture(u_atlas, v_uv);\n bool useLinear = u_blend.x > 0.5;\n bool useCorrection = u_blend.y > 0.5;\n\n if (v_mode > 0.5) {\n vec4 color = sample;\n if (useLinear) {\n color.rgb = srgbToLinear(color.rgb);\n }\n color.rgb *= color.a;\n fragColor = color;\n return;\n }\n\n vec4 fg = v_color;\n vec4 bg = v_bg;\n if (useLinear) {\n fg.rgb = srgbToLinear(fg.rgb);\n bg.rgb = srgbToLinear(bg.rgb);\n }\n fg.rgb *= fg.a;\n bg.rgb *= bg.a;\n\n float alpha = sample.a;\n if (useCorrection && useLinear) {\n float fg_l = luminance(fg.rgb);\n float bg_l = luminance(bg.rgb);\n if (abs(fg_l - bg_l) > 0.001) {\n float blend_l = srgbToLinear(linearToSrgb(fg_l) * alpha + linearToSrgb(bg_l) * (1.0 - alpha));\n alpha = clamp((blend_l - bg_l) / (fg_l - bg_l), 0.0, 1.0);\n }\n }\n\n vec4 color = fg * alpha;\n fragColor = color;\n}\n";
6
+ export declare const GLYPH_SHADER = "\nstruct Uniforms {\n res: vec2f,\n _pad: vec2f,\n blend: vec2f,\n _pad2: vec2f,\n};\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(0) @binding(1) var atlasSampler: sampler;\n@group(0) @binding(2) var atlasTex: texture_2d<f32>;\n\nstruct VSIn {\n @location(0) quad: vec2f,\n @location(1) pos: vec2f,\n @location(2) size: vec2f,\n @location(3) uv0: vec2f,\n @location(4) uv1: vec2f,\n @location(5) color: vec4f,\n @location(6) bg: vec4f,\n @location(7) slant: f32,\n @location(8) mode: f32,\n};\n\nstruct VSOut {\n @builtin(position) position: vec4f,\n @location(0) uv: vec2f,\n @location(1) color: vec4f,\n @location(2) bg: vec4f,\n @location(3) mode: f32,\n};\n\n@vertex\nfn vsMain(input: VSIn) -> VSOut {\n let pixel = input.pos +\n vec2f(input.quad.x * input.size.x + input.slant * (1.0 - input.quad.y), input.quad.y * input.size.y);\n let clip = vec2f(\n (pixel.x / uniforms.res.x) * 2.0 - 1.0,\n 1.0 - (pixel.y / uniforms.res.y) * 2.0\n );\n let uv = input.uv0 + (input.uv1 - input.uv0) * input.quad;\n\n var out: VSOut;\n out.position = vec4f(clip.x, clip.y, 0.0, 1.0);\n out.uv = uv;\n out.color = input.color;\n out.bg = input.bg;\n out.mode = input.mode;\n return out;\n}\n\n// sRGB to linear conversion for proper blending\nfn srgbToLinear(c: f32) -> f32 {\n if (c <= 0.04045) {\n return c / 12.92;\n }\n return pow((c + 0.055) / 1.055, 2.4);\n}\n\n// Linear to sRGB conversion\nfn linearToSrgb(c: f32) -> f32 {\n if (c <= 0.0031308) {\n return c * 12.92;\n }\n return 1.055 * pow(c, 1.0 / 2.4) - 0.055;\n}\n\nfn srgbToLinear3(c: vec3f) -> vec3f {\n return vec3f(srgbToLinear(c.x), srgbToLinear(c.y), srgbToLinear(c.z));\n}\n\nfn linearToSrgb3(c: vec3f) -> vec3f {\n return vec3f(linearToSrgb(c.x), linearToSrgb(c.y), linearToSrgb(c.z));\n}\n\nfn luminance(color: vec3f) -> f32 {\n return dot(color, vec3f(0.2126, 0.7152, 0.0722));\n}\n\n@fragment\nfn fsMain(input: VSOut) -> @location(0) vec4f {\n let sample = textureSample(atlasTex, atlasSampler, input.uv);\n let useLinear = uniforms.blend.x > 0.5;\n let useCorrection = uniforms.blend.y > 0.5;\n\n if (input.mode > 0.5) {\n var color = sample;\n if (useLinear) {\n color = vec4f(srgbToLinear3(color.rgb), color.a);\n }\n return vec4f(color.rgb * color.a, color.a);\n }\n\n var alpha = sample.a;\n\n var fg = input.color;\n var bg = input.bg;\n if (useLinear) {\n fg = vec4f(srgbToLinear3(fg.rgb), fg.a);\n bg = vec4f(srgbToLinear3(bg.rgb), bg.a);\n }\n fg = vec4f(fg.rgb * fg.a, fg.a);\n bg = vec4f(bg.rgb * bg.a, bg.a);\n\n if (useCorrection && useLinear) {\n let fg_l = luminance(fg.rgb);\n let bg_l = luminance(bg.rgb);\n if (abs(fg_l - bg_l) > 0.001) {\n let blend_l = srgbToLinear(linearToSrgb(fg_l) * alpha + linearToSrgb(bg_l) * (1.0 - alpha));\n alpha = clamp((blend_l - bg_l) / (fg_l - bg_l), 0.0, 1.0);\n }\n }\n\n var color = fg * alpha;\n return color;\n}\n";
7
+ export declare const GLYPH_SHADER_NEAREST = "\nstruct Uniforms {\n res: vec2f,\n _pad: vec2f,\n blend: vec2f,\n _pad2: vec2f,\n};\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(0) @binding(1) var atlasSampler: sampler;\n@group(0) @binding(2) var atlasTex: texture_2d<f32>;\n\nstruct VSIn {\n @location(0) quad: vec2f,\n @location(1) pos: vec2f,\n @location(2) size: vec2f,\n @location(3) uv0: vec2f,\n @location(4) uv1: vec2f,\n @location(5) color: vec4f,\n @location(6) bg: vec4f,\n @location(7) slant: f32,\n @location(8) mode: f32,\n};\n\nstruct VSOut {\n @builtin(position) position: vec4f,\n @location(0) uv: vec2f,\n @location(1) color: vec4f,\n @location(2) bg: vec4f,\n @location(3) mode: f32,\n};\n\n@vertex\nfn vsMain(input: VSIn) -> VSOut {\n let pixel = input.pos +\n vec2f(input.quad.x * input.size.x + input.slant * (1.0 - input.quad.y), input.quad.y * input.size.y);\n let clip = vec2f(\n (pixel.x / uniforms.res.x) * 2.0 - 1.0,\n 1.0 - (pixel.y / uniforms.res.y) * 2.0\n );\n let uv = input.uv0 + (input.uv1 - input.uv0) * input.quad;\n\n var out: VSOut;\n out.position = vec4f(clip.x, clip.y, 0.0, 1.0);\n out.uv = uv;\n out.color = input.color;\n out.bg = input.bg;\n out.mode = input.mode;\n return out;\n}\n\n// sRGB to linear conversion for proper blending\nfn srgbToLinear(c: f32) -> f32 {\n if (c <= 0.04045) {\n return c / 12.92;\n }\n return pow((c + 0.055) / 1.055, 2.4);\n}\n\n// Linear to sRGB conversion\nfn linearToSrgb(c: f32) -> f32 {\n if (c <= 0.0031308) {\n return c * 12.92;\n }\n return 1.055 * pow(c, 1.0 / 2.4) - 0.055;\n}\n\nfn srgbToLinear3(c: vec3f) -> vec3f {\n return vec3f(srgbToLinear(c.x), srgbToLinear(c.y), srgbToLinear(c.z));\n}\n\nfn linearToSrgb3(c: vec3f) -> vec3f {\n return vec3f(linearToSrgb(c.x), linearToSrgb(c.y), linearToSrgb(c.z));\n}\n\nfn luminance(color: vec3f) -> f32 {\n return dot(color, vec3f(0.2126, 0.7152, 0.0722));\n}\n\n@fragment\nfn fsMain(input: VSOut) -> @location(0) vec4f {\n let sample = textureSample(atlasTex, atlasSampler, input.uv);\n let useLinear = uniforms.blend.x > 0.5;\n let useCorrection = uniforms.blend.y > 0.5;\n\n if (input.mode > 0.5) {\n var color = sample;\n if (useLinear) {\n color = vec4f(srgbToLinear3(color.rgb), color.a);\n }\n return vec4f(color.rgb * color.a, color.a);\n }\n\n var alpha = sample.a;\n\n var fg = input.color;\n var bg = input.bg;\n if (useLinear) {\n fg = vec4f(srgbToLinear3(fg.rgb), fg.a);\n bg = vec4f(srgbToLinear3(bg.rgb), bg.a);\n }\n fg = vec4f(fg.rgb * fg.a, fg.a);\n bg = vec4f(bg.rgb * bg.a, bg.a);\n\n if (useCorrection && useLinear) {\n let fg_l = luminance(fg.rgb);\n let bg_l = luminance(bg.rgb);\n if (abs(fg_l - bg_l) > 0.001) {\n let blend_l = srgbToLinear(linearToSrgb(fg_l) * alpha + linearToSrgb(bg_l) * (1.0 - alpha));\n alpha = clamp((blend_l - bg_l) / (fg_l - bg_l), 0.0, 1.0);\n }\n }\n\n var color = fg * alpha;\n return color;\n}\n";
@@ -0,0 +1,40 @@
1
+ import type { NerdConstraint } from "../fonts/nerd-constraints";
2
+ export type Color = [number, number, number, number];
3
+ export type RectData = number[];
4
+ export type NerdMetrics = {
5
+ cellWidth: number;
6
+ cellHeight: number;
7
+ faceWidth: number;
8
+ faceHeight: number;
9
+ faceY: number;
10
+ iconHeight: number;
11
+ iconHeightSingle: number;
12
+ };
13
+ export type GlyphBox = {
14
+ x: number;
15
+ y: number;
16
+ width: number;
17
+ height: number;
18
+ };
19
+ export declare const BOX_STYLE_NONE = 0;
20
+ export declare const BOX_STYLE_LIGHT = 1;
21
+ export declare const BOX_STYLE_HEAVY = 2;
22
+ export declare const BOX_STYLE_DOUBLE = 3;
23
+ export declare function isPrivateUse(cp: number): boolean;
24
+ export declare function isSpaceCp(cp: number): boolean;
25
+ export declare function isBoxDrawing(cp: number): boolean;
26
+ export declare function isBlockElement(cp: number): boolean;
27
+ export declare function isLegacyComputing(cp: number): boolean;
28
+ export declare function isPowerline(cp: number): boolean;
29
+ export declare function isBraille(cp: number): boolean;
30
+ export declare function isGraphicsElement(cp: number): boolean;
31
+ export declare function isSymbolCp(cp: number): boolean;
32
+ export declare function applyAlpha(color: Color, alpha: number): Color;
33
+ export declare function pushRect(out: RectData, x: number, y: number, w: number, h: number, color: Color): void;
34
+ export declare function pushRectSnapped(out: RectData, x: number, y: number, w: number, h: number, color: Color): void;
35
+ export declare function pushRectBox(out: RectData, x: number, y: number, w: number, h: number, color: Color): void;
36
+ export declare function drawBlockElement(cp: number, x: number, y: number, cellW: number, cellH: number, color: Color, out: RectData): boolean;
37
+ export declare function drawBoxDrawing(cp: number, x: number, y: number, cellW: number, cellH: number, color: Color, out: RectData): boolean;
38
+ export declare function drawBraille(cp: number, x: number, y: number, cellW: number, cellH: number, color: Color, out: RectData): boolean;
39
+ export declare function drawPowerline(cp: number, x: number, y: number, cellW: number, cellH: number, color: Color, out: RectData): boolean;
40
+ export declare function constrainGlyphBox(glyph: GlyphBox, constraint: NerdConstraint, metrics: NerdMetrics, constraintWidth: number): GlyphBox;
@@ -0,0 +1,80 @@
1
+ import type { Color } from "./shapes";
2
+ export type WebGPUState = {
3
+ device: GPUDevice;
4
+ context: GPUCanvasContext;
5
+ format: GPUTextureFormat;
6
+ srgbSwapchain: boolean;
7
+ rectPipeline: GPURenderPipeline;
8
+ glyphPipeline: GPURenderPipeline;
9
+ glyphPipelineNearest: GPURenderPipeline;
10
+ rectBindGroup: GPUBindGroup;
11
+ uniformBuffer: GPUBuffer;
12
+ vertexBuffer: GPUBuffer;
13
+ rectInstanceBuffer: GPUBuffer;
14
+ rectCapacity: number;
15
+ glyphInstanceBuffer: GPUBuffer;
16
+ glyphCapacity: number;
17
+ glyphAtlases: Map<number, AtlasState>;
18
+ };
19
+ export type AtlasState = {
20
+ texture: GPUTexture;
21
+ sampler?: GPUSampler;
22
+ samplerNearest?: GPUSampler;
23
+ samplerLinear?: GPUSampler;
24
+ bindGroup: GPUBindGroup;
25
+ bindGroupNearest?: GPUBindGroup;
26
+ bindGroupLinear?: GPUBindGroup;
27
+ width: number;
28
+ height: number;
29
+ inset: number;
30
+ colorGlyphs?: Set<number>;
31
+ constrainedGlyphWidths?: Map<number, number>;
32
+ nearest?: boolean;
33
+ };
34
+ export type WebGLState = {
35
+ gl: WebGL2RenderingContext;
36
+ rectProgram: WebGLProgram;
37
+ glyphProgram: WebGLProgram;
38
+ rectResolutionLoc: WebGLUniformLocation;
39
+ rectBlendLoc: WebGLUniformLocation;
40
+ glyphResolutionLoc: WebGLUniformLocation;
41
+ glyphBlendLoc: WebGLUniformLocation;
42
+ glyphAtlasLoc: WebGLUniformLocation;
43
+ quadBuffer: WebGLBuffer;
44
+ rectVao: WebGLVertexArrayObject;
45
+ glyphVao: WebGLVertexArrayObject;
46
+ rectInstanceBuffer: WebGLBuffer;
47
+ glyphInstanceBuffer: WebGLBuffer;
48
+ rectCapacity: number;
49
+ glyphCapacity: number;
50
+ glyphAtlases: Map<number, WebGLAtlasState>;
51
+ };
52
+ export type WebGLAtlasState = {
53
+ texture: WebGLTexture;
54
+ width: number;
55
+ height: number;
56
+ inset: number;
57
+ colorGlyphs?: Set<number>;
58
+ constrainedGlyphWidths?: Map<number, number>;
59
+ nearest?: boolean;
60
+ };
61
+ export type RendererState = WebGPUState | WebGLState | null;
62
+ export type RendererConfig = {
63
+ defaultBg: Color;
64
+ defaultFg: Color;
65
+ selectionColor: Color;
66
+ cursorFallback: Color;
67
+ };
68
+ export type ResizeState = {
69
+ active: boolean;
70
+ lastAt: number;
71
+ cols: number;
72
+ rows: number;
73
+ dpr: number;
74
+ };
75
+ export type ScrollbarState = {
76
+ lastInputAt: number;
77
+ lastTotal: number;
78
+ lastOffset: number;
79
+ lastLen: number;
80
+ };
@@ -0,0 +1,19 @@
1
+ import type { WebGPUState, WebGLState } from "./types";
2
+ export declare function initWebGPU(canvas: HTMLCanvasElement): Promise<WebGPUState | null>;
3
+ export declare function initWebGL(canvas: HTMLCanvasElement): WebGLState | null;
4
+ export declare function ensureInstanceBuffer(state: WebGPUState, kind: "rect" | "glyph", byteLength: number): void;
5
+ export declare function configureContext(state: WebGPUState): void;
6
+ export declare function ensureGLInstanceBuffer(state: WebGLState, kind: "rect" | "glyph", byteLength: number): void;
7
+ export declare function createResizeState(): {
8
+ active: boolean;
9
+ lastAt: number;
10
+ cols: number;
11
+ rows: number;
12
+ dpr: number;
13
+ };
14
+ export declare function createScrollbarState(): {
15
+ lastInputAt: number;
16
+ lastTotal: number;
17
+ lastOffset: number;
18
+ lastLen: number;
19
+ };
@@ -0,0 +1 @@
1
+ export * from "./input/index";
@@ -0,0 +1,2 @@
1
+ export * from "./types";
2
+ export * from "./selection";
@@ -0,0 +1,13 @@
1
+ import type { CellPosition, SelectionRange, SelectionState } from "./types";
2
+ export declare function createSelectionState(): SelectionState;
3
+ export declare function clearSelection(state: SelectionState): void;
4
+ export declare function startSelection(state: SelectionState, cell: CellPosition): void;
5
+ export declare function updateSelection(state: SelectionState, cell: CellPosition): void;
6
+ export declare function endSelection(state: SelectionState, cell: CellPosition): boolean;
7
+ export declare function selectionForRow(state: SelectionState, row: number, cols: number): SelectionRange | null;
8
+ export type CellTextGetter = (idx: number) => string;
9
+ export declare function getSelectionText(state: SelectionState, rows: number, cols: number, getCellText: CellTextGetter): string;
10
+ export declare function normalizeSelectionCell(cell: CellPosition | null, rows: number, cols: number, wideFlags?: Uint8Array | null): CellPosition | null;
11
+ export declare function positionToCell(clientX: number, clientY: number, canvasRect: DOMRect, dpr: number, cellW: number, cellH: number, cols: number, rows: number): CellPosition;
12
+ export declare function copyToClipboard(text: string): Promise<boolean>;
13
+ export declare function pasteFromClipboard(): Promise<string | null>;
@@ -0,0 +1,14 @@
1
+ export type CellPosition = {
2
+ row: number;
3
+ col: number;
4
+ };
5
+ export type SelectionState = {
6
+ active: boolean;
7
+ dragging: boolean;
8
+ anchor: CellPosition | null;
9
+ focus: CellPosition | null;
10
+ };
11
+ export type SelectionRange = {
12
+ start: number;
13
+ end: number;
14
+ };
@@ -0,0 +1,3 @@
1
+ export declare const BUILTIN_THEME_NAMES: readonly ["0x96f", "12-bit Rainbow", "3024 Day", "3024 Night", "Aardvark Blue", "Abernathy", "Adventure", "Adventure Time", "Adwaita", "Adwaita Dark", "Afterglow", "Aizen Dark", "Aizen Light", "Alabaster", "Alien Blood", "Andromeda", "Apple Classic", "Apple System Colors", "Apple System Colors Light", "Arcoiris", "Ardoise", "Argonaut", "Arthur", "Atelier Sulphurpool", "Atom", "Atom One Dark", "Atom One Light", "Aura", "Aurora", "Ayu", "Ayu Light", "Ayu Mirage", "Banana Blueberry", "Batman", "Belafonte Day", "Belafonte Night", "Birds Of Paradise", "Black Metal", "Black Metal (Bathory)", "Black Metal (Burzum)", "Black Metal (Dark Funeral)", "Black Metal (Gorgoroth)", "Black Metal (Immortal)", "Black Metal (Khold)", "Black Metal (Marduk)", "Black Metal (Mayhem)", "Black Metal (Nile)", "Black Metal (Venom)", "Blazer", "Blue Berry Pie", "Blue Dolphin", "Blue Matrix", "Bluloco Dark", "Bluloco Light", "Borland", "Box", "branch", "Breadog", "Breeze", "Bright Lights", "Broadcast", "Brogrammer", "Builtin Dark", "Builtin Light", "Builtin Pastel Dark", "Builtin Tango Dark", "Builtin Tango Light", "C64", "Calamity", "Carbonfox", "Catppuccin Frappe", "Catppuccin Latte", "Catppuccin Macchiato", "Catppuccin Mocha", "CGA", "Chalk", "Chalkboard", "Challenger Deep", "Chester", "Ciapre", "Citruszest", "CLRS", "Cobalt Neon", "Cobalt Next", "Cobalt Next Dark", "Cobalt Next Minimal", "Cobalt2", "Coffee Theme", "Crayon Pony Fish", "Cursor Dark", "Cutie Pro", "Cyberdyne", "Cyberpunk", "Cyberpunk Scarlet Protocol", "Dark Modern", "Dark Pastel", "Dark+", "Darkermatrix", "Darkmatrix", "Darkside", "Dawnfox", "Dayfox", "Deep", "Desert", "Detuned", "Dimidium", "Dimmed Monokai", "Django", "Django Reborn Again", "Django Smooth", "Doom One", "Doom Peacock", "Dot Gov", "Dracula", "Dracula+", "Duckbones", "Duotone Dark", "Duskfox", "Earthsong", "Electron Highlighter", "Elegant", "Elemental", "Elementary", "Embark", "Embers Dark", "ENCOM", "Espresso", "Espresso Libre", "Everblush", "Everforest Dark Hard", "Everforest Light Med", "Fahrenheit", "Fairyfloss", "Farmhouse Dark", "Farmhouse Light", "Fideloper", "Firefly Traditional", "Firefox Dev", "Firewatch", "Fish Tank", "Flat", "Flatland", "Flexoki Dark", "Flexoki Light", "Floraverse", "Forest Blue", "Framer", "Front End Delight", "Fun Forrest", "Galaxy", "Galizur", "Ghostty Default Style Dark", "GitHub", "GitHub Dark", "GitHub Dark Colorblind", "GitHub Dark Default", "GitHub Dark Dimmed", "GitHub Dark High Contrast", "GitHub Light Colorblind", "GitHub Light Default", "GitHub Light High Contrast", "GitLab Dark", "GitLab Dark Grey", "GitLab Light", "Glacier", "Grape", "Grass", "Grey Green", "Gruber Darker", "Gruvbox Dark", "Gruvbox Dark Hard", "Gruvbox Light", "Gruvbox Light Hard", "Gruvbox Material", "Gruvbox Material Dark", "Gruvbox Material Light", "Guezwhoz", "Hacktober", "Hardcore", "Harper", "Havn Daggry", "Havn Skumring", "HaX0R Blue", "HaX0R Gr33N", "HaX0R R3D", "Heeler", "Highway", "Hipster Green", "Hivacruz", "Homebrew", "Hopscotch", "Hopscotch.256", "Horizon", "Horizon Bright", "Hot Dog Stand", "Hot Dog Stand (Mustard)", "Hurtado", "Hybrid", "IBM 5153 CGA", "IBM 5153 CGA (Black)", "IC Green PPL", "IC Orange PPL", "Iceberg Dark", "Iceberg Light", "Idea", "Idle Toes", "IR Black", "IRIX Console", "IRIX Terminal", "iTerm2 Dark Background", "iTerm2 Default", "iTerm2 Light Background", "iTerm2 Pastel Dark Background", "iTerm2 Smoooooth", "iTerm2 Solarized Dark", "iTerm2 Solarized Light", "iTerm2 Tango Dark", "iTerm2 Tango Light", "Jackie Brown", "Japanesque", "Jellybeans", "JetBrains Darcula", "Jubi", "Kanagawa Dragon", "Kanagawa Lotus", "Kanagawa Wave", "Kanagawabones", "Kanso Ink", "Kanso Mist", "Kanso Pearl", "Kanso Zen", "Kibble", "Kitty Default", "Kitty Low Contrast", "Kolorit", "Konsolas", "Kurokula", "Lab Fox", "Laser", "Later This Evening", "Lavandula", "Light Owl", "Liquid Carbon", "Liquid Carbon Transparent", "Lovelace", "Man Page", "Mariana", "Material", "Material Dark", "Material Darker", "Material Design Colors", "Material Ocean", "Mathias", "Matrix", "Matte Black", "Medallion", "Melange Dark", "Melange Light", "Mellifluous", "Mellow", "Miasma", "Midnight In Mojave", "Mirage", "Misterioso", "Molokai", "Mona Lisa", "Monokai Classic", "Monokai Pro", "Monokai Pro Light", "Monokai Pro Light Sun", "Monokai Pro Machine", "Monokai Pro Octagon", "Monokai Pro Ristretto", "Monokai Pro Spectrum", "Monokai Remastered", "Monokai Soda", "Monokai Vivid", "Moonfly", "N0Tch2K", "Neobones Dark", "Neobones Light", "Neon", "Neopolitan", "Neutron", "Night Lion V1", "Night Lion V2", "Night Owl", "Night Owlish Light", "Nightfox", "Niji", "No Clown Fiesta", "No Clown Fiesta Light", "Nocturnal Winter", "Nord", "Nord Light", "Nord Wave", "Nordfox", "Novel", "novmbr", "Nvim Dark", "Nvim Light", "Obsidian", "Ocean", "Oceanic Material", "Oceanic Next", "Ollie", "One Dark Two", "One Double Dark", "One Double Light", "One Half Dark", "One Half Light", "Onenord", "Onenord Light", "Operator Mono Dark", "Overnight Slumber", "owl", "Oxocarbon", "Pale Night Hc", "Pandora", "Paraiso Dark", "Paul Millr", "Pencil Dark", "Pencil Light", "Peppermint", "Phala Green Dark", "Piatto Light", "Pnevma", "Poimandres", "Poimandres Darker", "Poimandres Storm", "Poimandres White", "Popping And Locking", "Powershell", "Primary", "Pro", "Pro Light", "Purple Rain", "Purplepeter", "Rapture", "Raycast Dark", "Raycast Light", "Rebecca", "Red Alert", "Red Planet", "Red Sands", "Relaxed", "Retro", "Retro Legends", "Rippedcasts", "Rose Pine", "Rose Pine Dawn", "Rose Pine Moon", "Rouge 2", "Royal", "Ryuuko", "Sakura", "Scarlet Protocol", "Sea Shells", "Seafoam Pastel", "Selenized Black", "Selenized Dark", "Selenized Light", "Seoulbones Dark", "Seoulbones Light", "Seti", "Shades Of Purple", "Shaman", "Slate", "Sleepy Hollow", "Smyck", "Snazzy", "Snazzy Soft", "Soft Server", "Solarized Darcula", "Solarized Dark Higher Contrast", "Solarized Dark Patched", "Solarized Osaka Night", "Sonokai", "Spacedust", "Spacegray", "Spacegray Bright", "Spacegray Eighties", "Spacegray Eighties Dull", "Spiderman", "Spring", "Square", "Squirrelsong Dark", "Srcery", "Starlight", "Sublette", "Subliminal", "Sugarplum", "Sundried", "Symfonic", "Synthwave", "Synthwave Alpha", "Synthwave Everything", "Tango Adapted", "Tango Half Adapted", "Tearout", "Teerb", "Terafox", "Terminal Basic", "Terminal Basic Dark", "Thayer Bright", "The Hulk", "Tinacious Design Dark", "Tinacious Design Light", "TokyoNight", "TokyoNight Day", "TokyoNight Moon", "TokyoNight Night", "TokyoNight Storm", "Tomorrow", "Tomorrow Night", "Tomorrow Night Blue", "Tomorrow Night Bright", "Tomorrow Night Burns", "Tomorrow Night Eighties", "Toy Chest", "traffic", "Treehouse", "Twilight", "Ubuntu", "Ultra Dark", "Ultra Violent", "Under The Sea", "Unikitty", "urban", "Urple", "Vague", "Vaughn", "Vercel", "Vesper", "Vibrant Ink", "Vimbones", "Violet Dark", "Violet Light", "Violite", "Warm Neon", "Wez", "Whimsy", "Wild Cherry", "Wilmersdorf", "Wombat", "Wryan", "Xcode Dark", "Xcode Dark hc", "Xcode Light", "Xcode Light hc", "Xcode WWDC", "Zenbones", "Zenbones Dark", "Zenbones Light", "Zenburn", "Zenburned", "Zenwritten Dark", "Zenwritten Light"];
2
+ export type BuiltinThemeName = (typeof BUILTIN_THEME_NAMES)[number];
3
+ export declare const BUILTIN_THEME_SOURCES: Record<BuiltinThemeName, string>;
@@ -0,0 +1,7 @@
1
+ import { type GhosttyTheme } from "./ghostty";
2
+ import { type BuiltinThemeName } from "./builtin-themes";
3
+ export type ResttyBuiltinThemeName = BuiltinThemeName;
4
+ export declare function listBuiltinThemeNames(): ResttyBuiltinThemeName[];
5
+ export declare function isBuiltinThemeName(name: string): name is ResttyBuiltinThemeName;
6
+ export declare function getBuiltinThemeSource(name: string): string | null;
7
+ export declare function getBuiltinTheme(name: string): GhosttyTheme | null;
@@ -0,0 +1,23 @@
1
+ export type ThemeColor = {
2
+ r: number;
3
+ g: number;
4
+ b: number;
5
+ a?: number;
6
+ };
7
+ export type GhosttyTheme = {
8
+ name?: string;
9
+ colors: {
10
+ background?: ThemeColor;
11
+ foreground?: ThemeColor;
12
+ cursor?: ThemeColor;
13
+ cursorText?: ThemeColor;
14
+ selectionBackground?: ThemeColor;
15
+ selectionForeground?: ThemeColor;
16
+ palette: Array<ThemeColor | undefined>;
17
+ };
18
+ raw: Record<string, string>;
19
+ };
20
+ export declare function parseGhosttyColor(value: string): ThemeColor | null;
21
+ export declare function colorToFloats(color: ThemeColor, alphaOverride?: number): [number, number, number, number];
22
+ export declare function colorToRgbU32(color: ThemeColor): number;
23
+ export declare function parseGhosttyTheme(text: string): GhosttyTheme;
@@ -0,0 +1,2 @@
1
+ export * from "./ghostty";
2
+ export * from "./catalog";