@navios/commander-tui 1.5.1 → 1.6.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/.turbo/turbo-build.log +13 -13
- package/.turbo/turbo-lint.log +7 -7
- package/.turbo/turbo-test$colon$ci.log +6 -6
- package/.turbo/turbo-test.log +33 -0
- package/CHANGELOG.md +16 -0
- package/dist/base/src/adapters/interface.d.ts +2 -1
- package/dist/base/src/adapters/interface.d.ts.map +1 -1
- package/dist/base/src/keyboard/index.d.ts +1 -1
- package/dist/base/src/keyboard/index.d.ts.map +1 -1
- package/dist/base/src/services/logger.d.ts.map +1 -1
- package/dist/base/src/services/screen.d.ts +5 -1
- package/dist/base/src/services/screen.d.ts.map +1 -1
- package/dist/base/src/services/screen_manager.d.ts +2 -2
- package/dist/base/src/services/screen_manager.d.ts.map +1 -1
- package/dist/base/tsconfig.tsbuildinfo +1 -1
- package/lib/index.cjs +167 -138
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +74 -69
- package/lib/index.d.cts.map +1 -1
- package/lib/index.d.mts +74 -69
- package/lib/index.d.mts.map +1 -1
- package/lib/index.mjs +167 -138
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/adapters/interface.ts +2 -1
- package/src/keyboard/index.ts +1 -1
- package/src/schemas/screen-options.ts +1 -1
- package/src/services/logger.ts +0 -1
- package/src/services/screen.ts +37 -2
- package/src/services/screen_manager.ts +13 -5
package/package.json
CHANGED
package/src/keyboard/index.ts
CHANGED
|
@@ -10,7 +10,7 @@ export const ScreenOptionsSchema = z.object({
|
|
|
10
10
|
/** Whether the screen is hidden */
|
|
11
11
|
hidden: z.boolean().optional().default(false),
|
|
12
12
|
/** Whether the screen is static (ignored in auto-close calculations) */
|
|
13
|
-
static: z.boolean().optional().default(
|
|
13
|
+
static: z.boolean().optional().default(true),
|
|
14
14
|
})
|
|
15
15
|
|
|
16
16
|
export type ScreenOptions = z.infer<typeof ScreenOptionsSchema>
|
package/src/services/logger.ts
CHANGED
package/src/services/screen.ts
CHANGED
|
@@ -43,6 +43,7 @@ export class ScreenInstance extends EventEmitter<ScreenEventMap> {
|
|
|
43
43
|
// Prompt queue system
|
|
44
44
|
private promptQueue: PendingPrompt[] = []
|
|
45
45
|
private activePrompt: PendingPrompt | null = null
|
|
46
|
+
private promptVersion: number = 0
|
|
46
47
|
|
|
47
48
|
constructor(id: string, options: ScreenOptions) {
|
|
48
49
|
super()
|
|
@@ -63,6 +64,14 @@ export class ScreenInstance extends EventEmitter<ScreenEventMap> {
|
|
|
63
64
|
return this.version
|
|
64
65
|
}
|
|
65
66
|
|
|
67
|
+
private incrementPromptVersion(): void {
|
|
68
|
+
this.promptVersion++
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
getPromptVersion(): number {
|
|
72
|
+
return this.promptVersion
|
|
73
|
+
}
|
|
74
|
+
|
|
66
75
|
/**
|
|
67
76
|
* Internal: Set the manager reference
|
|
68
77
|
*/
|
|
@@ -343,10 +352,22 @@ export class ScreenInstance extends EventEmitter<ScreenEventMap> {
|
|
|
343
352
|
}
|
|
344
353
|
|
|
345
354
|
/**
|
|
346
|
-
* Get the currently active prompt (for rendering)
|
|
355
|
+
* Get the currently active prompt (for rendering).
|
|
356
|
+
* Returns a shallow clone to ensure React detects changes when prompt state mutates.
|
|
347
357
|
*/
|
|
348
358
|
getActivePrompt(): PromptData | null {
|
|
349
|
-
|
|
359
|
+
if (!this.activePrompt?.data) return null
|
|
360
|
+
const prompt = this.activePrompt.data
|
|
361
|
+
|
|
362
|
+
// Clone with proper Set handling for multiChoice
|
|
363
|
+
if (prompt.type === 'multiChoice') {
|
|
364
|
+
return {
|
|
365
|
+
...prompt,
|
|
366
|
+
selectedIndices: new Set(prompt.selectedIndices),
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
return { ...prompt }
|
|
350
371
|
}
|
|
351
372
|
|
|
352
373
|
/**
|
|
@@ -372,6 +393,7 @@ export class ScreenInstance extends EventEmitter<ScreenEventMap> {
|
|
|
372
393
|
} else if (prompt.type === 'confirm') {
|
|
373
394
|
;(prompt as ConfirmPromptData).selectedValue = index === 0
|
|
374
395
|
}
|
|
396
|
+
this.incrementPromptVersion()
|
|
375
397
|
this.emit('prompt:updated')
|
|
376
398
|
}
|
|
377
399
|
|
|
@@ -415,6 +437,7 @@ export class ScreenInstance extends EventEmitter<ScreenEventMap> {
|
|
|
415
437
|
const prompt = this.activePrompt.data
|
|
416
438
|
if (prompt.type === 'confirm') {
|
|
417
439
|
;(prompt as ConfirmPromptData).selectedValue = true
|
|
440
|
+
this.incrementPromptVersion()
|
|
418
441
|
this.emit('prompt:updated')
|
|
419
442
|
}
|
|
420
443
|
}
|
|
@@ -424,6 +447,7 @@ export class ScreenInstance extends EventEmitter<ScreenEventMap> {
|
|
|
424
447
|
const prompt = this.activePrompt.data
|
|
425
448
|
if (prompt.type === 'confirm') {
|
|
426
449
|
;(prompt as ConfirmPromptData).selectedValue = false
|
|
450
|
+
this.incrementPromptVersion()
|
|
427
451
|
this.emit('prompt:updated')
|
|
428
452
|
}
|
|
429
453
|
}
|
|
@@ -441,6 +465,7 @@ export class ScreenInstance extends EventEmitter<ScreenEventMap> {
|
|
|
441
465
|
} else if (p.selectedIndices.size < p.maxSelect) {
|
|
442
466
|
p.selectedIndices.add(p.focusedIndex)
|
|
443
467
|
}
|
|
468
|
+
this.incrementPromptVersion()
|
|
444
469
|
this.emit('prompt:updated')
|
|
445
470
|
}
|
|
446
471
|
}
|
|
@@ -457,6 +482,7 @@ export class ScreenInstance extends EventEmitter<ScreenEventMap> {
|
|
|
457
482
|
const choice = prompt.choices[prompt.selectedIndex]
|
|
458
483
|
if (choice?.input) {
|
|
459
484
|
;(prompt as ChoicePromptData).inputMode = true
|
|
485
|
+
this.incrementPromptVersion()
|
|
460
486
|
this.emit('prompt:updated')
|
|
461
487
|
return true
|
|
462
488
|
}
|
|
@@ -476,6 +502,7 @@ export class ScreenInstance extends EventEmitter<ScreenEventMap> {
|
|
|
476
502
|
const prompt = this.activePrompt.data
|
|
477
503
|
if (prompt.type === 'choice' && prompt.inputMode) {
|
|
478
504
|
;(prompt as ChoicePromptData).inputMode = false
|
|
505
|
+
this.incrementPromptVersion()
|
|
479
506
|
this.emit('prompt:updated')
|
|
480
507
|
}
|
|
481
508
|
// Input prompts cannot exit input mode
|
|
@@ -505,9 +532,11 @@ export class ScreenInstance extends EventEmitter<ScreenEventMap> {
|
|
|
505
532
|
const prompt = this.activePrompt.data
|
|
506
533
|
if (prompt.type === 'choice' && prompt.inputMode) {
|
|
507
534
|
;(prompt as ChoicePromptData).inputValue = value
|
|
535
|
+
this.incrementPromptVersion()
|
|
508
536
|
this.emit('prompt:updated')
|
|
509
537
|
} else if (prompt.type === 'input') {
|
|
510
538
|
;(prompt as InputPromptData).value = value
|
|
539
|
+
this.incrementPromptVersion()
|
|
511
540
|
this.emit('prompt:updated')
|
|
512
541
|
}
|
|
513
542
|
}
|
|
@@ -521,9 +550,11 @@ export class ScreenInstance extends EventEmitter<ScreenEventMap> {
|
|
|
521
550
|
const prompt = this.activePrompt.data
|
|
522
551
|
if (prompt.type === 'choice' && prompt.inputMode) {
|
|
523
552
|
;(prompt as ChoicePromptData).inputValue += char
|
|
553
|
+
this.incrementPromptVersion()
|
|
524
554
|
this.emit('prompt:updated')
|
|
525
555
|
} else if (prompt.type === 'input') {
|
|
526
556
|
;(prompt as InputPromptData).value += char
|
|
557
|
+
this.incrementPromptVersion()
|
|
527
558
|
this.emit('prompt:updated')
|
|
528
559
|
}
|
|
529
560
|
}
|
|
@@ -537,9 +568,11 @@ export class ScreenInstance extends EventEmitter<ScreenEventMap> {
|
|
|
537
568
|
const prompt = this.activePrompt.data
|
|
538
569
|
if (prompt.type === 'choice' && prompt.inputMode) {
|
|
539
570
|
;(prompt as ChoicePromptData).inputValue = prompt.inputValue.slice(0, -1)
|
|
571
|
+
this.incrementPromptVersion()
|
|
540
572
|
this.emit('prompt:updated')
|
|
541
573
|
} else if (prompt.type === 'input') {
|
|
542
574
|
;(prompt as InputPromptData).value = prompt.value.slice(0, -1)
|
|
575
|
+
this.incrementPromptVersion()
|
|
543
576
|
this.emit('prompt:updated')
|
|
544
577
|
}
|
|
545
578
|
}
|
|
@@ -606,6 +639,7 @@ export class ScreenInstance extends EventEmitter<ScreenEventMap> {
|
|
|
606
639
|
this.activePrompt = null
|
|
607
640
|
this.activateNextPrompt()
|
|
608
641
|
this.incrementVersion()
|
|
642
|
+
this.incrementPromptVersion()
|
|
609
643
|
this.emit('prompt:resolved')
|
|
610
644
|
}
|
|
611
645
|
|
|
@@ -618,6 +652,7 @@ export class ScreenInstance extends EventEmitter<ScreenEventMap> {
|
|
|
618
652
|
// Notify manager to focus this screen
|
|
619
653
|
this.manager?.onScreenPromptActivated(this)
|
|
620
654
|
this.incrementVersion()
|
|
655
|
+
this.incrementPromptVersion()
|
|
621
656
|
this.emit('prompt:activated')
|
|
622
657
|
}
|
|
623
658
|
}
|
|
@@ -74,6 +74,8 @@ export class ScreenManagerInstance
|
|
|
74
74
|
// Set first visible screen as active by default
|
|
75
75
|
if (!this.activeScreenId && !screen.isHidden()) {
|
|
76
76
|
this.activeScreenId = id
|
|
77
|
+
// Emit activeScreen:changed so subscribers know about the new active screen
|
|
78
|
+
this.emit('activeScreen:changed', id)
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
this.checkAutoClose()
|
|
@@ -125,6 +127,12 @@ export class ScreenManagerInstance
|
|
|
125
127
|
async bind(options?: BindOptions): Promise<void> {
|
|
126
128
|
if (this.mode !== RenderMode.UNBOUND) return
|
|
127
129
|
|
|
130
|
+
// In non-interactive environments (no TTY), stay in UNBOUND mode
|
|
131
|
+
// This allows prompts to return defaults and screens to print on completion
|
|
132
|
+
if (!process.stdout.isTTY) {
|
|
133
|
+
return
|
|
134
|
+
}
|
|
135
|
+
|
|
128
136
|
this.bindOptions = options ?? {}
|
|
129
137
|
|
|
130
138
|
// Resolve theme from options
|
|
@@ -266,15 +274,15 @@ export class ScreenManagerInstance
|
|
|
266
274
|
return this.globalLogLevels ? Array.from(this.globalLogLevels) : null
|
|
267
275
|
}
|
|
268
276
|
|
|
269
|
-
onServiceDestroy(): void {
|
|
270
|
-
this.unbind()
|
|
277
|
+
async onServiceDestroy(): Promise<void> {
|
|
278
|
+
await this.unbind()
|
|
271
279
|
}
|
|
272
280
|
|
|
273
281
|
/**
|
|
274
282
|
* Stop TUI rendering and cleanup
|
|
275
283
|
* Flushes screens to stdout/stderr based on mode
|
|
276
284
|
*/
|
|
277
|
-
unbind(): void {
|
|
285
|
+
async unbind(): Promise<void> {
|
|
278
286
|
if (this.mode === RenderMode.UNBOUND) {
|
|
279
287
|
// Even in unbound mode, flush any remaining screens on destroy
|
|
280
288
|
this.flushRemainingScreens()
|
|
@@ -292,7 +300,7 @@ export class ScreenManagerInstance
|
|
|
292
300
|
// Cleanup TUI if active
|
|
293
301
|
if (previousMode === RenderMode.TUI_ACTIVE) {
|
|
294
302
|
if (this.root) {
|
|
295
|
-
this.root.unmount()
|
|
303
|
+
await this.root.unmount()
|
|
296
304
|
}
|
|
297
305
|
|
|
298
306
|
// Explicitly disable mouse tracking before destroy to prevent escape sequence leakage
|
|
@@ -504,7 +512,7 @@ export class ScreenManagerInstance
|
|
|
504
512
|
// Start auto-close timer (either all non-static screens succeeded, or only static screens exist)
|
|
505
513
|
const delay = typeof autoClose === 'number' ? autoClose : 5000
|
|
506
514
|
this.autoCloseTimer = setTimeout(() => {
|
|
507
|
-
this.unbind()
|
|
515
|
+
void this.unbind()
|
|
508
516
|
}, delay)
|
|
509
517
|
}
|
|
510
518
|
|