config: packages,designer,css (7 files)

This commit is contained in:
Richard Ward
2025-12-30 19:59:29 +00:00
parent e7126be651
commit c85dbe59c6
7 changed files with 670 additions and 1 deletions

View File

@@ -26,7 +26,7 @@ export {
Settings,
User,
UserCheck,
Menu,
Menu as MenuIcon,
Eye,
EyeSlash,
Pencil,

View File

@@ -0,0 +1,242 @@
{
"components": [
{
"id": "CSSDesigner",
"type": "layout",
"props": {
"title": "CSS Designer",
"layout": "sidebar"
},
"children": [
{ "ref": "ColorPaletteEditor" },
{ "ref": "FontSelector" },
{ "ref": "SpacingEditor" },
{ "ref": "BorderEditor" },
{ "ref": "ShadowEditor" },
{ "ref": "StylePreview" }
],
"scripts": {
"onInit": "init.lua",
"onSave": "export/to_scss.lua"
}
},
{
"id": "ColorPaletteEditor",
"type": "form",
"props": {
"title": "Color Palette",
"icon": "Palette"
},
"children": [
{
"type": "color_picker",
"props": { "id": "primary", "label": "Primary Color", "defaultValue": "#1976d2" }
},
{
"type": "color_picker",
"props": { "id": "secondary", "label": "Secondary Color", "defaultValue": "#9c27b0" }
},
{
"type": "color_picker",
"props": { "id": "background", "label": "Background", "defaultValue": "#ffffff" }
},
{
"type": "color_picker",
"props": { "id": "surface", "label": "Surface", "defaultValue": "#f5f5f5" }
},
{
"type": "color_picker",
"props": { "id": "text_primary", "label": "Text Primary", "defaultValue": "#212121" }
},
{
"type": "color_picker",
"props": { "id": "text_secondary", "label": "Text Secondary", "defaultValue": "#757575" }
},
{
"type": "color_picker",
"props": { "id": "error", "label": "Error", "defaultValue": "#f44336" }
},
{
"type": "color_picker",
"props": { "id": "warning", "label": "Warning", "defaultValue": "#ff9800" }
},
{
"type": "color_picker",
"props": { "id": "success", "label": "Success", "defaultValue": "#4caf50" }
},
{
"type": "color_picker",
"props": { "id": "info", "label": "Info", "defaultValue": "#2196f3" }
}
],
"scripts": {
"onColorChange": "colors/color_picker.lua"
}
},
{
"id": "FontSelector",
"type": "form",
"props": {
"title": "Typography",
"icon": "TextFields"
},
"children": [
{
"type": "select",
"props": {
"id": "fontFamily",
"label": "Font Family",
"options": [
{ "value": "IBM Plex Sans", "label": "IBM Plex Sans (Default)" },
{ "value": "Inter", "label": "Inter" },
{ "value": "Roboto", "label": "Roboto" },
{ "value": "Open Sans", "label": "Open Sans" },
{ "value": "system-ui", "label": "System UI" }
]
}
},
{
"type": "select",
"props": {
"id": "headingFont",
"label": "Heading Font",
"options": [
{ "value": "Space Grotesk", "label": "Space Grotesk (Default)" },
{ "value": "Poppins", "label": "Poppins" },
{ "value": "Montserrat", "label": "Montserrat" }
]
}
},
{
"type": "select",
"props": {
"id": "codeFont",
"label": "Code Font",
"options": [
{ "value": "JetBrains Mono", "label": "JetBrains Mono (Default)" },
{ "value": "Fira Code", "label": "Fira Code" },
{ "value": "Source Code Pro", "label": "Source Code Pro" }
]
}
},
{
"type": "slider",
"props": {
"id": "baseFontSize",
"label": "Base Font Size",
"min": 12,
"max": 20,
"defaultValue": 16,
"unit": "px"
}
}
],
"scripts": {
"onFontChange": "fonts/font_selector.lua"
}
},
{
"id": "SpacingEditor",
"type": "form",
"props": {
"title": "Spacing",
"icon": "Grid"
},
"children": [
{
"type": "slider",
"props": { "id": "spacingUnit", "label": "Base Unit", "min": 4, "max": 16, "defaultValue": 8, "unit": "px" }
},
{
"type": "slider",
"props": { "id": "borderRadius", "label": "Border Radius", "min": 0, "max": 24, "defaultValue": 4, "unit": "px" }
},
{
"type": "slider",
"props": { "id": "containerWidth", "label": "Container Width", "min": 900, "max": 1400, "defaultValue": 1200, "unit": "px" }
}
],
"scripts": {
"onSpacingChange": "spacing/spacing_editor.lua"
}
},
{
"id": "BorderEditor",
"type": "form",
"props": {
"title": "Borders",
"icon": "CropFree"
},
"children": [
{
"type": "slider",
"props": { "id": "borderWidth", "label": "Border Width", "min": 0, "max": 4, "defaultValue": 1, "unit": "px" }
},
{
"type": "color_picker",
"props": { "id": "borderColor", "label": "Border Color", "defaultValue": "#e0e0e0" }
},
{
"type": "select",
"props": {
"id": "borderStyle",
"label": "Border Style",
"options": [
{ "value": "solid", "label": "Solid" },
{ "value": "dashed", "label": "Dashed" },
{ "value": "dotted", "label": "Dotted" }
]
}
}
],
"scripts": {
"onBorderChange": "borders/border_editor.lua"
}
},
{
"id": "ShadowEditor",
"type": "form",
"props": {
"title": "Shadows",
"icon": "Layers"
},
"children": [
{
"type": "slider",
"props": { "id": "shadowBlur", "label": "Blur Radius", "min": 0, "max": 24, "defaultValue": 4, "unit": "px" }
},
{
"type": "slider",
"props": { "id": "shadowSpread", "label": "Spread", "min": 0, "max": 12, "defaultValue": 0, "unit": "px" }
},
{
"type": "slider",
"props": { "id": "shadowOpacity", "label": "Opacity", "min": 0, "max": 100, "defaultValue": 15, "unit": "%" }
}
],
"scripts": {
"onShadowChange": "shadows/shadow_editor.lua"
}
},
{
"id": "StylePreview",
"type": "preview",
"props": {
"title": "Preview",
"icon": "Eye"
},
"children": [
{
"type": "card",
"props": { "className": "preview-card" },
"children": [
{ "type": "typography", "props": { "variant": "h4", "text": "Heading Preview" } },
{ "type": "typography", "props": { "variant": "body1", "text": "This is body text to preview your typography settings." } },
{ "type": "button", "props": { "variant": "contained", "text": "Primary Button" } },
{ "type": "button", "props": { "variant": "outlined", "text": "Secondary Button" } }
]
}
]
}
]
}

View File

@@ -0,0 +1,134 @@
-- Color picker utility functions
-- Single-purpose module for color conversion and manipulation
---@class ColorPicker
local M = {}
---Convert hex color to RGB
---@param hex string Hex color (e.g., "#1976d2" or "1976d2")
---@return RGBColor|nil rgb RGB color or nil if invalid
function M.hex_to_rgb(hex)
if not hex then return nil end
-- Remove # prefix if present
hex = hex:gsub("^#", "")
-- Validate length
if #hex ~= 6 and #hex ~= 3 then
return nil
end
-- Expand shorthand (e.g., "abc" -> "aabbcc")
if #hex == 3 then
hex = hex:sub(1,1):rep(2) .. hex:sub(2,2):rep(2) .. hex:sub(3,3):rep(2)
end
local r = tonumber(hex:sub(1,2), 16)
local g = tonumber(hex:sub(3,4), 16)
local b = tonumber(hex:sub(5,6), 16)
if not r or not g or not b then
return nil
end
return { r = r, g = g, b = b }
end
---Convert RGB to hex color
---@param rgb RGBColor RGB color
---@return string hex Hex color string
function M.rgb_to_hex(rgb)
return string.format("#%02x%02x%02x", rgb.r, rgb.g, rgb.b)
end
---Convert hex to HSL color
---@param hex string Hex color
---@return HSLColor|nil hsl HSL color or nil if invalid
function M.hex_to_hsl(hex)
local rgb = M.hex_to_rgb(hex)
if not rgb then return nil end
local r, g, b = rgb.r / 255, rgb.g / 255, rgb.b / 255
local max, min = math.max(r, g, b), math.min(r, g, b)
local h, s, l = 0, 0, (max + min) / 2
if max ~= min then
local d = max - min
s = l > 0.5 and d / (2 - max - min) or d / (max + min)
if max == r then
h = (g - b) / d + (g < b and 6 or 0)
elseif max == g then
h = (b - r) / d + 2
else
h = (r - g) / d + 4
end
h = h / 6
end
return {
h = math.floor(h * 360),
s = math.floor(s * 100),
l = math.floor(l * 100)
}
end
---Convert HSL to hex color
---@param hsl HSLColor HSL color
---@return string hex Hex color string
function M.hsl_to_hex(hsl)
local h, s, l = hsl.h / 360, hsl.s / 100, hsl.l / 100
local function hue_to_rgb(p, q, t)
if t < 0 then t = t + 1 end
if t > 1 then t = t - 1 end
if t < 1/6 then return p + (q - p) * 6 * t end
if t < 1/2 then return q end
if t < 2/3 then return p + (q - p) * (2/3 - t) * 6 end
return p
end
local r, g, b
if s == 0 then
r, g, b = l, l, l
else
local q = l < 0.5 and l * (1 + s) or l + s - l * s
local p = 2 * l - q
r = hue_to_rgb(p, q, h + 1/3)
g = hue_to_rgb(p, q, h)
b = hue_to_rgb(p, q, h - 1/3)
end
return M.rgb_to_hex({
r = math.floor(r * 255 + 0.5),
g = math.floor(g * 255 + 0.5),
b = math.floor(b * 255 + 0.5)
})
end
---Adjust the lightness of a color
---@param hex string Hex color
---@param amount number Amount to adjust (-100 to 100)
---@return string hex Adjusted hex color
function M.adjust_lightness(hex, amount)
local hsl = M.hex_to_hsl(hex)
if not hsl then return hex end
hsl.l = math.max(0, math.min(100, hsl.l + amount))
return M.hsl_to_hex(hsl)
end
---Adjust the saturation of a color
---@param hex string Hex color
---@param amount number Amount to adjust (-100 to 100)
---@return string hex Adjusted hex color
function M.adjust_saturation(hex, amount)
local hsl = M.hex_to_hsl(hex)
if not hsl then return hex end
hsl.s = math.max(0, math.min(100, hsl.s + amount))
return M.hsl_to_hex(hsl)
end
return M

View File

@@ -0,0 +1,23 @@
-- Color utility functions facade
-- Re-exports all color-related functions
local colorPicker = require("colors.color_picker")
local palette = require("colors.palette")
---@class ColorsModule
local M = {}
-- Re-export color picker functions
M.hex_to_rgb = colorPicker.hex_to_rgb
M.rgb_to_hex = colorPicker.rgb_to_hex
M.hex_to_hsl = colorPicker.hex_to_hsl
M.hsl_to_hex = colorPicker.hsl_to_hex
M.adjust_lightness = colorPicker.adjust_lightness
M.adjust_saturation = colorPicker.adjust_saturation
-- Re-export palette functions
M.generate_shades = palette.generate_shades
M.generate_tints = palette.generate_tints
M.create_palette = palette.create_palette
return M

View File

@@ -0,0 +1,73 @@
-- Color palette generation functions
-- Creates color variations from a base color
local colorPicker = require("colors.color_picker")
---@class Palette
local M = {}
---Generate darker shades of a color
---@param hex string Base hex color
---@param count? number Number of shades (default 5)
---@return string[] shades Array of hex colors from base to darkest
function M.generate_shades(hex, count)
count = count or 5
local shades = { hex }
local step = 80 / count
for i = 1, count - 1 do
local shade = colorPicker.adjust_lightness(hex, -step * i)
table.insert(shades, shade)
end
return shades
end
---Generate lighter tints of a color
---@param hex string Base hex color
---@param count? number Number of tints (default 5)
---@return string[] tints Array of hex colors from base to lightest
function M.generate_tints(hex, count)
count = count or 5
local tints = { hex }
local step = 80 / count
for i = 1, count - 1 do
local tint = colorPicker.adjust_lightness(hex, step * i)
table.insert(tints, tint)
end
return tints
end
---Create a full color palette from a base color
---@param hex string Base hex color
---@return table palette Palette with shades and tints
function M.create_palette(hex)
local hsl = colorPicker.hex_to_hsl(hex)
if not hsl then
return { base = hex, shades = {hex}, tints = {hex} }
end
-- Generate palette scales (50, 100, 200, ... 900)
local scale = {}
local lightness_values = {95, 90, 80, 70, 60, 50, 40, 30, 20, 10}
local scale_names = {50, 100, 200, 300, 400, 500, 600, 700, 800, 900}
for i, l in ipairs(lightness_values) do
scale[scale_names[i]] = colorPicker.hsl_to_hex({
h = hsl.h,
s = hsl.s,
l = l
})
end
return {
base = hex,
scale = scale,
shades = M.generate_shades(hex, 5),
tints = M.generate_tints(hex, 5)
}
end
return M

View File

@@ -0,0 +1,68 @@
-- CSS Designer initialization
-- Main entry point for the css_designer package
---@class CSSDesigner
---@field name string Package name
---@field version string Package version
local M = {}
M.name = "css_designer"
M.version = "1.0.0"
---@class InitResult
---@field name string Package name
---@field version string Package version
---@field loaded boolean Whether successfully loaded
---Initialize the CSS designer module
---@return InitResult
function M.init()
return {
name = M.name,
version = M.version,
loaded = true
}
end
---Get default theme configuration
---@return ThemeConfig
function M.get_default_theme()
return {
name = "Default",
colors = {
primary = { hex = "#1976d2" },
secondary = { hex = "#9c27b0" },
background = { hex = "#ffffff" },
surface = { hex = "#f5f5f5" },
text_primary = { hex = "#212121" },
text_secondary = { hex = "#757575" },
error = { hex = "#f44336" },
warning = { hex = "#ff9800" },
success = { hex = "#4caf50" },
info = { hex = "#2196f3" }
},
typography = {
fontFamily = "IBM Plex Sans",
headingFont = "Space Grotesk",
codeFont = "JetBrains Mono",
baseFontSize = 16
},
spacing = {
spacingUnit = 8,
borderRadius = 4,
containerWidth = 1200
},
borders = {
width = 1,
color = { hex = "#e0e0e0" },
style = "solid"
},
shadows = {
blur = 4,
spread = 0,
opacity = 15
}
}
end
return M

View File

@@ -0,0 +1,129 @@
-- LuaCATS type definitions for css_designer package
-- Provides types for visual CSS design and style export
-- See: https://luals.github.io/wiki/annotations/
--------------------------------------------------------------------------------
-- Color Types
--------------------------------------------------------------------------------
---@class ColorValue
---@field hex string Hex color value (e.g., "#1976d2")
---@field rgb? RGBColor RGB representation
---@field hsl? HSLColor HSL representation
---@field alpha? number Alpha/opacity (0-1)
---@class RGBColor
---@field r number Red (0-255)
---@field g number Green (0-255)
---@field b number Blue (0-255)
---@class HSLColor
---@field h number Hue (0-360)
---@field s number Saturation (0-100)
---@field l number Lightness (0-100)
---@class ColorPalette
---@field primary ColorValue Primary brand color
---@field secondary ColorValue Secondary brand color
---@field background ColorValue Background color
---@field surface ColorValue Surface/card color
---@field text_primary ColorValue Primary text color
---@field text_secondary ColorValue Secondary text color
---@field error ColorValue Error state color
---@field warning ColorValue Warning state color
---@field success ColorValue Success state color
---@field info ColorValue Info state color
--------------------------------------------------------------------------------
-- Typography Types
--------------------------------------------------------------------------------
---@class TypographyConfig
---@field fontFamily string Primary font family
---@field headingFont string Heading font family
---@field codeFont string Monospace/code font family
---@field baseFontSize number Base font size in pixels
---@field lineHeight? number Line height multiplier
---@field letterSpacing? number Letter spacing in em
---@class FontOption
---@field value string Font family value
---@field label string Display label
---@field category? "sans-serif"|"serif"|"monospace" Font category
--------------------------------------------------------------------------------
-- Spacing Types
--------------------------------------------------------------------------------
---@class SpacingConfig
---@field spacingUnit number Base spacing unit in pixels
---@field borderRadius number Default border radius in pixels
---@field containerWidth number Max container width in pixels
---@class SpacingScale
---@field xs number Extra small spacing
---@field sm number Small spacing
---@field md number Medium spacing
---@field lg number Large spacing
---@field xl number Extra large spacing
--------------------------------------------------------------------------------
-- Border Types
--------------------------------------------------------------------------------
---@class BorderConfig
---@field width number Border width in pixels
---@field color ColorValue Border color
---@field style "solid"|"dashed"|"dotted"|"none" Border style
---@field radius? number Border radius override
--------------------------------------------------------------------------------
-- Shadow Types
--------------------------------------------------------------------------------
---@class ShadowConfig
---@field blur number Blur radius in pixels
---@field spread number Spread radius in pixels
---@field opacity number Shadow opacity (0-100)
---@field offsetX? number Horizontal offset
---@field offsetY? number Vertical offset
---@field color? ColorValue Shadow color
---@class ShadowPreset
---@field name string Preset name
---@field config ShadowConfig Shadow configuration
--------------------------------------------------------------------------------
-- Theme Types
--------------------------------------------------------------------------------
---@class ThemeConfig
---@field name string Theme name
---@field colors ColorPalette Color palette
---@field typography TypographyConfig Typography settings
---@field spacing SpacingConfig Spacing settings
---@field borders BorderConfig Border defaults
---@field shadows ShadowConfig Shadow defaults
---@class ThemeExport
---@field scss string SCSS variable output
---@field css string CSS custom properties output
---@field json string JSON configuration output
--------------------------------------------------------------------------------
-- Component Types
--------------------------------------------------------------------------------
---@class DesignerState
---@field theme ThemeConfig Current theme configuration
---@field isDirty boolean Has unsaved changes
---@field previewMode "light"|"dark" Preview mode
---@class EditorProps
---@field value any Current value
---@field onChange fun(value: any): void Change handler
---@field label string Field label
---@field disabled? boolean Whether editor is disabled
-- Export types (no runtime exports)
return {}