@dealdeploy/skl 0.1.7 → 0.1.8

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 (57) hide show
  1. package/.agents/skills/opentui/SKILL.md +198 -0
  2. package/.agents/skills/opentui/references/animation/REFERENCE.md +431 -0
  3. package/.agents/skills/opentui/references/components/REFERENCE.md +143 -0
  4. package/.agents/skills/opentui/references/components/code-diff.md +496 -0
  5. package/.agents/skills/opentui/references/components/containers.md +412 -0
  6. package/.agents/skills/opentui/references/components/inputs.md +531 -0
  7. package/.agents/skills/opentui/references/components/text-display.md +384 -0
  8. package/.agents/skills/opentui/references/core/REFERENCE.md +145 -0
  9. package/.agents/skills/opentui/references/core/api.md +506 -0
  10. package/.agents/skills/opentui/references/core/configuration.md +166 -0
  11. package/.agents/skills/opentui/references/core/gotchas.md +393 -0
  12. package/.agents/skills/opentui/references/core/patterns.md +448 -0
  13. package/.agents/skills/opentui/references/keyboard/REFERENCE.md +511 -0
  14. package/.agents/skills/opentui/references/layout/REFERENCE.md +337 -0
  15. package/.agents/skills/opentui/references/layout/patterns.md +444 -0
  16. package/.agents/skills/opentui/references/react/REFERENCE.md +174 -0
  17. package/.agents/skills/opentui/references/react/api.md +435 -0
  18. package/.agents/skills/opentui/references/react/configuration.md +301 -0
  19. package/.agents/skills/opentui/references/react/gotchas.md +443 -0
  20. package/.agents/skills/opentui/references/react/patterns.md +501 -0
  21. package/.agents/skills/opentui/references/solid/REFERENCE.md +201 -0
  22. package/.agents/skills/opentui/references/solid/api.md +543 -0
  23. package/.agents/skills/opentui/references/solid/configuration.md +315 -0
  24. package/.agents/skills/opentui/references/solid/gotchas.md +415 -0
  25. package/.agents/skills/opentui/references/solid/patterns.md +558 -0
  26. package/.agents/skills/opentui/references/testing/REFERENCE.md +614 -0
  27. package/.claude/settings.local.json +11 -0
  28. package/.claude/skills/opentui/SKILL.md +198 -0
  29. package/.claude/skills/opentui/references/animation/REFERENCE.md +431 -0
  30. package/.claude/skills/opentui/references/components/REFERENCE.md +143 -0
  31. package/.claude/skills/opentui/references/components/code-diff.md +496 -0
  32. package/.claude/skills/opentui/references/components/containers.md +412 -0
  33. package/.claude/skills/opentui/references/components/inputs.md +531 -0
  34. package/.claude/skills/opentui/references/components/text-display.md +384 -0
  35. package/.claude/skills/opentui/references/core/REFERENCE.md +145 -0
  36. package/.claude/skills/opentui/references/core/api.md +506 -0
  37. package/.claude/skills/opentui/references/core/configuration.md +166 -0
  38. package/.claude/skills/opentui/references/core/gotchas.md +393 -0
  39. package/.claude/skills/opentui/references/core/patterns.md +448 -0
  40. package/.claude/skills/opentui/references/keyboard/REFERENCE.md +511 -0
  41. package/.claude/skills/opentui/references/layout/REFERENCE.md +337 -0
  42. package/.claude/skills/opentui/references/layout/patterns.md +444 -0
  43. package/.claude/skills/opentui/references/react/REFERENCE.md +174 -0
  44. package/.claude/skills/opentui/references/react/api.md +435 -0
  45. package/.claude/skills/opentui/references/react/configuration.md +301 -0
  46. package/.claude/skills/opentui/references/react/gotchas.md +443 -0
  47. package/.claude/skills/opentui/references/react/patterns.md +501 -0
  48. package/.claude/skills/opentui/references/solid/REFERENCE.md +201 -0
  49. package/.claude/skills/opentui/references/solid/api.md +543 -0
  50. package/.claude/skills/opentui/references/solid/configuration.md +315 -0
  51. package/.claude/skills/opentui/references/solid/gotchas.md +415 -0
  52. package/.claude/skills/opentui/references/solid/patterns.md +558 -0
  53. package/.claude/skills/opentui/references/testing/REFERENCE.md +614 -0
  54. package/bun.lock +0 -1
  55. package/index.ts +163 -38
  56. package/package.json +1 -1
  57. package/update.ts +87 -0
@@ -0,0 +1,448 @@
1
+ # Core Patterns
2
+
3
+ ## Composition Patterns
4
+
5
+ ### Imperative Composition
6
+
7
+ Create renderables and compose with `.add()`:
8
+
9
+ ```typescript
10
+ import { createCliRenderer, BoxRenderable, TextRenderable } from "@opentui/core"
11
+
12
+ const renderer = await createCliRenderer()
13
+
14
+ // Create parent
15
+ const container = new BoxRenderable(renderer, {
16
+ id: "container",
17
+ flexDirection: "column",
18
+ padding: 1,
19
+ })
20
+
21
+ // Create children
22
+ const header = new TextRenderable(renderer, {
23
+ id: "header",
24
+ content: "Header",
25
+ fg: "#00FF00",
26
+ })
27
+
28
+ const body = new TextRenderable(renderer, {
29
+ id: "body",
30
+ content: "Body content",
31
+ })
32
+
33
+ // Compose tree
34
+ container.add(header)
35
+ container.add(body)
36
+ renderer.root.add(container)
37
+ ```
38
+
39
+ ### Declarative Composition (Constructs)
40
+
41
+ Use VNode functions for cleaner composition:
42
+
43
+ ```typescript
44
+ import { createCliRenderer, Box, Text, Input, delegate } from "@opentui/core"
45
+
46
+ const renderer = await createCliRenderer()
47
+
48
+ // Compose as function calls
49
+ const ui = Box(
50
+ { flexDirection: "column", padding: 1 },
51
+ Text({ content: "Header", fg: "#00FF00" }),
52
+ Box(
53
+ { flexDirection: "row", gap: 2 },
54
+ Text({ content: "Name:" }),
55
+ Input({ id: "name", placeholder: "Enter name..." }),
56
+ ),
57
+ )
58
+
59
+ renderer.root.add(ui)
60
+ ```
61
+
62
+ ### Reusable Components
63
+
64
+ Create factory functions for reusable UI pieces:
65
+
66
+ ```typescript
67
+ // Imperative factory
68
+ function createLabeledInput(
69
+ renderer: RenderContext,
70
+ props: { id: string; label: string; placeholder: string }
71
+ ) {
72
+ const container = new BoxRenderable(renderer, {
73
+ id: `${props.id}-container`,
74
+ flexDirection: "row",
75
+ gap: 1,
76
+ })
77
+
78
+ container.add(new TextRenderable(renderer, {
79
+ id: `${props.id}-label`,
80
+ content: props.label,
81
+ }))
82
+
83
+ container.add(new InputRenderable(renderer, {
84
+ id: `${props.id}-input`,
85
+ placeholder: props.placeholder,
86
+ width: 20,
87
+ }))
88
+
89
+ return container
90
+ }
91
+
92
+ // Declarative factory
93
+ function LabeledInput(props: { id: string; label: string; placeholder: string }) {
94
+ return delegate(
95
+ { focus: `${props.id}-input` },
96
+ Box(
97
+ { flexDirection: "row", gap: 1 },
98
+ Text({ content: props.label }),
99
+ Input({
100
+ id: `${props.id}-input`,
101
+ placeholder: props.placeholder,
102
+ width: 20,
103
+ }),
104
+ ),
105
+ )
106
+ }
107
+ ```
108
+
109
+ ### Focus Delegation
110
+
111
+ Route focus calls to nested elements:
112
+
113
+ ```typescript
114
+ import { delegate, Box, Input, Text } from "@opentui/core"
115
+
116
+ const form = delegate(
117
+ {
118
+ focus: "email-input", // Route .focus() to this child
119
+ blur: "email-input", // Route .blur() to this child
120
+ },
121
+ Box(
122
+ { border: true, padding: 1 },
123
+ Text({ content: "Email:" }),
124
+ Input({ id: "email-input", placeholder: "you@example.com" }),
125
+ ),
126
+ )
127
+
128
+ // This focuses the input inside, not the box
129
+ form.focus()
130
+ ```
131
+
132
+ ## Event Handling
133
+
134
+ ### Keyboard Events
135
+
136
+ ```typescript
137
+ const renderer = await createCliRenderer()
138
+
139
+ // Global keyboard handler
140
+ renderer.keyInput.on("keypress", (key) => {
141
+ if (key.name === "escape") {
142
+ renderer.destroy()
143
+ process.exit(0)
144
+ }
145
+
146
+ if (key.ctrl && key.name === "c") {
147
+ // Ctrl+C handling (if exitOnCtrlC is false)
148
+ }
149
+
150
+ if (key.name === "tab") {
151
+ // Tab navigation
152
+ focusNext()
153
+ }
154
+ })
155
+
156
+ // Paste events
157
+ renderer.keyInput.on("paste", (text) => {
158
+ currentInput?.setValue(currentInput.value + text)
159
+ })
160
+ ```
161
+
162
+ ### Component Events
163
+
164
+ ```typescript
165
+ import { InputRenderable, InputRenderableEvents } from "@opentui/core"
166
+
167
+ const input = new InputRenderable(renderer, {
168
+ id: "search",
169
+ placeholder: "Search...",
170
+ })
171
+
172
+ input.on(InputRenderableEvents.CHANGE, (value) => {
173
+ performSearch(value)
174
+ })
175
+
176
+ // Select events
177
+ const select = new SelectRenderable(renderer, {
178
+ id: "menu",
179
+ options: [...],
180
+ })
181
+
182
+ select.on(SelectRenderableEvents.ITEM_SELECTED, (index, option) => {
183
+ handleSelection(option)
184
+ })
185
+
186
+ select.on(SelectRenderableEvents.SELECTION_CHANGED, (index, option) => {
187
+ showPreview(option)
188
+ })
189
+ ```
190
+
191
+ ### Mouse Events
192
+
193
+ ```typescript
194
+ const button = new BoxRenderable(renderer, {
195
+ id: "button",
196
+ border: true,
197
+ onMouseDown: (event) => {
198
+ button.setBackgroundColor("#444444")
199
+ },
200
+ onMouseUp: (event) => {
201
+ button.setBackgroundColor("#222222")
202
+ handleClick()
203
+ },
204
+ onMouseMove: (event) => {
205
+ // Hover effect
206
+ },
207
+ })
208
+ ```
209
+
210
+ ## State Management
211
+
212
+ ### Local State
213
+
214
+ Manage state in closures or objects:
215
+
216
+ ```typescript
217
+ // Closure-based state
218
+ function createCounter(renderer: RenderContext) {
219
+ let count = 0
220
+
221
+ const display = new TextRenderable(renderer, {
222
+ id: "count",
223
+ content: `Count: ${count}`,
224
+ })
225
+
226
+ const increment = () => {
227
+ count++
228
+ display.setContent(`Count: ${count}`)
229
+ }
230
+
231
+ return { display, increment }
232
+ }
233
+
234
+ // Class-based state
235
+ class CounterWidget {
236
+ private count = 0
237
+ private display: TextRenderable
238
+
239
+ constructor(renderer: RenderContext) {
240
+ this.display = new TextRenderable(renderer, {
241
+ id: "count",
242
+ content: this.formatCount(),
243
+ })
244
+ }
245
+
246
+ private formatCount() {
247
+ return `Count: ${this.count}`
248
+ }
249
+
250
+ increment() {
251
+ this.count++
252
+ this.display.setContent(this.formatCount())
253
+ }
254
+
255
+ getRenderable() {
256
+ return this.display
257
+ }
258
+ }
259
+ ```
260
+
261
+ ### Focus Management
262
+
263
+ Track and manage focus across components:
264
+
265
+ ```typescript
266
+ class FocusManager {
267
+ private focusables: Renderable[] = []
268
+ private currentIndex = 0
269
+
270
+ register(renderable: Renderable) {
271
+ this.focusables.push(renderable)
272
+ }
273
+
274
+ focusNext() {
275
+ this.focusables[this.currentIndex]?.blur()
276
+ this.currentIndex = (this.currentIndex + 1) % this.focusables.length
277
+ this.focusables[this.currentIndex]?.focus()
278
+ }
279
+
280
+ focusPrevious() {
281
+ this.focusables[this.currentIndex]?.blur()
282
+ this.currentIndex = (this.currentIndex - 1 + this.focusables.length) % this.focusables.length
283
+ this.focusables[this.currentIndex]?.focus()
284
+ }
285
+ }
286
+
287
+ // Usage
288
+ const focusManager = new FocusManager()
289
+ focusManager.register(input1)
290
+ focusManager.register(input2)
291
+ focusManager.register(select1)
292
+
293
+ renderer.keyInput.on("keypress", (key) => {
294
+ if (key.name === "tab") {
295
+ key.shift ? focusManager.focusPrevious() : focusManager.focusNext()
296
+ }
297
+ })
298
+ ```
299
+
300
+ ## Lifecycle Patterns
301
+
302
+ ### Cleanup
303
+
304
+ Always clean up resources:
305
+
306
+ ```typescript
307
+ const renderer = await createCliRenderer()
308
+
309
+ // Track intervals/timeouts
310
+ const intervals: Timer[] = []
311
+
312
+ intervals.push(setInterval(() => {
313
+ updateClock()
314
+ }, 1000))
315
+
316
+ // Cleanup on exit
317
+ process.on("SIGINT", () => {
318
+ intervals.forEach(clearInterval)
319
+ renderer.destroy()
320
+ process.exit(0)
321
+ })
322
+
323
+ // Or use onDestroy callback
324
+ const renderer = await createCliRenderer({
325
+ onDestroy: () => {
326
+ intervals.forEach(clearInterval)
327
+ },
328
+ })
329
+ ```
330
+
331
+ ### Dynamic Updates
332
+
333
+ Update UI based on external data:
334
+
335
+ ```typescript
336
+ async function createDashboard(renderer: RenderContext) {
337
+ const statsText = new TextRenderable(renderer, {
338
+ id: "stats",
339
+ content: "Loading...",
340
+ })
341
+
342
+ // Poll for updates
343
+ const updateStats = async () => {
344
+ const data = await fetchStats()
345
+ statsText.setContent(`CPU: ${data.cpu}% | Memory: ${data.memory}%`)
346
+ }
347
+
348
+ // Initial load
349
+ await updateStats()
350
+
351
+ // Periodic updates
352
+ setInterval(updateStats, 5000)
353
+
354
+ return statsText
355
+ }
356
+ ```
357
+
358
+ ## Layout Patterns
359
+
360
+ ### Responsive Layout
361
+
362
+ Adapt to terminal size:
363
+
364
+ ```typescript
365
+ const renderer = await createCliRenderer()
366
+
367
+ const mainPanel = new BoxRenderable(renderer, {
368
+ id: "main",
369
+ width: "100%",
370
+ height: "100%",
371
+ flexDirection: renderer.width > 80 ? "row" : "column",
372
+ })
373
+
374
+ // Listen for resize
375
+ process.stdout.on("resize", () => {
376
+ mainPanel.setFlexDirection(renderer.width > 80 ? "row" : "column")
377
+ })
378
+ ```
379
+
380
+ ### Split Panels
381
+
382
+ ```typescript
383
+ function createSplitView(renderer: RenderContext, ratio = 0.3) {
384
+ const container = new BoxRenderable(renderer, {
385
+ id: "split",
386
+ flexDirection: "row",
387
+ width: "100%",
388
+ height: "100%",
389
+ })
390
+
391
+ const left = new BoxRenderable(renderer, {
392
+ id: "left",
393
+ width: `${ratio * 100}%`,
394
+ border: true,
395
+ })
396
+
397
+ const right = new BoxRenderable(renderer, {
398
+ id: "right",
399
+ flexGrow: 1,
400
+ border: true,
401
+ })
402
+
403
+ container.add(left)
404
+ container.add(right)
405
+
406
+ return { container, left, right }
407
+ }
408
+ ```
409
+
410
+ ## Debugging Patterns
411
+
412
+ ### Console Overlay
413
+
414
+ Use the built-in console for debugging:
415
+
416
+ ```typescript
417
+ const renderer = await createCliRenderer({
418
+ consoleOptions: {
419
+ startInDebugMode: true,
420
+ },
421
+ })
422
+
423
+ // Show console
424
+ renderer.console.show()
425
+
426
+ // All console methods work
427
+ console.log("Debug info")
428
+ console.warn("Warning")
429
+ console.error("Error")
430
+
431
+ // Toggle with keyboard
432
+ renderer.keyInput.on("keypress", (key) => {
433
+ if (key.name === "f12") {
434
+ renderer.console.toggle()
435
+ }
436
+ })
437
+ ```
438
+
439
+ ### State Inspection
440
+
441
+ ```typescript
442
+ function debugState(label: string, state: unknown) {
443
+ console.log(`[${label}]`, JSON.stringify(state, null, 2))
444
+ }
445
+
446
+ // In your update logic
447
+ debugState("form", { name: nameInput.value, email: emailInput.value })
448
+ ```