@opentui/react 0.1.62 → 0.1.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -83,6 +83,7 @@ For optimal TypeScript support, configure your `tsconfig.json`:
83
83
  - [System Monitor Animation](#system-monitor-animation)
84
84
  - [Styled Text Showcase](#styled-text-showcase)
85
85
  - [Component Extension](#component-extension)
86
+ - [Using React DevTools](#using-react-devtools)
86
87
 
87
88
  ## Core Concepts
88
89
 
@@ -970,3 +971,31 @@ function App() {
970
971
  const renderer = await createCliRenderer()
971
972
  createRoot(renderer).render(<App />)
972
973
  ```
974
+
975
+ ## Using React DevTools
976
+
977
+ OpenTUI React supports [React DevTools](https://github.com/facebook/react/tree/master/packages/react-devtools) for debugging your terminal applications. To enable DevTools integration:
978
+
979
+ 1. Install the optional peer dependency:
980
+
981
+ ```bash
982
+ bun add --dev react-devtools-core@7
983
+ ```
984
+
985
+ 2. Start the standalone React DevTools:
986
+
987
+ ```bash
988
+ npx npx react-devtools@7
989
+ ```
990
+
991
+ 3. Run your app with the `DEV` environment variable:
992
+
993
+ ```bash
994
+ DEV=true bun run your-app.ts
995
+ ```
996
+
997
+ After the app starts, you should see the component tree in React DevTools. You can inspect and modify props in real-time, and changes will be reflected immediately in your terminal UI.
998
+
999
+ ### Process Exit with DevTools
1000
+
1001
+ When DevTools is connected, the WebSocket connection may prevent your process from exiting naturally.
@@ -0,0 +1,20 @@
1
+ // @bun
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __require = import.meta.require;
19
+
20
+ export { __toESM, __require };
@@ -0,0 +1,29 @@
1
+ // @bun
2
+ import {
3
+ __require,
4
+ __toESM
5
+ } from "./chunk-e11q5a3p.js";
6
+
7
+ // src/reconciler/devtools-polyfill.ts
8
+ var g = globalThis;
9
+ if (typeof g.WebSocket === "undefined") {
10
+ try {
11
+ const ws = await import("ws");
12
+ g.WebSocket = ws.default;
13
+ } catch {}
14
+ }
15
+ g.window ||= globalThis;
16
+ g.self ||= globalThis;
17
+ g.window.__REACT_DEVTOOLS_COMPONENT_FILTERS__ = [
18
+ {
19
+ type: 2,
20
+ value: "ErrorBoundary",
21
+ isEnabled: true,
22
+ isValid: true
23
+ }
24
+ ];
25
+
26
+ // src/reconciler/devtools.ts
27
+ import devtools from "react-devtools-core";
28
+ devtools.initialize();
29
+ devtools.connectToDevTools();
package/index.js CHANGED
@@ -1,4 +1,9 @@
1
1
  // @bun
2
+ import {
3
+ __require,
4
+ __toESM
5
+ } from "./chunk-e11q5a3p.js";
6
+
2
7
  // src/components/index.ts
3
8
  import {
4
9
  ASCIIFontRenderable,
@@ -16,7 +21,7 @@ import {
16
21
 
17
22
  // src/components/text.ts
18
23
  import { TextAttributes, TextNodeRenderable } from "@opentui/core";
19
- var textNodeKeys = ["span", "b", "strong", "i", "em", "u", "br"];
24
+ var textNodeKeys = ["span", "b", "strong", "i", "em", "u", "br", "a"];
20
25
 
21
26
  class SpanRenderable extends TextNodeRenderable {
22
27
  ctx;
@@ -68,6 +73,16 @@ class LineBreakRenderable extends SpanRenderable {
68
73
  }
69
74
  }
70
75
 
76
+ class LinkRenderable extends SpanRenderable {
77
+ constructor(_ctx, options) {
78
+ const linkOptions = {
79
+ ...options,
80
+ link: { url: options.href }
81
+ };
82
+ super(null, linkOptions);
83
+ }
84
+ }
85
+
71
86
  // src/components/index.ts
72
87
  var baseComponents = {
73
88
  box: BoxRenderable,
@@ -87,7 +102,8 @@ var baseComponents = {
87
102
  strong: BoldSpanRenderable,
88
103
  i: ItalicSpanRenderable,
89
104
  em: ItalicSpanRenderable,
90
- u: UnderlineSpanRenderable
105
+ u: UnderlineSpanRenderable,
106
+ a: LinkRenderable
91
107
  };
92
108
  var componentCatalogue = { ...baseComponents };
93
109
  function extend(objects) {
@@ -229,6 +245,76 @@ import { ConcurrentRoot } from "react-reconciler/constants";
229
245
 
230
246
  // src/reconciler/host-config.ts
231
247
  import { TextNodeRenderable as TextNodeRenderable2 } from "@opentui/core";
248
+ // package.json
249
+ var package_default = {
250
+ name: "@opentui/react",
251
+ version: "0.1.64",
252
+ description: "React renderer for building terminal user interfaces using OpenTUI core",
253
+ license: "MIT",
254
+ repository: {
255
+ type: "git",
256
+ url: "https://github.com/sst/opentui",
257
+ directory: "packages/react"
258
+ },
259
+ module: "src/index.ts",
260
+ type: "module",
261
+ private: true,
262
+ main: "src/index.ts",
263
+ exports: {
264
+ ".": {
265
+ import: "./src/index.ts",
266
+ types: "./src/index.ts"
267
+ },
268
+ "./test-utils": {
269
+ import: "./src/test-utils.ts",
270
+ types: "./src/test-utils.d.ts"
271
+ },
272
+ "./jsx-runtime": {
273
+ import: "./jsx-runtime.js",
274
+ types: "./jsx-runtime.d.ts"
275
+ },
276
+ "./jsx-dev-runtime": {
277
+ import: "./jsx-dev-runtime.js",
278
+ types: "./jsx-dev-runtime.d.ts"
279
+ }
280
+ },
281
+ scripts: {
282
+ build: "bun run scripts/build.ts",
283
+ "build:dev": "bun run scripts/build.ts --dev",
284
+ publish: "bun run scripts/publish.ts",
285
+ test: "bun test"
286
+ },
287
+ devDependencies: {
288
+ "@types/bun": "latest",
289
+ "@types/node": "^24.0.0",
290
+ "@types/react": "^19.0.0",
291
+ "@types/react-reconciler": "^0.32.0",
292
+ "@types/ws": "^8.18.1",
293
+ react: ">=19.0.0",
294
+ "react-devtools-core": "^7.0.1",
295
+ typescript: "^5",
296
+ ws: "^8.18.0"
297
+ },
298
+ peerDependencies: {
299
+ react: ">=19.0.0",
300
+ "react-devtools-core": "^7.0.1",
301
+ ws: "^8.18.0"
302
+ },
303
+ peerDependenciesMeta: {
304
+ "react-devtools-core": {
305
+ optional: true
306
+ },
307
+ ws: {
308
+ optional: true
309
+ }
310
+ },
311
+ dependencies: {
312
+ "@opentui/core": "workspace:*",
313
+ "react-reconciler": "^0.32.0"
314
+ }
315
+ };
316
+
317
+ // src/reconciler/host-config.ts
232
318
  import { createContext as createContext2 } from "react";
233
319
  import { DefaultEventPriority, NoEventPriority } from "react-reconciler/constants";
234
320
 
@@ -262,18 +348,21 @@ function initEventListeners(instance, eventName, listener, previousListener) {
262
348
  }
263
349
  }
264
350
  function setStyle(instance, styles, oldStyles) {
265
- if (styles && typeof styles === "object") {
266
- if (oldStyles != null) {
267
- for (const styleName in styles) {
268
- const value = styles[styleName];
269
- if (styles.hasOwnProperty(styleName) && oldStyles[styleName] !== value) {
270
- instance[styleName] = value;
351
+ if (oldStyles != null && typeof oldStyles === "object") {
352
+ for (const styleName in oldStyles) {
353
+ if (oldStyles.hasOwnProperty(styleName)) {
354
+ if (styles == null || !styles.hasOwnProperty(styleName)) {
355
+ instance[styleName] = null;
271
356
  }
272
357
  }
273
- } else {
274
- for (const styleName in styles) {
275
- if (styles.hasOwnProperty(styleName)) {
276
- const value = styles[styleName];
358
+ }
359
+ }
360
+ if (styles != null && typeof styles === "object") {
361
+ for (const styleName in styles) {
362
+ if (styles.hasOwnProperty(styleName)) {
363
+ const value = styles[styleName];
364
+ const oldValue = oldStyles?.[styleName];
365
+ if (value !== oldValue) {
277
366
  instance[styleName] = value;
278
367
  }
279
368
  }
@@ -506,11 +595,33 @@ var hostConfig = {
506
595
  prepareScopeUpdate() {},
507
596
  getInstanceFromScope() {
508
597
  return null;
509
- }
598
+ },
599
+ rendererPackageName: "@opentui/react",
600
+ rendererVersion: package_default.version
510
601
  };
511
602
 
512
603
  // src/reconciler/reconciler.ts
513
604
  var reconciler = ReactReconciler(hostConfig);
605
+ if (process.env["DEV"] === "true") {
606
+ try {
607
+ await import("./chunk-fcedq94e.js");
608
+ } catch (error) {
609
+ if (error.code === "ERR_MODULE_NOT_FOUND") {
610
+ console.warn(`
611
+ The environment variable DEV is set to true, so opentui tried to import \`react-devtools-core\`,
612
+ but this failed as it was not installed. Debugging with React DevTools requires it.
613
+
614
+ To install use this command:
615
+
616
+ $ bun add react-devtools-core@7 -d
617
+ `.trim() + `
618
+ `);
619
+ } else {
620
+ throw error;
621
+ }
622
+ }
623
+ }
624
+ reconciler.injectIntoDevTools();
514
625
  function _render(element, root) {
515
626
  const container = reconciler.createContainer(root, ConcurrentRoot, null, false, null, "", console.error, console.error, console.error, console.error, null);
516
627
  reconciler.updateContainer(element, container, null, () => {});
@@ -518,6 +629,7 @@ function _render(element, root) {
518
629
  }
519
630
 
520
631
  // src/reconciler/renderer.ts
632
+ var { flushSync, createPortal } = reconciler;
521
633
  function createRoot(renderer) {
522
634
  let container = null;
523
635
  return {
@@ -546,8 +658,10 @@ export {
546
658
  useKeyboard,
547
659
  useAppContext,
548
660
  getComponentCatalogue,
661
+ flushSync,
549
662
  extend,
550
663
  createRoot,
664
+ createPortal,
551
665
  createElement,
552
666
  componentCatalogue,
553
667
  baseComponents,
@@ -8,6 +8,7 @@ import type {
8
8
  InputProps,
9
9
  LineBreakProps,
10
10
  LineNumberProps,
11
+ LinkProps,
11
12
  OpenTUIComponents,
12
13
  ScrollBoxProps,
13
14
  SelectProps,
@@ -54,5 +55,6 @@ export namespace JSX {
54
55
  strong: SpanProps
55
56
  em: SpanProps
56
57
  br: LineBreakProps
58
+ a: LinkProps
57
59
  }
58
60
  }
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "main": "index.js",
5
5
  "types": "src/index.d.ts",
6
6
  "type": "module",
7
- "version": "0.1.62",
7
+ "version": "0.1.64",
8
8
  "description": "React renderer for building terminal user interfaces using OpenTUI core",
9
9
  "license": "MIT",
10
10
  "repository": {
@@ -40,7 +40,7 @@
40
40
  }
41
41
  },
42
42
  "dependencies": {
43
- "@opentui/core": "0.1.62",
43
+ "@opentui/core": "0.1.64",
44
44
  "react-reconciler": "^0.32.0"
45
45
  },
46
46
  "devDependencies": {
@@ -48,9 +48,15 @@
48
48
  "@types/node": "^24.0.0",
49
49
  "@types/react": "^19.0.0",
50
50
  "@types/react-reconciler": "^0.32.0",
51
- "typescript": "^5"
51
+ "@types/ws": "^8.18.1",
52
+ "react": ">=19.0.0",
53
+ "react-devtools-core": "^7.0.1",
54
+ "typescript": "^5",
55
+ "ws": "^8.18.0"
52
56
  },
53
57
  "peerDependencies": {
54
- "react": ">=19.0.0"
58
+ "react": ">=19.0.0",
59
+ "react-devtools-core": "^7.0.1",
60
+ "ws": "^8.18.0"
55
61
  }
56
62
  }
@@ -1,6 +1,6 @@
1
1
  import { ASCIIFontRenderable, BoxRenderable, CodeRenderable, DiffRenderable, InputRenderable, LineNumberRenderable, ScrollBoxRenderable, SelectRenderable, TabSelectRenderable, TextareaRenderable, TextRenderable } from "@opentui/core";
2
2
  import type { RenderableConstructor } from "../types/components";
3
- import { BoldSpanRenderable, ItalicSpanRenderable, LineBreakRenderable, SpanRenderable, UnderlineSpanRenderable } from "./text";
3
+ import { BoldSpanRenderable, ItalicSpanRenderable, LineBreakRenderable, LinkRenderable, SpanRenderable, UnderlineSpanRenderable } from "./text";
4
4
  export declare const baseComponents: {
5
5
  box: typeof BoxRenderable;
6
6
  text: typeof TextRenderable;
@@ -20,6 +20,7 @@ export declare const baseComponents: {
20
20
  i: typeof ItalicSpanRenderable;
21
21
  em: typeof ItalicSpanRenderable;
22
22
  u: typeof UnderlineSpanRenderable;
23
+ a: typeof LinkRenderable;
23
24
  };
24
25
  type ComponentCatalogue = Record<string, RenderableConstructor>;
25
26
  export declare const componentCatalogue: ComponentCatalogue;
@@ -1,5 +1,5 @@
1
1
  import { TextNodeRenderable, type RenderContext, type TextNodeOptions } from "@opentui/core";
2
- export declare const textNodeKeys: readonly ["span", "b", "strong", "i", "em", "u", "br"];
2
+ export declare const textNodeKeys: readonly ["span", "b", "strong", "i", "em", "u", "br", "a"];
3
3
  export type TextNodeKey = (typeof textNodeKeys)[number];
4
4
  export declare class SpanRenderable extends TextNodeRenderable {
5
5
  private readonly ctx;
@@ -21,4 +21,10 @@ export declare class LineBreakRenderable extends SpanRenderable {
21
21
  constructor(_ctx: RenderContext | null, options: TextNodeOptions);
22
22
  add(): number;
23
23
  }
24
+ export interface LinkOptions extends TextNodeOptions {
25
+ href: string;
26
+ }
27
+ export declare class LinkRenderable extends SpanRenderable {
28
+ constructor(_ctx: RenderContext | null, options: LinkOptions);
29
+ }
24
30
  export {};
@@ -0,0 +1,20 @@
1
+ // @bun
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __require = import.meta.require;
19
+
20
+ export { __toESM, __require };
@@ -0,0 +1,29 @@
1
+ // @bun
2
+ import {
3
+ __require,
4
+ __toESM
5
+ } from "./chunk-e11q5a3p.js";
6
+
7
+ // src/reconciler/devtools-polyfill.ts
8
+ var g = globalThis;
9
+ if (typeof g.WebSocket === "undefined") {
10
+ try {
11
+ const ws = await import("ws");
12
+ g.WebSocket = ws.default;
13
+ } catch {}
14
+ }
15
+ g.window ||= globalThis;
16
+ g.self ||= globalThis;
17
+ g.window.__REACT_DEVTOOLS_COMPONENT_FILTERS__ = [
18
+ {
19
+ type: 2,
20
+ value: "ErrorBoundary",
21
+ isEnabled: true,
22
+ isValid: true
23
+ }
24
+ ];
25
+
26
+ // src/reconciler/devtools.ts
27
+ import devtools from "react-devtools-core";
28
+ devtools.initialize();
29
+ devtools.connectToDevTools();
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ import "./devtools-polyfill";
@@ -1,5 +1,9 @@
1
1
  import { CliRenderer } from "@opentui/core";
2
2
  import { type ReactNode } from "react";
3
+ declare const flushSync: {
4
+ (): void;
5
+ <R>(fn: () => R): R;
6
+ }, createPortal: (children: ReactNode, containerInfo: any, implementation: any, key?: string | null) => import("react-reconciler").ReactPortal;
3
7
  export type Root = {
4
8
  render: (node: ReactNode) => void;
5
9
  unmount: () => void;
@@ -15,3 +19,4 @@ export type Root = {
15
19
  * ```
16
20
  */
17
21
  export declare function createRoot(renderer: CliRenderer): Root;
22
+ export { createPortal, flushSync };
@@ -1,4 +1,9 @@
1
1
  // @bun
2
+ import {
3
+ __require,
4
+ __toESM
5
+ } from "./chunk-e11q5a3p.js";
6
+
2
7
  // src/reconciler/renderer.ts
3
8
  import { engine } from "@opentui/core";
4
9
  import React2 from "react";
@@ -45,6 +50,76 @@ import { ConcurrentRoot } from "react-reconciler/constants";
45
50
 
46
51
  // src/reconciler/host-config.ts
47
52
  import { TextNodeRenderable as TextNodeRenderable2 } from "@opentui/core";
53
+ // package.json
54
+ var package_default = {
55
+ name: "@opentui/react",
56
+ version: "0.1.64",
57
+ description: "React renderer for building terminal user interfaces using OpenTUI core",
58
+ license: "MIT",
59
+ repository: {
60
+ type: "git",
61
+ url: "https://github.com/sst/opentui",
62
+ directory: "packages/react"
63
+ },
64
+ module: "src/index.ts",
65
+ type: "module",
66
+ private: true,
67
+ main: "src/index.ts",
68
+ exports: {
69
+ ".": {
70
+ import: "./src/index.ts",
71
+ types: "./src/index.ts"
72
+ },
73
+ "./test-utils": {
74
+ import: "./src/test-utils.ts",
75
+ types: "./src/test-utils.d.ts"
76
+ },
77
+ "./jsx-runtime": {
78
+ import: "./jsx-runtime.js",
79
+ types: "./jsx-runtime.d.ts"
80
+ },
81
+ "./jsx-dev-runtime": {
82
+ import: "./jsx-dev-runtime.js",
83
+ types: "./jsx-dev-runtime.d.ts"
84
+ }
85
+ },
86
+ scripts: {
87
+ build: "bun run scripts/build.ts",
88
+ "build:dev": "bun run scripts/build.ts --dev",
89
+ publish: "bun run scripts/publish.ts",
90
+ test: "bun test"
91
+ },
92
+ devDependencies: {
93
+ "@types/bun": "latest",
94
+ "@types/node": "^24.0.0",
95
+ "@types/react": "^19.0.0",
96
+ "@types/react-reconciler": "^0.32.0",
97
+ "@types/ws": "^8.18.1",
98
+ react: ">=19.0.0",
99
+ "react-devtools-core": "^7.0.1",
100
+ typescript: "^5",
101
+ ws: "^8.18.0"
102
+ },
103
+ peerDependencies: {
104
+ react: ">=19.0.0",
105
+ "react-devtools-core": "^7.0.1",
106
+ ws: "^8.18.0"
107
+ },
108
+ peerDependenciesMeta: {
109
+ "react-devtools-core": {
110
+ optional: true
111
+ },
112
+ ws: {
113
+ optional: true
114
+ }
115
+ },
116
+ dependencies: {
117
+ "@opentui/core": "workspace:*",
118
+ "react-reconciler": "^0.32.0"
119
+ }
120
+ };
121
+
122
+ // src/reconciler/host-config.ts
48
123
  import { createContext as createContext2 } from "react";
49
124
  import { DefaultEventPriority, NoEventPriority } from "react-reconciler/constants";
50
125
 
@@ -65,7 +140,7 @@ import {
65
140
 
66
141
  // src/components/text.ts
67
142
  import { TextAttributes, TextNodeRenderable } from "@opentui/core";
68
- var textNodeKeys = ["span", "b", "strong", "i", "em", "u", "br"];
143
+ var textNodeKeys = ["span", "b", "strong", "i", "em", "u", "br", "a"];
69
144
 
70
145
  class SpanRenderable extends TextNodeRenderable {
71
146
  ctx;
@@ -117,6 +192,16 @@ class LineBreakRenderable extends SpanRenderable {
117
192
  }
118
193
  }
119
194
 
195
+ class LinkRenderable extends SpanRenderable {
196
+ constructor(_ctx, options) {
197
+ const linkOptions = {
198
+ ...options,
199
+ link: { url: options.href }
200
+ };
201
+ super(null, linkOptions);
202
+ }
203
+ }
204
+
120
205
  // src/components/index.ts
121
206
  var baseComponents = {
122
207
  box: BoxRenderable,
@@ -136,7 +221,8 @@ var baseComponents = {
136
221
  strong: BoldSpanRenderable,
137
222
  i: ItalicSpanRenderable,
138
223
  em: ItalicSpanRenderable,
139
- u: UnderlineSpanRenderable
224
+ u: UnderlineSpanRenderable,
225
+ a: LinkRenderable
140
226
  };
141
227
  var componentCatalogue = { ...baseComponents };
142
228
  function getComponentCatalogue() {
@@ -173,18 +259,21 @@ function initEventListeners(instance, eventName, listener, previousListener) {
173
259
  }
174
260
  }
175
261
  function setStyle(instance, styles, oldStyles) {
176
- if (styles && typeof styles === "object") {
177
- if (oldStyles != null) {
178
- for (const styleName in styles) {
179
- const value = styles[styleName];
180
- if (styles.hasOwnProperty(styleName) && oldStyles[styleName] !== value) {
181
- instance[styleName] = value;
262
+ if (oldStyles != null && typeof oldStyles === "object") {
263
+ for (const styleName in oldStyles) {
264
+ if (oldStyles.hasOwnProperty(styleName)) {
265
+ if (styles == null || !styles.hasOwnProperty(styleName)) {
266
+ instance[styleName] = null;
182
267
  }
183
268
  }
184
- } else {
185
- for (const styleName in styles) {
186
- if (styles.hasOwnProperty(styleName)) {
187
- const value = styles[styleName];
269
+ }
270
+ }
271
+ if (styles != null && typeof styles === "object") {
272
+ for (const styleName in styles) {
273
+ if (styles.hasOwnProperty(styleName)) {
274
+ const value = styles[styleName];
275
+ const oldValue = oldStyles?.[styleName];
276
+ if (value !== oldValue) {
188
277
  instance[styleName] = value;
189
278
  }
190
279
  }
@@ -417,11 +506,33 @@ var hostConfig = {
417
506
  prepareScopeUpdate() {},
418
507
  getInstanceFromScope() {
419
508
  return null;
420
- }
509
+ },
510
+ rendererPackageName: "@opentui/react",
511
+ rendererVersion: package_default.version
421
512
  };
422
513
 
423
514
  // src/reconciler/reconciler.ts
424
515
  var reconciler = ReactReconciler(hostConfig);
516
+ if (process.env["DEV"] === "true") {
517
+ try {
518
+ await import("./chunk-fcedq94e.js");
519
+ } catch (error) {
520
+ if (error.code === "ERR_MODULE_NOT_FOUND") {
521
+ console.warn(`
522
+ The environment variable DEV is set to true, so opentui tried to import \`react-devtools-core\`,
523
+ but this failed as it was not installed. Debugging with React DevTools requires it.
524
+
525
+ To install use this command:
526
+
527
+ $ bun add react-devtools-core@7 -d
528
+ `.trim() + `
529
+ `);
530
+ } else {
531
+ throw error;
532
+ }
533
+ }
534
+ }
535
+ reconciler.injectIntoDevTools();
425
536
  function _render(element, root) {
426
537
  const container = reconciler.createContainer(root, ConcurrentRoot, null, false, null, "", console.error, console.error, console.error, console.error, null);
427
538
  reconciler.updateContainer(element, container, null, () => {});
@@ -429,6 +540,7 @@ function _render(element, root) {
429
540
  }
430
541
 
431
542
  // src/reconciler/renderer.ts
543
+ var { flushSync, createPortal } = reconciler;
432
544
  function createRoot(renderer) {
433
545
  let container = null;
434
546
  return {
@@ -447,5 +559,7 @@ function createRoot(renderer) {
447
559
  };
448
560
  }
449
561
  export {
450
- createRoot
562
+ flushSync,
563
+ createRoot,
564
+ createPortal
451
565
  };
@@ -0,0 +1,20 @@
1
+ // @bun
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __require = import.meta.require;
19
+
20
+ export { __toESM, __require };
@@ -0,0 +1,29 @@
1
+ // @bun
2
+ import {
3
+ __require,
4
+ __toESM
5
+ } from "./chunk-e11q5a3p.js";
6
+
7
+ // src/reconciler/devtools-polyfill.ts
8
+ var g = globalThis;
9
+ if (typeof g.WebSocket === "undefined") {
10
+ try {
11
+ const ws = await import("ws");
12
+ g.WebSocket = ws.default;
13
+ } catch {}
14
+ }
15
+ g.window ||= globalThis;
16
+ g.self ||= globalThis;
17
+ g.window.__REACT_DEVTOOLS_COMPONENT_FILTERS__ = [
18
+ {
19
+ type: 2,
20
+ value: "ErrorBoundary",
21
+ isEnabled: true,
22
+ isValid: true
23
+ }
24
+ ];
25
+
26
+ // src/reconciler/devtools.ts
27
+ import devtools from "react-devtools-core";
28
+ devtools.initialize();
29
+ devtools.connectToDevTools();
@@ -1,4 +1,9 @@
1
1
  // @bun
2
+ import {
3
+ __require,
4
+ __toESM
5
+ } from "./chunk-e11q5a3p.js";
6
+
2
7
  // src/test-utils.ts
3
8
  import { createTestRenderer } from "@opentui/core/testing";
4
9
  import { act } from "react";
@@ -49,6 +54,76 @@ import { ConcurrentRoot } from "react-reconciler/constants";
49
54
 
50
55
  // src/reconciler/host-config.ts
51
56
  import { TextNodeRenderable as TextNodeRenderable2 } from "@opentui/core";
57
+ // package.json
58
+ var package_default = {
59
+ name: "@opentui/react",
60
+ version: "0.1.64",
61
+ description: "React renderer for building terminal user interfaces using OpenTUI core",
62
+ license: "MIT",
63
+ repository: {
64
+ type: "git",
65
+ url: "https://github.com/sst/opentui",
66
+ directory: "packages/react"
67
+ },
68
+ module: "src/index.ts",
69
+ type: "module",
70
+ private: true,
71
+ main: "src/index.ts",
72
+ exports: {
73
+ ".": {
74
+ import: "./src/index.ts",
75
+ types: "./src/index.ts"
76
+ },
77
+ "./test-utils": {
78
+ import: "./src/test-utils.ts",
79
+ types: "./src/test-utils.d.ts"
80
+ },
81
+ "./jsx-runtime": {
82
+ import: "./jsx-runtime.js",
83
+ types: "./jsx-runtime.d.ts"
84
+ },
85
+ "./jsx-dev-runtime": {
86
+ import: "./jsx-dev-runtime.js",
87
+ types: "./jsx-dev-runtime.d.ts"
88
+ }
89
+ },
90
+ scripts: {
91
+ build: "bun run scripts/build.ts",
92
+ "build:dev": "bun run scripts/build.ts --dev",
93
+ publish: "bun run scripts/publish.ts",
94
+ test: "bun test"
95
+ },
96
+ devDependencies: {
97
+ "@types/bun": "latest",
98
+ "@types/node": "^24.0.0",
99
+ "@types/react": "^19.0.0",
100
+ "@types/react-reconciler": "^0.32.0",
101
+ "@types/ws": "^8.18.1",
102
+ react: ">=19.0.0",
103
+ "react-devtools-core": "^7.0.1",
104
+ typescript: "^5",
105
+ ws: "^8.18.0"
106
+ },
107
+ peerDependencies: {
108
+ react: ">=19.0.0",
109
+ "react-devtools-core": "^7.0.1",
110
+ ws: "^8.18.0"
111
+ },
112
+ peerDependenciesMeta: {
113
+ "react-devtools-core": {
114
+ optional: true
115
+ },
116
+ ws: {
117
+ optional: true
118
+ }
119
+ },
120
+ dependencies: {
121
+ "@opentui/core": "workspace:*",
122
+ "react-reconciler": "^0.32.0"
123
+ }
124
+ };
125
+
126
+ // src/reconciler/host-config.ts
52
127
  import { createContext as createContext2 } from "react";
53
128
  import { DefaultEventPriority, NoEventPriority } from "react-reconciler/constants";
54
129
 
@@ -69,7 +144,7 @@ import {
69
144
 
70
145
  // src/components/text.ts
71
146
  import { TextAttributes, TextNodeRenderable } from "@opentui/core";
72
- var textNodeKeys = ["span", "b", "strong", "i", "em", "u", "br"];
147
+ var textNodeKeys = ["span", "b", "strong", "i", "em", "u", "br", "a"];
73
148
 
74
149
  class SpanRenderable extends TextNodeRenderable {
75
150
  ctx;
@@ -121,6 +196,16 @@ class LineBreakRenderable extends SpanRenderable {
121
196
  }
122
197
  }
123
198
 
199
+ class LinkRenderable extends SpanRenderable {
200
+ constructor(_ctx, options) {
201
+ const linkOptions = {
202
+ ...options,
203
+ link: { url: options.href }
204
+ };
205
+ super(null, linkOptions);
206
+ }
207
+ }
208
+
124
209
  // src/components/index.ts
125
210
  var baseComponents = {
126
211
  box: BoxRenderable,
@@ -140,7 +225,8 @@ var baseComponents = {
140
225
  strong: BoldSpanRenderable,
141
226
  i: ItalicSpanRenderable,
142
227
  em: ItalicSpanRenderable,
143
- u: UnderlineSpanRenderable
228
+ u: UnderlineSpanRenderable,
229
+ a: LinkRenderable
144
230
  };
145
231
  var componentCatalogue = { ...baseComponents };
146
232
  function getComponentCatalogue() {
@@ -177,18 +263,21 @@ function initEventListeners(instance, eventName, listener, previousListener) {
177
263
  }
178
264
  }
179
265
  function setStyle(instance, styles, oldStyles) {
180
- if (styles && typeof styles === "object") {
181
- if (oldStyles != null) {
182
- for (const styleName in styles) {
183
- const value = styles[styleName];
184
- if (styles.hasOwnProperty(styleName) && oldStyles[styleName] !== value) {
185
- instance[styleName] = value;
266
+ if (oldStyles != null && typeof oldStyles === "object") {
267
+ for (const styleName in oldStyles) {
268
+ if (oldStyles.hasOwnProperty(styleName)) {
269
+ if (styles == null || !styles.hasOwnProperty(styleName)) {
270
+ instance[styleName] = null;
186
271
  }
187
272
  }
188
- } else {
189
- for (const styleName in styles) {
190
- if (styles.hasOwnProperty(styleName)) {
191
- const value = styles[styleName];
273
+ }
274
+ }
275
+ if (styles != null && typeof styles === "object") {
276
+ for (const styleName in styles) {
277
+ if (styles.hasOwnProperty(styleName)) {
278
+ const value = styles[styleName];
279
+ const oldValue = oldStyles?.[styleName];
280
+ if (value !== oldValue) {
192
281
  instance[styleName] = value;
193
282
  }
194
283
  }
@@ -421,11 +510,33 @@ var hostConfig = {
421
510
  prepareScopeUpdate() {},
422
511
  getInstanceFromScope() {
423
512
  return null;
424
- }
513
+ },
514
+ rendererPackageName: "@opentui/react",
515
+ rendererVersion: package_default.version
425
516
  };
426
517
 
427
518
  // src/reconciler/reconciler.ts
428
519
  var reconciler = ReactReconciler(hostConfig);
520
+ if (process.env["DEV"] === "true") {
521
+ try {
522
+ await import("./chunk-fcedq94e.js");
523
+ } catch (error) {
524
+ if (error.code === "ERR_MODULE_NOT_FOUND") {
525
+ console.warn(`
526
+ The environment variable DEV is set to true, so opentui tried to import \`react-devtools-core\`,
527
+ but this failed as it was not installed. Debugging with React DevTools requires it.
528
+
529
+ To install use this command:
530
+
531
+ $ bun add react-devtools-core@7 -d
532
+ `.trim() + `
533
+ `);
534
+ } else {
535
+ throw error;
536
+ }
537
+ }
538
+ }
539
+ reconciler.injectIntoDevTools();
429
540
  function _render(element, root) {
430
541
  const container = reconciler.createContainer(root, ConcurrentRoot, null, false, null, "", console.error, console.error, console.error, console.error, null);
431
542
  reconciler.updateContainer(element, container, null, () => {});
@@ -31,6 +31,9 @@ export type TextProps = ComponentProps<TextOptions, TextRenderable> & {
31
31
  export type SpanProps = ComponentProps<TextNodeOptions, TextNodeRenderable> & {
32
32
  children?: TextChildren;
33
33
  };
34
+ export type LinkProps = SpanProps & {
35
+ href: string;
36
+ };
34
37
  export type LineBreakProps = Pick<SpanProps, "id">;
35
38
  export type BoxProps = ComponentProps<ContainerProps<BoxOptions>, BoxRenderable>;
36
39
  export type InputProps = ComponentProps<InputRenderableOptions, InputRenderable> & {