tinky 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 (99) hide show
  1. package/LICENSE +47 -0
  2. package/README.ja-JP.md +350 -0
  3. package/README.md +350 -0
  4. package/README.zh-CN.md +350 -0
  5. package/lib/colorize.d.ts +16 -0
  6. package/lib/colorize.js +55 -0
  7. package/lib/components/AccessibilityContext.d.ts +9 -0
  8. package/lib/components/AccessibilityContext.js +10 -0
  9. package/lib/components/App.d.ts +169 -0
  10. package/lib/components/App.js +314 -0
  11. package/lib/components/AppContext.d.ts +14 -0
  12. package/lib/components/AppContext.js +11 -0
  13. package/lib/components/BackgroundContext.d.ts +10 -0
  14. package/lib/components/BackgroundContext.js +5 -0
  15. package/lib/components/Box.d.ts +153 -0
  16. package/lib/components/Box.js +57 -0
  17. package/lib/components/ErrorOverview.d.ts +9 -0
  18. package/lib/components/ErrorOverview.js +49 -0
  19. package/lib/components/FocusContext.d.ts +51 -0
  20. package/lib/components/FocusContext.js +35 -0
  21. package/lib/components/Newline.d.ts +29 -0
  22. package/lib/components/Newline.js +21 -0
  23. package/lib/components/Spacer.d.ts +19 -0
  24. package/lib/components/Spacer.js +23 -0
  25. package/lib/components/Static.d.ts +48 -0
  26. package/lib/components/Static.js +46 -0
  27. package/lib/components/StderrContext.d.ts +21 -0
  28. package/lib/components/StderrContext.js +12 -0
  29. package/lib/components/StdinContext.d.ts +36 -0
  30. package/lib/components/StdinContext.js +16 -0
  31. package/lib/components/StdoutContext.d.ts +22 -0
  32. package/lib/components/StdoutContext.js +13 -0
  33. package/lib/components/Text.d.ts +84 -0
  34. package/lib/components/Text.js +74 -0
  35. package/lib/components/Transform.d.ts +41 -0
  36. package/lib/components/Transform.js +32 -0
  37. package/lib/devtools-window-polyfill.d.ts +1 -0
  38. package/lib/devtools-window-polyfill.js +70 -0
  39. package/lib/devtools.d.ts +1 -0
  40. package/lib/devtools.js +8 -0
  41. package/lib/dom.d.ts +130 -0
  42. package/lib/dom.js +209 -0
  43. package/lib/get-max-width.d.ts +9 -0
  44. package/lib/get-max-width.js +14 -0
  45. package/lib/hooks/use-app.d.ts +26 -0
  46. package/lib/hooks/use-app.js +28 -0
  47. package/lib/hooks/use-focus-manager.d.ts +40 -0
  48. package/lib/hooks/use-focus-manager.js +18 -0
  49. package/lib/hooks/use-focus.d.ts +67 -0
  50. package/lib/hooks/use-focus.js +65 -0
  51. package/lib/hooks/use-input.d.ts +118 -0
  52. package/lib/hooks/use-input.js +101 -0
  53. package/lib/hooks/use-is-screen-reader-enabled.d.ts +7 -0
  54. package/lib/hooks/use-is-screen-reader-enabled.js +12 -0
  55. package/lib/hooks/use-stderr.d.ts +6 -0
  56. package/lib/hooks/use-stderr.js +8 -0
  57. package/lib/hooks/use-stdin.d.ts +6 -0
  58. package/lib/hooks/use-stdin.js +8 -0
  59. package/lib/hooks/use-stdout.d.ts +7 -0
  60. package/lib/hooks/use-stdout.js +9 -0
  61. package/lib/index.d.ts +22 -0
  62. package/lib/index.js +20 -0
  63. package/lib/instances.d.ts +10 -0
  64. package/lib/instances.js +9 -0
  65. package/lib/log-update.d.ts +32 -0
  66. package/lib/log-update.js +147 -0
  67. package/lib/measure-element.d.ts +19 -0
  68. package/lib/measure-element.js +13 -0
  69. package/lib/measure-text.d.ts +13 -0
  70. package/lib/measure-text.js +26 -0
  71. package/lib/output.d.ts +73 -0
  72. package/lib/output.js +190 -0
  73. package/lib/parse-keypress.d.ts +20 -0
  74. package/lib/parse-keypress.js +228 -0
  75. package/lib/reconciler.d.ts +12 -0
  76. package/lib/reconciler.js +282 -0
  77. package/lib/render-background.d.ts +11 -0
  78. package/lib/render-background.js +32 -0
  79. package/lib/render-border.d.ts +13 -0
  80. package/lib/render-border.js +82 -0
  81. package/lib/render-node-to-output.d.ts +43 -0
  82. package/lib/render-node-to-output.js +179 -0
  83. package/lib/render.d.ts +129 -0
  84. package/lib/render.js +84 -0
  85. package/lib/renderer.d.ts +27 -0
  86. package/lib/renderer.js +62 -0
  87. package/lib/signal-exit.d.ts +11 -0
  88. package/lib/signal-exit.js +24 -0
  89. package/lib/squash-text-nodes.d.ts +10 -0
  90. package/lib/squash-text-nodes.js +36 -0
  91. package/lib/styles.d.ts +402 -0
  92. package/lib/styles.js +633 -0
  93. package/lib/taffy-node.d.ts +39 -0
  94. package/lib/taffy-node.js +60 -0
  95. package/lib/tinky.d.ts +153 -0
  96. package/lib/tinky.js +396 -0
  97. package/lib/wrap-text.d.ts +11 -0
  98. package/lib/wrap-text.js +38 -0
  99. package/package.json +87 -0
package/README.md ADDED
@@ -0,0 +1,350 @@
1
+ <p align="center">
2
+ <h1 align="center">Tinky</h1>
3
+ <p align="center">
4
+ <strong>React for CLIs, re-imagined with the Taffy layout engine</strong>
5
+ </p>
6
+ <p align="center">
7
+ <a href="./README.zh-CN.md">中文</a> · <a href="./README.ja-JP.md">日本語</a>
8
+ </p>
9
+ </p>
10
+
11
+ ---
12
+
13
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
14
+ [![npm version](https://img.shields.io/npm/v/tinky.svg)](https://www.npmjs.com/package/tinky)
15
+
16
+ Tinky is a modern React-based framework for building beautiful and interactive command-line interfaces. It leverages the powerful [Taffy](https://github.com/DioxusLabs/taffy) layout engine to provide **CSS Flexbox and Grid** layout support in the terminal.
17
+
18
+ ## ✨ Features
19
+
20
+ - 🎨 **React Components** — Build CLIs using familiar React patterns and JSX syntax
21
+ - 📐 **Flexbox & Grid Layout** — Full CSS Flexbox and CSS Grid support powered by Taffy
22
+ - ⌨️ **Keyboard Input** — Built-in hooks for handling keyboard input and focus management
23
+ - 🎯 **Focus Management** — Tab/Shift+Tab navigation with customizable focus behavior
24
+ - 🖼️ **Borders & Backgrounds** — Rich styling with borders, background colors, and more
25
+ - ♿ **Accessibility** — Screen reader support with ARIA attributes
26
+ - 🔄 **Hot Reloading** — Fast development with React DevTools support
27
+ - 📦 **TypeScript First** — Full TypeScript support with comprehensive type definitions
28
+
29
+ ## 📦 Installation
30
+
31
+ ```bash
32
+ # Using npm
33
+ npm install tinky react
34
+
35
+ # Using yarn
36
+ yarn add tinky react
37
+
38
+ # Using pnpm
39
+ pnpm add tinky react
40
+
41
+ # Using bun
42
+ bun add tinky react
43
+ ```
44
+
45
+ ## 🚀 Quick Start
46
+
47
+ ```tsx
48
+ import { render, Box, Text } from "tinky";
49
+
50
+ function App() {
51
+ return (
52
+ <Box flexDirection="column" padding={1}>
53
+ <Text color="green" bold>
54
+ Hello, Tinky! 🎉
55
+ </Text>
56
+ <Text>Build beautiful CLIs with React</Text>
57
+ </Box>
58
+ );
59
+ }
60
+
61
+ render(<App />);
62
+ ```
63
+
64
+ ## 📚 Components
65
+
66
+ ### Box
67
+
68
+ The `<Box>` component is a fundamental building block. It's like a `<div>` in the browser, supporting Flexbox and Grid layouts.
69
+
70
+ ```tsx
71
+ import { Box, Text } from "tinky";
72
+
73
+ // Flexbox layout
74
+ <Box flexDirection="row" gap={2}>
75
+ <Text>Left</Text>
76
+ <Text>Right</Text>
77
+ </Box>
78
+
79
+ // Grid layout
80
+ <Box display="grid" gridTemplateColumns="1fr 2fr 1fr" gap={1}>
81
+ <Text>Col 1</Text>
82
+ <Text>Col 2</Text>
83
+ <Text>Col 3</Text>
84
+ </Box>
85
+
86
+ // With borders and padding
87
+ <Box borderStyle="round" borderColor="cyan" padding={1}>
88
+ <Text>Styled Box</Text>
89
+ </Box>
90
+ ```
91
+
92
+ ### Text
93
+
94
+ The `<Text>` component renders styled text with colors, bold, italic, and more.
95
+
96
+ ```tsx
97
+ import { Text } from "tinky";
98
+
99
+ <Text color="blue">Blue text</Text>
100
+ <Text backgroundColor="red" color="white">Highlighted</Text>
101
+ <Text bold italic underline>Styled text</Text>
102
+ <Text color="#ff6600">Hex colors work too!</Text>
103
+ ```
104
+
105
+ ### Static
106
+
107
+ The `<Static>` component renders static content that won't be updated. Perfect for logs and history.
108
+
109
+ ```tsx
110
+ import { Static, Text } from "tinky";
111
+
112
+ const logs = ["Log 1", "Log 2", "Log 3"];
113
+
114
+ <Static items={logs}>{(log, index) => <Text key={index}>{log}</Text>}</Static>;
115
+ ```
116
+
117
+ ### Transform
118
+
119
+ The `<Transform>` component allows you to transform the output of its children.
120
+
121
+ ```tsx
122
+ import { Transform, Text } from "tinky";
123
+
124
+ <Transform transform={(output) => output.toUpperCase()}>
125
+ <Text>hello</Text>
126
+ </Transform>;
127
+ // Renders: HELLO
128
+ ```
129
+
130
+ ### Newline & Spacer
131
+
132
+ ```tsx
133
+ import { Box, Text, Newline, Spacer } from "tinky";
134
+
135
+ // Newline - adds vertical space
136
+ <Box flexDirection="column">
137
+ <Text>Line 1</Text>
138
+ <Newline count={2} />
139
+ <Text>Line 2</Text>
140
+ </Box>
141
+
142
+ // Spacer - flexible space in flex containers
143
+ <Box>
144
+ <Text>Left</Text>
145
+ <Spacer />
146
+ <Text>Right</Text>
147
+ </Box>
148
+ ```
149
+
150
+ ## 🪝 Hooks
151
+
152
+ ### useInput
153
+
154
+ Handle keyboard input in your components.
155
+
156
+ ```tsx
157
+ import { useInput, useApp } from "tinky";
158
+
159
+ function MyComponent() {
160
+ const { exit } = useApp();
161
+
162
+ useInput((input, key) => {
163
+ if (key.escape) {
164
+ exit();
165
+ }
166
+ if (key.upArrow) {
167
+ // Handle up arrow
168
+ }
169
+ if (input === "q") {
170
+ exit();
171
+ }
172
+ });
173
+
174
+ return <Text>Press 'q' to quit</Text>;
175
+ }
176
+ ```
177
+
178
+ ### useApp
179
+
180
+ Access the app instance to control exit behavior.
181
+
182
+ ```tsx
183
+ import { useApp } from "tinky";
184
+
185
+ function MyComponent() {
186
+ const { exit } = useApp();
187
+
188
+ // Exit with error
189
+ exit(new Error("Something went wrong"));
190
+
191
+ // Exit normally
192
+ exit();
193
+ }
194
+ ```
195
+
196
+ ### useFocus & useFocusManager
197
+
198
+ Manage focus for interactive components.
199
+
200
+ ```tsx
201
+ import { useFocus, Box, Text } from "tinky";
202
+
203
+ function FocusableItem({ label }: { label: string }) {
204
+ const { isFocused } = useFocus();
205
+
206
+ return (
207
+ <Box borderStyle={isFocused ? "bold" : "single"}>
208
+ <Text color={isFocused ? "green" : "white"}>{label}</Text>
209
+ </Box>
210
+ );
211
+ }
212
+ ```
213
+
214
+ ### useStdin, useStdout, useStderr
215
+
216
+ Direct access to stdin, stdout, and stderr streams.
217
+
218
+ ```tsx
219
+ import { useStdout, useEffect } from "tinky";
220
+
221
+ function MyComponent() {
222
+ const { write } = useStdout();
223
+
224
+ useEffect(() => {
225
+ write("Hello from stdout!\n");
226
+ }, []);
227
+
228
+ return null;
229
+ }
230
+ ```
231
+
232
+ ## 🎨 Styling
233
+
234
+ ### Flexbox Properties
235
+
236
+ ```tsx
237
+ <Box
238
+ flexDirection="row" // row, row-reverse, column, column-reverse
239
+ justifyContent="center" // flex-start, flex-end, center, space-between, space-around
240
+ alignItems="center" // flex-start, flex-end, center, stretch
241
+ flexWrap="wrap" // nowrap, wrap, wrap-reverse
242
+ flexGrow={1}
243
+ flexShrink={0}
244
+ gap={2}
245
+ />
246
+ ```
247
+
248
+ ### Grid Properties
249
+
250
+ ```tsx
251
+ <Box
252
+ display="grid"
253
+ gridTemplateColumns="1fr 2fr 1fr"
254
+ gridTemplateRows="auto 1fr"
255
+ columnGap={1}
256
+ rowGap={1}
257
+ justifyItems="center"
258
+ alignItems="center"
259
+ />
260
+ ```
261
+
262
+ ### Border Styles
263
+
264
+ ```tsx
265
+ <Box borderStyle="single" /> // ┌─┐
266
+ <Box borderStyle="double" /> // ╔═╗
267
+ <Box borderStyle="round" /> // ╭─╮
268
+ <Box borderStyle="bold" /> // ┏━┓
269
+ <Box borderStyle="classic" /> // +--+
270
+ ```
271
+
272
+ ### Colors
273
+
274
+ Tinky supports multiple color formats:
275
+
276
+ ```tsx
277
+ <Text color="red" /> // Named colors
278
+ <Text color="#ff6600" /> // Hex colors
279
+ <Text color="rgb(255, 102, 0)" /> // RGB colors
280
+ <Text color="ansi256:208" /> // ANSI 256 colors
281
+ ```
282
+
283
+ ## 🔧 API Reference
284
+
285
+ ### render(element, options?)
286
+
287
+ Render a React element to the terminal.
288
+
289
+ ```tsx
290
+ import { render } from "tinky";
291
+
292
+ const { unmount, waitUntilExit, rerender, clear } = render(<App />, {
293
+ stdout: process.stdout,
294
+ stdin: process.stdin,
295
+ stderr: process.stderr,
296
+ exitOnCtrlC: true,
297
+ patchConsole: true,
298
+ });
299
+
300
+ // Wait for the app to exit
301
+ await waitUntilExit();
302
+
303
+ // Rerender with new props
304
+ rerender(<App newProp={true} />);
305
+
306
+ // Unmount the app
307
+ unmount();
308
+
309
+ // Clear the output
310
+ clear();
311
+ ```
312
+
313
+ ### measureElement(ref)
314
+
315
+ Measure the dimensions of a rendered element.
316
+
317
+ ```tsx
318
+ import { measureElement, Box, useRef, useEffect } from "tinky";
319
+
320
+ function MyComponent() {
321
+ const ref = useRef(null);
322
+
323
+ useEffect(() => {
324
+ if (ref.current) {
325
+ const { width, height } = measureElement(ref.current);
326
+ console.log(`Size: ${width}x${height}`);
327
+ }
328
+ }, []);
329
+
330
+ return <Box ref={ref}>Content</Box>;
331
+ }
332
+ ```
333
+
334
+ ## 🧪 Testing
335
+
336
+ Tinky uses Bun for testing. Run the test suite:
337
+
338
+ ```bash
339
+ bun test
340
+ ```
341
+
342
+ ## 📄 License
343
+
344
+ MIT © [ByteLandTechnology](https://github.com/ByteLandTechnology)
345
+
346
+ ## 🙏 Acknowledgements
347
+
348
+ - [Ink](https://github.com/vadimdemedes/ink) — The original React for CLIs
349
+ - [Taffy](https://github.com/DioxusLabs/taffy) — High-performance CSS layout engine
350
+ - [React](https://reactjs.org/) — The UI library that makes this possible
@@ -0,0 +1,350 @@
1
+ <p align="center">
2
+ <h1 align="center">Tinky</h1>
3
+ <p align="center">
4
+ <strong>使用 Taffy 布局引擎重新构想的 React CLI 框架</strong>
5
+ </p>
6
+ <p align="center">
7
+ <a href="./README.md">English</a> · <a href="./README.ja-JP.md">日本語</a>
8
+ </p>
9
+ </p>
10
+
11
+ ---
12
+
13
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
14
+ [![npm version](https://img.shields.io/npm/v/tinky.svg)](https://www.npmjs.com/package/tinky)
15
+
16
+ Tinky 是一个现代化的基于 React 的框架,用于构建美观且交互式的命令行界面。它利用强大的 [Taffy](https://github.com/DioxusLabs/taffy) 布局引擎,在终端中提供 **CSS Flexbox 和 Grid** 布局支持。
17
+
18
+ ## ✨ 特性
19
+
20
+ - 🎨 **React 组件** — 使用熟悉的 React 模式和 JSX 语法构建 CLI
21
+ - 📐 **Flexbox 和 Grid 布局** — 由 Taffy 驱动的完整 CSS Flexbox 和 CSS Grid 支持
22
+ - ⌨️ **键盘输入** — 内置处理键盘输入和焦点管理的 hooks
23
+ - 🎯 **焦点管理** — Tab/Shift+Tab 导航,可自定义焦点行为
24
+ - 🖼️ **边框和背景** — 丰富的边框、背景色等样式支持
25
+ - ♿ **无障碍访问** — 支持 ARIA 属性的屏幕阅读器
26
+ - 🔄 **热重载** — 支持 React DevTools 的快速开发体验
27
+ - 📦 **TypeScript 优先** — 完整的 TypeScript 支持和类型定义
28
+
29
+ ## 📦 安装
30
+
31
+ ```bash
32
+ # 使用 npm
33
+ npm install tinky react
34
+
35
+ # 使用 yarn
36
+ yarn add tinky react
37
+
38
+ # 使用 pnpm
39
+ pnpm add tinky react
40
+
41
+ # 使用 bun
42
+ bun add tinky react
43
+ ```
44
+
45
+ ## 🚀 快速开始
46
+
47
+ ```tsx
48
+ import { render, Box, Text } from "tinky";
49
+
50
+ function App() {
51
+ return (
52
+ <Box flexDirection="column" padding={1}>
53
+ <Text color="green" bold>
54
+ 你好,Tinky!🎉
55
+ </Text>
56
+ <Text>用 React 构建漂亮的 CLI</Text>
57
+ </Box>
58
+ );
59
+ }
60
+
61
+ render(<App />);
62
+ ```
63
+
64
+ ## 📚 组件
65
+
66
+ ### Box
67
+
68
+ `<Box>` 组件是基础构建块。它类似于浏览器中的 `<div>`,支持 Flexbox 和 Grid 布局。
69
+
70
+ ```tsx
71
+ import { Box, Text } from "tinky";
72
+
73
+ // Flexbox 布局
74
+ <Box flexDirection="row" gap={2}>
75
+ <Text>左边</Text>
76
+ <Text>右边</Text>
77
+ </Box>
78
+
79
+ // Grid 布局
80
+ <Box display="grid" gridTemplateColumns="1fr 2fr 1fr" gap={1}>
81
+ <Text>列 1</Text>
82
+ <Text>列 2</Text>
83
+ <Text>列 3</Text>
84
+ </Box>
85
+
86
+ // 带边框和内边距
87
+ <Box borderStyle="round" borderColor="cyan" padding={1}>
88
+ <Text>样式化的 Box</Text>
89
+ </Box>
90
+ ```
91
+
92
+ ### Text
93
+
94
+ `<Text>` 组件渲染带样式的文本,支持颜色、粗体、斜体等。
95
+
96
+ ```tsx
97
+ import { Text } from "tinky";
98
+
99
+ <Text color="blue">蓝色文本</Text>
100
+ <Text backgroundColor="red" color="white">高亮显示</Text>
101
+ <Text bold italic underline>样式化文本</Text>
102
+ <Text color="#ff6600">也支持十六进制颜色!</Text>
103
+ ```
104
+
105
+ ### Static
106
+
107
+ `<Static>` 组件渲染不会更新的静态内容。非常适合日志和历史记录。
108
+
109
+ ```tsx
110
+ import { Static, Text } from "tinky";
111
+
112
+ const logs = ["日志 1", "日志 2", "日志 3"];
113
+
114
+ <Static items={logs}>{(log, index) => <Text key={index}>{log}</Text>}</Static>;
115
+ ```
116
+
117
+ ### Transform
118
+
119
+ `<Transform>` 组件允许你转换其子元素的输出。
120
+
121
+ ```tsx
122
+ import { Transform, Text } from "tinky";
123
+
124
+ <Transform transform={(output) => output.toUpperCase()}>
125
+ <Text>hello</Text>
126
+ </Transform>;
127
+ // 渲染结果: HELLO
128
+ ```
129
+
130
+ ### Newline 和 Spacer
131
+
132
+ ```tsx
133
+ import { Box, Text, Newline, Spacer } from "tinky";
134
+
135
+ // Newline - 添加垂直空间
136
+ <Box flexDirection="column">
137
+ <Text>第一行</Text>
138
+ <Newline count={2} />
139
+ <Text>第二行</Text>
140
+ </Box>
141
+
142
+ // Spacer - flex 容器中的弹性空间
143
+ <Box>
144
+ <Text>左边</Text>
145
+ <Spacer />
146
+ <Text>右边</Text>
147
+ </Box>
148
+ ```
149
+
150
+ ## 🪝 Hooks
151
+
152
+ ### useInput
153
+
154
+ 在组件中处理键盘输入。
155
+
156
+ ```tsx
157
+ import { useInput, useApp } from "tinky";
158
+
159
+ function MyComponent() {
160
+ const { exit } = useApp();
161
+
162
+ useInput((input, key) => {
163
+ if (key.escape) {
164
+ exit();
165
+ }
166
+ if (key.upArrow) {
167
+ // 处理上箭头
168
+ }
169
+ if (input === "q") {
170
+ exit();
171
+ }
172
+ });
173
+
174
+ return <Text>按 'q' 退出</Text>;
175
+ }
176
+ ```
177
+
178
+ ### useApp
179
+
180
+ 访问应用实例以控制退出行为。
181
+
182
+ ```tsx
183
+ import { useApp } from "tinky";
184
+
185
+ function MyComponent() {
186
+ const { exit } = useApp();
187
+
188
+ // 带错误退出
189
+ exit(new Error("出错了"));
190
+
191
+ // 正常退出
192
+ exit();
193
+ }
194
+ ```
195
+
196
+ ### useFocus 和 useFocusManager
197
+
198
+ 管理交互式组件的焦点。
199
+
200
+ ```tsx
201
+ import { useFocus, Box, Text } from "tinky";
202
+
203
+ function FocusableItem({ label }: { label: string }) {
204
+ const { isFocused } = useFocus();
205
+
206
+ return (
207
+ <Box borderStyle={isFocused ? "bold" : "single"}>
208
+ <Text color={isFocused ? "green" : "white"}>{label}</Text>
209
+ </Box>
210
+ );
211
+ }
212
+ ```
213
+
214
+ ### useStdin、useStdout、useStderr
215
+
216
+ 直接访问 stdin、stdout 和 stderr 流。
217
+
218
+ ```tsx
219
+ import { useStdout, useEffect } from "tinky";
220
+
221
+ function MyComponent() {
222
+ const { write } = useStdout();
223
+
224
+ useEffect(() => {
225
+ write("来自 stdout 的问候!\n");
226
+ }, []);
227
+
228
+ return null;
229
+ }
230
+ ```
231
+
232
+ ## 🎨 样式
233
+
234
+ ### Flexbox 属性
235
+
236
+ ```tsx
237
+ <Box
238
+ flexDirection="row" // row, row-reverse, column, column-reverse
239
+ justifyContent="center" // flex-start, flex-end, center, space-between, space-around
240
+ alignItems="center" // flex-start, flex-end, center, stretch
241
+ flexWrap="wrap" // nowrap, wrap, wrap-reverse
242
+ flexGrow={1}
243
+ flexShrink={0}
244
+ gap={2}
245
+ />
246
+ ```
247
+
248
+ ### Grid 属性
249
+
250
+ ```tsx
251
+ <Box
252
+ display="grid"
253
+ gridTemplateColumns="1fr 2fr 1fr"
254
+ gridTemplateRows="auto 1fr"
255
+ columnGap={1}
256
+ rowGap={1}
257
+ justifyItems="center"
258
+ alignItems="center"
259
+ />
260
+ ```
261
+
262
+ ### 边框样式
263
+
264
+ ```tsx
265
+ <Box borderStyle="single" /> // ┌─┐
266
+ <Box borderStyle="double" /> // ╔═╗
267
+ <Box borderStyle="round" /> // ╭─╮
268
+ <Box borderStyle="bold" /> // ┏━┓
269
+ <Box borderStyle="classic" /> // +--+
270
+ ```
271
+
272
+ ### 颜色
273
+
274
+ Tinky 支持多种颜色格式:
275
+
276
+ ```tsx
277
+ <Text color="red" /> // 命名颜色
278
+ <Text color="#ff6600" /> // 十六进制颜色
279
+ <Text color="rgb(255, 102, 0)" /> // RGB 颜色
280
+ <Text color="ansi256:208" /> // ANSI 256 颜色
281
+ ```
282
+
283
+ ## 🔧 API 参考
284
+
285
+ ### render(element, options?)
286
+
287
+ 将 React 元素渲染到终端。
288
+
289
+ ```tsx
290
+ import { render } from "tinky";
291
+
292
+ const { unmount, waitUntilExit, rerender, clear } = render(<App />, {
293
+ stdout: process.stdout,
294
+ stdin: process.stdin,
295
+ stderr: process.stderr,
296
+ exitOnCtrlC: true,
297
+ patchConsole: true,
298
+ });
299
+
300
+ // 等待应用退出
301
+ await waitUntilExit();
302
+
303
+ // 使用新 props 重新渲染
304
+ rerender(<App newProp={true} />);
305
+
306
+ // 卸载应用
307
+ unmount();
308
+
309
+ // 清除输出
310
+ clear();
311
+ ```
312
+
313
+ ### measureElement(ref)
314
+
315
+ 测量已渲染元素的尺寸。
316
+
317
+ ```tsx
318
+ import { measureElement, Box, useRef, useEffect } from "tinky";
319
+
320
+ function MyComponent() {
321
+ const ref = useRef(null);
322
+
323
+ useEffect(() => {
324
+ if (ref.current) {
325
+ const { width, height } = measureElement(ref.current);
326
+ console.log(`尺寸: ${width}x${height}`);
327
+ }
328
+ }, []);
329
+
330
+ return <Box ref={ref}>内容</Box>;
331
+ }
332
+ ```
333
+
334
+ ## 🧪 测试
335
+
336
+ Tinky 使用 Bun 进行测试。运行测试套件:
337
+
338
+ ```bash
339
+ bun test
340
+ ```
341
+
342
+ ## 📄 许可证
343
+
344
+ MIT © [ByteLandTechnology](https://github.com/ByteLandTechnology)
345
+
346
+ ## 🙏 致谢
347
+
348
+ - [Ink](https://github.com/vadimdemedes/ink) — 原版 React CLI 框架
349
+ - [Taffy](https://github.com/DioxusLabs/taffy) — 高性能 CSS 布局引擎
350
+ - [React](https://reactjs.org/) — 使这一切成为可能的 UI 库
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Type representing the target of the color application (foreground or
3
+ * background).
4
+ */
5
+ type ColorType = "foreground" | "background";
6
+ /**
7
+ * Applies a color to a string using Chalk.
8
+ * Supports named colors, hex codes, RGB values, and ANSI-256 color codes.
9
+ *
10
+ * @param str - The string to colorize.
11
+ * @param color - The color to apply.
12
+ * @param type - Whether to apply the color to the foreground or background.
13
+ * @returns The colorized string.
14
+ */
15
+ export declare const colorize: (str: string, color: string | undefined, type: ColorType) => string;
16
+ export {};