@townco/ui 0.1.6 → 0.1.8
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/README.md +11 -11
- package/dist/core/hooks/index.d.ts +1 -0
- package/dist/core/hooks/index.js +1 -0
- package/dist/core/hooks/use-chat-input.d.ts +17 -17
- package/dist/core/hooks/use-chat-input.js +55 -64
- package/dist/core/hooks/use-chat-messages.d.ts +11 -11
- package/dist/core/hooks/use-chat-messages.js +114 -121
- package/dist/core/hooks/use-chat-session.d.ts +5 -5
- package/dist/core/hooks/use-chat-session.js +80 -78
- package/dist/core/hooks/use-media-query.d.ts +5 -5
- package/dist/core/hooks/use-media-query.js +42 -38
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/schemas/chat.d.ts +56 -83
- package/dist/core/schemas/chat.js +25 -27
- package/dist/core/store/chat-store.d.ts +22 -28
- package/dist/core/store/chat-store.js +50 -59
- package/dist/gui/components/Button.d.ts +7 -23
- package/dist/gui/components/Button.js +27 -40
- package/dist/gui/components/Card.d.ts +7 -26
- package/dist/gui/components/Card.js +8 -54
- package/dist/gui/components/ChatHeader.d.ts +31 -58
- package/dist/gui/components/ChatHeader.js +68 -171
- package/dist/gui/components/ChatInput.d.ts +54 -58
- package/dist/gui/components/ChatInput.js +207 -194
- package/dist/gui/components/ChatInputCommandMenu.d.ts +20 -0
- package/dist/gui/components/ChatInputCommandMenu.js +62 -0
- package/dist/gui/components/ChatLayout.d.ts +41 -71
- package/dist/gui/components/ChatLayout.js +87 -214
- package/dist/gui/components/ChatPanelTabContent.d.ts +9 -18
- package/dist/gui/components/ChatPanelTabContent.js +10 -88
- package/dist/gui/components/ChatSecondaryPanel.d.ts +11 -14
- package/dist/gui/components/ChatSecondaryPanel.js +38 -115
- package/dist/gui/components/ChatSidebar.d.ts +13 -26
- package/dist/gui/components/ChatSidebar.js +14 -48
- package/dist/gui/components/ChatStatus.d.ts +2 -4
- package/dist/gui/components/ChatStatus.js +34 -45
- package/dist/gui/components/Conversation.d.ts +14 -17
- package/dist/gui/components/Conversation.js +83 -143
- package/dist/gui/components/Dialog.d.ts +11 -57
- package/dist/gui/components/Dialog.js +8 -84
- package/dist/gui/components/DropdownMenu.d.ts +20 -101
- package/dist/gui/components/DropdownMenu.js +14 -161
- package/dist/gui/components/HeightTransition.d.ts +7 -12
- package/dist/gui/components/HeightTransition.js +77 -88
- package/dist/gui/components/Input.d.ts +6 -13
- package/dist/gui/components/Input.js +16 -27
- package/dist/gui/components/Label.d.ts +1 -7
- package/dist/gui/components/Label.js +2 -12
- package/dist/gui/components/MarkdownRenderer.d.ts +4 -6
- package/dist/gui/components/MarkdownRenderer.js +81 -178
- package/dist/gui/components/Message.d.ts +22 -25
- package/dist/gui/components/Message.js +97 -44
- package/dist/gui/components/MessageContent.d.ts +22 -29
- package/dist/gui/components/MessageContent.js +85 -157
- package/dist/gui/components/Reasoning.d.ts +24 -30
- package/dist/gui/components/Reasoning.js +60 -187
- package/dist/gui/components/Response.d.ts +9 -11
- package/dist/gui/components/Response.js +90 -229
- package/dist/gui/components/Select.d.ts +10 -69
- package/dist/gui/components/Select.js +12 -118
- package/dist/gui/components/Sonner.d.ts +1 -3
- package/dist/gui/components/Sonner.js +18 -29
- package/dist/gui/components/Tabs.d.ts +4 -24
- package/dist/gui/components/Tabs.js +4 -32
- package/dist/gui/components/Task.d.ts +24 -28
- package/dist/gui/components/Task.js +31 -164
- package/dist/gui/components/Textarea.d.ts +7 -15
- package/dist/gui/components/Textarea.js +46 -63
- package/dist/gui/components/ThinkingBlock.d.ts +10 -20
- package/dist/gui/components/ThinkingBlock.js +35 -134
- package/dist/gui/components/TodoList.d.ts +10 -12
- package/dist/gui/components/TodoList.js +7 -22
- package/dist/gui/components/TodoListItem.d.ts +6 -9
- package/dist/gui/components/TodoListItem.js +4 -18
- package/dist/gui/components/index.d.ts +16 -59
- package/dist/gui/components/index.js +18 -42
- package/dist/gui/lib/utils.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.test.js +1 -0
- package/dist/sdk/client/acp-client.d.ts +76 -88
- package/dist/sdk/client/acp-client.js +217 -215
- package/dist/sdk/index.d.ts +1 -1
- package/dist/sdk/index.js +1 -1
- package/dist/sdk/schemas/agent.d.ts +64 -111
- package/dist/sdk/schemas/agent.js +24 -24
- package/dist/sdk/schemas/message.d.ts +147 -245
- package/dist/sdk/schemas/message.js +40 -40
- package/dist/sdk/schemas/session.d.ts +135 -219
- package/dist/sdk/schemas/session.js +27 -27
- package/dist/sdk/transports/http.d.ts +55 -55
- package/dist/sdk/transports/http.js +469 -472
- package/dist/sdk/transports/stdio.d.ts +20 -20
- package/dist/sdk/transports/stdio.js +286 -289
- package/dist/sdk/transports/types.d.ts +42 -42
- package/dist/sdk/transports/websocket.d.ts +12 -12
- package/dist/sdk/transports/websocket.js +46 -52
- package/dist/tui/components/ChatView.d.ts +2 -4
- package/dist/tui/components/ChatView.js +18 -51
- package/dist/tui/components/GameOfLife.js +35 -64
- package/dist/tui/components/InputBox.d.ts +11 -18
- package/dist/tui/components/InputBox.js +10 -70
- package/dist/tui/components/MessageList.d.ts +2 -4
- package/dist/tui/components/MessageList.js +10 -37
- package/dist/tui/components/MultiSelect.d.ts +10 -15
- package/dist/tui/components/MultiSelect.js +73 -116
- package/dist/tui/components/ReadlineInput.d.ts +6 -12
- package/dist/tui/components/ReadlineInput.js +237 -252
- package/dist/tui/components/SingleSelect.d.ts +9 -15
- package/dist/tui/components/SingleSelect.js +43 -84
- package/dist/tui/components/StatusBar.d.ts +6 -11
- package/dist/tui/components/StatusBar.js +67 -102
- package/dist/tui/index.d.ts +1 -1
- package/dist/tui/index.js +1 -1
- package/package.json +6 -4
- package/src/styles/global.css +2 -0
- package/dist/core/hooks/index.d.ts.map +0 -1
- package/dist/core/hooks/index.js.map +0 -1
- package/dist/core/hooks/use-chat-input.d.ts.map +0 -1
- package/dist/core/hooks/use-chat-input.js.map +0 -1
- package/dist/core/hooks/use-chat-messages.d.ts.map +0 -1
- package/dist/core/hooks/use-chat-messages.js.map +0 -1
- package/dist/core/hooks/use-chat-session.d.ts.map +0 -1
- package/dist/core/hooks/use-chat-session.js.map +0 -1
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js.map +0 -1
- package/dist/core/schemas/chat.d.ts.map +0 -1
- package/dist/core/schemas/chat.js.map +0 -1
- package/dist/core/schemas/index.d.ts.map +0 -1
- package/dist/core/schemas/index.js.map +0 -1
- package/dist/core/store/chat-store.d.ts.map +0 -1
- package/dist/core/store/chat-store.js.map +0 -1
- package/dist/gui/components/Button.d.ts.map +0 -1
- package/dist/gui/components/Button.js.map +0 -1
- package/dist/gui/components/Card.d.ts.map +0 -1
- package/dist/gui/components/Card.js.map +0 -1
- package/dist/gui/components/ChatInput.d.ts.map +0 -1
- package/dist/gui/components/ChatInput.js.map +0 -1
- package/dist/gui/components/ChatInterface.d.ts +0 -12
- package/dist/gui/components/ChatInterface.d.ts.map +0 -1
- package/dist/gui/components/ChatInterface.js +0 -204
- package/dist/gui/components/ChatInterface.js.map +0 -1
- package/dist/gui/components/ChatPreview.d.ts +0 -12
- package/dist/gui/components/ChatPreview.d.ts.map +0 -1
- package/dist/gui/components/ChatPreview.js +0 -214
- package/dist/gui/components/ChatPreview.js.map +0 -1
- package/dist/gui/components/ChatSecondaryPanel.d.ts.map +0 -1
- package/dist/gui/components/ChatSecondaryPanel.js.map +0 -1
- package/dist/gui/components/ChatStatus.d.ts.map +0 -1
- package/dist/gui/components/ChatStatus.js.map +0 -1
- package/dist/gui/components/ChatView.d.ts +0 -8
- package/dist/gui/components/ChatView.d.ts.map +0 -1
- package/dist/gui/components/ChatView.js +0 -42
- package/dist/gui/components/ChatView.js.map +0 -1
- package/dist/gui/components/ConfigPanel.d.ts +0 -20
- package/dist/gui/components/ConfigPanel.d.ts.map +0 -1
- package/dist/gui/components/ConfigPanel.js +0 -225
- package/dist/gui/components/ConfigPanel.js.map +0 -1
- package/dist/gui/components/Conversation.d.ts.map +0 -1
- package/dist/gui/components/Conversation.js.map +0 -1
- package/dist/gui/components/Dialog.d.ts.map +0 -1
- package/dist/gui/components/Dialog.js.map +0 -1
- package/dist/gui/components/HeightTransition.d.ts.map +0 -1
- package/dist/gui/components/HeightTransition.js.map +0 -1
- package/dist/gui/components/Input.d.ts.map +0 -1
- package/dist/gui/components/Input.js.map +0 -1
- package/dist/gui/components/InputBox.d.ts +0 -21
- package/dist/gui/components/InputBox.d.ts.map +0 -1
- package/dist/gui/components/InputBox.js +0 -90
- package/dist/gui/components/InputBox.js.map +0 -1
- package/dist/gui/components/Label.d.ts.map +0 -1
- package/dist/gui/components/Label.js.map +0 -1
- package/dist/gui/components/MarkdownRenderer.d.ts.map +0 -1
- package/dist/gui/components/MarkdownRenderer.js.map +0 -1
- package/dist/gui/components/Message.d.ts.map +0 -1
- package/dist/gui/components/Message.js.map +0 -1
- package/dist/gui/components/MessageContent.d.ts.map +0 -1
- package/dist/gui/components/MessageContent.js.map +0 -1
- package/dist/gui/components/MessageList.d.ts.map +0 -1
- package/dist/gui/components/MessageList.js.map +0 -1
- package/dist/gui/components/PlaygroundLayout.d.ts +0 -14
- package/dist/gui/components/PlaygroundLayout.d.ts.map +0 -1
- package/dist/gui/components/PlaygroundLayout.js +0 -49
- package/dist/gui/components/PlaygroundLayout.js.map +0 -1
- package/dist/gui/components/Reasoning.d.ts.map +0 -1
- package/dist/gui/components/Reasoning.js.map +0 -1
- package/dist/gui/components/Response.d.ts.map +0 -1
- package/dist/gui/components/Response.js.map +0 -1
- package/dist/gui/components/Select.d.ts.map +0 -1
- package/dist/gui/components/Select.js.map +0 -1
- package/dist/gui/components/StatusBar.d.ts +0 -12
- package/dist/gui/components/StatusBar.d.ts.map +0 -1
- package/dist/gui/components/StatusBar.js +0 -58
- package/dist/gui/components/StatusBar.js.map +0 -1
- package/dist/gui/components/Tabs.d.ts.map +0 -1
- package/dist/gui/components/Tabs.js.map +0 -1
- package/dist/gui/components/Task.d.ts.map +0 -1
- package/dist/gui/components/Task.js.map +0 -1
- package/dist/gui/components/Textarea.d.ts.map +0 -1
- package/dist/gui/components/Textarea.js.map +0 -1
- package/dist/gui/components/ThinkingBlock.d.ts.map +0 -1
- package/dist/gui/components/ThinkingBlock.js.map +0 -1
- package/dist/gui/components/TodoList.d.ts.map +0 -1
- package/dist/gui/components/TodoList.js.map +0 -1
- package/dist/gui/components/TodoListItem.d.ts.map +0 -1
- package/dist/gui/components/TodoListItem.js.map +0 -1
- package/dist/gui/components/index.d.ts.map +0 -1
- package/dist/gui/components/index.js.map +0 -1
- package/dist/gui/index.d.ts.map +0 -1
- package/dist/gui/index.js.map +0 -1
- package/dist/gui/lib/utils.d.ts.map +0 -1
- package/dist/gui/lib/utils.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/sdk/client/acp-client.d.ts.map +0 -1
- package/dist/sdk/client/acp-client.js.map +0 -1
- package/dist/sdk/client/index.d.ts.map +0 -1
- package/dist/sdk/client/index.js.map +0 -1
- package/dist/sdk/index.d.ts.map +0 -1
- package/dist/sdk/index.js.map +0 -1
- package/dist/sdk/schemas/agent.d.ts.map +0 -1
- package/dist/sdk/schemas/agent.js.map +0 -1
- package/dist/sdk/schemas/index.d.ts.map +0 -1
- package/dist/sdk/schemas/index.js.map +0 -1
- package/dist/sdk/schemas/message.d.ts.map +0 -1
- package/dist/sdk/schemas/message.js.map +0 -1
- package/dist/sdk/schemas/session.d.ts.map +0 -1
- package/dist/sdk/schemas/session.js.map +0 -1
- package/dist/sdk/transports/http.d.ts.map +0 -1
- package/dist/sdk/transports/http.js.map +0 -1
- package/dist/sdk/transports/index.d.ts.map +0 -1
- package/dist/sdk/transports/index.js.map +0 -1
- package/dist/sdk/transports/stdio.d.ts.map +0 -1
- package/dist/sdk/transports/stdio.js.map +0 -1
- package/dist/sdk/transports/types.d.ts.map +0 -1
- package/dist/sdk/transports/types.js.map +0 -1
- package/dist/sdk/transports/websocket.d.ts.map +0 -1
- package/dist/sdk/transports/websocket.js.map +0 -1
- package/dist/tui/components/ChatView.d.ts.map +0 -1
- package/dist/tui/components/ChatView.js.map +0 -1
- package/dist/tui/components/GameOfLife.d.ts.map +0 -1
- package/dist/tui/components/GameOfLife.js.map +0 -1
- package/dist/tui/components/InputBox.d.ts.map +0 -1
- package/dist/tui/components/InputBox.js.map +0 -1
- package/dist/tui/components/MessageList.d.ts.map +0 -1
- package/dist/tui/components/MessageList.js.map +0 -1
- package/dist/tui/components/ReadlineInput.d.ts.map +0 -1
- package/dist/tui/components/ReadlineInput.js.map +0 -1
- package/dist/tui/components/StatusBar.d.ts.map +0 -1
- package/dist/tui/components/StatusBar.js.map +0 -1
- package/dist/tui/components/index.d.ts.map +0 -1
- package/dist/tui/components/index.js.map +0 -1
- package/dist/tui/index.d.ts.map +0 -1
- package/dist/tui/index.js.map +0 -1
|
@@ -1,207 +1,220 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
2
|
import { Slot } from "@radix-ui/react-slot";
|
|
3
|
+
import { Mic, Paperclip, SquareSlash } from "lucide-react";
|
|
2
4
|
import * as React from "react";
|
|
3
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
5
|
import { useChatInput as useCoreChatInput } from "../../core/hooks/use-chat-input.js";
|
|
5
6
|
import { useChatStore } from "../../core/store/chat-store.js";
|
|
6
7
|
import { cn } from "../lib/utils.js";
|
|
7
8
|
import { Button } from "./Button.js";
|
|
8
|
-
|
|
9
|
+
import { ChatInputCommandMenu as ChatInputCommandMenuComponent, } from "./ChatInputCommandMenu.js";
|
|
9
10
|
const ChatInputContext = React.createContext(undefined);
|
|
10
11
|
const useChatInputContext = () => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
const context = React.useContext(ChatInputContext);
|
|
13
|
+
if (!context) {
|
|
14
|
+
throw new Error("ChatInput components must be used within ChatInput.Root");
|
|
15
|
+
}
|
|
16
|
+
return context;
|
|
16
17
|
};
|
|
17
|
-
const ChatInputRoot = React.forwardRef(
|
|
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
|
-
"w-full divide-y overflow-hidden rounded-xl border bg-background shadow-sm",
|
|
84
|
-
className,
|
|
85
|
-
),
|
|
86
|
-
...props,
|
|
87
|
-
children: children,
|
|
88
|
-
}),
|
|
89
|
-
});
|
|
90
|
-
},
|
|
91
|
-
);
|
|
18
|
+
const ChatInputRoot = React.forwardRef(({ client, value: valueProp, onChange: onChangeProp, onSubmit: onSubmitProp, disabled = false, isSubmitting: isSubmittingProp, submitOnEnter = true, className, children, ...props }, ref) => {
|
|
19
|
+
const textareaRef = React.useRef(null);
|
|
20
|
+
// Always call hooks unconditionally (React rules)
|
|
21
|
+
const hookData = useCoreChatInput(client ?? null);
|
|
22
|
+
const storeIsStreaming = useChatStore((state) => state.isStreaming);
|
|
23
|
+
// Choose data source based on whether client is provided
|
|
24
|
+
const value = hookData ? hookData.value : valueProp || "";
|
|
25
|
+
const onChange = hookData ? hookData.onChange : onChangeProp || (() => { });
|
|
26
|
+
const onSubmit = hookData
|
|
27
|
+
? hookData.onSubmit
|
|
28
|
+
: onSubmitProp || (async () => { });
|
|
29
|
+
const isSubmitting = hookData
|
|
30
|
+
? hookData.isSubmitting || storeIsStreaming
|
|
31
|
+
: isSubmittingProp || false;
|
|
32
|
+
// Command menu state
|
|
33
|
+
const [showCommandMenu, setShowCommandMenu] = React.useState(false);
|
|
34
|
+
const [commandMenuQuery, setCommandMenuQuery] = React.useState("");
|
|
35
|
+
const [selectedMenuIndex, setSelectedMenuIndex] = React.useState(0);
|
|
36
|
+
const [menuItemCount, setMenuItemCount] = React.useState(0);
|
|
37
|
+
const [triggerCounter, setTriggerCounter] = React.useState(0);
|
|
38
|
+
const triggerMenuSelect = React.useCallback(() => {
|
|
39
|
+
setTriggerCounter((prev) => prev + 1);
|
|
40
|
+
}, []);
|
|
41
|
+
const handleSubmit = async (e) => {
|
|
42
|
+
e.preventDefault();
|
|
43
|
+
if (value.trim() && !isSubmitting && !disabled) {
|
|
44
|
+
await onSubmit();
|
|
45
|
+
// Restore focus to textarea after submit
|
|
46
|
+
setTimeout(() => {
|
|
47
|
+
textareaRef.current?.focus();
|
|
48
|
+
}, 0);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
// Expose textarea ref to children via context
|
|
52
|
+
React.useEffect(() => {
|
|
53
|
+
const textarea = document.querySelector('textarea[name="chat-input"]');
|
|
54
|
+
if (textarea && textareaRef.current !== textarea) {
|
|
55
|
+
textareaRef.current = textarea;
|
|
56
|
+
}
|
|
57
|
+
}, []);
|
|
58
|
+
// Reset textarea height when value becomes empty (after submit)
|
|
59
|
+
React.useEffect(() => {
|
|
60
|
+
if (!value && textareaRef.current) {
|
|
61
|
+
textareaRef.current.style.height = "auto";
|
|
62
|
+
textareaRef.current.style.overflowY = "hidden";
|
|
63
|
+
}
|
|
64
|
+
}, [value]);
|
|
65
|
+
return (_jsx(ChatInputContext.Provider, { value: {
|
|
66
|
+
value,
|
|
67
|
+
onChange,
|
|
68
|
+
onSubmit,
|
|
69
|
+
disabled,
|
|
70
|
+
isSubmitting,
|
|
71
|
+
submitOnEnter,
|
|
72
|
+
showCommandMenu,
|
|
73
|
+
setShowCommandMenu,
|
|
74
|
+
commandMenuQuery,
|
|
75
|
+
setCommandMenuQuery,
|
|
76
|
+
selectedMenuIndex,
|
|
77
|
+
setSelectedMenuIndex,
|
|
78
|
+
menuItemCount,
|
|
79
|
+
setMenuItemCount,
|
|
80
|
+
triggerMenuSelect,
|
|
81
|
+
triggerCounter,
|
|
82
|
+
}, children: _jsx("form", { ref: ref, onSubmit: handleSubmit, className: cn("relative w-full divide-y rounded-xl border bg-background shadow-md", className), ...props, children: children }) }));
|
|
83
|
+
});
|
|
92
84
|
ChatInputRoot.displayName = "ChatInput.Root";
|
|
93
|
-
const ChatInputField = React.forwardRef(
|
|
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
|
-
|
|
85
|
+
const ChatInputField = React.forwardRef(({ asChild = false, className, onKeyDown, children, ...props }, ref) => {
|
|
86
|
+
const { value, onChange, onSubmit, disabled, isSubmitting, submitOnEnter, showCommandMenu, setShowCommandMenu, setCommandMenuQuery, setSelectedMenuIndex, menuItemCount, triggerMenuSelect, } = useChatInputContext();
|
|
87
|
+
const textareaRef = React.useRef(null);
|
|
88
|
+
const handleRef = React.useCallback((node) => {
|
|
89
|
+
textareaRef.current = node;
|
|
90
|
+
if (typeof ref === "function") {
|
|
91
|
+
ref(node);
|
|
92
|
+
}
|
|
93
|
+
else if (ref) {
|
|
94
|
+
ref.current = node;
|
|
95
|
+
}
|
|
96
|
+
}, [ref]);
|
|
97
|
+
const handleKeyDown = (e) => {
|
|
98
|
+
// Handle arrow keys and Enter when command menu is open
|
|
99
|
+
if (showCommandMenu && menuItemCount > 0) {
|
|
100
|
+
if (e.key === "ArrowDown") {
|
|
101
|
+
e.preventDefault();
|
|
102
|
+
setSelectedMenuIndex((prev) => (prev + 1) % menuItemCount);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
else if (e.key === "ArrowUp") {
|
|
106
|
+
e.preventDefault();
|
|
107
|
+
setSelectedMenuIndex((prev) => (prev - 1 + menuItemCount) % menuItemCount);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
else if (e.key === "Enter" && !e.shiftKey) {
|
|
111
|
+
e.preventDefault();
|
|
112
|
+
triggerMenuSelect();
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
else if (e.key === "Escape") {
|
|
116
|
+
e.preventDefault();
|
|
117
|
+
setShowCommandMenu(false);
|
|
118
|
+
setCommandMenuQuery("");
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Handle Enter without Shift - only submit if not already submitting
|
|
123
|
+
if (submitOnEnter && e.key === "Enter" && !e.shiftKey) {
|
|
124
|
+
// Only prevent default and submit if conditions are met
|
|
125
|
+
if (value.trim() && !isSubmitting && !disabled) {
|
|
126
|
+
e.preventDefault();
|
|
127
|
+
onSubmit();
|
|
128
|
+
}
|
|
129
|
+
else if (isSubmitting || disabled) {
|
|
130
|
+
// Block Enter when submitting or disabled - don't add newline
|
|
131
|
+
e.preventDefault();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
onKeyDown?.(e);
|
|
135
|
+
};
|
|
136
|
+
const handleChange = (e) => {
|
|
137
|
+
const newValue = e.target.value;
|
|
138
|
+
onChange(newValue);
|
|
139
|
+
// Check if user typed "/" at the start to trigger command menu
|
|
140
|
+
if (newValue.startsWith("/") && !newValue.includes("\n")) {
|
|
141
|
+
setShowCommandMenu(true);
|
|
142
|
+
// Extract search query (everything after "/")
|
|
143
|
+
const query = newValue.slice(1);
|
|
144
|
+
setCommandMenuQuery(query);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
setShowCommandMenu(false);
|
|
148
|
+
setCommandMenuQuery("");
|
|
149
|
+
}
|
|
150
|
+
// Auto-resize
|
|
151
|
+
const textarea = textareaRef.current;
|
|
152
|
+
if (!textarea)
|
|
153
|
+
return;
|
|
154
|
+
textarea.style.height = "auto";
|
|
155
|
+
const newHeight = Math.min(textarea.scrollHeight, 164);
|
|
156
|
+
textarea.style.height = `${newHeight}px`;
|
|
157
|
+
if (textarea.scrollHeight > 164) {
|
|
158
|
+
textarea.style.overflowY = "auto";
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
textarea.style.overflowY = "hidden";
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
const fieldProps = {
|
|
165
|
+
ref: handleRef,
|
|
166
|
+
name: "chat-input",
|
|
167
|
+
value,
|
|
168
|
+
onChange: handleChange,
|
|
169
|
+
onKeyDown: handleKeyDown,
|
|
170
|
+
disabled: disabled,
|
|
171
|
+
...props,
|
|
172
|
+
};
|
|
173
|
+
if (asChild && React.isValidElement(children)) {
|
|
174
|
+
return React.cloneElement(children, fieldProps);
|
|
175
|
+
}
|
|
176
|
+
return (_jsx("textarea", { ...fieldProps, className: cn("w-full resize-none rounded-none border-none p-4 shadow-none", "outline-none ring-0 field-sizing-content max-h-[6lh]", "bg-transparent dark:bg-transparent focus-visible:ring-0", "text-sm placeholder:text-muted-foreground", "disabled:cursor-not-allowed disabled:opacity-50", className) }));
|
|
177
|
+
});
|
|
162
178
|
ChatInputField.displayName = "ChatInput.Field";
|
|
163
|
-
const ChatInputSubmit = React.forwardRef(
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const isDisabled =
|
|
170
|
-
disabledProp || disabled || isSubmitting || !value.trim();
|
|
171
|
-
const Comp = asChild ? Slot : Button;
|
|
172
|
-
return _jsx(Comp, {
|
|
173
|
-
ref: ref,
|
|
174
|
-
type: "submit",
|
|
175
|
-
disabled: isDisabled,
|
|
176
|
-
size: "icon",
|
|
177
|
-
className: cn(
|
|
178
|
-
!asChild &&
|
|
179
|
-
"gap-1.5 rounded-lg bg-transparent text-foreground hover:bg-transparent",
|
|
180
|
-
className,
|
|
181
|
-
),
|
|
182
|
-
...props,
|
|
183
|
-
children: children,
|
|
184
|
-
});
|
|
185
|
-
},
|
|
186
|
-
);
|
|
179
|
+
const ChatInputSubmit = React.forwardRef(({ asChild = false, className, disabled: disabledProp, children, ...props }, ref) => {
|
|
180
|
+
const { value, disabled, isSubmitting } = useChatInputContext();
|
|
181
|
+
const isDisabled = disabledProp || disabled || isSubmitting || !value.trim();
|
|
182
|
+
const Comp = asChild ? Slot : Button;
|
|
183
|
+
return (_jsx(Comp, { ref: ref, type: "submit", disabled: isDisabled, variant: !asChild ? "default" : undefined, size: "icon", className: cn(!asChild && "gap-1.5 rounded-full", className), ...props, children: children }));
|
|
184
|
+
});
|
|
187
185
|
ChatInputSubmit.displayName = "ChatInput.Submit";
|
|
188
|
-
const ChatInputToolbar = React.forwardRef(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
ref: ref,
|
|
192
|
-
className: cn("flex items-center justify-between p-1", className),
|
|
193
|
-
...props,
|
|
194
|
-
children: children,
|
|
195
|
-
});
|
|
196
|
-
},
|
|
197
|
-
);
|
|
186
|
+
const ChatInputToolbar = React.forwardRef(({ className, children, ...props }, ref) => {
|
|
187
|
+
return (_jsx("div", { ref: ref, className: cn("flex items-center justify-between p-2", className), ...props, children: children }));
|
|
188
|
+
});
|
|
198
189
|
ChatInputToolbar.displayName = "ChatInput.Toolbar";
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
190
|
+
const ChatInputActions = React.forwardRef(({ asChild = false, className, children, onClick, ...props }, ref) => {
|
|
191
|
+
const { value, onChange, setShowCommandMenu, setCommandMenuQuery } = useChatInputContext();
|
|
192
|
+
const handleClick = (e) => {
|
|
193
|
+
// Trigger command menu by setting "/" in the input
|
|
194
|
+
if (!value.startsWith("/")) {
|
|
195
|
+
onChange("/");
|
|
196
|
+
setShowCommandMenu(true);
|
|
197
|
+
setCommandMenuQuery("");
|
|
198
|
+
}
|
|
199
|
+
onClick?.(e);
|
|
200
|
+
};
|
|
201
|
+
const Comp = asChild ? Slot : Button;
|
|
202
|
+
return (_jsx(Comp, { ref: ref, type: "button", variant: "ghost", size: "icon", className: cn("rounded-full", className), onClick: handleClick, ...props, children: children || _jsx(SquareSlash, { className: "size-4" }) }));
|
|
203
|
+
});
|
|
204
|
+
ChatInputActions.displayName = "ChatInput.Actions";
|
|
205
|
+
const ChatInputAttachment = React.forwardRef(({ asChild = false, className, children, ...props }, ref) => {
|
|
206
|
+
const Comp = asChild ? Slot : Button;
|
|
207
|
+
return (_jsx(Comp, { ref: ref, type: "button", variant: "ghost", size: "icon", className: cn("rounded-full", className), ...props, children: children || _jsx(Paperclip, { className: "size-4" }) }));
|
|
208
|
+
});
|
|
209
|
+
ChatInputAttachment.displayName = "ChatInput.Attachment";
|
|
210
|
+
const ChatInputVoiceInput = React.forwardRef(({ asChild = false, className, children, ...props }, ref) => {
|
|
211
|
+
const Comp = asChild ? Slot : Button;
|
|
212
|
+
return (_jsx(Comp, { ref: ref, type: "button", variant: "ghost", size: "icon", className: cn("rounded-full", className), ...props, children: children || _jsx(Mic, { className: "size-4" }) }));
|
|
213
|
+
});
|
|
214
|
+
ChatInputVoiceInput.displayName = "ChatInput.VoiceInput";
|
|
215
|
+
const ChatInputCommandMenu = React.forwardRef(({ commands = [], className, onChange: _, ...props }, ref) => {
|
|
216
|
+
const { showCommandMenu, commandMenuQuery, selectedMenuIndex, setSelectedMenuIndex, setMenuItemCount, triggerCounter, onChange, } = useChatInputContext();
|
|
217
|
+
return (_jsx(ChatInputCommandMenuComponent, { ref: ref, commands: commands, showCommandMenu: showCommandMenu, commandMenuQuery: commandMenuQuery, selectedMenuIndex: selectedMenuIndex, setSelectedMenuIndex: setSelectedMenuIndex, setMenuItemCount: setMenuItemCount, triggerCounter: triggerCounter, onChange: onChange, className: className, ...props }));
|
|
218
|
+
});
|
|
219
|
+
ChatInputCommandMenu.displayName = "ChatInput.CommandMenu";
|
|
220
|
+
export { ChatInputRoot as Root, ChatInputField as Field, ChatInputSubmit as Submit, ChatInputToolbar as Toolbar, ChatInputActions as Actions, ChatInputAttachment as Attachment, ChatInputVoiceInput as VoiceInput, ChatInputCommandMenu as CommandMenu, };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface CommandMenuItem {
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
icon?: React.ReactNode;
|
|
7
|
+
category?: string;
|
|
8
|
+
onSelect: () => void;
|
|
9
|
+
}
|
|
10
|
+
export interface ChatInputCommandMenuProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onChange"> {
|
|
11
|
+
commands?: CommandMenuItem[];
|
|
12
|
+
showCommandMenu: boolean;
|
|
13
|
+
commandMenuQuery: string;
|
|
14
|
+
selectedMenuIndex: number;
|
|
15
|
+
setSelectedMenuIndex: (index: number) => void;
|
|
16
|
+
setMenuItemCount: (count: number) => void;
|
|
17
|
+
triggerCounter: number;
|
|
18
|
+
onChange: (value: string) => void;
|
|
19
|
+
}
|
|
20
|
+
export declare const ChatInputCommandMenu: React.ForwardRefExoticComponent<ChatInputCommandMenuProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { cn } from "../lib/utils.js";
|
|
4
|
+
/* -------------------------------------------------------------------------------------------------
|
|
5
|
+
* ChatInputCommandMenu
|
|
6
|
+
* -----------------------------------------------------------------------------------------------*/
|
|
7
|
+
export const ChatInputCommandMenu = React.forwardRef(({ commands = [], showCommandMenu, commandMenuQuery, selectedMenuIndex, setSelectedMenuIndex, setMenuItemCount, triggerCounter, onChange, className, ...props }, ref) => {
|
|
8
|
+
// Fuzzy search implementation
|
|
9
|
+
const fuzzyMatch = React.useCallback((text, query) => {
|
|
10
|
+
const lowerText = text.toLowerCase();
|
|
11
|
+
const lowerQuery = query.toLowerCase();
|
|
12
|
+
if (!query)
|
|
13
|
+
return 1; // Show all when no query
|
|
14
|
+
if (lowerText.includes(lowerQuery)) {
|
|
15
|
+
// Exact substring match gets high score
|
|
16
|
+
return 1 - lowerQuery.length / lowerText.length;
|
|
17
|
+
}
|
|
18
|
+
// Fuzzy matching - check if all query chars appear in order
|
|
19
|
+
let queryIndex = 0;
|
|
20
|
+
for (let i = 0; i < lowerText.length && queryIndex < lowerQuery.length; i++) {
|
|
21
|
+
if (lowerText[i] === lowerQuery[queryIndex]) {
|
|
22
|
+
queryIndex++;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (queryIndex === lowerQuery.length) {
|
|
26
|
+
// All chars found, score based on how spread out they are
|
|
27
|
+
return 0.5 - queryIndex / lowerText.length;
|
|
28
|
+
}
|
|
29
|
+
return 0; // No match
|
|
30
|
+
}, []);
|
|
31
|
+
// Filter and sort commands by relevance
|
|
32
|
+
const filteredCommands = React.useMemo(() => {
|
|
33
|
+
return commands
|
|
34
|
+
.map((cmd) => ({
|
|
35
|
+
...cmd,
|
|
36
|
+
score: Math.max(fuzzyMatch(cmd.label, commandMenuQuery), cmd.description ? fuzzyMatch(cmd.description, commandMenuQuery) : 0),
|
|
37
|
+
}))
|
|
38
|
+
.filter((cmd) => cmd.score > 0)
|
|
39
|
+
.sort((a, b) => b.score - a.score);
|
|
40
|
+
}, [commands, commandMenuQuery, fuzzyMatch]);
|
|
41
|
+
// Update menu item count
|
|
42
|
+
React.useEffect(() => {
|
|
43
|
+
setMenuItemCount(filteredCommands.length);
|
|
44
|
+
}, [filteredCommands.length, setMenuItemCount]);
|
|
45
|
+
// Reset selected index when filtered results change
|
|
46
|
+
React.useEffect(() => {
|
|
47
|
+
setSelectedMenuIndex(0);
|
|
48
|
+
}, [setSelectedMenuIndex]);
|
|
49
|
+
// Handle selection when triggered
|
|
50
|
+
React.useEffect(() => {
|
|
51
|
+
if (triggerCounter > 0 && filteredCommands[selectedMenuIndex]) {
|
|
52
|
+
filteredCommands[selectedMenuIndex].onSelect();
|
|
53
|
+
// Clear the input after selection
|
|
54
|
+
onChange("");
|
|
55
|
+
}
|
|
56
|
+
}, [triggerCounter, filteredCommands, selectedMenuIndex, onChange]);
|
|
57
|
+
if (!showCommandMenu || filteredCommands.length === 0) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
return (_jsxs("div", { ref: ref, className: cn("absolute bottom-full left-0 z-50 mb-2 w-full max-w-md", "rounded-md border border-border bg-card p-2 shadow-lg", className), ...props, children: [_jsx("div", { className: "text-xs font-semibold text-muted-foreground px-2 py-1", children: "Commands" }), _jsx("div", { className: "max-h-64 overflow-y-auto", children: filteredCommands.map((command, index) => (_jsxs("button", { type: "button", onClick: () => command.onSelect(), className: cn("w-full rounded-sm px-2 py-2 text-left text-sm transition-colors", "flex items-start gap-2", "hover:bg-muted", index === selectedMenuIndex && "bg-muted"), children: [command.icon && (_jsx("span", { className: "shrink-0 mt-0.5", children: command.icon })), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("div", { className: "font-medium", children: command.label }), command.description && (_jsx("div", { className: "text-xs text-muted-foreground truncate", children: command.description }))] })] }, command.id))) })] }));
|
|
61
|
+
});
|
|
62
|
+
ChatInputCommandMenu.displayName = "ChatInputCommandMenu";
|
|
@@ -2,81 +2,51 @@ import * as React from "react";
|
|
|
2
2
|
type PanelSize = "hidden" | "small" | "large";
|
|
3
3
|
type PanelTabType = "todo" | "files" | "database";
|
|
4
4
|
interface ChatLayoutContextValue {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
sidebarOpen: boolean;
|
|
6
|
+
setSidebarOpen: (open: boolean) => void;
|
|
7
|
+
panelSize: PanelSize;
|
|
8
|
+
setPanelSize: (size: PanelSize) => void;
|
|
9
|
+
activeTab: PanelTabType;
|
|
10
|
+
setActiveTab: (tab: PanelTabType) => void;
|
|
11
11
|
}
|
|
12
12
|
declare const useChatLayoutContext: () => ChatLayoutContextValue;
|
|
13
|
-
export interface ChatLayoutRootProps
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
defaultActiveTab?: PanelTabType;
|
|
13
|
+
export interface ChatLayoutRootProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
14
|
+
/** Initial sidebar open state */
|
|
15
|
+
defaultSidebarOpen?: boolean;
|
|
16
|
+
/** Initial panel size state */
|
|
17
|
+
defaultPanelSize?: PanelSize;
|
|
18
|
+
/** Initial active tab */
|
|
19
|
+
defaultActiveTab?: PanelTabType;
|
|
21
20
|
}
|
|
22
|
-
declare const ChatLayoutRoot: React.ForwardRefExoticComponent<
|
|
23
|
-
|
|
24
|
-
>;
|
|
25
|
-
export interface ChatLayoutHeaderProps
|
|
26
|
-
extends React.HTMLAttributes<HTMLDivElement> {}
|
|
27
|
-
declare const ChatLayoutHeader: React.ForwardRefExoticComponent<
|
|
28
|
-
ChatLayoutHeaderProps & React.RefAttributes<HTMLDivElement>
|
|
29
|
-
>;
|
|
30
|
-
export interface ChatLayoutMainProps
|
|
31
|
-
extends React.HTMLAttributes<HTMLDivElement> {}
|
|
32
|
-
declare const ChatLayoutMain: React.ForwardRefExoticComponent<
|
|
33
|
-
ChatLayoutMainProps & React.RefAttributes<HTMLDivElement>
|
|
34
|
-
>;
|
|
35
|
-
export interface ChatLayoutBodyProps
|
|
36
|
-
extends React.HTMLAttributes<HTMLDivElement> {
|
|
37
|
-
/** Whether to show toaster */
|
|
38
|
-
showToaster?: boolean;
|
|
21
|
+
declare const ChatLayoutRoot: React.ForwardRefExoticComponent<ChatLayoutRootProps & React.RefAttributes<HTMLDivElement>>;
|
|
22
|
+
export interface ChatLayoutHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
39
23
|
}
|
|
40
|
-
declare const
|
|
41
|
-
|
|
42
|
-
>;
|
|
43
|
-
export interface ChatLayoutMessagesProps
|
|
44
|
-
extends React.HTMLAttributes<HTMLDivElement> {
|
|
45
|
-
/** Callback when scroll position changes */
|
|
46
|
-
onScrollChange?: (isAtBottom: boolean) => void;
|
|
47
|
-
/** Whether to show scroll to bottom button */
|
|
48
|
-
showScrollToBottom?: boolean;
|
|
24
|
+
declare const ChatLayoutHeader: React.ForwardRefExoticComponent<ChatLayoutHeaderProps & React.RefAttributes<HTMLDivElement>>;
|
|
25
|
+
export interface ChatLayoutMainProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
49
26
|
}
|
|
50
|
-
declare const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
extends React.HTMLAttributes<HTMLDivElement> {}
|
|
55
|
-
declare const ChatLayoutFooter: React.ForwardRefExoticComponent<
|
|
56
|
-
ChatLayoutFooterProps & React.RefAttributes<HTMLDivElement>
|
|
57
|
-
>;
|
|
58
|
-
export interface ChatLayoutSidebarProps
|
|
59
|
-
extends React.HTMLAttributes<HTMLDivElement> {}
|
|
60
|
-
declare const ChatLayoutSidebar: React.ForwardRefExoticComponent<
|
|
61
|
-
ChatLayoutSidebarProps & React.RefAttributes<HTMLDivElement>
|
|
62
|
-
>;
|
|
63
|
-
export interface ChatLayoutAsideProps
|
|
64
|
-
extends React.HTMLAttributes<HTMLDivElement> {
|
|
65
|
-
/** Show panel on these breakpoints (default: lg and above) */
|
|
66
|
-
breakpoint?: "md" | "lg" | "xl" | "2xl";
|
|
27
|
+
declare const ChatLayoutMain: React.ForwardRefExoticComponent<ChatLayoutMainProps & React.RefAttributes<HTMLDivElement>>;
|
|
28
|
+
export interface ChatLayoutBodyProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
29
|
+
/** Whether to show toaster */
|
|
30
|
+
showToaster?: boolean;
|
|
67
31
|
}
|
|
68
|
-
declare const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
32
|
+
declare const ChatLayoutBody: React.ForwardRefExoticComponent<ChatLayoutBodyProps & React.RefAttributes<HTMLDivElement>>;
|
|
33
|
+
export interface ChatLayoutMessagesProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
34
|
+
/** Callback when scroll position changes */
|
|
35
|
+
onScrollChange?: (isAtBottom: boolean) => void;
|
|
36
|
+
/** Whether to show scroll to bottom button */
|
|
37
|
+
showScrollToBottom?: boolean;
|
|
38
|
+
}
|
|
39
|
+
declare const ChatLayoutMessages: React.ForwardRefExoticComponent<ChatLayoutMessagesProps & React.RefAttributes<HTMLDivElement>>;
|
|
40
|
+
export interface ChatLayoutFooterProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
41
|
+
}
|
|
42
|
+
declare const ChatLayoutFooter: React.ForwardRefExoticComponent<ChatLayoutFooterProps & React.RefAttributes<HTMLDivElement>>;
|
|
43
|
+
export interface ChatLayoutSidebarProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
44
|
+
}
|
|
45
|
+
declare const ChatLayoutSidebar: React.ForwardRefExoticComponent<ChatLayoutSidebarProps & React.RefAttributes<HTMLDivElement>>;
|
|
46
|
+
export interface ChatLayoutAsideProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
47
|
+
/** Show panel on these breakpoints (default: lg and above) */
|
|
48
|
+
breakpoint?: "md" | "lg" | "xl" | "2xl";
|
|
49
|
+
}
|
|
50
|
+
declare const ChatLayoutAside: React.ForwardRefExoticComponent<ChatLayoutAsideProps & React.RefAttributes<HTMLDivElement>>;
|
|
51
|
+
export { ChatLayoutRoot as Root, ChatLayoutHeader as Header, ChatLayoutMain as Main, ChatLayoutBody as Body, ChatLayoutMessages as Messages, ChatLayoutFooter as Footer, ChatLayoutSidebar as Sidebar, ChatLayoutAside as Aside, useChatLayoutContext, };
|
|
82
52
|
export type { PanelSize, PanelTabType };
|