@oro.ad/nuxt-claude-devtools 1.3.0 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/client/200.html +1 -1
- package/dist/client/404.html +1 -1
- package/dist/client/_nuxt/{COus5Ssl.js → 0BAoaFXM.js} +1 -1
- package/dist/client/_nuxt/{B_BoWmnX.js → 88aFj9mk.js} +1 -1
- package/dist/client/_nuxt/{DolUcBed.js → B5vRr8Ti.js} +1 -1
- package/dist/client/_nuxt/{CDQtmRaX.js → BI4BFakr.js} +1 -1
- package/dist/client/_nuxt/{CPA0s6N9.js → BJuQJ8yP.js} +1 -1
- package/dist/client/_nuxt/{BB1-kxmm.js → BMxGt8ZG.js} +1 -1
- package/dist/client/_nuxt/{TQi6eIO6.js → Baq9Hzkz.js} +1 -1
- package/dist/client/_nuxt/{DbJLoP3G.js → Bf779K50.js} +1 -1
- package/dist/client/_nuxt/BmF8r-gh.js +1 -0
- package/dist/client/_nuxt/BryQ1L4F.js +1 -0
- package/dist/client/_nuxt/{V4UvAcd3.js → BsG0VKct.js} +1 -1
- package/dist/client/_nuxt/Bt-DdLhQ.js +12 -0
- package/dist/client/_nuxt/{CHeJJZL9.js → C6Xm_PzB.js} +1 -1
- package/dist/client/_nuxt/{DC_XB519.js → C8AkZ-W3.js} +1 -1
- package/dist/client/_nuxt/{BSVkH7b6.js → CEM1iRz_.js} +1 -1
- package/dist/client/_nuxt/{BcZxFXBD.js → CETmet01.js} +1 -1
- package/dist/client/_nuxt/CG1tBJBN.js +1 -0
- package/dist/client/_nuxt/{D2l4TRxW.js → CXOn8Upj.js} +1 -1
- package/dist/client/_nuxt/CYomf6PL.js +1 -0
- package/dist/client/_nuxt/{DEys9N1G.js → CrhTgxiU.js} +1 -1
- package/dist/client/_nuxt/{BYp73eMl.js → CtWfW1XP.js} +1 -1
- package/dist/client/_nuxt/{d8BPa19J.js → CuUOvg0u.js} +1 -1
- package/dist/client/_nuxt/CxYvL5O5.js +1 -0
- package/dist/client/_nuxt/D8DUrd91.js +1 -0
- package/dist/client/_nuxt/{DSt96JPY.js → DFkDlupw.js} +2 -2
- package/dist/client/_nuxt/{B8uzckkK.js → DG-9quB_.js} +1 -1
- package/dist/client/_nuxt/DHlhBFAg.js +1 -0
- package/dist/client/_nuxt/{BnXQTjo-.js → DJw5U4z8.js} +1 -1
- package/dist/client/_nuxt/{M6QPYocW.js → DRReoGGV.js} +1 -1
- package/dist/client/_nuxt/{DGQ4s7ae.js → DSMailoF.js} +1 -1
- package/dist/client/_nuxt/{qbS8UemQ.js → DUPgidXP.js} +1 -1
- package/dist/client/_nuxt/{QumocfwJ.js → D_JyZ6Hh.js} +1 -1
- package/dist/client/_nuxt/{BAb1fJOF.js → Dgm9zqhP.js} +2 -2
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/024950b2-9b05-4789-9918-c859c91d6b13.json +1 -0
- package/dist/client/_nuxt/{C--9REmc.js → h1c4XpR7.js} +1 -1
- package/dist/client/_nuxt/kN0L7CSs.js +1 -0
- package/dist/client/_nuxt/{BMZIbUUD.js → n4TwJfzb.js} +1 -1
- package/dist/client/_nuxt/zY60w9UT.js +1 -0
- package/dist/client/agents/index.html +1 -1
- package/dist/client/commands/index.html +1 -1
- package/dist/client/docs/index.html +1 -1
- package/dist/client/index.html +1 -1
- package/dist/client/mcp/index.html +1 -1
- package/dist/client/plugins/index.html +1 -1
- package/dist/client/settings/index.html +1 -1
- package/dist/client/skills/index.html +1 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +10 -4
- package/dist/runtime/overlay/components/ChatOverlay.d.vue.ts +0 -1
- package/dist/runtime/overlay/components/ChatOverlay.vue +221 -731
- package/dist/runtime/overlay/components/ChatOverlay.vue.d.ts +0 -1
- package/dist/runtime/overlay/components/MarkdownContent.vue +1 -1
- package/dist/runtime/overlay/components/ToolCallBlock.vue +1 -1
- package/dist/runtime/overlay/components/chat/ChatHeader.d.vue.ts +18 -0
- package/dist/runtime/overlay/components/chat/ChatHeader.vue +82 -0
- package/dist/runtime/overlay/components/chat/ChatHeader.vue.d.ts +18 -0
- package/dist/runtime/overlay/components/chat/ChatInput.d.vue.ts +22 -0
- package/dist/runtime/overlay/components/chat/ChatInput.vue +526 -0
- package/dist/runtime/overlay/components/chat/ChatInput.vue.d.ts +22 -0
- package/dist/runtime/overlay/components/chat/ChatMessages.d.vue.ts +13 -0
- package/dist/runtime/overlay/components/chat/ChatMessages.vue +160 -0
- package/dist/runtime/overlay/components/chat/ChatMessages.vue.d.ts +13 -0
- package/dist/runtime/overlay/components/chat/ClaudeBadge.d.vue.ts +22 -0
- package/dist/runtime/overlay/components/chat/ClaudeBadge.vue +85 -0
- package/dist/runtime/overlay/components/chat/ClaudeBadge.vue.d.ts +22 -0
- package/dist/runtime/overlay/components/chat/HistoryPanel.d.vue.ts +17 -0
- package/dist/runtime/overlay/components/chat/HistoryPanel.vue +65 -0
- package/dist/runtime/overlay/components/chat/HistoryPanel.vue.d.ts +17 -0
- package/dist/runtime/overlay/components/chat/NicknameModal.d.vue.ts +13 -0
- package/dist/runtime/overlay/components/chat/NicknameModal.vue +89 -0
- package/dist/runtime/overlay/components/chat/NicknameModal.vue.d.ts +13 -0
- package/dist/runtime/overlay/components/chat/index.d.ts +6 -0
- package/dist/runtime/overlay/components/chat/index.js +6 -0
- package/dist/runtime/overlay/composables/index.d.ts +3 -0
- package/dist/runtime/overlay/composables/index.js +3 -0
- package/dist/runtime/overlay/composables/useMessageContext.d.ts +25 -0
- package/dist/runtime/overlay/composables/useMessageContext.js +29 -0
- package/dist/runtime/overlay/composables/useMobileSwipe.d.ts +15 -0
- package/dist/runtime/overlay/composables/useMobileSwipe.js +79 -0
- package/dist/runtime/overlay/composables/usePanelInteraction.d.ts +30 -0
- package/dist/runtime/overlay/composables/usePanelInteraction.js +184 -0
- package/dist/runtime/overlay/composables/usePanelPosition.d.ts +69 -0
- package/dist/runtime/overlay/composables/usePanelPosition.js +147 -0
- package/dist/runtime/server/claude-session.d.ts +11 -0
- package/dist/runtime/server/claude-session.js +166 -6
- package/dist/runtime/shared/composables/useClaudeChat.d.ts +7 -3
- package/dist/runtime/shared/composables/useClaudeChat.js +27 -251
- package/dist/runtime/shared/composables/useClaudeChatCore.d.ts +40 -0
- package/dist/runtime/shared/composables/useClaudeChatCore.js +350 -0
- package/dist/runtime/shared/composables/useMessageContext.d.ts +54 -0
- package/dist/runtime/shared/composables/useMessageContext.js +195 -0
- package/dist/runtime/shared/composables/useShare.d.ts +14 -4
- package/dist/runtime/shared/composables/useShare.js +57 -35
- package/dist/runtime/shared/composables/useVoiceInput.js +40 -11
- package/dist/runtime/shared/types.d.ts +36 -0
- package/dist/runtime/types.d.ts +14 -0
- package/package.json +1 -1
- package/dist/client/_nuxt/BSF2Vz9o.js +0 -1
- package/dist/client/_nuxt/BflmC3YB.js +0 -1
- package/dist/client/_nuxt/CRkq21kc.js +0 -1
- package/dist/client/_nuxt/Cgba93Y9.js +0 -1
- package/dist/client/_nuxt/DH8Ugy8E.js +0 -1
- package/dist/client/_nuxt/DeGmaFBY.js +0 -1
- package/dist/client/_nuxt/DgfRwrFR.js +0 -1
- package/dist/client/_nuxt/builds/meta/2be12f06-336a-4fdd-b982-2f6c682c14a6.json +0 -1
- package/dist/client/_nuxt/wDw60tEC.js +0 -10
- package/dist/client/_nuxt/xEjB6ozD.js +0 -1
|
@@ -1,173 +1,76 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import {
|
|
2
|
+
import { nextTick, onMounted, onUnmounted, ref, watch } from "vue";
|
|
3
3
|
import { useClaudeChat } from "../../shared/composables/useClaudeChat";
|
|
4
4
|
import { useVoiceInput } from "../../shared/composables/useVoiceInput";
|
|
5
5
|
import { useShare } from "../../shared/composables/useShare";
|
|
6
|
-
import
|
|
7
|
-
import
|
|
6
|
+
import { useMessageContext } from "../composables/useMessageContext";
|
|
7
|
+
import { useMobileSwipe, usePanelInteraction, usePanelPosition } from "../composables";
|
|
8
|
+
import { ChatHeader, ChatInput, ChatMessages, ClaudeBadge, HistoryPanel, NicknameModal } from "./chat";
|
|
8
9
|
const props = defineProps({
|
|
9
10
|
socketUrl: { type: String, required: false }
|
|
10
11
|
});
|
|
11
12
|
const isOpen = ref(false);
|
|
12
|
-
const
|
|
13
|
-
const messagesContainer = ref(null);
|
|
14
|
-
const textareaRef = ref(null);
|
|
13
|
+
const isMobile = ref(false);
|
|
15
14
|
const panelRef = ref(null);
|
|
16
15
|
const headerRef = ref(null);
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const fabDragStart = ref({ x: 0, y: 0, fabX: 0, fabY: 0 });
|
|
22
|
-
const fabDragMoved = ref(false);
|
|
23
|
-
function loadFabPosition() {
|
|
24
|
-
try {
|
|
25
|
-
const saved = localStorage.getItem(FAB_STORAGE_KEY);
|
|
26
|
-
if (saved) {
|
|
27
|
-
fabPosition.value = JSON.parse(saved);
|
|
28
|
-
}
|
|
29
|
-
} catch {
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
function saveFabPosition() {
|
|
33
|
-
if (fabPosition.value) {
|
|
34
|
-
try {
|
|
35
|
-
localStorage.setItem(FAB_STORAGE_KEY, JSON.stringify(fabPosition.value));
|
|
36
|
-
} catch {
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
function getFabStyle() {
|
|
41
|
-
if (!fabPosition.value) return {};
|
|
42
|
-
return {
|
|
43
|
-
left: `${fabPosition.value.x}px`,
|
|
44
|
-
top: `${fabPosition.value.y}px`,
|
|
45
|
-
right: "auto",
|
|
46
|
-
bottom: "auto"
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
function handleFabDragStart(e) {
|
|
50
|
-
const clientX = "touches" in e ? e.touches[0].clientX : e.clientX;
|
|
51
|
-
const clientY = "touches" in e ? e.touches[0].clientY : e.clientY;
|
|
52
|
-
const fab = fabRef.value;
|
|
53
|
-
if (!fab) return;
|
|
54
|
-
const rect = fab.getBoundingClientRect();
|
|
55
|
-
fabDragStart.value = {
|
|
56
|
-
x: clientX,
|
|
57
|
-
y: clientY,
|
|
58
|
-
fabX: rect.left,
|
|
59
|
-
fabY: rect.top
|
|
60
|
-
};
|
|
61
|
-
isDraggingFab.value = true;
|
|
62
|
-
fabDragMoved.value = false;
|
|
63
|
-
window.addEventListener("mousemove", handleFabDragMove);
|
|
64
|
-
window.addEventListener("mouseup", handleFabDragEnd);
|
|
65
|
-
window.addEventListener("touchmove", handleFabDragMove, { passive: false });
|
|
66
|
-
window.addEventListener("touchend", handleFabDragEnd);
|
|
67
|
-
}
|
|
68
|
-
function handleFabDragMove(e) {
|
|
69
|
-
if (!isDraggingFab.value) return;
|
|
70
|
-
e.preventDefault();
|
|
71
|
-
const clientX = "touches" in e ? e.touches[0].clientX : e.clientX;
|
|
72
|
-
const clientY = "touches" in e ? e.touches[0].clientY : e.clientY;
|
|
73
|
-
const deltaX = clientX - fabDragStart.value.x;
|
|
74
|
-
const deltaY = clientY - fabDragStart.value.y;
|
|
75
|
-
if (Math.abs(deltaX) > 5 || Math.abs(deltaY) > 5) {
|
|
76
|
-
fabDragMoved.value = true;
|
|
77
|
-
}
|
|
78
|
-
const fabSize = 56;
|
|
79
|
-
const padding = 16;
|
|
80
|
-
let newX = fabDragStart.value.fabX + deltaX;
|
|
81
|
-
let newY = fabDragStart.value.fabY + deltaY;
|
|
82
|
-
newX = Math.max(padding, Math.min(window.innerWidth - fabSize - padding, newX));
|
|
83
|
-
newY = Math.max(padding, Math.min(window.innerHeight - fabSize - padding, newY));
|
|
84
|
-
fabPosition.value = { x: newX, y: newY };
|
|
16
|
+
const chatInputRef = ref(null);
|
|
17
|
+
const chatMessagesRef = ref(null);
|
|
18
|
+
function checkMobile() {
|
|
19
|
+
isMobile.value = window.innerWidth <= 640;
|
|
85
20
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
function
|
|
113
|
-
if (
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if (delta > 0) {
|
|
117
|
-
e.preventDefault();
|
|
118
|
-
touchDeltaY.value = delta;
|
|
119
|
-
if (panelRef.value) {
|
|
120
|
-
panelRef.value.style.transform = `translateY(${delta}px)`;
|
|
121
|
-
panelRef.value.style.transition = "none";
|
|
122
|
-
}
|
|
123
|
-
}
|
|
21
|
+
const {
|
|
22
|
+
badgePos,
|
|
23
|
+
panelSize,
|
|
24
|
+
panelScreenPos,
|
|
25
|
+
load: loadPanelState,
|
|
26
|
+
openPanel,
|
|
27
|
+
closePanel,
|
|
28
|
+
onBadgeDragEnd,
|
|
29
|
+
getPanelStyle
|
|
30
|
+
} = usePanelPosition();
|
|
31
|
+
const {
|
|
32
|
+
isDragging: isPanelDragging,
|
|
33
|
+
isResizing: isPanelResizing,
|
|
34
|
+
activeEdge: activeResizeEdge,
|
|
35
|
+
hoveredEdge,
|
|
36
|
+
cursor: resizeCursor,
|
|
37
|
+
startDrag: handlePanelDragStart,
|
|
38
|
+
startResize: handlePanelResizeStart,
|
|
39
|
+
onMouseMove: handlePanelMouseMove,
|
|
40
|
+
onMouseLeave: handlePanelMouseLeave
|
|
41
|
+
} = usePanelInteraction({
|
|
42
|
+
panelScreenPos,
|
|
43
|
+
panelSize,
|
|
44
|
+
panelRef,
|
|
45
|
+
isMobile
|
|
46
|
+
});
|
|
47
|
+
function lockBodyScroll(lock) {
|
|
48
|
+
if (typeof document === "undefined") return;
|
|
49
|
+
document.body.style.overflow = lock ? "hidden" : "";
|
|
50
|
+
document.body.style.touchAction = lock ? "none" : "";
|
|
124
51
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
isSwipeClosing.value = false;
|
|
138
|
-
if (panelRef.value) {
|
|
139
|
-
panelRef.value.style.transform = "";
|
|
140
|
-
panelRef.value.style.transition = "";
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
}, 300);
|
|
144
|
-
} else {
|
|
145
|
-
panelRef.value.style.transform = "translateY(0)";
|
|
146
|
-
setTimeout(() => {
|
|
147
|
-
if (panelRef.value) {
|
|
148
|
-
panelRef.value.style.transition = "";
|
|
149
|
-
}
|
|
150
|
-
}, 300);
|
|
151
|
-
}
|
|
52
|
+
const {
|
|
53
|
+
isSwipeClosing,
|
|
54
|
+
handleTouchStart,
|
|
55
|
+
handleTouchEnd,
|
|
56
|
+
setupTouchMoveListener,
|
|
57
|
+
cleanupTouchMoveListener
|
|
58
|
+
} = useMobileSwipe({
|
|
59
|
+
panelRef,
|
|
60
|
+
headerRef,
|
|
61
|
+
onSwipeClose: () => {
|
|
62
|
+
isOpen.value = false;
|
|
63
|
+
lockBodyScroll(false);
|
|
152
64
|
}
|
|
153
|
-
|
|
154
|
-
}
|
|
65
|
+
});
|
|
155
66
|
const commands = ref([]);
|
|
156
|
-
const showCommandsAutocomplete = ref(false);
|
|
157
67
|
const showHistory = ref(false);
|
|
158
|
-
const contextEnabled = ref({
|
|
159
|
-
viewport: true,
|
|
160
|
-
userAgent: true,
|
|
161
|
-
routing: true
|
|
162
|
-
});
|
|
163
68
|
const {
|
|
164
69
|
userId,
|
|
165
70
|
nickname,
|
|
166
|
-
users: _users,
|
|
167
71
|
showNicknameModal,
|
|
168
72
|
nicknameError,
|
|
169
73
|
isShareMode,
|
|
170
|
-
sharingActiveOnServer: _sharingActiveOnServer,
|
|
171
74
|
initShare,
|
|
172
75
|
setNickname,
|
|
173
76
|
needsNicknameImmediate,
|
|
@@ -179,11 +82,9 @@ const {
|
|
|
179
82
|
isOwnMessage,
|
|
180
83
|
copyShareLink
|
|
181
84
|
} = useShare({
|
|
182
|
-
|
|
85
|
+
getBaseUrl: () => props.socketUrl || window.location.origin,
|
|
183
86
|
log: (...args) => {
|
|
184
|
-
if (import.meta.env.DEV)
|
|
185
|
-
console.log("[ChatOverlay:Share]", ...args);
|
|
186
|
-
}
|
|
87
|
+
if (import.meta.env.DEV) console.log("[ChatOverlay:Share]", ...args);
|
|
187
88
|
}
|
|
188
89
|
});
|
|
189
90
|
const {
|
|
@@ -192,11 +93,11 @@ const {
|
|
|
192
93
|
conversations,
|
|
193
94
|
isConnected,
|
|
194
95
|
isProcessing,
|
|
195
|
-
statusText,
|
|
196
96
|
statusColor,
|
|
197
97
|
connectSocket,
|
|
198
98
|
disconnect,
|
|
199
99
|
sendMessage: sendChatMessage,
|
|
100
|
+
stopGeneration,
|
|
200
101
|
newChat,
|
|
201
102
|
toggleHistory,
|
|
202
103
|
selectConversation,
|
|
@@ -208,9 +109,7 @@ const {
|
|
|
208
109
|
commands.value = cmds;
|
|
209
110
|
},
|
|
210
111
|
log: (...args) => {
|
|
211
|
-
if (import.meta.env.DEV)
|
|
212
|
-
console.log("[ChatOverlay]", ...args);
|
|
213
|
-
}
|
|
112
|
+
if (import.meta.env.DEV) console.log("[ChatOverlay]", ...args);
|
|
214
113
|
}
|
|
215
114
|
});
|
|
216
115
|
const {
|
|
@@ -221,227 +120,121 @@ const {
|
|
|
221
120
|
} = useVoiceInput();
|
|
222
121
|
const showShareCopied = ref(false);
|
|
223
122
|
const pendingNicknameAction = ref(null);
|
|
224
|
-
const
|
|
225
|
-
const filteredCommands = computed(() => {
|
|
226
|
-
if (!showCommandsAutocomplete.value) return [];
|
|
227
|
-
const match = inputMessage.value.match(/(?:^|\s)\/(\S*)$/);
|
|
228
|
-
if (!match) return [];
|
|
229
|
-
const query = match[1].toLowerCase();
|
|
230
|
-
return commands.value.filter(
|
|
231
|
-
(cmd) => cmd.name.toLowerCase().includes(query)
|
|
232
|
-
).slice(0, 5);
|
|
233
|
-
});
|
|
234
|
-
function stripContextBlock(content) {
|
|
235
|
-
return content.replace(/^\[context\]\n[\s\S]*?\n\[\/context\]\n?/, "").trim();
|
|
236
|
-
}
|
|
237
|
-
function getDisplayContent(message) {
|
|
238
|
-
return stripContextBlock(message.content);
|
|
239
|
-
}
|
|
123
|
+
const { generateContextBlock } = useMessageContext();
|
|
240
124
|
function collectContext() {
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
else if (ua.includes("Safari/") && !ua.includes("Chrome")) browser = "Safari";
|
|
252
|
-
let os = "Unknown";
|
|
253
|
-
if (ua.includes("Windows")) os = "Windows";
|
|
254
|
-
else if (ua.includes("Mac OS")) os = "macOS";
|
|
255
|
-
else if (ua.includes("Linux")) os = "Linux";
|
|
256
|
-
else if (ua.includes("Android")) os = "Android";
|
|
257
|
-
else if (ua.includes("iPhone") || ua.includes("iPad")) os = "iOS";
|
|
258
|
-
parts.push(`browser: ${browser} on ${os}`);
|
|
259
|
-
}
|
|
260
|
-
if (contextEnabled.value.routing) {
|
|
261
|
-
parts.push(`route: ${window.location.pathname}`);
|
|
262
|
-
if (window.location.search) {
|
|
263
|
-
parts.push(`query: ${window.location.search}`);
|
|
125
|
+
const context = {
|
|
126
|
+
viewport: {
|
|
127
|
+
width: window.innerWidth,
|
|
128
|
+
height: window.innerHeight
|
|
129
|
+
},
|
|
130
|
+
userAgent: navigator.userAgent,
|
|
131
|
+
routing: {
|
|
132
|
+
path: window.location.pathname,
|
|
133
|
+
fullPath: window.location.pathname + window.location.search,
|
|
134
|
+
query: window.location.search ? Object.fromEntries(new URLSearchParams(window.location.search)) : void 0
|
|
264
135
|
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
return `[context]
|
|
268
|
-
${parts.join("\n")}
|
|
269
|
-
[/context]
|
|
270
|
-
`;
|
|
271
|
-
}
|
|
272
|
-
function handleInput() {
|
|
273
|
-
const match = inputMessage.value.match(/(?:^|\s)\/\S*$/);
|
|
274
|
-
showCommandsAutocomplete.value = !!match;
|
|
275
|
-
autoResizeTextarea();
|
|
276
|
-
}
|
|
277
|
-
function autoResizeTextarea() {
|
|
278
|
-
const textarea = textareaRef.value;
|
|
279
|
-
if (!textarea) return;
|
|
280
|
-
textarea.style.height = "auto";
|
|
281
|
-
textarea.style.height = `${Math.min(textarea.scrollHeight, 280)}px`;
|
|
282
|
-
}
|
|
283
|
-
function selectCommand(cmd) {
|
|
284
|
-
const match = inputMessage.value.match(/(?:^|\s)(\/\S*)$/);
|
|
285
|
-
if (match) {
|
|
286
|
-
const slashIndex = inputMessage.value.length - match[1].length;
|
|
287
|
-
inputMessage.value = inputMessage.value.slice(0, slashIndex) + `/${cmd.name} `;
|
|
288
|
-
}
|
|
289
|
-
showCommandsAutocomplete.value = false;
|
|
290
|
-
textareaRef.value?.focus();
|
|
291
|
-
nextTick(autoResizeTextarea);
|
|
136
|
+
};
|
|
137
|
+
return generateContextBlock(context) + "\n";
|
|
292
138
|
}
|
|
293
|
-
function
|
|
294
|
-
if (!inputMessage.value.trim() || isProcessing.value) return;
|
|
139
|
+
function handleMessageSubmit(message, attachments) {
|
|
295
140
|
if (needsNicknameForMessage()) {
|
|
296
141
|
pendingNicknameAction.value = "message";
|
|
297
142
|
showNicknameModal.value = true;
|
|
298
|
-
nicknameInput.value = "";
|
|
299
143
|
return;
|
|
300
144
|
}
|
|
301
145
|
const context = collectContext();
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
function handleKeydown(e) {
|
|
311
|
-
if (e.key === "Enter" && !e.shiftKey) {
|
|
312
|
-
e.preventDefault();
|
|
313
|
-
handleSubmit();
|
|
314
|
-
}
|
|
315
|
-
if (e.key === "Escape") {
|
|
316
|
-
if (showCommandsAutocomplete.value) {
|
|
317
|
-
showCommandsAutocomplete.value = false;
|
|
318
|
-
} else if (showHistory.value) {
|
|
319
|
-
showHistory.value = false;
|
|
320
|
-
} else {
|
|
321
|
-
isOpen.value = false;
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
function lockBodyScroll(lock) {
|
|
326
|
-
if (typeof document === "undefined") return;
|
|
327
|
-
if (lock) {
|
|
328
|
-
document.body.style.overflow = "hidden";
|
|
329
|
-
document.body.style.touchAction = "none";
|
|
330
|
-
} else {
|
|
331
|
-
document.body.style.overflow = "";
|
|
332
|
-
document.body.style.touchAction = "";
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
function toggleOverlay() {
|
|
336
|
-
isOpen.value = !isOpen.value;
|
|
337
|
-
if (isOpen.value) {
|
|
338
|
-
if (window.innerWidth <= 640) {
|
|
339
|
-
lockBodyScroll(true);
|
|
340
|
-
}
|
|
341
|
-
nextTick(() => {
|
|
342
|
-
textareaRef.value?.focus();
|
|
343
|
-
scrollToBottom();
|
|
344
|
-
});
|
|
345
|
-
} else {
|
|
346
|
-
lockBodyScroll(false);
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
function scrollToBottom() {
|
|
350
|
-
if (messagesContainer.value) {
|
|
351
|
-
messagesContainer.value.scrollTop = messagesContainer.value.scrollHeight;
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
function handleToggleHistory() {
|
|
355
|
-
showHistory.value = !showHistory.value;
|
|
356
|
-
if (showHistory.value) {
|
|
357
|
-
toggleHistory();
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
function handleSelectConversation(id) {
|
|
361
|
-
selectConversation(id);
|
|
362
|
-
showHistory.value = false;
|
|
363
|
-
}
|
|
364
|
-
function handleVoiceInput() {
|
|
365
|
-
toggleVoiceInput((transcript) => {
|
|
366
|
-
inputMessage.value += transcript + " ";
|
|
367
|
-
nextTick(autoResizeTextarea);
|
|
368
|
-
});
|
|
146
|
+
sendChatMessage(
|
|
147
|
+
context + message,
|
|
148
|
+
isShareMode.value ? userId.value || void 0 : void 0,
|
|
149
|
+
nickname.value || void 0,
|
|
150
|
+
attachments
|
|
151
|
+
);
|
|
369
152
|
}
|
|
370
153
|
function handleShareClick() {
|
|
371
154
|
if (needsNicknameForShare()) {
|
|
372
155
|
pendingNicknameAction.value = "share";
|
|
373
156
|
showNicknameModal.value = true;
|
|
374
|
-
nicknameInput.value = "";
|
|
375
157
|
} else {
|
|
376
158
|
doShareCopy();
|
|
377
159
|
}
|
|
378
160
|
}
|
|
379
161
|
async function doShareCopy() {
|
|
380
|
-
|
|
381
|
-
if (success) {
|
|
162
|
+
if (await copyShareLink()) {
|
|
382
163
|
showShareCopied.value = true;
|
|
383
164
|
setTimeout(() => {
|
|
384
165
|
showShareCopied.value = false;
|
|
385
166
|
}, 2e3);
|
|
386
167
|
}
|
|
387
168
|
}
|
|
388
|
-
function handleNicknameSubmit() {
|
|
389
|
-
const name = nicknameInput.value.trim();
|
|
390
|
-
if (name.length < 2 || name.length > 20) return;
|
|
169
|
+
function handleNicknameSubmit(name) {
|
|
391
170
|
setNickname(name);
|
|
392
|
-
if (socket.value)
|
|
393
|
-
registerUser(socket.value);
|
|
394
|
-
}
|
|
171
|
+
if (socket.value) registerUser(socket.value);
|
|
395
172
|
showNicknameModal.value = false;
|
|
396
173
|
if (pendingNicknameAction.value === "share") {
|
|
397
174
|
doShareCopy();
|
|
398
|
-
} else if (pendingNicknameAction.value === "message") {
|
|
399
|
-
handleSubmit();
|
|
400
175
|
}
|
|
401
176
|
pendingNicknameAction.value = null;
|
|
402
177
|
}
|
|
403
178
|
function handleNicknameCancel() {
|
|
404
179
|
showNicknameModal.value = false;
|
|
405
180
|
pendingNicknameAction.value = null;
|
|
406
|
-
nicknameInput.value = "";
|
|
407
181
|
}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
182
|
+
function handleToggleHistory() {
|
|
183
|
+
showHistory.value = !showHistory.value;
|
|
184
|
+
if (showHistory.value) toggleHistory();
|
|
185
|
+
}
|
|
186
|
+
function handleSelectConversation(id) {
|
|
187
|
+
selectConversation(id);
|
|
188
|
+
showHistory.value = false;
|
|
189
|
+
}
|
|
190
|
+
function handleVoiceInput() {
|
|
191
|
+
toggleVoiceInput((transcript) => {
|
|
192
|
+
chatInputRef.value?.appendText(transcript);
|
|
416
193
|
});
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
()
|
|
420
|
-
|
|
421
|
-
|
|
194
|
+
}
|
|
195
|
+
function handleStopGeneration() {
|
|
196
|
+
stopGeneration();
|
|
197
|
+
}
|
|
198
|
+
function handleClose() {
|
|
199
|
+
closePanel();
|
|
200
|
+
isOpen.value = false;
|
|
201
|
+
lockBodyScroll(false);
|
|
202
|
+
}
|
|
203
|
+
function toggleOverlay() {
|
|
204
|
+
if (!isOpen.value) {
|
|
205
|
+
if (window.innerWidth <= 640) lockBodyScroll(true);
|
|
206
|
+
openPanel();
|
|
207
|
+
isOpen.value = true;
|
|
208
|
+
nextTick(() => {
|
|
209
|
+
chatInputRef.value?.focus();
|
|
210
|
+
chatMessagesRef.value?.scrollToBottom();
|
|
211
|
+
});
|
|
212
|
+
} else {
|
|
213
|
+
handleClose();
|
|
422
214
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
(
|
|
426
|
-
|
|
427
|
-
|
|
215
|
+
}
|
|
216
|
+
function handleKeydown(e) {
|
|
217
|
+
if (e.key === "Escape") {
|
|
218
|
+
if (showHistory.value) {
|
|
219
|
+
showHistory.value = false;
|
|
220
|
+
} else {
|
|
221
|
+
handleClose();
|
|
222
|
+
}
|
|
428
223
|
}
|
|
429
|
-
|
|
224
|
+
}
|
|
430
225
|
function handleGlobalKeydown(e) {
|
|
431
226
|
if (e.ctrlKey && e.shiftKey && e.key === "K") {
|
|
432
227
|
e.preventDefault();
|
|
433
228
|
toggleOverlay();
|
|
434
229
|
}
|
|
435
230
|
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
pendingNicknameAction.value = null;
|
|
444
|
-
}
|
|
231
|
+
watch(isOpen, (open) => {
|
|
232
|
+
if (!open) lockBodyScroll(false);
|
|
233
|
+
nextTick(() => {
|
|
234
|
+
if (open) {
|
|
235
|
+
setupTouchMoveListener();
|
|
236
|
+
}
|
|
237
|
+
});
|
|
445
238
|
});
|
|
446
239
|
watch(isConnected, (connected) => {
|
|
447
240
|
if (connected && socket.value) {
|
|
@@ -452,442 +245,139 @@ watch(isConnected, (connected) => {
|
|
|
452
245
|
}
|
|
453
246
|
}
|
|
454
247
|
});
|
|
248
|
+
onMounted(() => {
|
|
249
|
+
initShare();
|
|
250
|
+
connectSocket();
|
|
251
|
+
loadPanelState();
|
|
252
|
+
checkMobile();
|
|
253
|
+
window.addEventListener("keydown", handleGlobalKeydown);
|
|
254
|
+
window.addEventListener("resize", checkMobile);
|
|
255
|
+
if (needsNicknameImmediate()) {
|
|
256
|
+
showNicknameModal.value = true;
|
|
257
|
+
pendingNicknameAction.value = null;
|
|
258
|
+
}
|
|
259
|
+
});
|
|
455
260
|
onUnmounted(() => {
|
|
456
261
|
disconnect();
|
|
457
262
|
cleanupVoice();
|
|
458
263
|
lockBodyScroll(false);
|
|
459
264
|
window.removeEventListener("keydown", handleGlobalKeydown);
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
}
|
|
265
|
+
window.removeEventListener("resize", checkMobile);
|
|
266
|
+
cleanupTouchMoveListener();
|
|
463
267
|
});
|
|
464
|
-
function getMessageClass(role) {
|
|
465
|
-
if (role === "user") return "claude-overlay-message-user";
|
|
466
|
-
if (role === "assistant") return "claude-overlay-message-assistant";
|
|
467
|
-
return "claude-overlay-message-system";
|
|
468
|
-
}
|
|
469
|
-
function formatDate(dateStr) {
|
|
470
|
-
const date = new Date(dateStr);
|
|
471
|
-
return date.toLocaleDateString() + " " + date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
472
|
-
}
|
|
473
268
|
</script>
|
|
474
269
|
|
|
475
270
|
<template>
|
|
476
271
|
<Teleport to="body">
|
|
477
|
-
<!--
|
|
478
|
-
<
|
|
272
|
+
<!-- Badge -->
|
|
273
|
+
<ClaudeBadge
|
|
479
274
|
v-if="!isOpen"
|
|
480
|
-
|
|
481
|
-
:
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
@touchstart="handleFabDragStart"
|
|
486
|
-
@click="handleFabClick"
|
|
487
|
-
>
|
|
488
|
-
<svg
|
|
489
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
490
|
-
viewBox="0 0 24 24"
|
|
491
|
-
fill="currentColor"
|
|
492
|
-
class="claude-overlay-fab-icon"
|
|
493
|
-
>
|
|
494
|
-
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z" />
|
|
495
|
-
</svg>
|
|
496
|
-
<span
|
|
497
|
-
:class="['claude-overlay-fab-status', `claude-overlay-fab-status-${statusColor}`]"
|
|
498
|
-
/>
|
|
499
|
-
</button>
|
|
275
|
+
:position="badgePos"
|
|
276
|
+
:status-color="statusColor"
|
|
277
|
+
@click="toggleOverlay"
|
|
278
|
+
@drag-end="onBadgeDragEnd"
|
|
279
|
+
/>
|
|
500
280
|
|
|
501
|
-
<!-- Backdrop
|
|
502
|
-
<Transition name="claude-
|
|
281
|
+
<!-- Backdrop -->
|
|
282
|
+
<Transition name="claude-fade">
|
|
503
283
|
<div
|
|
504
284
|
v-if="isOpen"
|
|
505
|
-
class="claude-
|
|
506
|
-
@click="
|
|
285
|
+
class="claude-backdrop"
|
|
286
|
+
@click="handleClose"
|
|
507
287
|
/>
|
|
508
288
|
</Transition>
|
|
509
289
|
|
|
510
290
|
<!-- Nickname Modal -->
|
|
511
|
-
<
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
<div class="claude-overlay-modal">
|
|
518
|
-
<div class="claude-overlay-modal-header">
|
|
519
|
-
<h3>Enter your nickname</h3>
|
|
520
|
-
<button
|
|
521
|
-
class="claude-overlay-btn-icon"
|
|
522
|
-
@click="handleNicknameCancel"
|
|
523
|
-
>
|
|
524
|
-
<svg
|
|
525
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
526
|
-
viewBox="0 0 24 24"
|
|
527
|
-
fill="currentColor"
|
|
528
|
-
width="16"
|
|
529
|
-
height="16"
|
|
530
|
-
>
|
|
531
|
-
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
|
|
532
|
-
</svg>
|
|
533
|
-
</button>
|
|
534
|
-
</div>
|
|
535
|
-
<div class="claude-overlay-modal-body">
|
|
536
|
-
<p class="claude-overlay-modal-hint">
|
|
537
|
-
Choose a nickname for collaborative chat sessions
|
|
538
|
-
</p>
|
|
539
|
-
<input
|
|
540
|
-
v-model="nicknameInput"
|
|
541
|
-
type="text"
|
|
542
|
-
class="claude-overlay-modal-input"
|
|
543
|
-
placeholder="Your nickname (2-20 characters)"
|
|
544
|
-
maxlength="20"
|
|
545
|
-
@keydown.enter="handleNicknameSubmit"
|
|
546
|
-
>
|
|
547
|
-
<p
|
|
548
|
-
v-if="nicknameError"
|
|
549
|
-
class="claude-overlay-modal-error"
|
|
550
|
-
>
|
|
551
|
-
{{ nicknameError }}
|
|
552
|
-
</p>
|
|
553
|
-
</div>
|
|
554
|
-
<div class="claude-overlay-modal-actions">
|
|
555
|
-
<button
|
|
556
|
-
class="claude-overlay-modal-btn-secondary"
|
|
557
|
-
@click="handleNicknameCancel"
|
|
558
|
-
>
|
|
559
|
-
Cancel
|
|
560
|
-
</button>
|
|
561
|
-
<button
|
|
562
|
-
class="claude-overlay-modal-btn-primary"
|
|
563
|
-
:disabled="nicknameInput.trim().length < 2"
|
|
564
|
-
@click="handleNicknameSubmit"
|
|
565
|
-
>
|
|
566
|
-
Save
|
|
567
|
-
</button>
|
|
568
|
-
</div>
|
|
569
|
-
</div>
|
|
570
|
-
</div>
|
|
571
|
-
</Transition>
|
|
291
|
+
<NicknameModal
|
|
292
|
+
:error="nicknameError"
|
|
293
|
+
:show="showNicknameModal"
|
|
294
|
+
@cancel="handleNicknameCancel"
|
|
295
|
+
@submit="handleNicknameSubmit"
|
|
296
|
+
/>
|
|
572
297
|
|
|
573
298
|
<!-- Chat Panel -->
|
|
574
|
-
<Transition :name="isSwipeClosing ? '' : 'claude-
|
|
299
|
+
<Transition :name="isSwipeClosing ? '' : 'claude-slide'">
|
|
575
300
|
<div
|
|
576
301
|
v-if="isOpen"
|
|
577
302
|
ref="panelRef"
|
|
578
|
-
class="claude-
|
|
303
|
+
:class="['claude-panel', { 'claude-panel-dragging': isPanelDragging, 'claude-panel-resizing': isPanelResizing }]"
|
|
304
|
+
:style="[isMobile ? {} : getPanelStyle(), { cursor: resizeCursor }]"
|
|
305
|
+
@keydown="handleKeydown"
|
|
306
|
+
@mouseleave="handlePanelMouseLeave"
|
|
307
|
+
@mousemove="handlePanelMouseMove"
|
|
579
308
|
>
|
|
580
|
-
<!--
|
|
309
|
+
<!-- Resize edges -->
|
|
310
|
+
<template v-if="!isMobile">
|
|
311
|
+
<div
|
|
312
|
+
v-for="edge in ['n', 's', 'e', 'w']"
|
|
313
|
+
:key="edge"
|
|
314
|
+
:class="`claude-resize-edge claude-resize-${edge}`"
|
|
315
|
+
@mousedown="(e) => handlePanelResizeStart(edge, e)"
|
|
316
|
+
/>
|
|
317
|
+
<div
|
|
318
|
+
v-for="corner in ['nw', 'ne', 'sw', 'se']"
|
|
319
|
+
:key="corner"
|
|
320
|
+
:class="['claude-resize-corner', `claude-resize-${corner}`, { 'claude-resize-active': hoveredEdge === corner || activeResizeEdge === corner }]"
|
|
321
|
+
@mousedown="(e) => handlePanelResizeStart(corner, e)"
|
|
322
|
+
/>
|
|
323
|
+
</template>
|
|
324
|
+
|
|
325
|
+
<!-- Mobile drag bumper -->
|
|
581
326
|
<div
|
|
327
|
+
v-if="isMobile"
|
|
582
328
|
ref="headerRef"
|
|
583
|
-
class="claude-
|
|
584
|
-
@touchstart="handleTouchStart"
|
|
329
|
+
class="claude-drag-bumper"
|
|
585
330
|
@touchend="handleTouchEnd"
|
|
331
|
+
@touchstart="handleTouchStart"
|
|
586
332
|
>
|
|
587
|
-
<div class="claude-
|
|
588
|
-
<svg
|
|
589
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
590
|
-
viewBox="0 0 24 24"
|
|
591
|
-
fill="currentColor"
|
|
592
|
-
class="claude-overlay-header-icon"
|
|
593
|
-
>
|
|
594
|
-
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z" />
|
|
595
|
-
</svg>
|
|
596
|
-
<span class="claude-overlay-header-title">Claude</span>
|
|
597
|
-
<span :class="['claude-overlay-status-badge', `claude-overlay-status-${statusColor}`]">
|
|
598
|
-
{{ statusText }}
|
|
599
|
-
</span>
|
|
600
|
-
</div>
|
|
601
|
-
<div class="claude-overlay-header-actions">
|
|
602
|
-
<!-- Share button -->
|
|
603
|
-
<button
|
|
604
|
-
class="claude-overlay-btn-icon"
|
|
605
|
-
:class="{ 'claude-overlay-btn-success': showShareCopied }"
|
|
606
|
-
:title="showShareCopied ? 'Link copied!' : 'Share chat'"
|
|
607
|
-
@click="handleShareClick"
|
|
608
|
-
>
|
|
609
|
-
<svg
|
|
610
|
-
v-if="showShareCopied"
|
|
611
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
612
|
-
viewBox="0 0 24 24"
|
|
613
|
-
fill="currentColor"
|
|
614
|
-
width="18"
|
|
615
|
-
height="18"
|
|
616
|
-
>
|
|
617
|
-
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" />
|
|
618
|
-
</svg>
|
|
619
|
-
<svg
|
|
620
|
-
v-else
|
|
621
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
622
|
-
viewBox="0 0 24 24"
|
|
623
|
-
fill="currentColor"
|
|
624
|
-
width="18"
|
|
625
|
-
height="18"
|
|
626
|
-
>
|
|
627
|
-
<path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92s2.92-1.31 2.92-2.92-1.31-2.92-2.92-2.92z" />
|
|
628
|
-
</svg>
|
|
629
|
-
</button>
|
|
630
|
-
<button
|
|
631
|
-
class="claude-overlay-btn-icon"
|
|
632
|
-
title="History"
|
|
633
|
-
@click="handleToggleHistory"
|
|
634
|
-
>
|
|
635
|
-
<svg
|
|
636
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
637
|
-
viewBox="0 0 24 24"
|
|
638
|
-
fill="currentColor"
|
|
639
|
-
width="18"
|
|
640
|
-
height="18"
|
|
641
|
-
>
|
|
642
|
-
<path d="M13 3a9 9 0 0 0-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42A8.954 8.954 0 0 0 13 21a9 9 0 0 0 0-18zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z" />
|
|
643
|
-
</svg>
|
|
644
|
-
</button>
|
|
645
|
-
<button
|
|
646
|
-
class="claude-overlay-btn-icon"
|
|
647
|
-
title="New chat"
|
|
648
|
-
@click="newChat"
|
|
649
|
-
>
|
|
650
|
-
<svg
|
|
651
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
652
|
-
viewBox="0 0 24 24"
|
|
653
|
-
fill="currentColor"
|
|
654
|
-
width="18"
|
|
655
|
-
height="18"
|
|
656
|
-
>
|
|
657
|
-
<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
|
|
658
|
-
</svg>
|
|
659
|
-
</button>
|
|
660
|
-
</div>
|
|
333
|
+
<div class="claude-drag-handle-bar" />
|
|
661
334
|
</div>
|
|
662
335
|
|
|
663
|
-
<!--
|
|
664
|
-
<
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
@click="showHistory = false"
|
|
674
|
-
>
|
|
675
|
-
<svg
|
|
676
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
677
|
-
viewBox="0 0 24 24"
|
|
678
|
-
fill="currentColor"
|
|
679
|
-
width="16"
|
|
680
|
-
height="16"
|
|
681
|
-
>
|
|
682
|
-
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
|
|
683
|
-
</svg>
|
|
684
|
-
</button>
|
|
685
|
-
</div>
|
|
686
|
-
<div class="claude-overlay-history-list">
|
|
687
|
-
<div
|
|
688
|
-
v-for="conv in conversations"
|
|
689
|
-
:key="conv.id"
|
|
690
|
-
class="claude-overlay-history-item"
|
|
691
|
-
@click="handleSelectConversation(conv.id)"
|
|
692
|
-
>
|
|
693
|
-
<div class="claude-overlay-history-title">
|
|
694
|
-
{{ stripContextBlock(conv.title || "") || "Untitled" }}
|
|
695
|
-
</div>
|
|
696
|
-
<div class="claude-overlay-history-date">
|
|
697
|
-
{{ formatDate(conv.updatedAt) }}
|
|
698
|
-
</div>
|
|
699
|
-
</div>
|
|
700
|
-
<div
|
|
701
|
-
v-if="conversations.length === 0"
|
|
702
|
-
class="claude-overlay-history-empty"
|
|
703
|
-
>
|
|
704
|
-
No conversations yet
|
|
705
|
-
</div>
|
|
706
|
-
</div>
|
|
707
|
-
</div>
|
|
708
|
-
</Transition>
|
|
709
|
-
|
|
710
|
-
<!-- Messages -->
|
|
711
|
-
<div
|
|
712
|
-
ref="messagesContainer"
|
|
713
|
-
class="claude-overlay-messages"
|
|
714
|
-
>
|
|
715
|
-
<div
|
|
716
|
-
v-if="messages.length === 0"
|
|
717
|
-
class="claude-overlay-empty"
|
|
718
|
-
>
|
|
719
|
-
<p>Start a conversation with Claude</p>
|
|
720
|
-
<p class="claude-overlay-empty-hint">
|
|
721
|
-
Type a message or use /commands
|
|
722
|
-
</p>
|
|
723
|
-
</div>
|
|
724
|
-
|
|
725
|
-
<div
|
|
726
|
-
v-for="message in messages"
|
|
727
|
-
:key="message.id"
|
|
728
|
-
:class="[
|
|
729
|
-
'claude-overlay-message',
|
|
730
|
-
getMessageClass(message.role),
|
|
731
|
-
{
|
|
732
|
-
'claude-overlay-message-own': message.role === 'user' && isOwnMessage(message.senderId),
|
|
733
|
-
'claude-overlay-message-other': message.role === 'user' && !isOwnMessage(message.senderId)
|
|
734
|
-
}
|
|
735
|
-
]"
|
|
736
|
-
>
|
|
737
|
-
<!-- User message -->
|
|
738
|
-
<template v-if="message.role === 'user'">
|
|
739
|
-
<div
|
|
740
|
-
v-if="isShareMode && message.senderNickname"
|
|
741
|
-
class="claude-overlay-message-sender"
|
|
742
|
-
>
|
|
743
|
-
{{ message.senderNickname }}
|
|
744
|
-
<span
|
|
745
|
-
v-if="isOwnMessage(message.senderId)"
|
|
746
|
-
class="claude-overlay-message-you"
|
|
747
|
-
>(you)</span>
|
|
748
|
-
</div>
|
|
749
|
-
<div class="claude-overlay-message-content">
|
|
750
|
-
{{ getDisplayContent(message) }}
|
|
751
|
-
</div>
|
|
752
|
-
</template>
|
|
336
|
+
<!-- Header -->
|
|
337
|
+
<ChatHeader
|
|
338
|
+
:is-mobile="isMobile"
|
|
339
|
+
:show-share-copied="showShareCopied"
|
|
340
|
+
:status-color="statusColor"
|
|
341
|
+
@history="handleToggleHistory"
|
|
342
|
+
@share="handleShareClick"
|
|
343
|
+
@new-chat="newChat"
|
|
344
|
+
@drag-start="handlePanelDragStart"
|
|
345
|
+
/>
|
|
753
346
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
>
|
|
762
|
-
<MarkdownContent
|
|
763
|
-
v-if="block.type === 'text' && block.text"
|
|
764
|
-
:content="stripContextBlock(block.text)"
|
|
765
|
-
/>
|
|
766
|
-
<ToolCallBlock
|
|
767
|
-
v-else-if="block.type === 'tool_use'"
|
|
768
|
-
:block="block"
|
|
769
|
-
:result="findToolResult(message.contentBlocks, block.id)"
|
|
770
|
-
/>
|
|
771
|
-
</template>
|
|
772
|
-
</template>
|
|
773
|
-
<template v-else-if="message.content">
|
|
774
|
-
<MarkdownContent :content="getDisplayContent(message)" />
|
|
775
|
-
</template>
|
|
776
|
-
<span
|
|
777
|
-
v-if="message.streaming"
|
|
778
|
-
class="claude-overlay-cursor"
|
|
779
|
-
/>
|
|
780
|
-
</div>
|
|
781
|
-
</template>
|
|
347
|
+
<!-- History -->
|
|
348
|
+
<HistoryPanel
|
|
349
|
+
:conversations="conversations"
|
|
350
|
+
:show="showHistory"
|
|
351
|
+
@close="showHistory = false"
|
|
352
|
+
@select="handleSelectConversation"
|
|
353
|
+
/>
|
|
782
354
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
355
|
+
<!-- Messages -->
|
|
356
|
+
<ChatMessages
|
|
357
|
+
ref="chatMessagesRef"
|
|
358
|
+
:find-tool-result="findToolResult"
|
|
359
|
+
:is-own-message="isOwnMessage"
|
|
360
|
+
:is-share-mode="isShareMode"
|
|
361
|
+
:messages="messages"
|
|
362
|
+
/>
|
|
791
363
|
|
|
792
364
|
<!-- Input -->
|
|
793
|
-
<
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
>
|
|
805
|
-
<span class="claude-overlay-autocomplete-name">/{{ cmd.name }}</span>
|
|
806
|
-
<span
|
|
807
|
-
v-if="cmd.description"
|
|
808
|
-
class="claude-overlay-autocomplete-desc"
|
|
809
|
-
>{{ cmd.description }}</span>
|
|
810
|
-
</button>
|
|
811
|
-
</div>
|
|
812
|
-
|
|
813
|
-
<div class="claude-overlay-input-wrapper">
|
|
814
|
-
<textarea
|
|
815
|
-
ref="textareaRef"
|
|
816
|
-
v-model="inputMessage"
|
|
817
|
-
class="claude-overlay-input"
|
|
818
|
-
placeholder="Ask Claude..."
|
|
819
|
-
rows="1"
|
|
820
|
-
:disabled="!isConnected || isProcessing"
|
|
821
|
-
@input="handleInput"
|
|
822
|
-
@keydown="handleKeydown"
|
|
823
|
-
/>
|
|
824
|
-
<div class="claude-overlay-input-actions">
|
|
825
|
-
<!-- Voice input button -->
|
|
826
|
-
<button
|
|
827
|
-
v-if="isSpeechSupported"
|
|
828
|
-
:class="['claude-overlay-voice-btn', { 'claude-overlay-voice-recording': isRecording }]"
|
|
829
|
-
:disabled="!isConnected || isProcessing"
|
|
830
|
-
title="Voice input"
|
|
831
|
-
@click="handleVoiceInput"
|
|
832
|
-
>
|
|
833
|
-
<svg
|
|
834
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
835
|
-
viewBox="0 0 24 24"
|
|
836
|
-
fill="currentColor"
|
|
837
|
-
width="20"
|
|
838
|
-
height="20"
|
|
839
|
-
>
|
|
840
|
-
<path d="M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z" />
|
|
841
|
-
</svg>
|
|
842
|
-
</button>
|
|
843
|
-
<!-- Send button -->
|
|
844
|
-
<button
|
|
845
|
-
class="claude-overlay-send-btn"
|
|
846
|
-
:disabled="!inputMessage.trim() || !isConnected || isProcessing"
|
|
847
|
-
@click="handleSubmit"
|
|
848
|
-
>
|
|
849
|
-
<svg
|
|
850
|
-
v-if="isProcessing"
|
|
851
|
-
class="claude-overlay-spinner"
|
|
852
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
853
|
-
viewBox="0 0 24 24"
|
|
854
|
-
fill="none"
|
|
855
|
-
stroke="currentColor"
|
|
856
|
-
width="20"
|
|
857
|
-
height="20"
|
|
858
|
-
>
|
|
859
|
-
<circle
|
|
860
|
-
cx="12"
|
|
861
|
-
cy="12"
|
|
862
|
-
r="10"
|
|
863
|
-
stroke-width="2"
|
|
864
|
-
opacity="0.25"
|
|
865
|
-
/>
|
|
866
|
-
<path
|
|
867
|
-
d="M12 2a10 10 0 0 1 10 10"
|
|
868
|
-
stroke-width="2"
|
|
869
|
-
stroke-linecap="round"
|
|
870
|
-
/>
|
|
871
|
-
</svg>
|
|
872
|
-
<svg
|
|
873
|
-
v-else
|
|
874
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
875
|
-
viewBox="0 0 24 24"
|
|
876
|
-
fill="currentColor"
|
|
877
|
-
width="20"
|
|
878
|
-
height="20"
|
|
879
|
-
>
|
|
880
|
-
<path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" />
|
|
881
|
-
</svg>
|
|
882
|
-
</button>
|
|
883
|
-
</div>
|
|
884
|
-
</div>
|
|
885
|
-
</div>
|
|
365
|
+
<ChatInput
|
|
366
|
+
ref="chatInputRef"
|
|
367
|
+
:commands="commands"
|
|
368
|
+
:is-connected="isConnected"
|
|
369
|
+
:is-processing="isProcessing"
|
|
370
|
+
:is-recording="isRecording"
|
|
371
|
+
:is-speech-supported="isSpeechSupported"
|
|
372
|
+
@submit="handleMessageSubmit"
|
|
373
|
+
@voice-input="handleVoiceInput"
|
|
374
|
+
@stop="handleStopGeneration"
|
|
375
|
+
/>
|
|
886
376
|
</div>
|
|
887
377
|
</Transition>
|
|
888
378
|
</Teleport>
|
|
889
379
|
</template>
|
|
890
380
|
|
|
891
381
|
<style>
|
|
892
|
-
:root{--claude-primary:#10a37f;--claude-primary-hover:#0d8a6a;--claude-bg:#1a1a1a;--claude-bg-elevated:#252525;--claude-bg-hover:#2a2a2a;--claude-text:#fff;--claude-text-muted:#a0a0a0;--claude-border:#333;--claude-user-bg:#2d4a3e;--claude-system-bg:#3d3d3d;--claude-radius:12px;--claude-radius-sm:8px}.claude-overlay-fab{align-items:center;background:var(--claude-primary);border:none;border-radius:50%;bottom:20px;box-shadow:0 4px 12px rgba(0,0,0,.2);color:#fff;cursor:pointer;display:flex;height:56px;justify-content:center;opacity:.6;position:fixed;transition:transform .2s,background .2s,opacity .2s,box-shadow .2s;width:56px;z-index:99998}.claude-overlay-fab:hover{background:var(--claude-primary-hover);box-shadow:0 6px 20px rgba(0,0,0,.35);opacity:1;transform:scale(1.05)}.claude-overlay-fab-dragging{box-shadow:0 8px 24px rgba(0,0,0,.4);cursor:grabbing;opacity:1;transform:scale(1.1);transition:none}.claude-overlay-backdrop{background:rgba(0,0,0,.3);inset:0;position:fixed;z-index:99997}.claude-overlay-fade-enter-active,.claude-overlay-fade-leave-active{transition:opacity .2s ease}.claude-overlay-fade-enter-from,.claude-overlay-fade-leave-to{opacity:0}.claude-overlay-fab-default{right:20px}.claude-overlay-fab-icon{height:28px;width:28px}.claude-overlay-fab-status{border:2px solid var(--claude-bg);border-radius:50%;height:12px;position:absolute;right:4px;top:4px;width:12px}.claude-overlay-fab-status-green{background:#22c55e}.claude-overlay-fab-status-blue{background:#3b82f6}.claude-overlay-fab-status-red{background:#ef4444}.claude-overlay-panel{background:var(--claude-bg);border-radius:var(--claude-radius);bottom:20px;box-shadow:0 8px 32px rgba(0,0,0,.4);color:var(--claude-text);display:flex;flex-direction:column;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:14px;height:calc(100vh - 40px);max-width:calc(100vw - 40px);overflow:hidden;position:fixed;right:20px;width:420px;z-index:99999}.claude-overlay-header{align-items:center;background:var(--claude-bg-elevated);border-bottom:1px solid var(--claude-border);display:flex;flex-shrink:0;justify-content:space-between;padding:12px 16px}.claude-overlay-header-left{align-items:center;display:flex;gap:8px}.claude-overlay-header-icon{color:var(--claude-primary);height:24px;width:24px}.claude-overlay-header-title{font-size:16px;font-weight:600}.claude-overlay-status-badge{background:var(--claude-bg);border-radius:10px;font-size:11px;padding:2px 8px}.claude-overlay-status-green{color:#22c55e}.claude-overlay-status-blue{color:#3b82f6}.claude-overlay-status-red{color:#ef4444}.claude-overlay-header-actions{display:flex;gap:4px}.claude-overlay-btn-icon{align-items:center;background:transparent;border:none;border-radius:var(--claude-radius-sm);color:var(--claude-text-muted);cursor:pointer;display:flex;height:32px;justify-content:center;transition:background .2s,color .2s;width:32px}.claude-overlay-btn-icon:hover{background:var(--claude-bg-hover);color:var(--claude-text)}.claude-overlay-btn-success{color:#22c55e!important}.claude-overlay-history{background:var(--claude-bg);bottom:0;display:flex;flex-direction:column;left:0;position:absolute;right:0;top:0;z-index:10}.claude-overlay-history-header{align-items:center;background:var(--claude-bg-elevated);border-bottom:1px solid var(--claude-border);display:flex;font-weight:600;justify-content:space-between;padding:12px 16px}.claude-overlay-history-list{flex:1;overflow-y:auto;padding:8px}.claude-overlay-history-item{border-radius:var(--claude-radius-sm);cursor:pointer;padding:12px;transition:background .15s}.claude-overlay-history-item:hover{background:var(--claude-bg-hover)}.claude-overlay-history-title{font-weight:500;margin-bottom:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.claude-overlay-history-date{color:var(--claude-text-muted);font-size:12px}.claude-overlay-history-empty{color:var(--claude-text-muted);padding:32px;text-align:center}.claude-overlay-messages{display:flex;flex:1;flex-direction:column;gap:12px;overflow-y:auto;padding:16px}.claude-overlay-empty{align-items:center;color:var(--claude-text-muted);display:flex;flex:1;flex-direction:column;justify-content:center;text-align:center}.claude-overlay-empty-hint{font-size:12px;margin-top:4px;opacity:.7}.claude-overlay-message{max-width:90%}.claude-overlay-message-user{align-self:flex-end}.claude-overlay-message-sender{color:var(--claude-primary);font-size:11px;font-weight:600;margin-bottom:4px;padding-left:2px}.claude-overlay-message-you{font-weight:400;opacity:.5}.claude-overlay-message-own{align-self:flex-end}.claude-overlay-message-own .claude-overlay-message-content{background:var(--claude-user-bg);border-radius:var(--claude-radius-sm);padding:10px 14px;white-space:pre-wrap;word-break:break-word}.claude-overlay-message-other{align-self:flex-start}.claude-overlay-message-other .claude-overlay-message-content{background:rgba(168,85,247,.2);border-radius:var(--claude-radius-sm);padding:10px 14px;white-space:pre-wrap;word-break:break-word}.claude-overlay-message-user .claude-overlay-message-content{background:var(--claude-user-bg);border-radius:var(--claude-radius-sm);padding:10px 14px;white-space:pre-wrap;word-break:break-word}.claude-overlay-message-assistant{align-self:flex-start}.claude-overlay-message-assistant .claude-overlay-message-content{background:var(--claude-bg-elevated);border-radius:var(--claude-radius-sm);padding:10px 14px}.claude-overlay-message-system{align-self:center}.claude-overlay-message-system-content{background:var(--claude-system-bg);border-radius:var(--claude-radius-sm);color:var(--claude-text-muted);font-size:12px;padding:8px 12px}.claude-overlay-cursor{animation:claude-blink 1s infinite;background:var(--claude-primary);display:inline-block;height:16px;margin-left:2px;width:8px}@keyframes claude-blink{0%,50%{opacity:1}51%,to{opacity:0}}.claude-overlay-input-container{background:var(--claude-bg-elevated);border-top:1px solid var(--claude-border);flex-shrink:0;padding:12px 16px;position:relative}.claude-overlay-autocomplete{background:var(--claude-bg);border:1px solid var(--claude-border);border-radius:var(--claude-radius-sm);bottom:100%;box-shadow:0 -4px 12px rgba(0,0,0,.2);left:16px;overflow:hidden;position:absolute;right:16px}.claude-overlay-autocomplete-item{background:transparent;border:none;color:var(--claude-text);cursor:pointer;display:flex;flex-direction:column;gap:2px;padding:10px 12px;text-align:left;transition:background .15s;width:100%}.claude-overlay-autocomplete-item:hover{background:var(--claude-bg-hover)}.claude-overlay-autocomplete-name{color:var(--claude-primary);font-family:monospace}.claude-overlay-autocomplete-desc{color:var(--claude-text-muted);font-size:12px}.claude-overlay-input-wrapper{align-items:flex-end;display:flex;gap:8px}.claude-overlay-input{background:var(--claude-bg);border:1px solid var(--claude-border);border-radius:var(--claude-radius-sm);color:var(--claude-text);flex:1;font-family:inherit;font-size:14px;line-height:1.4;max-height:280px;min-height:40px;overflow-y:auto;padding:10px 12px;resize:none}.claude-overlay-input:focus{border-color:var(--claude-primary);outline:none}.claude-overlay-input::-moz-placeholder{color:var(--claude-text-muted)}.claude-overlay-input::placeholder{color:var(--claude-text-muted)}.claude-overlay-input:disabled{cursor:not-allowed;opacity:.5}.claude-overlay-input-actions{display:flex;flex-shrink:0;gap:4px}.claude-overlay-voice-btn{align-items:center;background:var(--claude-bg);border:none;border-radius:var(--claude-radius-sm);color:var(--claude-text-muted);cursor:pointer;display:flex;height:40px;justify-content:center;transition:background .2s,color .2s;width:40px}.claude-overlay-voice-btn:hover:not(:disabled){background:var(--claude-bg-hover);color:var(--claude-text)}.claude-overlay-voice-btn:disabled{cursor:not-allowed;opacity:.5}.claude-overlay-voice-recording{animation:claude-pulse 1s infinite;background:#ef4444!important;color:#fff!important}@keyframes claude-pulse{0%,to{opacity:1}50%{opacity:.7}}.claude-overlay-send-btn{align-items:center;background:var(--claude-primary);border:none;border-radius:var(--claude-radius-sm);color:#fff;cursor:pointer;display:flex;height:40px;justify-content:center;transition:background .2s;width:40px}.claude-overlay-send-btn:hover:not(:disabled){background:var(--claude-primary-hover)}.claude-overlay-send-btn:disabled{cursor:not-allowed;opacity:.5}.claude-overlay-spinner{animation:claude-spin 1s linear infinite}@keyframes claude-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.claude-overlay-slide-enter-active,.claude-overlay-slide-leave-active{transition:opacity .2s,transform .2s}.claude-overlay-slide-enter-from,.claude-overlay-slide-leave-to{opacity:0;transform:translateY(20px) scale(.95)}.claude-overlay-slide-right-enter-active,.claude-overlay-slide-right-leave-active{transition:transform .2s ease-out}.claude-overlay-slide-right-enter-from,.claude-overlay-slide-right-leave-to{transform:translateX(100%)}.claude-overlay-history-list::-webkit-scrollbar,.claude-overlay-messages::-webkit-scrollbar{width:6px}.claude-overlay-history-list::-webkit-scrollbar-track,.claude-overlay-messages::-webkit-scrollbar-track{background:transparent}.claude-overlay-history-list::-webkit-scrollbar-thumb,.claude-overlay-messages::-webkit-scrollbar-thumb{background:var(--claude-border);border-radius:3px}.claude-overlay-history-list::-webkit-scrollbar-thumb:hover,.claude-overlay-messages::-webkit-scrollbar-thumb:hover{background:var(--claude-text-muted)}@media (max-width:640px){.claude-overlay-fab{bottom:16px;height:52px;width:52px}.claude-overlay-fab-default{right:16px}.claude-overlay-panel{border-radius:var(--claude-radius) var(--claude-radius) 0 0;bottom:0;height:92vh;height:92dvh;left:0!important;max-height:92vh;max-height:92dvh;max-width:100%;right:0!important;width:100%}.claude-overlay-slide-enter-from,.claude-overlay-slide-leave-to{opacity:1;transform:translateY(100%)}.claude-overlay-slide-enter-active,.claude-overlay-slide-leave-active{transition:transform .3s ease-out}.claude-overlay-header{cursor:grab;touch-action:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.claude-overlay-header:active{cursor:grabbing}.claude-overlay-header:before{background:var(--claude-border);border-radius:2px;content:"";height:4px;left:50%;position:absolute;top:8px;transform:translateX(-50%);width:36px}.claude-overlay-header{padding-top:20px;position:relative}.claude-overlay-btn-icon{height:40px;width:40px}.claude-overlay-input{font-size:16px}.claude-overlay-send-btn,.claude-overlay-voice-btn{height:44px;width:44px}.claude-overlay-input-container{padding-bottom:calc(12px + env(safe-area-inset-bottom, 0px))}}.claude-overlay-modal-backdrop{align-items:center;background:rgba(0,0,0,.6);display:flex;inset:0;justify-content:center;padding:20px;position:fixed;z-index:100000}.claude-overlay-modal{background:var(--claude-bg);border-radius:var(--claude-radius);box-shadow:0 8px 32px rgba(0,0,0,.4);max-width:360px;width:100%}.claude-overlay-modal-header{align-items:center;border-bottom:1px solid var(--claude-border);display:flex;justify-content:space-between;padding:16px 16px 12px}.claude-overlay-modal-header h3{font-size:16px;font-weight:600;margin:0}.claude-overlay-modal-body{padding:16px}.claude-overlay-modal-hint{color:var(--claude-text-muted);font-size:13px;margin:0 0 12px}.claude-overlay-modal-input{background:var(--claude-bg-elevated);border:1px solid var(--claude-border);border-radius:var(--claude-radius-sm);color:var(--claude-text);font-family:inherit;font-size:14px;padding:10px 12px;width:100%}.claude-overlay-modal-input:focus{border-color:var(--claude-primary);outline:none}.claude-overlay-modal-input::-moz-placeholder{color:var(--claude-text-muted)}.claude-overlay-modal-input::placeholder{color:var(--claude-text-muted)}.claude-overlay-modal-error{color:#ef4444;font-size:13px;margin:8px 0 0}.claude-overlay-modal-actions{display:flex;gap:8px;justify-content:flex-end;padding:12px 16px 16px}.claude-overlay-modal-btn-primary,.claude-overlay-modal-btn-secondary{border:none;border-radius:var(--claude-radius-sm);cursor:pointer;font-size:14px;font-weight:500;padding:8px 16px;transition:background .2s,opacity .2s}.claude-overlay-modal-btn-secondary{background:var(--claude-bg-elevated);color:var(--claude-text)}.claude-overlay-modal-btn-secondary:hover{background:var(--claude-bg-hover)}.claude-overlay-modal-btn-primary{background:var(--claude-primary);color:#fff}.claude-overlay-modal-btn-primary:hover:not(:disabled){background:var(--claude-primary-hover)}.claude-overlay-modal-btn-primary:disabled{cursor:not-allowed;opacity:.5}
|
|
382
|
+
:root{--claude-primary:#fe9a00;--claude-primary-hover:#ffb340;--claude-primary-dark:#e58a00;--claude-primary-glow:rgba(254,154,0,.5);--claude-glass:hsla(0,0%,100%,.05);--claude-glass-elevated:hsla(0,0%,100%,.08);--claude-glass-hover:hsla(0,0%,100%,.12);--claude-glass-solid:rgba(12,12,18,.88);--claude-text:hsla(0,0%,100%,.95);--claude-text-muted:hsla(0,0%,100%,.5);--claude-text-dim:hsla(0,0%,100%,.3);--claude-border:hsla(0,0%,100%,.1);--claude-border-light:hsla(0,0%,100%,.15);--claude-user-bg:linear-gradient(135deg,rgba(254,154,0,.25),rgba(251,191,36,.15));--claude-assistant-bg:hsla(0,0%,100%,.06);--claude-other-user-bg:linear-gradient(135deg,rgba(244,63,94,.2),rgba(254,154,0,.15));--claude-system-bg:hsla(0,0%,100%,.04);--claude-blur:20px;--claude-blur-heavy:40px;--claude-radius:20px;--claude-radius-sm:12px;--claude-radius-xs:8px;--claude-shadow:0 8px 32px rgba(0,0,0,.3);--claude-shadow-lg:0 25px 50px -12px rgba(0,0,0,.5);--claude-glow:0 0 40px var(--claude-primary-glow)}.claude-backdrop{background:rgba(0,0,0,.4);inset:0;position:fixed;z-index:99997}.claude-fade-enter-active,.claude-fade-leave-active{transition:opacity .3s ease}.claude-fade-enter-from,.claude-fade-leave-to{opacity:0}.claude-panel{backdrop-filter:blur(var(--claude-blur-heavy));-webkit-backdrop-filter:blur(var(--claude-blur-heavy));background:var(--claude-glass-solid);border:1px solid var(--claude-border-light);border-radius:var(--claude-radius);box-shadow:var(--claude-shadow-lg),inset 0 1px 0 hsla(0,0%,100%,.1),inset 0 -1px 0 rgba(0,0,0,.1);color:var(--claude-text);display:flex;flex-direction:column;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:14px;max-height:calc(100vh - 48px);max-width:calc(100vw - 48px);min-height:400px;min-width:320px;overflow:hidden;position:fixed;z-index:99999}.claude-panel:before{background:linear-gradient(180deg,rgba(254,154,0,.04),transparent 30%,transparent 70%,rgba(251,191,36,.02));border-radius:inherit;content:"";inset:0;pointer-events:none;position:absolute}.claude-panel-dragging,.claude-panel-resizing{transition:none!important;-webkit-user-select:none;-moz-user-select:none;user-select:none}.claude-panel-dragging{cursor:grabbing}.claude-resize-edge{position:absolute;z-index:100}.claude-resize-n{top:0}.claude-resize-n,.claude-resize-s{cursor:ns-resize;height:8px;left:16px;right:16px}.claude-resize-s{bottom:0}.claude-resize-e{right:0}.claude-resize-e,.claude-resize-w{bottom:16px;cursor:ew-resize;top:16px;width:8px}.claude-resize-w{left:0}.claude-resize-corner{height:16px;position:absolute;width:16px;z-index:101}.claude-resize-corner:before{content:"";height:12px;opacity:0;position:absolute;transition:opacity .2s ease;width:12px}.claude-resize-active:before,.claude-resize-corner:hover:before{opacity:1}.claude-resize-nw{cursor:nwse-resize;left:0;top:0}.claude-resize-ne{cursor:nesw-resize;right:0;top:0}.claude-resize-sw{bottom:0;cursor:nesw-resize;left:0}.claude-resize-se{bottom:0;cursor:nwse-resize;right:0}.claude-resize-nw:before{border-left:3px solid var(--claude-primary);border-radius:4px 0 0 0;left:2px}.claude-resize-ne:before,.claude-resize-nw:before{border-top:3px solid var(--claude-primary);box-shadow:0 0 10px var(--claude-primary-glow);top:2px}.claude-resize-ne:before{border-radius:0 4px 0 0;border-right:3px solid var(--claude-primary);right:2px}.claude-resize-sw:before{border-left:3px solid var(--claude-primary);border-radius:0 0 0 4px;left:2px}.claude-resize-se:before,.claude-resize-sw:before{border-bottom:3px solid var(--claude-primary);bottom:2px;box-shadow:0 0 10px var(--claude-primary-glow)}.claude-resize-se:before{border-radius:0 0 4px 0;border-right:3px solid var(--claude-primary);right:2px}.claude-drag-bumper,.claude-drag-handle-bar{display:none}.claude-slide-enter-active,.claude-slide-leave-active{transition:all .35s cubic-bezier(.4,0,.2,1)}.claude-slide-enter-from,.claude-slide-leave-to{opacity:0;transform:scale(.3)}@media (max-width:640px){.claude-panel{border-radius:var(--claude-radius) var(--claude-radius) 0 0;bottom:0!important;height:96dvh!important;left:0!important;max-height:96dvh;max-width:100%;min-height:auto;min-width:auto;right:0!important;top:auto!important;transform-origin:bottom center;width:100%!important}.claude-slide-enter-from,.claude-slide-leave-to{opacity:1;transform:translateY(100%)}.claude-slide-enter-active,.claude-slide-leave-active{transition:transform .35s cubic-bezier(.4,0,.2,1)}.claude-drag-bumper{align-items:center;background:hsla(0,0%,100%,.06);border-bottom:1px solid hsla(0,0%,100%,.08);cursor:grab;display:flex;flex-shrink:0;justify-content:center;padding:10px 20px;touch-action:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}.claude-drag-bumper:active{background:hsla(0,0%,100%,.1);cursor:grabbing}.claude-drag-handle-bar{background:hsla(0,0%,100%,.35);border-radius:2px;display:block;height:4px;width:40px}}
|
|
893
383
|
</style>
|