diff --git a/docs/fakemui-icons-quick-reference.md b/docs/fakemui-icons-quick-reference.md new file mode 100644 index 000000000..46736acb7 --- /dev/null +++ b/docs/fakemui-icons-quick-reference.md @@ -0,0 +1,349 @@ +# FakeMUI Icons Quick Reference + +## Quick Start + +### 1. Import icon module in your Lua package + +```lua +local icons = require("icons") +``` + +### 2. Use icons in components + +```lua +-- In a button +{ + type = "Button", + children = { + { type = "Icon", props = { name = icons.get("ADD"), size = "medium" } }, + { type = "Typography", props = { text = "Add Item" } } + } +} + +-- In a stat card +stat_card.create({ + label = "Total Users", + value = 1234, + icon = icons.get("USERS") +}) +``` + +## Icon Sizes + +| Size | Pixels | Usage | +|------|--------|-------| +| `small` | 20px | Inline with text | +| `medium` | 24px | Buttons, default | +| `large` | 32px | Headers, cards | +| `inherit` | - | Inherit from parent | + +## Package Icon Constants + +### Dashboard (`packages/dashboard/seed/scripts/icons.lua`) + +```lua +-- Stats & Analytics +CHART_LINE, TREND_UP, BAR_CHART, PIE_CHART, ANALYTICS, DASHBOARD, STATS + +-- Status +CHECK_CIRCLE, SHIELD_CHECK, WARNING, ERROR, INFO + +-- Time +CLOCK, CALENDAR, SCHEDULE + +-- Users +USER, USERS, USER_CIRCLE, PEOPLE +``` + +### Navigation Menu (`packages/nav_menu/seed/scripts/icons.lua`) + +```lua +-- Navigation +HOME, HOUSE, DASHBOARD, MENU, SIDEBAR + +-- Pages +SETTINGS, PROFILE, USER, USERS + +-- Actions +SEARCH, NOTIFICATIONS, MAIL, CALENDAR + +-- Data +FILE, FOLDER, DATABASE, TABLE, LIST, GRID + +-- Admin +ADMIN_PANEL, MANAGE_ACCOUNTS, SECURITY, VERIFIED_USER, POLICY +``` + +### Data Table (`packages/data_table/seed/scripts/icons.lua`) + +```lua +-- Sorting +SORT, SORT_ASCENDING, SORT_DESCENDING, ARROW_UP_DOWN + +-- Filtering +FILTER, FILTER_LIST, FILTER_OFF, FILTER_CLEAR, FUNNEL + +-- Actions +EDIT, DELETE, TRASH, ADD, REMOVE, COPY, SAVE + +-- Export +DOWNLOAD, UPLOAD, EXPORT, CSV, JSON + +-- Selection +CHECKBOX, SELECT_ALL, ROW_SELECT + +-- Pagination +FIRST_PAGE, LAST_PAGE, CHEVRON_LEFT, CHEVRON_RIGHT +``` + +### Workflow Editor (`packages/workflow_editor/seed/scripts/icons.lua`) + +```lua +-- Workflow +WORKFLOW, GIT_BRANCH, CALL_SPLIT, ACCOUNT_TREE + +-- Control +PLAY, PLAY_ARROW, STOP, PAUSE + +-- Status +CHECK_CIRCLE, CIRCLE_X, WARNING, INFO, PENDING + +-- Tools +BUILD, CODE, TERMINAL, SETTINGS + +-- View +ZOOM_IN, ZOOM_OUT, FULLSCREEN, FULLSCREEN_EXIT, CENTER_FOCUS +``` + +### Form Builder (`packages/form_builder/seed/scripts/icons.lua`) + +```lua +-- Validation +CHECK_CIRCLE, ERROR, WARNING, INFO + +-- Field Types +TEXT_FIELDS, EMAIL, LOCK, CALENDAR, CHECKBOX, RADIO, TOGGLE_ON + +-- Visibility +VISIBILITY, VISIBILITY_OFF + +-- File Handling +ATTACH_FILE, INSERT_PHOTO, UPLOAD + +-- Rich Text +FORMAT_BOLD, FORMAT_ITALIC, FORMAT_UNDERLINE, INSERT_LINK +``` + +## Common Icon Patterns + +### Button with Icon + +```lua +{ + type = "Button", + props = { variant = "contained" }, + children = { + { type = "Icon", props = { name = "Add", className = "mr-2" } }, + { type = "Typography", props = { text = "Add Item" } } + } +} +``` + +### Icon Button + +```lua +{ + type = "IconButton", + props = { onClick = "delete_item", title = "Delete" }, + children = { + { type = "Icon", props = { name = "Trash" } } + } +} +``` + +### List Item with Icon + +```lua +{ + type = "ListItem", + children = { + { + type = "ListItemIcon", + children = { + { type = "Icon", props = { name = "Home" } } + } + }, + { + type = "ListItemText", + props = { text = "Home" } + } + } +} +``` + +### Input with Start/End Icons + +```lua +{ + type = "Box", + props = { className = "relative" }, + children = { + -- Start icon + { + type = "Icon", + props = { name = "Search", className = "absolute left-3 top-4" } + }, + -- Input field + { + type = "TextField", + props = { label = "Search", className = "pl-10" } + } + } +} +``` + +### Status Badge with Icon + +```lua +{ + type = "Chip", + props = { + label = "Active", + color = "success" + }, + children = { + { type = "Icon", props = { name = "CheckCircle", size = "small" } } + } +} +``` + +## Color Classes + +Use Tailwind classes for icon colors: + +```lua +-- Success (green) +{ type = "Icon", props = { name = "CheckCircle", className = "text-green-500" } } + +-- Error (red) +{ type = "Icon", props = { name = "CircleX", className = "text-red-500" } } + +-- Warning (yellow) +{ type = "Icon", props = { name = "Warning", className = "text-yellow-500" } } + +-- Info (blue) +{ type = "Icon", props = { name = "Info", className = "text-blue-500" } } + +-- Muted +{ type = "Icon", props = { name = "User", className = "text-gray-400" } } +``` + +## Icon Name Formats + +All formats work (case-insensitive, alias-aware): + +```lua +-- PascalCase (recommended) +{ type = "Icon", props = { name = "CheckCircle" } } + +-- kebab-case +{ type = "Icon", props = { name = "check-circle" } } + +-- lowercase +{ type = "Icon", props = { name = "checkcircle" } } +``` + +## Top 50 Most Useful Icons + +### Actions (15) +`Add`, `Edit`, `Delete`, `Save`, `Check`, `Close`, `Copy`, `Download`, `Upload`, `Refresh`, `Search`, `Filter`, `Play`, `Pause`, `Stop` + +### Navigation (10) +`Home`, `Menu`, `ChevronRight`, `ChevronDown`, `ArrowRight`, `ArrowLeft`, `ExpandMore`, `Close`, `NavigateNext`, `NavigateBefore` + +### Status (10) +`CheckCircle`, `CircleX`, `Warning`, `Info`, `Star`, `Heart`, `Flag`, `CircleCheck`, `AlertCircle`, `AlertTriangle` + +### Users & Security (5) +`User`, `Users`, `Lock`, `Shield`, `Settings` + +### Data & Content (10) +`Dashboard`, `Table`, `List`, `Grid`, `File`, `Folder`, `Database`, `Calendar`, `Mail`, `Bell` + +## Accessibility + +Always pair icons with text labels: + +```lua +-- Good: Icon + Label +{ + type = "Button", + children = { + { type = "Icon", props = { name = "Delete", className = "mr-2" } }, + { type = "Typography", props = { text = "Delete" } } + } +} + +-- Also Good: Icon with title attribute +{ + type = "IconButton", + props = { title = "Delete", onClick = "delete_item" }, + children = { + { type = "Icon", props = { name = "Delete" } } + } +} +``` + +## File Locations + +| Component | Path | +|-----------|------| +| Icon Registry | `frontends/nextjs/src/lib/rendering/icon-registry.ts` | +| Component Registry | `frontends/nextjs/src/lib/rendering/component-registry.ts` | +| Icon Component | `frontends/nextjs/src/components/atoms/display/Icon.tsx` | +| FakeMUI Icons | `fakemui/icons/` | +| Package Icons | `packages/{package}/seed/scripts/icons.lua` | +| Examples | `packages/{package}/seed/scripts/examples/` | + +## Complete Example + +```lua +-- Import modules +local icons = require("icons") +local sidebar = require("sidebar") + +-- Create sidebar with icons +local admin_nav = sidebar.render({ + title = "Admin Panel", + currentPath = "/admin/users", + items = { + { + label = "Dashboard", + path = "/admin", + icon = icons.get("DASHBOARD") + }, + { + label = "User Management", + path = "/admin/users", + icon = icons.get("MANAGE_ACCOUNTS") + }, + { + label = "Security Settings", + path = "/admin/security", + icon = icons.get("SECURITY") + }, + { + label = "Database", + path = "/admin/database", + icon = icons.get("DATABASE") + } + } +}) +``` + +## Next Steps + +1. Browse available icons in `fakemui/icons/index.ts` +2. Check package-specific icon constants in `packages/{package}/seed/scripts/icons.lua` +3. See full examples in `packages/{package}/seed/scripts/examples/` +4. Read complete documentation in `docs/fakemui-icons-integration.md` diff --git a/packages/dashboard/seed/scripts/examples/stats_with_icons.lua b/packages/dashboard/seed/scripts/examples/stats_with_icons.lua new file mode 100644 index 000000000..f802afd93 --- /dev/null +++ b/packages/dashboard/seed/scripts/examples/stats_with_icons.lua @@ -0,0 +1,67 @@ +-- Example: Dashboard stats cards with icons +local icons = require("icons") +local stat_card = require("stats.card") + +---@class StatsExample +local M = {} + +---Create example dashboard stats with icons +---@return UIComponent[] +function M.create_example_stats() + return { + stat_card.create({ + label = "Total Revenue", + value = "$45,231.89", + icon = icons.get("CHART_LINE"), + change = "+20.1% from last month", + positive = true, + className = "col-span-1" + }), + stat_card.create({ + label = "Active Users", + value = "2,350", + icon = icons.get("USERS"), + change = "+180 new users", + positive = true, + className = "col-span-1" + }), + stat_card.create({ + label = "Success Rate", + value = "98.5%", + icon = icons.get("SHIELD_CHECK"), + change = "+2.5% improvement", + positive = true, + className = "col-span-1" + }), + stat_card.create({ + label = "Pending Tasks", + value = 12, + icon = icons.get("CLOCK"), + change = "3 overdue", + positive = false, + className = "col-span-1" + }) + } +end + +---Create analytics dashboard +---@return UIComponent +function M.create_analytics_dashboard() + return { + type = "Box", + props = { className = "p-6" }, + children = { + { + type = "Typography", + props = { variant = "h4", text = "Analytics Dashboard", className = "mb-6" } + }, + { + type = "Grid", + props = { container = true, spacing = 3 }, + children = M.create_example_stats() + } + } + } +end + +return M diff --git a/packages/data_table/seed/scripts/examples/table_with_icons.lua b/packages/data_table/seed/scripts/examples/table_with_icons.lua new file mode 100644 index 000000000..2a140266e --- /dev/null +++ b/packages/data_table/seed/scripts/examples/table_with_icons.lua @@ -0,0 +1,103 @@ +-- Example: Data table with icon-based actions +local icons = require("icons") +local action_column = require("columns.action") +local text_column = require("columns.text") + +---@class DataTableExample +local M = {} + +---Create example user table with icons +---@return table +function M.create_user_table() + local columns = { + text_column("name", "Name"), + text_column("email", "Email"), + text_column("role", "Role"), + text_column("status", "Status"), + action_column("actions", { + { + id = "view", + icon = icons.get("EYE"), + label = "View", + handler = "view_user" + }, + { + id = "edit", + icon = icons.get("EDIT"), + label = "Edit", + handler = "edit_user" + }, + { + id = "delete", + icon = icons.get("TRASH"), + label = "Delete", + handler = "delete_user", + confirm = true + } + }) + } + + local data = { + { name = "John Doe", email = "john@example.com", role = "Admin", status = "Active" }, + { name = "Jane Smith", email = "jane@example.com", role = "User", status = "Active" }, + { name = "Bob Wilson", email = "bob@example.com", role = "User", status = "Inactive" } + } + + return { + columns = columns, + data = data + } +end + +---Create example table with export options +---@return UIComponent +function M.create_table_with_export() + return { + type = "Box", + props = { className = "p-6" }, + children = { + { + type = "Stack", + props = { direction = "row", spacing = 2, className = "mb-4" }, + children = { + { + type = "Button", + props = { + variant = "outlined", + onClick = "export_csv" + }, + children = { + { type = "Icon", props = { name = icons.get("CSV"), className = "mr-2" } }, + { type = "Typography", props = { text = "Export CSV" } } + } + }, + { + type = "Button", + props = { + variant = "outlined", + onClick = "export_json" + }, + children = { + { type = "Icon", props = { name = icons.get("JSON"), className = "mr-2" } }, + { type = "Typography", props = { text = "Export JSON" } } + } + }, + { + type = "Button", + props = { + variant = "outlined", + onClick = "refresh_data" + }, + children = { + { type = "Icon", props = { name = icons.get("REFRESH"), className = "mr-2" } }, + { type = "Typography", props = { text = "Refresh" } } + } + } + } + } + -- Table would be added here + } + } +end + +return M diff --git a/packages/form_builder/seed/scripts/examples/form_with_icons.lua b/packages/form_builder/seed/scripts/examples/form_with_icons.lua new file mode 100644 index 000000000..5c1263036 --- /dev/null +++ b/packages/form_builder/seed/scripts/examples/form_with_icons.lua @@ -0,0 +1,179 @@ +-- Example: Form fields with validation icons +local icons = require("icons") +local text_field = require("fields.text") +local email_field = require("fields.email") +local password_field = require("fields.password") +local required = require("validate.required") + +---@class FormExample +local M = {} + +---Create example login form with icons +---@return UIComponent +function M.create_login_form() + return { + type = "Box", + props = { className = "max-w-md mx-auto p-6" }, + children = { + { + type = "Typography", + props = { variant = "h4", text = "Login", className = "mb-6" } + }, + { + type = "Stack", + props = { spacing = 3 }, + children = { + -- Email field with icon + { + type = "Box", + props = { className = "relative" }, + children = { + { + type = "Icon", + props = { + name = icons.get("EMAIL"), + className = "absolute left-3 top-4 text-gray-400" + } + }, + { + type = "TextField", + props = { + label = "Email", + type = "email", + required = true, + className = "pl-10", + helperText = "Enter your email address" + } + } + } + }, + -- Password field with visibility toggle icon + { + type = "Box", + props = { className = "relative" }, + children = { + { + type = "Icon", + props = { + name = icons.get("LOCK"), + className = "absolute left-3 top-4 text-gray-400" + } + }, + { + type = "TextField", + props = { + label = "Password", + type = "password", + required = true, + className = "pl-10" + } + }, + { + type = "IconButton", + props = { + className = "absolute right-3 top-3", + onClick = "toggle_password_visibility" + }, + children = { + { type = "Icon", props = { name = icons.get("VISIBILITY") } } + } + } + } + }, + -- Submit button + { + type = "Button", + props = { + variant = "contained", + fullWidth = true, + onClick = "submit_login" + }, + children = { + { type = "Icon", props = { name = icons.get("SIGN_IN"), className = "mr-2" } }, + { type = "Typography", props = { text = "Sign In" } } + } + } + } + } + } + } +end + +---Create form with validation feedback icons +---@return UIComponent +function M.create_form_with_validation() + return { + type = "Stack", + props = { spacing = 3 }, + children = { + -- Success state + { + type = "Box", + props = { className = "relative" }, + children = { + { + type = "TextField", + props = { + label = "Username", + value = "johndoe", + helperText = "Username is available" + } + }, + { + type = "Icon", + props = { + name = icons.get("CHECK_CIRCLE"), + className = "absolute right-3 top-4 text-green-500" + } + } + } + }, + -- Error state + { + type = "Box", + props = { className = "relative" }, + children = { + { + type = "TextField", + props = { + label = "Email", + value = "invalid-email", + error = true, + helperText = "Please enter a valid email address" + } + }, + { + type = "Icon", + props = { + name = icons.get("ERROR"), + className = "absolute right-3 top-4 text-red-500" + } + } + } + }, + -- Warning state + { + type = "Box", + props = { className = "relative" }, + children = { + { + type = "TextField", + props = { + label = "Password", + helperText = "Password strength: weak" + } + }, + { + type = "Icon", + props = { + name = icons.get("WARNING_AMBER"), + className = "absolute right-3 top-4 text-yellow-500" + } + } + } + } + } + } +end + +return M diff --git a/packages/nav_menu/seed/scripts/examples/sidebar_with_icons.lua b/packages/nav_menu/seed/scripts/examples/sidebar_with_icons.lua new file mode 100644 index 000000000..6ac230915 --- /dev/null +++ b/packages/nav_menu/seed/scripts/examples/sidebar_with_icons.lua @@ -0,0 +1,94 @@ +-- Example: Sidebar navigation with icons +local icons = require("icons") +local sidebar = require("sidebar") + +---@class SidebarExample +local M = {} + +---Create example sidebar with icons +---@return UIComponent +function M.create_example_sidebar() + local items = { + { + label = "Dashboard", + path = "/dashboard", + icon = icons.get("DASHBOARD") + }, + { + label = "Analytics", + path = "/analytics", + icon = icons.get("ANALYTICS") + }, + { + label = "Users", + path = "/users", + icon = icons.get("USERS") + }, + { + label = "Database", + path = "/database", + icon = icons.get("DATABASE") + }, + { + label = "Settings", + path = "/settings", + icon = icons.get("SETTINGS") + }, + { + label = "Profile", + path = "/profile", + icon = icons.get("PROFILE") + } + } + + return sidebar.render({ + items = items, + currentPath = "/dashboard", + title = "Navigation" + }) +end + +---Create admin sidebar with icons +---@return UIComponent +function M.create_admin_sidebar() + local items = { + { + label = "Admin Panel", + path = "/admin", + icon = icons.get("ADMIN_PANEL") + }, + { + label = "User Management", + path = "/admin/users", + icon = icons.get("MANAGE_ACCOUNTS") + }, + { + label = "Security", + path = "/admin/security", + icon = icons.get("SECURITY") + }, + { + label = "Policies", + path = "/admin/policies", + icon = icons.get("POLICY") + }, + { + label = "Workflows", + path = "/admin/workflows", + icon = icons.get("WORKFLOW") + }, + { + label = "Schema", + path = "/admin/schema", + icon = icons.get("SCHEMA") + } + } + + return sidebar.render({ + items = items, + currentPath = "/admin", + title = "Admin" + }) +end + +return M diff --git a/packages/stats_grid/seed/scripts/formatters.lua b/packages/stats_grid/seed/scripts/formatters.lua new file mode 100644 index 000000000..bf26a08ca --- /dev/null +++ b/packages/stats_grid/seed/scripts/formatters.lua @@ -0,0 +1,11 @@ +-- Formatters module for stats display +local stats = require("stats") + +---@class FormattersModule +local M = {} + +-- Export formatting functions +M.formatLabel = stats.formatLabel +M.formatValue = stats.formatValue + +return M diff --git a/packages/stats_grid/seed/scripts/init.lua b/packages/stats_grid/seed/scripts/init.lua new file mode 100644 index 000000000..d90cafbf3 --- /dev/null +++ b/packages/stats_grid/seed/scripts/init.lua @@ -0,0 +1,7 @@ +-- Stats Grid Package +-- Provides configurable statistics grid display components + +return { + stats = require("stats"), + formatters = require("formatters") +} diff --git a/packages/stats_grid/seed/scripts/stats.lua b/packages/stats_grid/seed/scripts/stats.lua new file mode 100644 index 000000000..26e6baa46 --- /dev/null +++ b/packages/stats_grid/seed/scripts/stats.lua @@ -0,0 +1,2 @@ +-- Main entry point for stats module +return require("stats") diff --git a/packages/stats_grid/seed/scripts/stats/card.lua b/packages/stats_grid/seed/scripts/stats/card.lua new file mode 100644 index 000000000..1ce61d4db --- /dev/null +++ b/packages/stats_grid/seed/scripts/stats/card.lua @@ -0,0 +1,54 @@ +-- Individual stat card component +require("stats.types") +local stats = require("stats") + +---@class StatCard +local M = {} + +---Create a single stat card +---@param item StatItem +---@param cardClass? string +---@return UIComponent +function M.create(item, cardClass) + local colorClass = stats.getColorClass(item.color) + local defaultCardClass = cardClass or stats.getDefaultCardClass() + + return { + type = "Card", + props = { className = defaultCardClass }, + children = { + { + type = "CardHeader", + props = { className = "pb-2" }, + children = { + { + type = "CardTitle", + props = { + text = item.label, + className = "text-sm font-medium text-gray-400" + } + } + } + }, + { + type = "CardContent", + children = { + { + type = "Box", + props = { + className = "text-2xl font-bold " .. colorClass + }, + children = { + { + type = "Text", + props = { text = tostring(item.value) } + } + } + } + } + } + } + } +end + +return M diff --git a/packages/stats_grid/seed/scripts/stats/grid.lua b/packages/stats_grid/seed/scripts/stats/grid.lua new file mode 100644 index 000000000..32f669066 --- /dev/null +++ b/packages/stats_grid/seed/scripts/stats/grid.lua @@ -0,0 +1,29 @@ +-- Stats grid component +require("stats.types") +local stats = require("stats") +local card = require("stats.card") + +---@class StatsGrid +local M = {} + +---Create a stats grid component +---@param props StatsGridProps +---@return UIComponent +function M.create(props) + local items = stats.createStatItems(props.stats, props.config) + local gridClass = props.gridClass or stats.getDefaultGridClass() + + -- Build card components + local cards = {} + for _, item in ipairs(items) do + table.insert(cards, card.create(item, props.cardClass)) + end + + return { + type = "Box", + props = { className = gridClass }, + children = cards + } +end + +return M diff --git a/packages/stats_grid/seed/scripts/stats/init.lua b/packages/stats_grid/seed/scripts/stats/init.lua new file mode 100644 index 000000000..62462e5be --- /dev/null +++ b/packages/stats_grid/seed/scripts/stats/init.lua @@ -0,0 +1,85 @@ +-- Stats grid module +require("stats.types") +local json = require("json") + +---@class StatsModule +local M = {} + +-- Load configuration from JSON +---@type GridConfig +M.gridConfig = json.load("config.json") + +---Get color class for a stat +---@param color StatColor +---@return string +function M.getColorClass(color) + return M.gridConfig.colorClasses[color] or M.gridConfig.colorClasses.white +end + +---Get default grid class +---@return string +function M.getDefaultGridClass() + return M.gridConfig.defaultGridClass +end + +---Get default card class +---@return string +function M.getDefaultCardClass() + return M.gridConfig.defaultCardClass +end + +---Create stat items from data and config +---@param stats StatsData +---@param config? StatConfig[] +---@return StatItem[] +function M.createStatItems(stats, config) + local items = {} + + if config then + -- Use provided config + for _, cfg in ipairs(config) do + table.insert(items, { + key = cfg.key, + label = cfg.label, + value = stats[cfg.key] or 0, + color = cfg.color + }) + end + else + -- Auto-generate from stats data + for key, value in pairs(stats) do + table.insert(items, { + key = key, + label = M.formatLabel(key), + value = value, + color = "white" + }) + end + end + + return items +end + +---Format a key into a human-readable label +---@param key string +---@return string +function M.formatLabel(key) + -- Convert snake_case or camelCase to Title Case + local label = key:gsub("_", " "):gsub("(%l)(%u)", "%1 %2") + return label:gsub("^%l", string.upper) +end + +---Format a number value for display +---@param value number +---@return string +function M.formatValue(value) + if value >= 1000000 then + return string.format("%.1fM", value / 1000000) + elseif value >= 1000 then + return string.format("%.1fK", value / 1000) + else + return tostring(value) + end +end + +return M diff --git a/packages/workflow_editor/seed/scripts/examples/workflow_with_icons.lua b/packages/workflow_editor/seed/scripts/examples/workflow_with_icons.lua new file mode 100644 index 000000000..3ecda72f1 --- /dev/null +++ b/packages/workflow_editor/seed/scripts/examples/workflow_with_icons.lua @@ -0,0 +1,106 @@ +-- Example: Workflow editor with node icons +local icons = require("icons") +local action_node = require("nodes.action") +local condition = require("nodes.condition") +local start_node = require("nodes.start") +local end_node = require("nodes.end") + +---@class WorkflowExample +local M = {} + +---Create example workflow with icons +---@return table +function M.create_example_workflow() + return { + nodes = { + start_node("start", "Start Process", icons.get("PLAY_ARROW")), + action_node("validate", "Validate Data", "validation", icons.get("CHECK_CIRCLE")), + condition("check_status", "Check Status", icons.get("CALL_SPLIT")), + action_node("process_success", "Process Success", "transform", icons.get("DONE")), + action_node("process_error", "Handle Error", "error_handler", icons.get("ERROR")), + end_node("end", "End Process", icons.get("STOP")) + }, + edges = { + { from = "start", to = "validate" }, + { from = "validate", to = "check_status" }, + { from = "check_status", to = "process_success", condition = "success" }, + { from = "check_status", to = "process_error", condition = "error" }, + { from = "process_success", to = "end" }, + { from = "process_error", to = "end" } + } + } +end + +---Create workflow toolbar with icons +---@return UIComponent +function M.create_workflow_toolbar() + return { + type = "Stack", + props = { direction = "row", spacing = 1, className = "border-b p-2" }, + children = { + { + type = "IconButton", + props = { + onClick = "save_workflow", + title = "Save" + }, + children = { + { type = "Icon", props = { name = icons.get("SAVE") } } + } + }, + { + type = "IconButton", + props = { + onClick = "undo", + title = "Undo" + }, + children = { + { type = "Icon", props = { name = icons.get("UNDO") } } + } + }, + { + type = "IconButton", + props = { + onClick = "redo", + title = "Redo" + }, + children = { + { type = "Icon", props = { name = icons.get("REDO") } } + } + }, + { type = "Divider", props = { orientation = "vertical" } }, + { + type = "IconButton", + props = { + onClick = "zoom_in", + title = "Zoom In" + }, + children = { + { type = "Icon", props = { name = icons.get("ZOOM_IN") } } + } + }, + { + type = "IconButton", + props = { + onClick = "zoom_out", + title = "Zoom Out" + }, + children = { + { type = "Icon", props = { name = icons.get("ZOOM_OUT") } } + } + }, + { + type = "IconButton", + props = { + onClick = "center_view", + title = "Center View" + }, + children = { + { type = "Icon", props = { name = icons.get("CENTER_FOCUS") } } + } + } + } + } +end + +return M