diff --git a/src/widgets/advanced_table/advanced_table.zig b/src/widgets/advanced_table/advanced_table.zig index 0026b67..831fa2d 100644 --- a/src/widgets/advanced_table/advanced_table.zig +++ b/src/widgets/advanced_table/advanced_table.zig @@ -28,6 +28,7 @@ pub const SortDirection = types.SortDirection; pub const CRUDAction = types.CRUDAction; pub const ValidationResult = types.ValidationResult; pub const TableColors = types.TableColors; +pub const BasicColors = types.BasicColors; pub const TableConfig = types.TableConfig; pub const Row = types.Row; diff --git a/src/widgets/advanced_table/types.zig b/src/widgets/advanced_table/types.zig index 530bff4..3191255 100644 --- a/src/widgets/advanced_table/types.zig +++ b/src/widgets/advanced_table/types.zig @@ -205,6 +205,41 @@ pub const CRUDAction = enum { // Colors // ============================================================================= +/// Colores básicos para crear un esquema de tabla +/// El consumidor solo necesita especificar 3 colores y el resto se deriva +pub const BasicColors = struct { + /// Color de fondo de las filas + background: Style.Color, + /// Color del texto + foreground: Style.Color, + /// Color de acento (selección, focus, header activo) + accent: Style.Color = Style.Color.rgb(66, 135, 245), + + // Opcionales - si null, se derivan de los básicos + header_bg: ?Style.Color = null, + row_alternate: ?Style.Color = null, + border: ?Style.Color = null, + + /// Convierte cualquier tipo con campos r,g,b (y opcionalmente a) a Style.Color. + /// Útil para convertir desde otros tipos Color (ej: zcatconfig.Color). + /// + /// Ejemplo: + /// ```zig + /// const cfg_color = config.panel_who_list_fondo; // zcatconfig.Color + /// const style_color = BasicColors.toColor(cfg_color); // Style.Color + /// ``` + pub fn toColor(c: anytype) Style.Color { + const T = @TypeOf(c); + const has_alpha = @hasField(T, "a"); + return .{ + .r = c.r, + .g = c.g, + .b = c.b, + .a = if (has_alpha) c.a else 255, + }; + } +}; + /// Color scheme for AdvancedTable pub const TableColors = struct { // Header @@ -246,6 +281,97 @@ pub const TableColors = struct { indicator_modified: Style.Color = Style.Color.rgb(255, 180, 0), // Orange indicator_new: Style.Color = Style.Color.rgb(76, 175, 80), // Green indicator_deleted: Style.Color = Style.Color.rgb(244, 67, 54), // Red + + // ========================================================================= + // Constructores + // ========================================================================= + + /// Crea un esquema de colores completo desde 3 colores básicos. + /// Deriva automáticamente hover, alternate, selected, etc. + /// + /// Ejemplo de uso: + /// ```zig + /// const colors = TableColors.fromBasic(.{ + /// .background = Style.Color.rgb(30, 30, 35), + /// .foreground = Style.Color.rgb(220, 220, 220), + /// .accent = Style.Color.rgb(40, 80, 120), + /// }); + /// ``` + pub fn fromBasic(opts: BasicColors) TableColors { + const bg = opts.background; + const fg = opts.foreground; + const accent = opts.accent; + + // Detectar si es tema oscuro (fondo oscuro) o claro + const is_dark = (bg.r + bg.g + bg.b) < 384; // < 128 promedio + + return .{ + // Header - ligeramente diferente del fondo + .header_bg = opts.header_bg orelse (if (is_dark) bg.darken(10) else bg.darken(5)), + .header_fg = fg, + .header_hover = if (is_dark) bg.lighten(15) else bg.darken(10), + .header_sorted = if (is_dark) bg.lighten(10) else bg.darken(8), + .sort_indicator = accent, + + // Rows + .row_normal = bg, + .row_alternate = opts.row_alternate orelse (if (is_dark) bg.lighten(5) else bg.darken(3)), + .row_hover = if (is_dark) bg.lighten(15) else bg.darken(8), + + // Selection - basada en acento + .selected_cell = accent, + .selected_row = accent.darken(30), + + // States - colores estándar universales + .state_modified = Style.Color.rgb(255, 255, 100), + .state_new = Style.Color.rgb(100, 200, 100), + .state_deleted = Style.Color.rgb(200, 100, 100), + .state_error = Style.Color.rgb(255, 80, 80), + + // Text + .text_normal = fg, + .text_selected = Style.Color.rgb(255, 255, 255), + .text_disabled = if (is_dark) fg.darken(50) else fg.lighten(50), + + // Cell editing + .cell_editing_bg = if (is_dark) bg.lighten(20) else bg.darken(10), + .cell_editing_border = accent, + + // Borders + .border = opts.border orelse (if (is_dark) bg.lighten(20) else bg.darken(15)), + .focus_ring = accent, + + // State indicators + .indicator_modified = Style.Color.rgb(255, 180, 0), + .indicator_new = Style.Color.rgb(76, 175, 80), + .indicator_deleted = Style.Color.rgb(244, 67, 54), + }; + } + + /// Preset de tema oscuro (valores por defecto) + pub fn dark() TableColors { + return .{}; + } + + /// Preset de tema claro + pub fn light() TableColors { + return fromBasic(.{ + .background = Style.Color.rgb(250, 250, 250), + .foreground = Style.Color.rgb(30, 30, 30), + .accent = Style.Color.rgb(66, 135, 245), + }); + } + + /// Crea una copia con un nuevo color de acento + pub fn withAccent(self: TableColors, accent: Style.Color) TableColors { + var result = self; + result.selected_cell = accent; + result.selected_row = accent.darken(30); + result.sort_indicator = accent; + result.cell_editing_border = accent; + result.focus_ring = accent; + return result; + } }; // =============================================================================