@gridland/web 0.2.16 → 0.2.18
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/dist/index.d.ts +1 -0
- package/dist/index.js +99 -10
- package/dist/index.js.map +4 -4
- package/dist/vite-plugin.js +68 -37
- package/dist/vite-plugin.js.map +1 -1
- package/package.json +5 -4
- package/src/browser-buffer.ts +715 -0
- package/src/core-shims/index.ts +269 -0
- package/src/core-shims/renderable-types.ts +4 -0
- package/src/core-shims/rgba.ts +195 -0
- package/src/core-shims/types.ts +132 -0
- package/src/shims/bun-ffi-structs.ts +20 -0
- package/src/shims/bun-ffi.ts +28 -0
- package/src/shims/console-stub.ts +13 -0
- package/src/shims/console.ts +3 -0
- package/src/shims/devtools-polyfill-stub.ts +3 -0
- package/src/shims/edit-buffer-stub.ts +475 -0
- package/src/shims/editor-view-stub.ts +388 -0
- package/src/shims/events-shim.ts +81 -0
- package/src/shims/filters-stub.ts +4 -0
- package/src/shims/hast-stub.ts +8 -0
- package/src/shims/native-span-feed-stub.ts +7 -0
- package/src/shims/node-buffer.ts +39 -0
- package/src/shims/node-fs.ts +20 -0
- package/src/shims/node-os.ts +6 -0
- package/src/shims/node-path.ts +35 -0
- package/src/shims/node-stream.ts +10 -0
- package/src/shims/node-url.ts +8 -0
- package/src/shims/node-util.ts +33 -0
- package/src/shims/renderer-stub.ts +21 -0
- package/src/shims/slider-deps.ts +8 -0
- package/src/shims/syntax-style-shim.ts +23 -0
- package/src/shims/text-buffer-shim.ts +3 -0
- package/src/shims/text-buffer-view-shim.ts +2 -0
- package/src/shims/timeline-stub.ts +43 -0
- package/src/shims/tree-sitter-stub.ts +47 -0
- package/src/shims/tree-sitter-styled-text-stub.ts +8 -0
- package/src/shims/zig-stub.ts +20 -0
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
// Core shims barrel — aliased as @opentui/core by Vite
|
|
2
|
+
// Re-exports portable code from opentui and swaps in browser replacements.
|
|
3
|
+
// Vite aliases intercept zig, buffer, text-buffer, text-buffer-view,
|
|
4
|
+
// syntax-style, renderer, console, etc. before they reach the filesystem.
|
|
5
|
+
|
|
6
|
+
// ─── Pure TS re-exports ───────────────────────────────────────────────────
|
|
7
|
+
|
|
8
|
+
// RGBA and color utilities (our own copy to avoid pulling in opentui's lib/index)
|
|
9
|
+
export { RGBA, parseColor, hexToRgb, rgbToHex, hsvToRgb } from "./rgba"
|
|
10
|
+
export type { ColorInput } from "./rgba"
|
|
11
|
+
|
|
12
|
+
// Types
|
|
13
|
+
export {
|
|
14
|
+
TextAttributes,
|
|
15
|
+
ATTRIBUTE_BASE_BITS,
|
|
16
|
+
ATTRIBUTE_BASE_MASK,
|
|
17
|
+
getBaseAttributes,
|
|
18
|
+
DebugOverlayCorner,
|
|
19
|
+
} from "./types"
|
|
20
|
+
export type {
|
|
21
|
+
RenderContext,
|
|
22
|
+
ThemeMode,
|
|
23
|
+
CursorStyle,
|
|
24
|
+
CursorStyleOptions,
|
|
25
|
+
MousePointerStyle,
|
|
26
|
+
WidthMethod,
|
|
27
|
+
Timeout,
|
|
28
|
+
ViewportBounds,
|
|
29
|
+
Highlight,
|
|
30
|
+
LineInfo,
|
|
31
|
+
LineInfoProvider,
|
|
32
|
+
CapturedSpan,
|
|
33
|
+
CapturedLine,
|
|
34
|
+
CapturedFrame,
|
|
35
|
+
} from "./types"
|
|
36
|
+
|
|
37
|
+
// ─── Re-exports from opentui source (Vite intercepts Zig deps) ───────────
|
|
38
|
+
|
|
39
|
+
// Renderable base classes (needed by our own code — main.tsx uses RootRenderable)
|
|
40
|
+
// NOTE: The opentui react package imports from the real opentui barrel instead
|
|
41
|
+
// (redirected by the Vite plugin) to avoid cross-barrel circular dependency issues.
|
|
42
|
+
export {
|
|
43
|
+
Renderable,
|
|
44
|
+
BaseRenderable,
|
|
45
|
+
RootRenderable,
|
|
46
|
+
LayoutEvents,
|
|
47
|
+
RenderableEvents,
|
|
48
|
+
isRenderable,
|
|
49
|
+
} from "../../../../opentui/packages/core/src/Renderable"
|
|
50
|
+
export type {
|
|
51
|
+
RenderableOptions,
|
|
52
|
+
LayoutOptions,
|
|
53
|
+
BaseRenderableOptions,
|
|
54
|
+
Position,
|
|
55
|
+
RenderCommand,
|
|
56
|
+
} from "../../../../opentui/packages/core/src/Renderable"
|
|
57
|
+
|
|
58
|
+
// Border (pure TS)
|
|
59
|
+
export {
|
|
60
|
+
BorderChars,
|
|
61
|
+
BorderCharArrays,
|
|
62
|
+
isValidBorderStyle,
|
|
63
|
+
parseBorderStyle,
|
|
64
|
+
getBorderFromSides,
|
|
65
|
+
getBorderSides,
|
|
66
|
+
borderCharsToArray,
|
|
67
|
+
} from "../../../../opentui/packages/core/src/lib/border"
|
|
68
|
+
export type {
|
|
69
|
+
BorderCharacters,
|
|
70
|
+
BorderStyle,
|
|
71
|
+
BorderSides,
|
|
72
|
+
BorderConfig,
|
|
73
|
+
BoxDrawOptions,
|
|
74
|
+
BorderSidesConfig,
|
|
75
|
+
} from "../../../../opentui/packages/core/src/lib/border"
|
|
76
|
+
|
|
77
|
+
// Styled text (pure TS)
|
|
78
|
+
export {
|
|
79
|
+
StyledText,
|
|
80
|
+
isStyledText,
|
|
81
|
+
stringToStyledText,
|
|
82
|
+
t,
|
|
83
|
+
bold,
|
|
84
|
+
italic,
|
|
85
|
+
underline,
|
|
86
|
+
strikethrough,
|
|
87
|
+
dim,
|
|
88
|
+
reverse,
|
|
89
|
+
blink,
|
|
90
|
+
fg,
|
|
91
|
+
bg,
|
|
92
|
+
black,
|
|
93
|
+
red,
|
|
94
|
+
green,
|
|
95
|
+
yellow,
|
|
96
|
+
blue,
|
|
97
|
+
magenta,
|
|
98
|
+
cyan,
|
|
99
|
+
white,
|
|
100
|
+
} from "../../../../opentui/packages/core/src/lib/styled-text"
|
|
101
|
+
|
|
102
|
+
// Yoga options (pure TS)
|
|
103
|
+
export {
|
|
104
|
+
parseAlign,
|
|
105
|
+
parseAlignItems,
|
|
106
|
+
parseFlexDirection,
|
|
107
|
+
parseJustify,
|
|
108
|
+
parseOverflow,
|
|
109
|
+
parsePositionType,
|
|
110
|
+
parseWrap,
|
|
111
|
+
} from "../../../../opentui/packages/core/src/lib/yoga.options"
|
|
112
|
+
export type {
|
|
113
|
+
AlignString,
|
|
114
|
+
FlexDirectionString,
|
|
115
|
+
JustifyString,
|
|
116
|
+
OverflowString,
|
|
117
|
+
PositionTypeString,
|
|
118
|
+
WrapString,
|
|
119
|
+
} from "../../../../opentui/packages/core/src/lib/yoga.options"
|
|
120
|
+
|
|
121
|
+
// Renderable validations (pure TS)
|
|
122
|
+
export {
|
|
123
|
+
validateOptions,
|
|
124
|
+
isPositionType,
|
|
125
|
+
isDimensionType,
|
|
126
|
+
isFlexBasisType,
|
|
127
|
+
isSizeType,
|
|
128
|
+
isMarginType,
|
|
129
|
+
isPaddingType,
|
|
130
|
+
isPositionTypeType,
|
|
131
|
+
isOverflowType,
|
|
132
|
+
} from "../../../../opentui/packages/core/src/lib/renderable.validations"
|
|
133
|
+
|
|
134
|
+
// Selection (pure TS)
|
|
135
|
+
export {
|
|
136
|
+
Selection,
|
|
137
|
+
convertGlobalToLocalSelection,
|
|
138
|
+
} from "../../../../opentui/packages/core/src/lib/selection"
|
|
139
|
+
|
|
140
|
+
// VNode composition (pure TS)
|
|
141
|
+
export { maybeMakeRenderable } from "../../../../opentui/packages/core/src/renderables/composition/vnode"
|
|
142
|
+
export type { VNode } from "../../../../opentui/packages/core/src/renderables/composition/vnode"
|
|
143
|
+
|
|
144
|
+
// ─── Renderable subclasses (re-exported from individual files, not barrel) ─
|
|
145
|
+
|
|
146
|
+
// These are needed by @opentui/react for the component catalogue and host-config.
|
|
147
|
+
// File-level shims (zig, buffer, renderer, etc.) handle their internal imports.
|
|
148
|
+
export * from "../../../../opentui/packages/core/src/renderables/Box"
|
|
149
|
+
export * from "../../../../opentui/packages/core/src/renderables/Text"
|
|
150
|
+
export * from "../../../../opentui/packages/core/src/renderables/TextNode"
|
|
151
|
+
export * from "../../../../opentui/packages/core/src/renderables/Code"
|
|
152
|
+
export * from "../../../../opentui/packages/core/src/renderables/Diff"
|
|
153
|
+
export * from "../../../../opentui/packages/core/src/renderables/Input"
|
|
154
|
+
export * from "../../../../opentui/packages/core/src/renderables/Select"
|
|
155
|
+
export * from "../../../../opentui/packages/core/src/renderables/TabSelect"
|
|
156
|
+
export * from "../../../../opentui/packages/core/src/renderables/Textarea"
|
|
157
|
+
export * from "../../../../opentui/packages/core/src/renderables/ScrollBox"
|
|
158
|
+
export * from "../../../../opentui/packages/core/src/renderables/ScrollBar"
|
|
159
|
+
export * from "../../../../opentui/packages/core/src/renderables/Slider"
|
|
160
|
+
export * from "../../../../opentui/packages/core/src/renderables/ASCIIFont"
|
|
161
|
+
export * from "../../../../opentui/packages/core/src/renderables/LineNumberRenderable"
|
|
162
|
+
export * from "../../../../opentui/packages/core/src/renderables/Markdown"
|
|
163
|
+
export * from "../../../../opentui/packages/core/src/renderables/FrameBuffer"
|
|
164
|
+
export * from "../../../../opentui/packages/core/src/renderables/TextBufferRenderable"
|
|
165
|
+
import { TextBufferRenderable } from "../../../../opentui/packages/core/src/renderables/TextBufferRenderable"
|
|
166
|
+
|
|
167
|
+
// Gridland extension: textAlign property on TextBufferRenderable
|
|
168
|
+
// Proxies to the BrowserTextBufferView's textAlign property for centered text rendering.
|
|
169
|
+
Object.defineProperty(TextBufferRenderable.prototype, "textAlign", {
|
|
170
|
+
get(this: any) {
|
|
171
|
+
return this.textBufferView?.textAlign ?? "left"
|
|
172
|
+
},
|
|
173
|
+
set(this: any, value: "left" | "center" | "right") {
|
|
174
|
+
if (this.textBufferView) {
|
|
175
|
+
this.textBufferView.textAlign = value
|
|
176
|
+
this.requestRender()
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
enumerable: true,
|
|
180
|
+
configurable: true,
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
// ─── Browser replacements ─────────────────────────────────────────────────
|
|
184
|
+
|
|
185
|
+
// Buffer — browser replacement
|
|
186
|
+
export { BrowserBuffer as OptimizedBuffer } from "../browser-buffer"
|
|
187
|
+
|
|
188
|
+
// TextBuffer — browser replacement
|
|
189
|
+
export { BrowserTextBuffer as TextBuffer } from "../browser-text-buffer"
|
|
190
|
+
export type { TextChunk } from "../browser-text-buffer"
|
|
191
|
+
|
|
192
|
+
// TextBufferView — browser replacement
|
|
193
|
+
export { BrowserTextBufferView as TextBufferView } from "../browser-text-buffer-view"
|
|
194
|
+
|
|
195
|
+
// SyntaxStyle — browser stub
|
|
196
|
+
export { BrowserSyntaxStyle as SyntaxStyle } from "../browser-syntax-style"
|
|
197
|
+
|
|
198
|
+
// ─── Stubs ────────────────────────────────────────────────────────────────
|
|
199
|
+
|
|
200
|
+
export function resolveRenderLib(): any {
|
|
201
|
+
return null
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export type RenderLib = any
|
|
205
|
+
export type Pointer = number
|
|
206
|
+
|
|
207
|
+
// KeyHandler (re-implemented for browser)
|
|
208
|
+
export {
|
|
209
|
+
BrowserKeyHandler as KeyHandler,
|
|
210
|
+
BrowserInternalKeyHandler as InternalKeyHandler,
|
|
211
|
+
} from "../browser-render-context"
|
|
212
|
+
|
|
213
|
+
// Renderer — re-exported from shimmed source path (resolved to renderer-stub.ts)
|
|
214
|
+
export {
|
|
215
|
+
CliRenderer,
|
|
216
|
+
CliRenderEvents,
|
|
217
|
+
createCliRenderer,
|
|
218
|
+
} from "../../../../opentui/packages/core/src/renderer"
|
|
219
|
+
export type { MouseEvent } from "../../../../opentui/packages/core/src/renderer"
|
|
220
|
+
|
|
221
|
+
// Timeline & engine — re-exported from shimmed source path (resolved to timeline-stub.ts)
|
|
222
|
+
export {
|
|
223
|
+
Timeline,
|
|
224
|
+
engine,
|
|
225
|
+
createTimeline,
|
|
226
|
+
} from "../../../../opentui/packages/core/src/animation/Timeline"
|
|
227
|
+
|
|
228
|
+
// Yoga re-export
|
|
229
|
+
export * as Yoga from "yoga-layout"
|
|
230
|
+
|
|
231
|
+
// Stub types for mouse
|
|
232
|
+
export type MouseEventType = any
|
|
233
|
+
|
|
234
|
+
// Utils
|
|
235
|
+
export function createTextAttributes(opts: {
|
|
236
|
+
bold?: boolean
|
|
237
|
+
italic?: boolean
|
|
238
|
+
underline?: boolean
|
|
239
|
+
dim?: boolean
|
|
240
|
+
blink?: boolean
|
|
241
|
+
inverse?: boolean
|
|
242
|
+
hidden?: boolean
|
|
243
|
+
strikethrough?: boolean
|
|
244
|
+
} = {}): number {
|
|
245
|
+
const TA = {
|
|
246
|
+
NONE: 0, BOLD: 1, DIM: 2, ITALIC: 4, UNDERLINE: 8,
|
|
247
|
+
BLINK: 16, INVERSE: 32, HIDDEN: 64, STRIKETHROUGH: 128,
|
|
248
|
+
}
|
|
249
|
+
let attr = TA.NONE
|
|
250
|
+
if (opts.bold) attr |= TA.BOLD
|
|
251
|
+
if (opts.italic) attr |= TA.ITALIC
|
|
252
|
+
if (opts.underline) attr |= TA.UNDERLINE
|
|
253
|
+
if (opts.dim) attr |= TA.DIM
|
|
254
|
+
if (opts.blink) attr |= TA.BLINK
|
|
255
|
+
if (opts.inverse) attr |= TA.INVERSE
|
|
256
|
+
if (opts.hidden) attr |= TA.HIDDEN
|
|
257
|
+
if (opts.strikethrough) attr |= TA.STRIKETHROUGH
|
|
258
|
+
return attr
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export function attributesWithLink(baseAttributes: number, linkId: number): number {
|
|
262
|
+
return (baseAttributes & 0xff) | ((linkId & 0xffffff) << 8)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export function getLinkId(attributes: number): number {
|
|
266
|
+
return (attributes >>> 8) & 0xffffff
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export function visualizeRenderableTree(..._args: any[]): void {}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
// Pure-TS RGBA - copied from opentui core for standalone use
|
|
2
|
+
// This avoids importing from opentui which pulls in Zig
|
|
3
|
+
|
|
4
|
+
export class RGBA {
|
|
5
|
+
buffer: Float32Array
|
|
6
|
+
|
|
7
|
+
constructor(buffer: Float32Array) {
|
|
8
|
+
this.buffer = buffer
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
static fromArray(array: Float32Array): RGBA {
|
|
12
|
+
return new RGBA(array)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static fromValues(r: number, g: number, b: number, a: number = 1.0): RGBA {
|
|
16
|
+
return new RGBA(new Float32Array([r, g, b, a]))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static fromInts(r: number, g: number, b: number, a: number = 255): RGBA {
|
|
20
|
+
return new RGBA(new Float32Array([r / 255, g / 255, b / 255, a / 255]))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static fromHex(hex: string): RGBA {
|
|
24
|
+
return hexToRgb(hex)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get r(): number {
|
|
28
|
+
return this.buffer[0]
|
|
29
|
+
}
|
|
30
|
+
set r(v: number) {
|
|
31
|
+
this.buffer[0] = v
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
get g(): number {
|
|
35
|
+
return this.buffer[1]
|
|
36
|
+
}
|
|
37
|
+
set g(v: number) {
|
|
38
|
+
this.buffer[1] = v
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
get b(): number {
|
|
42
|
+
return this.buffer[2]
|
|
43
|
+
}
|
|
44
|
+
set b(v: number) {
|
|
45
|
+
this.buffer[2] = v
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
get a(): number {
|
|
49
|
+
return this.buffer[3]
|
|
50
|
+
}
|
|
51
|
+
set a(v: number) {
|
|
52
|
+
this.buffer[3] = v
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
toInts(): [number, number, number, number] {
|
|
56
|
+
return [
|
|
57
|
+
Math.round(this.buffer[0] * 255),
|
|
58
|
+
Math.round(this.buffer[1] * 255),
|
|
59
|
+
Math.round(this.buffer[2] * 255),
|
|
60
|
+
Math.round(this.buffer[3] * 255),
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
map<R>(fn: (value: number) => R): R[] {
|
|
65
|
+
return [fn(this.buffer[0]), fn(this.buffer[1]), fn(this.buffer[2]), fn(this.buffer[3])]
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
toString(): string {
|
|
69
|
+
const [r, g, b, a] = this.toInts()
|
|
70
|
+
return `rgba(${r}, ${g}, ${b}, ${a / 255})`
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
equals(other?: RGBA): boolean {
|
|
74
|
+
if (!other) return false
|
|
75
|
+
return (
|
|
76
|
+
this.buffer[0] === other.buffer[0] &&
|
|
77
|
+
this.buffer[1] === other.buffer[1] &&
|
|
78
|
+
this.buffer[2] === other.buffer[2] &&
|
|
79
|
+
this.buffer[3] === other.buffer[3]
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export type ColorInput = string | RGBA
|
|
85
|
+
|
|
86
|
+
const CSS_COLOR_NAMES: Record<string, string> = {
|
|
87
|
+
black: "#000000",
|
|
88
|
+
white: "#ffffff",
|
|
89
|
+
red: "#ff0000",
|
|
90
|
+
green: "#008000",
|
|
91
|
+
blue: "#0000ff",
|
|
92
|
+
yellow: "#ffff00",
|
|
93
|
+
cyan: "#00ffff",
|
|
94
|
+
magenta: "#ff00ff",
|
|
95
|
+
silver: "#c0c0c0",
|
|
96
|
+
gray: "#808080",
|
|
97
|
+
grey: "#808080",
|
|
98
|
+
maroon: "#800000",
|
|
99
|
+
olive: "#808000",
|
|
100
|
+
lime: "#00ff00",
|
|
101
|
+
aqua: "#00ffff",
|
|
102
|
+
teal: "#008080",
|
|
103
|
+
navy: "#000080",
|
|
104
|
+
fuchsia: "#ff00ff",
|
|
105
|
+
purple: "#800080",
|
|
106
|
+
orange: "#ffa500",
|
|
107
|
+
transparent: "#00000000",
|
|
108
|
+
brightblack: "#808080",
|
|
109
|
+
brightred: "#ff5555",
|
|
110
|
+
brightgreen: "#55ff55",
|
|
111
|
+
brightyellow: "#ffff55",
|
|
112
|
+
brightblue: "#5555ff",
|
|
113
|
+
brightmagenta: "#ff55ff",
|
|
114
|
+
brightcyan: "#55ffff",
|
|
115
|
+
brightwhite: "#ffffff",
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function hexToRgb(hex: string): RGBA {
|
|
119
|
+
hex = hex.replace(/^#/, "")
|
|
120
|
+
|
|
121
|
+
if (hex.length === 3) {
|
|
122
|
+
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (hex.length === 6) {
|
|
126
|
+
hex = hex + "ff"
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const r = parseInt(hex.substring(0, 2), 16) / 255
|
|
130
|
+
const g = parseInt(hex.substring(2, 4), 16) / 255
|
|
131
|
+
const b = parseInt(hex.substring(4, 6), 16) / 255
|
|
132
|
+
const a = parseInt(hex.substring(6, 8), 16) / 255
|
|
133
|
+
|
|
134
|
+
return RGBA.fromValues(r, g, b, a)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function rgbToHex(rgb: RGBA): string {
|
|
138
|
+
const [r, g, b] = rgb.toInts()
|
|
139
|
+
return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function hsvToRgb(h: number, s: number, v: number): RGBA {
|
|
143
|
+
const c = v * s
|
|
144
|
+
const x = c * (1 - Math.abs(((h / 60) % 2) - 1))
|
|
145
|
+
const m = v - c
|
|
146
|
+
let r = 0,
|
|
147
|
+
g = 0,
|
|
148
|
+
b = 0
|
|
149
|
+
|
|
150
|
+
if (h < 60) {
|
|
151
|
+
r = c; g = x; b = 0
|
|
152
|
+
} else if (h < 120) {
|
|
153
|
+
r = x; g = c; b = 0
|
|
154
|
+
} else if (h < 180) {
|
|
155
|
+
r = 0; g = c; b = x
|
|
156
|
+
} else if (h < 240) {
|
|
157
|
+
r = 0; g = x; b = c
|
|
158
|
+
} else if (h < 300) {
|
|
159
|
+
r = x; g = 0; b = c
|
|
160
|
+
} else {
|
|
161
|
+
r = c; g = 0; b = x
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return RGBA.fromValues(r + m, g + m, b + m, 1)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function parseColor(color: ColorInput): RGBA {
|
|
168
|
+
if (color instanceof RGBA) return color
|
|
169
|
+
if (typeof color !== "string") return RGBA.fromValues(1, 1, 1, 1)
|
|
170
|
+
|
|
171
|
+
const lower = color.toLowerCase().trim()
|
|
172
|
+
|
|
173
|
+
// Check CSS named colors
|
|
174
|
+
if (CSS_COLOR_NAMES[lower]) {
|
|
175
|
+
return hexToRgb(CSS_COLOR_NAMES[lower])
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Hex
|
|
179
|
+
if (lower.startsWith("#")) {
|
|
180
|
+
return hexToRgb(lower)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// rgba(r, g, b, a)
|
|
184
|
+
const rgbaMatch = lower.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)$/)
|
|
185
|
+
if (rgbaMatch) {
|
|
186
|
+
return RGBA.fromInts(
|
|
187
|
+
parseInt(rgbaMatch[1]),
|
|
188
|
+
parseInt(rgbaMatch[2]),
|
|
189
|
+
parseInt(rgbaMatch[3]),
|
|
190
|
+
rgbaMatch[4] ? Math.round(parseFloat(rgbaMatch[4]) * 255) : 255,
|
|
191
|
+
)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return RGBA.fromValues(1, 1, 1, 1)
|
|
195
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// Types matching opentui core types.ts
|
|
2
|
+
import type { RGBA } from "./rgba"
|
|
3
|
+
import type { Renderable } from "./renderable-types"
|
|
4
|
+
|
|
5
|
+
export const TextAttributes = {
|
|
6
|
+
NONE: 0,
|
|
7
|
+
BOLD: 1 << 0,
|
|
8
|
+
DIM: 1 << 1,
|
|
9
|
+
ITALIC: 1 << 2,
|
|
10
|
+
UNDERLINE: 1 << 3,
|
|
11
|
+
BLINK: 1 << 4,
|
|
12
|
+
INVERSE: 1 << 5,
|
|
13
|
+
HIDDEN: 1 << 6,
|
|
14
|
+
STRIKETHROUGH: 1 << 7,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const ATTRIBUTE_BASE_BITS = 8
|
|
18
|
+
export const ATTRIBUTE_BASE_MASK = 0xff
|
|
19
|
+
|
|
20
|
+
export function getBaseAttributes(attr: number): number {
|
|
21
|
+
return attr & 0xff
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type ThemeMode = "dark" | "light"
|
|
25
|
+
export type CursorStyle = "block" | "line" | "underline"
|
|
26
|
+
export type MousePointerStyle = "default" | "pointer" | "text" | "crosshair" | "move" | "not-allowed"
|
|
27
|
+
export type WidthMethod = "wcwidth" | "unicode"
|
|
28
|
+
export type Timeout = ReturnType<typeof setTimeout> | undefined
|
|
29
|
+
|
|
30
|
+
export interface CursorStyleOptions {
|
|
31
|
+
style?: CursorStyle
|
|
32
|
+
blinking?: boolean
|
|
33
|
+
color?: RGBA
|
|
34
|
+
cursor?: MousePointerStyle
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export enum DebugOverlayCorner {
|
|
38
|
+
topLeft = 0,
|
|
39
|
+
topRight = 1,
|
|
40
|
+
bottomLeft = 2,
|
|
41
|
+
bottomRight = 3,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface RenderContext {
|
|
45
|
+
addToHitGrid: (x: number, y: number, width: number, height: number, id: number) => void
|
|
46
|
+
pushHitGridScissorRect: (x: number, y: number, width: number, height: number) => void
|
|
47
|
+
popHitGridScissorRect: () => void
|
|
48
|
+
clearHitGridScissorRects: () => void
|
|
49
|
+
width: number
|
|
50
|
+
height: number
|
|
51
|
+
requestRender: () => void
|
|
52
|
+
setCursorPosition: (x: number, y: number, visible: boolean) => void
|
|
53
|
+
setCursorStyle: (options: CursorStyleOptions) => void
|
|
54
|
+
setCursorColor: (color: RGBA) => void
|
|
55
|
+
setMousePointer: (shape: MousePointerStyle) => void
|
|
56
|
+
widthMethod: WidthMethod
|
|
57
|
+
capabilities: any | null
|
|
58
|
+
requestLive: () => void
|
|
59
|
+
dropLive: () => void
|
|
60
|
+
hasSelection: boolean
|
|
61
|
+
getSelection: () => any | null
|
|
62
|
+
requestSelectionUpdate: () => void
|
|
63
|
+
currentFocusedRenderable: any | null
|
|
64
|
+
focusRenderable: (renderable: any) => void
|
|
65
|
+
registerLifecyclePass: (renderable: any) => void
|
|
66
|
+
unregisterLifecyclePass: (renderable: any) => void
|
|
67
|
+
getLifecyclePasses: () => Set<any>
|
|
68
|
+
keyInput: any
|
|
69
|
+
_internalKeyInput: any
|
|
70
|
+
clearSelection: () => void
|
|
71
|
+
startSelection: (renderable: any, x: number, y: number) => void
|
|
72
|
+
updateSelection: (
|
|
73
|
+
currentRenderable: any | undefined,
|
|
74
|
+
x: number,
|
|
75
|
+
y: number,
|
|
76
|
+
options?: { finishDragging?: boolean },
|
|
77
|
+
) => void
|
|
78
|
+
// EventEmitter methods
|
|
79
|
+
on: (event: string, listener: (...args: any[]) => void) => any
|
|
80
|
+
off: (event: string, listener: (...args: any[]) => void) => any
|
|
81
|
+
emit: (event: string, ...args: any[]) => boolean
|
|
82
|
+
removeAllListeners: (event?: string) => any
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface ViewportBounds {
|
|
86
|
+
x: number
|
|
87
|
+
y: number
|
|
88
|
+
width: number
|
|
89
|
+
height: number
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface Highlight {
|
|
93
|
+
start: number
|
|
94
|
+
end: number
|
|
95
|
+
styleId: number
|
|
96
|
+
priority?: number | null
|
|
97
|
+
hlRef?: number | null
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface LineInfo {
|
|
101
|
+
lineStarts: number[]
|
|
102
|
+
lineWidths: number[]
|
|
103
|
+
maxLineWidth: number
|
|
104
|
+
lineSources: number[]
|
|
105
|
+
lineWraps: number[]
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface LineInfoProvider {
|
|
109
|
+
get lineInfo(): LineInfo
|
|
110
|
+
get lineCount(): number
|
|
111
|
+
get virtualLineCount(): number
|
|
112
|
+
get scrollY(): number
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface CapturedSpan {
|
|
116
|
+
text: string
|
|
117
|
+
fg: RGBA
|
|
118
|
+
bg: RGBA
|
|
119
|
+
attributes: number
|
|
120
|
+
width: number
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface CapturedLine {
|
|
124
|
+
spans: CapturedSpan[]
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export interface CapturedFrame {
|
|
128
|
+
cols: number
|
|
129
|
+
rows: number
|
|
130
|
+
cursor: [number, number]
|
|
131
|
+
lines: CapturedLine[]
|
|
132
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Shim for bun-ffi-structs
|
|
2
|
+
export class Struct {
|
|
3
|
+
constructor(_def: any) {}
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export function defineStruct(_def: any): any {
|
|
7
|
+
return class StubStruct {
|
|
8
|
+
constructor(..._args: any[]) {}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function defineEnum(_def: any): any {
|
|
13
|
+
return {}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function defineUnion(_def: any): any {
|
|
17
|
+
return class StubUnion {
|
|
18
|
+
constructor(..._args: any[]) {}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Shim for bun:ffi - provides dummy types/stubs for browser environment
|
|
2
|
+
export type Pointer = number
|
|
3
|
+
|
|
4
|
+
export function toArrayBuffer(_ptr: Pointer, _offset: number, _size: number): ArrayBuffer {
|
|
5
|
+
return new ArrayBuffer(0)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function ptr(_buf: ArrayBuffer): Pointer {
|
|
9
|
+
return 0
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function read(ptr: Pointer): { ptr: Pointer } {
|
|
13
|
+
return { ptr: 0 }
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function dlopen(_path: string, _symbols: Record<string, unknown>): { symbols: Record<string, unknown>; close(): void } {
|
|
17
|
+
return { symbols: {}, close() {} }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class JSCallback {
|
|
21
|
+
ptr: Pointer = 0
|
|
22
|
+
constructor(_fn: (...args: unknown[]) => unknown, _options?: unknown) {}
|
|
23
|
+
close() {}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function suffix(): string {
|
|
27
|
+
return ""
|
|
28
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Stub for opentui/packages/core/src/console.ts
|
|
2
|
+
export class TerminalConsole {
|
|
3
|
+
constructor(..._args: any[]) {}
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export type ConsoleOptions = any
|
|
7
|
+
|
|
8
|
+
export function capture(..._args: any[]): any {
|
|
9
|
+
return null
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class Capture {}
|
|
13
|
+
export class CapturedWritableStream {}
|