Commit graph

173 commits

Author SHA1 Message Date
e8b4c98d4a docs: Add TABLES_ARCHITECTURE.md - definitive reference for table widgets
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
2025-12-27 01:58:57 +01:00
27b69cfcde refactor(table_core): Move Tab navigation logic to shared module (Norma #7 DRY)
ANTES: calculateNextCell/calculatePrevCell duplicados en:
  - AdvancedTableState
  - VirtualAdvancedTableState

AHORA: Lógica común en table_core.zig:
  - calculateNextCell() - calcula siguiente celda (Tab)
  - calculatePrevCell() - calcula celda anterior (Shift+Tab)
  - toggleSort() - alterna ordenación de columna
  - TabNavigateResult, CellPosition, SortDirection, SortToggleResult

Ambos widgets usan table_core, adaptando el resultado a su modelo:
  - AdvancedTable: selected_row/selected_col (índices)
  - VirtualAdvancedTable: selected_id + active_col (ID + columna)

Tests añadidos para calculateNextCell, calculatePrevCell, toggleSort
2025-12-27 01:49:56 +01:00
c2f0fbb19d refactor(tables): Add tabToNextCell/tabToPrevCell to both AdvancedTable and VirtualAdvancedTable
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
2025-12-27 01:28:32 +01:00
702c33c13a feat(virtual_table): Tab navigation + cursor fixes + cell editing
- 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
2025-12-27 01:18:54 +01:00
47fc5b28f7 refactor(tables): Add table_core.zig with shared rendering functions
- 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
2025-12-26 17:53:16 +01:00
65f6782d24 feat(virtual_advanced_table): Add keyboard/mouse editing triggers (F2, chars, column nav) 2025-12-26 14:54:24 +01:00
97ddf28c15 feat(virtual_advanced_table): Integrate CellEditor in draw loop with result handling 2025-12-26 14:51:03 +01:00
93836aef50 feat(virtual_advanced_table): Add CellEditor widget for inline editing 2025-12-26 14:49:04 +01:00
66816bcbf1 feat(virtual_advanced_table): Add CRUD Excel-style editing state
- Rename VirtualList → VirtualAdvancedTable
- Add CellId and CellGeometry types
- Add editing state fields (editing_cell, original_value, escape_count, etc.)
- Add editing methods: startEditing, commitEdit, cancelEdit, handleEscape
- Add getCellGeometry() for overlay positioning
- Add row_dirty flag for change tracking
2025-12-26 14:45:32 +01:00
7f8870d890 fix(advanced_table): Use std.mem.swap for Row sorting + doc warnings
- 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
2025-12-25 23:04:01 +01:00
1c284ed0f6 fix(virtual_list): Move footer display buffer to state struct
- 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
2025-12-25 22:40:14 +01:00
ae55ea5488 CLAUDE.md: jj + NORMAS_ESENCIALES 2025-12-25 19:24:00 +01:00
R.Eugenio
b0b8346355 feat(virtual_list): FilterBar visual + click offset fix
- 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>
2025-12-24 00:09:57 +01:00
R.Eugenio
7b2ba06035 fix(virtual_list): Borde completo + centrado texto
- 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>
2025-12-23 14:41:56 +01:00
R.Eugenio
b2bcdeae1a fix(virtual_list): Scroll arriba + footer compacto
- 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>
2025-12-23 14:31:12 +01:00
R.Eugenio
ae993a0f6f fix(virtual_list): Scroll en última fila y posición correcta
- 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>
2025-12-23 14:18:47 +01:00
R.Eugenio
b9e7434ef7 fix(virtual_list): Scroll visual y click con offset correcto
- 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>
2025-12-23 14:11:12 +01:00
R.Eugenio
ab39830477 Añadir /init optimizado (lee NORMAS_ESENCIALES + teamdocs)
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 13:28:54 +01:00
R.Eugenio
edba1cc7e5 fix(virtual_list): Soportar key repeat con navKeyPressed
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>
2025-12-23 13:12:54 +01:00
R.Eugenio
206a997628 fix(virtual_list): Usar Style.Color y Command.rect
- 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>
2025-12-23 13:00:20 +01:00
R.Eugenio
2abb8547a5 feat(virtual_list): Fase 3 - Widget completo con renderizado
Implementación del widget VirtualList (~530 LOC):

virtualListRect():
- Registra focusable, maneja mouse/keyboard
- Calcula filas visibles y buffer size
- Detecta si necesita refetch (needsRefetch)
- Llama a DataProvider.fetchWindow() cuando necesario
- Actualiza counts desde provider

Renderizado:
- drawHeader(): títulos columnas, indicadores sort (^/v), click para ordenar
- drawRows(): filas con alternancia, selección con/sin focus
- drawFooter(): contador "pos de total" con soporte para "..."
- drawScrollbar(): thumb proporcional al scroll

Interacción:
- handleKeyboard(): ↑↓, PgUp/Dn, Home/End
- handleMouseClick(): click en fila selecciona

Características:
- Colores configurables (row_selected, row_selected_unfocus, etc.)
- Focus ring (fancy o simple)
- Clipping para contenido
- Footer muestra "15 de 500+..." → "15 de 1,234"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 12:46:50 +01:00
R.Eugenio
7d1919969f feat(virtual_list): Fase 2 - DataProvider interface + tipos + state
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>
2025-12-23 12:27:23 +01:00
R.Eugenio
59d102315d fix(memory): Deep clone en Row + CellValue para evitar dangling pointers
- 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>
2025-12-22 13:16:59 +01:00
3f442bf8b9 feat(autocomplete): Sistema overlay para dropdowns + mejoras UX
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>
2025-12-20 19:07:44 +01:00
fdda6ba1a4 fix(autocomplete): Cursor igual que TextInput - altura completa + parpadeo
- 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
2025-12-20 17:26:31 +01:00
fc2dc83e6c fix(autocomplete): Sync last_filter en setText/clear + auto-cierre dropdown vacío
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.
2025-12-20 00:13:43 +01:00
f077c87dfc feat(v0.22.2): AutoComplete focus + Text Metrics + cursor 300ms
AutoComplete:
- Integración sistema focus (registerFocusable, requestFocus, hasFocus)
- Fix input: event.char → ctx.input.getTextInput()
- Fix dropdown al iniciar: is_first_frame guard

Text Metrics:
- Nuevo ctx.measureText() y ctx.measureTextToCursor()
- text_measure_fn callback para fuentes TTF
- char_width fallback para bitmap (8px)

Cursor:
- text_input.zig y autocomplete.zig usan métricas reales
- Blink rate: 500ms → 300ms (más responsive)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 20:08:11 +01:00
a377a00803 cleanup: Eliminar prints de debug de investigación fondo azul
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>
2025-12-19 12:51:54 +01:00
3d44631cc3 fix: Eliminar código olvidado en drawRoundedRect que rellenaba área
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>
2025-12-19 12:48:30 +01:00
7d91835fb7 docs: Actualizar CLAUDE.md y CHANGELOG.md v0.21.2
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>
2025-12-18 23:18:55 +01:00
ab63d5a7f8 feat(AdvancedTable): Color selección según focus del panel
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>
2025-12-18 23:04:11 +01:00
3c52d2aa0e docs: Refactorizar CLAUDE.md (1006→354 líneas, -65%)
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>
2025-12-18 22:00:38 +01:00
48ab2b749b feat(advanced_table): BasicColors helper para colores configurables
- 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>
2025-12-18 11:33:34 +01:00
bd95013ffc fix(advanced_table): Teclado funciona - result.selected_row/col
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>
2025-12-17 20:06:17 +01:00
654183c0eb docs: Actualizar CLAUDE.md con bug pendiente AdvancedTable
- 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>
2025-12-17 18:56:51 +01:00
1eed0181d6 docs: Bug teclado AdvancedTable NO RESUELTO
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>
2025-12-17 18:54:05 +01:00
af1bb76aab feat(advanced_table): Multi-select, search, sorting, keyboard fixes
Bugs corregidos:
- Bug 1: Navegación teclado - cambio de keyPressed() a navKeyPressed()
- Bug 2: Sorting real - implementado sortRows() con bubble sort estable

Funcionalidades añadidas de Table:
- Multi-row selection (bit array 1024 rows, Ctrl+click, Shift+click, Ctrl+A)
- Incremental search (type-to-search con timeout 1000ms)
- Cell validation tracking (256 celdas con mensajes de error)

Nuevas funciones en AdvancedTableState:
- isRowSelected, addRowToSelection, removeRowFromSelection
- toggleRowSelection, clearRowSelection, selectAllRows
- selectRowRange, getSelectedRowCount, getSelectedRows, selectSingleRow
- addSearchChar, getSearchTerm, clearSearch, startsWithIgnoreCase
- hasCellError, addCellError, clearCellError, clearAllCellErrors
- hasAnyCellErrors, getLastValidationMessage

Cambios en types.zig:
- CellValue.compare() para ordenación
- allow_multi_select en TableConfig

Tests: 379 passing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 18:34:34 +01:00
3aac03da4a docs: Análisis mejoras AdvancedTable + consideración merge
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>
2025-12-17 18:04:29 +01:00
964523b883 docs: REFERENCE.md - Documentación completa AdvancedTable
- 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>
2025-12-17 17:31:03 +01:00
6287231cee feat: AdvancedTable Fases 7-8 - Lookup & Callbacks
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>
2025-12-17 17:26:53 +01:00
2dccddeab0 feat: Paridad Visual DVUI Fase 3 - Sombras y Gradientes
Nuevas capacidades de rendering:
- ShadowCommand: sombras multi-capa con blur simulado
  - Helpers: shadow(), shadowDrop(), shadowFloat()
  - Quadratic alpha falloff para bordes suaves
- GradientCommand: gradientes suaves pixel a pixel
  - Direcciones: vertical, horizontal, diagonal
  - Helpers: gradientV/H(), gradientButton(), gradientProgress()
  - Soporte esquinas redondeadas

Widgets actualizados:
- Panel/Modal: sombras en fancy mode
- Select/Menu: dropdown con sombra + rounded corners
- Tooltip/Toast: sombra sutil + rounded corners
- Button: gradiente 3D (lighten top, darken bottom)
- Progress: gradientes suaves vs 4 bandas

IMPORTANTE: Compila y pasa tests (370/370) pero NO probado visualmente

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 13:27:48 +01:00
83049a99be feat: AdvancedTable widget - Fases 1-6 IMPLEMENTADO (pendiente aprobacion)
Widget AdvancedTable portado de Go (simifactu-fyne) a Zig.
2,526 LOC en 4 archivos, 370 tests pasan.

Archivos:
- types.zig (369 LOC): CellValue, ColumnType, RowState, TableColors
- schema.zig (373 LOC): ColumnDef, TableSchema, DataStore interface
- state.zig (762 LOC): Selection, editing, dirty tracking, snapshots
- advanced_table.zig (1,022 LOC): Widget, rendering, keyboard

Fases implementadas:
1. Core (types, schema, state)
2. Navigation (arrows, Tab, PgUp/Dn, Home/End, Ctrl+Home/End)
3. Cell Editing (F2/Enter start, Escape cancel, text input)
4. Sorting (header click, visual indicators)
5. Auto-CRUD (CREATE/UPDATE/DELETE detection on row change)
6. Row Operations (Ctrl+N insert, Ctrl+Delete remove)

Fases diferidas (7-8): Lookup & Auto-fill, Callbacks avanzados

ESTADO: Compilado y tests pasan. NO probado en uso real.
REQUIERE: Aprobacion antes de tag de version.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 11:25:48 +01:00
e0d7e99bb6 fix: Corregir nombre de usuario Arno → R.Eugenio
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>
2025-12-17 10:39:22 +01:00
a3c48efbab docs: Actualizar CLAUDE.md a v0.19.0 - Fases 1+2 completas
- 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>
2025-12-17 10:23:40 +01:00
e0cbbf6413 feat: Focus ring AA para todos los widgets focusables
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>
2025-12-17 09:24:50 +01:00
ed0e3e8e5b feat: Focus ring con anti-aliasing
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>
2025-12-17 09:18:53 +01:00
6e1f8b79d7 docs: Actualizar CLAUDE.md con Fase 2 transiciones hover 2025-12-17 01:12:53 +01:00
74e83d2334 feat: Transiciones hover en Select widget
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>
2025-12-17 01:12:21 +01:00
25728c151c feat: Paridad Visual DVUI Fase 2 - transiciones hover/press
HoverTransition helper:
- animation.zig: HoverTransition struct para widgets
- Métodos update(), updateWithPress() para animar hacia target
- blend() y blendThree() para interpolar colores
- Speed configurable (default 0.008/ms = ~125ms transición)

Button con transiciones:
- ButtonState struct opcional para transiciones suaves
- buttonStateful(), buttonStatefulEx(), buttonStatefulRect()
- Mantiene retrocompatibilidad (button() sigue siendo instantáneo)
- Test buttonStateful transitions

Uso:
```zig
var btn_state = button.ButtonState{};
if (button.buttonStateful(&ctx, &btn_state, "Click me")) {
    // clicked
}
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 01:10:58 +01:00
ebad736c75 docs: Actualizar CLAUDE.md - v0.18.0 con paridad visual DVUI Fase 1 2025-12-17 01:03:51 +01:00