Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,44 @@ new DeployCommand('app:deploy', [
]);
```

## Theme Configuration

TART ships with a default theme, but you can customize colors, highlight behavior, and layout width. The `max_line_width` setting is especially useful for matching the width of your terminal and for how blocks, progress bars, and banners wrap long text.

### Theme Options

- `class` - The theme class to use (defaults to `IGC\Tart\Themes\Theme`)
- `color` - Primary color used by blocks and accents (default: `blue`)
- `text_color` - Default text color inside themed blocks (default: `white`)
- `highlight_color` - Accent/highlight color (default: `yellow`)
- `max_line_width` - Maximum line width for formatting (default: `72`)
- `colors` - Palette used for random or multi-color effects (default: `['red', 'green', 'yellow', 'cyan', 'white']`)

### Example: Custom Theme via Config

```php
new DeployCommand('app:deploy', [
'theme' => [
'class' => \IGC\Tart\Themes\Theme::class,
'color' => 'magenta',
'text_color' => 'white',
'highlight_color' => 'yellow',
'max_line_width' => 100,
'colors' => ['magenta', 'cyan', 'white'],
],
]);
```

### Example: Fluent Theme Updates

```php
$theme = \IGC\Tart\Themes\Theme::make('green')
->withTextColor('white')
->withHighlightColor('yellow')
->withMaxWidth(90)
->withColors(['green', 'cyan', 'white']);
```

### Laravel Auto-Discovery & Demo Commands

Laravel 9+ automatically discovers the `IGC\Tart\Laravel\TartServiceProvider`, which registers several Artisan demo commands. After installing the package you can immediately preview different aspects of the styling toolkit:
Expand Down Expand Up @@ -255,6 +293,31 @@ $this->stat('Completed in 2.5s'); // Stat block
$this->footer('Process', 'Time: 2.5s'); // Footer
```

## Recommended API Usage

TART supports both fluent APIs and the original, traditional methods. The fluent API is the preferred approach going forward because it is more expressive and easier to read. The traditional methods remain supported for backward compatibility.

**Preferred (fluent)**

```php
$this->logo()
->text('MY APP')
->boxed()
->color('cyan')
->render();

$this->success('Deploy complete!');
```

**Legacy (still supported)**

```php
$this->displayTextLogo('MY APP', 'box', ['text_color' => 'cyan']);
$this->success('Deploy complete!');
```

If you're migrating existing code, you can adopt fluent methods incrementally while keeping the original APIs for older commands.

### Logo Creation 🎨

```php
Expand Down
41 changes: 41 additions & 0 deletions docs/feature-todo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# TUI Feature Research TODOs

## Interactive Menus & Navigable Lists
- [x] Prototype a raw-mode input loop that detects arrow key escape sequences (ESC [ A/B/C/D) and Enter to select the highlighted item.
- [x] Implement a menu renderer that highlights the focused item (e.g., inverse colors or a leading `>` marker) and supports redrawing on selection changes.
- [x] Add cursor hide/show and safe terminal cleanup to avoid leaving the cursor hidden after menu exit.
- [x] Evaluate redraw strategies: full-screen clear (`\033[H\033[2J`) vs. partial updates with cursor movement to reduce flicker.

## Multiple-Choice Inputs (Checkbox/Radio)
- [x] Extend the menu loop to toggle checkboxes via Space/Enter and render markers like `[x]` / `[ ]`.
- [x] Implement radio-style selection (single choice) where selecting one item clears the previous choice.
- [x] Store selection state in an array of booleans (checkbox) or a single index (radio) and expose selected values.

## Text Input Fields
- [ ] Decide between readline-based prompts (simple) vs. raw-mode character capture for embedded inputs.
- [ ] Prototype raw-mode text input with Backspace handling (support ASCII 127 and 8) and optional masking for passwords.
- [ ] Ensure terminal settings are restored after input (save `stty -g`, restore on exit).

## Keyboard Input Handling
- [x] Build a small key parser for escape sequences (arrows, escape, enter) with optional timeout logic for lone ESC.
- [x] Add `stream_select()` support to allow non-blocking reads for animations/spinners during input loops.
- [ ] Document key mappings and supported terminals (ANSI/VT100 assumptions).

## Cursor & Screen Control
- [x] Create helpers for cursor movement (`ESC[<row>;<col>H`, `ESC[<n>A/B/C/D`), line clearing (`ESC[K`), and full-screen clear.
- [x] Add cursor hide/show helpers (`ESC[?25l` / `ESC[?25h`) and use them during redraws.
- [ ] Explore buffer-based redraws (compose full screen in a string, output once) to minimize flicker.

## Text Formatting Beyond Colors
- [x] Add support for bold/underline/reverse video SGR codes and a reset helper (`ESC[0m`).
- [ ] Consider 256-color or truecolor extensions for richer themes where terminals support it.

## Library Ecosystem Evaluation
- [ ] Review php-school/cli-menu for menu and checkbox patterns that can inform API design.
- [ ] Evaluate php-tui/php-tui terminal/event handling patterns for raw mode and event parsing.
- [ ] Decide whether to depend on external libraries or keep a minimal internal implementation.

## Integration & UX
- [x] Define a public API for menus, checkbox lists, and text inputs that fits TART’s fluent style.
- [x] Add safeguards to prevent leaving the terminal in raw mode after exceptions (try/finally wrapper).
- [ ] Provide Laravel/Symfony usage examples once core components are stable.
25 changes: 24 additions & 1 deletion docs/guides/QUICK-REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,30 @@ $email = $this->prompt('Email?', null, function($value) {
$password = $this->password('Enter password');
```

## 🧭 Interactive Menus (NEW!)

```php
// Single-select menu
$choice = $this->menu('Pick a deployment target', [
'Staging',
'Production',
]);

// Checkbox menu (multi-select)
$selected = $this->checkboxMenu('Select features', [
'Spinners',
'Progress bars',
'Tables',
]);

// Radio menu (single-select)
$theme = $this->radioMenu('Choose a theme', [
'Default',
'Success',
'Error',
]);
```

## 📝 Lists (NEW!)

```php
Expand Down Expand Up @@ -304,4 +328,3 @@ public function handle()
---

**Quick Start:** Extend `StyledCommand` and use any method above!

46 changes: 46 additions & 0 deletions src/Concerns/HasInteractiveMenus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace IGC\Tart\Concerns;

use IGC\Tart\Support\InteractiveMenu;

trait HasInteractiveMenus
{
/**
* Present a single-select menu and return the chosen value.
*
* @param array<int|string, string> $items
*/
public function menu(string $title, array $items, int $defaultIndex = 0): string
{
$menu = new InteractiveMenu($this->getOutput());

return $menu->select($title, $items, $defaultIndex);
}

/**
* Present a multi-select checkbox menu and return the chosen values.
*
* @param array<int|string, string> $items
* @param array<int|string> $defaults
* @return array<int|string>
*/
public function checkboxMenu(string $title, array $items, array $defaults = []): array
{
$menu = new InteractiveMenu($this->getOutput());

return $menu->checkbox($title, $items, $defaults);
}

/**
* Present a single-select radio menu and return the chosen value.
*
* @param array<int|string, string> $items
*/
public function radioMenu(string $title, array $items, int $defaultIndex = 0): string
{
$menu = new InteractiveMenu($this->getOutput());

return $menu->radio($title, $items, $defaultIndex);
}
}
2 changes: 2 additions & 0 deletions src/Laravel/StyledCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use IGC\Tart\Concerns\HasColoredOutput;
use IGC\Tart\Concerns\HasEnhancedInput;
use IGC\Tart\Concerns\HasInteractivity;
use IGC\Tart\Concerns\HasInteractiveMenus;
use IGC\Tart\Concerns\HasLineBuilding;
use IGC\Tart\Concerns\HasLists;
use IGC\Tart\Concerns\HasProgressBars;
Expand All @@ -27,6 +28,7 @@ abstract class StyledCommand extends Command implements StyledCommandInterface
use HasBlocks;
use HasLineBuilding;
use HasInteractivity;
use HasInteractiveMenus;
use HasEnhancedInput;
use HasLists;
use HasTables;
Expand Down
Loading
Loading