diff --git a/frontends/nextjs/src/components/editors/JsonEditor.tsx b/frontends/nextjs/src/components/editors/JsonEditor.tsx index 73907d312..f575e5005 100644 --- a/frontends/nextjs/src/components/editors/JsonEditor.tsx +++ b/frontends/nextjs/src/components/editors/JsonEditor.tsx @@ -133,7 +133,7 @@ export function JsonEditor({ open, onClose, title, value, onSave, schema }: Json {securityScanResult.issues.length} security{' '} {securityScanResult.issues.length === 1 ? 'issue' : 'issues'} -  detected. Click Security Scan to review. + detected. Click Security Scan to review. )} diff --git a/frontends/nextjs/src/components/managers/css/class-builder/hooks.ts b/frontends/nextjs/src/components/managers/css/class-builder/hooks.ts index 02409f0f7..93ee45928 100644 --- a/frontends/nextjs/src/components/managers/css/class-builder/hooks.ts +++ b/frontends/nextjs/src/components/managers/css/class-builder/hooks.ts @@ -3,7 +3,7 @@ import { toast } from 'sonner' import { CssCategory, Database } from '@/lib/database' -const CLASS_TOKEN_PATTERN = /^[A-Za-z0-9:_/.\[\]()%#!,=+-]+$/ +const CLASS_TOKEN_PATTERN = /^[A-Za-z0-9:_/.[\]()%#!,=+-]+$/ const parseClassList = (value: string) => Array.from(new Set(value.split(/\s+/).filter(Boolean))) interface UseClassBuilderStateProps { diff --git a/frontends/nextjs/src/lib/lua/ui/call-lua-function.ts b/frontends/nextjs/src/lib/lua/ui/call-lua-function.ts index 60c91ccd5..86b84c8d2 100644 --- a/frontends/nextjs/src/lib/lua/ui/call-lua-function.ts +++ b/frontends/nextjs/src/lib/lua/ui/call-lua-function.ts @@ -1,4 +1,5 @@ import * as fengari from 'fengari-web' + import { fromLua } from '@/lib/lua/functions/converters/from-lua' const lua = fengari.lua diff --git a/frontends/nextjs/src/lib/lua/ui/generate-component-tree.test.tsx b/frontends/nextjs/src/lib/lua/ui/generate-component-tree.test.tsx index c0911f282..64b1aeb7c 100644 --- a/frontends/nextjs/src/lib/lua/ui/generate-component-tree.test.tsx +++ b/frontends/nextjs/src/lib/lua/ui/generate-component-tree.test.tsx @@ -1,5 +1,6 @@ -import { describe, it, expect } from 'bun:test' +import { describe, expect,it } from 'bun:test' import React from 'react' + import { generateComponentTree } from './generate-component-tree' import type { LuaUIComponent } from './types/lua-ui-package' diff --git a/frontends/nextjs/src/lib/lua/ui/load-lua-ui-package.ts b/frontends/nextjs/src/lib/lua/ui/load-lua-ui-package.ts index c44683f87..03c1ea9c1 100644 --- a/frontends/nextjs/src/lib/lua/ui/load-lua-ui-package.ts +++ b/frontends/nextjs/src/lib/lua/ui/load-lua-ui-package.ts @@ -1,9 +1,11 @@ +import * as fengari from 'fengari-web' import { readFile } from 'fs/promises' import { join } from 'path' -import * as fengari from 'fengari-web' + import { createLuaEngine } from '@/lib/lua/engine/core/create-lua-engine' -import { pushToLua } from '@/lib/lua/functions/converters/push-to-lua' import { fromLua } from '@/lib/lua/functions/converters/from-lua' +import { pushToLua } from '@/lib/lua/functions/converters/push-to-lua' + import { normalizeLuaComponent } from './normalize-lua-structure' import type { LuaUIManifest, LuaUIPackage, LuaUIPage } from './types/lua-ui-package' @@ -85,7 +87,7 @@ export async function loadLuaUIPackage(packagePath: string): Promise = {} + const actions: Record any> = {} if (manifest.actions) { for (const actionManifest of manifest.actions) { const actionPath = join(packagePath, actionManifest.file) @@ -148,7 +150,7 @@ export async function loadLuaUIPackage(packagePath: string): Promise any { return (...args: any[]) => { // Create a new Lua engine for this call const engine = createLuaEngine() diff --git a/frontends/nextjs/src/lib/lua/ui/types/lua-ui-package.ts b/frontends/nextjs/src/lib/lua/ui/types/lua-ui-package.ts index 1f39072bc..3da417d93 100644 --- a/frontends/nextjs/src/lib/lua/ui/types/lua-ui-package.ts +++ b/frontends/nextjs/src/lib/lua/ui/types/lua-ui-package.ts @@ -58,7 +58,7 @@ export interface LuaUIComponent { export interface LuaUIAction { name: string - handler: string | Function + handler: string | ((...args: any[]) => any) } export interface LuaUIValidation { @@ -71,7 +71,7 @@ export interface LuaUIValidation { max?: number pattern?: string format?: string - custom?: string | Function + custom?: string | ((...args: any[]) => any) } } @@ -81,5 +81,5 @@ export interface LuaUIValidation { export interface LuaUIPackage { manifest: LuaUIManifest pages: LuaUIPage[] - actions: Record + actions: Record any> } diff --git a/frontends/nextjs/src/lib/packages/lua-ui/level1-page/level1-ui.json b/frontends/nextjs/src/lib/packages/lua-ui/level1-page/level1-ui.json new file mode 100644 index 000000000..669df98a4 --- /dev/null +++ b/frontends/nextjs/src/lib/packages/lua-ui/level1-page/level1-ui.json @@ -0,0 +1,118 @@ +{ + "type": "Box", + "props": { + "className": "min-h-screen bg-gradient-to-br from-primary/5 via-background to-accent/5" + }, + "children": [ + { + "type": "NavigationBar", + "props": { + "level": 1, + "onNavigate": "handleNavigate" + } + }, + { + "type": "Container", + "props": { + "maxWidth": "lg", + "className": "px-4 sm:px-6 lg:px-8 pt-6 space-y-6" + }, + "children": [ + { + "type": "Card", + "children": [ + { + "type": "CardHeader", + "children": [ + { + "type": "CardTitle", + "props": { "text": "Server Status" } + } + ] + }, + { + "type": "CardContent", + "children": [ + { + "type": "Typography", + "props": { + "variant": "body1", + "text": "MetaBuilder Development Server" + } + }, + { + "type": "Typography", + "props": { + "variant": "body2", + "color": "textSecondary", + "text": "Status: Active" + } + } + ] + } + ] + }, + { + "type": "Tabs", + "props": { "defaultValue": "overview" }, + "children": [ + { + "type": "TabsList", + "children": [ + { + "type": "TabsTrigger", + "props": { "value": "overview", "text": "Overview" } + }, + { + "type": "TabsTrigger", + "props": { "value": "features", "text": "Features" } + }, + { + "type": "TabsTrigger", + "props": { "value": "docs", "text": "Documentation" } + } + ] + }, + { + "type": "TabsContent", + "props": { "value": "overview" }, + "children": [ + { + "type": "Stack", + "props": { "spacing": 2 }, + "children": [ + { + "type": "Typography", + "props": { + "variant": "h5", + "text": "Welcome to MetaBuilder" + } + }, + { + "type": "Typography", + "props": { + "variant": "body1", + "text": "MetaBuilder is a powerful data-driven platform with multi-level navigation." + } + }, + { + "type": "Button", + "props": { + "variant": "contained", + "text": "Explore Level 2", + "onClick": "navigateToLevel2" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "AppFooter" + } + ] +} diff --git a/frontends/nextjs/src/lib/packages/lua-ui/level1-page/level1-ui.lua b/frontends/nextjs/src/lib/packages/lua-ui/level1-page/level1-ui.lua new file mode 100644 index 000000000..dad7d1c2c --- /dev/null +++ b/frontends/nextjs/src/lib/packages/lua-ui/level1-page/level1-ui.lua @@ -0,0 +1,137 @@ +local M = {} + +function M.render() + return { + type = "Box", + props = { + className = "min-h-screen bg-gradient-to-br from-primary/5 via-background to-accent/5" + }, + children = { + -- Navigation Bar + { + type = "NavigationBar", + props = { + level = 1, + onNavigate = "handleNavigate" + } + }, + + -- Main Content + { + type = "Container", + props = { + maxWidth = "lg", + className = "px-4 sm:px-6 lg:px-8 pt-6 space-y-6" + }, + children = { + -- Credentials Section + { + type = "Card", + props = {}, + children = { + { + type = "CardHeader", + props = {}, + children = { + { + type = "CardTitle", + props = { text = "Server Status" } + } + } + }, + { + type = "CardContent", + props = {}, + children = { + { + type = "Typography", + props = { + variant = "body1", + text = "MetaBuilder Development Server" + } + }, + { + type = "Typography", + props = { + variant = "body2", + color = "textSecondary", + text = "Status: Active" + } + } + } + } + } + }, + + -- Level Tabs + { + type = "Tabs", + props = { defaultValue = "overview" }, + children = { + { + type = "TabsList", + props = {}, + children = { + { + type = "TabsTrigger", + props = { value = "overview", text = "Overview" } + }, + { + type = "TabsTrigger", + props = { value = "features", text = "Features" } + }, + { + type = "TabsTrigger", + props = { value = "docs", text = "Documentation" } + } + } + }, + { + type = "TabsContent", + props = { value = "overview" }, + children = { + { + type = "Stack", + props = { spacing = 2 }, + children = { + { + type = "Typography", + props = { + variant = "h5", + text = "Welcome to MetaBuilder" + } + }, + { + type = "Typography", + props = { + variant = "body1", + text = "MetaBuilder is a powerful data-driven platform with multi-level navigation." + } + }, + { + type = "Button", + props = { + variant = "contained", + text = "Explore Level 2", + onClick = "navigateToLevel2" + } + } + } + } + } + } + } + } + } + }, + + -- Footer + { + type = "AppFooter", + props = {} + } + } + } +end + +return M diff --git a/frontends/nextjs/src/lib/packages/lua-ui/level1-page/manifest.json b/frontends/nextjs/src/lib/packages/lua-ui/level1-page/manifest.json new file mode 100644 index 000000000..7a4742985 --- /dev/null +++ b/frontends/nextjs/src/lib/packages/lua-ui/level1-page/manifest.json @@ -0,0 +1,22 @@ +{ + "id": "level1-page", + "version": "1.0.0", + "name": "Level 1 - Home", + "description": "Main landing page with navigation and credentials", + "category": "ui", + "pages": [ + { + "file": "level1-ui.lua", + "path": "/", + "title": "Home", + "level": 1, + "requiresAuth": false + } + ], + "actions": [ + { + "file": "level1-actions.lua", + "name": "level1_actions" + } + ] +} diff --git a/frontends/nextjs/src/lib/packages/lua-ui/login-page/login-actions.lua b/frontends/nextjs/src/lib/packages/lua-ui/login-page/login-actions.lua new file mode 100644 index 000000000..08618b4ff --- /dev/null +++ b/frontends/nextjs/src/lib/packages/lua-ui/login-page/login-actions.lua @@ -0,0 +1,25 @@ +local M = {} + +function M.handleLogin(formData) + -- This will be called from React with form data + print("Login attempt for user:", formData.username) + + -- Return result that React can handle + return { + action = "login", + username = formData.username, + password = formData.password + } +end + +function M.handleRegister(formData) + print("Registration attempt for:", formData.username, formData.email) + + return { + action = "register", + username = formData.username, + email = formData.email + } +end + +return M diff --git a/frontends/nextjs/src/lib/packages/lua-ui/login-page/login-ui.lua b/frontends/nextjs/src/lib/packages/lua-ui/login-page/login-ui.lua new file mode 100644 index 000000000..b49e8badb --- /dev/null +++ b/frontends/nextjs/src/lib/packages/lua-ui/login-page/login-ui.lua @@ -0,0 +1,180 @@ +local M = {} + +function M.render() + return { + type = "Box", + props = { + className = "min-h-screen bg-gradient-to-br from-primary/5 via-background to-accent/5 flex items-center justify-center p-4" + }, + children = { + { + type = "Card", + props = { className = "w-full max-w-md" }, + children = { + { + type = "CardHeader", + props = {}, + children = { + { + type = "CardTitle", + props = { text = "Welcome to MetaBuilder" } + }, + { + type = "CardDescription", + props = { text = "Sign in to your account or create a new one" } + } + } + }, + { + type = "CardContent", + props = {}, + children = { + { + type = "Tabs", + props = { defaultValue = "login" }, + children = { + { + type = "TabsList", + props = { className = "grid w-full grid-cols-2" }, + children = { + { + type = "TabsTrigger", + props = { value = "login", text = "Login" } + }, + { + type = "TabsTrigger", + props = { value = "register", text = "Register" } + } + } + }, + { + type = "TabsContent", + props = { value = "login" }, + children = { + { + type = "Stack", + props = { spacing = 3 }, + children = { + { + type = "Box", + props = {}, + children = { + { + type = "Label", + props = { htmlFor = "username", text = "Username" } + }, + { + type = "Input", + props = { + id = "username", + name = "username", + placeholder = "Enter your username", + required = true + } + } + } + }, + { + type = "Box", + props = {}, + children = { + { + type = "Label", + props = { htmlFor = "password", text = "Password" } + }, + { + type = "Input", + props = { + id = "password", + name = "password", + type = "password", + placeholder = "Enter your password", + required = true + } + } + } + }, + { + type = "Button", + props = { + type = "submit", + className = "w-full", + text = "Sign In", + onClick = "handleLogin" + } + } + } + } + } + }, + { + type = "TabsContent", + props = { value = "register" }, + children = { + { + type = "Stack", + props = { spacing = 3 }, + children = { + { + type = "Box", + props = {}, + children = { + { + type = "Label", + props = { htmlFor = "reg-username", text = "Username" } + }, + { + type = "Input", + props = { + id = "reg-username", + name = "username", + placeholder = "Choose a username", + required = true + } + } + } + }, + { + type = "Box", + props = {}, + children = { + { + type = "Label", + props = { htmlFor = "email", text = "Email" } + }, + { + type = "Input", + props = { + id = "email", + name = "email", + type = "email", + placeholder = "your@email.com", + required = true + } + } + } + }, + { + type = "Button", + props = { + type = "submit", + className = "w-full", + text = "Create Account", + onClick = "handleRegister" + } + } + } + } + } + } + } + } + } + } + } + } + } + } +end + +return M diff --git a/frontends/nextjs/src/lib/packages/lua-ui/login-page/manifest.json b/frontends/nextjs/src/lib/packages/lua-ui/login-page/manifest.json new file mode 100644 index 000000000..bb08b24d8 --- /dev/null +++ b/frontends/nextjs/src/lib/packages/lua-ui/login-page/manifest.json @@ -0,0 +1,22 @@ +{ + "id": "login-page", + "version": "1.0.0", + "name": "Login Page", + "description": "Unified login and registration page", + "category": "ui", + "pages": [ + { + "file": "login-ui.lua", + "path": "/login", + "title": "Login", + "level": 1, + "requiresAuth": false + } + ], + "actions": [ + { + "file": "login-actions.lua", + "name": "login_actions" + } + ] +} diff --git a/frontends/nextjs/src/lib/rendering/page/page-definition-builder/PageDefinitionBuilderUtils.ts b/frontends/nextjs/src/lib/rendering/page/page-definition-builder/PageDefinitionBuilderUtils.ts index c3e23ddcd..4788ff6d4 100644 --- a/frontends/nextjs/src/lib/rendering/page/page-definition-builder/PageDefinitionBuilderUtils.ts +++ b/frontends/nextjs/src/lib/rendering/page/page-definition-builder/PageDefinitionBuilderUtils.ts @@ -13,26 +13,26 @@ import { initializeDefaultPages } from './functions/initialize-default-pages' */ export class PageDefinitionBuilderUtils { static async initializeDefaultPages(): Promise { - return await initializeDefaultPages(...(arguments as any)) + return await initializeDefaultPages() } static buildLevel1Homepage(): PageDefinition { - return buildLevel1Homepage(...(arguments as any)) + return buildLevel1Homepage() } static buildLevel2UserDashboard(): PageDefinition { - return buildLevel2UserDashboard(...(arguments as any)) + return buildLevel2UserDashboard() } static buildLevel3AdminPanel(): PageDefinition { - return buildLevel3AdminPanel(...(arguments as any)) + return buildLevel3AdminPanel() } static getPages(): PageDefinition[] { - return getPages(...(arguments as any)) + return getPages() } static getPageDefinitionBuilder(): PageDefinitionBuilder { - return getPageDefinitionBuilder(...(arguments as any)) + return getPageDefinitionBuilder() } } diff --git a/packages/ui_pages/seed/metadata.json b/packages/ui_pages/seed/metadata.json new file mode 100644 index 000000000..4ebc3cb32 --- /dev/null +++ b/packages/ui_pages/seed/metadata.json @@ -0,0 +1,20 @@ +{ + "packageId": "ui_pages", + "name": "UI Pages", + "version": "1.0.0", + "description": "Declarative JSON-defined UI pages for all levels", + "author": "MetaBuilder", + "category": "ui", + "dependencies": [], + "exports": { + "pages": [ + "login", + "level1", + "level2", + "level3", + "level4", + "level5", + "level6" + ] + } +} diff --git a/packages/ui_pages/seed/pages/level1.json b/packages/ui_pages/seed/pages/level1.json new file mode 100644 index 000000000..e3a6eedd0 --- /dev/null +++ b/packages/ui_pages/seed/pages/level1.json @@ -0,0 +1,124 @@ +{ + "path": "/", + "title": "Home", + "level": 1, + "requiresAuth": false, + "layout": { + "type": "Box", + "props": { + "className": "min-h-screen bg-gradient-to-br from-primary/5 via-background to-accent/5" + }, + "children": [ + { + "type": "NavigationBar", + "props": { + "level": 1, + "onNavigate": "handleNavigate" + } + }, + { + "type": "Container", + "props": { + "maxWidth": "lg", + "className": "px-4 sm:px-6 lg:px-8 pt-6 space-y-6" + }, + "children": [ + { + "type": "Card", + "children": [ + { + "type": "CardHeader", + "children": [ + { + "type": "CardTitle", + "props": { "text": "Server Status" } + } + ] + }, + { + "type": "CardContent", + "children": [ + { + "type": "Typography", + "props": { + "variant": "body1", + "text": "MetaBuilder Development Server" + } + }, + { + "type": "Typography", + "props": { + "variant": "body2", + "color": "textSecondary", + "text": "Status: Active" + } + } + ] + } + ] + }, + { + "type": "Tabs", + "props": { "defaultValue": "overview" }, + "children": [ + { + "type": "TabsList", + "children": [ + { + "type": "TabsTrigger", + "props": { "value": "overview", "text": "Overview" } + }, + { + "type": "TabsTrigger", + "props": { "value": "features", "text": "Features" } + }, + { + "type": "TabsTrigger", + "props": { "value": "docs", "text": "Documentation" } + } + ] + }, + { + "type": "TabsContent", + "props": { "value": "overview" }, + "children": [ + { + "type": "Stack", + "props": { "spacing": 2 }, + "children": [ + { + "type": "Typography", + "props": { + "variant": "h5", + "text": "Welcome to MetaBuilder" + } + }, + { + "type": "Typography", + "props": { + "variant": "body1", + "text": "MetaBuilder is a powerful data-driven platform with multi-level navigation." + } + }, + { + "type": "Button", + "props": { + "variant": "contained", + "text": "Explore Level 2", + "onClick": "navigateToLevel2" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "AppFooter" + } + ] + } +} diff --git a/packages/ui_pages/seed/pages/login.json b/packages/ui_pages/seed/pages/login.json new file mode 100644 index 000000000..e78ed5e9c --- /dev/null +++ b/packages/ui_pages/seed/pages/login.json @@ -0,0 +1,174 @@ +{ + "path": "/login", + "title": "Login", + "level": 1, + "requiresAuth": false, + "layout": { + "type": "Box", + "props": { + "className": "min-h-screen bg-gradient-to-br from-primary/5 via-background to-accent/5 flex items-center justify-center p-4" + }, + "children": [ + { + "type": "Card", + "props": { "className": "w-full max-w-md" }, + "children": [ + { + "type": "CardHeader", + "children": [ + { + "type": "CardTitle", + "props": { "text": "Welcome to MetaBuilder" } + }, + { + "type": "CardDescription", + "props": { "text": "Sign in to your account or create a new one" } + } + ] + }, + { + "type": "CardContent", + "children": [ + { + "type": "Tabs", + "props": { "defaultValue": "login" }, + "children": [ + { + "type": "TabsList", + "props": { "className": "grid w-full grid-cols-2" }, + "children": [ + { + "type": "TabsTrigger", + "props": { "value": "login", "text": "Login" } + }, + { + "type": "TabsTrigger", + "props": { "value": "register", "text": "Register" } + } + ] + }, + { + "type": "TabsContent", + "props": { "value": "login" }, + "children": [ + { + "type": "Stack", + "props": { "spacing": 3 }, + "children": [ + { + "type": "Box", + "children": [ + { + "type": "Label", + "props": { "htmlFor": "username", "text": "Username" } + }, + { + "type": "Input", + "props": { + "id": "username", + "name": "username", + "placeholder": "Enter your username", + "required": true + } + } + ] + }, + { + "type": "Box", + "children": [ + { + "type": "Label", + "props": { "htmlFor": "password", "text": "Password" } + }, + { + "type": "Input", + "props": { + "id": "password", + "name": "password", + "type": "password", + "placeholder": "Enter your password", + "required": true + } + } + ] + }, + { + "type": "Button", + "props": { + "type": "submit", + "className": "w-full", + "text": "Sign In", + "onClick": "handleLogin" + } + } + ] + } + ] + }, + { + "type": "TabsContent", + "props": { "value": "register" }, + "children": [ + { + "type": "Stack", + "props": { "spacing": 3 }, + "children": [ + { + "type": "Box", + "children": [ + { + "type": "Label", + "props": { "htmlFor": "reg-username", "text": "Username" } + }, + { + "type": "Input", + "props": { + "id": "reg-username", + "name": "username", + "placeholder": "Choose a username", + "required": true + } + } + ] + }, + { + "type": "Box", + "children": [ + { + "type": "Label", + "props": { "htmlFor": "email", "text": "Email" } + }, + { + "type": "Input", + "props": { + "id": "email", + "name": "email", + "type": "email", + "placeholder": "your@email.com", + "required": true + } + } + ] + }, + { + "type": "Button", + "props": { + "type": "submit", + "className": "w-full", + "text": "Create Account", + "onClick": "handleRegister" + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } +}