@object-ui/plugin-chatbot 3.1.5 → 3.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/README.md +106 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +12293 -2897
- package/dist/index.umd.cjs +101 -28
- package/dist/{src → packages/plugin-chatbot/src}/ChatbotEnhanced.d.ts +8 -0
- package/dist/packages/plugin-chatbot/src/ChatbotEnhanced.d.ts.map +1 -0
- package/dist/packages/plugin-chatbot/src/FloatingChatbot.d.ts +15 -0
- package/dist/packages/plugin-chatbot/src/FloatingChatbot.d.ts.map +1 -0
- package/dist/packages/plugin-chatbot/src/FloatingChatbotPanel.d.ts +29 -0
- package/dist/packages/plugin-chatbot/src/FloatingChatbotPanel.d.ts.map +1 -0
- package/dist/packages/plugin-chatbot/src/FloatingChatbotProvider.d.ts +37 -0
- package/dist/packages/plugin-chatbot/src/FloatingChatbotProvider.d.ts.map +1 -0
- package/dist/packages/plugin-chatbot/src/FloatingChatbotTrigger.d.ts +21 -0
- package/dist/packages/plugin-chatbot/src/FloatingChatbotTrigger.d.ts.map +1 -0
- package/dist/{src → packages/plugin-chatbot/src}/index.d.ts +10 -0
- package/dist/packages/plugin-chatbot/src/index.d.ts.map +1 -0
- package/dist/packages/plugin-chatbot/src/renderer.d.ts.map +1 -0
- package/dist/packages/plugin-chatbot/src/useObjectChat.d.ts +112 -0
- package/dist/packages/plugin-chatbot/src/useObjectChat.d.ts.map +1 -0
- package/dist/packages/plugin-chatbot/src/utils.d.ts.map +1 -0
- package/package.json +36 -10
- package/.turbo/turbo-build.log +0 -22
- package/dist/src/ChatbotEnhanced.d.ts.map +0 -1
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/renderer.d.ts.map +0 -1
- package/dist/src/utils.d.ts.map +0 -1
- package/src/ChatbotEnhanced.tsx +0 -375
- package/src/__tests__/ChatbotEnhanced.test.tsx +0 -199
- package/src/index.tsx +0 -248
- package/src/renderer.tsx +0 -314
- package/src/utils.ts +0 -18
- package/tsconfig.json +0 -18
- package/vite.config.ts +0 -54
- /package/dist/{src → packages/plugin-chatbot/src}/renderer.d.ts +0 -0
- /package/dist/{src → packages/plugin-chatbot/src}/utils.d.ts +0 -0
package/src/index.tsx
DELETED
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ObjectUI
|
|
3
|
-
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
-
*
|
|
5
|
-
* This source code is licensed under the MIT license found in the
|
|
6
|
-
* LICENSE file in the root directory of this source tree.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import * as React from "react"
|
|
10
|
-
import { cn } from "@object-ui/components"
|
|
11
|
-
import { Button, Input, ScrollArea, Avatar, AvatarFallback, AvatarImage } from "@object-ui/components"
|
|
12
|
-
import { Send } from "lucide-react"
|
|
13
|
-
|
|
14
|
-
// Message type definition
|
|
15
|
-
export interface ChatMessage {
|
|
16
|
-
id: string
|
|
17
|
-
role: "user" | "assistant" | "system"
|
|
18
|
-
content: string
|
|
19
|
-
timestamp?: string
|
|
20
|
-
avatar?: string
|
|
21
|
-
avatarFallback?: string
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Chatbot container props
|
|
25
|
-
export interface ChatbotProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
26
|
-
messages?: ChatMessage[]
|
|
27
|
-
placeholder?: string
|
|
28
|
-
onSendMessage?: (message: string) => void
|
|
29
|
-
disabled?: boolean
|
|
30
|
-
showTimestamp?: boolean
|
|
31
|
-
userAvatarUrl?: string
|
|
32
|
-
userAvatarFallback?: string
|
|
33
|
-
assistantAvatarUrl?: string
|
|
34
|
-
assistantAvatarFallback?: string
|
|
35
|
-
maxHeight?: string
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Chatbot container component
|
|
39
|
-
const Chatbot = React.forwardRef<HTMLDivElement, ChatbotProps>(
|
|
40
|
-
(
|
|
41
|
-
{
|
|
42
|
-
className,
|
|
43
|
-
messages = [],
|
|
44
|
-
placeholder = "Type your message...",
|
|
45
|
-
onSendMessage,
|
|
46
|
-
disabled = false,
|
|
47
|
-
showTimestamp = false,
|
|
48
|
-
userAvatarUrl,
|
|
49
|
-
userAvatarFallback = "You",
|
|
50
|
-
assistantAvatarUrl,
|
|
51
|
-
assistantAvatarFallback = "AI",
|
|
52
|
-
maxHeight = "500px",
|
|
53
|
-
...props
|
|
54
|
-
},
|
|
55
|
-
ref
|
|
56
|
-
) => {
|
|
57
|
-
const [inputValue, setInputValue] = React.useState("")
|
|
58
|
-
const scrollRef = React.useRef<HTMLDivElement>(null)
|
|
59
|
-
const inputRef = React.useRef<HTMLInputElement>(null)
|
|
60
|
-
|
|
61
|
-
// Auto-scroll to bottom when new messages arrive
|
|
62
|
-
React.useEffect(() => {
|
|
63
|
-
if (scrollRef.current) {
|
|
64
|
-
const scrollElement = scrollRef.current.querySelector('[data-radix-scroll-area-viewport]')
|
|
65
|
-
if (scrollElement) {
|
|
66
|
-
scrollElement.scrollTop = scrollElement.scrollHeight
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}, [messages])
|
|
70
|
-
|
|
71
|
-
const handleSend = () => {
|
|
72
|
-
if (inputValue.trim() && onSendMessage) {
|
|
73
|
-
onSendMessage(inputValue.trim())
|
|
74
|
-
setInputValue("")
|
|
75
|
-
inputRef.current?.focus()
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
80
|
-
if (e.key === "Enter" && !e.shiftKey) {
|
|
81
|
-
e.preventDefault()
|
|
82
|
-
handleSend()
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return (
|
|
87
|
-
<div
|
|
88
|
-
ref={ref}
|
|
89
|
-
className={cn(
|
|
90
|
-
"flex flex-col border rounded-lg bg-background overflow-hidden",
|
|
91
|
-
className
|
|
92
|
-
)}
|
|
93
|
-
style={{ maxHeight }}
|
|
94
|
-
{...props}
|
|
95
|
-
>
|
|
96
|
-
{/* Messages area */}
|
|
97
|
-
<ScrollArea ref={scrollRef} className="flex-1 p-4">
|
|
98
|
-
<div className="space-y-4">
|
|
99
|
-
{messages.length === 0 ? (
|
|
100
|
-
<div className="flex items-center justify-center h-32 text-muted-foreground text-sm">
|
|
101
|
-
No messages yet. Start a conversation!
|
|
102
|
-
</div>
|
|
103
|
-
) : (
|
|
104
|
-
messages.map((message) => (
|
|
105
|
-
<ChatMessageItem
|
|
106
|
-
key={message.id}
|
|
107
|
-
message={message}
|
|
108
|
-
showTimestamp={showTimestamp}
|
|
109
|
-
userAvatarUrl={userAvatarUrl}
|
|
110
|
-
userAvatarFallback={userAvatarFallback}
|
|
111
|
-
assistantAvatarUrl={assistantAvatarUrl}
|
|
112
|
-
assistantAvatarFallback={assistantAvatarFallback}
|
|
113
|
-
/>
|
|
114
|
-
))
|
|
115
|
-
)}
|
|
116
|
-
</div>
|
|
117
|
-
</ScrollArea>
|
|
118
|
-
|
|
119
|
-
{/* Input area */}
|
|
120
|
-
<div className="border-t p-4">
|
|
121
|
-
<div className="flex gap-2">
|
|
122
|
-
<Input
|
|
123
|
-
ref={inputRef}
|
|
124
|
-
value={inputValue}
|
|
125
|
-
onChange={(e) => setInputValue(e.target.value)}
|
|
126
|
-
onKeyDown={handleKeyDown}
|
|
127
|
-
placeholder={placeholder}
|
|
128
|
-
disabled={disabled}
|
|
129
|
-
className="flex-1"
|
|
130
|
-
/>
|
|
131
|
-
<Button
|
|
132
|
-
onClick={handleSend}
|
|
133
|
-
disabled={disabled || !inputValue.trim()}
|
|
134
|
-
size="icon"
|
|
135
|
-
>
|
|
136
|
-
<Send className="h-4 w-4" />
|
|
137
|
-
</Button>
|
|
138
|
-
</div>
|
|
139
|
-
</div>
|
|
140
|
-
</div>
|
|
141
|
-
)
|
|
142
|
-
}
|
|
143
|
-
)
|
|
144
|
-
Chatbot.displayName = "Chatbot"
|
|
145
|
-
|
|
146
|
-
// Individual message component
|
|
147
|
-
export interface ChatMessageProps {
|
|
148
|
-
message: ChatMessage
|
|
149
|
-
showTimestamp?: boolean
|
|
150
|
-
userAvatarUrl?: string
|
|
151
|
-
userAvatarFallback?: string
|
|
152
|
-
assistantAvatarUrl?: string
|
|
153
|
-
assistantAvatarFallback?: string
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const ChatMessageItem: React.FC<ChatMessageProps> = ({
|
|
157
|
-
message,
|
|
158
|
-
showTimestamp,
|
|
159
|
-
userAvatarUrl,
|
|
160
|
-
userAvatarFallback,
|
|
161
|
-
assistantAvatarUrl,
|
|
162
|
-
assistantAvatarFallback,
|
|
163
|
-
}) => {
|
|
164
|
-
const isUser = message.role === "user"
|
|
165
|
-
const isSystem = message.role === "system"
|
|
166
|
-
|
|
167
|
-
if (isSystem) {
|
|
168
|
-
return (
|
|
169
|
-
<div className="flex justify-center">
|
|
170
|
-
<div className="text-xs text-muted-foreground bg-muted px-3 py-1 rounded-full">
|
|
171
|
-
{message.content}
|
|
172
|
-
</div>
|
|
173
|
-
</div>
|
|
174
|
-
)
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const avatar = isUser
|
|
178
|
-
? (message.avatar || userAvatarUrl)
|
|
179
|
-
: (message.avatar || assistantAvatarUrl)
|
|
180
|
-
|
|
181
|
-
const avatarFallback = isUser
|
|
182
|
-
? (message.avatarFallback || userAvatarFallback)
|
|
183
|
-
: (message.avatarFallback || assistantAvatarFallback)
|
|
184
|
-
|
|
185
|
-
return (
|
|
186
|
-
<div
|
|
187
|
-
className={cn(
|
|
188
|
-
"flex gap-3",
|
|
189
|
-
isUser ? "flex-row-reverse" : "flex-row"
|
|
190
|
-
)}
|
|
191
|
-
>
|
|
192
|
-
<Avatar className="h-8 w-8">
|
|
193
|
-
<AvatarImage src={avatar} />
|
|
194
|
-
<AvatarFallback className="text-xs">{avatarFallback}</AvatarFallback>
|
|
195
|
-
</Avatar>
|
|
196
|
-
|
|
197
|
-
<div className={cn("flex flex-col gap-1", isUser ? "items-end" : "items-start")}>
|
|
198
|
-
<div
|
|
199
|
-
className={cn(
|
|
200
|
-
"rounded-lg px-4 py-2 max-w-[70%] break-words",
|
|
201
|
-
isUser
|
|
202
|
-
? "bg-primary text-primary-foreground"
|
|
203
|
-
: "bg-muted"
|
|
204
|
-
)}
|
|
205
|
-
>
|
|
206
|
-
<p className="text-sm whitespace-pre-wrap">{message.content}</p>
|
|
207
|
-
</div>
|
|
208
|
-
{showTimestamp && message.timestamp && (
|
|
209
|
-
<span className="text-xs text-muted-foreground">
|
|
210
|
-
{message.timestamp}
|
|
211
|
-
</span>
|
|
212
|
-
)}
|
|
213
|
-
</div>
|
|
214
|
-
</div>
|
|
215
|
-
)
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// Typing indicator component
|
|
219
|
-
export interface TypingIndicatorProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
220
|
-
avatarSrc?: string
|
|
221
|
-
avatarFallback?: string
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const TypingIndicator = React.forwardRef<HTMLDivElement, TypingIndicatorProps>(
|
|
225
|
-
({ className, avatarSrc, avatarFallback = "AI", ...props }, ref) => {
|
|
226
|
-
return (
|
|
227
|
-
<div ref={ref} className={cn("flex gap-3", className)} {...props}>
|
|
228
|
-
<Avatar className="h-8 w-8">
|
|
229
|
-
<AvatarImage src={avatarSrc} />
|
|
230
|
-
<AvatarFallback className="text-xs">{avatarFallback}</AvatarFallback>
|
|
231
|
-
</Avatar>
|
|
232
|
-
<div className="flex items-center bg-muted rounded-lg px-4 py-2">
|
|
233
|
-
<div className="flex gap-1">
|
|
234
|
-
<span className="w-2 h-2 bg-muted-foreground rounded-full animate-bounce [animation-delay:-0.3s]"></span>
|
|
235
|
-
<span className="w-2 h-2 bg-muted-foreground rounded-full animate-bounce [animation-delay:-0.15s]"></span>
|
|
236
|
-
<span className="w-2 h-2 bg-muted-foreground rounded-full animate-bounce"></span>
|
|
237
|
-
</div>
|
|
238
|
-
</div>
|
|
239
|
-
</div>
|
|
240
|
-
)
|
|
241
|
-
}
|
|
242
|
-
)
|
|
243
|
-
TypingIndicator.displayName = "TypingIndicator"
|
|
244
|
-
|
|
245
|
-
export { Chatbot, TypingIndicator }
|
|
246
|
-
|
|
247
|
-
// Export renderer to register the component with ObjectUI
|
|
248
|
-
export * from './renderer';
|
package/src/renderer.tsx
DELETED
|
@@ -1,314 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ObjectUI
|
|
3
|
-
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
-
*
|
|
5
|
-
* This source code is licensed under the MIT license found in the
|
|
6
|
-
* LICENSE file in the root directory of this source tree.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { ComponentRegistry } from '@object-ui/core';
|
|
10
|
-
import type { ChatbotSchema, ChatMessage } from '@object-ui/types';
|
|
11
|
-
import { Chatbot } from './index';
|
|
12
|
-
import { ChatbotEnhanced } from './ChatbotEnhanced';
|
|
13
|
-
import { generateUniqueId } from './utils';
|
|
14
|
-
import { useState } from 'react';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Chatbot component for Object UI
|
|
18
|
-
*
|
|
19
|
-
* @remarks
|
|
20
|
-
* This component supports an optional `onSend` callback in the schema:
|
|
21
|
-
* - Signature: `onSend(content: string, messages: ChatMessage[]): void`
|
|
22
|
-
* - Parameters:
|
|
23
|
-
* - content: The message text that was sent
|
|
24
|
-
* - messages: Array of all messages including the newly added message
|
|
25
|
-
* - Called when: User sends a message via the input field
|
|
26
|
-
* - Use case: Connect to backend API or trigger custom actions on message send
|
|
27
|
-
*/
|
|
28
|
-
ComponentRegistry.register('chatbot',
|
|
29
|
-
({ schema, className, ...props }: { schema: ChatbotSchema; className?: string; [key: string]: any }) => {
|
|
30
|
-
// Initialize messages from schema or use empty array
|
|
31
|
-
const [messages, setMessages] = useState<ChatMessage[]>(
|
|
32
|
-
schema.messages?.map((msg: any, idx: number) => ({
|
|
33
|
-
id: msg.id || `msg-${idx}`,
|
|
34
|
-
role: msg.role || 'user',
|
|
35
|
-
content: msg.content || '',
|
|
36
|
-
timestamp: typeof msg.timestamp === 'string' ? msg.timestamp : (msg.timestamp instanceof Date ? msg.timestamp.toISOString() : undefined),
|
|
37
|
-
avatar: msg.avatar,
|
|
38
|
-
avatarFallback: msg.avatarFallback,
|
|
39
|
-
})) || []
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
// Handle sending new messages
|
|
43
|
-
const handleSendMessage = (content: string) => {
|
|
44
|
-
// Create user message with robust ID generation
|
|
45
|
-
const userMessage: ChatMessage = {
|
|
46
|
-
id: generateUniqueId('msg'),
|
|
47
|
-
role: 'user',
|
|
48
|
-
content,
|
|
49
|
-
timestamp: schema.showTimestamp ? new Date().toLocaleTimeString() : undefined,
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const updatedMessages = [...messages, userMessage];
|
|
53
|
-
setMessages(updatedMessages);
|
|
54
|
-
|
|
55
|
-
// If onSend callback is provided in schema, call it with updated messages
|
|
56
|
-
if (schema.onSend) {
|
|
57
|
-
schema.onSend(content, updatedMessages);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Auto-response feature for demo purposes
|
|
61
|
-
if (schema.autoResponse) {
|
|
62
|
-
setTimeout(() => {
|
|
63
|
-
const assistantMessage: ChatMessage = {
|
|
64
|
-
id: generateUniqueId('msg'),
|
|
65
|
-
role: 'assistant',
|
|
66
|
-
content: schema.autoResponseText || 'Thank you for your message!',
|
|
67
|
-
timestamp: schema.showTimestamp ? new Date().toLocaleTimeString() : undefined,
|
|
68
|
-
};
|
|
69
|
-
setMessages((prev) => [...prev, assistantMessage]);
|
|
70
|
-
}, schema.autoResponseDelay || 1000);
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
return (
|
|
75
|
-
<Chatbot
|
|
76
|
-
messages={messages as any}
|
|
77
|
-
placeholder={schema.placeholder}
|
|
78
|
-
onSendMessage={handleSendMessage}
|
|
79
|
-
disabled={schema.disabled}
|
|
80
|
-
showTimestamp={schema.showTimestamp}
|
|
81
|
-
userAvatarUrl={schema.userAvatarUrl}
|
|
82
|
-
userAvatarFallback={schema.userAvatarFallback}
|
|
83
|
-
assistantAvatarUrl={schema.assistantAvatarUrl}
|
|
84
|
-
assistantAvatarFallback={schema.assistantAvatarFallback}
|
|
85
|
-
maxHeight={schema.maxHeight}
|
|
86
|
-
className={className}
|
|
87
|
-
{...props}
|
|
88
|
-
/>
|
|
89
|
-
);
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
namespace: 'plugin-chatbot',
|
|
93
|
-
label: 'Chatbot',
|
|
94
|
-
inputs: [
|
|
95
|
-
{
|
|
96
|
-
name: 'messages',
|
|
97
|
-
type: 'array',
|
|
98
|
-
label: 'Initial Messages',
|
|
99
|
-
description: 'Array of message objects with id, role, content, and optional timestamp'
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
name: 'placeholder',
|
|
103
|
-
type: 'string',
|
|
104
|
-
label: 'Input Placeholder',
|
|
105
|
-
defaultValue: 'Type your message...'
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
name: 'showTimestamp',
|
|
109
|
-
type: 'boolean',
|
|
110
|
-
label: 'Show Timestamps',
|
|
111
|
-
defaultValue: false
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
name: 'disabled',
|
|
115
|
-
type: 'boolean',
|
|
116
|
-
label: 'Disabled',
|
|
117
|
-
defaultValue: false
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
name: 'userAvatarUrl',
|
|
121
|
-
type: 'string',
|
|
122
|
-
label: 'User Avatar URL',
|
|
123
|
-
description: 'URL of the user avatar image'
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
name: 'userAvatarFallback',
|
|
127
|
-
type: 'string',
|
|
128
|
-
label: 'User Avatar Fallback',
|
|
129
|
-
defaultValue: 'You',
|
|
130
|
-
description: 'Fallback text shown when user avatar image is not available'
|
|
131
|
-
},
|
|
132
|
-
{
|
|
133
|
-
name: 'assistantAvatarUrl',
|
|
134
|
-
type: 'string',
|
|
135
|
-
label: 'Assistant Avatar URL',
|
|
136
|
-
description: 'URL of the assistant avatar image'
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
name: 'assistantAvatarFallback',
|
|
140
|
-
type: 'string',
|
|
141
|
-
label: 'Assistant Avatar Fallback',
|
|
142
|
-
defaultValue: 'AI',
|
|
143
|
-
description: 'Fallback text shown when assistant avatar image is not available'
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
name: 'maxHeight',
|
|
147
|
-
type: 'string',
|
|
148
|
-
label: 'Max Height',
|
|
149
|
-
defaultValue: '500px'
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
name: 'autoResponse',
|
|
153
|
-
type: 'boolean',
|
|
154
|
-
label: 'Enable Auto Response (Demo)',
|
|
155
|
-
defaultValue: false,
|
|
156
|
-
description: 'Automatically send a response after user message (for demo purposes)'
|
|
157
|
-
},
|
|
158
|
-
{
|
|
159
|
-
name: 'autoResponseText',
|
|
160
|
-
type: 'string',
|
|
161
|
-
label: 'Auto Response Text',
|
|
162
|
-
defaultValue: 'Thank you for your message!'
|
|
163
|
-
},
|
|
164
|
-
{
|
|
165
|
-
name: 'autoResponseDelay',
|
|
166
|
-
type: 'number',
|
|
167
|
-
label: 'Auto Response Delay (ms)',
|
|
168
|
-
defaultValue: 1000
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
name: 'className',
|
|
172
|
-
type: 'string',
|
|
173
|
-
label: 'CSS Class'
|
|
174
|
-
}
|
|
175
|
-
],
|
|
176
|
-
defaultProps: {
|
|
177
|
-
messages: [
|
|
178
|
-
{
|
|
179
|
-
id: 'welcome',
|
|
180
|
-
role: 'assistant',
|
|
181
|
-
content: 'Hello! How can I help you today?',
|
|
182
|
-
}
|
|
183
|
-
],
|
|
184
|
-
placeholder: 'Type your message...',
|
|
185
|
-
showTimestamp: false,
|
|
186
|
-
disabled: false,
|
|
187
|
-
userAvatarFallback: 'You',
|
|
188
|
-
assistantAvatarFallback: 'AI',
|
|
189
|
-
maxHeight: '500px',
|
|
190
|
-
autoResponse: true,
|
|
191
|
-
autoResponseText: 'Thank you for your message! This is an automated response.',
|
|
192
|
-
autoResponseDelay: 1000,
|
|
193
|
-
className: 'w-full max-w-2xl'
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
);
|
|
197
|
-
|
|
198
|
-
// Register Enhanced Chatbot
|
|
199
|
-
ComponentRegistry.register('chatbot-enhanced',
|
|
200
|
-
({ schema, className, ...props }: { schema: ChatbotSchema & {
|
|
201
|
-
enableMarkdown?: boolean;
|
|
202
|
-
enableFileUpload?: boolean;
|
|
203
|
-
onClear?: () => void;
|
|
204
|
-
}; className?: string; [key: string]: any }) => {
|
|
205
|
-
const [messages, setMessages] = useState<ChatMessage[]>(
|
|
206
|
-
schema.messages?.map((msg: any, idx: number) => ({
|
|
207
|
-
id: msg.id || `msg-${idx}`,
|
|
208
|
-
role: msg.role || 'user',
|
|
209
|
-
content: msg.content || '',
|
|
210
|
-
timestamp: typeof msg.timestamp === 'string' ? msg.timestamp : (msg.timestamp instanceof Date ? msg.timestamp.toISOString() : undefined),
|
|
211
|
-
avatar: msg.avatar,
|
|
212
|
-
avatarFallback: msg.avatarFallback,
|
|
213
|
-
})) || []
|
|
214
|
-
);
|
|
215
|
-
|
|
216
|
-
const handleSendMessage = (content: string, _files?: File[]) => {
|
|
217
|
-
const userMessage: ChatMessage = {
|
|
218
|
-
id: generateUniqueId('msg'),
|
|
219
|
-
role: 'user',
|
|
220
|
-
content,
|
|
221
|
-
timestamp: schema.showTimestamp ? new Date().toLocaleTimeString() : undefined,
|
|
222
|
-
};
|
|
223
|
-
|
|
224
|
-
const updatedMessages = [...messages, userMessage];
|
|
225
|
-
setMessages(updatedMessages);
|
|
226
|
-
|
|
227
|
-
if (schema.onSend) {
|
|
228
|
-
schema.onSend(content, updatedMessages);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// Auto-response with streaming simulation
|
|
232
|
-
if (schema.autoResponse) {
|
|
233
|
-
setTimeout(() => {
|
|
234
|
-
const assistantMessage: ChatMessage = {
|
|
235
|
-
id: generateUniqueId('msg'),
|
|
236
|
-
role: 'assistant',
|
|
237
|
-
content: schema.autoResponseText || 'Thank you for your message!',
|
|
238
|
-
timestamp: schema.showTimestamp ? new Date().toLocaleTimeString() : undefined,
|
|
239
|
-
};
|
|
240
|
-
setMessages((prev) => [...prev, assistantMessage]);
|
|
241
|
-
}, schema.autoResponseDelay || 1000);
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
|
|
245
|
-
const handleClear = () => {
|
|
246
|
-
setMessages([]);
|
|
247
|
-
if (schema.onClear) {
|
|
248
|
-
schema.onClear();
|
|
249
|
-
}
|
|
250
|
-
};
|
|
251
|
-
|
|
252
|
-
return (
|
|
253
|
-
<ChatbotEnhanced
|
|
254
|
-
messages={messages as any}
|
|
255
|
-
placeholder={schema.placeholder}
|
|
256
|
-
onSendMessage={handleSendMessage}
|
|
257
|
-
onClear={handleClear}
|
|
258
|
-
disabled={schema.disabled}
|
|
259
|
-
showTimestamp={schema.showTimestamp}
|
|
260
|
-
userAvatarUrl={schema.userAvatarUrl}
|
|
261
|
-
userAvatarFallback={schema.userAvatarFallback}
|
|
262
|
-
assistantAvatarUrl={schema.assistantAvatarUrl}
|
|
263
|
-
assistantAvatarFallback={schema.assistantAvatarFallback}
|
|
264
|
-
maxHeight={schema.maxHeight}
|
|
265
|
-
enableMarkdown={schema.enableMarkdown ?? true}
|
|
266
|
-
enableFileUpload={schema.enableFileUpload ?? false}
|
|
267
|
-
className={className}
|
|
268
|
-
{...props}
|
|
269
|
-
/>
|
|
270
|
-
);
|
|
271
|
-
},
|
|
272
|
-
{
|
|
273
|
-
namespace: 'plugin-chatbot',
|
|
274
|
-
label: 'Chatbot (Enhanced)',
|
|
275
|
-
inputs: [
|
|
276
|
-
{ name: 'messages', type: 'array', label: 'Initial Messages' },
|
|
277
|
-
{ name: 'placeholder', type: 'string', label: 'Input Placeholder', defaultValue: 'Type your message...' },
|
|
278
|
-
{ name: 'showTimestamp', type: 'boolean', label: 'Show Timestamps', defaultValue: false },
|
|
279
|
-
{ name: 'disabled', type: 'boolean', label: 'Disabled', defaultValue: false },
|
|
280
|
-
{ name: 'enableMarkdown', type: 'boolean', label: 'Enable Markdown', defaultValue: true },
|
|
281
|
-
{ name: 'enableFileUpload', type: 'boolean', label: 'Enable File Upload', defaultValue: false },
|
|
282
|
-
{ name: 'userAvatarUrl', type: 'string', label: 'User Avatar URL' },
|
|
283
|
-
{ name: 'userAvatarFallback', type: 'string', label: 'User Avatar Fallback', defaultValue: 'You' },
|
|
284
|
-
{ name: 'assistantAvatarUrl', type: 'string', label: 'Assistant Avatar URL' },
|
|
285
|
-
{ name: 'assistantAvatarFallback', type: 'string', label: 'Assistant Avatar Fallback', defaultValue: 'AI' },
|
|
286
|
-
{ name: 'maxHeight', type: 'string', label: 'Max Height', defaultValue: '500px' },
|
|
287
|
-
{ name: 'autoResponse', type: 'boolean', label: 'Enable Auto Response (Demo)', defaultValue: false },
|
|
288
|
-
{ name: 'autoResponseText', type: 'string', label: 'Auto Response Text', defaultValue: 'Thank you for your message!' },
|
|
289
|
-
{ name: 'autoResponseDelay', type: 'number', label: 'Auto Response Delay (ms)', defaultValue: 1000 },
|
|
290
|
-
{ name: 'className', type: 'string', label: 'CSS Class' }
|
|
291
|
-
],
|
|
292
|
-
defaultProps: {
|
|
293
|
-
messages: [
|
|
294
|
-
{
|
|
295
|
-
id: 'welcome',
|
|
296
|
-
role: 'assistant',
|
|
297
|
-
content: 'Hello! How can I help you today?',
|
|
298
|
-
}
|
|
299
|
-
],
|
|
300
|
-
placeholder: 'Type your message...',
|
|
301
|
-
showTimestamp: false,
|
|
302
|
-
disabled: false,
|
|
303
|
-
enableMarkdown: true,
|
|
304
|
-
enableFileUpload: false,
|
|
305
|
-
userAvatarFallback: 'You',
|
|
306
|
-
assistantAvatarFallback: 'AI',
|
|
307
|
-
maxHeight: '500px',
|
|
308
|
-
autoResponse: true,
|
|
309
|
-
autoResponseText: 'Thank you for your message! This is an automated response.',
|
|
310
|
-
autoResponseDelay: 1000,
|
|
311
|
-
className: 'w-full max-w-2xl'
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
);
|
package/src/utils.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ObjectUI
|
|
3
|
-
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
-
*
|
|
5
|
-
* This source code is licensed under the MIT license found in the
|
|
6
|
-
* LICENSE file in the root directory of this source tree.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Generates a unique ID for messages or other entities
|
|
11
|
-
* Uses crypto.randomUUID() if available, otherwise falls back to timestamp + random string
|
|
12
|
-
*/
|
|
13
|
-
export function generateUniqueId(prefix = 'msg'): string {
|
|
14
|
-
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
|
|
15
|
-
return crypto.randomUUID();
|
|
16
|
-
}
|
|
17
|
-
return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
18
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "../../tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"outDir": "dist",
|
|
5
|
-
"jsx": "react-jsx",
|
|
6
|
-
"baseUrl": ".",
|
|
7
|
-
"paths": {
|
|
8
|
-
"@/*": ["src/*"]
|
|
9
|
-
},
|
|
10
|
-
"noEmit": false,
|
|
11
|
-
"declaration": true,
|
|
12
|
-
"composite": true,
|
|
13
|
-
"declarationMap": true,
|
|
14
|
-
"skipLibCheck": true
|
|
15
|
-
},
|
|
16
|
-
"include": ["src"],
|
|
17
|
-
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
|
|
18
|
-
}
|
package/vite.config.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ObjectUI
|
|
3
|
-
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
-
*
|
|
5
|
-
* This source code is licensed under the MIT license found in the
|
|
6
|
-
* LICENSE file in the root directory of this source tree.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { defineConfig } from 'vite';
|
|
10
|
-
import react from '@vitejs/plugin-react';
|
|
11
|
-
import dts from 'vite-plugin-dts';
|
|
12
|
-
import { resolve } from 'path';
|
|
13
|
-
|
|
14
|
-
export default defineConfig({
|
|
15
|
-
plugins: [
|
|
16
|
-
react(),
|
|
17
|
-
dts({
|
|
18
|
-
insertTypesEntry: true,
|
|
19
|
-
include: ['src'],
|
|
20
|
-
exclude: ['**/*.test.ts', '**/*.test.tsx', 'node_modules'],
|
|
21
|
-
skipDiagnostics: true,
|
|
22
|
-
}),
|
|
23
|
-
],
|
|
24
|
-
resolve: {
|
|
25
|
-
alias: {
|
|
26
|
-
'@': resolve(__dirname, './src'),
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
build: {
|
|
30
|
-
lib: {
|
|
31
|
-
entry: resolve(__dirname, 'src/index.tsx'),
|
|
32
|
-
name: 'ObjectUIPluginChatbot',
|
|
33
|
-
fileName: 'index',
|
|
34
|
-
},
|
|
35
|
-
rollupOptions: {
|
|
36
|
-
external: ['react', 'react-dom', '@object-ui/components', '@object-ui/core', '@object-ui/react', 'lucide-react'],
|
|
37
|
-
output: {
|
|
38
|
-
globals: {
|
|
39
|
-
react: 'React',
|
|
40
|
-
'react-dom': 'ReactDOM',
|
|
41
|
-
'@object-ui/components': 'ObjectUIComponents',
|
|
42
|
-
'@object-ui/core': 'ObjectUICore',
|
|
43
|
-
'@object-ui/react': 'ObjectUIReact',
|
|
44
|
-
'lucide-react': 'LucideReact',
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
test: {
|
|
50
|
-
globals: true,
|
|
51
|
-
environment: 'happy-dom',
|
|
52
|
-
passWithNoTests: true,
|
|
53
|
-
},
|
|
54
|
-
});
|
|
File without changes
|
|
File without changes
|