Cambiar de keyPressed() a navKeyPressed() permite que mantener
pulsada la flecha arriba/abajo mueva la selección continuamente.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- VirtualListConfig.Colors ahora usa Style.Color en vez de u32
- Reemplazar Command.fill() por Command.rect() (fill no existe)
- Corregir tipo bg_color en drawRows
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Nuevo módulo virtual_list para listas virtualizadas:
types.zig:
- RowData: datos genéricos de fila con ID persistente
- ColumnDef: definición de columnas (name, title, width)
- SortDirection: enum con toggle()
- CountInfo: conteo con estado (loading, partial, ready)
- VirtualListConfig: configuración con umbral configurable
data_provider.zig:
- DataProvider: interface vtable para fuentes de datos
- Métodos: fetchWindow, getTotalCount, setFilter, setSort
- MockProvider para tests
- Tests completos
state.zig:
- VirtualListState: estado de navegación y selección
- Selección por ID (no índice)
- Conversión global ↔ window index
- Navegación: moveUp/Down, pageUp/Down, goToStart/End
- Tests completos
virtual_list.zig:
- Re-exports de módulos
- Documentación de arquitectura
- VirtualListResult struct
- TODO: widget principal (Fase 3)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- CellValue.clone(): duplica strings en lugar de copiar punteros
- CellValue.deinit(): libera strings clonados
- Row.owns_data: flag para indicar propiedad de memoria
- Row.clone(): ahora hace deep copy completo
- Row.deinit(): libera strings si owns_data=true
Soluciona crash al guardar cliente sin población/provincia/país,
donde loadWhoList() liberaba strings que Row clonada seguía referenciando.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
OVERLAY SYSTEM:
- Context: nuevo campo overlay_commands para capa superior
- Context: nueva función pushOverlayCommand()
- mainloop: renderiza overlay_commands DESPUÉS de commands
- autocomplete: dropdown usa overlay (se dibuja encima de otros widgets)
MEJORAS AUTOCOMPLETE:
- Dropdown se abre inmediatamente al escribir (sin delay de 1 frame)
- Dropdown se abre al borrar con backspace/delete
- Click en flecha del dropdown hace toggle abrir/cerrar
- Área clicable de flecha: 20px
ESTADO: En progreso - funcionalidad básica operativa, pendiente:
- Keyboard handlers completos
- Más testing de casos edge
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Altura del cursor: inner.h (toda la altura del campo, no 8px fijos)
- Posición Y: inner.y (no centrado en el texto)
- Parpadeo: usa CURSOR_BLINK_PERIOD_MS y CURSOR_IDLE_TIMEOUT_MS
- Lógica idéntica a TextInput para consistencia visual
Cambios de Gemini para estabilidad IMGUI:
- setText(): Sincroniza last_filter para evitar falsos text_changed
- clear(): Resetea last_filter_len
- autocompleteRect(): Cierra dropdown si options.len == 0
Parte de la solución para corrupción de memoria en cascade AutoComplete.
Eliminados std.debug.print con números mágicos 99999 y debug de
focus/colores añadidos durante investigación del bug.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Bug crítico: Al dar focus a cualquier widget, TODO el fondo se pintaba
de azul semitransparente, no solo el borde de focus.
Causa: En drawRoundedRect() había código de una implementación anterior
que hacía fillRoundedRect() antes de dibujar el outline. Cuando focusRing
llamaba a drawRoundedRect con color azul, primero rellenaba todo el área.
Fix: Eliminadas 8 líneas de código obsoleto (comentarios de estrategia
abandonada + la llamada a fillRoundedRect).
También: Limpieza de código debug en advanced_table.zig.
Crédito: Bug encontrado por Gemini tras descripción del problema.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Cambios:
- Añadir selected_row_unfocus a TableColors
- drawRow ahora recibe has_focus para elegir color
- Con focus: usa selected_row (color accent)
- Sin focus: usa selected_row_unfocus (gris sutil)
BasicColors ahora acepta selected_row y selected_row_unfocus
opcionales para permitir override desde PanelColorScheme.
Esto permite que el usuario vea claramente:
- Qué panel tiene focus (fila con color accent)
- Qué fila está seleccionada en panel sin focus (gris)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- BasicColors struct: background, foreground, accent, header_bg opcionales
- TableColors.fromBasic(): deriva 26 colores desde 3-4 básicos
- BasicColors.toColor(): convierte cualquier tipo con r,g,b a Style.Color
- Detecta automáticamente tema claro/oscuro para derivar colores
- Presets dark()/light() y withAccent() para personalización
Permite que las aplicaciones pasen colores configurables desde sus
sistemas de config propios (como zsimifactu con resolveColor()).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Bug: Las flechas no movían la selección en AdvancedTable.
Causa raíz:
- handleKeyboard seteaba result.selection_changed = true
- PERO NO seteaba result.selected_row / result.selected_col
- zsimifactu sincroniza selección desde DataManager cada frame
- Sin esos valores, DataManager no se actualizaba
- Siguiente frame: selección se reseteaba al valor anterior
Solución:
- Añadir result.selected_row y result.selected_col a todas
las teclas de navegación (up, down, left, right, page_up,
page_down, home, end)
Cambios visuales:
- Celda seleccionada: borde + tinte sutil (15%) en lugar
de fondo sólido azul
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fase 7 - Lookup & Auto-fill:
- performLookupAndAutoFill() en commitEdit
- Busca en DataStore.lookup() al editar columna lookup
- Auto-rellena columnas según auto_fill_columns mapping
- Indicador visual "?" en header para columnas lookup
- Campo lookup_success en AdvancedTableResult
Fase 8 - Callbacks + Debounce:
- invokeCallbacks() con sistema de debounce (150ms default)
- on_row_selected: al cambiar selección
- on_cell_changed: al confirmar edición
- on_active_row_changed: al cambiar de fila (para paneles detalle)
- Campos last_callback_time_ms, last_notified_row en state
Tests: 373/373 (+3 nuevos)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Widgets actualizados:
- NumberEntry: esquinas redondeadas + focus ring
- Radio: esquinas redondeadas para círculos + focus ring en opción
- Slider: esquinas redondeadas en track/thumb + focus ring
- Tabs: esquinas redondeadas en tab seleccionado + focus ring
- Table: focus ring alrededor de toda la tabla
- TextArea: esquinas redondeadas + focus ring
Nuevos campos:
- TableColors.focus_ring para consistencia
Total: +135 LOC en 7 archivos
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Command helpers:
- focusRing(x, y, w, h, radius) - focus indicator con AA
- focusRingColor() - versión con color custom
Características:
- Dibuja 2px fuera del widget (offset)
- Color semi-transparente (primary alpha 180)
- Radio +2 para mantener proporciones
- Thickness 2px para visibilidad
- Anti-aliasing habilitado
Widgets actualizados:
- TextInput: focus ring cuando has_focus
- Select: focus ring cuando has_focus (no cuando dropdown abierto)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
SelectState ahora incluye:
- hover: HoverTransition para transiciones suaves
- last_time_ms: tracking de tiempo para delta
El color de fondo del botón principal del Select ahora
transiciona suavemente entre normal y hover (lighten 5%).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sistema de rendering dual para zcatgui:
Core:
- RenderMode enum (simple/fancy) en style.zig
- global_render_mode con helpers: isFancy(), setRenderMode()
- fillRoundedRect con edge-fade AA en framebuffer.zig (~350 LOC)
- Nuevos comandos: rounded_rect, rounded_rect_outline
Widgets actualizados:
- Button: corner_radius=4, usa roundedRect en fancy mode
- Panel: corner_radius=6, show_shadow=true, sombra offset 4px
- TextInput: corner_radius=3
- Select: corner_radius=3
- Modal: corner_radius=8, show_shadow=true, sombra offset 6px
- Botones y input field del modal también redondeados
Técnica edge-fade (de DVUI):
- Anti-aliasing por gradiente alfa en bordes
- Sin supersampling, mínimo impacto en rendimiento
- Bordes suaves sin multisampling
+589 líneas, 9 archivos modificados
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- build.zig.zon: Añadir zcatttf como dependencia local
- build.zig: Importar módulo zcatttf en todos los targets
- ttf.zig: Reescribir como wrapper de zcatttf (991→561 LOC)
Cambios en ttf.zig:
- Usa zcatttf.Font para parsing y rasterización
- Mantiene API pública compatible (TtfFont, drawText, etc.)
- Añade soporte UTF-8 completo en drawText
- Elimina código de rasterización propio (buggy)
Eliminado:
- cmap_debug.zig del build (herramienta de diagnóstico obsoleta)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Cambios:
- ttf.zig: Fix formato pixel ABGR (era RGBA invertido)
- cmap_debug.zig: Herramienta diagnóstico tabla cmap
- build.zig: Target cmap-debug para ejecutar diagnóstico
- docs/research/TTF_DEBUG_SESSION: Documentación sesión debug
Nota: El código base TTF funciona (cmap_debug lo confirma).
El bug de rendering sigue sin resolver en integración.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- AdwaitaSans era fuente variable (fvar/gvar) incompatible con parser
- DroidSans.ttf: fuente estática 187KB (Apache 2.0)
- Y-flip en rasterización: TTF Y crece arriba, bitmap Y crece abajo
- Pendiente: UTF-8 multibyte en drawText
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Añadir src/render/fonts/AdwaitaSans-Regular.ttf (860KB)
- Crear src/render/embedded_font.zig con @embedFile
- Añadir TtfFont.initEmbedded() para carga sin dependencias
- Exportar embedded_font en zcatgui.zig
Ahora cualquier programa que use zcatgui tiene TTF
disponible automáticamente sin archivos externos.
Licencia: SIL Open Font License (redistribución OK)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Cambios:
- TTF rasterization completo con bezier curves
- Antialiasing via supersampling 2x
- Integración TTF en SoftwareRenderer (setTtfFont)
- Fix ArrayListUnmanaged para Zig 0.15.2
- Documentación REFERENCE.md actualizada
CLAUDE.md actualizado con v0.16.0 y historial.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Test carga fuente del sistema
- Verificar parsing de contornos para 'A'
- Verificar rasterización produce bitmap con datos
- Test múltiples caracteres (AaBb0123)
- Tests skip gracefully si fuente no disponible
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Añadir GlyphPoint, Contour, GlyphOutline para representar contornos
- Implementar getGlyphOutline() para parsear tabla glyf
- Implementar rasterizeGlyph() con supersampling 2x
- Scanline fill con non-zero winding rule
- Subdivisión de curvas Bezier cuadráticas
- Cache de glyphs por codepoint+size
- Alpha blending para antialiasing
- Reemplazar drawGlyphPlaceholder con renderizado real
El código parsea contornos TTF y los rasteriza con antialiasing.
Próximo paso: test visual con AdwaitaSans.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Añadir sección PROTOCOLO DE DOCUMENTACIÓN (2025-12-16)
- Agenda = índice, detalles en hitos/
- Límite ~300 líneas por archivo
- Añadir sección TAREA ACTUAL: Fuentes TTF con Antialiasing
- Estado de ttf.zig y fases de implementación
- TextInput: añadir text_color/border_color para validación
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Cambios:
- base.zig: Añadido x_offset a ActionButtonsOpts y NavButtonsOpts
- text_input.zig: char_height 8→16 para fuente 8x16
- table/render.zig: char_height 8→16 (header y celdas)
El centrado vertical del texto ahora funciona correctamente
con fuentes 8x16 (VGA standard).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Rename data_manager.zig to change_notifier.zig
- Update exports in panels.zig
- Clarifies that ChangeNotifier is for panel communication,
not application data management (which apps implement separately)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1592 líneas eliminadas - archivo no usado.
widgets.zig importa table/table.zig (versión fragmentada).
Detectado durante auditoría de tamaños de archivo.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Archivos que estaban localmente pero no en el repo:
- src/core/focus_group.zig (416 líneas)
- src/widgets/focus.zig (272 líneas)
- src/widgets/progress.zig (806 líneas)
- src/widgets/table.zig (1592 líneas)
- src/widgets/textarea.zig (871 líneas)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
El clip se aplicaba solo al área de contenido (excluyendo header),
lo que permitía que el texto de los headers se extendiera fuera
de los límites de la tabla.
Ahora el clip abarca toda la tabla (bounds completos) antes de
dibujar headers y contenido.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Table clipping:
- Add clip region around table content area
- Prevents cell text from drawing outside table bounds
- Header and scrollbar render outside clip region
Cursor animation API:
- Add CURSOR_IDLE_TIMEOUT_MS (5s) and CURSOR_BLINK_PERIOD_MS (500ms) constants
- Add needsCursorAnimation() to check if cursor should blink
- Add getAnimationTimeout() for dynamic event loop timeout
- Update TextInput to use constants from Context
The application can now query ctx.getAnimationTimeout() to determine
if a short timeout is needed for cursor animation, or if it can wait
indefinitely for events.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Split large widget files for better maintainability (~500-600 lines per file):
textarea/ (was 882 lines):
- types.zig: TextAreaConfig, TextAreaColors, TextAreaResult
- state.zig: TextAreaState with cursor/selection methods
- render.zig: drawLineNumber, drawLineText, drawLineSelection
- textarea.zig: Main API with re-exports and tests
progress/ (was 806 lines):
- render.zig: Shared drawing helpers (stripes, gradients, arcs)
- bar.zig: ProgressBar widget
- circle.zig: ProgressCircle widget
- spinner.zig: Spinner widget with animation state
- progress.zig: Main API with re-exports and tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Split the 1770-line table.zig into a cleaner module structure:
src/widgets/table/
├── table.zig (~400 lines) - Public API + re-exports + tests
├── types.zig (~150 lines) - Enums, configs, column definitions
├── state.zig (~500 lines) - TableState, TableResult
├── keyboard.zig (~270 lines) - Keyboard handling, search
└── render.zig (~350 lines) - Drawing functions
Benefits:
- Each file is now manageable (<500 lines)
- Clearer separation of concerns
- Easier to navigate and modify
- Same public API (no breaking changes)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 1: Frame timing in Context
- Added current_time_ms and frame_delta_ms to Context
- Added setFrameTime() method for applications to provide timing
Phase 2: Centralized shortcuts system
- Added StandardShortcut enum with common shortcuts (copy, paste, etc.)
- Added isStandardActive() function for checking shortcuts
- Updated TextInput to use centralized shortcuts
Phase 3: Incremental search in table
- Added search_buffer, search_len, search_last_time to TableState
- Added addSearchChar(), getSearchTerm(), clearSearch() methods
- Typing in focused table searches first column (case-insensitive)
- 1 second timeout resets search buffer
Phase 4: Blinking cursor in TextInput
- Cursor blinks every 500ms when field is focused
- Uses current_time_ms from Context for timing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Actualizar FOCUS_TRANSITION_2025-12-11.md con patrón de integración
- Actualizar CLAUDE.md: sección SISTEMA DE FOCUS - RESUELTO
- Widgets adaptados a FocusSystem:
- numberentry.zig: registerFocusable, requestFocus, hasFocus
- textarea.zig: registerFocusable, requestFocus, hasFocus
- select.zig: campo focused, integración completa
- radio.zig: reemplazado focus manual por FocusSystem
- slider.zig: reemplazado focus manual por FocusSystem
- tabs.zig: navegación teclado solo cuando tiene focus
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Cambios principales:
- Nuevo FocusSystem unificado en core/focus.zig
- Separación registration_group / active_group para multi-panel
- Focus implícito para primer widget del grupo activo
- Table inicializa selected_row/col a 0 cuando tiene datos
- Corregido test navKeyPressed (usaba setKeyState en vez de handleKeyEvent)
Bug resuelto: tabla no respondía a teclado sin clic previo
Causa: selected_col quedaba en -1, selectedCell() retornaba null
Documentación: docs/FOCUS_TRANSITION_2025-12-11.md
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
PROBLEMA DETECTADO:
- Existían dos sistemas de focus paralelos que no se comunicaban
- FocusManager (widgets/focus.zig) usaba IDs u32
- FocusGroupManager (core/focus_group.zig) usaba IDs u64
- Esto causaba que Tab no funcionara y clics no cambiaran focus
SOLUCIÓN CONSENSUADA:
- Usar SOLO FocusGroupManager como fuente de verdad
- Integrar en Context con métodos públicos
- Widgets se auto-registran en el grupo activo al dibujarse
- Tab navega DENTRO del grupo activo
- F6 (u otro) cambia entre grupos/paneles
CAMBIOS:
- context.zig: Añadidos createFocusGroup(), setActiveFocusGroup(),
hasFocus(), requestFocus(), registerFocusable(), handleTabKey()
- text_input.zig: Usa @intFromPtr para ID único, se auto-registra
- table.zig: Ahora se registra como widget focusable
- widgets.zig/zcatgui.zig: Eliminadas referencias antiguas a FocusManager
- CLAUDE.md: Documentado el trabajo en progreso
ESTADO: EN PROGRESO - Compila pero requiere más testing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
For solid colors (alpha=255), use @memset per row instead of
pixel-by-pixel loop. @memset is SIMD-optimized by the compiler
(uses SSE/AVX on x86-64).
Result: Render time 1.4ms → 1.0ms (28% faster in Release build)
Also cleaner code separation between solid color fast path
and alpha blending slow path.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Framebuffer:
- Add clearRect() for clearing specific rectangular regions
SoftwareRenderer:
- Add executeWithDirtyRegions() for optimized partial rendering
- Add clearRect() convenience method
- Add commandBounds() to extract bounding box from draw commands
- Add rectsIntersect() helper for intersection testing
This enables applications to:
1. Clear only dirty regions instead of full screen
2. Skip rendering commands outside dirty areas
3. Significantly reduce CPU when only small areas change
Usage: Pass dirty_regions from Context.getDirtyRects() to
executeWithDirtyRegions() instead of using clear()+executeAll().
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add waitEvent() and waitEventTimeout() to Backend abstract interface
- Implement SDL_WaitEvent and SDL_WaitEventTimeout in SDL2 backend
- Refactor translateEvent into shared function
- Optional vtable entries with fallback to pollEvent for compatibility
This enables progressive sleep patterns:
- Phase 1: Short sleep (8ms) for quick response
- Phase 2: Medium sleep (33ms) for moderate idle
- Phase 3: SDL_WaitEventTimeout for 0% CPU in deep idle
Result: CPU 92% → 1.9% in idle applications.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Early out para caracteres completamente fuera del clip
- Fast path para caracteres 100% visibles (caso común)
- Escritura directa al buffer de píxeles sin setPixel
- Loop optimizado para fuentes de 8px de ancho
- Unroll de los 8 bits del glyph byte
Resultados:
- Debug: 40ms → 32ms por frame
- Release: 40ms → 1.5ms por frame (~26x más rápido)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Cambio de SDL_RENDERER_SOFTWARE a SDL_RENDERER_ACCELERATED | PRESENTVSYNC:
- VSync sincroniza con el refresco del monitor (~60Hz)
- SDL_RenderPresent() ahora bloquea hasta el próximo frame
- Elimina necesidad de sleep manual en aplicaciones
- CPU de ~70% a ~1-5% en idle
Fallback a software renderer si GPU no disponible.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
El widget TextInput ahora procesa internamente:
- Backspace/Delete: borrar caracteres
- Flechas izq/der: mover cursor
- Home/End: inicio/fin del texto
- Shift+movimiento: selección
- Ctrl+A: seleccionar todo
- Enter: submit
Esto hace que el widget sea auto-contenido y reutilizable,
sin requerir manejo de teclas en la aplicación.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- REFERENCE.md: Nueva sección "UTF-8 Text Rendering" explicando:
- Cómo funciona la decodificación UTF-8 → Latin-1
- Caracteres soportados (ASCII + Latin-1 Supplement)
- Por qué UTF-8 es el estándar correcto para BD/archivos
- Ejemplo de uso con texto español
- software.zig: Doc comments explicando el sistema UTF-8
El renderer ahora maneja texto UTF-8 automáticamente,
permitiendo mostrar correctamente: ñ, á, é, í, ó, ú, ¿, ¡, €, etc.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
El renderer iteraba byte por byte, causando que caracteres UTF-8
multi-byte (como ñ, á, é) se mostraran incorrectamente.
Cambios:
- Decodificación completa de UTF-8 (1-4 bytes)
- Mapeo de codepoints a Latin-1 para renderizado
- Caracteres fuera de Latin-1 se muestran como '?'
Esto permite mostrar correctamente texto en español y otros
idiomas europeos que usan caracteres Latin-1.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New Core Modules (4):
Clipboard - System clipboard integration
- getText()/setText() via SDL2 clipboard API
- hasText() and clear() utilities
- Cross-platform support
DragDrop - Drag and drop system
- DragData with typed data transfer
- DropZone registration with type filtering
- DragDropManager for coordinating operations
- Hover detection and drop results
- Helper functions: makeDraggable(), makeDropZone()
Shortcuts - Keyboard shortcuts system
- Shortcut struct with key + modifiers
- ShortcutManager for registration and checking
- Common shortcuts (Ctrl+C/V/X/Z, etc.)
- Human-readable formatting (formatShortcut)
- Enable/disable individual shortcuts
FocusGroup - Focus group management
- FocusGroup for widget tab order
- focusNext/Previous with wrap support
- FocusGroupManager for multiple groups
- Group switching (focusNextGroup)
- Tab/Shift+Tab navigation
All tests passing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New Widgets:
- TextArea: Multi-line text editor with cursor navigation,
line numbers, selection, and scrolling support
- Tree: Hierarchical tree view with expand/collapse,
keyboard navigation, and selection
- Badge: Status labels with variants (primary, success,
warning, danger, info, outline), dismissible option
- TagGroup: Multiple badges in a row with wrapping
From previous session (v0.7.0):
- Progress: Bar (solid, striped, gradient, segmented),
Circle, Spinner (circular, dots, bars, ring)
- Tooltip: Hover tooltips with smart positioning
- Toast: Non-blocking notifications with auto-dismiss
Widget count: 23 widgets
Test count: 163 tests passing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New Widgets (3):
- Progress: Bar, Circle, Spinner with multiple styles
- Bar styles: solid, striped, gradient, segmented
- Spinner styles: circular, dots, bars, ring
- Animated spinners with configurable speed
- Tooltip: Hover tooltips with smart positioning
- Auto-position to stay within screen bounds
- Arrow pointing to target element
- Multi-line text support with wrapping
- Configurable delay and styling
- Toast: Non-blocking notifications
- Types: info, success, warning, error
- Configurable position (6 positions)
- Auto-dismiss with countdown
- Action buttons support
- Stack multiple toasts
Widget count: 20 widgets
Test count: 140 tests passing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Apply TEAM_STANDARDS Norma #25: project names use lowercase
everywhere - repo, directory, module, documentation, imports.
No CamelCase in project names. Consistency = less cognitive friction.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>