@rlabs-inc/tui 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.
- package/README.md +141 -0
- package/index.ts +45 -0
- package/package.json +59 -0
- package/src/api/index.ts +7 -0
- package/src/api/mount.ts +230 -0
- package/src/engine/arrays/core.ts +60 -0
- package/src/engine/arrays/dimensions.ts +68 -0
- package/src/engine/arrays/index.ts +166 -0
- package/src/engine/arrays/interaction.ts +112 -0
- package/src/engine/arrays/layout.ts +175 -0
- package/src/engine/arrays/spacing.ts +100 -0
- package/src/engine/arrays/text.ts +55 -0
- package/src/engine/arrays/visual.ts +140 -0
- package/src/engine/index.ts +25 -0
- package/src/engine/inheritance.ts +138 -0
- package/src/engine/registry.ts +180 -0
- package/src/pipeline/frameBuffer.ts +473 -0
- package/src/pipeline/layout/index.ts +105 -0
- package/src/pipeline/layout/titan-engine.ts +798 -0
- package/src/pipeline/layout/types.ts +194 -0
- package/src/pipeline/layout/utils/hierarchy.ts +202 -0
- package/src/pipeline/layout/utils/math.ts +134 -0
- package/src/pipeline/layout/utils/text-measure.ts +160 -0
- package/src/pipeline/layout.ts +30 -0
- package/src/primitives/box.ts +312 -0
- package/src/primitives/index.ts +12 -0
- package/src/primitives/text.ts +199 -0
- package/src/primitives/types.ts +222 -0
- package/src/primitives/utils.ts +37 -0
- package/src/renderer/ansi.ts +625 -0
- package/src/renderer/buffer.ts +667 -0
- package/src/renderer/index.ts +40 -0
- package/src/renderer/input.ts +518 -0
- package/src/renderer/output.ts +451 -0
- package/src/state/cursor.ts +176 -0
- package/src/state/focus.ts +241 -0
- package/src/state/index.ts +43 -0
- package/src/state/keyboard.ts +771 -0
- package/src/state/mouse.ts +524 -0
- package/src/state/scroll.ts +341 -0
- package/src/state/theme.ts +687 -0
- package/src/types/color.ts +401 -0
- package/src/types/index.ts +316 -0
- package/src/utils/text.ts +471 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TUI Framework - Primitive Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for all component primitives.
|
|
5
|
+
* Props can be static values OR reactive (signals/bindings).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { RGBA, CellAttrs, Dimension } from '../types'
|
|
9
|
+
import type { WritableSignal, Binding, ReadonlyBinding } from '@rlabs-inc/signals'
|
|
10
|
+
import type { Variant } from '../state/theme'
|
|
11
|
+
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// REACTIVE PROP TYPES
|
|
14
|
+
// =============================================================================
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A prop value that can be static or reactive.
|
|
18
|
+
* Components will sync reactive values automatically.
|
|
19
|
+
*/
|
|
20
|
+
export type Reactive<T> = T | WritableSignal<T> | Binding<T> | ReadonlyBinding<T>
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Make specific props reactive while keeping others static.
|
|
24
|
+
*/
|
|
25
|
+
export type WithReactive<T, K extends keyof T> = Omit<T, K> & {
|
|
26
|
+
[P in K]: Reactive<T[P]>
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// =============================================================================
|
|
30
|
+
// COMMON PROPS
|
|
31
|
+
// =============================================================================
|
|
32
|
+
|
|
33
|
+
export interface StyleProps {
|
|
34
|
+
/** Foreground color (text) */
|
|
35
|
+
fg?: Reactive<RGBA | null>
|
|
36
|
+
/** Background color */
|
|
37
|
+
bg?: Reactive<RGBA | null>
|
|
38
|
+
/** Opacity 0-1 */
|
|
39
|
+
opacity?: Reactive<number>
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface BorderProps {
|
|
43
|
+
/** Border style (0=none, 1=single, 2=double, 3=rounded, etc.) */
|
|
44
|
+
border?: Reactive<number>
|
|
45
|
+
/** Border color */
|
|
46
|
+
borderColor?: Reactive<RGBA | null>
|
|
47
|
+
/** Per-side border styles */
|
|
48
|
+
borderTop?: Reactive<number>
|
|
49
|
+
borderRight?: Reactive<number>
|
|
50
|
+
borderBottom?: Reactive<number>
|
|
51
|
+
borderLeft?: Reactive<number>
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface DimensionProps {
|
|
55
|
+
/** Width (0 = auto, '100%' = full parent, '50%' = half parent) */
|
|
56
|
+
width?: Reactive<Dimension>
|
|
57
|
+
/** Height (0 = auto, '100%' = full parent, '50%' = half parent) */
|
|
58
|
+
height?: Reactive<Dimension>
|
|
59
|
+
/** Minimum width */
|
|
60
|
+
minWidth?: Reactive<Dimension>
|
|
61
|
+
/** Maximum width (0 = no max) */
|
|
62
|
+
maxWidth?: Reactive<Dimension>
|
|
63
|
+
/** Minimum height */
|
|
64
|
+
minHeight?: Reactive<Dimension>
|
|
65
|
+
/** Maximum height (0 = no max) */
|
|
66
|
+
maxHeight?: Reactive<Dimension>
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface SpacingProps {
|
|
70
|
+
/** Padding all sides */
|
|
71
|
+
padding?: Reactive<number>
|
|
72
|
+
/** Padding per side */
|
|
73
|
+
paddingTop?: Reactive<number>
|
|
74
|
+
paddingRight?: Reactive<number>
|
|
75
|
+
paddingBottom?: Reactive<number>
|
|
76
|
+
paddingLeft?: Reactive<number>
|
|
77
|
+
/** Margin all sides */
|
|
78
|
+
margin?: Reactive<number>
|
|
79
|
+
/** Margin per side */
|
|
80
|
+
marginTop?: Reactive<number>
|
|
81
|
+
marginRight?: Reactive<number>
|
|
82
|
+
marginBottom?: Reactive<number>
|
|
83
|
+
marginLeft?: Reactive<number>
|
|
84
|
+
/** Gap between children */
|
|
85
|
+
gap?: Reactive<number>
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface LayoutProps {
|
|
89
|
+
/** Flex direction: 'column' | 'row' | 'column-reverse' | 'row-reverse' */
|
|
90
|
+
flexDirection?: Reactive<'column' | 'row' | 'column-reverse' | 'row-reverse'>
|
|
91
|
+
/** Flex wrap: 'nowrap' | 'wrap' | 'wrap-reverse' */
|
|
92
|
+
flexWrap?: Reactive<'nowrap' | 'wrap' | 'wrap-reverse'>
|
|
93
|
+
/** Justify content */
|
|
94
|
+
justifyContent?: Reactive<'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly'>
|
|
95
|
+
/** Align items (container) */
|
|
96
|
+
alignItems?: Reactive<'stretch' | 'flex-start' | 'center' | 'flex-end' | 'baseline'>
|
|
97
|
+
/** Align self (item override) */
|
|
98
|
+
alignSelf?: Reactive<'auto' | 'stretch' | 'flex-start' | 'center' | 'flex-end' | 'baseline'>
|
|
99
|
+
/** Flex grow */
|
|
100
|
+
grow?: Reactive<number>
|
|
101
|
+
/** Flex shrink */
|
|
102
|
+
shrink?: Reactive<number>
|
|
103
|
+
/** Flex basis (initial size before grow/shrink) */
|
|
104
|
+
flexBasis?: Reactive<number>
|
|
105
|
+
/** Overflow: 'visible' | 'hidden' | 'scroll' | 'auto' */
|
|
106
|
+
overflow?: Reactive<'visible' | 'hidden' | 'scroll' | 'auto'>
|
|
107
|
+
/** Z-index for stacking */
|
|
108
|
+
zIndex?: Reactive<number>
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface InteractionProps {
|
|
112
|
+
/** Can this component receive focus */
|
|
113
|
+
focusable?: Reactive<boolean>
|
|
114
|
+
/** Tab order for focus navigation (-1 = not in tab order) */
|
|
115
|
+
tabIndex?: Reactive<number>
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// =============================================================================
|
|
119
|
+
// BOX PROPS
|
|
120
|
+
// =============================================================================
|
|
121
|
+
|
|
122
|
+
export interface BoxProps extends StyleProps, BorderProps, DimensionProps, SpacingProps, LayoutProps, InteractionProps {
|
|
123
|
+
/** Component ID (optional, auto-generated if not provided) */
|
|
124
|
+
id?: string
|
|
125
|
+
/** Is visible */
|
|
126
|
+
visible?: Reactive<boolean>
|
|
127
|
+
/** Children renderer */
|
|
128
|
+
children?: () => void
|
|
129
|
+
/**
|
|
130
|
+
* Style variant - applies theme colors automatically.
|
|
131
|
+
* Variants: 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' | 'ghost' | 'outline'
|
|
132
|
+
*/
|
|
133
|
+
variant?: Variant
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// =============================================================================
|
|
137
|
+
// TEXT PROPS
|
|
138
|
+
// =============================================================================
|
|
139
|
+
|
|
140
|
+
export interface TextProps extends StyleProps, DimensionProps, SpacingProps {
|
|
141
|
+
/** Text content */
|
|
142
|
+
content: Reactive<string>
|
|
143
|
+
/** Text alignment: 'left' | 'center' | 'right' */
|
|
144
|
+
align?: Reactive<'left' | 'center' | 'right'>
|
|
145
|
+
/** Text attributes (bold, italic, etc.) */
|
|
146
|
+
attrs?: Reactive<CellAttrs>
|
|
147
|
+
/** Text wrapping: 'wrap' | 'nowrap' | 'truncate' */
|
|
148
|
+
wrap?: Reactive<'wrap' | 'nowrap' | 'truncate'>
|
|
149
|
+
/** Is visible */
|
|
150
|
+
visible?: Reactive<boolean>
|
|
151
|
+
/**
|
|
152
|
+
* Style variant - applies theme colors automatically.
|
|
153
|
+
* Variants: 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' | 'ghost' | 'outline'
|
|
154
|
+
*/
|
|
155
|
+
variant?: Variant
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// =============================================================================
|
|
159
|
+
// INPUT PROPS
|
|
160
|
+
// =============================================================================
|
|
161
|
+
|
|
162
|
+
export interface InputProps extends StyleProps, BorderProps, DimensionProps, SpacingProps {
|
|
163
|
+
/** Current value (two-way bound) */
|
|
164
|
+
value: WritableSignal<string> | Binding<string>
|
|
165
|
+
/** Placeholder text */
|
|
166
|
+
placeholder?: string
|
|
167
|
+
/** Text attributes */
|
|
168
|
+
attrs?: Reactive<CellAttrs>
|
|
169
|
+
/** Is visible */
|
|
170
|
+
visible?: Reactive<boolean>
|
|
171
|
+
/** Is focused by default */
|
|
172
|
+
autoFocus?: boolean
|
|
173
|
+
/** Called when value changes */
|
|
174
|
+
onChange?: (value: string) => void
|
|
175
|
+
/** Called on Enter key */
|
|
176
|
+
onSubmit?: (value: string) => void
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// =============================================================================
|
|
180
|
+
// SELECT PROPS
|
|
181
|
+
// =============================================================================
|
|
182
|
+
|
|
183
|
+
export interface SelectOption {
|
|
184
|
+
value: string
|
|
185
|
+
label: string
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export interface SelectProps extends StyleProps, BorderProps, DimensionProps {
|
|
189
|
+
/** Selected value (two-way bound) */
|
|
190
|
+
value: WritableSignal<string> | Binding<string>
|
|
191
|
+
/** Available options */
|
|
192
|
+
options: SelectOption[]
|
|
193
|
+
/** Placeholder when nothing selected */
|
|
194
|
+
placeholder?: string
|
|
195
|
+
/** Is visible */
|
|
196
|
+
visible?: Reactive<boolean>
|
|
197
|
+
/** Called when selection changes */
|
|
198
|
+
onChange?: (value: string) => void
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// =============================================================================
|
|
202
|
+
// PROGRESS PROPS
|
|
203
|
+
// =============================================================================
|
|
204
|
+
|
|
205
|
+
export interface ProgressProps extends StyleProps, DimensionProps {
|
|
206
|
+
/** Progress value 0-1 */
|
|
207
|
+
value: Reactive<number>
|
|
208
|
+
/** Show percentage text */
|
|
209
|
+
showPercent?: boolean
|
|
210
|
+
/** Is visible */
|
|
211
|
+
visible?: Reactive<boolean>
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// =============================================================================
|
|
215
|
+
// COMPONENT RETURN TYPE
|
|
216
|
+
// =============================================================================
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Components return a cleanup function.
|
|
220
|
+
* Call it to unmount the component and release its index.
|
|
221
|
+
*/
|
|
222
|
+
export type Cleanup = () => void
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TUI Framework - Primitive Utilities
|
|
3
|
+
*
|
|
4
|
+
* Shared helpers for primitives.
|
|
5
|
+
* Most conversion functions are now inline in each primitive.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { isBinding, type WritableSignal, type Binding } from '@rlabs-inc/signals'
|
|
9
|
+
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// TYPE GUARDS
|
|
12
|
+
// =============================================================================
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Check if a value is a signal (has .value getter/setter)
|
|
16
|
+
*/
|
|
17
|
+
export function isWritableSignal<T>(value: unknown): value is WritableSignal<T> {
|
|
18
|
+
return value !== null && typeof value === 'object' && 'value' in value
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Check if a value is reactive (signal or binding)
|
|
23
|
+
*/
|
|
24
|
+
export function isReactive<T>(value: unknown): value is WritableSignal<T> | Binding<T> {
|
|
25
|
+
return isWritableSignal(value) || isBinding(value)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Unwrap a potentially reactive value to get current value.
|
|
30
|
+
* Handles: signals, bindings, getters, or raw values.
|
|
31
|
+
*/
|
|
32
|
+
export function getValue<T>(prop: T | { value: T } | (() => T) | undefined, defaultVal: T): T {
|
|
33
|
+
if (prop === undefined) return defaultVal
|
|
34
|
+
if (typeof prop === 'function') return (prop as () => T)()
|
|
35
|
+
if (typeof prop === 'object' && prop !== null && 'value' in prop) return (prop as { value: T }).value
|
|
36
|
+
return prop as T
|
|
37
|
+
}
|