refactor(icon): Modularizar en carpeta (805→515 LOC hub, -36%)

This commit is contained in:
reugenio 2025-12-29 11:41:24 +01:00
parent 50a6d3ca60
commit 1ae07812bd
7 changed files with 758 additions and 809 deletions

View file

@ -9,7 +9,7 @@ const Command = @import("../core/command.zig");
const Layout = @import("../core/layout.zig"); const Layout = @import("../core/layout.zig");
const Style = @import("../core/style.zig"); const Style = @import("../core/style.zig");
const Input = @import("../core/input.zig"); const Input = @import("../core/input.zig");
const icon_module = @import("icon.zig"); const icon_module = @import("icon/icon.zig");
const iconbutton = @import("iconbutton.zig"); const iconbutton = @import("iconbutton.zig");
/// AppBar position /// AppBar position

View file

@ -0,0 +1,93 @@
//! Icon - Helpers de dibujo
//!
//! Funciones para dibujar líneas y círculos con grosor.
const Context = @import("../../core/context.zig").Context;
const Command = @import("../../core/command.zig");
const Style = @import("../../core/style.zig");
// =============================================================================
// Drawing Helpers
// =============================================================================
/// Draw a line with thickness
pub fn drawLine(ctx: *Context, x1: i32, y1: i32, x2: i32, y2: i32, thickness: u32, color: Style.Color) void {
if (thickness <= 1) {
ctx.pushCommand(Command.line(x1, y1, x2, y2, color));
} else {
const dx = x2 - x1;
const dy = y2 - y1;
const len = @sqrt(@as(f32, @floatFromInt(dx * dx + dy * dy)));
if (len < 1) {
ctx.pushCommand(Command.rect(x1, y1, thickness, thickness, color));
return;
}
const nx = -@as(f32, @floatFromInt(dy)) / len;
const ny = @as(f32, @floatFromInt(dx)) / len;
const half = @as(f32, @floatFromInt(thickness)) / 2.0;
var offset: f32 = -half;
while (offset < half) : (offset += 1.0) {
const ox = @as(i32, @intFromFloat(nx * offset));
const oy = @as(i32, @intFromFloat(ny * offset));
ctx.pushCommand(Command.line(x1 + ox, y1 + oy, x2 + ox, y2 + oy, color));
}
}
}
/// Fill a circle
pub fn fillCircle(ctx: *Context, cx: i32, cy: i32, radius: u32, color: Style.Color) void {
if (radius == 0) {
ctx.pushCommand(Command.rect(cx, cy, 1, 1, color));
return;
}
const r = @as(i32, @intCast(radius));
var dy: i32 = -r;
while (dy <= r) : (dy += 1) {
const dy_f = @as(f32, @floatFromInt(dy));
const r_f = @as(f32, @floatFromInt(r));
const dx = @as(i32, @intFromFloat(@sqrt(r_f * r_f - dy_f * dy_f)));
ctx.pushCommand(Command.rect(cx - dx, cy + dy, @intCast(dx * 2 + 1), 1, color));
}
}
/// Stroke a circle
pub fn strokeCircle(ctx: *Context, cx: i32, cy: i32, radius: u32, thickness: u32, color: Style.Color) void {
if (radius == 0) return;
const r = @as(i32, @intCast(radius));
var px: i32 = 0;
var py: i32 = r;
var d: i32 = 3 - 2 * r;
while (px <= py) {
setPixelThick(ctx, cx + px, cy + py, thickness, color);
setPixelThick(ctx, cx - px, cy + py, thickness, color);
setPixelThick(ctx, cx + px, cy - py, thickness, color);
setPixelThick(ctx, cx - px, cy - py, thickness, color);
setPixelThick(ctx, cx + py, cy + px, thickness, color);
setPixelThick(ctx, cx - py, cy + px, thickness, color);
setPixelThick(ctx, cx + py, cy - px, thickness, color);
setPixelThick(ctx, cx - py, cy - px, thickness, color);
if (d < 0) {
d = d + 4 * px + 6;
} else {
d = d + 4 * (px - py) + 10;
py -= 1;
}
px += 1;
}
}
fn setPixelThick(ctx: *Context, pixel_x: i32, pixel_y: i32, thickness: u32, color: Style.Color) void {
if (thickness <= 1) {
ctx.pushCommand(Command.rect(pixel_x, pixel_y, 1, 1, color));
} else {
const half = @as(i32, @intCast(thickness / 2));
ctx.pushCommand(Command.rect(pixel_x - half, pixel_y - half, thickness, thickness, color));
}
}

View file

@ -2,137 +2,34 @@
//! //!
//! A lightweight icon system using simple vector drawing. //! A lightweight icon system using simple vector drawing.
//! Icons are defined as draw commands for resolution independence. //! Icons are defined as draw commands for resolution independence.
//!
//! ## Estructura modular
//!
//! - types.zig: Size, IconType, Config, Colors
//! - drawing_helpers.zig: drawLine, fillCircle, strokeCircle
//! - icon.zig: Hub principal (este archivo)
const std = @import("std"); const std = @import("std");
const Context = @import("../core/context.zig").Context; const Context = @import("../../core/context.zig").Context;
const Command = @import("../core/command.zig"); const Command = @import("../../core/command.zig");
const Layout = @import("../core/layout.zig"); const Layout = @import("../../core/layout.zig");
const Style = @import("../core/style.zig"); const Style = @import("../../core/style.zig");
/// Icon size presets // Re-exports desde módulos
pub const Size = enum { pub const types = @import("types.zig");
small, // 12x12 pub const Size = types.Size;
medium, // 16x16 pub const IconType = types.IconType;
large, // 24x24 pub const Config = types.Config;
xlarge, // 32x32 pub const Colors = types.Colors;
pub fn pixels(self: Size) u32 { const helpers = @import("drawing_helpers.zig");
return switch (self) { const drawLine = helpers.drawLine;
.small => 12, const fillCircle = helpers.fillCircle;
.medium => 16, const strokeCircle = helpers.strokeCircle;
.large => 24,
.xlarge => 32,
};
}
};
/// Built-in icon types // =============================================================================
pub const IconType = enum { // Public API
// Navigation // =============================================================================
arrow_up,
arrow_down,
arrow_left,
arrow_right,
chevron_up,
chevron_down,
chevron_left,
chevron_right,
home,
menu,
more_horizontal,
more_vertical,
// Actions
check,
close,
plus,
minus,
edit,
delete,
refresh,
search,
settings,
filter,
sort,
copy,
paste,
cut,
undo,
redo,
// Files
file,
folder,
folder_open,
document,
image_file,
download,
upload,
save,
// Status
info,
warning,
error_icon,
success,
question,
star,
star_filled,
heart,
heart_filled,
// UI elements
eye,
eye_off,
lock,
unlock,
user,
users,
calendar,
clock,
bell,
mail,
// Media
play,
pause,
stop,
volume,
volume_off,
// Misc
grip,
drag,
expand,
collapse,
maximize,
minimize,
external_link,
};
/// Icon configuration
pub const Config = struct {
/// Icon size
size: Size = .medium,
/// Custom size (overrides size preset)
custom_size: ?u32 = null,
/// Stroke width
stroke_width: u32 = 2,
/// Fill icon
filled: bool = false,
};
/// Icon colors
pub const Colors = struct {
foreground: Style.Color = Style.Color.rgba(220, 220, 220, 255),
background: ?Style.Color = null,
pub fn fromTheme(theme: Style.Theme) Colors {
return .{
.foreground = theme.foreground,
};
}
};
/// Draw an icon /// Draw an icon
pub fn icon(ctx: *Context, icon_type: IconType) void { pub fn icon(ctx: *Context, icon_type: IconType) void {
@ -171,7 +68,7 @@ pub fn iconRect(
const s: i32 = @intCast(size); const s: i32 = @intCast(size);
const sw = config.stroke_width; const sw = config.stroke_width;
// Pre-calculated divisions to avoid runtime @divTrunc issues // Pre-calculated divisions
const s2 = @divTrunc(s, 2); const s2 = @divTrunc(s, 2);
const s3 = @divTrunc(s, 3); const s3 = @divTrunc(s, 3);
const s4 = @divTrunc(s, 4); const s4 = @divTrunc(s, 4);
@ -184,7 +81,6 @@ pub fn iconRect(
// Draw icon based on type // Draw icon based on type
switch (icon_type) { switch (icon_type) {
// Arrows
.arrow_up => { .arrow_up => {
drawLine(ctx, x + s2, y + 2, x + 2, y + s - 4, sw, fg); drawLine(ctx, x + s2, y + 2, x + 2, y + s - 4, sw, fg);
drawLine(ctx, x + s2, y + 2, x + s - 2, y + s - 4, sw, fg); drawLine(ctx, x + s2, y + 2, x + s - 2, y + s - 4, sw, fg);
@ -205,8 +101,6 @@ pub fn iconRect(
drawLine(ctx, x + s - 2, y + s2, x + 4, y + s - 2, sw, fg); drawLine(ctx, x + s - 2, y + s2, x + 4, y + s - 2, sw, fg);
drawLine(ctx, x + s - 2, y + s2, x + 2, y + s2, sw, fg); drawLine(ctx, x + s - 2, y + s2, x + 2, y + s2, sw, fg);
}, },
// Chevrons
.chevron_up => { .chevron_up => {
drawLine(ctx, x + 2, y + s23, x + s2, y + s3, sw, fg); drawLine(ctx, x + 2, y + s23, x + s2, y + s3, sw, fg);
drawLine(ctx, x + s2, y + s3, x + s - 2, y + s23, sw, fg); drawLine(ctx, x + s2, y + s3, x + s - 2, y + s23, sw, fg);
@ -223,8 +117,6 @@ pub fn iconRect(
drawLine(ctx, x + s3, y + 2, x + s23, y + s2, sw, fg); drawLine(ctx, x + s3, y + 2, x + s23, y + s2, sw, fg);
drawLine(ctx, x + s23, y + s2, x + s3, y + s - 2, sw, fg); drawLine(ctx, x + s23, y + s2, x + s3, y + s - 2, sw, fg);
}, },
// Actions
.check => { .check => {
drawLine(ctx, x + 2, y + s2, x + s3, y + s - 4, sw, fg); drawLine(ctx, x + 2, y + s2, x + s3, y + s - 4, sw, fg);
drawLine(ctx, x + s3, y + s - 4, x + s - 2, y + 3, sw, fg); drawLine(ctx, x + s3, y + s - 4, x + s - 2, y + 3, sw, fg);
@ -240,8 +132,6 @@ pub fn iconRect(
.minus => { .minus => {
drawLine(ctx, x + 3, y + s2, x + s - 3, y + s2, sw, fg); drawLine(ctx, x + 3, y + s2, x + s - 3, y + s2, sw, fg);
}, },
// Home
.home => { .home => {
drawLine(ctx, x + 2, y + s2, x + s2, y + 2, sw, fg); drawLine(ctx, x + 2, y + s2, x + s2, y + 2, sw, fg);
drawLine(ctx, x + s2, y + 2, x + s - 2, y + s2, sw, fg); drawLine(ctx, x + s2, y + 2, x + s - 2, y + s2, sw, fg);
@ -249,8 +139,6 @@ pub fn iconRect(
drawLine(ctx, x + s - 3, y + s2, x + s - 3, y + s - 2, sw, fg); drawLine(ctx, x + s - 3, y + s2, x + s - 3, y + s - 2, sw, fg);
drawLine(ctx, x + 3, y + s - 2, x + s - 3, y + s - 2, sw, fg); drawLine(ctx, x + 3, y + s - 2, x + s - 3, y + s - 2, sw, fg);
}, },
// Menu
.menu => { .menu => {
const bar_y1 = y + s4; const bar_y1 = y + s4;
const bar_y2 = y + s2; const bar_y2 = y + s2;
@ -259,8 +147,6 @@ pub fn iconRect(
drawLine(ctx, x + 2, bar_y2, x + s - 2, bar_y2, sw, fg); drawLine(ctx, x + 2, bar_y2, x + s - 2, bar_y2, sw, fg);
drawLine(ctx, x + 2, bar_y3, x + s - 2, bar_y3, sw, fg); drawLine(ctx, x + 2, bar_y3, x + s - 2, bar_y3, sw, fg);
}, },
// More (dots)
.more_horizontal => { .more_horizontal => {
const dot_r: u32 = @max(2, @as(u32, @intCast(s6))); const dot_r: u32 = @max(2, @as(u32, @intCast(s6)));
fillCircle(ctx, x + s4, y + s2, dot_r, fg); fillCircle(ctx, x + s4, y + s2, dot_r, fg);
@ -273,15 +159,11 @@ pub fn iconRect(
fillCircle(ctx, x + s2, y + s2, dot_r, fg); fillCircle(ctx, x + s2, y + s2, dot_r, fg);
fillCircle(ctx, x + s2, y + s34, dot_r, fg); fillCircle(ctx, x + s2, y + s34, dot_r, fg);
}, },
// Search
.search => { .search => {
const r: u32 = @intCast(s3); const r: u32 = @intCast(s3);
strokeCircle(ctx, x + s3, y + s3, r, sw, fg); strokeCircle(ctx, x + s3, y + s3, r, sw, fg);
drawLine(ctx, x + s2, y + s2, x + s - 3, y + s - 3, sw, fg); drawLine(ctx, x + s2, y + s2, x + s - 3, y + s - 3, sw, fg);
}, },
// Settings (gear)
.settings => { .settings => {
const r: u32 = @intCast(s4); const r: u32 = @intCast(s4);
strokeCircle(ctx, x + s2, y + s2, r, sw, fg); strokeCircle(ctx, x + s2, y + s2, r, sw, fg);
@ -290,44 +172,32 @@ pub fn iconRect(
drawLine(ctx, x + 2, y + s2, x + s4, y + s2, sw, fg); drawLine(ctx, x + 2, y + s2, x + s4, y + s2, sw, fg);
drawLine(ctx, x + s - 2, y + s2, x + s34, y + s2, sw, fg); drawLine(ctx, x + s - 2, y + s2, x + s34, y + s2, sw, fg);
}, },
// File
.file => { .file => {
ctx.pushCommand(Command.rectOutline(x + 2, y + 2, @intCast(s - 4), @intCast(s - 4), fg)); ctx.pushCommand(Command.rectOutline(x + 2, y + 2, @intCast(s - 4), @intCast(s - 4), fg));
drawLine(ctx, x + s - 6, y + 2, x + s - 2, y + 6, sw, fg); drawLine(ctx, x + s - 6, y + 2, x + s - 2, y + 6, sw, fg);
}, },
// Folder
.folder => { .folder => {
ctx.pushCommand(Command.rectOutline(x + 2, y + 4, @intCast(s - 4), @intCast(s - 6), fg)); ctx.pushCommand(Command.rectOutline(x + 2, y + 4, @intCast(s - 4), @intCast(s - 6), fg));
drawLine(ctx, x + 2, y + 4, x + s3, y + 4, sw, fg); drawLine(ctx, x + 2, y + 4, x + s3, y + 4, sw, fg);
drawLine(ctx, x + s3, y + 4, x + s3 + 2, y + 2, sw, fg); drawLine(ctx, x + s3, y + 4, x + s3 + 2, y + 2, sw, fg);
drawLine(ctx, x + s3 + 2, y + 2, x + s2, y + 2, sw, fg); drawLine(ctx, x + s3 + 2, y + 2, x + s2, y + 2, sw, fg);
}, },
// Document
.document => { .document => {
ctx.pushCommand(Command.rectOutline(x + 3, y + 2, @intCast(s - 6), @intCast(s - 4), fg)); ctx.pushCommand(Command.rectOutline(x + 3, y + 2, @intCast(s - 6), @intCast(s - 4), fg));
drawLine(ctx, x + 5, y + s3, x + s - 5, y + s3, 1, fg); drawLine(ctx, x + 5, y + s3, x + s - 5, y + s3, 1, fg);
drawLine(ctx, x + 5, y + s2, x + s - 5, y + s2, 1, fg); drawLine(ctx, x + 5, y + s2, x + s - 5, y + s2, 1, fg);
drawLine(ctx, x + 5, y + s23, x + s - 7, y + s23, 1, fg); drawLine(ctx, x + 5, y + s23, x + s - 7, y + s23, 1, fg);
}, },
// Save (floppy)
.save => { .save => {
ctx.pushCommand(Command.rectOutline(x + 2, y + 2, @intCast(s - 4), @intCast(s - 4), fg)); ctx.pushCommand(Command.rectOutline(x + 2, y + 2, @intCast(s - 4), @intCast(s - 4), fg));
ctx.pushCommand(Command.rect(x + 4, y + s2, @intCast(s - 8), @intCast(s3), fg)); ctx.pushCommand(Command.rect(x + 4, y + s2, @intCast(s - 8), @intCast(s3), fg));
}, },
// Info
.info => { .info => {
const r: u32 = @intCast(s2 - 2); const r: u32 = @intCast(s2 - 2);
strokeCircle(ctx, x + s2, y + s2, r, sw, fg); strokeCircle(ctx, x + s2, y + s2, r, sw, fg);
fillCircle(ctx, x + s2, y + s3, 2, fg); fillCircle(ctx, x + s2, y + s3, 2, fg);
drawLine(ctx, x + s2, y + s2 - 1, x + s2, y + s23 + 1, sw, fg); drawLine(ctx, x + s2, y + s2 - 1, x + s2, y + s23 + 1, sw, fg);
}, },
// Warning (triangle)
.warning => { .warning => {
drawLine(ctx, x + s2, y + 2, x + 2, y + s - 2, sw, fg); drawLine(ctx, x + s2, y + 2, x + 2, y + s - 2, sw, fg);
drawLine(ctx, x + s2, y + 2, x + s - 2, y + s - 2, sw, fg); drawLine(ctx, x + s2, y + 2, x + s - 2, y + s - 2, sw, fg);
@ -335,31 +205,23 @@ pub fn iconRect(
drawLine(ctx, x + s2, y + s3 + 1, x + s2, y + s2 + 1, sw, fg); drawLine(ctx, x + s2, y + s3 + 1, x + s2, y + s2 + 1, sw, fg);
fillCircle(ctx, x + s2, y + s23, 2, fg); fillCircle(ctx, x + s2, y + s23, 2, fg);
}, },
// Error (X in circle)
.error_icon => { .error_icon => {
const r: u32 = @intCast(s2 - 2); const r: u32 = @intCast(s2 - 2);
strokeCircle(ctx, x + s2, y + s2, r, sw, fg); strokeCircle(ctx, x + s2, y + s2, r, sw, fg);
drawLine(ctx, x + s3, y + s3, x + s23, y + s23, sw, fg); drawLine(ctx, x + s3, y + s3, x + s23, y + s23, sw, fg);
drawLine(ctx, x + s23, y + s3, x + s3, y + s23, sw, fg); drawLine(ctx, x + s23, y + s3, x + s3, y + s23, sw, fg);
}, },
// Success (checkmark in circle)
.success => { .success => {
const r: u32 = @intCast(s2 - 2); const r: u32 = @intCast(s2 - 2);
strokeCircle(ctx, x + s2, y + s2, r, sw, fg); strokeCircle(ctx, x + s2, y + s2, r, sw, fg);
drawLine(ctx, x + s4 + 1, y + s2, x + s2 - 1, y + s23, sw, fg); drawLine(ctx, x + s4 + 1, y + s2, x + s2 - 1, y + s23, sw, fg);
drawLine(ctx, x + s2 - 1, y + s23, x + s34 - 1, y + s3, sw, fg); drawLine(ctx, x + s2 - 1, y + s23, x + s34 - 1, y + s3, sw, fg);
}, },
// Question
.question => { .question => {
const r: u32 = @intCast(s2 - 2); const r: u32 = @intCast(s2 - 2);
strokeCircle(ctx, x + s2, y + s2, r, sw, fg); strokeCircle(ctx, x + s2, y + s2, r, sw, fg);
ctx.pushCommand(Command.text(x + s2 - 3, y + s3, "?", fg)); ctx.pushCommand(Command.text(x + s2 - 3, y + s3, "?", fg));
}, },
// Star
.star => { .star => {
const s25 = @divTrunc(s * 2, 5); const s25 = @divTrunc(s * 2, 5);
const s35 = @divTrunc(s * 3, 5); const s35 = @divTrunc(s * 3, 5);
@ -377,8 +239,6 @@ pub fn iconRect(
.star_filled => { .star_filled => {
fillCircle(ctx, x + s2, y + s2, @intCast(s3), fg); fillCircle(ctx, x + s2, y + s2, @intCast(s3), fg);
}, },
// Heart
.heart => { .heart => {
drawLine(ctx, x + s2, y + s - 3, x + 3, y + s2, sw, fg); drawLine(ctx, x + s2, y + s - 3, x + 3, y + s2, sw, fg);
drawLine(ctx, x + s2, y + s - 3, x + s - 3, y + s2, sw, fg); drawLine(ctx, x + s2, y + s - 3, x + s - 3, y + s2, sw, fg);
@ -394,8 +254,6 @@ pub fn iconRect(
ctx.pushCommand(Command.rect(x + s2 - hw, y + s2 + dy, @intCast(hw * 2), 1, fg)); ctx.pushCommand(Command.rect(x + s2 - hw, y + s2 + dy, @intCast(hw * 2), 1, fg));
} }
}, },
// Eye
.eye => { .eye => {
ctx.pushCommand(Command.rectOutline(x + 2, y + s3, @intCast(s - 4), @intCast(s3), fg)); ctx.pushCommand(Command.rectOutline(x + 2, y + s3, @intCast(s - 4), @intCast(s3), fg));
fillCircle(ctx, x + s2, y + s2, @intCast(s6), fg); fillCircle(ctx, x + s2, y + s2, @intCast(s6), fg);
@ -404,8 +262,6 @@ pub fn iconRect(
ctx.pushCommand(Command.rectOutline(x + 2, y + s3, @intCast(s - 4), @intCast(s3), fg)); ctx.pushCommand(Command.rectOutline(x + 2, y + s3, @intCast(s - 4), @intCast(s3), fg));
drawLine(ctx, x + 2, y + s - 3, x + s - 2, y + 3, sw, fg); drawLine(ctx, x + 2, y + s - 3, x + s - 2, y + 3, sw, fg);
}, },
// Lock
.lock => { .lock => {
ctx.pushCommand(Command.rectOutline(x + 3, y + s2, @intCast(s - 6), @intCast(s2 - 2), fg)); ctx.pushCommand(Command.rectOutline(x + 3, y + s2, @intCast(s - 6), @intCast(s2 - 2), fg));
drawLine(ctx, x + s3, y + s2, x + s3, y + s4, sw, fg); drawLine(ctx, x + s3, y + s2, x + s3, y + s4, sw, fg);
@ -417,8 +273,6 @@ pub fn iconRect(
drawLine(ctx, x + s3, y + s2, x + s3, y + s4, sw, fg); drawLine(ctx, x + s3, y + s2, x + s3, y + s4, sw, fg);
drawLine(ctx, x + s3, y + s4, x + s2, y + s4, sw, fg); drawLine(ctx, x + s3, y + s4, x + s2, y + s4, sw, fg);
}, },
// User
.user => { .user => {
fillCircle(ctx, x + s2, y + s3, @intCast(s5), fg); fillCircle(ctx, x + s2, y + s3, @intCast(s5), fg);
drawLine(ctx, x + s4, y + s - 2, x + s4, y + s2 + 2, sw, fg); drawLine(ctx, x + s4, y + s - 2, x + s4, y + s2 + 2, sw, fg);
@ -429,24 +283,18 @@ pub fn iconRect(
fillCircle(ctx, x + s3, y + s3 + 1, @intCast(s6), fg); fillCircle(ctx, x + s3, y + s3 + 1, @intCast(s6), fg);
fillCircle(ctx, x + s23, y + s4, @intCast(s6), fg); fillCircle(ctx, x + s23, y + s4, @intCast(s6), fg);
}, },
// Calendar
.calendar => { .calendar => {
ctx.pushCommand(Command.rectOutline(x + 2, y + 4, @intCast(s - 4), @intCast(s - 6), fg)); ctx.pushCommand(Command.rectOutline(x + 2, y + 4, @intCast(s - 4), @intCast(s - 6), fg));
drawLine(ctx, x + 2, y + s3, x + s - 2, y + s3, sw, fg); drawLine(ctx, x + 2, y + s3, x + s - 2, y + s3, sw, fg);
drawLine(ctx, x + s3, y + 2, x + s3, y + 5, sw, fg); drawLine(ctx, x + s3, y + 2, x + s3, y + 5, sw, fg);
drawLine(ctx, x + s23, y + 2, x + s23, y + 5, sw, fg); drawLine(ctx, x + s23, y + 2, x + s23, y + 5, sw, fg);
}, },
// Clock
.clock => { .clock => {
const r: u32 = @intCast(s2 - 2); const r: u32 = @intCast(s2 - 2);
strokeCircle(ctx, x + s2, y + s2, r, sw, fg); strokeCircle(ctx, x + s2, y + s2, r, sw, fg);
drawLine(ctx, x + s2, y + s2, x + s2, y + s3, sw, fg); drawLine(ctx, x + s2, y + s2, x + s2, y + s3, sw, fg);
drawLine(ctx, x + s2, y + s2, x + s23, y + s2, sw, fg); drawLine(ctx, x + s2, y + s2, x + s23, y + s2, sw, fg);
}, },
// Bell
.bell => { .bell => {
drawLine(ctx, x + s3, y + s23, x + s3, y + s3, sw, fg); drawLine(ctx, x + s3, y + s23, x + s3, y + s3, sw, fg);
drawLine(ctx, x + s23, y + s23, x + s23, y + s3, sw, fg); drawLine(ctx, x + s23, y + s23, x + s23, y + s3, sw, fg);
@ -454,33 +302,23 @@ pub fn iconRect(
drawLine(ctx, x + 3, y + s23, x + s - 3, y + s23, sw, fg); drawLine(ctx, x + 3, y + s23, x + s - 3, y + s23, sw, fg);
fillCircle(ctx, x + s2, y + s - 3, 2, fg); fillCircle(ctx, x + s2, y + s - 3, 2, fg);
}, },
// Mail
.mail => { .mail => {
ctx.pushCommand(Command.rectOutline(x + 2, y + s4, @intCast(s - 4), @intCast(s2), fg)); ctx.pushCommand(Command.rectOutline(x + 2, y + s4, @intCast(s - 4), @intCast(s2), fg));
drawLine(ctx, x + 2, y + s4, x + s2, y + s2, sw, fg); drawLine(ctx, x + 2, y + s4, x + s2, y + s2, sw, fg);
drawLine(ctx, x + s - 2, y + s4, x + s2, y + s2, sw, fg); drawLine(ctx, x + s - 2, y + s4, x + s2, y + s2, sw, fg);
}, },
// Play
.play => { .play => {
drawLine(ctx, x + s3, y + 3, x + s3, y + s - 3, sw, fg); drawLine(ctx, x + s3, y + 3, x + s3, y + s - 3, sw, fg);
drawLine(ctx, x + s3, y + 3, x + s23 + 1, y + s2, sw, fg); drawLine(ctx, x + s3, y + 3, x + s23 + 1, y + s2, sw, fg);
drawLine(ctx, x + s3, y + s - 3, x + s23 + 1, y + s2, sw, fg); drawLine(ctx, x + s3, y + s - 3, x + s23 + 1, y + s2, sw, fg);
}, },
// Pause
.pause => { .pause => {
ctx.pushCommand(Command.rect(x + s4, y + 3, @intCast(s5), @intCast(s - 6), fg)); ctx.pushCommand(Command.rect(x + s4, y + 3, @intCast(s5), @intCast(s - 6), fg));
ctx.pushCommand(Command.rect(x + s - s4 - s5, y + 3, @intCast(s5), @intCast(s - 6), fg)); ctx.pushCommand(Command.rect(x + s - s4 - s5, y + 3, @intCast(s5), @intCast(s - 6), fg));
}, },
// Stop
.stop => { .stop => {
ctx.pushCommand(Command.rect(x + 3, y + 3, @intCast(s - 6), @intCast(s - 6), fg)); ctx.pushCommand(Command.rect(x + 3, y + 3, @intCast(s - 6), @intCast(s - 6), fg));
}, },
// Volume
.volume => { .volume => {
ctx.pushCommand(Command.rect(x + 2, y + s3, 4, @intCast(s3), fg)); ctx.pushCommand(Command.rect(x + 2, y + s3, 4, @intCast(s3), fg));
drawLine(ctx, x + 6, y + s3, x + s2, y + 3, sw, fg); drawLine(ctx, x + 6, y + s3, x + s2, y + 3, sw, fg);
@ -494,111 +332,81 @@ pub fn iconRect(
drawLine(ctx, x + s23, y + s3, x + s - 3, y + s23, sw, fg); drawLine(ctx, x + s23, y + s3, x + s - 3, y + s23, sw, fg);
drawLine(ctx, x + s - 3, y + s3, x + s23, y + s23, sw, fg); drawLine(ctx, x + s - 3, y + s3, x + s23, y + s23, sw, fg);
}, },
// Edit
.edit => { .edit => {
drawLine(ctx, x + 3, y + s - 5, x + s - 5, y + 3, sw, fg); drawLine(ctx, x + 3, y + s - 5, x + s - 5, y + 3, sw, fg);
drawLine(ctx, x + s - 5, y + 3, x + s - 3, y + 5, sw, fg); drawLine(ctx, x + s - 5, y + 3, x + s - 3, y + 5, sw, fg);
drawLine(ctx, x + s - 3, y + 5, x + 5, y + s - 3, sw, fg); drawLine(ctx, x + s - 3, y + 5, x + 5, y + s - 3, sw, fg);
}, },
// Delete (trash)
.delete => { .delete => {
ctx.pushCommand(Command.rectOutline(x + 4, y + 4, @intCast(s - 8), @intCast(s - 6), fg)); ctx.pushCommand(Command.rectOutline(x + 4, y + 4, @intCast(s - 8), @intCast(s - 6), fg));
drawLine(ctx, x + 2, y + 4, x + s - 2, y + 4, sw, fg); drawLine(ctx, x + 2, y + 4, x + s - 2, y + 4, sw, fg);
drawLine(ctx, x + s3, y + 2, x + s23, y + 2, sw, fg); drawLine(ctx, x + s3, y + 2, x + s23, y + 2, sw, fg);
}, },
// Refresh
.refresh => { .refresh => {
const r: u32 = @intCast(s3); const r: u32 = @intCast(s3);
strokeCircle(ctx, x + s2, y + s2, r, sw, fg); strokeCircle(ctx, x + s2, y + s2, r, sw, fg);
drawLine(ctx, x + s2 + @as(i32, @intCast(r)), y + s2 - 3, x + s2 + @as(i32, @intCast(r)) + 3, y + s2, sw, fg); drawLine(ctx, x + s2 + @as(i32, @intCast(r)), y + s2 - 3, x + s2 + @as(i32, @intCast(r)) + 3, y + s2, sw, fg);
}, },
// Filter
.filter => { .filter => {
drawLine(ctx, x + 2, y + 3, x + s - 2, y + 3, sw, fg); drawLine(ctx, x + 2, y + 3, x + s - 2, y + 3, sw, fg);
drawLine(ctx, x + 2, y + 3, x + s2, y + s2, sw, fg); drawLine(ctx, x + 2, y + 3, x + s2, y + s2, sw, fg);
drawLine(ctx, x + s - 2, y + 3, x + s2, y + s2, sw, fg); drawLine(ctx, x + s - 2, y + 3, x + s2, y + s2, sw, fg);
drawLine(ctx, x + s2, y + s2, x + s2, y + s - 3, sw, fg); drawLine(ctx, x + s2, y + s2, x + s2, y + s - 3, sw, fg);
}, },
// Sort
.sort => { .sort => {
drawLine(ctx, x + 3, y + s4, x + s - 3, y + s4, sw, fg); drawLine(ctx, x + 3, y + s4, x + s - 3, y + s4, sw, fg);
drawLine(ctx, x + 5, y + s2, x + s - 5, y + s2, sw, fg); drawLine(ctx, x + 5, y + s2, x + s - 5, y + s2, sw, fg);
drawLine(ctx, x + 7, y + s34, x + s - 7, y + s34, sw, fg); drawLine(ctx, x + 7, y + s34, x + s - 7, y + s34, sw, fg);
}, },
// Copy
.copy => { .copy => {
ctx.pushCommand(Command.rectOutline(x + 2, y + 4, @intCast(s - 6), @intCast(s - 6), fg)); ctx.pushCommand(Command.rectOutline(x + 2, y + 4, @intCast(s - 6), @intCast(s - 6), fg));
ctx.pushCommand(Command.rectOutline(x + 4, y + 2, @intCast(s - 6), @intCast(s - 6), fg)); ctx.pushCommand(Command.rectOutline(x + 4, y + 2, @intCast(s - 6), @intCast(s - 6), fg));
}, },
// Paste
.paste => { .paste => {
ctx.pushCommand(Command.rectOutline(x + 3, y + 3, @intCast(s - 6), @intCast(s - 5), fg)); ctx.pushCommand(Command.rectOutline(x + 3, y + 3, @intCast(s - 6), @intCast(s - 5), fg));
ctx.pushCommand(Command.rect(x + s3, y + 2, @intCast(s3), 3, fg)); ctx.pushCommand(Command.rect(x + s3, y + 2, @intCast(s3), 3, fg));
}, },
// Cut
.cut => { .cut => {
fillCircle(ctx, x + s3, y + s23, @intCast(s6), fg); fillCircle(ctx, x + s3, y + s23, @intCast(s6), fg);
fillCircle(ctx, x + s23, y + s23, @intCast(s6), fg); fillCircle(ctx, x + s23, y + s23, @intCast(s6), fg);
drawLine(ctx, x + s3, y + s2, x + s2, y + 3, sw, fg); drawLine(ctx, x + s3, y + s2, x + s2, y + 3, sw, fg);
drawLine(ctx, x + s23, y + s2, x + s2, y + 3, sw, fg); drawLine(ctx, x + s23, y + s2, x + s2, y + 3, sw, fg);
}, },
// Undo
.undo => { .undo => {
drawLine(ctx, x + 3, y + s3, x + s3, y + 3, sw, fg); drawLine(ctx, x + 3, y + s3, x + s3, y + 3, sw, fg);
drawLine(ctx, x + 3, y + s3, x + s3, y + s2, sw, fg); drawLine(ctx, x + 3, y + s3, x + s3, y + s2, sw, fg);
drawLine(ctx, x + 3, y + s3, x + s - 3, y + s3, sw, fg); drawLine(ctx, x + 3, y + s3, x + s - 3, y + s3, sw, fg);
drawLine(ctx, x + s - 3, y + s3, x + s - 3, y + s23, sw, fg); drawLine(ctx, x + s - 3, y + s3, x + s - 3, y + s23, sw, fg);
}, },
// Redo
.redo => { .redo => {
drawLine(ctx, x + s - 3, y + s3, x + s23, y + 3, sw, fg); drawLine(ctx, x + s - 3, y + s3, x + s23, y + 3, sw, fg);
drawLine(ctx, x + s - 3, y + s3, x + s23, y + s2, sw, fg); drawLine(ctx, x + s - 3, y + s3, x + s23, y + s2, sw, fg);
drawLine(ctx, x + s - 3, y + s3, x + 3, y + s3, sw, fg); drawLine(ctx, x + s - 3, y + s3, x + 3, y + s3, sw, fg);
drawLine(ctx, x + 3, y + s3, x + 3, y + s23, sw, fg); drawLine(ctx, x + 3, y + s3, x + 3, y + s23, sw, fg);
}, },
// Folder open
.folder_open => { .folder_open => {
ctx.pushCommand(Command.rectOutline(x + 2, y + 4, @intCast(s - 4), @intCast(s - 6), fg)); ctx.pushCommand(Command.rectOutline(x + 2, y + 4, @intCast(s - 4), @intCast(s - 6), fg));
drawLine(ctx, x + 2, y + s2, x + s3, y + s2, sw, fg); drawLine(ctx, x + 2, y + s2, x + s3, y + s2, sw, fg);
drawLine(ctx, x + s3, y + s2, x + s2, y + s3, sw, fg); drawLine(ctx, x + s3, y + s2, x + s2, y + s3, sw, fg);
}, },
// Image file
.image_file => { .image_file => {
ctx.pushCommand(Command.rectOutline(x + 2, y + 2, @intCast(s - 4), @intCast(s - 4), fg)); ctx.pushCommand(Command.rectOutline(x + 2, y + 2, @intCast(s - 4), @intCast(s - 4), fg));
drawLine(ctx, x + 4, y + s23, x + s3, y + s2, sw, fg); drawLine(ctx, x + 4, y + s23, x + s3, y + s2, sw, fg);
drawLine(ctx, x + s3, y + s2, x + s23, y + s23, sw, fg); drawLine(ctx, x + s3, y + s2, x + s23, y + s23, sw, fg);
fillCircle(ctx, x + s23, y + s3, 2, fg); fillCircle(ctx, x + s23, y + s3, 2, fg);
}, },
// Download
.download => { .download => {
drawLine(ctx, x + s2, y + 3, x + s2, y + s23, sw, fg); drawLine(ctx, x + s2, y + 3, x + s2, y + s23, sw, fg);
drawLine(ctx, x + s2, y + s23, x + s3, y + s2, sw, fg); drawLine(ctx, x + s2, y + s23, x + s3, y + s2, sw, fg);
drawLine(ctx, x + s2, y + s23, x + s23, y + s2, sw, fg); drawLine(ctx, x + s2, y + s23, x + s23, y + s2, sw, fg);
drawLine(ctx, x + 3, y + s - 3, x + s - 3, y + s - 3, sw, fg); drawLine(ctx, x + 3, y + s - 3, x + s - 3, y + s - 3, sw, fg);
}, },
// Upload
.upload => { .upload => {
drawLine(ctx, x + s2, y + s23, x + s2, y + 3, sw, fg); drawLine(ctx, x + s2, y + s23, x + s2, y + 3, sw, fg);
drawLine(ctx, x + s2, y + 3, x + s3, y + s4 + 1, sw, fg); drawLine(ctx, x + s2, y + 3, x + s3, y + s4 + 1, sw, fg);
drawLine(ctx, x + s2, y + 3, x + s23, y + s4 + 1, sw, fg); drawLine(ctx, x + s2, y + 3, x + s23, y + s4 + 1, sw, fg);
drawLine(ctx, x + 3, y + s - 3, x + s - 3, y + s - 3, sw, fg); drawLine(ctx, x + 3, y + s - 3, x + s - 3, y + s - 3, sw, fg);
}, },
// Grip (drag handle)
.grip => { .grip => {
const dot_r: u32 = 1; const dot_r: u32 = 1;
fillCircle(ctx, x + s3, y + s3, dot_r, fg); fillCircle(ctx, x + s3, y + s3, dot_r, fg);
@ -608,16 +416,12 @@ pub fn iconRect(
fillCircle(ctx, x + s3, y + s23, dot_r, fg); fillCircle(ctx, x + s3, y + s23, dot_r, fg);
fillCircle(ctx, x + s23, y + s23, dot_r, fg); fillCircle(ctx, x + s23, y + s23, dot_r, fg);
}, },
// Drag
.drag => { .drag => {
drawLine(ctx, x + s2, y + 2, x + s2, y + s - 2, sw, fg); drawLine(ctx, x + s2, y + 2, x + s2, y + s - 2, sw, fg);
drawLine(ctx, x + 2, y + s2, x + s - 2, y + s2, sw, fg); drawLine(ctx, x + 2, y + s2, x + s - 2, y + s2, sw, fg);
drawLine(ctx, x + s2, y + 2, x + s3, y + s4, sw, fg); drawLine(ctx, x + s2, y + 2, x + s3, y + s4, sw, fg);
drawLine(ctx, x + s2, y + 2, x + s23, y + s4, sw, fg); drawLine(ctx, x + s2, y + 2, x + s23, y + s4, sw, fg);
}, },
// Expand
.expand => { .expand => {
drawLine(ctx, x + 2, y + 2, x + s3, y + 2, sw, fg); drawLine(ctx, x + 2, y + 2, x + s3, y + 2, sw, fg);
drawLine(ctx, x + 2, y + 2, x + 2, y + s3, sw, fg); drawLine(ctx, x + 2, y + 2, x + 2, y + s3, sw, fg);
@ -628,8 +432,6 @@ pub fn iconRect(
drawLine(ctx, x + s - 2, y + s - 2, x + s23, y + s - 2, sw, fg); drawLine(ctx, x + s - 2, y + s - 2, x + s23, y + s - 2, sw, fg);
drawLine(ctx, x + s - 2, y + s - 2, x + s - 2, y + s23, sw, fg); drawLine(ctx, x + s - 2, y + s - 2, x + s - 2, y + s23, sw, fg);
}, },
// Collapse
.collapse => { .collapse => {
drawLine(ctx, x + s3, y + s3, x + 2, y + s3, sw, fg); drawLine(ctx, x + s3, y + s3, x + 2, y + s3, sw, fg);
drawLine(ctx, x + s3, y + s3, x + s3, y + 2, sw, fg); drawLine(ctx, x + s3, y + s3, x + s3, y + 2, sw, fg);
@ -640,19 +442,13 @@ pub fn iconRect(
drawLine(ctx, x + s23, y + s23, x + s - 2, y + s23, sw, fg); drawLine(ctx, x + s23, y + s23, x + s - 2, y + s23, sw, fg);
drawLine(ctx, x + s23, y + s23, x + s23, y + s - 2, sw, fg); drawLine(ctx, x + s23, y + s23, x + s23, y + s - 2, sw, fg);
}, },
// Maximize
.maximize => { .maximize => {
ctx.pushCommand(Command.rectOutline(x + 3, y + 3, @intCast(s - 6), @intCast(s - 6), fg)); ctx.pushCommand(Command.rectOutline(x + 3, y + 3, @intCast(s - 6), @intCast(s - 6), fg));
drawLine(ctx, x + 3, y + 5, x + s - 3, y + 5, sw, fg); drawLine(ctx, x + 3, y + 5, x + s - 3, y + 5, sw, fg);
}, },
// Minimize
.minimize => { .minimize => {
drawLine(ctx, x + 3, y + s - 4, x + s - 3, y + s - 4, sw, fg); drawLine(ctx, x + 3, y + s - 4, x + s - 3, y + s - 4, sw, fg);
}, },
// External link
.external_link => { .external_link => {
ctx.pushCommand(Command.rectOutline(x + 2, y + 4, @intCast(s - 6), @intCast(s - 6), fg)); ctx.pushCommand(Command.rectOutline(x + 2, y + 4, @intCast(s - 6), @intCast(s - 6), fg));
drawLine(ctx, x + s2, y + 2, x + s - 2, y + 2, sw, fg); drawLine(ctx, x + s2, y + 2, x + s - 2, y + 2, sw, fg);
@ -662,92 +458,6 @@ pub fn iconRect(
} }
} }
// =============================================================================
// Helper functions
// =============================================================================
/// Draw a line with thickness
fn drawLine(ctx: *Context, x1: i32, y1: i32, x2: i32, y2: i32, thickness: u32, color: Style.Color) void {
if (thickness <= 1) {
ctx.pushCommand(Command.line(x1, y1, x2, y2, color));
} else {
const dx = x2 - x1;
const dy = y2 - y1;
const len = @sqrt(@as(f32, @floatFromInt(dx * dx + dy * dy)));
if (len < 1) {
ctx.pushCommand(Command.rect(x1, y1, thickness, thickness, color));
return;
}
const nx = -@as(f32, @floatFromInt(dy)) / len;
const ny = @as(f32, @floatFromInt(dx)) / len;
const half = @as(f32, @floatFromInt(thickness)) / 2.0;
var offset: f32 = -half;
while (offset < half) : (offset += 1.0) {
const ox = @as(i32, @intFromFloat(nx * offset));
const oy = @as(i32, @intFromFloat(ny * offset));
ctx.pushCommand(Command.line(x1 + ox, y1 + oy, x2 + ox, y2 + oy, color));
}
}
}
/// Fill a circle
fn fillCircle(ctx: *Context, cx: i32, cy: i32, radius: u32, color: Style.Color) void {
if (radius == 0) {
ctx.pushCommand(Command.rect(cx, cy, 1, 1, color));
return;
}
const r = @as(i32, @intCast(radius));
var dy: i32 = -r;
while (dy <= r) : (dy += 1) {
const dy_f = @as(f32, @floatFromInt(dy));
const r_f = @as(f32, @floatFromInt(r));
const dx = @as(i32, @intFromFloat(@sqrt(r_f * r_f - dy_f * dy_f)));
ctx.pushCommand(Command.rect(cx - dx, cy + dy, @intCast(dx * 2 + 1), 1, color));
}
}
/// Stroke a circle
fn strokeCircle(ctx: *Context, cx: i32, cy: i32, radius: u32, thickness: u32, color: Style.Color) void {
if (radius == 0) return;
const r = @as(i32, @intCast(radius));
var px: i32 = 0;
var py: i32 = r;
var d: i32 = 3 - 2 * r;
while (px <= py) {
setPixelThick(ctx, cx + px, cy + py, thickness, color);
setPixelThick(ctx, cx - px, cy + py, thickness, color);
setPixelThick(ctx, cx + px, cy - py, thickness, color);
setPixelThick(ctx, cx - px, cy - py, thickness, color);
setPixelThick(ctx, cx + py, cy + px, thickness, color);
setPixelThick(ctx, cx - py, cy + px, thickness, color);
setPixelThick(ctx, cx + py, cy - px, thickness, color);
setPixelThick(ctx, cx - py, cy - px, thickness, color);
if (d < 0) {
d = d + 4 * px + 6;
} else {
d = d + 4 * (px - py) + 10;
py -= 1;
}
px += 1;
}
}
fn setPixelThick(ctx: *Context, pixel_x: i32, pixel_y: i32, thickness: u32, color: Style.Color) void {
if (thickness <= 1) {
ctx.pushCommand(Command.rect(pixel_x, pixel_y, 1, 1, color));
} else {
const half = @as(i32, @intCast(thickness / 2));
ctx.pushCommand(Command.rect(pixel_x - half, pixel_y - half, thickness, thickness, color));
}
}
// ============================================================================= // =============================================================================
// Tests // Tests
// ============================================================================= // =============================================================================

146
src/widgets/icon/types.zig Normal file
View file

@ -0,0 +1,146 @@
//! Icon - Tipos y configuración
//!
//! Size, IconType, Config, Colors.
const Style = @import("../../core/style.zig");
// =============================================================================
// Size
// =============================================================================
/// Icon size presets
pub const Size = enum {
small, // 12x12
medium, // 16x16
large, // 24x24
xlarge, // 32x32
pub fn pixels(self: Size) u32 {
return switch (self) {
.small => 12,
.medium => 16,
.large => 24,
.xlarge => 32,
};
}
};
// =============================================================================
// IconType
// =============================================================================
/// Built-in icon types
pub const IconType = enum {
// Navigation
arrow_up,
arrow_down,
arrow_left,
arrow_right,
chevron_up,
chevron_down,
chevron_left,
chevron_right,
home,
menu,
more_horizontal,
more_vertical,
// Actions
check,
close,
plus,
minus,
edit,
delete,
refresh,
search,
settings,
filter,
sort,
copy,
paste,
cut,
undo,
redo,
// Files
file,
folder,
folder_open,
document,
image_file,
download,
upload,
save,
// Status
info,
warning,
error_icon,
success,
question,
star,
star_filled,
heart,
heart_filled,
// UI elements
eye,
eye_off,
lock,
unlock,
user,
users,
calendar,
clock,
bell,
mail,
// Media
play,
pause,
stop,
volume,
volume_off,
// Misc
grip,
drag,
expand,
collapse,
maximize,
minimize,
external_link,
};
// =============================================================================
// Config
// =============================================================================
/// Icon configuration
pub const Config = struct {
/// Icon size
size: Size = .medium,
/// Custom size (overrides size preset)
custom_size: ?u32 = null,
/// Stroke width
stroke_width: u32 = 2,
/// Fill icon
filled: bool = false,
};
// =============================================================================
// Colors
// =============================================================================
/// Icon colors
pub const Colors = struct {
foreground: Style.Color = Style.Color.rgba(220, 220, 220, 255),
background: ?Style.Color = null,
pub fn fromTheme(theme: Style.Theme) Colors {
return .{
.foreground = theme.foreground,
};
}
};

View file

@ -9,7 +9,7 @@ const Command = @import("../core/command.zig");
const Layout = @import("../core/layout.zig"); const Layout = @import("../core/layout.zig");
const Style = @import("../core/style.zig"); const Style = @import("../core/style.zig");
const Input = @import("../core/input.zig"); const Input = @import("../core/input.zig");
const icon_module = @import("icon.zig"); const icon_module = @import("icon/icon.zig");
/// IconButton style variants /// IconButton style variants
pub const ButtonStyle = enum { pub const ButtonStyle = enum {

View file

@ -9,7 +9,7 @@ const Command = @import("../core/command.zig");
const Layout = @import("../core/layout.zig"); const Layout = @import("../core/layout.zig");
const Style = @import("../core/style.zig"); const Style = @import("../core/style.zig");
const Input = @import("../core/input.zig"); const Input = @import("../core/input.zig");
const icon_module = @import("icon.zig"); const icon_module = @import("icon/icon.zig");
/// Navigation item /// Navigation item
pub const NavItem = struct { pub const NavItem = struct {

View file

@ -39,7 +39,7 @@ pub const richtext = @import("richtext.zig");
pub const breadcrumb = @import("breadcrumb.zig"); pub const breadcrumb = @import("breadcrumb.zig");
pub const canvas = @import("canvas.zig"); pub const canvas = @import("canvas.zig");
pub const chart = @import("chart.zig"); pub const chart = @import("chart.zig");
pub const icon = @import("icon.zig"); pub const icon = @import("icon/icon.zig");
pub const virtual_scroll = @import("virtual_scroll.zig"); pub const virtual_scroll = @import("virtual_scroll.zig");
pub const virtual_advanced_table = @import("virtual_advanced_table/virtual_advanced_table.zig"); pub const virtual_advanced_table = @import("virtual_advanced_table/virtual_advanced_table.zig");