linecraft 0.1.0 → 0.2.1
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 +1 -1
- package/README.md +337 -64
- package/lib/api/color.d.ts +6 -0
- package/lib/api/color.d.ts.map +1 -0
- package/lib/api/color.js +9 -0
- package/lib/api/color.js.map +1 -0
- package/lib/api/color.test.d.ts +2 -0
- package/lib/api/color.test.d.ts.map +1 -0
- package/lib/api/color.test.js +23 -0
- package/lib/api/color.test.js.map +1 -0
- package/lib/api/flex.d.ts +55 -0
- package/lib/api/flex.d.ts.map +1 -0
- package/lib/api/flex.js +86 -0
- package/lib/api/flex.js.map +1 -0
- package/lib/api/flex.test.d.ts +2 -0
- package/lib/api/flex.test.d.ts.map +1 -0
- package/lib/api/flex.test.js +82 -0
- package/lib/api/flex.test.js.map +1 -0
- package/lib/api/grid.d.ts +22 -0
- package/lib/api/grid.d.ts.map +1 -0
- package/lib/api/grid.js +65 -0
- package/lib/api/grid.js.map +1 -0
- package/lib/api/grid.test.d.ts +2 -0
- package/lib/api/grid.test.d.ts.map +1 -0
- package/lib/api/grid.test.js +48 -0
- package/lib/api/grid.test.js.map +1 -0
- package/lib/components/base.d.ts +53 -0
- package/lib/components/base.d.ts.map +1 -0
- package/lib/components/base.js +47 -0
- package/lib/components/base.js.map +1 -0
- package/lib/components/col.d.ts +35 -0
- package/lib/components/col.d.ts.map +1 -0
- package/lib/components/col.js +168 -0
- package/lib/components/col.js.map +1 -0
- package/lib/components/col.test.d.ts +2 -0
- package/lib/components/col.test.d.ts.map +1 -0
- package/lib/components/col.test.js +96 -0
- package/lib/components/col.test.js.map +1 -0
- package/lib/components/index.d.ts +3 -0
- package/lib/components/index.d.ts.map +1 -0
- package/lib/components/index.js +5 -0
- package/lib/components/index.js.map +1 -0
- package/lib/components/progress-bar-grid.d.ts +20 -0
- package/lib/components/progress-bar-grid.d.ts.map +1 -0
- package/lib/components/progress-bar-grid.js +44 -0
- package/lib/components/progress-bar-grid.js.map +1 -0
- package/lib/components/progress-bar-grid.test.d.ts +2 -0
- package/lib/components/progress-bar-grid.test.d.ts.map +1 -0
- package/lib/components/progress-bar-grid.test.js +101 -0
- package/lib/components/progress-bar-grid.test.js.map +1 -0
- package/lib/components/progress-bar.d.ts +26 -3
- package/lib/components/progress-bar.d.ts.map +1 -1
- package/lib/components/progress-bar.js +62 -6
- package/lib/components/progress-bar.js.map +1 -1
- package/lib/components/progress-bar.test.d.ts +2 -0
- package/lib/components/progress-bar.test.d.ts.map +1 -0
- package/lib/components/progress-bar.test.js +153 -0
- package/lib/components/progress-bar.test.js.map +1 -0
- package/lib/components/prompt.d.ts +14 -0
- package/lib/components/prompt.d.ts.map +1 -0
- package/lib/components/prompt.js +77 -0
- package/lib/components/prompt.js.map +1 -0
- package/lib/components/renderable.d.ts +42 -0
- package/lib/components/renderable.d.ts.map +1 -0
- package/lib/components/renderable.js +225 -0
- package/lib/components/renderable.js.map +1 -0
- package/lib/components/spinner.d.ts +2 -2
- package/lib/components/spinner.d.ts.map +1 -1
- package/lib/components/spinner.js +3 -1
- package/lib/components/spinner.js.map +1 -1
- package/lib/components/spinner.test.d.ts +2 -0
- package/lib/components/spinner.test.d.ts.map +1 -0
- package/lib/components/spinner.test.js +168 -0
- package/lib/components/spinner.test.js.map +1 -0
- package/lib/components/style.d.ts +16 -0
- package/lib/components/style.d.ts.map +1 -0
- package/lib/components/style.js +72 -0
- package/lib/components/style.js.map +1 -0
- package/lib/components/style.test.d.ts +2 -0
- package/lib/components/style.test.d.ts.map +1 -0
- package/lib/components/style.test.js +135 -0
- package/lib/components/style.test.js.map +1 -0
- package/lib/components/text.d.ts +24 -0
- package/lib/components/text.d.ts.map +1 -0
- package/lib/components/text.js +65 -0
- package/lib/components/text.js.map +1 -0
- package/lib/drawing/boxes.d.ts +33 -0
- package/lib/drawing/boxes.d.ts.map +1 -0
- package/lib/drawing/boxes.js +76 -0
- package/lib/drawing/boxes.js.map +1 -0
- package/lib/index.d.ts +18 -11
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +21 -10
- package/lib/index.js.map +1 -1
- package/lib/index.test.d.ts +2 -0
- package/lib/index.test.d.ts.map +1 -0
- package/lib/index.test.js +80 -0
- package/lib/index.test.js.map +1 -0
- package/lib/layout/flex.d.ts +39 -0
- package/lib/layout/flex.d.ts.map +1 -0
- package/lib/layout/flex.js +300 -0
- package/lib/layout/flex.js.map +1 -0
- package/lib/layout/flex.test.d.ts +2 -0
- package/lib/layout/flex.test.d.ts.map +1 -0
- package/lib/layout/flex.test.js +206 -0
- package/lib/layout/flex.test.js.map +1 -0
- package/lib/layout/grid.d.ts +53 -0
- package/lib/layout/grid.d.ts.map +1 -0
- package/lib/layout/grid.js +421 -0
- package/lib/layout/grid.js.map +1 -0
- package/lib/layout/grid.test.d.ts +2 -0
- package/lib/layout/grid.test.d.ts.map +1 -0
- package/lib/layout/grid.test.js +139 -0
- package/lib/layout/grid.test.js.map +1 -0
- package/lib/native/ansi.d.ts +104 -0
- package/lib/native/ansi.d.ts.map +1 -0
- package/lib/native/ansi.js +120 -0
- package/lib/native/ansi.js.map +1 -0
- package/lib/native/ansi.test.d.ts +2 -0
- package/lib/native/ansi.test.d.ts.map +1 -0
- package/lib/native/ansi.test.js +57 -0
- package/lib/native/ansi.test.js.map +1 -0
- package/lib/native/buffer.d.ts +32 -0
- package/lib/native/buffer.d.ts.map +1 -0
- package/lib/native/buffer.js +49 -0
- package/lib/native/buffer.js.map +1 -0
- package/lib/native/buffer.test.d.ts +2 -0
- package/lib/native/buffer.test.d.ts.map +1 -0
- package/lib/native/buffer.test.js +64 -0
- package/lib/native/buffer.test.js.map +1 -0
- package/lib/native/diff.d.ts +20 -0
- package/lib/native/diff.d.ts.map +1 -0
- package/lib/native/diff.js +33 -0
- package/lib/native/diff.js.map +1 -0
- package/lib/native/diff.test.d.ts +2 -0
- package/lib/native/diff.test.d.ts.map +1 -0
- package/lib/native/diff.test.js +106 -0
- package/lib/native/diff.test.js.map +1 -0
- package/lib/native/region-old.d.ts +117 -0
- package/lib/native/region-old.d.ts.map +1 -0
- package/lib/native/region-old.js +539 -0
- package/lib/native/region-old.js.map +1 -0
- package/lib/native/region-renderer.d.ts +167 -0
- package/lib/native/region-renderer.d.ts.map +1 -0
- package/lib/native/region-renderer.js +1238 -0
- package/lib/native/region-renderer.js.map +1 -0
- package/lib/native/region-simple.d.ts +44 -0
- package/lib/native/region-simple.d.ts.map +1 -0
- package/lib/native/region-simple.js +290 -0
- package/lib/native/region-simple.js.map +1 -0
- package/lib/native/region.d.ts +53 -0
- package/lib/native/region.d.ts.map +1 -0
- package/lib/native/region.js +426 -0
- package/lib/native/region.js.map +1 -0
- package/lib/native/region.test.d.ts +2 -0
- package/lib/native/region.test.d.ts.map +1 -0
- package/lib/native/region.test.js +248 -0
- package/lib/native/region.test.js.map +1 -0
- package/lib/native/throttle.d.ts +29 -0
- package/lib/native/throttle.d.ts.map +1 -0
- package/lib/native/throttle.js +57 -0
- package/lib/native/throttle.js.map +1 -0
- package/lib/native/throttle.test.d.ts +2 -0
- package/lib/native/throttle.test.d.ts.map +1 -0
- package/lib/native/throttle.test.js +86 -0
- package/lib/native/throttle.test.js.map +1 -0
- package/lib/native.d.ts +5 -11
- package/lib/native.d.ts.map +1 -1
- package/lib/native.js +8 -64
- package/lib/native.js.map +1 -1
- package/lib/region.d.ts +48 -5
- package/lib/region.d.ts.map +1 -1
- package/lib/region.js +474 -36
- package/lib/region.js.map +1 -1
- package/lib/region.test.d.ts +2 -0
- package/lib/region.test.d.ts.map +1 -0
- package/lib/region.test.js +227 -0
- package/lib/region.test.js.map +1 -0
- package/lib/region.visual.test.d.ts +2 -0
- package/lib/region.visual.test.d.ts.map +1 -0
- package/lib/region.visual.test.js +55 -0
- package/lib/region.visual.test.js.map +1 -0
- package/lib/test-helpers/capturable-terminal.d.ts +61 -0
- package/lib/test-helpers/capturable-terminal.d.ts.map +1 -0
- package/lib/test-helpers/capturable-terminal.js +113 -0
- package/lib/test-helpers/capturable-terminal.js.map +1 -0
- package/lib/test-helpers/capturable-terminal.test.d.ts +2 -0
- package/lib/test-helpers/capturable-terminal.test.d.ts.map +1 -0
- package/lib/test-helpers/capturable-terminal.test.js +45 -0
- package/lib/test-helpers/capturable-terminal.test.js.map +1 -0
- package/lib/test-helpers/mock-region.d.ts +21 -0
- package/lib/test-helpers/mock-region.d.ts.map +1 -0
- package/lib/test-helpers/mock-region.js +37 -0
- package/lib/test-helpers/mock-region.js.map +1 -0
- package/lib/test-helpers/virtual-terminal-diff-reflow.test.d.ts +2 -0
- package/lib/test-helpers/virtual-terminal-diff-reflow.test.d.ts.map +1 -0
- package/lib/test-helpers/virtual-terminal-diff-reflow.test.js +256 -0
- package/lib/test-helpers/virtual-terminal-diff-reflow.test.js.map +1 -0
- package/lib/test-helpers/virtual-terminal-flex-resize.test.d.ts +2 -0
- package/lib/test-helpers/virtual-terminal-flex-resize.test.d.ts.map +1 -0
- package/lib/test-helpers/virtual-terminal-flex-resize.test.js +438 -0
- package/lib/test-helpers/virtual-terminal-flex-resize.test.js.map +1 -0
- package/lib/test-helpers/virtual-terminal.d.ts +176 -0
- package/lib/test-helpers/virtual-terminal.d.ts.map +1 -0
- package/lib/test-helpers/virtual-terminal.js +492 -0
- package/lib/test-helpers/virtual-terminal.js.map +1 -0
- package/lib/test-helpers/virtual-terminal.test.d.ts +2 -0
- package/lib/test-helpers/virtual-terminal.test.d.ts.map +1 -0
- package/lib/test-helpers/virtual-terminal.test.js +219 -0
- package/lib/test-helpers/virtual-terminal.test.js.map +1 -0
- package/lib/ts/components/spinner.test.d.ts +2 -0
- package/lib/ts/components/spinner.test.d.ts.map +1 -0
- package/lib/ts/components/spinner.test.js +168 -0
- package/lib/ts/components/spinner.test.js.map +1 -0
- package/lib/ts/utils/colors.test.d.ts +2 -0
- package/lib/ts/utils/colors.test.d.ts.map +1 -0
- package/lib/ts/utils/colors.test.js +87 -0
- package/lib/ts/utils/colors.test.js.map +1 -0
- package/lib/types.d.ts +8 -2
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js.map +1 -1
- package/lib/utils/colors-simple.d.ts +51 -0
- package/lib/utils/colors-simple.d.ts.map +1 -0
- package/lib/utils/colors-simple.js +59 -0
- package/lib/utils/colors-simple.js.map +1 -0
- package/lib/utils/colors.d.ts +1 -1
- package/lib/utils/colors.d.ts.map +1 -1
- package/lib/utils/colors.js.map +1 -1
- package/lib/utils/colors.test.d.ts +2 -0
- package/lib/utils/colors.test.d.ts.map +1 -0
- package/lib/utils/colors.test.js +87 -0
- package/lib/utils/colors.test.js.map +1 -0
- package/lib/utils/cursor-position.d.ts +22 -0
- package/lib/utils/cursor-position.d.ts.map +1 -0
- package/lib/utils/cursor-position.js +139 -0
- package/lib/utils/cursor-position.js.map +1 -0
- package/lib/utils/debug-log.d.ts +2 -0
- package/lib/utils/debug-log.d.ts.map +1 -0
- package/lib/utils/debug-log.js +36 -0
- package/lib/utils/debug-log.js.map +1 -0
- package/lib/utils/terminal.d.ts +27 -0
- package/lib/utils/terminal.d.ts.map +1 -0
- package/lib/utils/terminal.js +116 -0
- package/lib/utils/terminal.js.map +1 -0
- package/lib/utils/text.d.ts +21 -0
- package/lib/utils/text.d.ts.map +1 -0
- package/lib/utils/text.js +82 -0
- package/lib/utils/text.js.map +1 -0
- package/lib/utils/wait-for-spacebar.d.ts +10 -0
- package/lib/utils/wait-for-spacebar.d.ts.map +1 -0
- package/lib/utils/wait-for-spacebar.js +71 -0
- package/lib/utils/wait-for-spacebar.js.map +1 -0
- package/package.json +35 -28
- package/.cursor/plan.md +0 -952
- package/TESTING.md +0 -102
- package/build.zig +0 -100
- package/examples/basic-progress.ts +0 -21
- package/examples/multi-lane.ts +0 -29
- package/examples/spinner.ts +0 -20
- package/examples/test-basic.ts +0 -23
- package/src/ts/components/progress-bar.ts +0 -53
- package/src/ts/components/spinner.ts +0 -56
- package/src/ts/index.ts +0 -37
- package/src/ts/native.ts +0 -86
- package/src/ts/region.ts +0 -89
- package/src/ts/types/ffi-napi.d.ts +0 -11
- package/src/ts/types/ref-napi.d.ts +0 -5
- package/src/ts/types.ts +0 -53
- package/src/ts/utils/colors.ts +0 -72
- package/src/zig/ansi.zig +0 -21
- package/src/zig/buffer.zig +0 -37
- package/src/zig/diff.zig +0 -43
- package/src/zig/region.zig +0 -292
- package/src/zig/renderer.zig +0 -92
- package/src/zig/test_ansi.zig +0 -66
- package/src/zig/test_buffer.zig +0 -82
- package/src/zig/test_diff.zig +0 -220
- package/src/zig/test_integration.zig +0 -76
- package/src/zig/test_region.zig +0 -191
- package/src/zig/test_runner.zig +0 -27
- package/src/zig/test_throttle.zig +0 -59
- package/src/zig/throttle.zig +0 -38
- package/tsconfig.json +0 -21
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,111 +1,384 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Linecraft
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
EchoKit provides a friendly TypeScript API while leveraging Zig's speed and efficiency for terminal operations like diffing, ANSI cursor movement, buffering, and throttling.
|
|
6
|
-
|
|
7
|
-
## Features
|
|
8
|
-
|
|
9
|
-
- **High Performance**: Zig backend handles all performance-critical operations
|
|
10
|
-
- **Automatic Batching**: Updates are automatically batched and throttled
|
|
11
|
-
- **Dynamic Regions**: Regions expand automatically as you add lines
|
|
12
|
-
- **Simple API**: Clean, intuitive TypeScript interface
|
|
13
|
-
- **Components**: Built-in progress bars and spinners
|
|
3
|
+
Build terminal UIs with components. Create progress bars, spinners, code error displays, and responsive layouts without the hassle.
|
|
14
4
|
|
|
15
5
|
## Installation
|
|
16
6
|
|
|
17
7
|
```bash
|
|
18
|
-
|
|
8
|
+
npm install linecraft
|
|
9
|
+
# or
|
|
10
|
+
pnpm add linecraft
|
|
19
11
|
```
|
|
20
12
|
|
|
21
13
|
## Quick Start
|
|
22
14
|
|
|
23
|
-
### Basic Progress Bar
|
|
24
|
-
|
|
25
15
|
```typescript
|
|
26
|
-
import {
|
|
16
|
+
import { Region, Styled, Spinner, Section, Grid } from 'linecraft';
|
|
17
|
+
|
|
18
|
+
const r = Region();
|
|
19
|
+
|
|
20
|
+
// Set some content
|
|
21
|
+
r.set(
|
|
22
|
+
Section({ title: 'Hello' },
|
|
23
|
+
Grid({ template: [20, '1*'], columnGap: 2 },
|
|
24
|
+
Styled({ color: 'cyan' }, 'Status:'),
|
|
25
|
+
Styled({ color: 'green' }, 'Ready')
|
|
26
|
+
)
|
|
27
|
+
)
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
// Add a spinner
|
|
31
|
+
r.set(
|
|
32
|
+
Section({ title: 'Loading' },
|
|
33
|
+
Grid({ template: [3, '1*'], columnGap: 1 },
|
|
34
|
+
Spinner({ style: 'classic-dots', color: 'green' }),
|
|
35
|
+
Styled({ color: 'white' }, 'Installing packages...')
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
// Clean up when done
|
|
41
|
+
r.destroy(true);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Performance
|
|
45
|
+
|
|
46
|
+
Linecraft is built for high-performance terminal rendering from Node.js. The renderer includes several optimizations to minimize terminal updates and CPU usage:
|
|
47
|
+
|
|
48
|
+
### Frame Diffing
|
|
49
|
+
Only updates lines that actually changed. Unchanged lines are skipped entirely, reducing terminal writes by up to 90% for static content.
|
|
50
|
+
|
|
51
|
+
### Render Throttling
|
|
52
|
+
Uses high-resolution timing (`process.hrtime.bigint()`) to limit frame rate (default: 30 FPS). Prevents excessive rendering during rapid updates while maintaining smooth animations.
|
|
53
|
+
|
|
54
|
+
### Batched ANSI Operations
|
|
55
|
+
All ANSI escape sequences are batched into a single `stdout.write()` call per frame, minimizing syscalls and improving throughput.
|
|
56
|
+
|
|
57
|
+
### Efficient Cursor Movement
|
|
58
|
+
Optimized ANSI cursor positioning that only moves when necessary. The renderer tracks viewport state to avoid redundant cursor movements.
|
|
59
|
+
|
|
60
|
+
### Viewport Management
|
|
61
|
+
Only renders visible lines within the terminal viewport. Content that extends beyond the viewport is efficiently managed without unnecessary rendering.
|
|
27
62
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
63
|
+
### Auto-Wrap Disabled
|
|
64
|
+
Disables terminal auto-wrap to prevent unwanted line breaks, ensuring precise control over terminal output layout.
|
|
65
|
+
|
|
66
|
+
These optimizations make Linecraft suitable for real-time terminal UIs, progress displays, and animated components without overwhelming the terminal or consuming excessive CPU.
|
|
67
|
+
|
|
68
|
+
## Core API
|
|
69
|
+
|
|
70
|
+
### Region
|
|
71
|
+
|
|
72
|
+
A region is a managed area of your terminal. It handles rendering, resizing, and component updates.
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
const r = Region({
|
|
76
|
+
width: 80, // Optional: auto-detects if not set
|
|
77
|
+
height: 1, // Optional: expands as needed
|
|
78
|
+
debugLog: 'debug.log' // Optional: log rendering for debugging
|
|
32
79
|
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Setting Content
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// Replace all content
|
|
86
|
+
r.set('Hello, world!');
|
|
33
87
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
await new Promise(resolve => setTimeout(resolve, 50));
|
|
37
|
-
}
|
|
88
|
+
// Or use components
|
|
89
|
+
r.set(Styled({ color: 'green' }, 'Success!'));
|
|
38
90
|
|
|
39
|
-
|
|
40
|
-
|
|
91
|
+
// Append content (returns a reference you can use to delete later)
|
|
92
|
+
const ref = r.add('Line 2');
|
|
93
|
+
ref.delete(); // Remove it
|
|
41
94
|
```
|
|
42
95
|
|
|
43
|
-
###
|
|
96
|
+
### Cleanup
|
|
44
97
|
|
|
45
98
|
```typescript
|
|
46
|
-
|
|
99
|
+
r.destroy(true); // Clean up and restore terminal (true = clear first)
|
|
100
|
+
```
|
|
47
101
|
|
|
48
|
-
|
|
49
|
-
const spinner = createSpinner(region, 1);
|
|
102
|
+
## Components
|
|
50
103
|
|
|
51
|
-
|
|
52
|
-
spinner.start();
|
|
104
|
+
### Styled
|
|
53
105
|
|
|
54
|
-
|
|
55
|
-
await doWork();
|
|
106
|
+
Apply colors and styling to text.
|
|
56
107
|
|
|
57
|
-
|
|
58
|
-
|
|
108
|
+
```typescript
|
|
109
|
+
import { Styled } from 'linecraft';
|
|
110
|
+
|
|
111
|
+
r.set(Styled({
|
|
112
|
+
color: 'brightGreen',
|
|
113
|
+
bold: true
|
|
114
|
+
}, 'Bold green text'));
|
|
59
115
|
```
|
|
60
116
|
|
|
61
|
-
|
|
117
|
+
**Options:**
|
|
118
|
+
- `color?: Color` - Text color
|
|
119
|
+
- `backgroundColor?: Color` - Background color
|
|
120
|
+
- `bold?: boolean` - Bold text
|
|
121
|
+
- `italic?: boolean` - Italic text
|
|
122
|
+
- `underline?: boolean` - Underlined text
|
|
123
|
+
- `overflow?: 'none' | 'ellipsis-end' | 'ellipsis-start' | 'ellipsis-middle' | 'wrap'` - Text overflow handling
|
|
124
|
+
- `align?: 'left' | 'right' | 'center'` - Text alignment
|
|
125
|
+
|
|
126
|
+
### Section
|
|
127
|
+
|
|
128
|
+
Wrap content in a bordered box with an optional title.
|
|
129
|
+
|
|
130
|
+

|
|
62
131
|
|
|
63
132
|
```typescript
|
|
64
|
-
import {
|
|
133
|
+
import { Section } from 'linecraft';
|
|
65
134
|
|
|
66
|
-
|
|
135
|
+
r.set(Section(
|
|
136
|
+
{ title: 'My Section' },
|
|
137
|
+
'Content goes here'
|
|
138
|
+
));
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Options:**
|
|
142
|
+
- `title?: string` - Title shown in a tab at the top
|
|
143
|
+
- `titleColor?: Color` - Color of the title
|
|
144
|
+
- `borderColor?: Color` - Color of borders
|
|
145
|
+
- `padding?: number` - Internal padding (default: 1)
|
|
146
|
+
- `left?: boolean` - Show left border (default: true)
|
|
147
|
+
- `right?: boolean` - Show right border (default: true)
|
|
148
|
+
- `top?: boolean` - Show top border (default: true)
|
|
149
|
+
- `bottom?: boolean` - Show bottom border (default: true)
|
|
67
150
|
|
|
68
|
-
|
|
69
|
-
region.setLine(1, { text: 'Status:', style: { bold: true } });
|
|
70
|
-
region.setLine(2, ' ✓ Connected');
|
|
71
|
-
region.setLine(3, ' ⏳ Processing...');
|
|
151
|
+
### CodeDebug
|
|
72
152
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
153
|
+
Display code errors and warnings with line numbers, context, and clickable file paths.
|
|
154
|
+
|
|
155
|
+

|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
import { CodeDebug } from 'linecraft';
|
|
159
|
+
|
|
160
|
+
r.set(CodeDebug({
|
|
161
|
+
startLine: 42,
|
|
162
|
+
startColumn: 10,
|
|
163
|
+
endLine: 42,
|
|
164
|
+
endColumn: 20,
|
|
165
|
+
errorLine: ' const result = fetchData();',
|
|
166
|
+
lineBefore: ' async function load() {',
|
|
167
|
+
lineAfter: ' return process(result);',
|
|
168
|
+
message: 'Type error: fetchData is not defined',
|
|
169
|
+
filePath: 'src/loaders/data.ts',
|
|
170
|
+
fullPath: '/absolute/path/to/src/loaders/data.ts',
|
|
171
|
+
baseDir: process.cwd(),
|
|
172
|
+
type: 'error' // 'error' | 'warning' | 'info'
|
|
173
|
+
}));
|
|
78
174
|
```
|
|
79
175
|
|
|
80
|
-
|
|
176
|
+
**Features:**
|
|
177
|
+
- Automatic line number coloring (adapts to dark/light terminals)
|
|
178
|
+
- Responsive truncation with ellipsis
|
|
179
|
+
- Curved underlines for error ranges
|
|
180
|
+
- Message wrapping
|
|
181
|
+
- Clickable file paths (OSC 8 links)
|
|
182
|
+
- Context lines (before/after)
|
|
81
183
|
|
|
82
|
-
###
|
|
184
|
+
### Spinner
|
|
185
|
+
|
|
186
|
+
Animated spinners for loading states. Includes built-in styles or use custom frames.
|
|
187
|
+
|
|
188
|
+

|
|
83
189
|
|
|
84
|
-
|
|
190
|
+
```typescript
|
|
191
|
+
import { Spinner } from 'linecraft';
|
|
192
|
+
|
|
193
|
+
// Built-in styles
|
|
194
|
+
r.set(Spinner({
|
|
195
|
+
style: 'classic-dots', // or 'bouncing-bar'
|
|
196
|
+
color: 'green',
|
|
197
|
+
interval: 100
|
|
198
|
+
}));
|
|
199
|
+
|
|
200
|
+
// Custom frames
|
|
201
|
+
r.set(Spinner({
|
|
202
|
+
frames: ['⠋', '⠙', '⠹', '⠸'],
|
|
203
|
+
color: 'yellow',
|
|
204
|
+
interval: 80
|
|
205
|
+
}));
|
|
206
|
+
```
|
|
85
207
|
|
|
86
208
|
**Options:**
|
|
87
|
-
- `
|
|
88
|
-
- `
|
|
89
|
-
- `
|
|
90
|
-
- `
|
|
209
|
+
- `style?: 'classic-dots' | 'bouncing-bar'` - Built-in animation style
|
|
210
|
+
- `frames?: string[]` - Custom frames (overrides style if provided)
|
|
211
|
+
- `interval?: number` - Milliseconds between frames (default: 80)
|
|
212
|
+
- `color?: Color` - Spinner color
|
|
213
|
+
- `autoStart?: boolean` - Start automatically (default: true)
|
|
91
214
|
|
|
92
|
-
|
|
215
|
+
Spinners automatically stop when components are replaced or the region is destroyed.
|
|
93
216
|
|
|
94
|
-
|
|
217
|
+
### ProgressBar
|
|
95
218
|
|
|
96
|
-
|
|
219
|
+
Progress bars with customizable colors and styling.
|
|
97
220
|
|
|
98
|
-
|
|
221
|
+

|
|
99
222
|
|
|
100
|
-
|
|
223
|
+
```typescript
|
|
224
|
+
import { progressBar } from 'linecraft';
|
|
225
|
+
|
|
226
|
+
r.set(progressBar({
|
|
227
|
+
current: 75,
|
|
228
|
+
total: 100,
|
|
229
|
+
barColor: 'green',
|
|
230
|
+
bracketColor: 'brightBlack',
|
|
231
|
+
percentColor: 'yellow'
|
|
232
|
+
}));
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
**Options:**
|
|
236
|
+
- `current: number` - Current progress value
|
|
237
|
+
- `total: number` - Total/max value
|
|
238
|
+
- `barColor?: Color` - Color of the filled bar
|
|
239
|
+
- `bracketColor?: Color` - Color of brackets
|
|
240
|
+
- `percentColor?: Color` - Color of percentage text
|
|
101
241
|
|
|
102
|
-
|
|
242
|
+
### Segments
|
|
103
243
|
|
|
104
|
-
|
|
244
|
+
Create segmented displays (like oh-my-zsh style prompts).
|
|
105
245
|
|
|
106
|
-
|
|
246
|
+

|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
import { Segments } from 'linecraft';
|
|
250
|
+
|
|
251
|
+
r.set(Segments({
|
|
252
|
+
segments: [
|
|
253
|
+
{ content: 'user@host', color: 'brightGreen', backgroundColor: 'blue' },
|
|
254
|
+
{ content: '~/projects', color: 'white', backgroundColor: 'brightBlue' },
|
|
255
|
+
{ content: 'main', color: 'black', backgroundColor: 'white' }
|
|
256
|
+
],
|
|
257
|
+
borderStyle: 'cap' // 'cap' | 'brace' | 'round' | 'square' | 'none'
|
|
258
|
+
}));
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**Options:**
|
|
262
|
+
- `segments: Array<{ content: string, color?: Color, backgroundColor?: Color, borderStyle?: BorderStyle }>` - Array of segments
|
|
263
|
+
- `borderStyle?: BorderStyle` - Style for segment borders ('cap', 'brace', 'round', 'square', 'none')
|
|
264
|
+
|
|
265
|
+
### Grid
|
|
266
|
+
|
|
267
|
+
Create responsive grid layouts. Children automatically wrap to new rows when they exceed the number of explicit columns.
|
|
268
|
+
|
|
269
|
+

|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
import { Grid } from 'linecraft';
|
|
273
|
+
|
|
274
|
+
// Basic grid
|
|
275
|
+
r.set(Grid({ template: [20, '1*'], columnGap: 2 },
|
|
276
|
+
Styled({ color: 'cyan' }, 'Label:'),
|
|
277
|
+
Styled({ color: 'yellow' }, 'Value')
|
|
278
|
+
));
|
|
279
|
+
|
|
280
|
+
// Multiple rows (children wrap automatically)
|
|
281
|
+
r.set(Grid({
|
|
282
|
+
columns: [20, 20], // 2 columns per row
|
|
283
|
+
autoColumns: 20, // Size for extra columns
|
|
284
|
+
columnGap: 2,
|
|
285
|
+
rowGap: 1
|
|
286
|
+
},
|
|
287
|
+
Styled({ color: 'cyan' }, 'Left'),
|
|
288
|
+
Styled({ color: 'cyan' }, 'Right'),
|
|
289
|
+
fill({ char: '─', color: 'brightCyan' }),
|
|
290
|
+
fill({ char: '─', color: 'brightCyan' })
|
|
291
|
+
));
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
**Options:**
|
|
295
|
+
- `columns?: GridTemplateEntry[]` - Explicit column definitions (like CSS `grid-template-columns`)
|
|
296
|
+
- `autoColumns?: GridTemplateEntry` - Size for implicitly created columns (like CSS `grid-auto-columns`)
|
|
297
|
+
- `columnGap?: number` - Spaces between columns (default: 0)
|
|
298
|
+
- `rowGap?: number` - Spaces between rows (default: 0)
|
|
299
|
+
- `spaceBetween?: FillChar | FillChar[]` - Characters to draw between columns
|
|
300
|
+
- `justify?: 'start' | 'end' | 'center' | 'space-between'` - Justify content
|
|
301
|
+
|
|
302
|
+
**Template entries:**
|
|
303
|
+
- Fixed width: `20`, `30`
|
|
304
|
+
- Flex units: `'1*'`, `'2*'` (like CSS `1fr`, `2fr`)
|
|
305
|
+
- Minmax: `{ min: 40, width: '2*' }`
|
|
306
|
+
- Auto: `'auto'` (content-based sizing)
|
|
307
|
+
|
|
308
|
+
### Fill
|
|
309
|
+
|
|
310
|
+
Fill available space with a character. Typically used within grids.
|
|
311
|
+
|
|
312
|
+

|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
import { fill } from 'linecraft';
|
|
316
|
+
|
|
317
|
+
r.set(fill({ char: '─', color: 'brightBlack' }));
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Utilities
|
|
321
|
+
|
|
322
|
+
### Prompt
|
|
323
|
+
|
|
324
|
+
Wait for user input before continuing.
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
import { prompt } from 'linecraft';
|
|
328
|
+
|
|
329
|
+
await prompt(r, {
|
|
330
|
+
message: 'continue',
|
|
331
|
+
key: 'spacebar', // 'spacebar' | 'enter' | 'q' | 'any'
|
|
332
|
+
color: 'brightBlack'
|
|
333
|
+
});
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
## Colors
|
|
337
|
+
|
|
338
|
+
Available colors:
|
|
339
|
+
- `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white`
|
|
340
|
+
- `brightBlack`, `brightRed`, `brightGreen`, `brightYellow`, `brightBlue`, `brightMagenta`, `brightCyan`, `brightWhite`
|
|
341
|
+
|
|
342
|
+
## Examples
|
|
343
|
+
|
|
344
|
+
Check out the `examples/` directory:
|
|
345
|
+
|
|
346
|
+
- `progress.ts` - Progress bars (basic and multi-lane)
|
|
347
|
+
- `spinner.ts` - Animated spinners
|
|
348
|
+
- `code-debug.ts` - Code error display
|
|
349
|
+
- `grid-all-features.ts` - Grid layout examples
|
|
350
|
+
- `segments.ts` - Segmented displays
|
|
351
|
+
|
|
352
|
+
Run examples with:
|
|
353
|
+
```bash
|
|
354
|
+
pnpm example <name>
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## API Reference
|
|
358
|
+
|
|
359
|
+
### Region Methods
|
|
360
|
+
|
|
361
|
+
- `set(content)` - Replace all content
|
|
362
|
+
- `add(content)` - Append content, returns `ComponentReference` or `SectionReference`
|
|
363
|
+
- `destroy(clearFirst?)` - Clean up and restore terminal
|
|
364
|
+
- `width` - Current region width (read-only)
|
|
365
|
+
- `height` - Current region height (read-only)
|
|
366
|
+
|
|
367
|
+
### ComponentReference
|
|
368
|
+
|
|
369
|
+
- `delete()` - Remove the component from the region
|
|
370
|
+
|
|
371
|
+
### SectionReference
|
|
372
|
+
|
|
373
|
+
- `update(content)` - Update the section content
|
|
374
|
+
- `delete()` - Remove the section from the region
|
|
375
|
+
|
|
376
|
+
## Contributing
|
|
377
|
+
|
|
378
|
+
Contributions welcome! Please open an issue or PR.
|
|
379
|
+
|
|
380
|
+
**Creating example recordings?** See [docs/creating-recordings.md](docs/creating-recordings.md) for a guide on using vhs to create animated GIFs.
|
|
107
381
|
|
|
108
382
|
## License
|
|
109
383
|
|
|
110
384
|
MIT
|
|
111
|
-
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../../src/api/color.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEtC;;GAEG;AACH,wBAAgB,KAAK,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5D"}
|
package/lib/api/color.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.js","sourceRoot":"","sources":["../../src/api/color.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAElC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C;;GAEG;AACH,MAAM,UAAU,KAAK,CAAC,SAAgB,EAAE,IAAY;IAClD,OAAO,UAAU,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.test.d.ts","sourceRoot":"","sources":["../../src/api/color.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { color } from './color';
|
|
3
|
+
describe('color', () => {
|
|
4
|
+
it('should apply red color', () => {
|
|
5
|
+
const result = color('red', 'Hello');
|
|
6
|
+
expect(result).toContain('\x1b[');
|
|
7
|
+
expect(result).toContain('31'); // Red ANSI code
|
|
8
|
+
expect(result).toContain('Hello');
|
|
9
|
+
});
|
|
10
|
+
it('should apply green color', () => {
|
|
11
|
+
const result = color('green', 'Hello');
|
|
12
|
+
expect(result).toContain('32'); // Green ANSI code
|
|
13
|
+
});
|
|
14
|
+
it('should apply blue color', () => {
|
|
15
|
+
const result = color('blue', 'Hello');
|
|
16
|
+
expect(result).toContain('34'); // Blue ANSI code
|
|
17
|
+
});
|
|
18
|
+
it('should reset color at end', () => {
|
|
19
|
+
const result = color('red', 'Hello');
|
|
20
|
+
expect(result).toMatch(/\x1b\[0m$/); // Reset code at end
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=color.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.test.js","sourceRoot":"","sources":["../../src/api/color.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE;IACrB,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB;QAChD,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,kBAAkB;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,iBAAiB;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,oBAAoB;IAC3D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Flex } from '../layout/flex.js';
|
|
2
|
+
import { Col } from '../components/col.js';
|
|
3
|
+
import type { TerminalRegion } from '../region.js';
|
|
4
|
+
import type { FlexOptions } from '../layout/flex.js';
|
|
5
|
+
import type { ColOptions } from '../components/col.js';
|
|
6
|
+
import type { FlexChild } from '../components/renderable.js';
|
|
7
|
+
export type { FlexChild };
|
|
8
|
+
export type FlexChildWithDescriptors = FlexChild | ColDescriptor | FlexDescriptor;
|
|
9
|
+
/**
|
|
10
|
+
* Descriptor for a flex container (resolved later with region)
|
|
11
|
+
*/
|
|
12
|
+
export interface FlexDescriptor {
|
|
13
|
+
type: 'flex';
|
|
14
|
+
options: FlexOptions;
|
|
15
|
+
children: FlexChild[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Descriptor for a column (resolved later with region)
|
|
19
|
+
*/
|
|
20
|
+
export interface ColDescriptor {
|
|
21
|
+
type: 'col';
|
|
22
|
+
options: ColOptions;
|
|
23
|
+
content: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Create a flex container with children
|
|
27
|
+
* Accepts strings, Renderables, arrays (for functional components), or descriptors
|
|
28
|
+
*/
|
|
29
|
+
export declare function flex(options: FlexOptions, ...children: FlexChildWithDescriptors[]): FlexDescriptor;
|
|
30
|
+
/**
|
|
31
|
+
* Create a column (flex item) with options and content
|
|
32
|
+
*/
|
|
33
|
+
export declare function col(options: ColOptions, content: string): ColDescriptor;
|
|
34
|
+
/**
|
|
35
|
+
* Resolve a flex descriptor tree into actual components
|
|
36
|
+
* Handles strings, arrays (for functional components), and descriptors
|
|
37
|
+
*/
|
|
38
|
+
export declare function resolveFlexTree(region: TerminalRegion, descriptor: FlexDescriptor | ColDescriptor | FlexChild): Flex | Col;
|
|
39
|
+
/**
|
|
40
|
+
* Helper for functional components that return arrays
|
|
41
|
+
* Example:
|
|
42
|
+
* ```ts
|
|
43
|
+
* function myComponent(options, ...children) {
|
|
44
|
+
* return component([
|
|
45
|
+
* 'Label:',
|
|
46
|
+
* ...children
|
|
47
|
+
* ]);
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* Actually, you don't need this helper - just return the array directly!
|
|
52
|
+
* Flex will automatically flatten arrays.
|
|
53
|
+
*/
|
|
54
|
+
export declare function component(children: FlexChild[]): FlexChild[];
|
|
55
|
+
//# sourceMappingURL=flex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flex.d.ts","sourceRoot":"","sources":["../../src/ts/api/flex.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAG7D,YAAY,EAAE,SAAS,EAAE,CAAC;AAG1B,MAAM,MAAM,wBAAwB,GAAG,SAAS,GAAG,aAAa,GAAG,cAAc,CAAC;AAElF;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,SAAS,EAAE,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,KAAK,CAAC;IACZ,OAAO,EAAE,UAAU,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,IAAI,CAClB,OAAO,EAAE,WAAW,EACpB,GAAG,QAAQ,EAAE,wBAAwB,EAAE,GACtC,cAAc,CAMhB;AAED;;GAEG;AACH,wBAAgB,GAAG,CACjB,OAAO,EAAE,UAAU,EACnB,OAAO,EAAE,MAAM,GACd,aAAa,CAMf;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,cAAc,EACtB,UAAU,EAAE,cAAc,GAAG,aAAa,GAAG,SAAS,GACrD,IAAI,GAAG,GAAG,CAwCZ;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAE5D"}
|
package/lib/api/flex.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Function-based API for flex layouts
|
|
2
|
+
import { Flex } from '../layout/flex.js';
|
|
3
|
+
import { Col } from '../components/col.js';
|
|
4
|
+
/**
|
|
5
|
+
* Create a flex container with children
|
|
6
|
+
* Accepts strings, Renderables, arrays (for functional components), or descriptors
|
|
7
|
+
*/
|
|
8
|
+
export function flex(options, ...children) {
|
|
9
|
+
return {
|
|
10
|
+
type: 'flex',
|
|
11
|
+
options,
|
|
12
|
+
children: children,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Create a column (flex item) with options and content
|
|
17
|
+
*/
|
|
18
|
+
export function col(options, content) {
|
|
19
|
+
return {
|
|
20
|
+
type: 'col',
|
|
21
|
+
options,
|
|
22
|
+
content,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Resolve a flex descriptor tree into actual components
|
|
27
|
+
* Handles strings, arrays (for functional components), and descriptors
|
|
28
|
+
*/
|
|
29
|
+
export function resolveFlexTree(region, descriptor) {
|
|
30
|
+
if (typeof descriptor === 'string') {
|
|
31
|
+
// Plain string - wrap in col
|
|
32
|
+
return new Col(region, descriptor, {});
|
|
33
|
+
}
|
|
34
|
+
// Check if it's a descriptor object
|
|
35
|
+
if (typeof descriptor === 'object' && descriptor !== null && 'type' in descriptor) {
|
|
36
|
+
if (descriptor.type === 'col') {
|
|
37
|
+
return new Col(region, descriptor.content, descriptor.options);
|
|
38
|
+
}
|
|
39
|
+
if (descriptor.type === 'flex') {
|
|
40
|
+
const flexComponent = new Flex(region, descriptor.options);
|
|
41
|
+
// Resolve children - Flex.addChild now handles strings, arrays, and Renderables
|
|
42
|
+
for (const child of descriptor.children) {
|
|
43
|
+
if (typeof child === 'string') {
|
|
44
|
+
// Plain string - Flex.addChild will handle it
|
|
45
|
+
flexComponent.addChild(child);
|
|
46
|
+
}
|
|
47
|
+
else if (typeof child === 'object' && child !== null && 'type' in child) {
|
|
48
|
+
// Check if it's a descriptor
|
|
49
|
+
if (child.type === 'col' || child.type === 'flex') {
|
|
50
|
+
const resolved = resolveFlexTree(region, child);
|
|
51
|
+
flexComponent.addChild(resolved);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
// Not a descriptor, pass through as-is
|
|
55
|
+
flexComponent.addChild(child);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// Already a Renderable or array - pass through
|
|
60
|
+
flexComponent.addChild(child);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return flexComponent;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
throw new Error(`Unknown descriptor type: ${descriptor.type || typeof descriptor}`);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Helper for functional components that return arrays
|
|
70
|
+
* Example:
|
|
71
|
+
* ```ts
|
|
72
|
+
* function myComponent(options, ...children) {
|
|
73
|
+
* return component([
|
|
74
|
+
* 'Label:',
|
|
75
|
+
* ...children
|
|
76
|
+
* ]);
|
|
77
|
+
* }
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
80
|
+
* Actually, you don't need this helper - just return the array directly!
|
|
81
|
+
* Flex will automatically flatten arrays.
|
|
82
|
+
*/
|
|
83
|
+
export function component(children) {
|
|
84
|
+
return children;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=flex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flex.js","sourceRoot":"","sources":["../../src/ts/api/flex.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAC;AA8B3C;;;GAGG;AACH,MAAM,UAAU,IAAI,CAClB,OAAoB,EACpB,GAAG,QAAoC;IAEvC,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,OAAO;QACP,QAAQ,EAAE,QAAuB;KAClC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,GAAG,CACjB,OAAmB,EACnB,OAAe;IAEf,OAAO;QACL,IAAI,EAAE,KAAK;QACX,OAAO;QACP,OAAO;KACR,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAsB,EACtB,UAAsD;IAEtD,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QACnC,6BAA6B;QAC7B,OAAO,IAAI,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,oCAAoC;IACpC,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,IAAI,IAAI,MAAM,IAAI,UAAU,EAAE,CAAC;QAClF,IAAI,UAAU,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YAC9B,OAAO,IAAI,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,UAAU,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC/B,MAAM,aAAa,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;YAE3D,gFAAgF;YAChF,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;gBACxC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;oBAC9B,8CAA8C;oBAC9C,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAChC,CAAC;qBAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;oBAC1E,6BAA6B;oBAC7B,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;wBAClD,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,EAAE,KAAkD,CAAC,CAAC;wBAC7F,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;oBACnC,CAAC;yBAAM,CAAC;wBACN,uCAAuC;wBACvC,aAAa,CAAC,QAAQ,CAAC,KAAY,CAAC,CAAC;oBACvC,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,+CAA+C;oBAC/C,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAChC,CAAC;YACH,CAAC;YAED,OAAO,aAAa,CAAC;QACvB,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,4BAA6B,UAAkB,CAAC,IAAI,IAAI,OAAO,UAAU,EAAE,CAAC,CAAC;AAC/F,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,SAAS,CAAC,QAAqB;IAC7C,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|