docs: packages,lua,stats (12 files)

This commit is contained in:
Richard Ward
2025-12-30 14:31:20 +00:00
parent d9369d3137
commit 3ff6f2b779
12 changed files with 1086 additions and 0 deletions

View File

@@ -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`

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,7 @@
-- Stats Grid Package
-- Provides configurable statistics grid display components
return {
stats = require("stats"),
formatters = require("formatters")
}

View File

@@ -0,0 +1,2 @@
-- Main entry point for stats module
return require("stats")

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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