diff --git a/frontends/nextjs/src/types/monaco-editor-react.d.ts b/frontends/nextjs/src/types/monaco-editor-react.d.ts index 7482b41f0..77aff2bd3 100644 --- a/frontends/nextjs/src/types/monaco-editor-react.d.ts +++ b/frontends/nextjs/src/types/monaco-editor-react.d.ts @@ -1,6 +1,10 @@ declare module '@monaco-editor/react' { - import type { ComponentType } from 'react' - + import type { ComponentType, ReactNode } from 'react' + import type { editor, languages } from 'monaco-editor' + import type * as MonacoNamespace from 'monaco-editor' + + type Monaco = typeof MonacoNamespace + export interface EditorProps { height?: string | number width?: string | number @@ -10,21 +14,21 @@ declare module '@monaco-editor/react' { defaultLanguage?: string theme?: string line?: number - loading?: string | React.ReactNode - options?: Record - overrideServices?: Record + loading?: string | ReactNode + options?: editor.IStandaloneEditorConstructionOptions + overrideServices?: editor.IEditorOverrideServices saveViewState?: boolean keepCurrentModel?: boolean path?: string - onChange?: (value: string | undefined, event: any) => void - onMount?: (editor: any, monaco: any) => void - onValidate?: (markers: any[]) => void - beforeMount?: (monaco: any) => void + onChange?: (value: string | undefined, event?: editor.IModelContentChangedEvent) => void + onMount?: (editor: editor.IStandaloneCodeEditor, monaco: Monaco) => void + onValidate?: (markers: languages.IMarker[]) => void + beforeMount?: (monaco: Monaco) => void } - + const Editor: ComponentType export default Editor - - export function useMonaco(): any - export function loader(): any + + export function useMonaco(): Monaco | null + export function loader(): Promise } diff --git a/packages/admin_dialog/seed/scripts/init.lua b/packages/admin_dialog/seed/scripts/init.lua new file mode 100644 index 000000000..8b63ad3ec --- /dev/null +++ b/packages/admin_dialog/seed/scripts/init.lua @@ -0,0 +1,15 @@ +-- Admin Dialog initialization +local M = {} + +M.name = "admin_dialog" +M.version = "1.0.0" + +function M.init() + return { + name = M.name, + version = M.version, + loaded = true + } +end + +return M diff --git a/packages/admin_dialog/seed/scripts/manifest.json b/packages/admin_dialog/seed/scripts/manifest.json new file mode 100644 index 000000000..a82a5723c --- /dev/null +++ b/packages/admin_dialog/seed/scripts/manifest.json @@ -0,0 +1,22 @@ +{ + "scripts": [ + { + "id": "init", + "name": "Admin Dialog Init", + "file": "init.lua", + "description": "Initialize admin dialog module" + }, + { + "id": "user", + "name": "User Management Dialog", + "file": "user.lua", + "description": "User edit/create dialog" + }, + { + "id": "settings", + "name": "Settings Dialog", + "file": "settings.lua", + "description": "Admin settings dialog" + } + ] +} diff --git a/packages/admin_dialog/seed/scripts/settings.lua b/packages/admin_dialog/seed/scripts/settings.lua new file mode 100644 index 000000000..bd8fb1c8f --- /dev/null +++ b/packages/admin_dialog/seed/scripts/settings.lua @@ -0,0 +1,35 @@ +-- Admin settings dialog +local M = {} + +function M.render_general() + return { + type = "dialog", + props = { + title = "General Settings", + size = "large" + }, + children = { + { type = "text_field", props = { label = "Site Name", name = "site_name" } }, + { type = "text_field", props = { label = "Admin Email", name = "admin_email", type = "email" } }, + { type = "switch", props = { label = "Maintenance Mode", name = "maintenance" } }, + { type = "switch", props = { label = "Allow Registration", name = "allow_registration" } } + } + } +end + +function M.render_security() + return { + type = "dialog", + props = { + title = "Security Settings", + size = "medium" + }, + children = { + { type = "number_field", props = { label = "Session Timeout (min)", name = "session_timeout", min = 5 } }, + { type = "number_field", props = { label = "Max Login Attempts", name = "max_attempts", min = 1 } }, + { type = "switch", props = { label = "Require 2FA", name = "require_2fa" } } + } + } +end + +return M diff --git a/packages/admin_dialog/seed/scripts/user.lua b/packages/admin_dialog/seed/scripts/user.lua new file mode 100644 index 000000000..694cb7547 --- /dev/null +++ b/packages/admin_dialog/seed/scripts/user.lua @@ -0,0 +1,36 @@ +-- User management dialog +local M = {} + +function M.render_create() + return { + type = "dialog", + props = { + title = "Create User", + size = "medium" + }, + children = { + { type = "text_field", props = { label = "Username", name = "username", required = true } }, + { type = "text_field", props = { label = "Email", name = "email", type = "email", required = true } }, + { type = "password_field", props = { label = "Password", name = "password", required = true } }, + { type = "select", props = { label = "Role", name = "role", options = {"user", "admin"} } } + } + } +end + +function M.render_edit(user) + return { + type = "dialog", + props = { + title = "Edit User", + size = "medium" + }, + children = { + { type = "text_field", props = { label = "Username", name = "username", value = user.username } }, + { type = "text_field", props = { label = "Email", name = "email", value = user.email } }, + { type = "select", props = { label = "Role", name = "role", value = user.role, options = {"user", "admin"} } }, + { type = "checkbox", props = { label = "Active", name = "active", checked = user.active } } + } + } +end + +return M diff --git a/packages/admin_dialog/static_content/icon.svg b/packages/admin_dialog/static_content/icon.svg new file mode 100644 index 000000000..3dd62f723 --- /dev/null +++ b/packages/admin_dialog/static_content/icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/admin_dialog/tests/admin_dialog.test.ts b/packages/admin_dialog/tests/admin_dialog.test.ts new file mode 100644 index 000000000..31d95b0fe --- /dev/null +++ b/packages/admin_dialog/tests/admin_dialog.test.ts @@ -0,0 +1,28 @@ +import { describe, it, expect } from 'vitest' + +describe('admin_dialog package', () => { + describe('metadata', () => { + it('should have valid package structure', async () => { + const metadata = await import('../seed/metadata.json') + expect(metadata.packageId).toBe('admin_dialog') + }) + }) + + describe('user dialog', () => { + it.each([ + { action: 'create', title: 'Create User' }, + { action: 'edit', title: 'Edit User' }, + ])('should render $action dialog', ({ title }) => { + expect(title).toBeDefined() + }) + }) + + describe('settings dialog', () => { + it.each([ + { type: 'general', title: 'General Settings' }, + { type: 'security', title: 'Security Settings' }, + ])('should render $type settings', ({ title }) => { + expect(title).toBeDefined() + }) + }) +}) diff --git a/packages/arcade_lobby/static_content/icon.svg b/packages/arcade_lobby/static_content/icon.svg new file mode 100644 index 000000000..69714a15d --- /dev/null +++ b/packages/arcade_lobby/static_content/icon.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/packages/code_editor/seed/components.json b/packages/code_editor/seed/components.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/packages/code_editor/seed/components.json @@ -0,0 +1 @@ +[] diff --git a/packages/code_editor/seed/metadata.json b/packages/code_editor/seed/metadata.json new file mode 100644 index 000000000..55a46c52f --- /dev/null +++ b/packages/code_editor/seed/metadata.json @@ -0,0 +1,13 @@ +{ + "packageId": "code_editor", + "name": "Code Editor", + "version": "1.0.0", + "description": "Code editor components for JSON, Lua, and themes", + "author": "MetaBuilder", + "category": "editors", + "dependencies": [], + "exports": { + "scripts": ["json", "lua", "theme"], + "components": ["CodeEditor", "JsonEditor", "LuaEditor", "ThemeEditor"] + } +} diff --git a/packages/code_editor/seed/scripts/init.lua b/packages/code_editor/seed/scripts/init.lua new file mode 100644 index 000000000..5fb93bf2d --- /dev/null +++ b/packages/code_editor/seed/scripts/init.lua @@ -0,0 +1,15 @@ +-- Code Editor initialization +local M = {} + +M.name = "code_editor" +M.version = "1.0.0" + +function M.init() + return { + name = M.name, + version = M.version, + loaded = true + } +end + +return M diff --git a/packages/code_editor/seed/scripts/json.lua b/packages/code_editor/seed/scripts/json.lua new file mode 100644 index 000000000..c86985dc3 --- /dev/null +++ b/packages/code_editor/seed/scripts/json.lua @@ -0,0 +1,32 @@ +-- JSON Editor utilities +local M = {} + +function M.render(value, options) + return { + type = "code_editor", + props = { + language = "json", + value = value or "{}", + read_only = options and options.read_only or false, + line_numbers = true, + auto_format = true + } + } +end + +function M.validate(json_string) + -- JSON validation placeholder + return { + valid = true, + errors = {} + } +end + +function M.format(json_string) + return { + action = "format", + language = "json" + } +end + +return M diff --git a/packages/code_editor/seed/scripts/lua.lua b/packages/code_editor/seed/scripts/lua.lua new file mode 100644 index 000000000..856cc3039 --- /dev/null +++ b/packages/code_editor/seed/scripts/lua.lua @@ -0,0 +1,33 @@ +-- Lua Editor utilities +local M = {} + +function M.render(value, options) + return { + type = "code_editor", + props = { + language = "lua", + value = value or "", + read_only = options and options.read_only or false, + line_numbers = true, + show_snippets = true + } + } +end + +function M.validate(lua_code) + -- Lua syntax validation placeholder + return { + valid = true, + errors = {} + } +end + +function M.run_sandbox(lua_code, context) + return { + action = "execute", + sandbox = true, + context = context or {} + } +end + +return M diff --git a/packages/code_editor/seed/scripts/manifest.json b/packages/code_editor/seed/scripts/manifest.json new file mode 100644 index 000000000..a26fce3be --- /dev/null +++ b/packages/code_editor/seed/scripts/manifest.json @@ -0,0 +1,28 @@ +{ + "scripts": [ + { + "id": "init", + "name": "Code Editor Init", + "file": "init.lua", + "description": "Initialize code editor module" + }, + { + "id": "json", + "name": "JSON Editor", + "file": "json.lua", + "description": "JSON editor configuration" + }, + { + "id": "lua", + "name": "Lua Editor", + "file": "lua.lua", + "description": "Lua editor configuration" + }, + { + "id": "theme", + "name": "Theme Editor", + "file": "theme.lua", + "description": "Theme editor configuration" + } + ] +} diff --git a/packages/code_editor/seed/scripts/theme.lua b/packages/code_editor/seed/scripts/theme.lua new file mode 100644 index 000000000..59b8639d8 --- /dev/null +++ b/packages/code_editor/seed/scripts/theme.lua @@ -0,0 +1,36 @@ +-- Theme Editor utilities +local M = {} + +function M.render(theme) + return { + type = "theme_editor", + props = { + primary = theme and theme.primary or "#1976d2", + secondary = theme and theme.secondary or "#dc004e", + mode = theme and theme.mode or "light" + } + } +end + +function M.color_picker(name, value) + return { + type = "color_picker", + props = { + name = name, + value = value, + show_alpha = false + } + } +end + +function M.mode_toggle() + return { + type = "switch", + props = { + label = "Dark Mode", + name = "dark_mode" + } + } +end + +return M diff --git a/packages/code_editor/static_content/icon.svg b/packages/code_editor/static_content/icon.svg new file mode 100644 index 000000000..8d00ced74 --- /dev/null +++ b/packages/code_editor/static_content/icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/code_editor/tests/code_editor.test.ts b/packages/code_editor/tests/code_editor.test.ts new file mode 100644 index 000000000..073580f52 --- /dev/null +++ b/packages/code_editor/tests/code_editor.test.ts @@ -0,0 +1,20 @@ +import { describe, it, expect } from 'vitest' + +describe('code_editor package', () => { + describe('metadata', () => { + it('should have valid package structure', async () => { + const metadata = await import('../seed/metadata.json') + expect(metadata.packageId).toBe('code_editor') + }) + }) + + describe('languages', () => { + it.each([ + { language: 'json', extension: '.json' }, + { language: 'lua', extension: '.lua' }, + { language: 'javascript', extension: '.js' }, + ])('should support $language', ({ language }) => { + expect(language).toBeDefined() + }) + }) +}) diff --git a/packages/codegen_studio/static_content/icon.svg b/packages/codegen_studio/static_content/icon.svg new file mode 100644 index 000000000..ef90d97aa --- /dev/null +++ b/packages/codegen_studio/static_content/icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/dashboard/static_content/icon.svg b/packages/dashboard/static_content/icon.svg new file mode 100644 index 000000000..c54a5c3a2 --- /dev/null +++ b/packages/dashboard/static_content/icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/data_table/seed/scripts/columns.lua b/packages/data_table/seed/scripts/columns.lua new file mode 100644 index 000000000..fbf1a98cc --- /dev/null +++ b/packages/data_table/seed/scripts/columns.lua @@ -0,0 +1,45 @@ +-- Column definition utilities +local M = {} + +function M.text_column(id, label, width) + return { + type = "text", + id = id, + label = label, + width = width or "auto", + sortable = true + } +end + +function M.number_column(id, label, width) + return { + type = "number", + id = id, + label = label, + width = width or "100px", + sortable = true, + align = "right" + } +end + +function M.date_column(id, label, format) + return { + type = "date", + id = id, + label = label, + format = format or "YYYY-MM-DD", + sortable = true + } +end + +function M.action_column(id, actions) + return { + type = "actions", + id = id, + label = "", + width = "120px", + actions = actions or {} + } +end + +return M diff --git a/packages/data_table/seed/scripts/init.lua b/packages/data_table/seed/scripts/init.lua new file mode 100644 index 000000000..2baeda206 --- /dev/null +++ b/packages/data_table/seed/scripts/init.lua @@ -0,0 +1,15 @@ +-- Data Table initialization +local M = {} + +M.name = "data_table" +M.version = "1.0.0" + +function M.init() + return { + name = M.name, + version = M.version, + loaded = true + } +end + +return M diff --git a/packages/data_table/seed/scripts/manifest.json b/packages/data_table/seed/scripts/manifest.json new file mode 100644 index 000000000..c5de46243 --- /dev/null +++ b/packages/data_table/seed/scripts/manifest.json @@ -0,0 +1,28 @@ +{ + "scripts": [ + { + "id": "init", + "name": "Data Table Init", + "file": "init.lua", + "description": "Initialize data table module" + }, + { + "id": "columns", + "name": "Column Definitions", + "file": "columns.lua", + "description": "Define table columns" + }, + { + "id": "rows", + "name": "Row Rendering", + "file": "rows.lua", + "description": "Render table rows" + }, + { + "id": "pagination", + "name": "Pagination", + "file": "pagination.lua", + "description": "Table pagination controls" + } + ] +} diff --git a/packages/data_table/seed/scripts/pagination.lua b/packages/data_table/seed/scripts/pagination.lua new file mode 100644 index 000000000..e592bd79d --- /dev/null +++ b/packages/data_table/seed/scripts/pagination.lua @@ -0,0 +1,30 @@ +-- Pagination utilities +local M = {} + +function M.calculate(total, page, per_page) + local pages = math.ceil(total / per_page) + return { + total = total, + page = page, + per_page = per_page, + pages = pages, + has_prev = page > 1, + has_next = page < pages + } +end + +function M.render(pagination) + return { + type = "pagination", + props = { + current = pagination.page, + total = pagination.pages, + show_prev = pagination.has_prev, + show_next = pagination.has_next, + on_prev = "prev_page", + on_next = "next_page" + } + } +end + +return M diff --git a/packages/data_table/seed/scripts/rows.lua b/packages/data_table/seed/scripts/rows.lua new file mode 100644 index 000000000..16f8bbda2 --- /dev/null +++ b/packages/data_table/seed/scripts/rows.lua @@ -0,0 +1,36 @@ +-- Row rendering utilities +local M = {} + +function M.render_cell(column, value) + if column.type == "date" then + return { type = "text", content = value } + elseif column.type == "number" then + return { type = "text", content = tostring(value), align = "right" } + elseif column.type == "actions" then + return { type = "actions", buttons = column.actions } + else + return { type = "text", content = value or "" } + end +end + +function M.render_row(columns, data, index) + local cells = {} + for _, col in ipairs(columns) do + table.insert(cells, M.render_cell(col, data[col.id])) + end + return { + index = index, + cells = cells, + selected = false + } +end + +function M.render_rows(columns, data_list) + local rows = {} + for i, data in ipairs(data_list) do + table.insert(rows, M.render_row(columns, data, i)) + end + return rows +end + +return M diff --git a/packages/data_table/static_content/icon.svg b/packages/data_table/static_content/icon.svg new file mode 100644 index 000000000..e619f46d7 --- /dev/null +++ b/packages/data_table/static_content/icon.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/packages/data_table/tests/data_table.test.ts b/packages/data_table/tests/data_table.test.ts new file mode 100644 index 000000000..7aae02e6e --- /dev/null +++ b/packages/data_table/tests/data_table.test.ts @@ -0,0 +1,33 @@ +import { describe, it, expect } from 'vitest' + +describe('data_table package', () => { + describe('metadata', () => { + it('should have valid package structure', async () => { + const metadata = await import('../seed/metadata.json') + expect(metadata.packageId).toBe('data_table') + }) + }) + + describe('columns', () => { + it.each([ + { type: 'text', id: 'name', label: 'Name' }, + { type: 'number', id: 'age', label: 'Age' }, + { type: 'date', id: 'created', label: 'Created' }, + ])('should define $type column for $id', ({ type, id, label }) => { + expect(type).toBeDefined() + expect(id).toBeDefined() + expect(label).toBeDefined() + }) + }) + + describe('pagination', () => { + it.each([ + { total: 100, page: 1, per_page: 10, expected_pages: 10 }, + { total: 25, page: 2, per_page: 10, expected_pages: 3 }, + { total: 0, page: 1, per_page: 10, expected_pages: 0 }, + ])('should calculate pages for total=$total', ({ total, per_page, expected_pages }) => { + const pages = Math.ceil(total / per_page) + expect(pages).toBe(expected_pages) + }) + }) +}) diff --git a/packages/form_builder/static_content/icon.svg b/packages/form_builder/static_content/icon.svg new file mode 100644 index 000000000..9d03f9790 --- /dev/null +++ b/packages/form_builder/static_content/icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/forum_forge/static_content/icon.svg b/packages/forum_forge/static_content/icon.svg new file mode 100644 index 000000000..4d5e1bdcf --- /dev/null +++ b/packages/forum_forge/static_content/icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/index.json b/packages/index.json index d333480c6..0ed7d7aad 100644 --- a/packages/index.json +++ b/packages/index.json @@ -5,11 +5,12 @@ "packageId": "admin_dialog", "name": "Admin Dialog", "version": "1.0.0", - "description": "Admin dialog components", + "description": "Admin dialogs for user and settings management", "author": "MetaBuilder", "category": "ui", - "dependencies": [], + "dependencies": ["ui_dialogs"], "exports": { + "scripts": ["user", "settings"], "components": [] } }, @@ -37,15 +38,29 @@ "components": [] } }, + { + "packageId": "code_editor", + "name": "Code Editor", + "version": "1.0.0", + "description": "Code editor components for JSON, Lua, and themes", + "author": "MetaBuilder", + "category": "editors", + "dependencies": [], + "exports": { + "scripts": ["json", "lua", "theme"], + "components": ["CodeEditor", "JsonEditor", "LuaEditor", "ThemeEditor"] + } + }, { "packageId": "dashboard", "name": "Dashboard", "version": "1.0.0", - "description": "Dashboard components", + "description": "Dashboard components with stats and layouts", "author": "MetaBuilder", "category": "ui", "dependencies": [], "exports": { + "scripts": ["stats", "layout"], "components": [] } }, @@ -53,11 +68,12 @@ "packageId": "data_table", "name": "Data Table", "version": "1.0.0", - "description": "Data table components", + "description": "Data table with columns, rows, and pagination", "author": "MetaBuilder", "category": "ui", "dependencies": [], "exports": { + "scripts": ["columns", "rows", "pagination"], "components": [] } }, @@ -65,11 +81,12 @@ "packageId": "form_builder", "name": "Form Builder", "version": "1.0.0", - "description": "Form builder components", + "description": "Form builder with field types and validation", "author": "MetaBuilder", "category": "ui", "dependencies": [], "exports": { + "scripts": ["fields", "validate"], "components": [] } }, @@ -89,11 +106,12 @@ "packageId": "nav_menu", "name": "Navigation Menu", "version": "1.0.0", - "description": "Navigation menu components", + "description": "Navigation sidebar and menu components", "author": "MetaBuilder", "category": "ui", - "dependencies": [], + "dependencies": ["ui_permissions"], "exports": { + "scripts": ["sidebar", "menu"], "components": [] } }, @@ -101,14 +119,41 @@ "packageId": "notification_center", "name": "Notification Center", "version": "1.0.0", - "description": "Notification center components", + "description": "Toast notifications and notification list", "author": "MetaBuilder", "category": "ui", "dependencies": [], "exports": { + "scripts": ["toast", "list"], "components": [] } }, + { + "packageId": "ui_auth", + "name": "Auth Components", + "version": "1.0.0", + "description": "Authentication gate and access denied views", + "author": "MetaBuilder", + "category": "ui", + "dependencies": ["ui_permissions"], + "exports": { + "scripts": ["gate", "denied"], + "components": ["AuthGate", "AccessDenied"] + } + }, + { + "packageId": "ui_dialogs", + "name": "Dialog Components", + "version": "1.0.0", + "description": "Confirm and alert dialog components", + "author": "MetaBuilder", + "category": "ui", + "dependencies": [], + "exports": { + "scripts": ["confirm", "alert"], + "components": ["ConfirmDialog", "AlertDialog"] + } + }, { "packageId": "social_hub", "name": "Social Hub", @@ -151,6 +196,19 @@ ] } }, + { + "packageId": "schema_editor", + "name": "Schema Editor", + "version": "1.0.0", + "description": "Database schema editor components", + "author": "MetaBuilder", + "category": "editors", + "dependencies": ["form_builder"], + "exports": { + "scripts": ["fields", "tables", "relations"], + "components": ["SchemaEditor", "TableEditor", "FieldEditor"] + } + }, { "packageId": "stream_cast", "name": "Stream Cast", @@ -163,6 +221,32 @@ "components": [] } }, + { + "packageId": "user_manager", + "name": "User Manager", + "version": "1.0.0", + "description": "User management components and actions", + "author": "MetaBuilder", + "category": "managers", + "dependencies": ["ui_permissions", "data_table"], + "exports": { + "scripts": ["list", "actions"], + "components": ["UserManagement", "UserList", "UserActions"] + } + }, + { + "packageId": "workflow_editor", + "name": "Workflow Editor", + "version": "1.0.0", + "description": "Workflow editor and run status components", + "author": "MetaBuilder", + "category": "editors", + "dependencies": [], + "exports": { + "scripts": ["editor", "status", "run"], + "components": ["WorkflowEditor", "WorkflowRunCard", "WorkflowRunStatus"] + } + }, { "packageId": "ui_permissions", "name": "UI Permissions", diff --git a/packages/nav_menu/static_content/icon.svg b/packages/nav_menu/static_content/icon.svg new file mode 100644 index 000000000..b80e96d04 --- /dev/null +++ b/packages/nav_menu/static_content/icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/notification_center/seed/scripts/init.lua b/packages/notification_center/seed/scripts/init.lua new file mode 100644 index 000000000..a182cfb20 --- /dev/null +++ b/packages/notification_center/seed/scripts/init.lua @@ -0,0 +1,15 @@ +-- Notification Center initialization +local M = {} + +M.name = "notification_center" +M.version = "1.0.0" + +function M.init() + return { + name = M.name, + version = M.version, + loaded = true + } +end + +return M diff --git a/packages/notification_center/seed/scripts/list.lua b/packages/notification_center/seed/scripts/list.lua new file mode 100644 index 000000000..af9f7bf0d --- /dev/null +++ b/packages/notification_center/seed/scripts/list.lua @@ -0,0 +1,40 @@ +-- Notification list utilities +local M = {} + +function M.render_item(notification) + return { + type = "notification_item", + props = { + id = notification.id, + title = notification.title, + message = notification.message, + time = notification.created_at, + read = notification.read or false, + icon = notification.icon or "bell" + } + } +end + +function M.render_list(notifications) + local items = {} + for _, n in ipairs(notifications) do + table.insert(items, M.render_item(n)) + end + return { + type = "notification_list", + children = items + } +end + +function M.render_badge(count) + if count > 0 then + return { + type = "badge", + content = count > 99 and "99+" or tostring(count), + variant = "error" + } + end + return nil +end + +return M diff --git a/packages/notification_center/seed/scripts/manifest.json b/packages/notification_center/seed/scripts/manifest.json new file mode 100644 index 000000000..7fa71d74f --- /dev/null +++ b/packages/notification_center/seed/scripts/manifest.json @@ -0,0 +1,22 @@ +{ + "scripts": [ + { + "id": "init", + "name": "Notification Center Init", + "file": "init.lua", + "description": "Initialize notification module" + }, + { + "id": "toast", + "name": "Toast Notifications", + "file": "toast.lua", + "description": "Toast notification rendering" + }, + { + "id": "list", + "name": "Notification List", + "file": "list.lua", + "description": "Notification list panel" + } + ] +} diff --git a/packages/notification_center/seed/scripts/toast.lua b/packages/notification_center/seed/scripts/toast.lua new file mode 100644 index 000000000..fd4bfe393 --- /dev/null +++ b/packages/notification_center/seed/scripts/toast.lua @@ -0,0 +1,44 @@ +-- Toast notification utilities +local M = {} + +function M.success(message, duration) + return { + type = "toast", + variant = "success", + message = message, + duration = duration or 3000, + icon = "check" + } +end + +function M.error(message, duration) + return { + type = "toast", + variant = "error", + message = message, + duration = duration or 5000, + icon = "error" + } +end + +function M.warning(message, duration) + return { + type = "toast", + variant = "warning", + message = message, + duration = duration or 4000, + icon = "warning" + } +end + +function M.info(message, duration) + return { + type = "toast", + variant = "info", + message = message, + duration = duration or 3000, + icon = "info" + } +end + +return M diff --git a/packages/notification_center/static_content/icon.svg b/packages/notification_center/static_content/icon.svg new file mode 100644 index 000000000..1b7c51f29 --- /dev/null +++ b/packages/notification_center/static_content/icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/notification_center/tests/notification_center.test.ts b/packages/notification_center/tests/notification_center.test.ts new file mode 100644 index 000000000..64e06081f --- /dev/null +++ b/packages/notification_center/tests/notification_center.test.ts @@ -0,0 +1,35 @@ +import { describe, it, expect } from 'vitest' + +describe('notification_center package', () => { + describe('metadata', () => { + it('should have valid package structure', async () => { + const metadata = await import('../seed/metadata.json') + expect(metadata.packageId).toBe('notification_center') + }) + }) + + describe('toast variants', () => { + it.each([ + { variant: 'success', icon: 'check', duration: 3000 }, + { variant: 'error', icon: 'error', duration: 5000 }, + { variant: 'warning', icon: 'warning', duration: 4000 }, + { variant: 'info', icon: 'info', duration: 3000 }, + ])('should support $variant toast', ({ variant, icon, duration }) => { + expect(variant).toBeDefined() + expect(icon).toBeDefined() + expect(duration).toBeGreaterThan(0) + }) + }) + + describe('badge rendering', () => { + it.each([ + { count: 0, expected: null }, + { count: 5, expected: '5' }, + { count: 99, expected: '99' }, + { count: 100, expected: '99+' }, + ])('should render badge for count=$count', ({ count, expected }) => { + const badge = count > 0 ? (count > 99 ? '99+' : String(count)) : null + expect(badge).toBe(expected) + }) + }) +}) diff --git a/packages/schema_editor/seed/components.json b/packages/schema_editor/seed/components.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/packages/schema_editor/seed/components.json @@ -0,0 +1 @@ +[] diff --git a/packages/schema_editor/seed/metadata.json b/packages/schema_editor/seed/metadata.json new file mode 100644 index 000000000..23d4bf6ed --- /dev/null +++ b/packages/schema_editor/seed/metadata.json @@ -0,0 +1,13 @@ +{ + "packageId": "schema_editor", + "name": "Schema Editor", + "version": "1.0.0", + "description": "Database schema editor components", + "author": "MetaBuilder", + "category": "editors", + "dependencies": ["form_builder"], + "exports": { + "scripts": ["fields", "tables", "relations"], + "components": ["SchemaEditor", "TableEditor", "FieldEditor"] + } +} diff --git a/packages/schema_editor/seed/scripts/fields.lua b/packages/schema_editor/seed/scripts/fields.lua new file mode 100644 index 000000000..f20a9ad0e --- /dev/null +++ b/packages/schema_editor/seed/scripts/fields.lua @@ -0,0 +1,33 @@ +-- Schema field types +local M = {} + +M.STRING = "string" +M.INTEGER = "integer" +M.FLOAT = "float" +M.BOOLEAN = "boolean" +M.DATE = "date" +M.DATETIME = "datetime" +M.TEXT = "text" +M.JSON = "json" + +function M.define(name, type, options) + return { + name = name, + type = type, + nullable = options and options.nullable or false, + default = options and options.default, + unique = options and options.unique or false + } +end + +function M.primary_key(name) + return M.define(name, M.INTEGER, { nullable = false, unique = true }) +end + +function M.foreign_key(name, ref_table, ref_field) + local field = M.define(name, M.INTEGER, { nullable = true }) + field.references = { table = ref_table, field = ref_field } + return field +end + +return M diff --git a/packages/schema_editor/seed/scripts/init.lua b/packages/schema_editor/seed/scripts/init.lua new file mode 100644 index 000000000..88835f903 --- /dev/null +++ b/packages/schema_editor/seed/scripts/init.lua @@ -0,0 +1,15 @@ +-- Schema Editor initialization +local M = {} + +M.name = "schema_editor" +M.version = "1.0.0" + +function M.init() + return { + name = M.name, + version = M.version, + loaded = true + } +end + +return M diff --git a/packages/schema_editor/seed/scripts/manifest.json b/packages/schema_editor/seed/scripts/manifest.json new file mode 100644 index 000000000..9d61c2f35 --- /dev/null +++ b/packages/schema_editor/seed/scripts/manifest.json @@ -0,0 +1,28 @@ +{ + "scripts": [ + { + "id": "init", + "name": "Schema Editor Init", + "file": "init.lua", + "description": "Initialize schema editor module" + }, + { + "id": "fields", + "name": "Field Types", + "file": "fields.lua", + "description": "Field type definitions" + }, + { + "id": "tables", + "name": "Table Editor", + "file": "tables.lua", + "description": "Table management" + }, + { + "id": "relations", + "name": "Relations", + "file": "relations.lua", + "description": "Table relationships" + } + ] +} diff --git a/packages/schema_editor/seed/scripts/relations.lua b/packages/schema_editor/seed/scripts/relations.lua new file mode 100644 index 000000000..36fc73aa2 --- /dev/null +++ b/packages/schema_editor/seed/scripts/relations.lua @@ -0,0 +1,33 @@ +-- Table relationships +local M = {} + +M.ONE_TO_ONE = "one_to_one" +M.ONE_TO_MANY = "one_to_many" +M.MANY_TO_MANY = "many_to_many" + +function M.define(type, from, to, options) + return { + type = type, + from_table = from.table, + from_field = from.field, + to_table = to.table, + to_field = to.field, + cascade = options and options.cascade or false + } +end + +function M.has_one(from, to) + return M.define(M.ONE_TO_ONE, from, to) +end + +function M.has_many(from, to) + return M.define(M.ONE_TO_MANY, from, to) +end + +function M.belongs_to_many(from, to, pivot) + local rel = M.define(M.MANY_TO_MANY, from, to) + rel.pivot_table = pivot + return rel +end + +return M diff --git a/packages/schema_editor/seed/scripts/tables.lua b/packages/schema_editor/seed/scripts/tables.lua new file mode 100644 index 000000000..1e5845d65 --- /dev/null +++ b/packages/schema_editor/seed/scripts/tables.lua @@ -0,0 +1,38 @@ +-- Table management +local M = {} + +function M.create(name, fields) + return { + action = "create_table", + name = name, + fields = fields or {} + } +end + +function M.render(table_def) + return { + type = "table_editor", + props = { + name = table_def.name, + fields = table_def.fields + } + } +end + +function M.add_field(table_name, field) + return { + action = "add_field", + table = table_name, + field = field + } +end + +function M.remove_field(table_name, field_name) + return { + action = "remove_field", + table = table_name, + field = field_name + } +end + +return M diff --git a/packages/schema_editor/static_content/icon.svg b/packages/schema_editor/static_content/icon.svg new file mode 100644 index 000000000..bb631619f --- /dev/null +++ b/packages/schema_editor/static_content/icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/schema_editor/tests/schema_editor.test.ts b/packages/schema_editor/tests/schema_editor.test.ts new file mode 100644 index 000000000..01664cf46 --- /dev/null +++ b/packages/schema_editor/tests/schema_editor.test.ts @@ -0,0 +1,33 @@ +import { describe, it, expect } from 'vitest' + +describe('schema_editor package', () => { + describe('metadata', () => { + it('should have valid package structure', async () => { + const metadata = await import('../seed/metadata.json') + expect(metadata.packageId).toBe('schema_editor') + }) + }) + + describe('field types', () => { + it.each([ + { type: 'string', nullable: true }, + { type: 'integer', nullable: false }, + { type: 'boolean', nullable: false }, + { type: 'datetime', nullable: true }, + { type: 'json', nullable: true }, + ])('should support $type', ({ type, nullable }) => { + expect(type).toBeDefined() + expect(typeof nullable).toBe('boolean') + }) + }) + + describe('relations', () => { + it.each([ + { type: 'one_to_one' }, + { type: 'one_to_many' }, + { type: 'many_to_many' }, + ])('should support $type relation', ({ type }) => { + expect(type).toBeDefined() + }) + }) +}) diff --git a/packages/social_hub/static_content/icon.svg b/packages/social_hub/static_content/icon.svg new file mode 100644 index 000000000..e67c6a81f --- /dev/null +++ b/packages/social_hub/static_content/icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/spark-tools/static_content/icon.svg b/packages/spark-tools/static_content/icon.svg new file mode 100644 index 000000000..038b73914 --- /dev/null +++ b/packages/spark-tools/static_content/icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/stream_cast/static_content/icon.svg b/packages/stream_cast/static_content/icon.svg new file mode 100644 index 000000000..818156a56 --- /dev/null +++ b/packages/stream_cast/static_content/icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/ui_auth/static_content/icon.svg b/packages/ui_auth/static_content/icon.svg new file mode 100644 index 000000000..cfabe4be2 --- /dev/null +++ b/packages/ui_auth/static_content/icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/ui_auth/tests/ui_auth.test.ts b/packages/ui_auth/tests/ui_auth.test.ts new file mode 100644 index 000000000..286750fb0 --- /dev/null +++ b/packages/ui_auth/tests/ui_auth.test.ts @@ -0,0 +1,31 @@ +import { describe, it, expect } from 'vitest' + +describe('ui_auth package', () => { + describe('metadata', () => { + it('should have valid package structure', async () => { + const metadata = await import('../seed/metadata.json') + expect(metadata.packageId).toBe('ui_auth') + }) + }) + + describe('access denied', () => { + it.each([ + { level: 2, message: 'User access required' }, + { level: 3, message: 'Admin access required' }, + { level: 4, message: 'God access required' }, + { level: 5, message: 'Super God access required' }, + ])('should show message for level $level', ({ message }) => { + expect(message).toBeDefined() + }) + }) + + describe('auth gate', () => { + it.each([ + { user_level: 1, required: 2, allowed: false }, + { user_level: 2, required: 2, allowed: true }, + { user_level: 3, required: 2, allowed: true }, + ])('should gate level $user_level against required $required', ({ user_level, required, allowed }) => { + expect(user_level >= required).toBe(allowed) + }) + }) +}) diff --git a/packages/ui_dialogs/static_content/icon.svg b/packages/ui_dialogs/static_content/icon.svg new file mode 100644 index 000000000..d40df0537 --- /dev/null +++ b/packages/ui_dialogs/static_content/icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/ui_dialogs/tests/ui_dialogs.test.ts b/packages/ui_dialogs/tests/ui_dialogs.test.ts new file mode 100644 index 000000000..952d910dd --- /dev/null +++ b/packages/ui_dialogs/tests/ui_dialogs.test.ts @@ -0,0 +1,33 @@ +import { describe, it, expect } from 'vitest' + +describe('ui_dialogs package', () => { + describe('metadata', () => { + it('should have valid package structure', async () => { + const metadata = await import('../seed/metadata.json') + expect(metadata.packageId).toBe('ui_dialogs') + }) + }) + + describe('confirm dialog', () => { + it.each([ + { title: 'Delete Item', confirm: 'Delete', cancel: 'Cancel', destructive: true }, + { title: 'Save Changes', confirm: 'Save', cancel: 'Discard', destructive: false }, + ])('should render confirm dialog: $title', ({ title, confirm, cancel }) => { + expect(title).toBeDefined() + expect(confirm).toBeDefined() + expect(cancel).toBeDefined() + }) + }) + + describe('alert dialog', () => { + it.each([ + { variant: 'info', icon: 'info' }, + { variant: 'success', icon: 'check' }, + { variant: 'warning', icon: 'warning' }, + { variant: 'error', icon: 'error' }, + ])('should render $variant alert', ({ variant, icon }) => { + expect(variant).toBeDefined() + expect(icon).toBeDefined() + }) + }) +}) diff --git a/packages/ui_footer/static_content/icon.svg b/packages/ui_footer/static_content/icon.svg new file mode 100644 index 000000000..bf8cdaaf7 --- /dev/null +++ b/packages/ui_footer/static_content/icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/ui_header/static_content/icon.svg b/packages/ui_header/static_content/icon.svg new file mode 100644 index 000000000..8fd4ac90f --- /dev/null +++ b/packages/ui_header/static_content/icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/ui_home/static_content/icon.svg b/packages/ui_home/static_content/icon.svg new file mode 100644 index 000000000..807235f29 --- /dev/null +++ b/packages/ui_home/static_content/icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/ui_intro/static_content/icon.svg b/packages/ui_intro/static_content/icon.svg new file mode 100644 index 000000000..68575e732 --- /dev/null +++ b/packages/ui_intro/static_content/icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/ui_level2/static_content/icon.svg b/packages/ui_level2/static_content/icon.svg new file mode 100644 index 000000000..ccafa8b6d --- /dev/null +++ b/packages/ui_level2/static_content/icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/user_manager/seed/components.json b/packages/user_manager/seed/components.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/packages/user_manager/seed/components.json @@ -0,0 +1 @@ +[] diff --git a/packages/user_manager/seed/metadata.json b/packages/user_manager/seed/metadata.json new file mode 100644 index 000000000..e41fb081f --- /dev/null +++ b/packages/user_manager/seed/metadata.json @@ -0,0 +1,13 @@ +{ + "packageId": "user_manager", + "name": "User Manager", + "version": "1.0.0", + "description": "User management components and actions", + "author": "MetaBuilder", + "category": "managers", + "dependencies": ["ui_permissions", "data_table"], + "exports": { + "scripts": ["list", "actions"], + "components": ["UserManagement", "UserList", "UserActions"] + } +} diff --git a/packages/user_manager/seed/scripts/actions.lua b/packages/user_manager/seed/scripts/actions.lua new file mode 100644 index 000000000..91fbc708c --- /dev/null +++ b/packages/user_manager/seed/scripts/actions.lua @@ -0,0 +1,43 @@ +-- User management actions +local M = {} + +function M.create(data) + return { + action = "create_user", + data = data + } +end + +function M.update(user_id, data) + return { + action = "update_user", + user_id = user_id, + data = data + } +end + +function M.delete(user_id) + return { + action = "delete_user", + user_id = user_id, + confirm = true + } +end + +function M.change_level(user_id, new_level) + return { + action = "change_level", + user_id = user_id, + level = new_level + } +end + +function M.toggle_active(user_id, active) + return { + action = "toggle_active", + user_id = user_id, + active = active + } +end + +return M diff --git a/packages/user_manager/seed/scripts/init.lua b/packages/user_manager/seed/scripts/init.lua new file mode 100644 index 000000000..a9357db68 --- /dev/null +++ b/packages/user_manager/seed/scripts/init.lua @@ -0,0 +1,15 @@ +-- User Manager initialization +local M = {} + +M.name = "user_manager" +M.version = "1.0.0" + +function M.init() + return { + name = M.name, + version = M.version, + loaded = true + } +end + +return M diff --git a/packages/user_manager/seed/scripts/list.lua b/packages/user_manager/seed/scripts/list.lua new file mode 100644 index 000000000..017c6c8d3 --- /dev/null +++ b/packages/user_manager/seed/scripts/list.lua @@ -0,0 +1,38 @@ +-- User list rendering +local M = {} + +function M.columns() + return { + { id = "username", label = "Username", sortable = true }, + { id = "email", label = "Email", sortable = true }, + { id = "role", label = "Role", sortable = true }, + { id = "level", label = "Level", sortable = true }, + { id = "active", label = "Status", type = "badge" }, + { id = "actions", label = "", type = "actions" } + } +end + +function M.render_row(user) + return { + username = user.username, + email = user.email, + role = user.role, + level = user.level, + active = user.active and "Active" or "Inactive", + actions = { "edit", "delete" } + } +end + +function M.render(users) + local rows = {} + for _, user in ipairs(users) do + table.insert(rows, M.render_row(user)) + end + return { + type = "data_table", + columns = M.columns(), + rows = rows + } +end + +return M diff --git a/packages/user_manager/seed/scripts/manifest.json b/packages/user_manager/seed/scripts/manifest.json new file mode 100644 index 000000000..1e8ee3c24 --- /dev/null +++ b/packages/user_manager/seed/scripts/manifest.json @@ -0,0 +1,22 @@ +{ + "scripts": [ + { + "id": "init", + "name": "User Manager Init", + "file": "init.lua", + "description": "Initialize user manager module" + }, + { + "id": "list", + "name": "User List", + "file": "list.lua", + "description": "Render user list table" + }, + { + "id": "actions", + "name": "User Actions", + "file": "actions.lua", + "description": "User management actions" + } + ] +} diff --git a/packages/user_manager/tests/user_manager.test.ts b/packages/user_manager/tests/user_manager.test.ts new file mode 100644 index 000000000..a0ba07d0b --- /dev/null +++ b/packages/user_manager/tests/user_manager.test.ts @@ -0,0 +1,22 @@ +import { describe, it, expect } from 'vitest' + +describe('user_manager package', () => { + describe('metadata', () => { + it('should have valid package structure', async () => { + const metadata = await import('../seed/metadata.json') + expect(metadata.packageId).toBe('user_manager') + }) + }) + + describe('user actions', () => { + it.each([ + { action: 'create', requiresConfirm: false }, + { action: 'update', requiresConfirm: false }, + { action: 'delete', requiresConfirm: true }, + { action: 'change_level', requiresConfirm: false }, + ])('should handle $action', ({ action, requiresConfirm }) => { + expect(action).toBeDefined() + expect(typeof requiresConfirm).toBe('boolean') + }) + }) +}) diff --git a/packages/workflow_editor/seed/components.json b/packages/workflow_editor/seed/components.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/packages/workflow_editor/seed/components.json @@ -0,0 +1 @@ +[] diff --git a/packages/workflow_editor/seed/metadata.json b/packages/workflow_editor/seed/metadata.json new file mode 100644 index 000000000..a49ee2b6d --- /dev/null +++ b/packages/workflow_editor/seed/metadata.json @@ -0,0 +1,13 @@ +{ + "packageId": "workflow_editor", + "name": "Workflow Editor", + "version": "1.0.0", + "description": "Workflow editor and run status components", + "author": "MetaBuilder", + "category": "editors", + "dependencies": [], + "exports": { + "scripts": ["editor", "status", "run"], + "components": ["WorkflowEditor", "WorkflowRunCard", "WorkflowRunStatus"] + } +} diff --git a/packages/workflow_editor/seed/scripts/editor.lua b/packages/workflow_editor/seed/scripts/editor.lua new file mode 100644 index 000000000..637508d39 --- /dev/null +++ b/packages/workflow_editor/seed/scripts/editor.lua @@ -0,0 +1,33 @@ +-- Workflow editor rendering +local M = {} + +function M.render(workflow) + return { + type = "workflow_editor", + props = { + id = workflow and workflow.id, + name = workflow and workflow.name or "New Workflow", + steps = workflow and workflow.steps or {} + } + } +end + +function M.add_step(step_type, config) + return { + type = "workflow_step", + step_type = step_type, + config = config or {}, + position = { x = 0, y = 0 } + } +end + +function M.connect_steps(from_id, to_id, condition) + return { + type = "connection", + from = from_id, + to = to_id, + condition = condition + } +end + +return M diff --git a/packages/workflow_editor/seed/scripts/init.lua b/packages/workflow_editor/seed/scripts/init.lua new file mode 100644 index 000000000..96e77c748 --- /dev/null +++ b/packages/workflow_editor/seed/scripts/init.lua @@ -0,0 +1,15 @@ +-- Workflow Editor initialization +local M = {} + +M.name = "workflow_editor" +M.version = "1.0.0" + +function M.init() + return { + name = M.name, + version = M.version, + loaded = true + } +end + +return M diff --git a/packages/workflow_editor/seed/scripts/manifest.json b/packages/workflow_editor/seed/scripts/manifest.json new file mode 100644 index 000000000..4720c1523 --- /dev/null +++ b/packages/workflow_editor/seed/scripts/manifest.json @@ -0,0 +1,28 @@ +{ + "scripts": [ + { + "id": "init", + "name": "Workflow Editor Init", + "file": "init.lua", + "description": "Initialize workflow editor module" + }, + { + "id": "editor", + "name": "Workflow Editor", + "file": "editor.lua", + "description": "Workflow editor rendering" + }, + { + "id": "status", + "name": "Run Status", + "file": "status.lua", + "description": "Workflow run status display" + }, + { + "id": "run", + "name": "Run Card", + "file": "run.lua", + "description": "Workflow run card component" + } + ] +} diff --git a/packages/workflow_editor/seed/scripts/run.lua b/packages/workflow_editor/seed/scripts/run.lua new file mode 100644 index 000000000..bab2e9561 --- /dev/null +++ b/packages/workflow_editor/seed/scripts/run.lua @@ -0,0 +1,31 @@ +-- Workflow run card utilities +local M = {} + +function M.render(run) + return { + type = "card", + props = { + title = run.workflow_name, + subtitle = "Run #" .. run.run_number + }, + children = { + { type = "text", content = "Started: " .. run.started_at }, + { type = "text", content = "Duration: " .. (run.duration or "running") }, + { type = "status_badge", status = run.status } + } + } +end + +function M.render_list(runs) + local cards = {} + for _, run in ipairs(runs) do + table.insert(cards, M.render(run)) + end + return { + type = "grid", + columns = 2, + children = cards + } +end + +return M diff --git a/packages/workflow_editor/seed/scripts/status.lua b/packages/workflow_editor/seed/scripts/status.lua new file mode 100644 index 000000000..51a7a557b --- /dev/null +++ b/packages/workflow_editor/seed/scripts/status.lua @@ -0,0 +1,38 @@ +-- Workflow run status utilities +local M = {} + +M.PENDING = "pending" +M.RUNNING = "running" +M.SUCCESS = "success" +M.FAILED = "failed" +M.CANCELLED = "cancelled" + +function M.render_badge(status) + local colors = { + pending = "default", + running = "info", + success = "success", + failed = "error", + cancelled = "warning" + } + return { + type = "badge", + props = { + label = status, + color = colors[status] or "default" + } + } +end + +function M.render_progress(completed, total) + local percent = total > 0 and (completed / total * 100) or 0 + return { + type = "progress", + props = { + value = percent, + label = completed .. "/" .. total + } + } +end + +return M diff --git a/packages/workflow_editor/tests/workflow_editor.test.ts b/packages/workflow_editor/tests/workflow_editor.test.ts new file mode 100644 index 000000000..7ba129622 --- /dev/null +++ b/packages/workflow_editor/tests/workflow_editor.test.ts @@ -0,0 +1,23 @@ +import { describe, it, expect } from 'vitest' + +describe('workflow_editor package', () => { + describe('metadata', () => { + it('should have valid package structure', async () => { + const metadata = await import('../seed/metadata.json') + expect(metadata.packageId).toBe('workflow_editor') + }) + }) + + describe('run status', () => { + it.each([ + { status: 'pending', color: 'default' }, + { status: 'running', color: 'info' }, + { status: 'success', color: 'success' }, + { status: 'failed', color: 'error' }, + { status: 'cancelled', color: 'warning' }, + ])('should render $status badge', ({ status, color }) => { + expect(status).toBeDefined() + expect(color).toBeDefined() + }) + }) +})