Spaces:
Running
Running
File size: 6,840 Bytes
e08e97a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
import gradio as gr
import modelscope_studio.components.antd as antd
import modelscope_studio.components.base as ms
import modelscope_studio.components.pro as pro
with gr.Blocks() as demo, ms.Application(), antd.ConfigProvider():
pro.WebSandbox(value={
"./index.tsx":
"""import Demo from './demo.tsx'
import "@tailwindcss/browser"
export default Demo
""",
"./demo.tsx":
"""import { useState, useEffect } from 'react';
export default function App() {
const [messages, setMessages] = useState([
{ id: 1, sender: 'ai', content: 'Hello! I am your AI assistant. How can I help you today?', timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) },
]);
const [inputValue, setInputValue] = useState('');
const [isTyping, setIsTyping] = useState(false);
const [darkMode, setDarkMode] = useState(false);
// Simulate AI typing effect
const handleSendMessage = () => {
if (inputValue.trim() === '') return;
const userMessage = {
id: messages.length + 1,
sender: 'user',
content: inputValue,
timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
};
setMessages((prev) => [...prev, userMessage]);
setInputValue('');
setIsTyping(true);
// Simulate AI response after delay
setTimeout(() => {
const aiResponse = {
id: messages.length + 2,
sender: 'ai',
content: 'I am processing your request and will respond shortly.',
timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
};
setMessages((prev) => [...prev, aiResponse]);
setIsTyping(false);
}, 1500);
};
// Handle Enter key press
const handleKeyPress = (e) => {
if (e.key === 'Enter') {
handleSendMessage();
}
};
// Toggle dark mode
const toggleDarkMode = () => {
setDarkMode(!darkMode);
};
useEffect(() => {
const app = document.documentElement;
if (darkMode) {
app.classList.add('dark');
} else {
app.classList.remove('dark');
}
}, [darkMode]);
return (
<div className={"min-h-screen flex flex-col transition-colors duration-300 " + (darkMode ? 'bg-gray-900 text-white' : 'bg-gray-100 text-gray-900')}>
{/* Header */}
<header className={"px-6 py-4 shadow-md flex justify-between items-center " + (darkMode ? 'bg-gray-800' : 'bg-white')}>
<div className="flex items-center space-x-2">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" className="text-blue-500">
<path d="M12 4L4 8V16L12 20L20 16V8L12 4Z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M12 15L9 12H15L12 9V15Z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
<h1 className="text-xl font-bold">Chatbot</h1>
</div>
<button onClick={toggleDarkMode} className="p-2 rounded-full hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors">
{darkMode ? (
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="5" stroke="white" strokeWidth="2"/>
<path d="M12 2V4M12 20V22M4 12H2M6.31 6.31L4.9 4.9M17.69 6.31L19.1 4.9M6.31 17.69L4.9 19.1M17.69 17.69L19.1 19.1" stroke="white" strokeWidth="2" strokeLinecap="round"/>
</svg>
) : (
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
)}
</button>
</header>
{/* Chat Area */}
<div className="flex-1 overflow-y-auto p-4 space-y-4">
{messages.map((message) => (
<div
key={message.id}
className={"flex " + (message.sender === 'user' ? 'justify-end' : 'justify-start')}
>
<div
className={"max-w-xs sm:max-w-md px-4 py-2 rounded-lg " +
(message.sender === 'user'
? 'bg-blue-500 text-white rounded-br-none'
: (darkMode ? 'bg-gray-700' : 'bg-white') + ' rounded-bl-none')
}
>
<p>{message.content}</p>
<span className={"text-xs mt-1 block " + (message.sender === 'user' ? 'text-blue-100' : 'text-gray-500')}>
{message.timestamp}
</span>
</div>
</div>
))}
{isTyping && (
<div className="flex justify-start">
<div className={"px-4 py-2 rounded-lg " + (darkMode ? 'bg-gray-700' : 'bg-white') + ' rounded-bl-none'}>
<div className="flex space-x-1">
<span className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{ animationDelay: '0ms' }}></span>
<span className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{ animationDelay: '150ms' }}></span>
<span className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{ animationDelay: '300ms' }}></span>
</div>
</div>
</div>
)}
</div>
{/* Input Area */}
<div className={"p-4 border-t " + (darkMode ? 'bg-gray-800 border-gray-700' : 'bg-white border-gray-200')}>
<div className="flex space-x-2">
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onKeyPress={handleKeyPress}
placeholder="Type a message..."
className={"flex-1 px-4 py-2 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 " +
(darkMode ? 'bg-gray-700 text-white placeholder-gray-400' : 'bg-gray-100 text-gray-900 placeholder-gray-500')
}
/>
<button
onClick={handleSendMessage}
disabled={inputValue.trim() === ''}
className={"px-4 py-2 rounded-lg font-medium text-white bg-blue-500 hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors " +
(inputValue.trim() === '' ? 'opacity-50 cursor-not-allowed' : '')
}
>
Send
</button>
</div>
</div>
</div>
);
}"""
},
height=600,
template="react",
imports={
"@tailwindcss/browser":
"https://esm.sh/@tailwindcss/browser",
})
if __name__ == "__main__":
demo.queue().launch()
|