Document the Tab double-processing bug and its solution:
- Symptom: Row color alternating on Tab press
- Root cause: Tab processed twice (widget + app level)
- Solution: NavigateDirection + handled flag + app check
- General rule for keyboard handling in immediate-mode widgets
Also updated EditKeyboardResult API documentation with new fields.
- Check navigate_direction before setting tab_out in handleKeyboard
- Export NavigateDirection from virtual_advanced_table module
- Use cell_editor.NavigateDirection in VirtualAdvancedTableResult
This fixes the bug where Tab was processed twice: once by CellEditor
(for cell navigation) and again by handleKeyboard (for tab_out).
- Import and use table_core for keyboard handling
- Re-export NavigateDirection from table_core
- Map table_core.EditKeyboardResult to CellEditorResult
- Remove ~100 lines of duplicated keyboard handling code
- Add 'handled' field to CellEditorResult
- Add NavigateDirection enum (none, next_cell, prev_cell, next_row, prev_row)
- Replace navigate_next/navigate_prev bools with single navigate field
- Add 'handled' flag to prevent double processing of Tab
- Add Up/Down arrow handling for row navigation
- Use getKeyEvents() loop instead of keyPressed() for consistency
Complete documentation covering:
- When to use AdvancedTable vs VirtualAdvancedTable
- Architecture diagram (table_core.zig as single source)
- How to extend functionality (always in table_core.zig)
- Complete API reference for table_core.zig
- Code examples and model differences
Norma #6: Abstract to library level
- Tab navigation with wrap now in library, not application
- AdvancedTableState.tabToNextCell/tabToPrevCell for in-memory data
- VirtualAdvancedTableState.tabToNextCell/tabToPrevCell for paginated data
- DRY: same logic available in both table widgets
- Tab/Shift+Tab with wrap navigation in editing mode
- tab_out/tab_shift result fields for application handling
- Cursor position, blinking, background color fixes
- markRowSaved() to clear dirty state after save
- last_edited_row only set when actual changes made
- New module: table_core.zig with common table rendering logic
- drawCellActiveIndicator(): visual indicator for selected cell
- detectDoubleClick(): timing-based double-click detection
- handleEditingKeyboard(): common keyboard handling for editing
- blendColor(), startsWithIgnoreCase(): utilities
VirtualAdvancedTable now uses table_core:
- Active cell indicator in drawRows (visible highlight on selected cell)
- Double-click detection in handleMouseClick
- Added state fields: last_click_time, last_click_row, last_click_col
AdvancedTable changes:
- Improved cell active indicator (alpha 0.35, double border)
- Added double-click fields to state
- Space starts editing with empty value
- Alphanumeric keys start editing in editable cells
- Replace manual temp variable swap with std.mem.swap (more explicit)
- Add documentation warning about pointer invalidation after sort/setRows
- Row contains StringHashMap with internal pointers - swap is safe but
pointers obtained via getRow() are invalidated after mutations
Based on INFORME_AUDITORIA_PROFUNDA_20251225.md §1.2
- Added footer_display_buf and footer_display_len to VirtualListState
- Fixes use-after-return bug: stack buffer passed to pushCommand() was
invalidated when function returned, causing corrupted display in
deferred rendering
- FilterBar chips con forma pill (border-radius completo)
- Esquinas redondeadas en TextInput del filtro
- Fix click offset: ahora cuenta filter_bar_h + header_h
- Corrección selección de fila por click
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Añadir borde alrededor de toda la lista (siempre visible)
- Mejorar centrado vertical del texto (y+4 → y+3)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- moveUp: Calcular screen position para scroll correcto
- footer_h: Reducir de 20 a 16 pixels para más filas visibles
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- moveDown: Calcular screen position antes de decidir scroll
- Scroll ahora ocurre cuando llega a última fila visible (no penúltima)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- drawRows: Calcular window_offset para dibujar desde scroll_offset
- handleMouseClick: Convertir screen_row a data_idx con offset
- Antes siempre dibujaba desde índice 0 del buffer
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
Documentar nueva funcionalidad AdvancedTable:
- selected_row_unfocus: color fila seleccionada sin focus
- BasicColors acepta override desde aplicación
- drawRow recibe has_focus para elegir color
🤖 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>
Cambios:
- Extraer historial de versiones a CHANGELOG.md
- Condensar secciones con enlaces a docs existentes
- Mantener completo: protocolo inicio, reglas críticas,
documentación teamdocs, rutas, comandos
- Eliminar duplicación con docs/ARCHITECTURE.md y REFERENCE.md
CLAUDE.md sigue siendo autosuficiente para inicio de conversación.
🤖 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>
- Añadida sección 🔴 BUG PENDIENTE con síntoma y pistas
- Actualizado historial: v0.20.0 y v0.21.0
- Añadido docs/BUG_ADVANCEDTABLE_KEYBOARD_2025-12-17.md a Paso 3
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
El bug de navegación con flechas persiste. Documentación
completa del problema y pistas de debugging para próxima sesión.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Documento ADVANCED_TABLE_ENHANCEMENT_ANALYSIS.md:
- Features de table/ que faltan en AdvancedTable
- Features de virtual_scroll y grid aplicables
- Investigación web: features estándar de tablas modernas
- Tareas priorizadas (TASK-AT-9 a TASK-AT-F5)
- Análisis merge Table + AdvancedTable (4 opciones)
- Timeline propuesto post-validación
Decisión: ESPERAR validación en zsimifactu antes de implementar
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Añadido AdvancedTable a lista de Data Widgets
- Sección completa de uso (~200 líneas):
- Basic usage con schema
- Column types
- Lookup & Auto-fill (Fase 7)
- DataStore interface
- Callbacks + Debounce (Fase 8)
- Keyboard navigation
- Row states
- Result fields
- Actualizado Version History (v0.18.0 → v0.20.0)
🤖 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>
Arno es el nombre de la carpeta/servidor, no del usuario.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Paridad Visual DVUI completada
- Focus Ring AA en 9 widgets documentado
- Historial actualizado con v0.19.0
- Bug TTF marcado como RESUELTO
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>