From 770ffeb424bbb7e220f55019cae77bcabdcdfbb8 Mon Sep 17 00:00:00 2001 From: Richard Ward Date: Tue, 30 Dec 2025 21:13:24 +0000 Subject: [PATCH] config: storybook,src,json (4 files) --- storybook/src/mocks/data/dashboard.json | 127 +++++++++++++++++++++ storybook/src/mocks/data/ui_level4.json | 119 +++++++++++++++++++ storybook/src/mocks/data/user_manager.json | 116 +++++++++++++++++++ storybook/src/mocks/schema.ts | 88 ++++++++++++++ 4 files changed, 450 insertions(+) create mode 100644 storybook/src/mocks/data/dashboard.json create mode 100644 storybook/src/mocks/data/ui_level4.json create mode 100644 storybook/src/mocks/data/user_manager.json create mode 100644 storybook/src/mocks/schema.ts diff --git a/storybook/src/mocks/data/dashboard.json b/storybook/src/mocks/data/dashboard.json new file mode 100644 index 000000000..6d01efbff --- /dev/null +++ b/storybook/src/mocks/data/dashboard.json @@ -0,0 +1,127 @@ +{ + "metadata": { + "packageId": "dashboard", + "name": "Dashboard", + "version": "1.0.0", + "description": "Dashboard layouts, stat cards, and widgets", + "category": "ui", + "minLevel": 2, + "exports": { + "components": ["StatCard", "DashboardGrid", "Widget"], + "scripts": ["stats", "layout"] + } + }, + "renders": { + "init.lua": { + "description": "Lifecycle hooks - no visual render", + "component": { + "type": "Alert", + "props": { "severity": "info" }, + "children": [ + { "type": "Typography", "props": { "variant": "body2", "text": "init.lua contains lifecycle hooks (on_install, on_update) - no visual render" } } + ] + } + }, + "stats.lua": { + "description": "Statistics grid with metric cards", + "component": { + "type": "Grid", + "props": { "container": true, "spacing": 3 }, + "children": [ + { + "type": "Grid", + "props": { "item": true, "xs": 12, "sm": 6, "md": 3 }, + "children": [{ + "type": "Card", + "children": [{ + "type": "CardContent", + "children": [ + { "type": "Icon", "props": { "name": "users", "color": "primary" } }, + { "type": "Typography", "props": { "variant": "overline", "text": "Total Users" } }, + { "type": "Typography", "props": { "variant": "h4", "text": "1,234" } }, + { "type": "Typography", "props": { "variant": "caption", "text": "+12.5%", "color": "success" } } + ] + }] + }] + }, + { + "type": "Grid", + "props": { "item": true, "xs": 12, "sm": 6, "md": 3 }, + "children": [{ + "type": "Card", + "children": [{ + "type": "CardContent", + "children": [ + { "type": "Icon", "props": { "name": "dollar", "color": "success" } }, + { "type": "Typography", "props": { "variant": "overline", "text": "Revenue" } }, + { "type": "Typography", "props": { "variant": "h4", "text": "$45.2K" } }, + { "type": "Typography", "props": { "variant": "caption", "text": "+8.1%", "color": "success" } } + ] + }] + }] + }, + { + "type": "Grid", + "props": { "item": true, "xs": 12, "sm": 6, "md": 3 }, + "children": [{ + "type": "Card", + "children": [{ + "type": "CardContent", + "children": [ + { "type": "Icon", "props": { "name": "shopping-cart", "color": "warning" } }, + { "type": "Typography", "props": { "variant": "overline", "text": "Orders" } }, + { "type": "Typography", "props": { "variant": "h4", "text": "892" } }, + { "type": "Typography", "props": { "variant": "caption", "text": "-2.4%", "color": "error" } } + ] + }] + }] + }, + { + "type": "Grid", + "props": { "item": true, "xs": 12, "sm": 6, "md": 3 }, + "children": [{ + "type": "Card", + "children": [{ + "type": "CardContent", + "children": [ + { "type": "Icon", "props": { "name": "activity", "color": "info" } }, + { "type": "Typography", "props": { "variant": "overline", "text": "Active Now" } }, + { "type": "Typography", "props": { "variant": "h4", "text": "573" } }, + { "type": "Typography", "props": { "variant": "caption", "text": "+18%", "color": "success" } } + ] + }] + }] + } + ] + } + }, + "layout.lua": { + "description": "Standard dashboard layout with header", + "component": { + "type": "Box", + "props": { "sx": { "minHeight": "100vh", "bgcolor": "background.default" } }, + "children": [ + { + "type": "AppHeader", + "children": [{ + "type": "Flex", + "props": { "justifyContent": "space-between", "alignItems": "center" }, + "children": [ + { "type": "Typography", "props": { "variant": "h5", "text": "Dashboard" } }, + { "type": "Typography", "props": { "variant": "body2", "text": "Welcome, {{user.username}}" } } + ] + }] + }, + { + "type": "Container", + "props": { "maxWidth": "xl", "sx": { "py": 4 } }, + "children": [ + { "type": "Typography", "props": { "variant": "h3", "text": "Welcome back!" } }, + { "type": "Typography", "props": { "variant": "body1", "color": "text.secondary", "text": "Here's what's happening with your projects." } } + ] + } + ] + } + } + } +} diff --git a/storybook/src/mocks/data/ui_level4.json b/storybook/src/mocks/data/ui_level4.json new file mode 100644 index 000000000..31fee29cf --- /dev/null +++ b/storybook/src/mocks/data/ui_level4.json @@ -0,0 +1,119 @@ +{ + "metadata": { + "packageId": "ui_level4", + "name": "Level 4 - Admin Panel", + "version": "1.0.0", + "description": "Admin panel for user and system management", + "category": "ui", + "minLevel": 4, + "dependencies": ["ui_permissions", "ui_header", "ui_intro", "user_manager", "admin_dialog"], + "exports": { + "pages": ["level4"], + "scripts": ["layout", "schemas", "workflows"] + } + }, + "renders": { + "init.lua": { + "description": "Lifecycle hooks", + "component": { + "type": "Alert", + "props": { "severity": "info" }, + "children": [ + { "type": "Typography", "props": { "variant": "body2", "text": "init.lua contains lifecycle hooks - no visual render" } } + ] + } + }, + "layout.lua": { + "description": "Main admin panel layout", + "component": { + "type": "Box", + "props": { "sx": { "minHeight": "100vh", "bgcolor": "background.default" } }, + "children": [ + { + "type": "Level4Header", + "props": { "username": "{{user.username}}", "nerdMode": "{{nerdMode}}" } + }, + { + "type": "Container", + "props": { "maxWidth": "xl", "sx": { "py": 4 } }, + "children": [ + { + "type": "IntroSection", + "props": { + "eyebrow": "Level 4", + "title": "Application Builder", + "description": "Build and manage your application components" + } + }, + { + "type": "Tabs", + "props": { + "items": [ + { "value": "schemas", "label": "Schemas" }, + { "value": "workflows", "label": "Workflows" }, + { "value": "users", "label": "Users" }, + { "value": "settings", "label": "Settings" } + ] + } + } + ] + } + ] + } + }, + "schemas.lua": { + "description": "Schema editor interface", + "component": { + "type": "Stack", + "props": { "spacing": 3 }, + "children": [ + { + "type": "Card", + "children": [ + { + "type": "CardHeader", + "children": [ + { "type": "Typography", "props": { "variant": "h5", "text": "Schema Editor" } } + ] + }, + { + "type": "CardContent", + "children": [ + { "type": "Typography", "props": { "variant": "body2", "color": "text.secondary", "text": "Define data models and validation rules for your application." } }, + { "type": "Button", "props": { "variant": "contained", "children": "Create Schema" } } + ] + } + ] + } + ] + } + }, + "workflows.lua": { + "description": "Workflow designer interface", + "component": { + "type": "Stack", + "props": { "spacing": 3 }, + "children": [ + { + "type": "Card", + "children": [ + { + "type": "CardHeader", + "children": [ + { "type": "Typography", "props": { "variant": "h5", "text": "Workflow Designer" } } + ] + }, + { + "type": "CardContent", + "children": [ + { "type": "Typography", "props": { "variant": "body2", "color": "text.secondary", "text": "Create automated workflows with visual node-based editor." } }, + { "type": "Button", "props": { "variant": "contained", "children": "New Workflow" } } + ] + } + ] + } + ] + } + } + } +} diff --git a/storybook/src/mocks/data/user_manager.json b/storybook/src/mocks/data/user_manager.json new file mode 100644 index 000000000..efc2408c8 --- /dev/null +++ b/storybook/src/mocks/data/user_manager.json @@ -0,0 +1,116 @@ +{ + "metadata": { + "packageId": "user_manager", + "name": "User Manager", + "version": "1.0.0", + "description": "User management with roles and permissions", + "category": "admin", + "minLevel": 4, + "exports": { + "scripts": ["list", "create_user", "render_users"] + } + }, + "renders": { + "init.lua": { + "description": "Lifecycle hooks", + "component": { + "type": "Alert", + "props": { "severity": "info" }, + "children": [ + { "type": "Typography", "props": { "variant": "body2", "text": "init.lua contains lifecycle hooks - no visual render" } } + ] + } + }, + "render_users.lua": { + "description": "User management table", + "component": { + "type": "Card", + "children": [ + { + "type": "CardHeader", + "children": [{ + "type": "Flex", + "props": { "justifyContent": "space-between", "alignItems": "center" }, + "children": [ + { "type": "Typography", "props": { "variant": "h5", "text": "Users" } }, + { "type": "Button", "props": { "variant": "contained", "children": "Add User" } } + ] + }] + }, + { + "type": "CardContent", + "children": [{ + "type": "Table", + "props": { + "columns": [ + { "field": "username", "headerName": "Username" }, + { "field": "email", "headerName": "Email" }, + { "field": "level", "headerName": "Level" }, + { "field": "status", "headerName": "Status" }, + { "field": "actions", "headerName": "Actions" } + ], + "rows": [ + { "id": 1, "username": "admin", "email": "admin@example.com", "level": 6, "status": "Active" }, + { "id": 2, "username": "moderator", "email": "mod@example.com", "level": 3, "status": "Active" }, + { "id": 3, "username": "user1", "email": "user1@example.com", "level": 2, "status": "Inactive" } + ] + } + }] + } + ] + } + }, + "list.lua": { + "description": "Simple user list", + "component": { + "type": "Stack", + "props": { "spacing": 1 }, + "children": [ + { "type": "Typography", "props": { "variant": "h6", "text": "User List" } }, + { "type": "Typography", "props": { "variant": "body2", "text": "• admin (Level 6)" } }, + { "type": "Typography", "props": { "variant": "body2", "text": "• moderator (Level 3)" } }, + { "type": "Typography", "props": { "variant": "body2", "text": "• user1 (Level 2)" } } + ] + } + }, + "create_user.lua": { + "description": "Create user form", + "component": { + "type": "Card", + "children": [ + { + "type": "CardHeader", + "children": [ + { "type": "Typography", "props": { "variant": "h5", "text": "Create User" } } + ] + }, + { + "type": "CardContent", + "children": [{ + "type": "Stack", + "props": { "spacing": 3 }, + "children": [ + { "type": "TextField", "props": { "label": "Username", "placeholder": "Enter username", "fullWidth": true } }, + { "type": "TextField", "props": { "label": "Email", "placeholder": "user@example.com", "fullWidth": true } }, + { "type": "TextField", "props": { "label": "Password", "type": "password", "fullWidth": true } }, + { + "type": "Select", + "props": { + "label": "Level", + "options": [ + { "value": 1, "label": "Public (1)" }, + { "value": 2, "label": "User (2)" }, + { "value": 3, "label": "Moderator (3)" }, + { "value": 4, "label": "Admin (4)" } + ] + } + }, + { "type": "Button", "props": { "variant": "contained", "children": "Create User" } } + ] + }] + } + ] + } + } + } +} diff --git a/storybook/src/mocks/schema.ts b/storybook/src/mocks/schema.ts new file mode 100644 index 000000000..a67ae1f5f --- /dev/null +++ b/storybook/src/mocks/schema.ts @@ -0,0 +1,88 @@ +/** + * JSON Schema types for data-driven mock definitions + * + * Mock packages are defined in JSON files and automatically loaded. + * No TypeScript boilerplate needed - just define the component trees in JSON. + */ + +import type { LuaUIComponent, LuaPackageMetadata } from '../types/lua-types' + +/** + * A mock render definition in JSON format + * Supports simple static renders and template variables + */ +export interface JsonMockRender { + /** The component tree to render */ + component: LuaUIComponent + /** Optional description shown in Storybook */ + description?: string +} + +/** + * A complete mock package definition in JSON + */ +export interface JsonMockPackage { + /** Package metadata */ + metadata: LuaPackageMetadata + /** + * Render definitions keyed by script name + * e.g., "init.lua", "layout.lua", "render_users" + */ + renders: Record +} + +/** + * Template variables that can be used in JSON mocks + * Use {{variable}} syntax in string props + */ +export interface TemplateVariables { + 'user.username': string + 'user.email': string + 'user.level': number + 'user.id': string + 'tenant.name': string + 'tenant.id': string + 'nerdMode': boolean + 'theme': string + [key: string]: unknown +} + +/** + * Process template variables in a component tree + * Replaces {{variable}} with actual values from context + */ +export function processTemplates( + component: LuaUIComponent, + variables: TemplateVariables +): LuaUIComponent { + const processValue = (value: unknown): unknown => { + if (typeof value === 'string') { + // Replace {{variable}} patterns + return value.replace(/\{\{([^}]+)\}\}/g, (_, key) => { + const keys = key.trim().split('.') + let result: unknown = variables + for (const k of keys) { + if (result && typeof result === 'object') { + result = (result as Record)[k] + } else { + return `{{${key}}}` + } + } + return String(result ?? `{{${key}}}`) + }) + } + if (Array.isArray(value)) { + return value.map(processValue) + } + if (value && typeof value === 'object') { + const processed: Record = {} + for (const [k, v] of Object.entries(value)) { + processed[k] = processValue(v) + } + return processed + } + return value + } + + return processValue(component) as LuaUIComponent +}