From 253c9b24490b62348c7932338de0417f2cf9432d Mon Sep 17 00:00:00 2001 From: reugenio Date: Sat, 27 Dec 2025 19:47:32 +0100 Subject: [PATCH] refactor(tables): FASE 5 - Embeber NavigationState en AdvancedTableState y VirtualAdvancedTableState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Añadido nav: table_core.NavigationState en ambos estados - Eliminados campos duplicados (scroll_row, scroll_x, active_col, double_click) - Actualizado todas las referencias a usar nav.* - Conservado scroll_offset_pixels en Virtual (específico smooth scroll) --- src/widgets/advanced_table/advanced_table.zig | 38 ++++---- src/widgets/advanced_table/state.zig | 88 ++++++++++++----- src/widgets/virtual_advanced_table/state.zig | 94 ++++++++----------- .../virtual_advanced_table.zig | 45 ++++----- 4 files changed, 142 insertions(+), 123 deletions(-) diff --git a/src/widgets/advanced_table/advanced_table.zig b/src/widgets/advanced_table/advanced_table.zig index 7614082..6175ad2 100644 --- a/src/widgets/advanced_table/advanced_table.zig +++ b/src/widgets/advanced_table/advanced_table.zig @@ -119,7 +119,7 @@ pub fn advancedTableRect( // Check if we have focus const has_focus = ctx.hasFocus(widget_id); - table_state.focused = has_focus; + table_state.nav.has_focus = has_focus; // Calculate dimensions const state_col_w: u32 = if (config.show_row_state_indicators) config.state_indicator_width else 0; @@ -136,7 +136,7 @@ pub fn advancedTableRect( } // Calculate visible row range - const first_visible = table_state.scroll_row; + const first_visible = table_state.nav.scroll_row; const last_visible = @min(first_visible + visible_rows, table_state.getRowCount()); // Manejar clicks en filas (separado del renderizado) @@ -359,10 +359,10 @@ fn handleRowClicks( // Detectar doble-click const current_time = ctx.current_time_ms; - const same_cell = table_state.last_click_row == @as(i32, @intCast(row_idx)) and - table_state.last_click_col == @as(i32, @intCast(col_idx)); - const time_diff = current_time -| table_state.last_click_time; - const is_double_click = same_cell and time_diff < table_state.double_click_threshold_ms; + const same_cell = table_state.nav.double_click.last_click_row == @as(i32, @intCast(row_idx)) and + table_state.nav.double_click.last_click_col == @as(i32, @intCast(col_idx)); + const time_diff = current_time -| table_state.nav.double_click.last_click_time; + const is_double_click = same_cell and time_diff < table_state.nav.double_click.threshold_ms; if (is_double_click and config.allow_edit and col_idx < table_schema.columns.len and table_schema.columns[col_idx].editable and !table_state.isEditing()) @@ -377,9 +377,9 @@ fn handleRowClicks( result.edit_started = true; } // Reset click tracking - table_state.last_click_time = 0; - table_state.last_click_row = -1; - table_state.last_click_col = -1; + table_state.nav.double_click.last_click_time = 0; + table_state.nav.double_click.last_click_row = -1; + table_state.nav.double_click.last_click_col = -1; } else { // Single click: seleccionar celda if (!is_selected_cell) { @@ -389,9 +389,9 @@ fn handleRowClicks( result.selected_col = col_idx; } // Actualizar tracking para posible doble-click - table_state.last_click_time = current_time; - table_state.last_click_row = @intCast(row_idx); - table_state.last_click_col = @intCast(col_idx); + table_state.nav.double_click.last_click_time = current_time; + table_state.nav.double_click.last_click_row = @intCast(row_idx); + table_state.nav.double_click.last_click_col = @intCast(col_idx); } } @@ -515,7 +515,7 @@ fn drawScrollbar( const thumb_ratio = @as(f32, @floatFromInt(visible_rows)) / @as(f32, @floatFromInt(total_rows)); const thumb_h = @max(20, @as(u32, @intFromFloat(@as(f32, @floatFromInt(scrollbar_h)) * thumb_ratio))); - const scroll_ratio = @as(f32, @floatFromInt(table_state.scroll_row)) / + const scroll_ratio = @as(f32, @floatFromInt(table_state.nav.scroll_row)) / @as(f32, @floatFromInt(@max(1, total_rows - visible_rows))); const thumb_y_offset = @as(u32, @intFromFloat(scroll_ratio * @as(f32, @floatFromInt(scrollbar_h - thumb_h)))); @@ -544,8 +544,8 @@ fn drawEditingOverlay( const config = table_schema.config; // Check if row is visible - if (row_idx < table_state.scroll_row) return; - const visible_row = row_idx - table_state.scroll_row; + if (row_idx < table_state.nav.scroll_row) return; + const visible_row = row_idx - table_state.nav.scroll_row; const visible_rows = (bounds.h -| header_h) / config.row_height; if (visible_row >= visible_rows) return; @@ -1178,10 +1178,10 @@ fn ensureSelectionVisible(table_state: *AdvancedTableState, visible_rows: usize) const row: usize = @intCast(table_state.selected_row); // Scroll to show selected row - if (row < table_state.scroll_row) { - table_state.scroll_row = row; - } else if (row >= table_state.scroll_row + visible_rows) { - table_state.scroll_row = row - visible_rows + 1; + if (row < table_state.nav.scroll_row) { + table_state.nav.scroll_row = row; + } else if (row >= table_state.nav.scroll_row + visible_rows) { + table_state.nav.scroll_row = row - visible_rows + 1; } } diff --git a/src/widgets/advanced_table/state.zig b/src/widgets/advanced_table/state.zig index 74c5f1d..c615c63 100644 --- a/src/widgets/advanced_table/state.zig +++ b/src/widgets/advanced_table/state.zig @@ -101,20 +101,16 @@ pub const AdvancedTableState = struct { original_value: ?CellValue = null, // ========================================================================= - // Double-click detection + // Navegación (usa NavigationState de table_core para composición) // ========================================================================= - /// Time of last click (ms) - last_click_time: u64 = 0, + /// Estado de navegación embebido (FASE 5 refactor) + /// Incluye: active_col, scroll_row, scroll_x, has_focus, double_click + nav: table_core.NavigationState = .{}, - /// Row of last click - last_click_row: i32 = -1, - - /// Column of last click - last_click_col: i32 = -1, - - /// Double-click threshold in ms - double_click_threshold_ms: u64 = 400, + // Aliases para backwards compatibility: + // - scroll_row → nav.scroll_row (acceso directo abajo) + // - double_click_* → nav.double_click.* (acceso directo abajo) // ========================================================================= // Sorting @@ -133,14 +129,9 @@ pub const AdvancedTableState = struct { has_original_order: bool = false, // ========================================================================= - // Scrolling + // Scrolling (delegado a nav - ver NavigationState) // ========================================================================= - - /// First visible row - scroll_row: usize = 0, - - /// Horizontal scroll offset (in pixels) - scroll_x: usize = 0, + // scroll_row y scroll_x ahora están en nav.scroll_row y nav.scroll_x // ========================================================================= // State Maps (sparse - only modified rows) @@ -165,13 +156,6 @@ pub const AdvancedTableState = struct { /// Row snapshots captured when entering row row_snapshots: std.AutoHashMap(usize, Row), - // ========================================================================= - // Focus - // ========================================================================= - - /// Does this table have focus - focused: bool = false, - // ========================================================================= // Callbacks & Debounce (Phase 8) // ========================================================================= @@ -182,6 +166,60 @@ pub const AdvancedTableState = struct { /// Last row that triggered on_active_row_changed (to avoid duplicate calls) last_notified_row: i32 = -1, + // ========================================================================= + // Propiedades de compatibilidad (FASE 5 - delegación a nav) + // ========================================================================= + + /// Alias para nav.scroll_row (backwards compatibility) + pub fn getScrollRow(self: *const AdvancedTableState) usize { + return self.nav.scroll_row; + } + + pub fn setScrollRow(self: *AdvancedTableState, row: usize) void { + self.nav.scroll_row = row; + } + + /// Alias para nav.has_focus (backwards compatibility) + pub fn hasFocus(self: *const AdvancedTableState) bool { + return self.nav.has_focus; + } + + pub fn setFocus(self: *AdvancedTableState, focused: bool) void { + self.nav.has_focus = focused; + } + + /// Double-click: último tiempo de click + pub fn getLastClickTime(self: *const AdvancedTableState) u64 { + return self.nav.double_click.last_click_time; + } + + pub fn setLastClickTime(self: *AdvancedTableState, time: u64) void { + self.nav.double_click.last_click_time = time; + } + + /// Double-click: última fila clickeada + pub fn getLastClickRow(self: *const AdvancedTableState) i64 { + return self.nav.double_click.last_click_row; + } + + pub fn setLastClickRow(self: *AdvancedTableState, row: i64) void { + self.nav.double_click.last_click_row = row; + } + + /// Double-click: última columna clickeada + pub fn getLastClickCol(self: *const AdvancedTableState) i32 { + return self.nav.double_click.last_click_col; + } + + pub fn setLastClickCol(self: *AdvancedTableState, col: i32) void { + self.nav.double_click.last_click_col = col; + } + + /// Double-click: threshold en ms + pub fn getDoubleClickThreshold(self: *const AdvancedTableState) u64 { + return self.nav.double_click.threshold_ms; + } + // ========================================================================= // Lifecycle // ========================================================================= diff --git a/src/widgets/virtual_advanced_table/state.zig b/src/widgets/virtual_advanced_table/state.zig index 95d7e0d..faa4d4c 100644 --- a/src/widgets/virtual_advanced_table/state.zig +++ b/src/widgets/virtual_advanced_table/state.zig @@ -24,39 +24,27 @@ pub const VirtualAdvancedTableState = struct { /// Índice de la fila con hover hover_index: ?usize = null, - /// Columna activa (para edición) - /// Cuando el usuario navega con flechas o hace click, se actualiza - active_col: usize = 0, - // ========================================================================= - // Double-click detection + // Navegación (usa NavigationState de table_core para composición) // ========================================================================= - /// Time of last click (ms) - last_click_time: u64 = 0, + /// Estado de navegación embebido (FASE 5 refactor) + /// Incluye: active_col, scroll_row (como scroll_offset), scroll_x, double_click + nav: table_core.NavigationState = .{}, - /// Row of last click (global index) - last_click_row: i64 = -1, - - /// Column of last click - last_click_col: i32 = -1, - - /// Double-click threshold in ms - double_click_threshold_ms: u64 = 400, + // Aliases: + // - active_col → nav.active_col + // - scroll_offset → nav.scroll_row + // - scroll_offset_x → nav.scroll_x + // - last_click_* → nav.double_click.* // ========================================================================= - // Scroll y ventana + // Scroll adicional (específico de Virtual - smooth scroll) // ========================================================================= - /// Offset actual del scroll vertical (en filas, no pixels) - scroll_offset: usize = 0, - /// Offset del scroll en pixels (para smooth scroll vertical) scroll_offset_pixels: i32 = 0, - /// Offset del scroll horizontal (en pixels) - scroll_offset_x: i32 = 0, - /// Ventana de datos actual (propiedad del DataProvider) /// NO liberar - el provider lo gestiona current_window: []const RowData = &.{}, @@ -350,7 +338,7 @@ pub const VirtualAdvancedTableState = struct { /// Mueve la selección hacia arriba pub fn moveUp(self: *Self) void { - const window_offset = self.scroll_offset -| self.window_start; + const window_offset = self.nav.scroll_row -| self.window_start; if (self.findSelectedInWindow()) |window_idx| { // Calcular posición en pantalla actual @@ -361,14 +349,14 @@ pub const VirtualAdvancedTableState = struct { self.selectByWindowIndex(window_idx - 1); // Si estábamos en la primera fila visible, hacer scroll - if (screen_pos == 0 and self.scroll_offset > 0) { - self.scroll_offset -= 1; + if (screen_pos == 0 and self.nav.scroll_row > 0) { + self.nav.scroll_row -= 1; } } else { // Estamos en el inicio del buffer // Scroll up para cargar más datos (si es posible) - if (self.scroll_offset > 0) { - self.scroll_offset -= 1; + if (self.nav.scroll_row > 0) { + self.nav.scroll_row -= 1; } } } else if (self.current_window.len > 0) { @@ -384,13 +372,13 @@ pub const VirtualAdvancedTableState = struct { self.selectByWindowIndex(window_idx + 1); // Calcular posición en pantalla de la nueva selección - const window_offset = self.scroll_offset -| self.window_start; + const window_offset = self.nav.scroll_row -| self.window_start; const new_screen_pos = (window_idx + 1) -| window_offset; // Scroll cuando la nueva posición llega a la ÚLTIMA fila visible // (visible_rows - 1 es el índice de la última fila, 0-indexed) if (new_screen_pos >= visible_rows) { - self.scroll_offset += 1; + self.nav.scroll_row += 1; } } } else if (self.current_window.len > 0) { @@ -401,22 +389,22 @@ pub const VirtualAdvancedTableState = struct { /// Mueve página arriba pub fn pageUp(self: *Self, visible_rows: usize) void { - if (self.scroll_offset >= visible_rows) { - self.scroll_offset -= visible_rows; + if (self.nav.scroll_row >= visible_rows) { + self.nav.scroll_row -= visible_rows; } else { - self.scroll_offset = 0; + self.nav.scroll_row = 0; } } /// Mueve página abajo pub fn pageDown(self: *Self, visible_rows: usize, total_rows: usize) void { const max_offset = if (total_rows > visible_rows) total_rows - visible_rows else 0; - self.scroll_offset = @min(self.scroll_offset + visible_rows, max_offset); + self.nav.scroll_row = @min(self.nav.scroll_row + visible_rows, max_offset); } /// Va al inicio pub fn goToStart(self: *Self) void { - self.scroll_offset = 0; + self.nav.scroll_row = 0; if (self.current_window.len > 0) { self.selectByWindowIndex(0); } @@ -425,7 +413,7 @@ pub const VirtualAdvancedTableState = struct { /// Va al final pub fn goToEnd(self: *Self, visible_rows: usize, total_rows: usize) void { if (total_rows > visible_rows) { - self.scroll_offset = total_rows - visible_rows; + self.nav.scroll_row = total_rows - visible_rows; } if (self.current_window.len > 0) { self.selectByWindowIndex(self.current_window.len - 1); @@ -444,47 +432,47 @@ pub const VirtualAdvancedTableState = struct { /// Scroll horizontal a la izquierda pub fn scrollLeft(self: *Self, amount: i32) void { - self.scroll_offset_x = @max(0, self.scroll_offset_x - amount); + self.nav.scroll_x = @max(0, self.nav.scroll_x - amount); } /// Scroll horizontal a la derecha pub fn scrollRight(self: *Self, amount: i32, max_scroll: i32) void { - self.scroll_offset_x = @min(max_scroll, self.scroll_offset_x + amount); + self.nav.scroll_x = @min(max_scroll, self.nav.scroll_x + amount); } /// Va al inicio horizontal pub fn goToStartX(self: *Self) void { - self.scroll_offset_x = 0; + self.nav.scroll_x = 0; } /// Va al final horizontal pub fn goToEndX(self: *Self, max_scroll: i32) void { - self.scroll_offset_x = max_scroll; + self.nav.scroll_x = max_scroll; } /// Mueve a columna anterior pub fn moveToPrevCol(self: *Self) void { - if (self.active_col > 0) { - self.active_col -= 1; + if (self.nav.active_col > 0) { + self.nav.active_col -= 1; } } /// Mueve a columna siguiente pub fn moveToNextCol(self: *Self, max_cols: usize) void { - if (self.active_col + 1 < max_cols) { - self.active_col += 1; + if (self.nav.active_col + 1 < max_cols) { + self.nav.active_col += 1; } } /// Va a primera columna pub fn goToFirstCol(self: *Self) void { - self.active_col = 0; + self.nav.active_col = 0; } /// Va a última columna pub fn goToLastCol(self: *Self, max_cols: usize) void { if (max_cols > 0) { - self.active_col = max_cols - 1; + self.nav.active_col = max_cols - 1; } } @@ -505,10 +493,10 @@ pub const VirtualAdvancedTableState = struct { const total_rows = self.current_window.len + self.window_start; // Usar función de table_core - const pos = table_core.calculateNextCell(current_row, self.active_col, num_cols, total_rows, wrap_to_start); + const pos = table_core.calculateNextCell(current_row, self.nav.active_col, num_cols, total_rows, wrap_to_start); if (pos.result == .navigated) { - self.active_col = pos.col; + self.nav.active_col = pos.col; // Navegar a la nueva fila si cambió if (pos.row != current_row) { if (pos.row == 0) { @@ -530,10 +518,10 @@ pub const VirtualAdvancedTableState = struct { const current_row = self.getSelectedRow() orelse 0; // Usar función de table_core - const pos = table_core.calculatePrevCell(current_row, self.active_col, num_cols, total_rows, wrap_to_end); + const pos = table_core.calculatePrevCell(current_row, self.nav.active_col, num_cols, total_rows, wrap_to_end); if (pos.result == .navigated) { - self.active_col = pos.col; + self.nav.active_col = pos.col; // Navegar a la nueva fila si cambió if (pos.row != current_row) { if (pos.row == total_rows - 1) { @@ -561,7 +549,7 @@ pub const VirtualAdvancedTableState = struct { /// Obtiene la celda activa (fila seleccionada + columna activa) pub fn getActiveCell(self: *const Self) ?CellId { if (self.getSelectedRow()) |row| { - return .{ .row = row, .col = self.active_col }; + return .{ .row = row, .col = self.nav.active_col }; } return null; } @@ -701,8 +689,8 @@ pub const VirtualAdvancedTableState = struct { filter_bar_height: u32, ) ?CellGeometry { // Verificar si la fila está en la ventana visible - if (row < self.scroll_offset) return null; - const visible_row = row - self.scroll_offset; + if (row < self.nav.scroll_row) return null; + const visible_row = row - self.nav.scroll_row; // Calcular Y (después de filter bar + header) const content_start_y = bounds_y + @as(i32, @intCast(filter_bar_height)) + @as(i32, @intCast(header_height)); @@ -712,7 +700,7 @@ pub const VirtualAdvancedTableState = struct { if (col >= columns.len) return null; // Calcular X (sumando anchos de columnas anteriores, menos scroll horizontal) - var x: i32 = bounds_x - self.scroll_offset_x; + var x: i32 = bounds_x - self.nav.scroll_x; for (columns[0..col]) |c| { x += @as(i32, @intCast(c.width)); } diff --git a/src/widgets/virtual_advanced_table/virtual_advanced_table.zig b/src/widgets/virtual_advanced_table/virtual_advanced_table.zig index 15d4711..be9e565 100644 --- a/src/widgets/virtual_advanced_table/virtual_advanced_table.zig +++ b/src/widgets/virtual_advanced_table/virtual_advanced_table.zig @@ -209,8 +209,8 @@ pub fn virtualAdvancedTableRect( const max_scroll_x: i32 = @max(0, @as(i32, @intCast(total_columns_width)) - @as(i32, @intCast(available_width))); // Clamp current scroll_offset_x - if (list_state.scroll_offset_x > max_scroll_x) { - list_state.scroll_offset_x = max_scroll_x; + if (list_state.nav.scroll_x > max_scroll_x) { + list_state.nav.scroll_x = max_scroll_x; } // Calculate FilterBar height @@ -228,9 +228,9 @@ pub fn virtualAdvancedTableRect( // Fetch window if needed if (needs_refetch) { - if (provider.fetchWindow(list_state.scroll_offset, buffer_size)) |window| { + if (provider.fetchWindow(list_state.nav.scroll_row, buffer_size)) |window| { list_state.current_window = window; - list_state.window_start = list_state.scroll_offset; + list_state.window_start = list_state.nav.scroll_row; } else |_| { // Error fetching - keep current window } @@ -258,7 +258,7 @@ pub fn virtualAdvancedTableRect( const header_y = bounds.y + @as(i32, @intCast(filter_bar_h)); // Draw header (with horizontal scroll offset) - drawHeaderAt(ctx, bounds, header_y, config, &colors, list_state, &result, list_state.scroll_offset_x); + drawHeaderAt(ctx, bounds, header_y, config, &colors, list_state, &result, list_state.nav.scroll_x); // Draw visible rows const content_bounds = Layout.Rect.init( @@ -277,7 +277,7 @@ pub fn virtualAdvancedTableRect( colors.row_normal, )); - drawRows(ctx, content_bounds, config, &colors, list_state, visible_rows, &result, list_state.scroll_offset_x); + drawRows(ctx, content_bounds, config, &colors, list_state, visible_rows, &result, list_state.nav.scroll_x); // Draw CellEditor overlay if editing if (list_state.isEditing()) { @@ -357,7 +357,7 @@ pub fn virtualAdvancedTableRect( // Draw horizontal scrollbar if needed if (needs_h_scroll and config.show_scrollbar) { - drawScrollbarH(ctx, bounds, footer_h, scrollbar_h_h, list_state.scroll_offset_x, max_scroll_x, available_width, &colors); + drawScrollbarH(ctx, bounds, footer_h, scrollbar_h_h, list_state.nav.scroll_x, max_scroll_x, available_width, &colors); } // Draw border around the entire list (always visible) @@ -441,7 +441,7 @@ fn needsRefetch(list_state: *VirtualAdvancedTableState, visible_rows: usize, buf if (list_state.current_window.len == 0) return true; // Check if scroll is outside current window - const scroll = list_state.scroll_offset; + const scroll = list_state.nav.scroll_row; const window_end = list_state.window_start + list_state.current_window.len; // Refetch if scroll is near edges of window @@ -793,9 +793,9 @@ fn drawRows( -1; // Calcular rango de filas a dibujar - const first_row = list_state.scroll_offset; + const first_row = list_state.nav.scroll_row; const last_row = @min( - list_state.scroll_offset + visible_rows, + list_state.nav.scroll_row + visible_rows, list_state.window_start + list_state.current_window.len, ); @@ -841,7 +841,7 @@ fn drawRows( .alternating_rows = true, .has_focus = list_state.has_focus, .selected_row = selected_row, - .active_col = list_state.active_col, + .active_col = list_state.nav.active_col, .colors = render_colors, .columns = render_cols[0..num_cols], }, @@ -923,7 +923,7 @@ fn drawScrollbar( const visible_ratio = @as(f32, @floatFromInt(visible_rows)) / @as(f32, @floatFromInt(total_rows)); const thumb_h = @max(20, @as(u32, @intFromFloat(visible_ratio * @as(f32, @floatFromInt(content_h))))); - const scroll_ratio = @as(f32, @floatFromInt(list_state.scroll_offset)) / + const scroll_ratio = @as(f32, @floatFromInt(list_state.nav.scroll_row)) / @as(f32, @floatFromInt(@max(1, total_rows - visible_rows))); const thumb_y = track_y + @as(i32, @intFromFloat(scroll_ratio * @as(f32, @floatFromInt(content_h - thumb_h)))); @@ -1093,15 +1093,15 @@ fn handleMouseClick( const screen_row = @as(usize, @intCast(relative_y)) / config.row_height; // Convert screen row to buffer index (accounting for scroll) - const window_offset = list_state.scroll_offset -| list_state.window_start; + const window_offset = list_state.nav.scroll_row -| list_state.window_start; const data_idx = window_offset + screen_row; if (data_idx < list_state.current_window.len) { - const global_row = list_state.scroll_offset + screen_row; + const global_row = list_state.nav.scroll_row + screen_row; // Detect which column was clicked var clicked_col: usize = 0; - const relative_x = mouse.x - bounds.x + list_state.scroll_offset_x; + const relative_x = mouse.x - bounds.x + list_state.nav.scroll_x; var col_start: i32 = 0; for (config.columns, 0..) |col, col_idx| { const col_end = col_start + @as(i32, @intCast(col.width)); @@ -1112,13 +1112,8 @@ fn handleMouseClick( col_start = col_end; } - // Double-click detection using table_core - var dc_state = table_core.DoubleClickState{ - .last_click_time = list_state.last_click_time, - .last_click_row = list_state.last_click_row, - .last_click_col = list_state.last_click_col, - .threshold_ms = list_state.double_click_threshold_ms, - }; + // Double-click detection using embedded nav.double_click + var dc_state = list_state.nav.double_click; const is_double_click = table_core.detectDoubleClick( &dc_state, @@ -1128,9 +1123,7 @@ fn handleMouseClick( ); // Update state from detection - list_state.last_click_time = dc_state.last_click_time; - list_state.last_click_row = dc_state.last_click_row; - list_state.last_click_col = dc_state.last_click_col; + list_state.nav.double_click = dc_state; if (is_double_click and !list_state.isEditing()) { // Double-click: start editing @@ -1143,7 +1136,7 @@ fn handleMouseClick( } else { // Single click: select list_state.selectById(list_state.current_window[data_idx].id); - list_state.active_col = clicked_col; + list_state.nav.active_col = clicked_col; } } }