@jitl/opentui-solid 0.1.97-next.130245d

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 opentui
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,193 @@
1
+ > Experimental build of OpenTUI for Node.js from [github.com/justjake/opentui](https://github.com/justjake/opentui).
2
+ >
3
+ > Published under `@jitl/*` until the Node.js support branch is upstreamed.
4
+ # @jitl/opentui-solid
5
+
6
+ Solid.js support for [OpenTUI](https://github.com/anomalyco/opentui).
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ bun install solid-js @jitl/opentui-solid
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ 1. Add jsx config to tsconfig.json:
17
+
18
+ ```json
19
+ {
20
+ "compilerOptions": {
21
+ "jsx": "preserve",
22
+ "jsxImportSource": "@jitl/opentui-solid"
23
+ }
24
+ }
25
+ ```
26
+
27
+ 2. Add preload script to bunfig.toml:
28
+
29
+ ```toml
30
+ preload = ["@jitl/opentui-solid/preload"]
31
+ ```
32
+
33
+ 3. Add render function to index.tsx:
34
+
35
+ ```tsx
36
+ import { render } from "@jitl/opentui-solid"
37
+
38
+ render(() => <text>Hello, World!</text>)
39
+ ```
40
+
41
+ 4. Run with `bun index.tsx`.
42
+
43
+ 5. To build use [Bun.build](https://bun.com/docs/bundler) ([source](https://github.com/anomalyco/opentui/issues/122)):
44
+
45
+ ```ts
46
+ import solidPlugin from "@jitl/opentui-solid/bun-plugin"
47
+
48
+ await Bun.build({
49
+ entrypoints: ["./index.tsx"],
50
+ target: "bun",
51
+ outdir: "./build",
52
+ plugins: [solidPlugin],
53
+ compile: {
54
+ target: "bun-darwin-arm64",
55
+ outfile: "app-macos",
56
+ },
57
+ })
58
+ ```
59
+
60
+ ## Table of Contents
61
+
62
+ - [Core Concepts](#core-concepts)
63
+ - [Components](#components)
64
+ - [API Reference](#api-reference)
65
+ - [render(node, rendererOrConfig?)](#rendernode-rendererorconfig)
66
+ - [testRender(node, options?)](#testrendernode-options)
67
+ - [extend(components)](#extendcomponents)
68
+ - [getComponentCatalogue()](#getcomponentcatalogue)
69
+ - [Hooks](#hooks)
70
+ - [Portal](#portal)
71
+ - [Dynamic](#dynamic)
72
+ - [Components](#components-1)
73
+ - [Layout & Display](#layout--display)
74
+ - [Input](#input)
75
+ - [Code & Diff](#code--diff)
76
+ - [Text Modifiers](#text-modifiers)
77
+
78
+ ## Core Concepts
79
+
80
+ ### Components
81
+
82
+ OpenTUI Solid exposes intrinsic JSX elements that map to OpenTUI renderables:
83
+
84
+ - **Layout & Display:** `text`, `box`, `scrollbox`, `ascii_font`
85
+ - **Input:** `input`, `textarea`, `select`, `tab_select`
86
+ - **Code & Diff:** `code`, `line_number`, `diff`
87
+ - **Text Modifiers:** `span`, `strong`, `b`, `em`, `i`, `u`, `br`, `a`
88
+
89
+ ## API Reference
90
+
91
+ ### `render(node, rendererOrConfig?)`
92
+
93
+ Render a Solid component tree into a CLI renderer. If `rendererOrConfig` is omitted, a renderer is created with default options.
94
+
95
+ ```tsx
96
+ import { render } from "@jitl/opentui-solid"
97
+
98
+ render(() => <App />)
99
+ ```
100
+
101
+ **Parameters:**
102
+
103
+ - `node`: Function returning a JSX element.
104
+ - `rendererOrConfig?`: `CliRenderer` instance or `CliRendererConfig`.
105
+
106
+ ### `testRender(node, options?)`
107
+
108
+ Create a test renderer for snapshots and interaction tests.
109
+
110
+ ```tsx
111
+ import { testRender } from "@jitl/opentui-solid"
112
+
113
+ const testSetup = await testRender(() => <App />, { width: 40, height: 10 })
114
+ ```
115
+
116
+ ### `extend(components)`
117
+
118
+ Register custom renderables as JSX intrinsic elements.
119
+
120
+ ```tsx
121
+ import { extend } from "@jitl/opentui-solid"
122
+
123
+ extend({ customBox: CustomBoxRenderable })
124
+ ```
125
+
126
+ ### `getComponentCatalogue()`
127
+
128
+ Returns the current component catalogue that powers JSX tag lookup.
129
+
130
+ ### Hooks
131
+
132
+ - `useRenderer()`
133
+ - `onResize(callback)`
134
+ - `onFocus(callback)`
135
+ - `onBlur(callback)`
136
+ - `useTerminalDimensions()`
137
+ - `useKeyboard(handler, options?)`
138
+ - `usePaste(handler)`
139
+ - `useSelectionHandler(handler)`
140
+ - `useTimeline(options?)`
141
+
142
+ ### `Portal`
143
+
144
+ Render children into a different mount node, useful for overlays and tooltips.
145
+
146
+ ```tsx
147
+ import { Portal } from "@jitl/opentui-solid"
148
+ ;<Portal mount={renderer.root}>
149
+ <box border>Overlay</box>
150
+ </Portal>
151
+ ```
152
+
153
+ ### `Dynamic`
154
+
155
+ Render arbitrary intrinsic elements or components dynamically.
156
+
157
+ ```tsx
158
+ import { Dynamic } from "@jitl/opentui-solid"
159
+ ;<Dynamic component={isMultiline() ? "textarea" : "input"} />
160
+ ```
161
+
162
+ ## Components
163
+
164
+ ### Layout & Display
165
+
166
+ - `text`: styled text container
167
+ - `box`: layout container with borders, padding, and flex settings
168
+ - `scrollbox`: scrollable container
169
+ - `ascii_font`: ASCII art text renderer
170
+
171
+ ### Input
172
+
173
+ - `input`: single-line text input
174
+ - `textarea`: multi-line text input
175
+ - `select`: list selection
176
+ - `tab_select`: tab-based selection
177
+
178
+ ### Code & Diff
179
+
180
+ - `code`: syntax-highlighted code blocks
181
+ - `line_number`: line-numbered code display with diff/diagnostic helpers
182
+ - `diff`: unified or split diff viewer
183
+
184
+ ### Text Modifiers
185
+
186
+ These must appear inside a `text` component:
187
+
188
+ - `span`: inline styled text
189
+ - `strong`/`b`: bold text
190
+ - `em`/`i`: italic text
191
+ - `u`: underline text
192
+ - `br`: line break
193
+ - `a`: link text with `href`
@@ -0,0 +1,160 @@
1
+ export function useTimeline(options?: {}): Timeline;
2
+ export function useTerminalDimensions(): import("solid-js").Accessor<{
3
+ width: any;
4
+ height: any;
5
+ }>;
6
+ export function useSelectionHandler(callback: any): void;
7
+ export function useRenderer(): any;
8
+ export function usePaste(callback: any): void;
9
+ export function useKeyboard(callback: any, options: any): void;
10
+ export function useKeyHandler(callback: any, options: any): void;
11
+ export function use(fn: any, element: any, arg: any): any;
12
+ export var textNodeKeys: string[];
13
+ export function testRender(node: any, renderConfig?: {}): Promise<{
14
+ renderer: import("@jitl/opentui-core/testing").TestRenderer;
15
+ mockInput: import("@jitl/opentui-core/testing").MockInput;
16
+ mockMouse: import("@jitl/opentui-core/testing").MockMouse;
17
+ renderOnce: () => Promise<void>;
18
+ captureCharFrame: () => string;
19
+ captureSpans: () => import("@jitl/opentui-core").CapturedFrame;
20
+ resize: (width: number, height: number) => void;
21
+ }>;
22
+ export function spread(node: any, accessor: any, skipChildren: any): void;
23
+ export function setProp(node: any, name: any, value: any, prev: any): any;
24
+ export function render(node: any, rendererOrConfig?: {}): Promise<void>;
25
+ export function onResize(callback: any): void;
26
+ export function onFocus(callback: any): void;
27
+ export function onBlur(callback: any): void;
28
+ declare var mergeProps3: typeof mergeProps;
29
+ declare function memo2(fn: any): import("solid-js").Accessor<any>;
30
+ export var insertNode: any;
31
+ export function insert(parent: any, accessor: any, marker: any, initial: any): any;
32
+ export function getComponentCatalogue(): {
33
+ box: typeof BoxRenderable;
34
+ text: typeof TextRenderable3;
35
+ input: typeof InputRenderable2;
36
+ select: typeof SelectRenderable2;
37
+ textarea: typeof TextareaRenderable;
38
+ ascii_font: typeof ASCIIFontRenderable;
39
+ tab_select: typeof TabSelectRenderable2;
40
+ scrollbox: typeof ScrollBoxRenderable2;
41
+ code: typeof CodeRenderable;
42
+ diff: typeof DiffRenderable;
43
+ line_number: typeof LineNumberRenderable;
44
+ markdown: typeof MarkdownRenderable;
45
+ span: typeof SpanRenderable;
46
+ strong: typeof BoldSpanRenderable;
47
+ b: typeof BoldSpanRenderable;
48
+ em: typeof ItalicSpanRenderable;
49
+ i: typeof ItalicSpanRenderable;
50
+ u: typeof UnderlineSpanRenderable;
51
+ br: typeof LineBreakRenderable;
52
+ a: typeof LinkRenderable;
53
+ };
54
+ export function extend(objects: any): void;
55
+ export var effect: typeof createRenderEffect;
56
+ export var createTextNode: any;
57
+ export function createSolidSlotRegistry(renderer: any, context: any, options?: {}): import("@jitl/opentui-core").SlotRegistry<any, object, any>;
58
+ export function createSlotNode(): SlotRenderable;
59
+ export function createSlot(registry: any, options?: {}): (props: any) => any;
60
+ export var createElement: any;
61
+ export function createDynamic(component: any, props: any): import("solid-js").Accessor<any>;
62
+ declare var createComponent2: typeof createComponent;
63
+ export namespace componentCatalogue {
64
+ export { BoxRenderable as box };
65
+ export { TextRenderable3 as text };
66
+ export { InputRenderable2 as input };
67
+ export { SelectRenderable2 as select };
68
+ export { TextareaRenderable as textarea };
69
+ export { ASCIIFontRenderable as ascii_font };
70
+ export { TabSelectRenderable2 as tab_select };
71
+ export { ScrollBoxRenderable2 as scrollbox };
72
+ export { CodeRenderable as code };
73
+ export { DiffRenderable as diff };
74
+ export { LineNumberRenderable as line_number };
75
+ export { MarkdownRenderable as markdown };
76
+ export { SpanRenderable as span };
77
+ export { BoldSpanRenderable as strong };
78
+ export { BoldSpanRenderable as b };
79
+ export { ItalicSpanRenderable as em };
80
+ export { ItalicSpanRenderable as i };
81
+ export { UnderlineSpanRenderable as u };
82
+ export { LineBreakRenderable as br };
83
+ export { LinkRenderable as a };
84
+ }
85
+ export namespace baseComponents { }
86
+ export function _render(code: any, element: any): undefined;
87
+ export class UnderlineSpanRenderable extends TextModifierRenderable {
88
+ constructor(options: any);
89
+ }
90
+ export function TimeToFirstDraw(props: any): any;
91
+ export class TextSlotRenderable extends TextNodeRenderable3 {
92
+ constructor(id: any, parent: any);
93
+ slotParent: any;
94
+ destroyed: boolean;
95
+ }
96
+ export class SlotRenderable extends SlotBaseRenderable {
97
+ layoutNode: any;
98
+ textNode: any;
99
+ destroyed: boolean;
100
+ getSlotChild(parent: any): any;
101
+ }
102
+ export function Slot(props: any): import("solid-js").Accessor<any>;
103
+ export var RendererContext: import("solid-js").Context<any>;
104
+ export function Portal(props: any): SlotRenderable;
105
+ export class LinkRenderable extends SpanRenderable {
106
+ }
107
+ export class LineBreakRenderable extends SpanRenderable {
108
+ add(): number;
109
+ }
110
+ export class LayoutSlotRenderable extends SlotBaseRenderable {
111
+ constructor(id: any, parent: any);
112
+ yogaNode: Yoga.Node;
113
+ slotParent: any;
114
+ destroyed: boolean;
115
+ getLayoutNode(): Yoga.Node;
116
+ updateFromLayout(): void;
117
+ updateLayout(): void;
118
+ onRemove(): void;
119
+ }
120
+ export class ItalicSpanRenderable extends TextModifierRenderable {
121
+ constructor(options: any);
122
+ }
123
+ export function Dynamic(props: any): import("solid-js").Accessor<any>;
124
+ export class BoldSpanRenderable extends TextModifierRenderable {
125
+ constructor(options: any);
126
+ }
127
+ import { Timeline } from "@jitl/opentui-core";
128
+ import { mergeProps } from "solid-js";
129
+ import { BoxRenderable } from "@jitl/opentui-core";
130
+ import { TextRenderable as TextRenderable3 } from "@jitl/opentui-core";
131
+ import { InputRenderable as InputRenderable2 } from "@jitl/opentui-core";
132
+ import { SelectRenderable as SelectRenderable2 } from "@jitl/opentui-core";
133
+ import { TextareaRenderable } from "@jitl/opentui-core";
134
+ import { ASCIIFontRenderable } from "@jitl/opentui-core";
135
+ import { TabSelectRenderable as TabSelectRenderable2 } from "@jitl/opentui-core";
136
+ import { ScrollBoxRenderable as ScrollBoxRenderable2 } from "@jitl/opentui-core";
137
+ import { CodeRenderable } from "@jitl/opentui-core";
138
+ import { DiffRenderable } from "@jitl/opentui-core";
139
+ import { LineNumberRenderable } from "@jitl/opentui-core";
140
+ import { MarkdownRenderable } from "@jitl/opentui-core";
141
+ declare class SpanRenderable extends TextNodeRenderable3 {
142
+ constructor(_ctx: any, options: any);
143
+ _ctx: any;
144
+ }
145
+ import { createRenderEffect } from "solid-js";
146
+ import { createComponent } from "solid-js";
147
+ declare class TextModifierRenderable extends SpanRenderable {
148
+ }
149
+ import { TextNodeRenderable as TextNodeRenderable3 } from "@jitl/opentui-core";
150
+ declare class SlotBaseRenderable extends BaseRenderable {
151
+ constructor(id: any);
152
+ add(obj: any, index: any): void;
153
+ remove(id: any): void;
154
+ insertBefore(obj: any, anchor: any): void;
155
+ getRenderable(id: any): void;
156
+ findDescendantById(id: any): void;
157
+ }
158
+ import { Yoga } from "@jitl/opentui-core";
159
+ import { BaseRenderable } from "@jitl/opentui-core";
160
+ export { mergeProps3 as mergeProps, memo2 as memo, createComponent2 as createComponent };
package/index.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ import { CliRenderer, type CliRendererConfig } from "@jitl/opentui-core";
2
+ import { type TestRendererOptions } from "@jitl/opentui-core/testing";
3
+ import type { JSX } from "./jsx-runtime";
4
+ export declare const render: (node: () => JSX.Element, rendererOrConfig?: CliRenderer | CliRendererConfig) => Promise<void>;
5
+ export declare const testRender: (node: () => JSX.Element, renderConfig?: TestRendererOptions) => Promise<{
6
+ renderer: import("@jitl/opentui-core/testing").TestRenderer;
7
+ mockInput: import("@jitl/opentui-core/testing").MockInput;
8
+ mockMouse: import("@jitl/opentui-core/testing").MockMouse;
9
+ renderOnce: () => Promise<void>;
10
+ captureCharFrame: () => string;
11
+ captureSpans: () => import("@jitl/opentui-core").CapturedFrame;
12
+ resize: (width: number, height: number) => void;
13
+ }>;
14
+ export * from "./src/reconciler.js";
15
+ export * from "./src/elements/index.js";
16
+ export * from "./src/time-to-first-draw.js";
17
+ export * from "./src/plugins/slot.js";
18
+ export * from "./src/types/elements.js";
19
+ export { type JSX };