@townco/ui 0.1.7 → 0.1.9

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.
Files changed (243) hide show
  1. package/dist/core/hooks/index.d.ts +1 -0
  2. package/dist/core/hooks/index.d.ts.map +1 -0
  3. package/dist/core/hooks/index.js +1 -0
  4. package/dist/core/hooks/index.js.map +1 -0
  5. package/dist/core/hooks/use-chat-input.d.ts +17 -17
  6. package/dist/core/hooks/use-chat-input.d.ts.map +1 -0
  7. package/dist/core/hooks/use-chat-input.js +64 -55
  8. package/dist/core/hooks/use-chat-input.js.map +1 -0
  9. package/dist/core/hooks/use-chat-messages.d.ts +11 -11
  10. package/dist/core/hooks/use-chat-messages.d.ts.map +1 -0
  11. package/dist/core/hooks/use-chat-messages.js +121 -114
  12. package/dist/core/hooks/use-chat-messages.js.map +1 -0
  13. package/dist/core/hooks/use-chat-session.d.ts +5 -5
  14. package/dist/core/hooks/use-chat-session.d.ts.map +1 -0
  15. package/dist/core/hooks/use-chat-session.js +78 -80
  16. package/dist/core/hooks/use-chat-session.js.map +1 -0
  17. package/dist/core/hooks/use-media-query.d.ts +39 -0
  18. package/dist/core/hooks/use-media-query.js +84 -0
  19. package/dist/core/index.d.ts.map +1 -0
  20. package/dist/core/index.js.map +1 -0
  21. package/dist/core/schemas/chat.d.ts +83 -56
  22. package/dist/core/schemas/chat.d.ts.map +1 -0
  23. package/dist/core/schemas/chat.js +27 -25
  24. package/dist/core/schemas/chat.js.map +1 -0
  25. package/dist/core/schemas/index.d.ts.map +1 -0
  26. package/dist/core/schemas/index.js.map +1 -0
  27. package/dist/core/store/chat-store.d.ts +28 -22
  28. package/dist/core/store/chat-store.d.ts.map +1 -0
  29. package/dist/core/store/chat-store.js +59 -50
  30. package/dist/core/store/chat-store.js.map +1 -0
  31. package/dist/gui/components/Button.d.ts +23 -7
  32. package/dist/gui/components/Button.d.ts.map +1 -0
  33. package/dist/gui/components/Button.js +40 -27
  34. package/dist/gui/components/Button.js.map +1 -0
  35. package/dist/gui/components/Card.d.ts +26 -7
  36. package/dist/gui/components/Card.d.ts.map +1 -0
  37. package/dist/gui/components/Card.js +54 -8
  38. package/dist/gui/components/Card.js.map +1 -0
  39. package/dist/gui/components/ChatHeader.d.ts +38 -0
  40. package/dist/gui/components/ChatHeader.js +86 -0
  41. package/dist/gui/components/ChatInput.d.ts +19 -1
  42. package/dist/gui/components/ChatInput.d.ts.map +1 -0
  43. package/dist/gui/components/ChatInput.js +94 -11
  44. package/dist/gui/components/ChatInput.js.map +1 -0
  45. package/dist/gui/components/ChatInputCommandMenu.d.ts +20 -0
  46. package/dist/gui/components/ChatInputCommandMenu.js +62 -0
  47. package/dist/gui/components/ChatInterface.d.ts +12 -0
  48. package/dist/gui/components/ChatInterface.d.ts.map +1 -0
  49. package/dist/gui/components/ChatInterface.js +204 -0
  50. package/dist/gui/components/ChatInterface.js.map +1 -0
  51. package/dist/gui/components/ChatLayout.d.ts +52 -0
  52. package/dist/gui/components/ChatLayout.js +105 -0
  53. package/dist/gui/components/ChatPanelTabContent.d.ts +18 -0
  54. package/dist/gui/components/ChatPanelTabContent.js +15 -0
  55. package/dist/gui/components/ChatPreview.d.ts +12 -0
  56. package/dist/gui/components/ChatPreview.d.ts.map +1 -0
  57. package/dist/gui/components/ChatPreview.js +214 -0
  58. package/dist/gui/components/ChatPreview.js.map +1 -0
  59. package/dist/gui/components/ChatSecondaryPanel.d.ts +14 -11
  60. package/dist/gui/components/ChatSecondaryPanel.d.ts.map +1 -0
  61. package/dist/gui/components/ChatSecondaryPanel.js +115 -38
  62. package/dist/gui/components/ChatSecondaryPanel.js.map +1 -0
  63. package/dist/gui/components/ChatSidebar.d.ts +14 -0
  64. package/dist/gui/components/ChatSidebar.js +23 -0
  65. package/dist/gui/components/ChatStatus.d.ts +4 -2
  66. package/dist/gui/components/ChatStatus.d.ts.map +1 -0
  67. package/dist/gui/components/ChatStatus.js +45 -34
  68. package/dist/gui/components/ChatStatus.js.map +1 -0
  69. package/dist/gui/components/ChatView.d.ts +8 -0
  70. package/dist/gui/components/ChatView.d.ts.map +1 -0
  71. package/dist/gui/components/ChatView.js +42 -0
  72. package/dist/gui/components/ChatView.js.map +1 -0
  73. package/dist/gui/components/ConfigPanel.d.ts +20 -0
  74. package/dist/gui/components/ConfigPanel.d.ts.map +1 -0
  75. package/dist/gui/components/ConfigPanel.js +225 -0
  76. package/dist/gui/components/ConfigPanel.js.map +1 -0
  77. package/dist/gui/components/Conversation.d.ts +17 -14
  78. package/dist/gui/components/Conversation.d.ts.map +1 -0
  79. package/dist/gui/components/Conversation.js +143 -83
  80. package/dist/gui/components/Conversation.js.map +1 -0
  81. package/dist/gui/components/Dialog.d.ts +57 -11
  82. package/dist/gui/components/Dialog.d.ts.map +1 -0
  83. package/dist/gui/components/Dialog.js +84 -8
  84. package/dist/gui/components/Dialog.js.map +1 -0
  85. package/dist/gui/components/DropdownMenu.d.ts +27 -0
  86. package/dist/gui/components/DropdownMenu.js +68 -0
  87. package/dist/gui/components/HeightTransition.d.ts +12 -7
  88. package/dist/gui/components/HeightTransition.d.ts.map +1 -0
  89. package/dist/gui/components/HeightTransition.js +88 -77
  90. package/dist/gui/components/HeightTransition.js.map +1 -0
  91. package/dist/gui/components/Input.d.ts +13 -6
  92. package/dist/gui/components/Input.d.ts.map +1 -0
  93. package/dist/gui/components/Input.js +27 -16
  94. package/dist/gui/components/Input.js.map +1 -0
  95. package/dist/gui/components/InputBox.d.ts +21 -0
  96. package/dist/gui/components/InputBox.d.ts.map +1 -0
  97. package/dist/gui/components/InputBox.js +90 -0
  98. package/dist/gui/components/InputBox.js.map +1 -0
  99. package/dist/gui/components/Label.d.ts +7 -1
  100. package/dist/gui/components/Label.d.ts.map +1 -0
  101. package/dist/gui/components/Label.js +12 -2
  102. package/dist/gui/components/Label.js.map +1 -0
  103. package/dist/gui/components/MarkdownRenderer.d.ts +6 -4
  104. package/dist/gui/components/MarkdownRenderer.d.ts.map +1 -0
  105. package/dist/gui/components/MarkdownRenderer.js +178 -81
  106. package/dist/gui/components/MarkdownRenderer.js.map +1 -0
  107. package/dist/gui/components/Message.d.ts +4 -0
  108. package/dist/gui/components/Message.d.ts.map +1 -0
  109. package/dist/gui/components/Message.js +77 -3
  110. package/dist/gui/components/Message.js.map +1 -0
  111. package/dist/gui/components/MessageContent.d.ts +29 -22
  112. package/dist/gui/components/MessageContent.d.ts.map +1 -0
  113. package/dist/gui/components/MessageContent.js +1 -1
  114. package/dist/gui/components/MessageContent.js.map +1 -0
  115. package/dist/gui/components/MessageList.d.ts.map +1 -0
  116. package/dist/gui/components/MessageList.js.map +1 -0
  117. package/dist/gui/components/PlaygroundLayout.d.ts +14 -0
  118. package/dist/gui/components/PlaygroundLayout.d.ts.map +1 -0
  119. package/dist/gui/components/PlaygroundLayout.js +49 -0
  120. package/dist/gui/components/PlaygroundLayout.js.map +1 -0
  121. package/dist/gui/components/Reasoning.d.ts +30 -24
  122. package/dist/gui/components/Reasoning.d.ts.map +1 -0
  123. package/dist/gui/components/Reasoning.js +187 -60
  124. package/dist/gui/components/Reasoning.js.map +1 -0
  125. package/dist/gui/components/Response.d.ts +11 -9
  126. package/dist/gui/components/Response.d.ts.map +1 -0
  127. package/dist/gui/components/Response.js +229 -90
  128. package/dist/gui/components/Response.js.map +1 -0
  129. package/dist/gui/components/Select.d.ts +69 -10
  130. package/dist/gui/components/Select.d.ts.map +1 -0
  131. package/dist/gui/components/Select.js +118 -12
  132. package/dist/gui/components/Select.js.map +1 -0
  133. package/dist/gui/components/Sonner.d.ts +5 -0
  134. package/dist/gui/components/Sonner.js +23 -0
  135. package/dist/gui/components/StatusBar.d.ts +12 -0
  136. package/dist/gui/components/StatusBar.d.ts.map +1 -0
  137. package/dist/gui/components/StatusBar.js +58 -0
  138. package/dist/gui/components/StatusBar.js.map +1 -0
  139. package/dist/gui/components/Tabs.d.ts +24 -4
  140. package/dist/gui/components/Tabs.d.ts.map +1 -0
  141. package/dist/gui/components/Tabs.js +32 -4
  142. package/dist/gui/components/Tabs.js.map +1 -0
  143. package/dist/gui/components/Task.d.ts +28 -24
  144. package/dist/gui/components/Task.d.ts.map +1 -0
  145. package/dist/gui/components/Task.js +164 -31
  146. package/dist/gui/components/Task.js.map +1 -0
  147. package/dist/gui/components/Textarea.d.ts +15 -7
  148. package/dist/gui/components/Textarea.d.ts.map +1 -0
  149. package/dist/gui/components/Textarea.js +63 -46
  150. package/dist/gui/components/Textarea.js.map +1 -0
  151. package/dist/gui/components/ThinkingBlock.d.ts +20 -10
  152. package/dist/gui/components/ThinkingBlock.d.ts.map +1 -0
  153. package/dist/gui/components/ThinkingBlock.js +134 -35
  154. package/dist/gui/components/ThinkingBlock.js.map +1 -0
  155. package/dist/gui/components/TodoList.d.ts +12 -10
  156. package/dist/gui/components/TodoList.d.ts.map +1 -0
  157. package/dist/gui/components/TodoList.js +22 -7
  158. package/dist/gui/components/TodoList.js.map +1 -0
  159. package/dist/gui/components/TodoListItem.d.ts +9 -6
  160. package/dist/gui/components/TodoListItem.d.ts.map +1 -0
  161. package/dist/gui/components/TodoListItem.js +18 -4
  162. package/dist/gui/components/TodoListItem.js.map +1 -0
  163. package/dist/gui/components/index.d.ts +9 -1
  164. package/dist/gui/components/index.d.ts.map +1 -0
  165. package/dist/gui/components/index.js +11 -1
  166. package/dist/gui/components/index.js.map +1 -0
  167. package/dist/gui/index.d.ts.map +1 -0
  168. package/dist/gui/index.js.map +1 -0
  169. package/dist/gui/lib/utils.d.ts.map +1 -0
  170. package/dist/gui/lib/utils.js +1 -1
  171. package/dist/gui/lib/utils.js.map +1 -0
  172. package/dist/index.d.ts.map +1 -0
  173. package/dist/index.js.map +1 -0
  174. package/dist/index.test.js +0 -1
  175. package/dist/sdk/client/acp-client.d.ts +88 -76
  176. package/dist/sdk/client/acp-client.d.ts.map +1 -0
  177. package/dist/sdk/client/acp-client.js +215 -217
  178. package/dist/sdk/client/acp-client.js.map +1 -0
  179. package/dist/sdk/client/index.d.ts.map +1 -0
  180. package/dist/sdk/client/index.js.map +1 -0
  181. package/dist/sdk/index.d.ts.map +1 -0
  182. package/dist/sdk/index.js.map +1 -0
  183. package/dist/sdk/schemas/agent.d.ts +111 -64
  184. package/dist/sdk/schemas/agent.d.ts.map +1 -0
  185. package/dist/sdk/schemas/agent.js +24 -24
  186. package/dist/sdk/schemas/agent.js.map +1 -0
  187. package/dist/sdk/schemas/index.d.ts.map +1 -0
  188. package/dist/sdk/schemas/index.js.map +1 -0
  189. package/dist/sdk/schemas/message.d.ts +245 -147
  190. package/dist/sdk/schemas/message.d.ts.map +1 -0
  191. package/dist/sdk/schemas/message.js +40 -40
  192. package/dist/sdk/schemas/message.js.map +1 -0
  193. package/dist/sdk/schemas/session.d.ts +219 -135
  194. package/dist/sdk/schemas/session.d.ts.map +1 -0
  195. package/dist/sdk/schemas/session.js +27 -27
  196. package/dist/sdk/schemas/session.js.map +1 -0
  197. package/dist/sdk/transports/http.d.ts +55 -55
  198. package/dist/sdk/transports/http.d.ts.map +1 -0
  199. package/dist/sdk/transports/http.js +472 -469
  200. package/dist/sdk/transports/http.js.map +1 -0
  201. package/dist/sdk/transports/index.d.ts.map +1 -0
  202. package/dist/sdk/transports/index.js.map +1 -0
  203. package/dist/sdk/transports/stdio.d.ts +20 -20
  204. package/dist/sdk/transports/stdio.d.ts.map +1 -0
  205. package/dist/sdk/transports/stdio.js.map +1 -0
  206. package/dist/sdk/transports/types.d.ts +42 -42
  207. package/dist/sdk/transports/types.d.ts.map +1 -0
  208. package/dist/sdk/transports/types.js.map +1 -0
  209. package/dist/sdk/transports/websocket.d.ts +12 -12
  210. package/dist/sdk/transports/websocket.d.ts.map +1 -0
  211. package/dist/sdk/transports/websocket.js +52 -46
  212. package/dist/sdk/transports/websocket.js.map +1 -0
  213. package/dist/tui/components/ChatView.d.ts +4 -2
  214. package/dist/tui/components/ChatView.d.ts.map +1 -0
  215. package/dist/tui/components/ChatView.js +51 -18
  216. package/dist/tui/components/ChatView.js.map +1 -0
  217. package/dist/tui/components/GameOfLife.d.ts.map +1 -0
  218. package/dist/tui/components/GameOfLife.js +64 -35
  219. package/dist/tui/components/GameOfLife.js.map +1 -0
  220. package/dist/tui/components/InputBox.d.ts +18 -11
  221. package/dist/tui/components/InputBox.d.ts.map +1 -0
  222. package/dist/tui/components/InputBox.js +70 -10
  223. package/dist/tui/components/InputBox.js.map +1 -0
  224. package/dist/tui/components/MessageList.d.ts +4 -2
  225. package/dist/tui/components/MessageList.d.ts.map +1 -0
  226. package/dist/tui/components/MessageList.js +37 -10
  227. package/dist/tui/components/MessageList.js.map +1 -0
  228. package/dist/tui/components/ReadlineInput.d.ts +12 -6
  229. package/dist/tui/components/ReadlineInput.d.ts.map +1 -0
  230. package/dist/tui/components/ReadlineInput.js +252 -237
  231. package/dist/tui/components/ReadlineInput.js.map +1 -0
  232. package/dist/tui/components/SingleSelect.d.ts +15 -9
  233. package/dist/tui/components/SingleSelect.js +84 -43
  234. package/dist/tui/components/StatusBar.d.ts +11 -6
  235. package/dist/tui/components/StatusBar.d.ts.map +1 -0
  236. package/dist/tui/components/StatusBar.js +102 -67
  237. package/dist/tui/components/StatusBar.js.map +1 -0
  238. package/dist/tui/components/index.d.ts.map +1 -0
  239. package/dist/tui/components/index.js.map +1 -0
  240. package/dist/tui/index.d.ts.map +1 -0
  241. package/dist/tui/index.js.map +1 -0
  242. package/package.json +6 -4
  243. package/src/styles/global.css +2 -0
@@ -1,10 +1,12 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Slot } from "@radix-ui/react-slot";
3
+ import { Mic, Paperclip, SquareSlash } from "lucide-react";
3
4
  import * as React from "react";
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";
9
+ import { ChatInputCommandMenu as ChatInputCommandMenuComponent, } from "./ChatInputCommandMenu.js";
8
10
  const ChatInputContext = React.createContext(undefined);
9
11
  const useChatInputContext = () => {
10
12
  const context = React.useContext(ChatInputContext);
@@ -27,6 +29,15 @@ const ChatInputRoot = React.forwardRef(({ client, value: valueProp, onChange: on
27
29
  const isSubmitting = hookData
28
30
  ? hookData.isSubmitting || storeIsStreaming
29
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
+ }, []);
30
41
  const handleSubmit = async (e) => {
31
42
  e.preventDefault();
32
43
  if (value.trim() && !isSubmitting && !disabled) {
@@ -58,11 +69,21 @@ const ChatInputRoot = React.forwardRef(({ client, value: valueProp, onChange: on
58
69
  disabled,
59
70
  isSubmitting,
60
71
  submitOnEnter,
61
- }, children: _jsx("form", { ref: ref, onSubmit: handleSubmit, className: cn("w-full divide-y overflow-hidden rounded-xl border bg-background shadow-sm", className), ...props, children: children }) }));
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 }) }));
62
83
  });
63
84
  ChatInputRoot.displayName = "ChatInput.Root";
64
85
  const ChatInputField = React.forwardRef(({ asChild = false, className, onKeyDown, children, ...props }, ref) => {
65
- const { value, onChange, onSubmit, disabled, isSubmitting, submitOnEnter } = useChatInputContext();
86
+ const { value, onChange, onSubmit, disabled, isSubmitting, submitOnEnter, showCommandMenu, setShowCommandMenu, setCommandMenuQuery, setSelectedMenuIndex, menuItemCount, triggerMenuSelect, } = useChatInputContext();
66
87
  const textareaRef = React.useRef(null);
67
88
  const handleRef = React.useCallback((node) => {
68
89
  textareaRef.current = node;
@@ -74,6 +95,30 @@ const ChatInputField = React.forwardRef(({ asChild = false, className, onKeyDown
74
95
  }
75
96
  }, [ref]);
76
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
+ }
77
122
  // Handle Enter without Shift - only submit if not already submitting
78
123
  if (submitOnEnter && e.key === "Enter" && !e.shiftKey) {
79
124
  // Only prevent default and submit if conditions are met
@@ -89,7 +134,19 @@ const ChatInputField = React.forwardRef(({ asChild = false, className, onKeyDown
89
134
  onKeyDown?.(e);
90
135
  };
91
136
  const handleChange = (e) => {
92
- onChange(e.target.value);
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
+ }
93
150
  // Auto-resize
94
151
  const textarea = textareaRef.current;
95
152
  if (!textarea)
@@ -116,22 +173,48 @@ const ChatInputField = React.forwardRef(({ asChild = false, className, onKeyDown
116
173
  if (asChild && React.isValidElement(children)) {
117
174
  return React.cloneElement(children, fieldProps);
118
175
  }
119
- return (_jsx("textarea", { ...fieldProps, className: cn("w-full resize-none rounded-none border-none p-3 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) }));
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) }));
120
177
  });
121
178
  ChatInputField.displayName = "ChatInput.Field";
122
179
  const ChatInputSubmit = React.forwardRef(({ asChild = false, className, disabled: disabledProp, children, ...props }, ref) => {
123
180
  const { value, disabled, isSubmitting } = useChatInputContext();
124
181
  const isDisabled = disabledProp || disabled || isSubmitting || !value.trim();
125
182
  const Comp = asChild ? Slot : Button;
126
- return (_jsx(Comp, { ref: ref, type: "submit", disabled: isDisabled, size: "icon", className: cn(!asChild &&
127
- "gap-1.5 rounded-lg bg-transparent text-foreground hover:bg-transparent", className), ...props, children: children }));
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 }));
128
184
  });
129
185
  ChatInputSubmit.displayName = "ChatInput.Submit";
130
186
  const ChatInputToolbar = React.forwardRef(({ className, children, ...props }, ref) => {
131
- return (_jsx("div", { ref: ref, className: cn("flex items-center justify-between p-1", className), ...props, children: children }));
187
+ return (_jsx("div", { ref: ref, className: cn("flex items-center justify-between p-2", className), ...props, children: children }));
132
188
  });
133
189
  ChatInputToolbar.displayName = "ChatInput.Toolbar";
134
- /* -------------------------------------------------------------------------------------------------
135
- * Exports
136
- * -----------------------------------------------------------------------------------------------*/
137
- export { ChatInputRoot as Root, ChatInputField as Field, ChatInputSubmit as Submit, ChatInputToolbar as Toolbar, };
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 @@
1
+ {"version":3,"file":"ChatInput.js","sourceRoot":"","sources":["../../../src/gui/components/ChatInput.tsx"],"names":[],"mappings":"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"}
@@ -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";
@@ -0,0 +1,12 @@
1
+ import { type DisplayMessage } from "./MessageList.js";
2
+ interface ChatInterfaceProps {
3
+ initialMessages?: DisplayMessage[];
4
+ thinkingDisplayStyle?: "collapsible" | "inline";
5
+ status?: string;
6
+ }
7
+ export declare function ChatInterface({
8
+ initialMessages,
9
+ thinkingDisplayStyle,
10
+ status,
11
+ }: ChatInterfaceProps): import("react/jsx-runtime").JSX.Element;
12
+ //# sourceMappingURL=ChatInterface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatInterface.d.ts","sourceRoot":"","sources":["../../../src/gui/components/ChatInterface.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAe,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAQpE,UAAU,kBAAkB;IAC1B,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;IACnC,oBAAoB,CAAC,EAAE,aAAa,GAAG,QAAQ,CAAC;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA2FD,wBAAgB,aAAa,CAAC,EAC5B,eAAiC,EACjC,oBAAoC,EACpC,MAAoB,GACrB,EAAE,kBAAkB,2CA+FpB"}
@@ -0,0 +1,204 @@
1
+ import { ChevronDown } from "lucide-react";
2
+ import { useEffect, useState } from "react";
3
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
+ import { ChatInput } from "./ChatInput.js";
5
+ import { ChatSecondaryPanel } from "./ChatSecondaryPanel.js";
6
+ import { ChatStatus } from "./ChatStatus.js";
7
+ import { HeightTransition } from "./HeightTransition.js";
8
+ import { MessageList } from "./MessageList.js";
9
+
10
+ const SAMPLE_TODOS = [
11
+ {
12
+ id: "1",
13
+ text: "Identify the last 25 Winter Olympics host countries",
14
+ status: "completed",
15
+ },
16
+ {
17
+ id: "2",
18
+ text: "For each host country, find the tallest mountain",
19
+ status: "in_progress",
20
+ },
21
+ {
22
+ id: "3",
23
+ text: "Gather key details for each mountain (name, elevation, location)",
24
+ status: "pending",
25
+ },
26
+ {
27
+ id: "4",
28
+ text: "Verify information using reliable sources (geographical databases, official records)",
29
+ status: "pending",
30
+ },
31
+ {
32
+ id: "5",
33
+ text: "Compile findings into a summary table or document",
34
+ status: "pending",
35
+ },
36
+ ];
37
+ const SAMPLE_MESSAGES = [
38
+ {
39
+ id: "msg-1",
40
+ role: "user",
41
+ content: "Hello! Can you help me understand how to use markdown?",
42
+ timestamp: new Date().toISOString(),
43
+ isStreaming: false,
44
+ },
45
+ {
46
+ id: "msg-2",
47
+ role: "assistant",
48
+ content: `Sure! Markdown is a lightweight markup language. Here are some basics:
49
+
50
+ ## Headings
51
+ Use \`#\` for headings. More \`#\` symbols make smaller headings.
52
+
53
+ ## Lists
54
+ - Unordered lists use dashes
55
+ - Or asterisks
56
+ - Or plus signs
57
+
58
+ 1. Ordered lists
59
+ 2. Use numbers
60
+ 3. Like this
61
+
62
+ ## Code
63
+ Inline code uses \`backticks\` and code blocks use triple backticks:
64
+
65
+ \`\`\`javascript
66
+ function hello() {
67
+ console.log("Hello world!");
68
+ }
69
+ \`\`\`
70
+
71
+ ## Links and emphasis
72
+ [This is a link](https://example.com)
73
+
74
+ You can make text **bold** or *italic*.
75
+
76
+ > Blockquotes use the > character
77
+
78
+ ## Tables
79
+ | Header 1 | Header 2 |
80
+ |----------|----------|
81
+ | Cell 1 | Cell 2 |
82
+ | Cell 3 | Cell 4 |`,
83
+ timestamp: new Date().toISOString(),
84
+ isStreaming: false,
85
+ metadata: {
86
+ thinking: "Let me provide a comprehensive overview of markdown syntax...",
87
+ },
88
+ },
89
+ {
90
+ id: "msg-3",
91
+ role: "user",
92
+ content: "That's really helpful, thank you!",
93
+ timestamp: new Date().toISOString(),
94
+ isStreaming: false,
95
+ },
96
+ ];
97
+ export function ChatInterface({
98
+ initialMessages = SAMPLE_MESSAGES,
99
+ thinkingDisplayStyle = "collapsible",
100
+ status = "Connected",
101
+ }) {
102
+ const [messages, setMessages] = useState(initialMessages);
103
+ const [currentStatus, setCurrentStatus] = useState(status);
104
+ const [config, setConfig] = useState(null);
105
+ const [isHeaderExpanded, setIsHeaderExpanded] = useState(false);
106
+ const [todos] = useState(SAMPLE_TODOS);
107
+ // Listen for config and status updates from parent window
108
+ useEffect(() => {
109
+ const handleMessage = (event) => {
110
+ if (event.data.type === "CONFIG_UPDATE") {
111
+ const newConfig = event.data.config;
112
+ setConfig(newConfig);
113
+ applyConfigToDocument(newConfig);
114
+ } else if (event.data.type === "STATUS_UPDATE") {
115
+ setCurrentStatus(event.data.status);
116
+ }
117
+ };
118
+ window.addEventListener("message", handleMessage);
119
+ // Request config from parent on mount
120
+ if (window.parent !== window) {
121
+ window.parent.postMessage({ type: "REQUEST_CONFIG" }, "*");
122
+ }
123
+ return () => {
124
+ window.removeEventListener("message", handleMessage);
125
+ };
126
+ }, []);
127
+ const applyConfigToDocument = (cfg) => {
128
+ const root = document.documentElement;
129
+ root.setAttribute("data-theme", cfg.colorScheme);
130
+ root.style.setProperty("--color-accent", cfg.accentColor);
131
+ root.style.setProperty("--font-family", cfg.typography);
132
+ root.style.setProperty("--font-size", `${cfg.fontSize}px`);
133
+ };
134
+ return _jsxs("div", {
135
+ className:
136
+ "flex flex-col h-screen bg-[var(--color-bg)] text-[var(--color-text)]",
137
+ children: [
138
+ _jsxs("div", {
139
+ className:
140
+ "relative border-b border-[var(--color-border)] bg-[var(--color-surface)] z-10",
141
+ children: [
142
+ _jsxs("div", {
143
+ className: "flex items-center justify-between px-6 py-4",
144
+ children: [
145
+ _jsx("h1", {
146
+ className: "text-xl font-semibold m-0",
147
+ children: "Chat Interface",
148
+ }),
149
+ _jsxs("div", {
150
+ className: "flex items-center gap-3",
151
+ children: [
152
+ _jsx(ChatStatus, { children: currentStatus }),
153
+ _jsx("button", {
154
+ onClick: () => setIsHeaderExpanded(!isHeaderExpanded),
155
+ className:
156
+ "p-1 rounded hover:bg-[var(--color-bg)] transition-colors",
157
+ "aria-label": isHeaderExpanded
158
+ ? "Collapse header"
159
+ : "Expand header",
160
+ children: _jsx(ChevronDown, {
161
+ className: `w-5 h-5 text-[var(--color-text)] transition-transform duration-200 ${isHeaderExpanded ? "rotate-180" : ""}`,
162
+ }),
163
+ }),
164
+ ],
165
+ }),
166
+ ],
167
+ }),
168
+ _jsx("div", {
169
+ className: "absolute top-full left-0 right-0 z-20",
170
+ children: _jsx(HeightTransition, {
171
+ children:
172
+ isHeaderExpanded &&
173
+ _jsx("div", {
174
+ className:
175
+ "bg-[var(--color-surface)] border-b border-[var(--color-border)] px-6 py-4 shadow-lg",
176
+ children: _jsx(ChatSecondaryPanel, { todos: todos }),
177
+ }),
178
+ }),
179
+ }),
180
+ ],
181
+ }),
182
+ _jsx("div", {
183
+ className: "flex-1 overflow-y-auto py-4",
184
+ children: _jsx(MessageList, {
185
+ messages: messages,
186
+ thinkingDisplayStyle:
187
+ config?.thinkingDisplayStyle || thinkingDisplayStyle,
188
+ }),
189
+ }),
190
+ _jsx("div", {
191
+ className:
192
+ "border-t border-[var(--color-border)] px-6 py-4 bg-[var(--color-surface)]",
193
+ children: _jsx(ChatInput, {
194
+ value: "",
195
+ onChange: () => {},
196
+ onSubmit: () => {},
197
+ disabled: true,
198
+ placeholder: "Type a message...",
199
+ }),
200
+ }),
201
+ ],
202
+ });
203
+ }
204
+ //# sourceMappingURL=ChatInterface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatInterface.js","sourceRoot":"","sources":["../../../src/gui/components/ChatInterface.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import * as React from "react";
2
+ type PanelSize = "hidden" | "small" | "large";
3
+ type PanelTabType = "todo" | "files" | "database";
4
+ interface ChatLayoutContextValue {
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
+ }
12
+ declare const useChatLayoutContext: () => ChatLayoutContextValue;
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;
20
+ }
21
+ declare const ChatLayoutRoot: React.ForwardRefExoticComponent<ChatLayoutRootProps & React.RefAttributes<HTMLDivElement>>;
22
+ export interface ChatLayoutHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
23
+ }
24
+ declare const ChatLayoutHeader: React.ForwardRefExoticComponent<ChatLayoutHeaderProps & React.RefAttributes<HTMLDivElement>>;
25
+ export interface ChatLayoutMainProps extends React.HTMLAttributes<HTMLDivElement> {
26
+ }
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;
31
+ }
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, };
52
+ export type { PanelSize, PanelTabType };
@@ -0,0 +1,105 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ArrowDown } from "lucide-react";
3
+ import * as React from "react";
4
+ import { cn } from "../lib/utils.js";
5
+ import { Toaster } from "./Sonner.js";
6
+ const ChatLayoutContext = React.createContext(undefined);
7
+ const useChatLayoutContext = () => {
8
+ const context = React.useContext(ChatLayoutContext);
9
+ if (!context) {
10
+ throw new Error("ChatLayout components must be used within ChatLayout.Root");
11
+ }
12
+ return context;
13
+ };
14
+ const ChatLayoutRoot = React.forwardRef(({ defaultSidebarOpen = false, defaultPanelSize = "hidden", defaultActiveTab = "todo", className, children, ...props }, ref) => {
15
+ const [sidebarOpen, setSidebarOpen] = React.useState(defaultSidebarOpen);
16
+ const [panelSize, setPanelSize] = React.useState(defaultPanelSize);
17
+ const [activeTab, setActiveTab] = React.useState(defaultActiveTab);
18
+ return (_jsx(ChatLayoutContext.Provider, { value: {
19
+ sidebarOpen,
20
+ setSidebarOpen,
21
+ panelSize,
22
+ setPanelSize,
23
+ activeTab,
24
+ setActiveTab,
25
+ }, children: _jsx("div", { ref: ref, className: cn("flex h-screen flex-row bg-background text-foreground", className), ...props, children: children }) }));
26
+ });
27
+ ChatLayoutRoot.displayName = "ChatLayout.Root";
28
+ const ChatLayoutHeader = React.forwardRef(({ className, children, ...props }, ref) => {
29
+ return (_jsx("div", { ref: ref, className: cn("relative z-10 border-b border-border bg-card shrink-0", className), ...props, children: children }));
30
+ });
31
+ ChatLayoutHeader.displayName = "ChatLayout.Header";
32
+ const ChatLayoutMain = React.forwardRef(({ className, children, ...props }, ref) => {
33
+ return (_jsx("div", { ref: ref, className: cn("flex flex-1 flex-col overflow-hidden", className), ...props, children: children }));
34
+ });
35
+ ChatLayoutMain.displayName = "ChatLayout.Main";
36
+ const ChatLayoutBody = React.forwardRef(({ showToaster = true, className, children, ...props }, ref) => {
37
+ return (_jsxs("div", { ref: ref, className: cn("relative flex flex-1 flex-col overflow-hidden", className), ...props, children: [children, showToaster && _jsx(Toaster, {})] }));
38
+ });
39
+ ChatLayoutBody.displayName = "ChatLayout.Body";
40
+ const ChatLayoutMessages = React.forwardRef(({ className, children, onScrollChange, showScrollToBottom = true, ...props }, ref) => {
41
+ const [showScrollButton, setShowScrollButton] = React.useState(false);
42
+ const scrollContainerRef = React.useRef(null);
43
+ // Merge refs
44
+ React.useImperativeHandle(ref, () => scrollContainerRef.current);
45
+ // Check if user is at bottom of scroll
46
+ const checkScrollPosition = React.useCallback(() => {
47
+ const container = scrollContainerRef.current;
48
+ if (!container)
49
+ return;
50
+ const { scrollTop, scrollHeight, clientHeight } = container;
51
+ const distanceFromBottom = scrollHeight - scrollTop - clientHeight;
52
+ const isAtBottom = distanceFromBottom < 100; // 100px threshold
53
+ setShowScrollButton(!isAtBottom && showScrollToBottom);
54
+ onScrollChange?.(isAtBottom);
55
+ }, [onScrollChange, showScrollToBottom]);
56
+ // Handle scroll events
57
+ const handleScroll = React.useCallback(() => {
58
+ checkScrollPosition();
59
+ }, [checkScrollPosition]);
60
+ // Scroll to bottom function
61
+ const scrollToBottom = React.useCallback(() => {
62
+ const container = scrollContainerRef.current;
63
+ if (!container)
64
+ return;
65
+ container.scrollTo({
66
+ top: container.scrollHeight,
67
+ behavior: "smooth",
68
+ });
69
+ }, []);
70
+ // Check scroll position on mount and when children change
71
+ React.useEffect(() => {
72
+ checkScrollPosition();
73
+ }, [checkScrollPosition]);
74
+ return (_jsxs("div", { className: "relative flex-1 overflow-hidden", children: [_jsx("div", { ref: scrollContainerRef, className: cn("h-full overflow-y-auto", className), onScroll: handleScroll, ...props, children: children }), showScrollButton && (_jsx("button", { type: "button", onClick: scrollToBottom, className: cn("absolute bottom-4 left-1/2 -translate-x-1/2 z-10", "flex items-center justify-center p-2 rounded-full", "bg-card border border-border shadow-lg", "text-foreground", "hover:bg-accent hover:text-accent-foreground", "transition-all duration-200 ease-in-out", "animate-in fade-in slide-in-from-bottom-2"), "aria-label": "Scroll to bottom", children: _jsx(ArrowDown, { className: "h-4 w-4" }) }))] }));
75
+ });
76
+ ChatLayoutMessages.displayName = "ChatLayout.Messages";
77
+ const ChatLayoutFooter = React.forwardRef(({ className, children, ...props }, ref) => {
78
+ return (_jsx("div", { ref: ref, className: cn("bg-linear-to-t from-background to-transparent px-4 pb-4", className), ...props, children: children }));
79
+ });
80
+ ChatLayoutFooter.displayName = "ChatLayout.Footer";
81
+ const ChatLayoutSidebar = React.forwardRef(({ className, children, ...props }, ref) => {
82
+ const { sidebarOpen } = useChatLayoutContext();
83
+ if (!sidebarOpen)
84
+ return null;
85
+ return (_jsx("div", { ref: ref, className: cn("border-r border-border bg-card w-64 overflow-y-auto", className), ...props, children: children }));
86
+ });
87
+ ChatLayoutSidebar.displayName = "ChatLayout.Sidebar";
88
+ const ChatLayoutAside = React.forwardRef(({ breakpoint = "lg", className, children, ...props }, ref) => {
89
+ const { panelSize } = useChatLayoutContext();
90
+ // Hidden state - don't render
91
+ if (panelSize === "hidden")
92
+ return null;
93
+ return (_jsx("div", { ref: ref, className: cn(
94
+ // Hidden by default, visible at breakpoint
95
+ "hidden border-l border-border bg-card overflow-y-auto transition-all duration-300",
96
+ // Breakpoint visibility
97
+ breakpoint === "md" && "md:block", breakpoint === "lg" && "lg:block", breakpoint === "xl" && "xl:block", breakpoint === "2xl" && "2xl:block",
98
+ // Size variants
99
+ panelSize === "small" && "w-80", panelSize === "large" && "w-lg", className), ...props, children: children }));
100
+ });
101
+ ChatLayoutAside.displayName = "ChatLayout.Aside";
102
+ /* -------------------------------------------------------------------------------------------------
103
+ * Exports
104
+ * -----------------------------------------------------------------------------------------------*/
105
+ 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, };