@townco/ui 0.1.0 → 0.1.6

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 (125) hide show
  1. package/dist/core/hooks/use-chat-input.d.ts +17 -17
  2. package/dist/core/hooks/use-chat-input.js +64 -55
  3. package/dist/core/hooks/use-chat-messages.d.ts +11 -11
  4. package/dist/core/hooks/use-chat-messages.js +121 -114
  5. package/dist/core/hooks/use-chat-session.d.ts +5 -5
  6. package/dist/core/hooks/use-chat-session.js +78 -80
  7. package/dist/core/hooks/use-media-query.d.ts +5 -5
  8. package/dist/core/hooks/use-media-query.js +38 -38
  9. package/dist/core/index.d.ts +1 -1
  10. package/dist/core/index.js +1 -1
  11. package/dist/core/schemas/chat.d.ts +83 -56
  12. package/dist/core/schemas/chat.js +27 -25
  13. package/dist/core/store/chat-store.d.ts +28 -22
  14. package/dist/core/store/chat-store.js +59 -50
  15. package/dist/gui/components/Button.d.ts +23 -7
  16. package/dist/gui/components/Button.js +40 -27
  17. package/dist/gui/components/Card.d.ts +26 -7
  18. package/dist/gui/components/Card.js +54 -8
  19. package/dist/gui/components/ChatHeader.d.ts +58 -31
  20. package/dist/gui/components/ChatHeader.js +171 -66
  21. package/dist/gui/components/ChatInput.d.ts +58 -36
  22. package/dist/gui/components/ChatInput.js +191 -121
  23. package/dist/gui/components/ChatInterface.d.ts +9 -6
  24. package/dist/gui/components/ChatInterface.js +162 -90
  25. package/dist/gui/components/ChatLayout.d.ts +71 -41
  26. package/dist/gui/components/ChatLayout.js +214 -87
  27. package/dist/gui/components/ChatPanelTabContent.d.ts +18 -9
  28. package/dist/gui/components/ChatPanelTabContent.js +88 -10
  29. package/dist/gui/components/ChatPreview.d.ts +9 -6
  30. package/dist/gui/components/ChatPreview.js +212 -162
  31. package/dist/gui/components/ChatSecondaryPanel.d.ts +14 -11
  32. package/dist/gui/components/ChatSecondaryPanel.js +115 -38
  33. package/dist/gui/components/ChatSidebar.d.ts +26 -13
  34. package/dist/gui/components/ChatSidebar.js +48 -14
  35. package/dist/gui/components/ChatStatus.d.ts +4 -2
  36. package/dist/gui/components/ChatStatus.js +45 -34
  37. package/dist/gui/components/ChatView.d.ts +5 -3
  38. package/dist/gui/components/ChatView.js +38 -9
  39. package/dist/gui/components/ConfigPanel.d.ts +16 -12
  40. package/dist/gui/components/ConfigPanel.js +218 -41
  41. package/dist/gui/components/Conversation.d.ts +17 -14
  42. package/dist/gui/components/Conversation.js +143 -83
  43. package/dist/gui/components/Dialog.d.ts +57 -11
  44. package/dist/gui/components/Dialog.js +84 -8
  45. package/dist/gui/components/DropdownMenu.d.ts +101 -20
  46. package/dist/gui/components/DropdownMenu.js +161 -14
  47. package/dist/gui/components/HeightTransition.d.ts +12 -7
  48. package/dist/gui/components/HeightTransition.js +88 -77
  49. package/dist/gui/components/Input.d.ts +13 -6
  50. package/dist/gui/components/Input.js +27 -16
  51. package/dist/gui/components/InputBox.d.ts +19 -12
  52. package/dist/gui/components/InputBox.js +86 -14
  53. package/dist/gui/components/Label.d.ts +7 -1
  54. package/dist/gui/components/Label.js +12 -2
  55. package/dist/gui/components/MarkdownRenderer.d.ts +6 -4
  56. package/dist/gui/components/MarkdownRenderer.js +178 -81
  57. package/dist/gui/components/Message.d.ts +25 -18
  58. package/dist/gui/components/Message.js +44 -23
  59. package/dist/gui/components/MessageContent.d.ts +29 -22
  60. package/dist/gui/components/MessageContent.js +157 -85
  61. package/dist/gui/components/PlaygroundLayout.d.ts +9 -5
  62. package/dist/gui/components/PlaygroundLayout.js +43 -12
  63. package/dist/gui/components/Reasoning.d.ts +30 -24
  64. package/dist/gui/components/Reasoning.js +187 -60
  65. package/dist/gui/components/Response.d.ts +11 -9
  66. package/dist/gui/components/Response.js +229 -90
  67. package/dist/gui/components/Select.d.ts +69 -10
  68. package/dist/gui/components/Select.js +118 -12
  69. package/dist/gui/components/Sonner.d.ts +3 -1
  70. package/dist/gui/components/Sonner.js +29 -18
  71. package/dist/gui/components/StatusBar.d.ts +9 -5
  72. package/dist/gui/components/StatusBar.js +56 -9
  73. package/dist/gui/components/Tabs.d.ts +24 -4
  74. package/dist/gui/components/Tabs.js +32 -4
  75. package/dist/gui/components/Task.d.ts +28 -24
  76. package/dist/gui/components/Task.js +164 -31
  77. package/dist/gui/components/Textarea.d.ts +15 -7
  78. package/dist/gui/components/Textarea.js +63 -46
  79. package/dist/gui/components/ThinkingBlock.d.ts +20 -10
  80. package/dist/gui/components/ThinkingBlock.js +134 -35
  81. package/dist/gui/components/TodoList.d.ts +12 -10
  82. package/dist/gui/components/TodoList.js +22 -7
  83. package/dist/gui/components/TodoListItem.d.ts +9 -6
  84. package/dist/gui/components/TodoListItem.js +18 -4
  85. package/dist/gui/components/index.d.ts +59 -8
  86. package/dist/gui/components/index.js +42 -8
  87. package/dist/gui/lib/utils.js +1 -1
  88. package/dist/index.d.ts +1 -1
  89. package/dist/index.js +1 -1
  90. package/dist/index.test.js +0 -1
  91. package/dist/sdk/client/acp-client.d.ts +88 -76
  92. package/dist/sdk/client/acp-client.js +215 -217
  93. package/dist/sdk/index.d.ts +1 -1
  94. package/dist/sdk/index.js +1 -1
  95. package/dist/sdk/schemas/agent.d.ts +111 -64
  96. package/dist/sdk/schemas/agent.js +24 -24
  97. package/dist/sdk/schemas/message.d.ts +245 -147
  98. package/dist/sdk/schemas/message.js +40 -40
  99. package/dist/sdk/schemas/session.d.ts +219 -135
  100. package/dist/sdk/schemas/session.js +27 -27
  101. package/dist/sdk/transports/http.d.ts +55 -55
  102. package/dist/sdk/transports/http.js +472 -469
  103. package/dist/sdk/transports/stdio.d.ts +20 -20
  104. package/dist/sdk/transports/stdio.js +289 -286
  105. package/dist/sdk/transports/types.d.ts +42 -42
  106. package/dist/sdk/transports/websocket.d.ts +12 -12
  107. package/dist/sdk/transports/websocket.js +52 -46
  108. package/dist/tui/components/ChatView.d.ts +4 -2
  109. package/dist/tui/components/ChatView.js +51 -18
  110. package/dist/tui/components/GameOfLife.js +64 -35
  111. package/dist/tui/components/InputBox.d.ts +18 -11
  112. package/dist/tui/components/InputBox.js +70 -10
  113. package/dist/tui/components/MessageList.d.ts +4 -2
  114. package/dist/tui/components/MessageList.js +37 -10
  115. package/dist/tui/components/MultiSelect.d.ts +15 -9
  116. package/dist/tui/components/MultiSelect.js +116 -69
  117. package/dist/tui/components/ReadlineInput.d.ts +12 -6
  118. package/dist/tui/components/ReadlineInput.js +252 -237
  119. package/dist/tui/components/SingleSelect.d.ts +15 -9
  120. package/dist/tui/components/SingleSelect.js +84 -43
  121. package/dist/tui/components/StatusBar.d.ts +11 -6
  122. package/dist/tui/components/StatusBar.js +102 -67
  123. package/dist/tui/index.d.ts +1 -1
  124. package/dist/tui/index.js +1 -1
  125. package/package.json +2 -3
@@ -1,164 +1,214 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
1
  import { useEffect, useRef, useState } from "react";
3
- export function ChatPreview({ config, status, iframeSrc = "/chat-standalone", }) {
4
- const iframeRef = useRef(null);
5
- const containerRef = useRef(null);
6
- const [dimensions, setDimensions] = useState({
7
- width: 800,
8
- height: 600,
9
- });
10
- const [isResizing, setIsResizing] = useState({
11
- horizontal: false,
12
- vertical: false,
13
- });
14
- const resizeStartRef = useRef({ x: 0, y: 0, width: 0, height: 0 });
15
- const isResizingRef = useRef({
16
- horizontal: false,
17
- vertical: false,
18
- });
19
- const resizeHandlersRef = useRef({ mouseMove: null, mouseUp: null, mouseLeave: null });
20
- const sendConfigToIframe = (configToSend) => {
21
- const iframe = iframeRef.current;
22
- if (iframe?.contentWindow) {
23
- iframe.contentWindow.postMessage({
24
- type: "CONFIG_UPDATE",
25
- config: configToSend,
26
- }, "*");
27
- }
28
- };
29
- const sendStatusToIframe = (statusToSend) => {
30
- const iframe = iframeRef.current;
31
- if (iframe?.contentWindow) {
32
- iframe.contentWindow.postMessage({
33
- type: "STATUS_UPDATE",
34
- status: statusToSend,
35
- }, "*");
36
- }
37
- };
38
- useEffect(() => {
39
- const iframe = iframeRef.current;
40
- if (!iframe)
41
- return;
42
- const handleMessage = (event) => {
43
- if (event.data && event.data.type === "REQUEST_CONFIG") {
44
- sendConfigToIframe(config);
45
- }
46
- };
47
- window.addEventListener("message", handleMessage);
48
- // Send initial config and status when iframe loads
49
- const handleLoad = () => {
50
- sendConfigToIframe(config);
51
- sendStatusToIframe(status);
52
- };
53
- iframe.addEventListener("load", handleLoad);
54
- return () => {
55
- window.removeEventListener("message", handleMessage);
56
- iframe.removeEventListener("load", handleLoad);
57
- };
58
- }, [config, status]);
59
- // Update iframe when config changes (after initial load)
60
- useEffect(() => {
61
- const iframe = iframeRef.current;
62
- // Only send if iframe is already loaded
63
- if (iframe?.contentWindow &&
64
- iframe.contentDocument?.readyState === "complete") {
65
- sendConfigToIframe(config);
66
- }
67
- }, [config]);
68
- // Update iframe when status changes (after initial load)
69
- useEffect(() => {
70
- const iframe = iframeRef.current;
71
- // Only send if iframe is already loaded
72
- if (iframe?.contentWindow &&
73
- iframe.contentDocument?.readyState === "complete") {
74
- sendStatusToIframe(status);
75
- }
76
- }, [status]);
77
- // Sync ref with state for UI updates
78
- useEffect(() => {
79
- isResizingRef.current = isResizing;
80
- }, [isResizing]);
81
- // Cleanup on unmount
82
- useEffect(() => {
83
- return () => {
84
- stopResizing();
85
- };
86
- }, []);
87
- const stopResizing = () => {
88
- const handlers = resizeHandlersRef.current;
89
- if (handlers.mouseMove) {
90
- window.removeEventListener("mousemove", handlers.mouseMove);
91
- }
92
- if (handlers.mouseUp) {
93
- window.removeEventListener("mouseup", handlers.mouseUp, true);
94
- }
95
- if (handlers.mouseLeave) {
96
- document.removeEventListener("mouseleave", handlers.mouseLeave);
97
- }
98
- setIsResizing({ horizontal: false, vertical: false });
99
- isResizingRef.current = { horizontal: false, vertical: false };
100
- resizeHandlersRef.current = {
101
- mouseMove: null,
102
- mouseUp: null,
103
- mouseLeave: null,
104
- };
105
- };
106
- const handleResizeStart = (direction, e) => {
107
- e.preventDefault();
108
- e.stopPropagation();
109
- // Clean up any existing listeners first
110
- stopResizing();
111
- const resizeState = direction === "horizontal"
112
- ? { horizontal: true, vertical: false }
113
- : { horizontal: false, vertical: true };
114
- setIsResizing(resizeState);
115
- isResizingRef.current = resizeState;
116
- resizeStartRef.current = {
117
- x: e.clientX,
118
- y: e.clientY,
119
- width: dimensions.width,
120
- height: dimensions.height,
121
- };
122
- const handleMouseMove = (e) => {
123
- if (!isResizingRef.current.horizontal &&
124
- !isResizingRef.current.vertical) {
125
- return;
126
- }
127
- const deltaX = e.clientX - resizeStartRef.current.x;
128
- const deltaY = e.clientY - resizeStartRef.current.y;
129
- let newWidth = resizeStartRef.current.width;
130
- let newHeight = resizeStartRef.current.height;
131
- if (isResizingRef.current.horizontal) {
132
- newWidth = Math.max(400, Math.min(1200, resizeStartRef.current.width + deltaX));
133
- }
134
- if (isResizingRef.current.vertical) {
135
- newHeight = Math.max(300, Math.min(900, resizeStartRef.current.height + deltaY));
136
- }
137
- setDimensions({ width: newWidth, height: newHeight });
138
- };
139
- const handleMouseUp = (e) => {
140
- e.preventDefault();
141
- e.stopPropagation();
142
- stopResizing();
143
- };
144
- const handleMouseLeave = () => {
145
- // If mouse leaves window during resize, stop resizing
146
- stopResizing();
147
- };
148
- // Store handlers for cleanup
149
- resizeHandlersRef.current = {
150
- mouseMove: handleMouseMove,
151
- mouseUp: handleMouseUp,
152
- mouseLeave: handleMouseLeave,
153
- };
154
- // Use capture phase to ensure we catch events even if they bubble
155
- window.addEventListener("mousemove", handleMouseMove);
156
- window.addEventListener("mouseup", handleMouseUp, { capture: true });
157
- document.addEventListener("mouseleave", handleMouseLeave);
158
- };
159
- return (_jsxs("div", { ref: containerRef, className: "relative rounded-xl overflow-visible bg-[var(--color-surface)] shadow-lg min-w-[400px] min-h-[300px]", style: {
160
- width: `${dimensions.width}px`,
161
- height: `${dimensions.height}px`,
162
- }, children: [_jsx("iframe", { ref: iframeRef, src: iframeSrc, className: "w-full h-full rounded-xl border-1 border-[var(--color-border)] block", title: "Chat Preview" }), _jsx("div", { className: "absolute -right-4 top-1/2 -translate-y-1/2 w-1.5 h-10 rounded-full bg-black/20 cursor-ew-resize hover:opacity-80 transition-opacity", onMouseDown: (e) => handleResizeStart("horizontal", e) }), _jsx("div", { className: "absolute -bottom-4 left-1/2 -translate-x-1/2 w-10 h-1.5 rounded-full bg-black/20 cursor-ns-resize hover:opacity-80 transition-opacity", onMouseDown: (e) => handleResizeStart("vertical", e) })] }));
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ export function ChatPreview({
4
+ config,
5
+ status,
6
+ iframeSrc = "/chat-standalone",
7
+ }) {
8
+ const iframeRef = useRef(null);
9
+ const containerRef = useRef(null);
10
+ const [dimensions, setDimensions] = useState({
11
+ width: 800,
12
+ height: 600,
13
+ });
14
+ const [isResizing, setIsResizing] = useState({
15
+ horizontal: false,
16
+ vertical: false,
17
+ });
18
+ const resizeStartRef = useRef({ x: 0, y: 0, width: 0, height: 0 });
19
+ const isResizingRef = useRef({
20
+ horizontal: false,
21
+ vertical: false,
22
+ });
23
+ const resizeHandlersRef = useRef({
24
+ mouseMove: null,
25
+ mouseUp: null,
26
+ mouseLeave: null,
27
+ });
28
+ const sendConfigToIframe = (configToSend) => {
29
+ const iframe = iframeRef.current;
30
+ if (iframe?.contentWindow) {
31
+ iframe.contentWindow.postMessage(
32
+ {
33
+ type: "CONFIG_UPDATE",
34
+ config: configToSend,
35
+ },
36
+ "*",
37
+ );
38
+ }
39
+ };
40
+ const sendStatusToIframe = (statusToSend) => {
41
+ const iframe = iframeRef.current;
42
+ if (iframe?.contentWindow) {
43
+ iframe.contentWindow.postMessage(
44
+ {
45
+ type: "STATUS_UPDATE",
46
+ status: statusToSend,
47
+ },
48
+ "*",
49
+ );
50
+ }
51
+ };
52
+ useEffect(() => {
53
+ const iframe = iframeRef.current;
54
+ if (!iframe) return;
55
+ const handleMessage = (event) => {
56
+ if (event.data && event.data.type === "REQUEST_CONFIG") {
57
+ sendConfigToIframe(config);
58
+ }
59
+ };
60
+ window.addEventListener("message", handleMessage);
61
+ // Send initial config and status when iframe loads
62
+ const handleLoad = () => {
63
+ sendConfigToIframe(config);
64
+ sendStatusToIframe(status);
65
+ };
66
+ iframe.addEventListener("load", handleLoad);
67
+ return () => {
68
+ window.removeEventListener("message", handleMessage);
69
+ iframe.removeEventListener("load", handleLoad);
70
+ };
71
+ }, [config, status]);
72
+ // Update iframe when config changes (after initial load)
73
+ useEffect(() => {
74
+ const iframe = iframeRef.current;
75
+ // Only send if iframe is already loaded
76
+ if (
77
+ iframe?.contentWindow &&
78
+ iframe.contentDocument?.readyState === "complete"
79
+ ) {
80
+ sendConfigToIframe(config);
81
+ }
82
+ }, [config]);
83
+ // Update iframe when status changes (after initial load)
84
+ useEffect(() => {
85
+ const iframe = iframeRef.current;
86
+ // Only send if iframe is already loaded
87
+ if (
88
+ iframe?.contentWindow &&
89
+ iframe.contentDocument?.readyState === "complete"
90
+ ) {
91
+ sendStatusToIframe(status);
92
+ }
93
+ }, [status]);
94
+ // Sync ref with state for UI updates
95
+ useEffect(() => {
96
+ isResizingRef.current = isResizing;
97
+ }, [isResizing]);
98
+ // Cleanup on unmount
99
+ useEffect(() => {
100
+ return () => {
101
+ stopResizing();
102
+ };
103
+ }, []);
104
+ const stopResizing = () => {
105
+ const handlers = resizeHandlersRef.current;
106
+ if (handlers.mouseMove) {
107
+ window.removeEventListener("mousemove", handlers.mouseMove);
108
+ }
109
+ if (handlers.mouseUp) {
110
+ window.removeEventListener("mouseup", handlers.mouseUp, true);
111
+ }
112
+ if (handlers.mouseLeave) {
113
+ document.removeEventListener("mouseleave", handlers.mouseLeave);
114
+ }
115
+ setIsResizing({ horizontal: false, vertical: false });
116
+ isResizingRef.current = { horizontal: false, vertical: false };
117
+ resizeHandlersRef.current = {
118
+ mouseMove: null,
119
+ mouseUp: null,
120
+ mouseLeave: null,
121
+ };
122
+ };
123
+ const handleResizeStart = (direction, e) => {
124
+ e.preventDefault();
125
+ e.stopPropagation();
126
+ // Clean up any existing listeners first
127
+ stopResizing();
128
+ const resizeState =
129
+ direction === "horizontal"
130
+ ? { horizontal: true, vertical: false }
131
+ : { horizontal: false, vertical: true };
132
+ setIsResizing(resizeState);
133
+ isResizingRef.current = resizeState;
134
+ resizeStartRef.current = {
135
+ x: e.clientX,
136
+ y: e.clientY,
137
+ width: dimensions.width,
138
+ height: dimensions.height,
139
+ };
140
+ const handleMouseMove = (e) => {
141
+ if (
142
+ !isResizingRef.current.horizontal &&
143
+ !isResizingRef.current.vertical
144
+ ) {
145
+ return;
146
+ }
147
+ const deltaX = e.clientX - resizeStartRef.current.x;
148
+ const deltaY = e.clientY - resizeStartRef.current.y;
149
+ let newWidth = resizeStartRef.current.width;
150
+ let newHeight = resizeStartRef.current.height;
151
+ if (isResizingRef.current.horizontal) {
152
+ newWidth = Math.max(
153
+ 400,
154
+ Math.min(1200, resizeStartRef.current.width + deltaX),
155
+ );
156
+ }
157
+ if (isResizingRef.current.vertical) {
158
+ newHeight = Math.max(
159
+ 300,
160
+ Math.min(900, resizeStartRef.current.height + deltaY),
161
+ );
162
+ }
163
+ setDimensions({ width: newWidth, height: newHeight });
164
+ };
165
+ const handleMouseUp = (e) => {
166
+ e.preventDefault();
167
+ e.stopPropagation();
168
+ stopResizing();
169
+ };
170
+ const handleMouseLeave = () => {
171
+ // If mouse leaves window during resize, stop resizing
172
+ stopResizing();
173
+ };
174
+ // Store handlers for cleanup
175
+ resizeHandlersRef.current = {
176
+ mouseMove: handleMouseMove,
177
+ mouseUp: handleMouseUp,
178
+ mouseLeave: handleMouseLeave,
179
+ };
180
+ // Use capture phase to ensure we catch events even if they bubble
181
+ window.addEventListener("mousemove", handleMouseMove);
182
+ window.addEventListener("mouseup", handleMouseUp, { capture: true });
183
+ document.addEventListener("mouseleave", handleMouseLeave);
184
+ };
185
+ return _jsxs("div", {
186
+ ref: containerRef,
187
+ className:
188
+ "relative rounded-xl overflow-visible bg-[var(--color-surface)] shadow-lg min-w-[400px] min-h-[300px]",
189
+ style: {
190
+ width: `${dimensions.width}px`,
191
+ height: `${dimensions.height}px`,
192
+ },
193
+ children: [
194
+ _jsx("iframe", {
195
+ ref: iframeRef,
196
+ src: iframeSrc,
197
+ className:
198
+ "w-full h-full rounded-xl border-1 border-[var(--color-border)] block",
199
+ title: "Chat Preview",
200
+ }),
201
+ _jsx("div", {
202
+ className:
203
+ "absolute -right-4 top-1/2 -translate-y-1/2 w-1.5 h-10 rounded-full bg-black/20 cursor-ew-resize hover:opacity-80 transition-opacity",
204
+ onMouseDown: (e) => handleResizeStart("horizontal", e),
205
+ }),
206
+ _jsx("div", {
207
+ className:
208
+ "absolute -bottom-4 left-1/2 -translate-x-1/2 w-10 h-1.5 rounded-full bg-black/20 cursor-ns-resize hover:opacity-80 transition-opacity",
209
+ onMouseDown: (e) => handleResizeStart("vertical", e),
210
+ }),
211
+ ],
212
+ });
163
213
  }
164
- //# sourceMappingURL=ChatPreview.js.map
214
+ //# sourceMappingURL=ChatPreview.js.map
@@ -6,15 +6,18 @@ import type { TodoItem } from "./TodoListItem.js";
6
6
  * 1. Hook-based: Pass `client` prop (future support when todos are in store)
7
7
  * 2. Prop-based: Pass `todos` prop directly
8
8
  */
9
- export interface ChatSecondaryPanelProps extends React.HTMLAttributes<HTMLDivElement> {
10
- /**
11
- * ACP Client for hook-based todo fetching (future support)
12
- */
13
- client?: AcpClient | null;
14
- /**
15
- * Todos to display (prop-based pattern)
16
- * Either client or todos should be provided
17
- */
18
- todos?: TodoItem[];
9
+ export interface ChatSecondaryPanelProps
10
+ extends React.HTMLAttributes<HTMLDivElement> {
11
+ /**
12
+ * ACP Client for hook-based todo fetching (future support)
13
+ */
14
+ client?: AcpClient | null;
15
+ /**
16
+ * Todos to display (prop-based pattern)
17
+ * Either client or todos should be provided
18
+ */
19
+ todos?: TodoItem[];
19
20
  }
20
- export declare const ChatSecondaryPanel: React.ForwardRefExoticComponent<ChatSecondaryPanelProps & React.RefAttributes<HTMLDivElement>>;
21
+ export declare const ChatSecondaryPanel: React.ForwardRefExoticComponent<
22
+ ChatSecondaryPanelProps & React.RefAttributes<HTMLDivElement>
23
+ >;
@@ -1,44 +1,121 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
1
  import * as React from "react";
3
2
  import { useEffect, useRef, useState } from "react";
3
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
4
  import { cn } from "../lib/utils.js";
5
5
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "./Tabs.js";
6
6
  import { TodoList } from "./TodoList.js";
7
- export const ChatSecondaryPanel = React.forwardRef(({ client, todos, className, ...props }, ref) => {
8
- // For now, just use prop-based todos
9
- // Future: Add hook to get todos from store when available
10
- const todosToDisplay = todos || [];
11
- const [activeTab, setActiveTab] = useState("todo");
12
- const containerRef = useRef(null);
13
- const activeTabElementRef = useRef(null);
14
- useEffect(() => {
15
- const updateClipPath = () => {
16
- const container = containerRef.current;
17
- if (activeTab && container) {
18
- const activeTabElement = activeTabElementRef.current;
19
- if (activeTabElement) {
20
- const containerRect = container.getBoundingClientRect();
21
- const tabRect = activeTabElement.getBoundingClientRect();
22
- const offsetLeft = tabRect.left - containerRect.left;
23
- const offsetWidth = tabRect.width;
24
- const clipLeftPercent = (offsetLeft / containerRect.width) * 100;
25
- const clipRightPercent = 100 - ((offsetLeft + offsetWidth) / containerRect.width) * 100;
26
- container.style.clipPath = `inset(0 ${clipRightPercent.toFixed(2)}% 0 ${clipLeftPercent.toFixed(2)}% round 999px)`;
27
- }
28
- }
29
- };
30
- // Small delay to ensure DOM is ready
31
- const timeoutId = setTimeout(updateClipPath, 0);
32
- return () => clearTimeout(timeoutId);
33
- }, [activeTab]);
34
- const tabs = [
35
- { id: "todo", label: "To-Do List" },
36
- { id: "files", label: "Files" },
37
- { id: "database", label: "Database" },
38
- ];
39
- return (_jsx("div", { ref: ref, className: cn("select-none", className), ...props, children: _jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "w-full", children: [_jsxs("div", { className: "relative mb-4 border-border", children: [_jsx(TabsList, { className: "bg-transparent p-0 h-auto rounded-none w-full border-none", children: tabs.map((tab) => (_jsx(TabsTrigger, { value: tab.id, className: "px-3 py-1 text-sm font-[var(--font-family)] font-medium rounded-none text-foreground opacity-60 data-[state=active]:opacity-100 data-[state=active]:bg-transparent data-[state=active]:shadow-none", children: tab.label }, tab.id))) }), _jsx("div", { ref: containerRef, className: "absolute top-0 left-0 w-full overflow-hidden z-10 pointer-events-none", style: {
40
- clipPath: "inset(0 100% 0 0% round 999px)",
41
- transition: "clip-path 0.25s ease-out",
42
- }, children: _jsx(TabsList, { className: "bg-secondary p-0 h-auto rounded-none w-full border-none", children: tabs.map((tab) => (_jsx(TabsTrigger, { value: tab.id, ref: activeTab === tab.id ? activeTabElementRef : null, className: "px-3 py-1 text-sm font-[var(--font-family)] font-medium rounded-none text-primary bg-transparent data-[state=active]:shadow-none shadow-none", tabIndex: -1, children: tab.label }, tab.id))) }) })] }), _jsx(TabsContent, { value: "todo", children: _jsx(TodoList, { todos: todosToDisplay }) }), _jsx(TabsContent, { value: "files", children: _jsx("div", { className: "text-sm text-foreground opacity-60 italic", children: "Files tab coming soon..." }) }), _jsx(TabsContent, { value: "database", children: _jsx("div", { className: "text-sm text-foreground opacity-60 italic", children: "Database tab coming soon..." }) })] }) }));
43
- });
7
+ export const ChatSecondaryPanel = React.forwardRef(
8
+ ({ client, todos, className, ...props }, ref) => {
9
+ // For now, just use prop-based todos
10
+ // Future: Add hook to get todos from store when available
11
+ const todosToDisplay = todos || [];
12
+ const [activeTab, setActiveTab] = useState("todo");
13
+ const containerRef = useRef(null);
14
+ const activeTabElementRef = useRef(null);
15
+ useEffect(() => {
16
+ const updateClipPath = () => {
17
+ const container = containerRef.current;
18
+ if (activeTab && container) {
19
+ const activeTabElement = activeTabElementRef.current;
20
+ if (activeTabElement) {
21
+ const containerRect = container.getBoundingClientRect();
22
+ const tabRect = activeTabElement.getBoundingClientRect();
23
+ const offsetLeft = tabRect.left - containerRect.left;
24
+ const offsetWidth = tabRect.width;
25
+ const clipLeftPercent = (offsetLeft / containerRect.width) * 100;
26
+ const clipRightPercent =
27
+ 100 - ((offsetLeft + offsetWidth) / containerRect.width) * 100;
28
+ container.style.clipPath = `inset(0 ${clipRightPercent.toFixed(2)}% 0 ${clipLeftPercent.toFixed(2)}% round 999px)`;
29
+ }
30
+ }
31
+ };
32
+ // Small delay to ensure DOM is ready
33
+ const timeoutId = setTimeout(updateClipPath, 0);
34
+ return () => clearTimeout(timeoutId);
35
+ }, [activeTab]);
36
+ const tabs = [
37
+ { id: "todo", label: "To-Do List" },
38
+ { id: "files", label: "Files" },
39
+ { id: "database", label: "Database" },
40
+ ];
41
+ return _jsx("div", {
42
+ ref: ref,
43
+ className: cn("select-none", className),
44
+ ...props,
45
+ children: _jsxs(Tabs, {
46
+ value: activeTab,
47
+ onValueChange: setActiveTab,
48
+ className: "w-full",
49
+ children: [
50
+ _jsxs("div", {
51
+ className: "relative mb-4 border-border",
52
+ children: [
53
+ _jsx(TabsList, {
54
+ className:
55
+ "bg-transparent p-0 h-auto rounded-none w-full border-none",
56
+ children: tabs.map((tab) =>
57
+ _jsx(
58
+ TabsTrigger,
59
+ {
60
+ value: tab.id,
61
+ className:
62
+ "px-3 py-1 text-sm font-[var(--font-family)] font-medium rounded-none text-foreground opacity-60 data-[state=active]:opacity-100 data-[state=active]:bg-transparent data-[state=active]:shadow-none",
63
+ children: tab.label,
64
+ },
65
+ tab.id,
66
+ ),
67
+ ),
68
+ }),
69
+ _jsx("div", {
70
+ ref: containerRef,
71
+ className:
72
+ "absolute top-0 left-0 w-full overflow-hidden z-10 pointer-events-none",
73
+ style: {
74
+ clipPath: "inset(0 100% 0 0% round 999px)",
75
+ transition: "clip-path 0.25s ease-out",
76
+ },
77
+ children: _jsx(TabsList, {
78
+ className:
79
+ "bg-secondary p-0 h-auto rounded-none w-full border-none",
80
+ children: tabs.map((tab) =>
81
+ _jsx(
82
+ TabsTrigger,
83
+ {
84
+ value: tab.id,
85
+ ref: activeTab === tab.id ? activeTabElementRef : null,
86
+ className:
87
+ "px-3 py-1 text-sm font-[var(--font-family)] font-medium rounded-none text-primary bg-transparent data-[state=active]:shadow-none shadow-none",
88
+ tabIndex: -1,
89
+ children: tab.label,
90
+ },
91
+ tab.id,
92
+ ),
93
+ ),
94
+ }),
95
+ }),
96
+ ],
97
+ }),
98
+ _jsx(TabsContent, {
99
+ value: "todo",
100
+ children: _jsx(TodoList, { todos: todosToDisplay }),
101
+ }),
102
+ _jsx(TabsContent, {
103
+ value: "files",
104
+ children: _jsx("div", {
105
+ className: "text-sm text-foreground opacity-60 italic",
106
+ children: "Files tab coming soon...",
107
+ }),
108
+ }),
109
+ _jsx(TabsContent, {
110
+ value: "database",
111
+ children: _jsx("div", {
112
+ className: "text-sm text-foreground opacity-60 italic",
113
+ children: "Database tab coming soon...",
114
+ }),
115
+ }),
116
+ ],
117
+ }),
118
+ });
119
+ },
120
+ );
44
121
  ChatSecondaryPanel.displayName = "ChatSecondaryPanel";
@@ -1,14 +1,27 @@
1
1
  import * as React from "react";
2
- export interface ChatSidebarRootProps extends React.HTMLAttributes<HTMLDivElement> {
3
- }
4
- declare const ChatSidebarRoot: React.ForwardRefExoticComponent<ChatSidebarRootProps & React.RefAttributes<HTMLDivElement>>;
5
- export interface ChatSidebarHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
6
- }
7
- declare const ChatSidebarHeader: React.ForwardRefExoticComponent<ChatSidebarHeaderProps & React.RefAttributes<HTMLDivElement>>;
8
- export interface ChatSidebarContentProps extends React.HTMLAttributes<HTMLDivElement> {
9
- }
10
- declare const ChatSidebarContent: React.ForwardRefExoticComponent<ChatSidebarContentProps & React.RefAttributes<HTMLDivElement>>;
11
- export interface ChatSidebarFooterProps extends React.HTMLAttributes<HTMLDivElement> {
12
- }
13
- declare const ChatSidebarFooter: React.ForwardRefExoticComponent<ChatSidebarFooterProps & React.RefAttributes<HTMLDivElement>>;
14
- export { ChatSidebarRoot as Root, ChatSidebarHeader as Header, ChatSidebarContent as Content, ChatSidebarFooter as Footer, };
2
+ export interface ChatSidebarRootProps
3
+ extends React.HTMLAttributes<HTMLDivElement> {}
4
+ declare const ChatSidebarRoot: React.ForwardRefExoticComponent<
5
+ ChatSidebarRootProps & React.RefAttributes<HTMLDivElement>
6
+ >;
7
+ export interface ChatSidebarHeaderProps
8
+ extends React.HTMLAttributes<HTMLDivElement> {}
9
+ declare const ChatSidebarHeader: React.ForwardRefExoticComponent<
10
+ ChatSidebarHeaderProps & React.RefAttributes<HTMLDivElement>
11
+ >;
12
+ export interface ChatSidebarContentProps
13
+ extends React.HTMLAttributes<HTMLDivElement> {}
14
+ declare const ChatSidebarContent: React.ForwardRefExoticComponent<
15
+ ChatSidebarContentProps & React.RefAttributes<HTMLDivElement>
16
+ >;
17
+ export interface ChatSidebarFooterProps
18
+ extends React.HTMLAttributes<HTMLDivElement> {}
19
+ declare const ChatSidebarFooter: React.ForwardRefExoticComponent<
20
+ ChatSidebarFooterProps & React.RefAttributes<HTMLDivElement>
21
+ >;
22
+ export {
23
+ ChatSidebarRoot as Root,
24
+ ChatSidebarHeader as Header,
25
+ ChatSidebarContent as Content,
26
+ ChatSidebarFooter as Footer,
27
+ };