mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-05-06 03:29:35 +00:00
feat: implement IRC Webchat component with workflows, actions, and layout schema
This commit is contained in:
+36
-230
@@ -1,238 +1,44 @@
|
||||
import type { PackageContent } from '../../package-types'
|
||||
import { ircWebchatComponentConfig } from './irc-webchat/schema/layout'
|
||||
|
||||
type IrcWebchatUiSchema = Pick<PackageContent, 'pages' | 'componentHierarchy' | 'componentConfigs'>
|
||||
|
||||
export const createIrcWebchatUiSchema = (): IrcWebchatUiSchema => ({
|
||||
pages: [
|
||||
{
|
||||
id: 'page_chat',
|
||||
path: '/chat',
|
||||
title: 'IRC Webchat',
|
||||
level: 2,
|
||||
componentTree: [
|
||||
{
|
||||
id: 'comp_chat_root',
|
||||
type: 'IRCWebchat',
|
||||
props: {
|
||||
channelName: 'general',
|
||||
},
|
||||
children: [],
|
||||
const pages: IrcWebchatUiSchema['pages'] = [
|
||||
{
|
||||
id: 'page_chat',
|
||||
path: '/chat',
|
||||
title: 'IRC Webchat',
|
||||
level: 2,
|
||||
componentTree: [
|
||||
{
|
||||
id: 'comp_chat_root',
|
||||
type: 'IRCWebchat',
|
||||
props: {
|
||||
channelName: 'general',
|
||||
},
|
||||
],
|
||||
requiresAuth: true,
|
||||
requiredRole: 'user',
|
||||
},
|
||||
],
|
||||
componentHierarchy: {
|
||||
page_chat: {
|
||||
id: 'comp_chat_root',
|
||||
type: 'IRCWebchat',
|
||||
props: {},
|
||||
children: [],
|
||||
},
|
||||
},
|
||||
componentConfigs: {
|
||||
IRCWebchat: {
|
||||
type: 'IRCWebchat',
|
||||
category: 'social',
|
||||
label: 'IRC Webchat',
|
||||
description: 'IRC-style chat component with channels and commands',
|
||||
icon: '💬',
|
||||
props: [
|
||||
{
|
||||
name: 'channelName',
|
||||
type: 'string',
|
||||
label: 'Channel Name',
|
||||
defaultValue: 'general',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'showSettings',
|
||||
type: 'boolean',
|
||||
label: 'Show Settings',
|
||||
defaultValue: false,
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'height',
|
||||
type: 'string',
|
||||
label: 'Height',
|
||||
defaultValue: '600px',
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
config: {
|
||||
layout: 'Card',
|
||||
styling: {
|
||||
className: 'h-[600px] flex flex-col',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'header',
|
||||
type: 'CardHeader',
|
||||
props: {
|
||||
className: 'border-b border-border pb-3',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'title_container',
|
||||
type: 'Flex',
|
||||
props: {
|
||||
className: 'flex items-center justify-between',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'title',
|
||||
type: 'CardTitle',
|
||||
props: {
|
||||
className: 'flex items-center gap-2 text-lg',
|
||||
content: '#{channelName}',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'actions',
|
||||
type: 'Flex',
|
||||
props: {
|
||||
className: 'flex items-center gap-2',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'user_badge',
|
||||
type: 'Badge',
|
||||
props: {
|
||||
variant: 'secondary',
|
||||
className: 'gap-1.5',
|
||||
icon: 'Users',
|
||||
content: '{onlineUsersCount}',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'settings_button',
|
||||
type: 'Button',
|
||||
props: {
|
||||
size: 'sm',
|
||||
variant: 'ghost',
|
||||
icon: 'Gear',
|
||||
onClick: 'toggleSettings',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'content',
|
||||
type: 'CardContent',
|
||||
props: {
|
||||
className: 'flex-1 flex flex-col p-0 overflow-hidden',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'main_area',
|
||||
type: 'Flex',
|
||||
props: {
|
||||
className: 'flex flex-1 overflow-hidden',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'messages_area',
|
||||
type: 'ScrollArea',
|
||||
props: {
|
||||
className: 'flex-1 p-4',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'messages_container',
|
||||
type: 'MessageList',
|
||||
props: {
|
||||
className: 'space-y-2 font-mono text-sm',
|
||||
dataSource: 'messages',
|
||||
itemRenderer: 'renderMessage',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'sidebar',
|
||||
type: 'Container',
|
||||
props: {
|
||||
className: 'w-48 border-l border-border p-4 bg-muted/20',
|
||||
conditional: 'showSettings',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'sidebar_title',
|
||||
type: 'Heading',
|
||||
props: {
|
||||
level: '4',
|
||||
className: 'font-semibold text-sm mb-3',
|
||||
content: 'Online Users',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'users_list',
|
||||
type: 'UserList',
|
||||
props: {
|
||||
className: 'space-y-1.5 text-sm',
|
||||
dataSource: 'onlineUsers',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'input_area',
|
||||
type: 'Container',
|
||||
props: {
|
||||
className: 'border-t border-border p-4',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'input_row',
|
||||
type: 'Flex',
|
||||
props: {
|
||||
className: 'flex gap-2',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'message_input',
|
||||
type: 'Input',
|
||||
props: {
|
||||
className: 'flex-1 font-mono',
|
||||
placeholder: 'Type a message... (/help for commands)',
|
||||
onKeyPress: 'handleKeyPress',
|
||||
value: '{inputMessage}',
|
||||
onChange: 'updateInputMessage',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'send_button',
|
||||
type: 'Button',
|
||||
props: {
|
||||
size: 'icon',
|
||||
icon: 'PaperPlaneTilt',
|
||||
onClick: 'handleSendMessage',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'help_text',
|
||||
type: 'Text',
|
||||
props: {
|
||||
className: 'text-xs text-muted-foreground mt-2',
|
||||
content: 'Press Enter to send. Type /help for commands.',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
children: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
requiresAuth: true,
|
||||
requiredRole: 'user',
|
||||
},
|
||||
]
|
||||
|
||||
const componentHierarchy: IrcWebchatUiSchema['componentHierarchy'] = {
|
||||
page_chat: {
|
||||
id: 'comp_chat_root',
|
||||
type: 'IRCWebchat',
|
||||
props: {},
|
||||
children: [],
|
||||
},
|
||||
}
|
||||
|
||||
const componentConfigs: IrcWebchatUiSchema['componentConfigs'] = {
|
||||
IRCWebchat: ircWebchatComponentConfig,
|
||||
}
|
||||
|
||||
export const createIrcWebchatUiSchema = (): IrcWebchatUiSchema => ({
|
||||
pages,
|
||||
componentHierarchy,
|
||||
componentConfigs,
|
||||
})
|
||||
|
||||
+8
-192
@@ -1,197 +1,13 @@
|
||||
import type { PackageContent } from '../../package-types'
|
||||
import { commandActions } from './irc-webchat/actions/commands'
|
||||
import { eventActions } from './irc-webchat/actions/events'
|
||||
|
||||
type IrcWebchatWorkflows = Pick<PackageContent, 'workflows' | 'luaScripts'>
|
||||
|
||||
export const createIrcWebchatWorkflowActions = (): IrcWebchatWorkflows => ({
|
||||
workflows: [
|
||||
{
|
||||
id: 'workflow_send_message',
|
||||
name: 'Send Chat Message',
|
||||
description: 'Workflow for sending a chat message',
|
||||
nodes: [],
|
||||
edges: [],
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
id: 'workflow_join_channel',
|
||||
name: 'Join Channel',
|
||||
description: 'Workflow for joining a chat channel',
|
||||
nodes: [],
|
||||
edges: [],
|
||||
enabled: true,
|
||||
},
|
||||
],
|
||||
luaScripts: [
|
||||
{
|
||||
id: 'lua_irc_send_message',
|
||||
name: 'Send IRC Message',
|
||||
description: 'Sends a message to the chat channel',
|
||||
code: `-- Send IRC Message
|
||||
function sendMessage(channelId, username, userId, message)
|
||||
local msgId = "msg_" .. tostring(os.time()) .. "_" .. math.random(1000, 9999)
|
||||
local msg = {
|
||||
id = msgId,
|
||||
channelId = channelId,
|
||||
username = username,
|
||||
userId = userId,
|
||||
message = message,
|
||||
type = "message",
|
||||
timestamp = os.time() * 1000
|
||||
}
|
||||
log("Sending message: " .. message)
|
||||
return msg
|
||||
end
|
||||
|
||||
return sendMessage`,
|
||||
parameters: [
|
||||
{ name: 'channelId', type: 'string' },
|
||||
{ name: 'username', type: 'string' },
|
||||
{ name: 'userId', type: 'string' },
|
||||
{ name: 'message', type: 'string' },
|
||||
],
|
||||
returnType: 'table',
|
||||
},
|
||||
{
|
||||
id: 'lua_irc_handle_command',
|
||||
name: 'Handle IRC Command',
|
||||
description: 'Processes IRC commands like /help, /users, etc',
|
||||
code: `-- Handle IRC Command
|
||||
function handleCommand(command, channelId, username, onlineUsers)
|
||||
local parts = {}
|
||||
for part in string.gmatch(command, "%S+") do
|
||||
table.insert(parts, part)
|
||||
end
|
||||
|
||||
local cmd = parts[1]:lower()
|
||||
local response = {
|
||||
id = "msg_" .. tostring(os.time()) .. "_" .. math.random(1000, 9999),
|
||||
username = "System",
|
||||
userId = "system",
|
||||
type = "system",
|
||||
timestamp = os.time() * 1000,
|
||||
channelId = channelId
|
||||
}
|
||||
|
||||
if cmd == "/help" then
|
||||
response.message = "Available commands: /help, /users, /clear, /me <action>"
|
||||
elseif cmd == "/users" then
|
||||
local userCount = #onlineUsers
|
||||
local userList = table.concat(onlineUsers, ", ")
|
||||
response.message = "Online users (" .. userCount .. "): " .. userList
|
||||
elseif cmd == "/clear" then
|
||||
response.message = "CLEAR_MESSAGES"
|
||||
response.type = "command"
|
||||
elseif cmd == "/me" then
|
||||
if #parts > 1 then
|
||||
local action = table.concat(parts, " ", 2)
|
||||
response.message = action
|
||||
response.username = username
|
||||
response.userId = username
|
||||
response.type = "system"
|
||||
else
|
||||
response.message = "Usage: /me <action>"
|
||||
end
|
||||
else
|
||||
response.message = "Unknown command: " .. cmd .. ". Type /help for available commands."
|
||||
end
|
||||
|
||||
return response
|
||||
end
|
||||
|
||||
return handleCommand`,
|
||||
parameters: [
|
||||
{ name: 'command', type: 'string' },
|
||||
{ name: 'channelId', type: 'string' },
|
||||
{ name: 'username', type: 'string' },
|
||||
{ name: 'onlineUsers', type: 'table' },
|
||||
],
|
||||
returnType: 'table',
|
||||
},
|
||||
{
|
||||
id: 'lua_irc_format_time',
|
||||
name: 'Format Timestamp',
|
||||
description: 'Formats a timestamp for display',
|
||||
code: `-- Format Timestamp
|
||||
function formatTime(timestamp)
|
||||
local date = os.date("*t", timestamp / 1000)
|
||||
local hour = date.hour
|
||||
local ampm = "AM"
|
||||
|
||||
if hour >= 12 then
|
||||
ampm = "PM"
|
||||
if hour > 12 then
|
||||
hour = hour - 12
|
||||
end
|
||||
end
|
||||
|
||||
if hour == 0 then
|
||||
hour = 12
|
||||
end
|
||||
|
||||
return string.format("%02d:%02d %s", hour, date.min, ampm)
|
||||
end
|
||||
|
||||
return formatTime`,
|
||||
parameters: [
|
||||
{ name: 'timestamp', type: 'number' },
|
||||
],
|
||||
returnType: 'string',
|
||||
},
|
||||
{
|
||||
id: 'lua_irc_user_join',
|
||||
name: 'User Join Channel',
|
||||
description: 'Handles user joining a channel',
|
||||
code: `-- User Join Channel
|
||||
function userJoin(channelId, username, userId)
|
||||
local joinMsg = {
|
||||
id = "msg_" .. tostring(os.time()) .. "_" .. math.random(1000, 9999),
|
||||
channelId = channelId,
|
||||
username = "System",
|
||||
userId = "system",
|
||||
message = username .. " has joined the channel",
|
||||
type = "join",
|
||||
timestamp = os.time() * 1000
|
||||
}
|
||||
|
||||
log(username .. " joined channel " .. channelId)
|
||||
return joinMsg
|
||||
end
|
||||
|
||||
return userJoin`,
|
||||
parameters: [
|
||||
{ name: 'channelId', type: 'string' },
|
||||
{ name: 'username', type: 'string' },
|
||||
{ name: 'userId', type: 'string' },
|
||||
],
|
||||
returnType: 'table',
|
||||
},
|
||||
{
|
||||
id: 'lua_irc_user_leave',
|
||||
name: 'User Leave Channel',
|
||||
description: 'Handles user leaving a channel',
|
||||
code: `-- User Leave Channel
|
||||
function userLeave(channelId, username, userId)
|
||||
local leaveMsg = {
|
||||
id = "msg_" .. tostring(os.time()) .. "_" .. math.random(1000, 9999),
|
||||
channelId = channelId,
|
||||
username = "System",
|
||||
userId = "system",
|
||||
message = username .. " has left the channel",
|
||||
type = "leave",
|
||||
timestamp = os.time() * 1000
|
||||
}
|
||||
|
||||
log(username .. " left channel " .. channelId)
|
||||
return leaveMsg
|
||||
end
|
||||
|
||||
return userLeave`,
|
||||
parameters: [
|
||||
{ name: 'channelId', type: 'string' },
|
||||
{ name: 'username', type: 'string' },
|
||||
{ name: 'userId', type: 'string' },
|
||||
],
|
||||
returnType: 'table',
|
||||
},
|
||||
],
|
||||
const mergeActions = (...actions: IrcWebchatWorkflows[]): IrcWebchatWorkflows => ({
|
||||
workflows: actions.flatMap((action) => action.workflows),
|
||||
luaScripts: actions.flatMap((action) => action.luaScripts),
|
||||
})
|
||||
|
||||
export const createIrcWebchatWorkflowActions = (): IrcWebchatWorkflows =>
|
||||
mergeActions(commandActions, eventActions)
|
||||
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
import type { PackageContent } from '../../../../package-types'
|
||||
|
||||
type IrcWebchatWorkflowActions = Pick<PackageContent, 'workflows' | 'luaScripts'>
|
||||
|
||||
export const commandActions: IrcWebchatWorkflowActions = {
|
||||
workflows: [
|
||||
{
|
||||
id: 'workflow_send_message',
|
||||
name: 'Send Chat Message',
|
||||
description: 'Workflow for sending a chat message',
|
||||
nodes: [],
|
||||
edges: [],
|
||||
enabled: true,
|
||||
},
|
||||
],
|
||||
luaScripts: [
|
||||
{
|
||||
id: 'lua_irc_send_message',
|
||||
name: 'Send IRC Message',
|
||||
description: 'Sends a message to the chat channel',
|
||||
code: `-- Send IRC Message
|
||||
function sendMessage(channelId, username, userId, message)
|
||||
local msgId = "msg_" .. tostring(os.time()) .. "_" .. math.random(1000, 9999)
|
||||
local msg = {
|
||||
id = msgId,
|
||||
channelId = channelId,
|
||||
username = username,
|
||||
userId = userId,
|
||||
message = message,
|
||||
type = "message",
|
||||
timestamp = os.time() * 1000
|
||||
}
|
||||
log("Sending message: " .. message)
|
||||
return msg
|
||||
end
|
||||
|
||||
return sendMessage`,
|
||||
parameters: [
|
||||
{ name: 'channelId', type: 'string' },
|
||||
{ name: 'username', type: 'string' },
|
||||
{ name: 'userId', type: 'string' },
|
||||
{ name: 'message', type: 'string' },
|
||||
],
|
||||
returnType: 'table',
|
||||
},
|
||||
{
|
||||
id: 'lua_irc_handle_command',
|
||||
name: 'Handle IRC Command',
|
||||
description: 'Processes IRC commands like /help, /users, etc',
|
||||
code: `-- Handle IRC Command
|
||||
function handleCommand(command, channelId, username, onlineUsers)
|
||||
local parts = {}
|
||||
for part in string.gmatch(command, "%S+") do
|
||||
table.insert(parts, part)
|
||||
end
|
||||
|
||||
local cmd = parts[1]:lower()
|
||||
local response = {
|
||||
id = "msg_" .. tostring(os.time()) .. "_" .. math.random(1000, 9999),
|
||||
username = "System",
|
||||
userId = "system",
|
||||
type = "system",
|
||||
timestamp = os.time() * 1000,
|
||||
channelId = channelId
|
||||
}
|
||||
|
||||
if cmd == "/help" then
|
||||
response.message = "Available commands: /help, /users, /clear, /me <action>"
|
||||
elseif cmd == "/users" then
|
||||
local userCount = #onlineUsers
|
||||
local userList = table.concat(onlineUsers, ", ")
|
||||
response.message = "Online users (" .. userCount .. "): " .. userList
|
||||
elseif cmd == "/clear" then
|
||||
response.message = "CLEAR_MESSAGES"
|
||||
response.type = "command"
|
||||
elseif cmd == "/me" then
|
||||
if #parts > 1 then
|
||||
local action = table.concat(parts, " ", 2)
|
||||
response.message = action
|
||||
response.username = username
|
||||
response.userId = username
|
||||
response.type = "system"
|
||||
else
|
||||
response.message = "Usage: /me <action>"
|
||||
end
|
||||
else
|
||||
response.message = "Unknown command: " .. cmd .. ". Type /help for available commands."
|
||||
end
|
||||
|
||||
return response
|
||||
end
|
||||
|
||||
return handleCommand`,
|
||||
parameters: [
|
||||
{ name: 'command', type: 'string' },
|
||||
{ name: 'channelId', type: 'string' },
|
||||
{ name: 'username', type: 'string' },
|
||||
{ name: 'onlineUsers', type: 'table' },
|
||||
],
|
||||
returnType: 'table',
|
||||
},
|
||||
],
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
import type { PackageContent } from '../../../../package-types'
|
||||
|
||||
type IrcWebchatWorkflowActions = Pick<PackageContent, 'workflows' | 'luaScripts'>
|
||||
|
||||
export const eventActions: IrcWebchatWorkflowActions = {
|
||||
workflows: [
|
||||
{
|
||||
id: 'workflow_join_channel',
|
||||
name: 'Join Channel',
|
||||
description: 'Workflow for joining a chat channel',
|
||||
nodes: [],
|
||||
edges: [],
|
||||
enabled: true,
|
||||
},
|
||||
],
|
||||
luaScripts: [
|
||||
{
|
||||
id: 'lua_irc_format_time',
|
||||
name: 'Format Timestamp',
|
||||
description: 'Formats a timestamp for display',
|
||||
code: `-- Format Timestamp
|
||||
function formatTime(timestamp)
|
||||
local date = os.date("*t", timestamp / 1000)
|
||||
local hour = date.hour
|
||||
local ampm = "AM"
|
||||
|
||||
if hour >= 12 then
|
||||
ampm = "PM"
|
||||
if hour > 12 then
|
||||
hour = hour - 12
|
||||
end
|
||||
end
|
||||
|
||||
if hour == 0 then
|
||||
hour = 12
|
||||
end
|
||||
|
||||
return string.format("%02d:%02d %s", hour, date.min, ampm)
|
||||
end
|
||||
|
||||
return formatTime`,
|
||||
parameters: [
|
||||
{ name: 'timestamp', type: 'number' },
|
||||
],
|
||||
returnType: 'string',
|
||||
},
|
||||
{
|
||||
id: 'lua_irc_user_join',
|
||||
name: 'User Join Channel',
|
||||
description: 'Handles user joining a channel',
|
||||
code: `-- User Join Channel
|
||||
function userJoin(channelId, username, userId)
|
||||
local joinMsg = {
|
||||
id = "msg_" .. tostring(os.time()) .. "_" .. math.random(1000, 9999),
|
||||
channelId = channelId,
|
||||
username = "System",
|
||||
userId = "system",
|
||||
message = username .. " has joined the channel",
|
||||
type = "join",
|
||||
timestamp = os.time() * 1000
|
||||
}
|
||||
|
||||
log(username .. " joined channel " .. channelId)
|
||||
return joinMsg
|
||||
end
|
||||
|
||||
return userJoin`,
|
||||
parameters: [
|
||||
{ name: 'channelId', type: 'string' },
|
||||
{ name: 'username', type: 'string' },
|
||||
{ name: 'userId', type: 'string' },
|
||||
],
|
||||
returnType: 'table',
|
||||
},
|
||||
{
|
||||
id: 'lua_irc_user_leave',
|
||||
name: 'User Leave Channel',
|
||||
description: 'Handles user leaving a channel',
|
||||
code: `-- User Leave Channel
|
||||
function userLeave(channelId, username, userId)
|
||||
local leaveMsg = {
|
||||
id = "msg_" .. tostring(os.time()) .. "_" .. math.random(1000, 9999),
|
||||
channelId = channelId,
|
||||
username = "System",
|
||||
userId = "system",
|
||||
message = username .. " has left the channel",
|
||||
type = "leave",
|
||||
timestamp = os.time() * 1000
|
||||
}
|
||||
|
||||
log(username .. " left channel " .. channelId)
|
||||
return leaveMsg
|
||||
end
|
||||
|
||||
return userLeave`,
|
||||
parameters: [
|
||||
{ name: 'channelId', type: 'string' },
|
||||
{ name: 'username', type: 'string' },
|
||||
{ name: 'userId', type: 'string' },
|
||||
],
|
||||
returnType: 'table',
|
||||
},
|
||||
],
|
||||
}
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
import { createMessageArea, createMessageInputArea } from './messages'
|
||||
|
||||
const createHeaderSection = () => ({
|
||||
id: 'header',
|
||||
type: 'CardHeader',
|
||||
props: {
|
||||
className: 'border-b border-border pb-3',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'title_container',
|
||||
type: 'Flex',
|
||||
props: {
|
||||
className: 'flex items-center justify-between',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'title',
|
||||
type: 'CardTitle',
|
||||
props: {
|
||||
className: 'flex items-center gap-2 text-lg',
|
||||
content: '#{channelName}',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'actions',
|
||||
type: 'Flex',
|
||||
props: {
|
||||
className: 'flex items-center gap-2',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'user_badge',
|
||||
type: 'Badge',
|
||||
props: {
|
||||
variant: 'secondary',
|
||||
className: 'gap-1.5',
|
||||
icon: 'Users',
|
||||
content: '{onlineUsersCount}',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'settings_button',
|
||||
type: 'Button',
|
||||
props: {
|
||||
size: 'sm',
|
||||
variant: 'ghost',
|
||||
icon: 'Gear',
|
||||
onClick: 'toggleSettings',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const createSidebar = () => ({
|
||||
id: 'sidebar',
|
||||
type: 'Container',
|
||||
props: {
|
||||
className: 'w-48 border-l border-border p-4 bg-muted/20',
|
||||
conditional: 'showSettings',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'sidebar_title',
|
||||
type: 'Heading',
|
||||
props: {
|
||||
level: '4',
|
||||
className: 'font-semibold text-sm mb-3',
|
||||
content: 'Online Users',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'users_list',
|
||||
type: 'UserList',
|
||||
props: {
|
||||
className: 'space-y-1.5 text-sm',
|
||||
dataSource: 'onlineUsers',
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
export const ircWebchatComponentConfig = {
|
||||
type: 'IRCWebchat',
|
||||
category: 'social',
|
||||
label: 'IRC Webchat',
|
||||
description: 'IRC-style chat component with channels and commands',
|
||||
icon: '💬',
|
||||
props: [
|
||||
{
|
||||
name: 'channelName',
|
||||
type: 'string',
|
||||
label: 'Channel Name',
|
||||
defaultValue: 'general',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'showSettings',
|
||||
type: 'boolean',
|
||||
label: 'Show Settings',
|
||||
defaultValue: false,
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'height',
|
||||
type: 'string',
|
||||
label: 'Height',
|
||||
defaultValue: '600px',
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
config: {
|
||||
layout: 'Card',
|
||||
styling: {
|
||||
className: 'h-[600px] flex flex-col',
|
||||
},
|
||||
children: [
|
||||
createHeaderSection(),
|
||||
{
|
||||
id: 'content',
|
||||
type: 'CardContent',
|
||||
props: {
|
||||
className: 'flex-1 flex flex-col p-0 overflow-hidden',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'main_area',
|
||||
type: 'Flex',
|
||||
props: {
|
||||
className: 'flex flex-1 overflow-hidden',
|
||||
},
|
||||
children: [createMessageArea(), createSidebar()],
|
||||
},
|
||||
createMessageInputArea(),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
export const createMessageArea = () => ({
|
||||
id: 'messages_area',
|
||||
type: 'ScrollArea',
|
||||
props: {
|
||||
className: 'flex-1 p-4',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'messages_container',
|
||||
type: 'MessageList',
|
||||
props: {
|
||||
className: 'space-y-2 font-mono text-sm',
|
||||
dataSource: 'messages',
|
||||
itemRenderer: 'renderMessage',
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
export const createMessageInputArea = () => ({
|
||||
id: 'input_area',
|
||||
type: 'Container',
|
||||
props: {
|
||||
className: 'border-t border-border p-4',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'input_row',
|
||||
type: 'Flex',
|
||||
props: {
|
||||
className: 'flex gap-2',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'message_input',
|
||||
type: 'Input',
|
||||
props: {
|
||||
className: 'flex-1 font-mono',
|
||||
placeholder: 'Type a message... (/help for commands)',
|
||||
onKeyPress: 'handleKeyPress',
|
||||
value: '{inputMessage}',
|
||||
onChange: 'updateInputMessage',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'send_button',
|
||||
type: 'Button',
|
||||
props: {
|
||||
size: 'icon',
|
||||
icon: 'PaperPlaneTilt',
|
||||
onClick: 'handleSendMessage',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'help_text',
|
||||
type: 'Text',
|
||||
props: {
|
||||
className: 'text-xs text-muted-foreground mt-2',
|
||||
content: 'Press Enter to send. Type /help for commands.',
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
Reference in New Issue
Block a user