forked from anomalyco/opentui
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnested-input-tree.ts
More file actions
136 lines (114 loc) · 3.58 KB
/
nested-input-tree.ts
File metadata and controls
136 lines (114 loc) · 3.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import { CliRenderer, createCliRenderer, BoxRenderable, InputRenderable, TextRenderable } from ".."
import { setupCommonDemoKeys } from "./lib/standalone-keys"
const MAX_DEPTH = 3
const MIN_INPUTS = 1
const MAX_INPUTS = 2
const MIN_SUBLEVELS = 2
const MAX_SUBLEVELS = 3
let renderer: CliRenderer | null = null
let parentContainer: BoxRenderable | null = null
let footer: TextRenderable | null = null
let footerBox: BoxRenderable | null = null
const PLACEHOLDER_TEMPLATES = [
"Enter your name",
"Type your email",
"Write a comment",
"Your favorite color",
"Add a note here",
]
function getLevelColor(depth: number) {
const LEVEL_COLORS = ["#3b82f6", "#059669", "#f59e0b", "#e11d48"]
return LEVEL_COLORS[(depth - 1) % LEVEL_COLORS.length]
}
function createNestedBox(depth: number, maxDepth: number): BoxRenderable {
if (!renderer) throw new Error("No renderer")
const levelColor = getLevelColor(depth)
const box = new BoxRenderable(renderer, {
zIndex: 0,
width: "auto",
height: "auto",
borderStyle: "single",
borderColor: levelColor,
focusedBorderColor: levelColor,
title: `Level ${depth}`,
titleAlignment: "center",
flexGrow: 1,
backgroundColor: "transparent",
border: true,
})
const inputCount = depth === 1 ? MAX_INPUTS : Math.floor(Math.random() * (MAX_INPUTS - MIN_INPUTS + 1)) + MIN_INPUTS
const sublevelCount =
depth < maxDepth ? Math.floor(Math.random() * (MAX_SUBLEVELS - MIN_SUBLEVELS + 1)) + MIN_SUBLEVELS : 0
const elements = Array(inputCount).fill("input").concat(Array(sublevelCount).fill("sublevel"))
for (let i = elements.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1))
;[elements[i], elements[j]] = [elements[j], elements[i]]
}
elements.forEach((type, idx) => {
if (type === "input") {
if (!renderer) throw new Error("No renderer")
const placeholder = PLACEHOLDER_TEMPLATES[idx % PLACEHOLDER_TEMPLATES.length]
box.add(
new InputRenderable(renderer, {
placeholder: `${placeholder} (level ${depth})`,
width: "auto",
height: 1,
backgroundColor: "#1e293b",
focusedBackgroundColor: "#334155",
textColor: levelColor,
focusedTextColor: "#ffffff",
placeholderColor: "#64748b",
cursorColor: levelColor,
maxLength: 100,
}),
)
} else if (type === "sublevel") {
box.add(createNestedBox(depth + 1, maxDepth))
}
})
return box
}
export function run(rendererInstance: CliRenderer): void {
renderer = rendererInstance
renderer.setBackgroundColor("#001122")
parentContainer = createNestedBox(1, MAX_DEPTH)
renderer.root.add(parentContainer)
footerBox = new BoxRenderable(renderer, {
width: "auto",
height: 3,
backgroundColor: "#1e40af",
borderStyle: "single",
borderColor: "#1d4ed8",
border: true,
})
footer = new TextRenderable(renderer, {
id: "footer",
content: "TAB: focus next | SHIFT+TAB: focus prev | ESC: quit",
fg: "#dbeafe",
bg: "transparent",
zIndex: 1,
flexGrow: 1,
flexShrink: 1,
})
footerBox.add(footer)
renderer.root.add(footerBox)
}
export function destroy(rendererInstance: CliRenderer): void {
if (parentContainer) {
parentContainer.destroyRecursively()
}
if (footerBox) footerBox.destroyRecursively()
parentContainer = null
footer = null
footerBox = null
renderer = null
}
if (import.meta.main) {
const renderer = await createCliRenderer({
exitOnCtrlC: true,
targetFps: 30,
})
run(renderer)
setupCommonDemoKeys(renderer)
renderer.start()
}