Commit Graph
28 Commits
Author SHA1 Message Date
phranck 750561ad76 feat: Add theme background color to Example App
ContentView now fills the entire terminal with the current theme's
background color, providing a consistent look when switching themes.
2026-01-28 21:10:33 +01:00
phranck 3470cb8e24 refactor: Use theme colors throughout UI components
- Update all 4 phosphor themes (Green, Amber, White, Red) to use neutral
  dark background (#1E1E1E) matching Spotnik reference
- Simplify theme names (remove 'Phosphor' suffix)
- Menu: Use theme.foreground for items, theme.accent for selection
- Button: Use theme colors for default focused style and focus indicator
- Panel/Card: Use theme.border as default border color
- BorderModifier: Use theme.border as default

All 189 tests passing.
2026-01-28 21:08:25 +01:00
phranck 1d547a4f19 refactor: Simplify themes - Green as default, remove Light/Dark
- Remove DefaultTheme, DarkTheme, LightTheme
- GreenPhosphorTheme is now the default theme
- Theme cycling order: Green → Amber → White → Red → NCurses
- .default now maps to GreenPhosphorTheme
2026-01-28 20:55:46 +01:00
phranck 201d920bdc fix: Apply ThemeManager's current theme to environment during render
The render() method was creating a new EnvironmentValues with the default
theme, overwriting any theme changes made by ThemeManager. Now the current
theme is explicitly set from themeManager.currentTheme.
2026-01-28 20:51:55 +01:00
phranck f00d919c1f feat: Use theme colors in StatusBar and Example App
- StatusBar now uses theme colors by default (statusBarHighlight, statusBarForeground)
- Example App MainMenuPage uses theme colors (accent, border, foreground*)
- Example App HeaderView uses theme colors
- Theme switching ('t' key) now shows visible changes
2026-01-28 20:50:28 +01:00
phranck 544152de02 refactor: Remove ThemeManager singleton, add Environment-based access
- ThemeManager is no longer a singleton
- Access via Environment: @Environment(\.themeManager)
- Type-safe setTheme() API: themeManager.setTheme(.amber)
- ThemeManager injected by AppRunner into environment
- Custom themes supported via init(themes:)
2026-01-28 20:48:00 +01:00
phranck 1d3c9b2a62 feat: Add QuitBehavior and ThemeManager
QuitBehavior:
- .always: Quit works from any screen (default)
- .rootOnly: Quit only works from main screen (no context pushed)
- Quit item hidden in status bar when not allowed

ThemeManager:
- Singleton for managing theme cycling
- cycleTheme() / cyclePreviousTheme() methods
- setTheme(at:) and setTheme(withId:) for direct access
- Automatically updates environment and triggers re-render
- 't' key now cycles themes in AppRunner
2026-01-28 20:44:00 +01:00
phranck 9c96e96460 feat: Add showHelpItem and showThemeItem flags
- System items are now built dynamically based on flags
- showHelpItem (default: true) - controls ? help visibility
- showThemeItem (default: true) - controls t theme visibility
- Quit item is always shown when showSystemItems is true
- Removed unused configureSystemItems method
2026-01-28 20:42:08 +01:00
phranck b9a6cc29ab fix: Show all system items (quit, help, theme) and fix deduplication
- StatusBarState now initializes with all 3 system items
- Added deduplication logic to StatusBar.renderToBuffer
- User items with same shortcut override system items
- Updated Example App to not duplicate 'q quit'
- Updated tests for 3 system items instead of 1
2026-01-28 20:40:52 +01:00
phranck 61a51ef056 refactor: Two-container model for StatusBar (user left, system right)
- StatusBar now has separate userItems and systemItems properties
- User items are sorted by order, then system items (fixed order) appended
- Rendering combines both: [sorted user items] + [system items]
- User items override system items with same shortcut (deduplication)
- StatusBarState passes items separately to StatusBar
- Alignment applies to the combined items
- Updated tests to use userItems property
2026-01-28 20:32:39 +01:00
phranck 04cbf2db8b feat: Add system StatusBar items with stable ordering
- Add StatusBarItemOrder for consistent item positioning
- System items (quit, help, theme) appear on the right side
- User items appear on the left, can override system items
- Separate tracking of user vs system items in StatusBarState
- Add showSystemItems flag to disable system items in tests
- Items sorted by order value (lower = left, higher = right)
- User items override system items with the same shortcut
- Add comprehensive tests for system item behavior (189 total)
2026-01-28 20:23:27 +01:00
phranck 45e73faafb refactor: Rename package from SwiftTUI to TUIKit
BREAKING CHANGE: Package name changed due to name collision with
existing rensbreur/SwiftTUI package.

Changes:
- Rename package from SwiftTUI to TUIKit in Package.swift
- Rename Sources/SwiftTUI to Sources/TUIKit
- Rename Sources/SwiftTUIExample to Sources/TUIKitExample
- Rename Tests/SwiftTUITests to Tests/TUIKitTests
- Rename SwiftTUI.swift to TUIKit.swift
- Update all imports: import SwiftTUI -> import TUIKit
- Update all code references: SwiftTUI.renderToBuffer -> TUIKit.renderToBuffer
- Update documentation comments
- Rename swiftTUIVersion to tuiKitVersion

All 181 tests passing.
2026-01-28 19:32:09 +01:00
phranck 44d9d4490e refactor: Replace FocusManager singleton with Environment-based injection
- Remove FocusManager.shared singleton pattern
- Add FocusManagerKey for Environment access via \.focusManager
- FocusState now reads from EnvironmentStorage
- AppRunner creates and injects FocusManager instance
- Button accesses FocusManager via context.environment
- Update all tests to use independent FocusManager instances
- Add new test suite for Environment integration
- Tests can now run in parallel (no more --no-parallel needed)

181 tests passing
2026-01-28 19:28:00 +01:00
phranck a53c1a07fd refactor: Remove T prefix from all public types
- Rename TView → View, TApp → App, TScene → Scene
- Rename TState → State, TViewBuilder → ViewBuilder
- Rename TViewModifier → ViewModifier, TViewArray → ViewArray
- Rename TStatusBar* → StatusBar* (Item, Style, Alignment, Protocol)
- Add Theme system with 8 predefined themes (Phosphor, ncurses, Dark, Light)
- Add Color extensions: hex string, HSL, lighter/darker/opacity
- Update all files, example app, and tests for new names
2026-01-28 19:08:50 +01:00
phranck 5a076dbf9b feat: Add lifecycle, storage, preferences and improve layout
- Add @AppStorage and @SceneStorage for persistent settings
- Add @onAppear, @onDisappear and .task() lifecycle modifiers
- Add Preferences system for bottom-up data flow (child → parent)
- Add UserDefaultsStorage with Linux-compatible implementation
- Add flexible .frame() with minWidth/maxWidth/maxHeight/.infinity
- Fix BorderModifier to reduce availableWidth for content
- Fix StatusBar .justified alignment for equal edge spacing
- Fix Alert vertical expansion by removing Spacer
- Fix q-quit not working when StatusBar item has no action
- Fix render loop caused by statusBarItems modifier
- Add Linux compatibility (Glibc, XDG paths)
2026-01-28 18:42:52 +01:00
phranck 0ce0d541b7 feat: Add Environment system and refactor StatusBar to use it
This commit introduces a SwiftUI-like Environment system and refactors
the StatusBar from a singleton pattern to an environment-based architecture.

## Environment System (new)
- EnvironmentKey protocol for defining custom environment values
- EnvironmentValues container with subscript access
- EnvironmentStorage for thread-local storage during rendering
- @Environment property wrapper for reading values in views
- EnvironmentModifier and .environment() modifier for injecting values

## StatusBar Refactoring
- Replaced StatusBarManager singleton with StatusBarState class
- StatusBarState is created by AppRunner and injected via Environment
- Views access StatusBar via @Environment(\.statusBar)
- Removed all singleton-based code from StatusBar.swift

## .statusBarItems() Modifier (new)
- .statusBarItems([...]) - set items from array
- .statusBarItems { ... } - set items with builder syntax
- .statusBarItems(context: "name") { ... } - push items to context stack
- Enables declarative StatusBar configuration per view

## Example App
- ContentView now uses .statusBarItems() modifier declaratively
- AppState simplified - no manual StatusBar reference needed
- Each page declares its own status bar items

## Tests
- 178 tests across 26 suites, all passing
- New tests for StatusBarItemsModifier
- Tests updated for StatusBarState API
2026-01-28 18:12:34 +01:00
phranck 959e7ffb5a feat: Add Shortcut constants for common Unicode symbols
- Add Shortcut enum with predefined Unicode symbols for keyboard shortcuts:
  - Special keys: escape (⎋), enter (↵), tab (⇥), backspace (⌫), etc.
  - Arrow keys: single (↑↓←→) and combinations (↑↓, ←→, ↑↓←→)
  - Modifier keys: command (⌘), option (⌥), control (⌃), shift (⇧)
  - Navigation: home, end, pageUp (⇞), pageDown (⇟)
  - Common shortcuts: quit, yes, no, cancel, ok
- Add helper methods:
  - Shortcut.combine() for combining symbols
  - Shortcut.ctrl() for Ctrl+key display (^c)
  - Shortcut.range() for range display (1-9)
- Update Example App to use Shortcut constants
- Add 9 new tests for Shortcut constants (103 total)
2026-01-28 17:22:00 +01:00
phranck 1c896fb1f8 feat: Add TStatusBar with dynamic context-sensitive shortcuts
- Add TStatusBarItemProtocol for custom status bar items
- Add TStatusBarItem with shortcut, label, and action callback
- Add TStatusBarStyle (compact, bordered) for visual customization
- Add StatusBarManager singleton for context-dependent item management
  - Global items (always shown)
  - Context stack (push/pop for dialogs, modals, etc.)
  - Automatic shortcut handling with case-sensitive matching
- Modify AppRunner to render StatusBar separately (never dimmed by overlays)
- Reserve space for StatusBar in content area calculation
- Add 20 new tests for StatusBar system (94 total)
- Restructure Example App into separate files:
  - main.swift (entry point)
  - AppState.swift (state management)
  - ContentView.swift (page router)
  - Components/ (HeaderView, DemoSection)
  - Pages/ (MainMenuPage, TextStylesPage, ColorsPage, etc.)
2026-01-28 17:16:44 +01:00
phranck 5ca3ce2de1 feat: Add Button view with focus system and keyboard support
- Add FocusManager for tracking which element has focus
- Add Focusable protocol for interactive views
- Add Button view with styles (default, primary, destructive, success, plain)
- Add ButtonRow for horizontal button groups
- Add ButtonStyle with customizable colors, borders, and padding
- Keyboard navigation: Tab to move focus, Enter/Space to activate
- Visual focus indicator (▸) for focused buttons
- Add 16 new tests for Focus and Button systems (74 total)
- Add Buttons & Focus demo page to example app
2026-01-28 16:50:20 +01:00
phranck ddcb918ad5 fix: onKeyPress handler now returns Bool to control event propagation
- Handler must return true if event was consumed, false to propagate
- This fixes 'q' not working to quit the app (was being consumed)
- ESC on sub-pages returns true (consumed), on menu returns false (exits)
2026-01-28 16:44:19 +01:00
phranck 461787a43e fix: ESC for back navigation and menu divider color
- ESC key now goes back to menu (instead of B key)
- ESC only exits app when already on main menu
- Menu divider line now uses same color as border
- Updated footer to show [ESC] Back instead of [B] Back
2026-01-28 16:36:58 +01:00
phranck e3b19fd518 fix: Panel top border and remove ugly border styles
Panel:
- Fixed top border calculation (left corner was missing)
- Added ANSI reset before right border to prevent color bleeding

BorderStyle:
- Removed .dashed, .dotted, and .ascii styles (poor visual quality)
- Remaining styles: .line, .rounded, .doubleLine, .heavy, .block, .none
2026-01-28 16:32:59 +01:00
phranck 97bdc5cf2f feat: Add state management and keyboard event system
State Management:
- @TState property wrapper for reactive state
- Binding<T> for two-way data binding
- AppState singleton for triggering re-renders

Event System:
- KeyEvent model with Key enum (arrows, enter, escape, characters, etc.)
- KeyEvent.parse() for terminal escape sequence parsing
- KeyEventDispatcher for routing events to handlers
- .onKeyPress() modifier for handling keyboard input
- Terminal.readKeyEvent() for reading complete key events

Interactive Menu:
- Menu now accepts selection Binding for interactive navigation
- Arrow keys move selection up/down (with wrap-around)
- Enter key and shortcuts trigger onSelect callback
- Automatic key handler registration during render

Example App:
- Full page navigation between demo screens
- Press [B] to go back to menu from any page
- Arrow keys and number shortcuts for menu navigation
- Footer shows available keyboard shortcuts
2026-01-28 16:09:16 +01:00
phranck 69ea72ac25 fix: Menu divider alignment and center feature boxes
- Menu divider now starts at same column as title text
- Feature boxes on main menu are now horizontally centered
2026-01-28 16:01:37 +01:00
phranck feb4967300 fix: Prevent ANSI color bleeding to right border
- Add ANSI reset before right border character in Menu and BorderModifier
- This prevents colored content from affecting border color
2026-01-28 15:59:59 +01:00
phranck 1bd5856c4d fix: Menu rendering and input handling
- Menu now uses Renderable protocol instead of ForEach in body
  (ForEach rendering in body not fully working yet)
- Input handler now only exits on ESC/q/Q, ignores other keys
- Menu items render correctly with selection indicator and shortcuts
2026-01-28 15:57:16 +01:00
phranck 7ddac7067d feat: Complete SwiftTUI foundation with overlay system and menu
Core Framework:
- TView protocol with TViewBuilder result builder (up to 10 children)
- Full ANSI rendering pipeline (Terminal, ANSIRenderer, FrameBuffer)
- TApp/TScene/WindowGroup app lifecycle with SIGWINCH handling
- Color system (ANSI, bright, 256-palette, RGB, hex, semantic colors)
- Text styling (bold, italic, underline, strikethrough, dim, blink, inverted)

Container Views:
- VStack, HStack, ZStack with alignment and spacing
- Card (bordered container with padding/background)
- Box (simple bordered container)
- Panel (titled container with title in border)
- ForEach for dynamic content

Modifiers:
- .padding(), .frame(), .border() (8 border styles), .background()
- .overlay() with alignment, .dimmed(), .modal() helper

Overlay System:
- Alert view with title, message, actions, and presets (warning/error/info/success)
- Dialog view for flexible modal content
- FrameBuffer character-level compositing

Menu View:
- Menu with items, selection indicator, shortcuts
- MenuItem model with id, label, shortcut
- AnyView type-erased wrapper

Example App:
- Menu-based navigation with multiple demo pages
- Text Styles, Colors, Containers, Overlays, Layout demos

Tests:
- 58 tests across 12 suites, all passing
2026-01-28 15:35:55 +01:00
phranck dac288a5e4 Initial Commit 2026-01-28 09:26:25 +01:00