@ewjdev/anyclick-react 2.0.0 → 4.0.0
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/dist/chunk-7KW4HSJM.mjs +35 -0
- package/dist/chunk-7KW4HSJM.mjs.map +1 -0
- package/dist/chunk-YBHJXEH6.mjs +305 -0
- package/dist/chunk-YBHJXEH6.mjs.map +1 -0
- package/dist/index.css +23 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.mts +419 -11
- package/dist/index.d.ts +419 -11
- package/dist/index.js +2539 -310
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2514 -279
- package/dist/index.mjs.map +1 -1
- package/dist/token-EXBG54PO.mjs +66 -0
- package/dist/token-EXBG54PO.mjs.map +1 -0
- package/dist/token-util-4XOQ3GFX.mjs +6 -0
- package/dist/token-util-4XOQ3GFX.mjs.map +1 -0
- package/package.json +20 -9
package/dist/index.mjs
CHANGED
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
// src/AnyclickProvider.tsx
|
|
4
4
|
import {
|
|
5
|
-
useCallback as
|
|
6
|
-
useEffect as
|
|
5
|
+
useCallback as useCallback4,
|
|
6
|
+
useEffect as useEffect4,
|
|
7
7
|
useId,
|
|
8
8
|
useLayoutEffect,
|
|
9
|
-
useMemo as
|
|
10
|
-
useRef as
|
|
11
|
-
useState as
|
|
9
|
+
useMemo as useMemo4,
|
|
10
|
+
useRef as useRef4,
|
|
11
|
+
useState as useState5
|
|
12
12
|
} from "react";
|
|
13
13
|
import { createAnyclickClient } from "@ewjdev/anyclick-core";
|
|
14
14
|
|
|
15
15
|
// src/ContextMenu.tsx
|
|
16
|
-
import
|
|
16
|
+
import React3, { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef3, useState as useState4 } from "react";
|
|
17
17
|
import {
|
|
18
18
|
DEFAULT_SCREENSHOT_CONFIG,
|
|
19
19
|
captureAllScreenshots,
|
|
@@ -26,11 +26,1884 @@ import {
|
|
|
26
26
|
FlagIcon,
|
|
27
27
|
GripVertical,
|
|
28
28
|
PlusIcon,
|
|
29
|
+
Sparkles,
|
|
29
30
|
ThumbsUpIcon
|
|
30
31
|
} from "lucide-react";
|
|
31
32
|
|
|
33
|
+
// src/QuickChat/QuickChat.tsx
|
|
34
|
+
import React, {
|
|
35
|
+
useCallback as useCallback2,
|
|
36
|
+
useEffect as useEffect2,
|
|
37
|
+
useMemo as useMemo2,
|
|
38
|
+
useRef as useRef2,
|
|
39
|
+
useState as useState2
|
|
40
|
+
} from "react";
|
|
41
|
+
import { buildAnyclickPayload } from "@ewjdev/anyclick-core";
|
|
42
|
+
import {
|
|
43
|
+
AlertCircle,
|
|
44
|
+
ChevronDown,
|
|
45
|
+
ChevronLeft,
|
|
46
|
+
ChevronUp,
|
|
47
|
+
Copy,
|
|
48
|
+
ExternalLink,
|
|
49
|
+
Pin,
|
|
50
|
+
PinOff,
|
|
51
|
+
RefreshCw,
|
|
52
|
+
Send,
|
|
53
|
+
X
|
|
54
|
+
} from "lucide-react";
|
|
55
|
+
|
|
56
|
+
// src/QuickChat/styles.ts
|
|
57
|
+
var quickChatStyles = {
|
|
58
|
+
// Inline container - inside the context menu
|
|
59
|
+
container: {
|
|
60
|
+
display: "flex",
|
|
61
|
+
flexDirection: "column",
|
|
62
|
+
width: "100%",
|
|
63
|
+
maxHeight: "320px",
|
|
64
|
+
overflow: "hidden"
|
|
65
|
+
},
|
|
66
|
+
// Pinned drawer - anchored to right side of screen
|
|
67
|
+
pinnedContainer: {
|
|
68
|
+
position: "fixed",
|
|
69
|
+
top: 0,
|
|
70
|
+
right: 0,
|
|
71
|
+
bottom: 0,
|
|
72
|
+
width: "340px",
|
|
73
|
+
display: "flex",
|
|
74
|
+
flexDirection: "column",
|
|
75
|
+
backgroundColor: "var(--anyclick-menu-bg, #ffffff)",
|
|
76
|
+
borderLeft: "1px solid var(--anyclick-menu-border, #e5e5e5)",
|
|
77
|
+
boxShadow: "-4px 0 24px rgba(0, 0, 0, 0.15)",
|
|
78
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
79
|
+
fontSize: "14px",
|
|
80
|
+
overflow: "hidden",
|
|
81
|
+
zIndex: 9998
|
|
82
|
+
},
|
|
83
|
+
// Pinned messages area (taller)
|
|
84
|
+
pinnedMessagesArea: {
|
|
85
|
+
flex: 1,
|
|
86
|
+
overflowY: "auto",
|
|
87
|
+
padding: "12px",
|
|
88
|
+
display: "flex",
|
|
89
|
+
flexDirection: "column",
|
|
90
|
+
gap: "8px",
|
|
91
|
+
minHeight: "200px"
|
|
92
|
+
},
|
|
93
|
+
// Header - minimal design
|
|
94
|
+
header: {
|
|
95
|
+
display: "flex",
|
|
96
|
+
alignItems: "center",
|
|
97
|
+
justifyContent: "space-between",
|
|
98
|
+
padding: "6px 8px",
|
|
99
|
+
gap: "8px"
|
|
100
|
+
},
|
|
101
|
+
headerTitle: {
|
|
102
|
+
fontSize: "11px",
|
|
103
|
+
fontWeight: 600,
|
|
104
|
+
textTransform: "uppercase",
|
|
105
|
+
letterSpacing: "0.5px",
|
|
106
|
+
color: "var(--anyclick-menu-text-muted, #666)"
|
|
107
|
+
},
|
|
108
|
+
headerActions: {
|
|
109
|
+
display: "flex",
|
|
110
|
+
alignItems: "center",
|
|
111
|
+
gap: "2px"
|
|
112
|
+
},
|
|
113
|
+
iconButton: {
|
|
114
|
+
display: "flex",
|
|
115
|
+
alignItems: "center",
|
|
116
|
+
justifyContent: "center",
|
|
117
|
+
width: "24px",
|
|
118
|
+
height: "24px",
|
|
119
|
+
border: "none",
|
|
120
|
+
borderRadius: "4px",
|
|
121
|
+
backgroundColor: "transparent",
|
|
122
|
+
color: "var(--anyclick-menu-text-muted, #666)",
|
|
123
|
+
cursor: "pointer",
|
|
124
|
+
transition: "all 0.15s ease"
|
|
125
|
+
},
|
|
126
|
+
iconButtonActive: {
|
|
127
|
+
backgroundColor: "var(--anyclick-menu-accent, #0066cc)",
|
|
128
|
+
color: "#fff"
|
|
129
|
+
},
|
|
130
|
+
// Context badge in header
|
|
131
|
+
contextBadge: {
|
|
132
|
+
display: "inline-flex",
|
|
133
|
+
alignItems: "center",
|
|
134
|
+
gap: "4px",
|
|
135
|
+
padding: "3px 8px",
|
|
136
|
+
fontSize: "10px",
|
|
137
|
+
fontWeight: 500,
|
|
138
|
+
border: "1px solid var(--anyclick-menu-border, #e5e5e5)",
|
|
139
|
+
borderRadius: "10px",
|
|
140
|
+
backgroundColor: "transparent",
|
|
141
|
+
color: "var(--anyclick-menu-text-muted, #666)",
|
|
142
|
+
cursor: "pointer",
|
|
143
|
+
transition: "all 0.15s ease"
|
|
144
|
+
},
|
|
145
|
+
contextBadgeActive: {
|
|
146
|
+
borderColor: "var(--anyclick-menu-accent, #0066cc)",
|
|
147
|
+
backgroundColor: "rgba(0, 102, 204, 0.08)"
|
|
148
|
+
},
|
|
149
|
+
// Context dropdown (in normal flow, not absolute)
|
|
150
|
+
contextDropdown: {
|
|
151
|
+
display: "flex",
|
|
152
|
+
flexDirection: "column",
|
|
153
|
+
gap: "2px",
|
|
154
|
+
padding: "6px 8px",
|
|
155
|
+
margin: "0 8px 6px 8px",
|
|
156
|
+
backgroundColor: "var(--anyclick-menu-hover, #f5f5f5)",
|
|
157
|
+
borderRadius: "6px",
|
|
158
|
+
maxHeight: "80px",
|
|
159
|
+
overflowY: "auto"
|
|
160
|
+
},
|
|
161
|
+
// Messages area
|
|
162
|
+
messagesArea: {
|
|
163
|
+
flex: 1,
|
|
164
|
+
overflowY: "auto",
|
|
165
|
+
padding: "8px 12px",
|
|
166
|
+
display: "flex",
|
|
167
|
+
flexDirection: "column",
|
|
168
|
+
gap: "8px",
|
|
169
|
+
minHeight: "40px",
|
|
170
|
+
maxHeight: "140px"
|
|
171
|
+
},
|
|
172
|
+
emptyState: {
|
|
173
|
+
display: "none"
|
|
174
|
+
// Hide empty state, placeholder in input is enough
|
|
175
|
+
},
|
|
176
|
+
// Message bubble
|
|
177
|
+
message: {
|
|
178
|
+
display: "flex",
|
|
179
|
+
flexDirection: "column",
|
|
180
|
+
gap: "4px",
|
|
181
|
+
maxWidth: "100%"
|
|
182
|
+
},
|
|
183
|
+
messageUser: {
|
|
184
|
+
alignSelf: "flex-end",
|
|
185
|
+
backgroundColor: "var(--anyclick-menu-accent, #0066cc)",
|
|
186
|
+
color: "#fff",
|
|
187
|
+
padding: "6px 10px",
|
|
188
|
+
borderRadius: "12px 12px 4px 12px",
|
|
189
|
+
fontSize: "13px",
|
|
190
|
+
maxWidth: "85%",
|
|
191
|
+
wordBreak: "break-word"
|
|
192
|
+
},
|
|
193
|
+
messageAssistant: {
|
|
194
|
+
alignSelf: "flex-start",
|
|
195
|
+
backgroundColor: "var(--anyclick-menu-hover, #f5f5f5)",
|
|
196
|
+
color: "var(--anyclick-menu-text, #333)",
|
|
197
|
+
padding: "8px 10px",
|
|
198
|
+
borderRadius: "12px 12px 12px 4px",
|
|
199
|
+
fontSize: "13px",
|
|
200
|
+
maxWidth: "100%",
|
|
201
|
+
wordBreak: "break-word",
|
|
202
|
+
lineHeight: 1.4
|
|
203
|
+
},
|
|
204
|
+
messageActions: {
|
|
205
|
+
display: "flex",
|
|
206
|
+
gap: "4px",
|
|
207
|
+
marginTop: "4px",
|
|
208
|
+
flexWrap: "wrap"
|
|
209
|
+
},
|
|
210
|
+
actionButton: {
|
|
211
|
+
display: "inline-flex",
|
|
212
|
+
alignItems: "center",
|
|
213
|
+
gap: "4px",
|
|
214
|
+
padding: "3px 8px",
|
|
215
|
+
fontSize: "11px",
|
|
216
|
+
fontWeight: 500,
|
|
217
|
+
border: "1px solid var(--anyclick-menu-border, #e5e5e5)",
|
|
218
|
+
borderRadius: "4px",
|
|
219
|
+
backgroundColor: "transparent",
|
|
220
|
+
color: "var(--anyclick-menu-text-muted, #666)",
|
|
221
|
+
cursor: "pointer",
|
|
222
|
+
transition: "all 0.15s ease"
|
|
223
|
+
},
|
|
224
|
+
streamingIndicator: {
|
|
225
|
+
display: "inline-block",
|
|
226
|
+
width: "4px",
|
|
227
|
+
height: "14px",
|
|
228
|
+
backgroundColor: "var(--anyclick-menu-accent, #0066cc)",
|
|
229
|
+
borderRadius: "1px",
|
|
230
|
+
animation: "blink 1s infinite"
|
|
231
|
+
},
|
|
232
|
+
// Suggestions - compact horizontal scroll
|
|
233
|
+
suggestionsContainer: {
|
|
234
|
+
display: "flex",
|
|
235
|
+
flexDirection: "column",
|
|
236
|
+
gap: "6px",
|
|
237
|
+
padding: "6px 8px",
|
|
238
|
+
overflowX: "auto",
|
|
239
|
+
overflowY: "hidden",
|
|
240
|
+
scrollbarWidth: "none",
|
|
241
|
+
msOverflowStyle: "none"
|
|
242
|
+
},
|
|
243
|
+
suggestionChip: {
|
|
244
|
+
display: "inline-flex",
|
|
245
|
+
alignItems: "center",
|
|
246
|
+
padding: "4px 10px",
|
|
247
|
+
fontSize: "11px",
|
|
248
|
+
border: "1px solid var(--anyclick-menu-border, #e5e5e5)",
|
|
249
|
+
borderRadius: "12px",
|
|
250
|
+
backgroundColor: "var(--anyclick-menu-hover, #f5f5f5)",
|
|
251
|
+
color: "var(--anyclick-menu-text, #333)",
|
|
252
|
+
cursor: "pointer",
|
|
253
|
+
transition: "all 0.15s ease",
|
|
254
|
+
whiteSpace: "nowrap",
|
|
255
|
+
flexShrink: 0
|
|
256
|
+
},
|
|
257
|
+
suggestionChipHover: {
|
|
258
|
+
backgroundColor: "var(--anyclick-menu-bg, #fff)",
|
|
259
|
+
borderColor: "var(--anyclick-menu-accent, #0066cc)"
|
|
260
|
+
},
|
|
261
|
+
// Context redaction - now in dropdown
|
|
262
|
+
contextContainer: {
|
|
263
|
+
display: "flex",
|
|
264
|
+
flexDirection: "column",
|
|
265
|
+
gap: "4px"
|
|
266
|
+
},
|
|
267
|
+
contextHeader: {
|
|
268
|
+
display: "flex",
|
|
269
|
+
alignItems: "center",
|
|
270
|
+
justifyContent: "space-between",
|
|
271
|
+
marginBottom: "4px"
|
|
272
|
+
},
|
|
273
|
+
contextTitle: {
|
|
274
|
+
fontSize: "10px",
|
|
275
|
+
fontWeight: 600,
|
|
276
|
+
textTransform: "uppercase",
|
|
277
|
+
letterSpacing: "0.5px",
|
|
278
|
+
color: "var(--anyclick-menu-text-muted, #666)"
|
|
279
|
+
},
|
|
280
|
+
contextToggle: {
|
|
281
|
+
fontSize: "10px",
|
|
282
|
+
color: "var(--anyclick-menu-accent, #0066cc)",
|
|
283
|
+
background: "none",
|
|
284
|
+
border: "none",
|
|
285
|
+
cursor: "pointer",
|
|
286
|
+
padding: 0
|
|
287
|
+
},
|
|
288
|
+
contextToggleSmall: {
|
|
289
|
+
fontSize: "9px",
|
|
290
|
+
fontWeight: 500,
|
|
291
|
+
color: "var(--anyclick-menu-text-muted, #666)",
|
|
292
|
+
background: "none",
|
|
293
|
+
border: "none",
|
|
294
|
+
cursor: "pointer",
|
|
295
|
+
padding: "2px 4px",
|
|
296
|
+
borderRadius: "3px",
|
|
297
|
+
transition: "all 0.15s ease"
|
|
298
|
+
},
|
|
299
|
+
contextChunks: {
|
|
300
|
+
display: "flex",
|
|
301
|
+
flexDirection: "column",
|
|
302
|
+
gap: "4px"
|
|
303
|
+
},
|
|
304
|
+
contextChunk: {
|
|
305
|
+
display: "flex",
|
|
306
|
+
alignItems: "center",
|
|
307
|
+
gap: "6px",
|
|
308
|
+
padding: "4px 6px",
|
|
309
|
+
borderRadius: "4px",
|
|
310
|
+
fontSize: "11px",
|
|
311
|
+
backgroundColor: "var(--anyclick-menu-hover, #f5f5f5)",
|
|
312
|
+
cursor: "pointer",
|
|
313
|
+
transition: "opacity 0.15s ease"
|
|
314
|
+
},
|
|
315
|
+
contextChunkCompact: {
|
|
316
|
+
display: "flex",
|
|
317
|
+
alignItems: "center",
|
|
318
|
+
gap: "6px",
|
|
319
|
+
padding: "2px 4px",
|
|
320
|
+
borderRadius: "3px",
|
|
321
|
+
fontSize: "10px",
|
|
322
|
+
cursor: "pointer",
|
|
323
|
+
transition: "opacity 0.15s ease"
|
|
324
|
+
},
|
|
325
|
+
contextChunkExcluded: {
|
|
326
|
+
opacity: 0.5,
|
|
327
|
+
textDecoration: "line-through"
|
|
328
|
+
},
|
|
329
|
+
contextCheckbox: {
|
|
330
|
+
width: "12px",
|
|
331
|
+
height: "12px",
|
|
332
|
+
accentColor: "var(--anyclick-menu-accent, #0066cc)"
|
|
333
|
+
},
|
|
334
|
+
contextLabel: {
|
|
335
|
+
flex: 1,
|
|
336
|
+
overflow: "hidden",
|
|
337
|
+
textOverflow: "ellipsis",
|
|
338
|
+
whiteSpace: "nowrap",
|
|
339
|
+
color: "var(--anyclick-menu-text, #333)"
|
|
340
|
+
},
|
|
341
|
+
contextSize: {
|
|
342
|
+
fontSize: "10px",
|
|
343
|
+
color: "var(--anyclick-menu-text-muted, #666)"
|
|
344
|
+
},
|
|
345
|
+
// Input area
|
|
346
|
+
inputContainer: {
|
|
347
|
+
display: "flex",
|
|
348
|
+
alignItems: "flex-end",
|
|
349
|
+
gap: "8px",
|
|
350
|
+
padding: "8px"
|
|
351
|
+
},
|
|
352
|
+
input: {
|
|
353
|
+
flex: 1,
|
|
354
|
+
padding: "8px 12px",
|
|
355
|
+
fontSize: "13px",
|
|
356
|
+
border: "1px solid var(--anyclick-menu-input-border, #ddd)",
|
|
357
|
+
borderRadius: "18px",
|
|
358
|
+
backgroundColor: "var(--anyclick-menu-input-bg, #fff)",
|
|
359
|
+
color: "var(--anyclick-menu-text, #333)",
|
|
360
|
+
outline: "none",
|
|
361
|
+
resize: "none",
|
|
362
|
+
fontFamily: "inherit",
|
|
363
|
+
lineHeight: 1.4,
|
|
364
|
+
maxHeight: "80px",
|
|
365
|
+
minHeight: "36px"
|
|
366
|
+
},
|
|
367
|
+
inputFocused: {
|
|
368
|
+
borderColor: "var(--anyclick-menu-accent, #0066cc)",
|
|
369
|
+
boxShadow: "0 0 0 2px rgba(0, 102, 204, 0.1)"
|
|
370
|
+
},
|
|
371
|
+
sendButton: {
|
|
372
|
+
display: "flex",
|
|
373
|
+
alignItems: "center",
|
|
374
|
+
justifyContent: "center",
|
|
375
|
+
width: "32px",
|
|
376
|
+
height: "32px",
|
|
377
|
+
border: "none",
|
|
378
|
+
borderRadius: "50%",
|
|
379
|
+
backgroundColor: "var(--anyclick-menu-accent, #0066cc)",
|
|
380
|
+
color: "#fff",
|
|
381
|
+
cursor: "pointer",
|
|
382
|
+
transition: "all 0.15s ease",
|
|
383
|
+
flexShrink: 0
|
|
384
|
+
},
|
|
385
|
+
sendButtonDisabled: {
|
|
386
|
+
backgroundColor: "var(--anyclick-menu-border, #e5e5e5)",
|
|
387
|
+
cursor: "not-allowed"
|
|
388
|
+
},
|
|
389
|
+
// Loading states
|
|
390
|
+
loadingDots: {
|
|
391
|
+
display: "flex",
|
|
392
|
+
gap: "4px",
|
|
393
|
+
padding: "8px"
|
|
394
|
+
},
|
|
395
|
+
loadingDot: {
|
|
396
|
+
width: "6px",
|
|
397
|
+
height: "6px",
|
|
398
|
+
borderRadius: "50%",
|
|
399
|
+
backgroundColor: "var(--anyclick-menu-text-muted, #666)",
|
|
400
|
+
animation: "bounce 1.4s infinite ease-in-out both"
|
|
401
|
+
},
|
|
402
|
+
// Error states
|
|
403
|
+
errorContainer: {
|
|
404
|
+
display: "flex",
|
|
405
|
+
flexDirection: "column",
|
|
406
|
+
alignItems: "center",
|
|
407
|
+
gap: "8px",
|
|
408
|
+
padding: "16px",
|
|
409
|
+
textAlign: "center"
|
|
410
|
+
},
|
|
411
|
+
errorIcon: {
|
|
412
|
+
color: "#ef4444"
|
|
413
|
+
},
|
|
414
|
+
errorText: {
|
|
415
|
+
fontSize: "12px",
|
|
416
|
+
color: "#ef4444",
|
|
417
|
+
maxWidth: "200px"
|
|
418
|
+
},
|
|
419
|
+
errorRetry: {
|
|
420
|
+
display: "inline-flex",
|
|
421
|
+
alignItems: "center",
|
|
422
|
+
gap: "4px",
|
|
423
|
+
padding: "4px 10px",
|
|
424
|
+
fontSize: "11px",
|
|
425
|
+
fontWeight: 500,
|
|
426
|
+
border: "1px solid #ef4444",
|
|
427
|
+
borderRadius: "4px",
|
|
428
|
+
backgroundColor: "transparent",
|
|
429
|
+
color: "#ef4444",
|
|
430
|
+
cursor: "pointer",
|
|
431
|
+
transition: "all 0.15s ease"
|
|
432
|
+
},
|
|
433
|
+
// Truncation indicator
|
|
434
|
+
truncated: {
|
|
435
|
+
fontSize: "10px",
|
|
436
|
+
color: "var(--anyclick-menu-text-muted, #666)",
|
|
437
|
+
fontStyle: "italic",
|
|
438
|
+
marginTop: "4px"
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
var quickChatKeyframes = `
|
|
442
|
+
@keyframes blink {
|
|
443
|
+
0%, 50% { opacity: 1; }
|
|
444
|
+
51%, 100% { opacity: 0; }
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
@keyframes bounce {
|
|
448
|
+
0%, 80%, 100% { transform: scale(0); }
|
|
449
|
+
40% { transform: scale(1); }
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
@keyframes slideIn {
|
|
453
|
+
from {
|
|
454
|
+
opacity: 0;
|
|
455
|
+
transform: translateY(-8px);
|
|
456
|
+
}
|
|
457
|
+
to {
|
|
458
|
+
opacity: 1;
|
|
459
|
+
transform: translateY(0);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
@keyframes slideInFromRight {
|
|
464
|
+
from {
|
|
465
|
+
transform: translateX(100%);
|
|
466
|
+
}
|
|
467
|
+
to {
|
|
468
|
+
transform: translateX(0);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
@keyframes slideOutToRight {
|
|
473
|
+
from {
|
|
474
|
+
transform: translateX(0);
|
|
475
|
+
}
|
|
476
|
+
to {
|
|
477
|
+
transform: translateX(100%);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
@keyframes fadeIn {
|
|
482
|
+
from { opacity: 0; }
|
|
483
|
+
to { opacity: 1; }
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
@keyframes spin {
|
|
487
|
+
from { transform: rotate(0deg); }
|
|
488
|
+
to { transform: rotate(360deg); }
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
@keyframes pulse {
|
|
492
|
+
0%, 100% { opacity: 1; }
|
|
493
|
+
50% { opacity: 0.5; }
|
|
494
|
+
}
|
|
495
|
+
`;
|
|
496
|
+
|
|
497
|
+
// src/QuickChat/useQuickChat.ts
|
|
498
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
499
|
+
import { useChat } from "@ai-sdk/react";
|
|
500
|
+
import { DefaultChatTransport } from "ai";
|
|
501
|
+
|
|
502
|
+
// src/QuickChat/store.ts
|
|
503
|
+
import { create } from "zustand";
|
|
504
|
+
import { createJSONStorage, persist } from "zustand/middleware";
|
|
505
|
+
var STORE_NAME = "anyclick-quick-chat-store";
|
|
506
|
+
var TWENTY_FOUR_HOURS_MS = 24 * 60 * 60 * 1e3;
|
|
507
|
+
function generateMessageId() {
|
|
508
|
+
return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
509
|
+
}
|
|
510
|
+
var storage = createJSONStorage(() => localStorage);
|
|
511
|
+
function filterExpiredMessages(messages) {
|
|
512
|
+
const now = Date.now();
|
|
513
|
+
return messages.filter((msg) => msg.expiresAt > now);
|
|
514
|
+
}
|
|
515
|
+
var useQuickChatStore = create()(
|
|
516
|
+
persist(
|
|
517
|
+
(set, get) => ({
|
|
518
|
+
messages: [],
|
|
519
|
+
isPinned: false,
|
|
520
|
+
input: "",
|
|
521
|
+
contextChunks: [],
|
|
522
|
+
suggestedPrompts: [],
|
|
523
|
+
isLoadingSuggestions: false,
|
|
524
|
+
isSending: false,
|
|
525
|
+
isStreaming: false,
|
|
526
|
+
error: null,
|
|
527
|
+
lastSyncedAt: null,
|
|
528
|
+
setInput: (input) => set({ input }),
|
|
529
|
+
addMessage: (message) => {
|
|
530
|
+
const id = generateMessageId();
|
|
531
|
+
const now = Date.now();
|
|
532
|
+
const storedMessage = {
|
|
533
|
+
...message,
|
|
534
|
+
id,
|
|
535
|
+
timestamp: now,
|
|
536
|
+
expiresAt: now + TWENTY_FOUR_HOURS_MS
|
|
537
|
+
};
|
|
538
|
+
set((state) => {
|
|
539
|
+
const newMessages = [...state.messages, storedMessage];
|
|
540
|
+
return {
|
|
541
|
+
messages: newMessages
|
|
542
|
+
};
|
|
543
|
+
});
|
|
544
|
+
return id;
|
|
545
|
+
},
|
|
546
|
+
updateMessage: (id, updates) => {
|
|
547
|
+
set((state) => ({
|
|
548
|
+
messages: state.messages.map(
|
|
549
|
+
(msg) => msg.id === id ? { ...msg, ...updates } : msg
|
|
550
|
+
)
|
|
551
|
+
}));
|
|
552
|
+
},
|
|
553
|
+
clearMessages: () => set({ messages: [], error: null }),
|
|
554
|
+
setIsPinned: (pinned) => set({ isPinned: pinned }),
|
|
555
|
+
setContextChunks: (chunks) => set({ contextChunks: chunks }),
|
|
556
|
+
toggleChunk: (chunkId) => {
|
|
557
|
+
set((state) => ({
|
|
558
|
+
contextChunks: state.contextChunks.map(
|
|
559
|
+
(chunk) => chunk.id === chunkId ? { ...chunk, included: !chunk.included } : chunk
|
|
560
|
+
)
|
|
561
|
+
}));
|
|
562
|
+
},
|
|
563
|
+
toggleAllChunks: (included) => {
|
|
564
|
+
set((state) => ({
|
|
565
|
+
contextChunks: state.contextChunks.map((chunk) => ({
|
|
566
|
+
...chunk,
|
|
567
|
+
included
|
|
568
|
+
}))
|
|
569
|
+
}));
|
|
570
|
+
},
|
|
571
|
+
setSuggestedPrompts: (prompts) => set({ suggestedPrompts: prompts }),
|
|
572
|
+
setIsLoadingSuggestions: (loading) => set({ isLoadingSuggestions: loading }),
|
|
573
|
+
setIsSending: (sending) => set({ isSending: sending }),
|
|
574
|
+
setIsStreaming: (streaming) => set({ isStreaming: streaming }),
|
|
575
|
+
setError: (error) => set({ error }),
|
|
576
|
+
setLastSyncedAt: (timestamp) => set({ lastSyncedAt: timestamp }),
|
|
577
|
+
pruneExpiredMessages: () => {
|
|
578
|
+
set((state) => ({
|
|
579
|
+
messages: filterExpiredMessages(state.messages)
|
|
580
|
+
}));
|
|
581
|
+
},
|
|
582
|
+
getActiveMessages: () => {
|
|
583
|
+
const state = get();
|
|
584
|
+
const now = Date.now();
|
|
585
|
+
const active = state.messages.filter((msg) => msg.expiresAt > now).map(({ expiresAt, ...msg }) => msg);
|
|
586
|
+
console.log("[store] getActiveMessages", {
|
|
587
|
+
totalMessages: state.messages.length,
|
|
588
|
+
activeMessages: active.length,
|
|
589
|
+
activeIds: active.map((m) => m.id)
|
|
590
|
+
});
|
|
591
|
+
return active;
|
|
592
|
+
},
|
|
593
|
+
hydrate: (messages) => {
|
|
594
|
+
const now = Date.now();
|
|
595
|
+
const storedMessages = messages.map((msg) => ({
|
|
596
|
+
...msg,
|
|
597
|
+
expiresAt: now + TWENTY_FOUR_HOURS_MS
|
|
598
|
+
}));
|
|
599
|
+
set({ messages: storedMessages, lastSyncedAt: now });
|
|
600
|
+
}
|
|
601
|
+
}),
|
|
602
|
+
{
|
|
603
|
+
name: STORE_NAME,
|
|
604
|
+
storage,
|
|
605
|
+
partialize: (state) => ({
|
|
606
|
+
messages: state.messages,
|
|
607
|
+
isPinned: state.isPinned,
|
|
608
|
+
lastSyncedAt: state.lastSyncedAt
|
|
609
|
+
}),
|
|
610
|
+
onRehydrateStorage: () => (state) => {
|
|
611
|
+
if (state) {
|
|
612
|
+
state.pruneExpiredMessages();
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
)
|
|
617
|
+
);
|
|
618
|
+
function useActiveMessages() {
|
|
619
|
+
const messages = useQuickChatStore((state) => state.messages);
|
|
620
|
+
const now = Date.now();
|
|
621
|
+
return messages.filter((msg) => msg.expiresAt > now).map(({ expiresAt, ...msg }) => msg);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// src/QuickChat/types.ts
|
|
625
|
+
var DEFAULT_T3CHAT_CONFIG = {
|
|
626
|
+
enabled: true,
|
|
627
|
+
baseUrl: "https://t3.chat",
|
|
628
|
+
label: "Ask t3.chat"
|
|
629
|
+
};
|
|
630
|
+
var DEFAULT_QUICK_CHAT_CONFIG = {
|
|
631
|
+
endpoint: "/api/anyclick/chat",
|
|
632
|
+
model: "gpt-5-nano",
|
|
633
|
+
prePassModel: "gpt-5-nano",
|
|
634
|
+
maxResponseLength: 1e4,
|
|
635
|
+
showRedactionUI: true,
|
|
636
|
+
showSuggestions: true,
|
|
637
|
+
systemPrompt: "You are a helpful assistant that provides quick, concise answers about web elements and UI. Keep responses brief and actionable.",
|
|
638
|
+
placeholder: "Ask about this element...",
|
|
639
|
+
title: "Quick Ask",
|
|
640
|
+
t3chat: DEFAULT_T3CHAT_CONFIG
|
|
641
|
+
};
|
|
642
|
+
|
|
643
|
+
// src/QuickChat/useQuickChat.context.ts
|
|
644
|
+
import { getElementInspectInfo } from "@ewjdev/anyclick-core";
|
|
645
|
+
function extractContextChunks(targetElement, _containerElement) {
|
|
646
|
+
const chunks = [];
|
|
647
|
+
if (!targetElement) return chunks;
|
|
648
|
+
try {
|
|
649
|
+
const info = getElementInspectInfo(targetElement);
|
|
650
|
+
const tagContent = `<${info.tagName.toLowerCase()}${info.id ? ` id="${info.id}"` : ""}${info.classNames.length > 0 ? ` class="${info.classNames.join(" ")}"` : ""}>`;
|
|
651
|
+
chunks.push({
|
|
652
|
+
id: "element-tag",
|
|
653
|
+
label: "Element Tag",
|
|
654
|
+
content: tagContent,
|
|
655
|
+
type: "element",
|
|
656
|
+
included: true,
|
|
657
|
+
size: tagContent.length
|
|
658
|
+
});
|
|
659
|
+
if (info.innerText && info.innerText.length > 0) {
|
|
660
|
+
const textContent = info.innerText.slice(0, 200);
|
|
661
|
+
chunks.push({
|
|
662
|
+
id: "element-text",
|
|
663
|
+
label: "Text Content",
|
|
664
|
+
content: textContent,
|
|
665
|
+
type: "text",
|
|
666
|
+
included: true,
|
|
667
|
+
size: textContent.length
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
if (info.computedStyles) {
|
|
671
|
+
const styleEntries = [];
|
|
672
|
+
for (const [, styles] of Object.entries(info.computedStyles)) {
|
|
673
|
+
if (styles && typeof styles === "object") {
|
|
674
|
+
const entries = Object.entries(styles).slice(0, 2);
|
|
675
|
+
for (const [k, v] of entries) {
|
|
676
|
+
if (v) styleEntries.push(`${k}: ${v}`);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
if (styleEntries.length >= 8) break;
|
|
680
|
+
}
|
|
681
|
+
const stylesContent = styleEntries.join("; ");
|
|
682
|
+
if (stylesContent) {
|
|
683
|
+
chunks.push({
|
|
684
|
+
id: "element-styles",
|
|
685
|
+
label: "Key Styles",
|
|
686
|
+
content: stylesContent,
|
|
687
|
+
type: "element",
|
|
688
|
+
included: true,
|
|
689
|
+
size: stylesContent.length
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
if (info.accessibility) {
|
|
694
|
+
const a11yContent = [
|
|
695
|
+
info.accessibility.role && `role="${info.accessibility.role}"`,
|
|
696
|
+
info.accessibility.accessibleName && `aria-label="${info.accessibility.accessibleName}"`
|
|
697
|
+
].filter(Boolean).join(", ");
|
|
698
|
+
if (a11yContent) {
|
|
699
|
+
chunks.push({
|
|
700
|
+
id: "element-a11y",
|
|
701
|
+
label: "Accessibility",
|
|
702
|
+
content: a11yContent,
|
|
703
|
+
type: "element",
|
|
704
|
+
included: true,
|
|
705
|
+
size: a11yContent.length
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
if (info.boxModel) {
|
|
710
|
+
const boxContent = `${Math.round(info.boxModel.content.width)}x${Math.round(
|
|
711
|
+
info.boxModel.content.height
|
|
712
|
+
)}px`;
|
|
713
|
+
chunks.push({
|
|
714
|
+
id: "element-dimensions",
|
|
715
|
+
label: "Dimensions",
|
|
716
|
+
content: boxContent,
|
|
717
|
+
type: "element",
|
|
718
|
+
included: true,
|
|
719
|
+
size: boxContent.length
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
} catch (error) {
|
|
723
|
+
console.error("[useQuickChat] Failed to extract context:", error);
|
|
724
|
+
}
|
|
725
|
+
return chunks;
|
|
726
|
+
}
|
|
727
|
+
function buildContextString(chunks) {
|
|
728
|
+
const included = chunks.filter((c) => c.included);
|
|
729
|
+
if (included.length === 0) return "";
|
|
730
|
+
return included.map((c) => `[${c.label}]: ${c.content}`).join("\n");
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
// src/QuickChat/useQuickChat.debug.ts
|
|
734
|
+
function createDebugInfo(args) {
|
|
735
|
+
return {
|
|
736
|
+
status: args.status,
|
|
737
|
+
ok: args.ok,
|
|
738
|
+
contentType: args.contentType ?? null,
|
|
739
|
+
rawTextPreview: args.rawText ?? "",
|
|
740
|
+
timestamp: Date.now(),
|
|
741
|
+
error: args.error
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
// src/QuickChat/useQuickChat.messages.ts
|
|
746
|
+
function getUIMessageText(msg) {
|
|
747
|
+
const partsText = msg.parts?.map((p) => {
|
|
748
|
+
const part = p;
|
|
749
|
+
if (typeof part.text === "string") return part.text;
|
|
750
|
+
if (typeof part.content === "string") return part.content;
|
|
751
|
+
return "";
|
|
752
|
+
}).join("") ?? "";
|
|
753
|
+
if (partsText) return partsText;
|
|
754
|
+
const maybeContent = msg.content;
|
|
755
|
+
return typeof maybeContent === "string" ? maybeContent : "";
|
|
756
|
+
}
|
|
757
|
+
function chatMessagesToUiMessages(messages) {
|
|
758
|
+
return messages.map((msg) => ({
|
|
759
|
+
id: msg.id,
|
|
760
|
+
role: msg.role,
|
|
761
|
+
parts: [{ type: "text", text: msg.content }]
|
|
762
|
+
}));
|
|
763
|
+
}
|
|
764
|
+
function safeCopyToClipboard(text) {
|
|
765
|
+
try {
|
|
766
|
+
if (typeof navigator === "undefined") return;
|
|
767
|
+
void navigator.clipboard.writeText(text);
|
|
768
|
+
} catch {
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
function buildAssistantActions(messageText, setInput) {
|
|
772
|
+
return [
|
|
773
|
+
{
|
|
774
|
+
id: "copy",
|
|
775
|
+
label: "Copy",
|
|
776
|
+
onClick: () => safeCopyToClipboard(messageText)
|
|
777
|
+
},
|
|
778
|
+
{
|
|
779
|
+
id: "research",
|
|
780
|
+
label: "Research more",
|
|
781
|
+
onClick: () => setInput(`Tell me more about: ${messageText.slice(0, 50)}`)
|
|
782
|
+
}
|
|
783
|
+
];
|
|
784
|
+
}
|
|
785
|
+
function uiMessagesToChatMessages(args) {
|
|
786
|
+
const { uiMessages, status, setInput } = args;
|
|
787
|
+
const last = uiMessages[uiMessages.length - 1];
|
|
788
|
+
return uiMessages.map((msg) => {
|
|
789
|
+
const text = getUIMessageText(msg);
|
|
790
|
+
const isStreaming = status === "streaming" && msg.role === "assistant" && msg === last;
|
|
791
|
+
const actions = msg.role === "assistant" && status === "ready" ? buildAssistantActions(text, setInput) : void 0;
|
|
792
|
+
return {
|
|
793
|
+
id: msg.id,
|
|
794
|
+
role: msg.role,
|
|
795
|
+
content: text,
|
|
796
|
+
timestamp: Date.now(),
|
|
797
|
+
isStreaming,
|
|
798
|
+
actions
|
|
799
|
+
};
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// src/QuickChat/useQuickChat.rateLimit.ts
|
|
804
|
+
function safeJsonParse(text) {
|
|
805
|
+
try {
|
|
806
|
+
return JSON.parse(text);
|
|
807
|
+
} catch {
|
|
808
|
+
return null;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
function formatRetryAt(retryAtMs) {
|
|
812
|
+
try {
|
|
813
|
+
const d = new Date(retryAtMs);
|
|
814
|
+
return new Intl.DateTimeFormat(void 0, {
|
|
815
|
+
hour: "numeric",
|
|
816
|
+
minute: "2-digit"
|
|
817
|
+
}).format(d);
|
|
818
|
+
} catch {
|
|
819
|
+
return new Date(retryAtMs).toLocaleTimeString();
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
function getRequestIdFromHeaders(res) {
|
|
823
|
+
return res?.headers?.get?.("X-Anyclick-Request-Id") ?? res?.headers?.get?.("x-anyclick-request-id") ?? void 0;
|
|
824
|
+
}
|
|
825
|
+
function parseRetryAfterSeconds(args) {
|
|
826
|
+
const { payload, res } = args;
|
|
827
|
+
if (typeof payload?.retryAfterSeconds === "number")
|
|
828
|
+
return payload.retryAfterSeconds;
|
|
829
|
+
const headerRetryAfter = res?.headers?.get?.("Retry-After");
|
|
830
|
+
if (!headerRetryAfter) return void 0;
|
|
831
|
+
const n = Number(headerRetryAfter);
|
|
832
|
+
return Number.isFinite(n) ? n : void 0;
|
|
833
|
+
}
|
|
834
|
+
function parseRetryAt(args) {
|
|
835
|
+
const { payload, retryAfterSeconds, nowMs } = args;
|
|
836
|
+
if (typeof payload?.retryAt === "number" && Number.isFinite(payload.retryAt)) {
|
|
837
|
+
return payload.retryAt;
|
|
838
|
+
}
|
|
839
|
+
if (typeof retryAfterSeconds === "number" && Number.isFinite(retryAfterSeconds)) {
|
|
840
|
+
return nowMs + Math.max(0, retryAfterSeconds) * 1e3;
|
|
841
|
+
}
|
|
842
|
+
return void 0;
|
|
843
|
+
}
|
|
844
|
+
function buildNotice(args) {
|
|
845
|
+
const { rawText, endpoint, res, nowMs } = args;
|
|
846
|
+
const parsed = safeJsonParse(rawText);
|
|
847
|
+
const payload = parsed && typeof parsed === "object" ? parsed : null;
|
|
848
|
+
const retryAfterSeconds = parseRetryAfterSeconds({ payload, res });
|
|
849
|
+
const retryAt = parseRetryAt({ payload, retryAfterSeconds, nowMs });
|
|
850
|
+
const timePart = retryAt ? `Try again at ${formatRetryAt(retryAt)}.` : "";
|
|
851
|
+
const message = timePart ? `Rate limited. ${timePart}` : "Rate limited.";
|
|
852
|
+
const requestId = payload?.requestId ?? getRequestIdFromHeaders(res);
|
|
853
|
+
return {
|
|
854
|
+
status: 429,
|
|
855
|
+
message,
|
|
856
|
+
retryAt,
|
|
857
|
+
retryAfterSeconds,
|
|
858
|
+
requestId,
|
|
859
|
+
endpoint,
|
|
860
|
+
raw: rawText
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
async function rateLimitNoticeFromResponse(res, endpoint) {
|
|
864
|
+
if (res.status !== 429) return null;
|
|
865
|
+
const raw = await res.text().catch(() => "");
|
|
866
|
+
return buildNotice({ rawText: raw, endpoint, res, nowMs: Date.now() });
|
|
867
|
+
}
|
|
868
|
+
function rateLimitNoticeFromError(args) {
|
|
869
|
+
const { statusCode, response, responseText, endpoint } = args;
|
|
870
|
+
if (statusCode !== 429) return null;
|
|
871
|
+
const raw = responseText ?? "";
|
|
872
|
+
return buildNotice({
|
|
873
|
+
rawText: raw,
|
|
874
|
+
endpoint,
|
|
875
|
+
res: response,
|
|
876
|
+
nowMs: Date.now()
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
// src/QuickChat/useQuickChat.ts
|
|
881
|
+
function useQuickChat(targetElement, containerElement, config = {}) {
|
|
882
|
+
console.count("useQuickChat");
|
|
883
|
+
const mergedConfig = { ...DEFAULT_QUICK_CHAT_CONFIG, ...config };
|
|
884
|
+
const initializedRef = useRef(false);
|
|
885
|
+
const syncTimeoutRef = useRef(null);
|
|
886
|
+
const [manualSending, setManualSending] = useState(false);
|
|
887
|
+
const [debugInfo, setDebugInfo] = useState(null);
|
|
888
|
+
const [rateLimitNotice, setRateLimitNotice] = useState(null);
|
|
889
|
+
const {
|
|
890
|
+
input,
|
|
891
|
+
setInput,
|
|
892
|
+
isPinned,
|
|
893
|
+
setIsPinned,
|
|
894
|
+
contextChunks,
|
|
895
|
+
setContextChunks,
|
|
896
|
+
toggleChunk,
|
|
897
|
+
toggleAllChunks,
|
|
898
|
+
suggestedPrompts,
|
|
899
|
+
setSuggestedPrompts,
|
|
900
|
+
isLoadingSuggestions,
|
|
901
|
+
setIsLoadingSuggestions,
|
|
902
|
+
error,
|
|
903
|
+
setError,
|
|
904
|
+
addMessage,
|
|
905
|
+
clearMessages: storeClearMessages,
|
|
906
|
+
setLastSyncedAt,
|
|
907
|
+
lastSyncedAt,
|
|
908
|
+
setIsSending: setStoreIsSending,
|
|
909
|
+
setIsStreaming: setStoreIsStreaming
|
|
910
|
+
} = useQuickChatStore();
|
|
911
|
+
const storedMessages = useActiveMessages();
|
|
912
|
+
const contextString = useMemo(
|
|
913
|
+
() => buildContextString(contextChunks),
|
|
914
|
+
[contextChunks]
|
|
915
|
+
);
|
|
916
|
+
const chatBody = useMemo(
|
|
917
|
+
() => ({
|
|
918
|
+
action: "chat",
|
|
919
|
+
context: contextString,
|
|
920
|
+
model: mergedConfig.model,
|
|
921
|
+
systemPrompt: mergedConfig.systemPrompt,
|
|
922
|
+
maxLength: mergedConfig.maxResponseLength
|
|
923
|
+
}),
|
|
924
|
+
[
|
|
925
|
+
contextString,
|
|
926
|
+
mergedConfig.model,
|
|
927
|
+
mergedConfig.systemPrompt,
|
|
928
|
+
mergedConfig.maxResponseLength
|
|
929
|
+
]
|
|
930
|
+
);
|
|
931
|
+
const transport = useMemo(
|
|
932
|
+
() => new DefaultChatTransport({
|
|
933
|
+
api: mergedConfig.endpoint,
|
|
934
|
+
body: chatBody
|
|
935
|
+
}),
|
|
936
|
+
[mergedConfig.endpoint, chatBody]
|
|
937
|
+
);
|
|
938
|
+
const handleRateLimitResponse = useCallback(
|
|
939
|
+
async (res, endpoint) => {
|
|
940
|
+
const notice = await rateLimitNoticeFromResponse(res, endpoint);
|
|
941
|
+
if (!notice) return false;
|
|
942
|
+
setRateLimitNotice(notice);
|
|
943
|
+
setError(null);
|
|
944
|
+
return true;
|
|
945
|
+
},
|
|
946
|
+
[setError]
|
|
947
|
+
);
|
|
948
|
+
const scheduleBackendSync = useCallback(() => {
|
|
949
|
+
if (syncTimeoutRef.current) clearTimeout(syncTimeoutRef.current);
|
|
950
|
+
syncTimeoutRef.current = setTimeout(async () => {
|
|
951
|
+
try {
|
|
952
|
+
const currentMessages = useQuickChatStore.getState().getActiveMessages();
|
|
953
|
+
if (currentMessages.length === 0) return;
|
|
954
|
+
const endpoint = `${mergedConfig.endpoint}/history`;
|
|
955
|
+
const res = await fetch(endpoint, {
|
|
956
|
+
method: "POST",
|
|
957
|
+
headers: { "Content-Type": "application/json" },
|
|
958
|
+
body: JSON.stringify({
|
|
959
|
+
action: "save",
|
|
960
|
+
messages: currentMessages
|
|
961
|
+
})
|
|
962
|
+
});
|
|
963
|
+
if (await handleRateLimitResponse(res, endpoint)) return;
|
|
964
|
+
if (res.ok) setLastSyncedAt(Date.now());
|
|
965
|
+
} catch (err) {
|
|
966
|
+
console.error("[useQuickChat] Failed to sync chat history:", err);
|
|
967
|
+
}
|
|
968
|
+
}, 1e3);
|
|
969
|
+
}, [handleRateLimitResponse, mergedConfig.endpoint, setLastSyncedAt]);
|
|
970
|
+
const {
|
|
971
|
+
messages: aiMessages,
|
|
972
|
+
sendMessage: aiSendMessage,
|
|
973
|
+
status,
|
|
974
|
+
stop,
|
|
975
|
+
setMessages: setAiMessages
|
|
976
|
+
} = useChat({
|
|
977
|
+
transport,
|
|
978
|
+
onError: (err) => {
|
|
979
|
+
const response = err.response ?? void 0;
|
|
980
|
+
const statusCode = err.status ?? (response ? response.status : void 0) ?? -1;
|
|
981
|
+
const responseText = err.responseText ?? err.message ?? "";
|
|
982
|
+
setDebugInfo(
|
|
983
|
+
createDebugInfo({
|
|
984
|
+
status: statusCode,
|
|
985
|
+
ok: false,
|
|
986
|
+
contentType: response?.headers?.get?.("content-type") ?? null,
|
|
987
|
+
rawText: responseText,
|
|
988
|
+
error: err.message
|
|
989
|
+
})
|
|
990
|
+
);
|
|
991
|
+
setStoreIsStreaming(false);
|
|
992
|
+
setStoreIsSending(false);
|
|
993
|
+
const notice = rateLimitNoticeFromError({
|
|
994
|
+
statusCode,
|
|
995
|
+
response,
|
|
996
|
+
responseText,
|
|
997
|
+
endpoint: mergedConfig.endpoint
|
|
998
|
+
});
|
|
999
|
+
if (notice) {
|
|
1000
|
+
setRateLimitNotice(notice);
|
|
1001
|
+
setError(null);
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
setRateLimitNotice(null);
|
|
1005
|
+
setError(err.message);
|
|
1006
|
+
},
|
|
1007
|
+
onFinish: ({ message }) => {
|
|
1008
|
+
const messageText = getUIMessageText(message);
|
|
1009
|
+
const current = useQuickChatStore.getState().getActiveMessages();
|
|
1010
|
+
const last = current[current.length - 1];
|
|
1011
|
+
const alreadyHaveSameTail = last?.role === "assistant" && last.content === messageText;
|
|
1012
|
+
if (!alreadyHaveSameTail && messageText) {
|
|
1013
|
+
addMessage({
|
|
1014
|
+
role: message.role,
|
|
1015
|
+
content: messageText,
|
|
1016
|
+
isStreaming: false
|
|
1017
|
+
});
|
|
1018
|
+
}
|
|
1019
|
+
scheduleBackendSync();
|
|
1020
|
+
setStoreIsStreaming(false);
|
|
1021
|
+
setStoreIsSending(false);
|
|
1022
|
+
}
|
|
1023
|
+
});
|
|
1024
|
+
const loadFromBackend = useCallback(async () => {
|
|
1025
|
+
try {
|
|
1026
|
+
const endpoint = `${mergedConfig.endpoint}/history`;
|
|
1027
|
+
const response = await fetch(endpoint, {
|
|
1028
|
+
method: "POST",
|
|
1029
|
+
headers: { "Content-Type": "application/json" },
|
|
1030
|
+
body: JSON.stringify({ action: "load" })
|
|
1031
|
+
});
|
|
1032
|
+
if (await handleRateLimitResponse(response, endpoint)) return;
|
|
1033
|
+
if (!response.ok) return;
|
|
1034
|
+
const data = await response.json().catch(() => null);
|
|
1035
|
+
if (!data?.messages || !Array.isArray(data.messages)) return;
|
|
1036
|
+
if (data.messages.length === 0) return;
|
|
1037
|
+
useQuickChatStore.getState().hydrate(data.messages);
|
|
1038
|
+
setAiMessages(chatMessagesToUiMessages(data.messages));
|
|
1039
|
+
} catch (err) {
|
|
1040
|
+
console.error("[useQuickChat] Failed to load chat history:", err);
|
|
1041
|
+
}
|
|
1042
|
+
}, [handleRateLimitResponse, mergedConfig.endpoint, setAiMessages]);
|
|
1043
|
+
const messages = useMemo(
|
|
1044
|
+
() => uiMessagesToChatMessages({
|
|
1045
|
+
uiMessages: aiMessages,
|
|
1046
|
+
status,
|
|
1047
|
+
setInput
|
|
1048
|
+
}),
|
|
1049
|
+
[aiMessages, setInput, status]
|
|
1050
|
+
);
|
|
1051
|
+
const isStreaming = status === "streaming";
|
|
1052
|
+
const isSending = status === "submitted" || status === "streaming" || manualSending;
|
|
1053
|
+
useEffect(() => {
|
|
1054
|
+
if (initializedRef.current) return;
|
|
1055
|
+
initializedRef.current = true;
|
|
1056
|
+
if (storedMessages.length > 0) {
|
|
1057
|
+
setAiMessages(chatMessagesToUiMessages(storedMessages));
|
|
1058
|
+
} else {
|
|
1059
|
+
void loadFromBackend();
|
|
1060
|
+
}
|
|
1061
|
+
}, [loadFromBackend, setAiMessages, storedMessages]);
|
|
1062
|
+
useEffect(() => {
|
|
1063
|
+
if (!targetElement) return;
|
|
1064
|
+
const chunks = extractContextChunks(targetElement, containerElement);
|
|
1065
|
+
setContextChunks(chunks);
|
|
1066
|
+
}, [targetElement, containerElement, setContextChunks]);
|
|
1067
|
+
useEffect(() => {
|
|
1068
|
+
if (!mergedConfig.showSuggestions) return;
|
|
1069
|
+
if (!contextString) return;
|
|
1070
|
+
if (suggestedPrompts.length > 0) return;
|
|
1071
|
+
let cancelled = false;
|
|
1072
|
+
const fetchSuggestions = async () => {
|
|
1073
|
+
setIsLoadingSuggestions(true);
|
|
1074
|
+
try {
|
|
1075
|
+
const response = await fetch(mergedConfig.endpoint, {
|
|
1076
|
+
method: "POST",
|
|
1077
|
+
headers: { "Content-Type": "application/json" },
|
|
1078
|
+
body: JSON.stringify({
|
|
1079
|
+
action: "suggest",
|
|
1080
|
+
context: contextString,
|
|
1081
|
+
model: mergedConfig.prePassModel
|
|
1082
|
+
})
|
|
1083
|
+
});
|
|
1084
|
+
if (await handleRateLimitResponse(response, mergedConfig.endpoint)) {
|
|
1085
|
+
return;
|
|
1086
|
+
}
|
|
1087
|
+
if (response.ok) {
|
|
1088
|
+
const data = await response.json().catch(() => null);
|
|
1089
|
+
if (data?.suggestions && Array.isArray(data.suggestions)) {
|
|
1090
|
+
if (!cancelled) {
|
|
1091
|
+
setSuggestedPrompts(
|
|
1092
|
+
data.suggestions.map((text, i) => ({
|
|
1093
|
+
id: `suggestion-${i}`,
|
|
1094
|
+
text
|
|
1095
|
+
}))
|
|
1096
|
+
);
|
|
1097
|
+
setIsLoadingSuggestions(false);
|
|
1098
|
+
}
|
|
1099
|
+
return;
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
} catch (err) {
|
|
1103
|
+
console.error("[useQuickChat] Failed to fetch suggestions:", err);
|
|
1104
|
+
}
|
|
1105
|
+
if (!cancelled) {
|
|
1106
|
+
setSuggestedPrompts([
|
|
1107
|
+
{ id: "s1", text: "What is this element?" },
|
|
1108
|
+
{ id: "s2", text: "How can I style this?" },
|
|
1109
|
+
{ id: "s3", text: "Is this accessible?" }
|
|
1110
|
+
]);
|
|
1111
|
+
setIsLoadingSuggestions(false);
|
|
1112
|
+
}
|
|
1113
|
+
};
|
|
1114
|
+
void fetchSuggestions();
|
|
1115
|
+
return () => {
|
|
1116
|
+
cancelled = true;
|
|
1117
|
+
};
|
|
1118
|
+
}, [
|
|
1119
|
+
contextString,
|
|
1120
|
+
handleRateLimitResponse,
|
|
1121
|
+
mergedConfig.endpoint,
|
|
1122
|
+
mergedConfig.prePassModel,
|
|
1123
|
+
mergedConfig.showSuggestions,
|
|
1124
|
+
setIsLoadingSuggestions,
|
|
1125
|
+
setSuggestedPrompts,
|
|
1126
|
+
suggestedPrompts.length
|
|
1127
|
+
]);
|
|
1128
|
+
const selectSuggestion = useCallback(
|
|
1129
|
+
(prompt) => {
|
|
1130
|
+
setInput(prompt.text);
|
|
1131
|
+
},
|
|
1132
|
+
[setInput]
|
|
1133
|
+
);
|
|
1134
|
+
const sendMessage = useCallback(
|
|
1135
|
+
async (messageText) => {
|
|
1136
|
+
const text = (messageText || input).trim();
|
|
1137
|
+
if (!text) return;
|
|
1138
|
+
setInput("");
|
|
1139
|
+
setError(null);
|
|
1140
|
+
setManualSending(true);
|
|
1141
|
+
setStoreIsSending(true);
|
|
1142
|
+
setStoreIsStreaming(true);
|
|
1143
|
+
setDebugInfo(null);
|
|
1144
|
+
try {
|
|
1145
|
+
addMessage({
|
|
1146
|
+
role: "user",
|
|
1147
|
+
content: text
|
|
1148
|
+
});
|
|
1149
|
+
await aiSendMessage({ text });
|
|
1150
|
+
} catch (err) {
|
|
1151
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1152
|
+
setError(msg);
|
|
1153
|
+
} finally {
|
|
1154
|
+
setManualSending(false);
|
|
1155
|
+
setStoreIsSending(false);
|
|
1156
|
+
setStoreIsStreaming(false);
|
|
1157
|
+
}
|
|
1158
|
+
},
|
|
1159
|
+
[
|
|
1160
|
+
addMessage,
|
|
1161
|
+
aiSendMessage,
|
|
1162
|
+
input,
|
|
1163
|
+
setError,
|
|
1164
|
+
setInput,
|
|
1165
|
+
setStoreIsSending,
|
|
1166
|
+
setStoreIsStreaming
|
|
1167
|
+
]
|
|
1168
|
+
);
|
|
1169
|
+
const clearMessages = useCallback(() => {
|
|
1170
|
+
stop();
|
|
1171
|
+
storeClearMessages();
|
|
1172
|
+
setAiMessages([]);
|
|
1173
|
+
const endpoint = `${mergedConfig.endpoint}/history`;
|
|
1174
|
+
fetch(endpoint, {
|
|
1175
|
+
method: "POST",
|
|
1176
|
+
headers: { "Content-Type": "application/json" },
|
|
1177
|
+
body: JSON.stringify({ action: "clear" })
|
|
1178
|
+
}).then((res) => handleRateLimitResponse(res, endpoint)).catch(
|
|
1179
|
+
(err) => console.error("[useQuickChat] Failed to clear backend history:", err)
|
|
1180
|
+
);
|
|
1181
|
+
}, [
|
|
1182
|
+
handleRateLimitResponse,
|
|
1183
|
+
mergedConfig.endpoint,
|
|
1184
|
+
setAiMessages,
|
|
1185
|
+
stop,
|
|
1186
|
+
storeClearMessages
|
|
1187
|
+
]);
|
|
1188
|
+
useEffect(() => {
|
|
1189
|
+
return () => {
|
|
1190
|
+
if (syncTimeoutRef.current) clearTimeout(syncTimeoutRef.current);
|
|
1191
|
+
};
|
|
1192
|
+
}, []);
|
|
1193
|
+
return {
|
|
1194
|
+
input,
|
|
1195
|
+
messages,
|
|
1196
|
+
isLoadingSuggestions,
|
|
1197
|
+
isSending,
|
|
1198
|
+
isStreaming,
|
|
1199
|
+
suggestedPrompts,
|
|
1200
|
+
contextChunks,
|
|
1201
|
+
error,
|
|
1202
|
+
debugInfo,
|
|
1203
|
+
rateLimitNotice,
|
|
1204
|
+
isPinned,
|
|
1205
|
+
lastSyncedAt,
|
|
1206
|
+
config: mergedConfig,
|
|
1207
|
+
setInput,
|
|
1208
|
+
toggleChunk,
|
|
1209
|
+
toggleAllChunks,
|
|
1210
|
+
selectSuggestion,
|
|
1211
|
+
sendMessage,
|
|
1212
|
+
clearMessages,
|
|
1213
|
+
setIsPinned,
|
|
1214
|
+
clearRateLimitNotice: () => setRateLimitNotice(null)
|
|
1215
|
+
};
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
// src/QuickChat/QuickChat.tsx
|
|
1219
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
1220
|
+
var stylesInjected = false;
|
|
1221
|
+
function injectStyles() {
|
|
1222
|
+
if (stylesInjected || typeof document === "undefined") return;
|
|
1223
|
+
const style = document.createElement("style");
|
|
1224
|
+
style.textContent = quickChatKeyframes;
|
|
1225
|
+
document.head.appendChild(style);
|
|
1226
|
+
stylesInjected = true;
|
|
1227
|
+
}
|
|
1228
|
+
var LoadingDots = React.memo(function LoadingDots2() {
|
|
1229
|
+
return /* @__PURE__ */ jsx("div", { style: quickChatStyles.loadingDots, children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx(
|
|
1230
|
+
"div",
|
|
1231
|
+
{
|
|
1232
|
+
style: {
|
|
1233
|
+
...quickChatStyles.loadingDot,
|
|
1234
|
+
animationDelay: `${i * 0.16}s`
|
|
1235
|
+
}
|
|
1236
|
+
},
|
|
1237
|
+
i
|
|
1238
|
+
)) });
|
|
1239
|
+
});
|
|
1240
|
+
function QuickChat({
|
|
1241
|
+
visible,
|
|
1242
|
+
targetElement,
|
|
1243
|
+
containerElement,
|
|
1244
|
+
onClose,
|
|
1245
|
+
onPin,
|
|
1246
|
+
isPinned: isPinnedProp = false,
|
|
1247
|
+
config,
|
|
1248
|
+
style,
|
|
1249
|
+
className,
|
|
1250
|
+
initialInput,
|
|
1251
|
+
onInitialInputConsumed
|
|
1252
|
+
}) {
|
|
1253
|
+
const inputRef = useRef2(null);
|
|
1254
|
+
const messagesEndRef = useRef2(null);
|
|
1255
|
+
const [inputFocused, setInputFocused] = useState2(false);
|
|
1256
|
+
const [showContext, setShowContext] = useState2(false);
|
|
1257
|
+
const [hoveredSuggestion, setHoveredSuggestion] = useState2(
|
|
1258
|
+
null
|
|
1259
|
+
);
|
|
1260
|
+
const {
|
|
1261
|
+
input,
|
|
1262
|
+
messages,
|
|
1263
|
+
isLoadingSuggestions,
|
|
1264
|
+
isSending,
|
|
1265
|
+
isStreaming,
|
|
1266
|
+
debugInfo,
|
|
1267
|
+
rateLimitNotice,
|
|
1268
|
+
suggestedPrompts,
|
|
1269
|
+
contextChunks,
|
|
1270
|
+
error,
|
|
1271
|
+
isPinned: storePinned,
|
|
1272
|
+
setInput,
|
|
1273
|
+
toggleChunk,
|
|
1274
|
+
toggleAllChunks,
|
|
1275
|
+
selectSuggestion,
|
|
1276
|
+
sendMessage,
|
|
1277
|
+
clearMessages,
|
|
1278
|
+
setIsPinned,
|
|
1279
|
+
clearRateLimitNotice,
|
|
1280
|
+
config: mergedConfig
|
|
1281
|
+
} = useQuickChat(targetElement, containerElement, config);
|
|
1282
|
+
const isPinned = isPinnedProp || storePinned;
|
|
1283
|
+
const handlePinToggle = useCallback2(() => {
|
|
1284
|
+
const newPinned = !isPinned;
|
|
1285
|
+
setIsPinned(newPinned);
|
|
1286
|
+
onPin?.(newPinned);
|
|
1287
|
+
}, [isPinned, setIsPinned, onPin]);
|
|
1288
|
+
const handleClose = useCallback2(() => {
|
|
1289
|
+
if (isPinned) {
|
|
1290
|
+
setIsPinned(false);
|
|
1291
|
+
onPin?.(false);
|
|
1292
|
+
}
|
|
1293
|
+
onClose();
|
|
1294
|
+
}, [isPinned, setIsPinned, onPin, onClose]);
|
|
1295
|
+
useEffect2(() => {
|
|
1296
|
+
injectStyles();
|
|
1297
|
+
}, []);
|
|
1298
|
+
useEffect2(() => {
|
|
1299
|
+
if (visible && inputRef.current) {
|
|
1300
|
+
const timer = setTimeout(() => {
|
|
1301
|
+
inputRef.current?.focus();
|
|
1302
|
+
}, 100);
|
|
1303
|
+
return () => clearTimeout(timer);
|
|
1304
|
+
}
|
|
1305
|
+
}, [visible]);
|
|
1306
|
+
useEffect2(() => {
|
|
1307
|
+
if (initialInput && visible) {
|
|
1308
|
+
setInput(initialInput);
|
|
1309
|
+
onInitialInputConsumed?.();
|
|
1310
|
+
if (inputRef.current) {
|
|
1311
|
+
inputRef.current.focus();
|
|
1312
|
+
inputRef.current.setSelectionRange(
|
|
1313
|
+
initialInput.length,
|
|
1314
|
+
initialInput.length
|
|
1315
|
+
);
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
}, [initialInput, visible, setInput, onInitialInputConsumed]);
|
|
1319
|
+
useEffect2(() => {
|
|
1320
|
+
if (messagesEndRef.current) {
|
|
1321
|
+
messagesEndRef.current.scrollIntoView({ behavior: "smooth" });
|
|
1322
|
+
}
|
|
1323
|
+
}, [messages]);
|
|
1324
|
+
const handleInputChange = useCallback2(
|
|
1325
|
+
(e) => {
|
|
1326
|
+
setInput(e.target.value);
|
|
1327
|
+
const target = e.target;
|
|
1328
|
+
target.style.height = "auto";
|
|
1329
|
+
target.style.height = `${Math.min(target.scrollHeight, 80)}px`;
|
|
1330
|
+
},
|
|
1331
|
+
[setInput]
|
|
1332
|
+
);
|
|
1333
|
+
const handleKeyDown = useCallback2(
|
|
1334
|
+
(e) => {
|
|
1335
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
1336
|
+
e.preventDefault();
|
|
1337
|
+
sendMessage();
|
|
1338
|
+
} else if (e.key === "Escape") {
|
|
1339
|
+
onClose();
|
|
1340
|
+
}
|
|
1341
|
+
},
|
|
1342
|
+
[sendMessage, onClose]
|
|
1343
|
+
);
|
|
1344
|
+
const handleSend = useCallback2(() => {
|
|
1345
|
+
sendMessage();
|
|
1346
|
+
}, [sendMessage]);
|
|
1347
|
+
const handleSendToT3Chat = useCallback2(() => {
|
|
1348
|
+
if (typeof window === "undefined") return;
|
|
1349
|
+
const query = input.trim();
|
|
1350
|
+
const baseUrl = mergedConfig.t3chat?.baseUrl ?? "https://t3.chat";
|
|
1351
|
+
const url = query ? `${baseUrl}/?q=${encodeURIComponent(query)}` : baseUrl;
|
|
1352
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
1353
|
+
}, [input, mergedConfig.t3chat?.baseUrl]);
|
|
1354
|
+
const handleCopy = useCallback2((text) => {
|
|
1355
|
+
navigator.clipboard.writeText(text);
|
|
1356
|
+
}, []);
|
|
1357
|
+
const includedCount = useMemo2(
|
|
1358
|
+
() => contextChunks.filter((c) => c.included).length,
|
|
1359
|
+
[contextChunks]
|
|
1360
|
+
);
|
|
1361
|
+
const [rateLimitExpanded, setRateLimitExpanded] = useState2(false);
|
|
1362
|
+
const [reportStatus, setReportStatus] = useState2("idle");
|
|
1363
|
+
const [reportUrl, setReportUrl] = useState2(null);
|
|
1364
|
+
const [reportError, setReportError] = useState2(null);
|
|
1365
|
+
useEffect2(() => {
|
|
1366
|
+
if (rateLimitNotice) {
|
|
1367
|
+
setReportStatus("idle");
|
|
1368
|
+
setReportUrl(null);
|
|
1369
|
+
setReportError(null);
|
|
1370
|
+
setRateLimitExpanded(false);
|
|
1371
|
+
}
|
|
1372
|
+
}, [rateLimitNotice]);
|
|
1373
|
+
const handleReportIssue = useCallback2(async () => {
|
|
1374
|
+
if (!rateLimitNotice) return;
|
|
1375
|
+
if (!targetElement) {
|
|
1376
|
+
setReportStatus("error");
|
|
1377
|
+
setReportError("No target element available to report.");
|
|
1378
|
+
return;
|
|
1379
|
+
}
|
|
1380
|
+
setReportStatus("sending");
|
|
1381
|
+
setReportError(null);
|
|
1382
|
+
try {
|
|
1383
|
+
const payload = buildAnyclickPayload(targetElement, "issue", {
|
|
1384
|
+
comment: `QuickChat: ${rateLimitNotice.message}`,
|
|
1385
|
+
metadata: {
|
|
1386
|
+
source: "quickchat",
|
|
1387
|
+
kind: "rate_limit",
|
|
1388
|
+
endpoint: rateLimitNotice.endpoint ?? mergedConfig.endpoint,
|
|
1389
|
+
retryAt: rateLimitNotice.retryAt,
|
|
1390
|
+
retryAfterSeconds: rateLimitNotice.retryAfterSeconds,
|
|
1391
|
+
requestId: rateLimitNotice.requestId,
|
|
1392
|
+
debugInfo: debugInfo ?? void 0,
|
|
1393
|
+
raw: rateLimitNotice.raw ?? void 0
|
|
1394
|
+
}
|
|
1395
|
+
});
|
|
1396
|
+
const res = await fetch("/api/feedback", {
|
|
1397
|
+
method: "POST",
|
|
1398
|
+
headers: { "Content-Type": "application/json" },
|
|
1399
|
+
body: JSON.stringify(payload)
|
|
1400
|
+
});
|
|
1401
|
+
const json = await res.json().catch(() => null);
|
|
1402
|
+
if (!res.ok || !json?.success) {
|
|
1403
|
+
const msg = json?.error || (res.status ? `Failed to create issue (${res.status}).` : "Failed to create issue.");
|
|
1404
|
+
throw new Error(msg);
|
|
1405
|
+
}
|
|
1406
|
+
const firstUrl = json.results?.find(
|
|
1407
|
+
(r) => typeof r.url === "string"
|
|
1408
|
+
)?.url;
|
|
1409
|
+
setReportUrl(firstUrl ?? null);
|
|
1410
|
+
setReportStatus("sent");
|
|
1411
|
+
} catch (e) {
|
|
1412
|
+
setReportStatus("error");
|
|
1413
|
+
setReportError(e instanceof Error ? e.message : String(e));
|
|
1414
|
+
}
|
|
1415
|
+
}, [rateLimitNotice, targetElement, mergedConfig.endpoint, debugInfo]);
|
|
1416
|
+
if (!visible) return null;
|
|
1417
|
+
const containerStyles = isPinned ? {
|
|
1418
|
+
...quickChatStyles.pinnedContainer,
|
|
1419
|
+
animation: "slideInFromRight 0.25s ease-out",
|
|
1420
|
+
...style
|
|
1421
|
+
} : {
|
|
1422
|
+
...quickChatStyles.container,
|
|
1423
|
+
animation: "fadeIn 0.15s ease-out",
|
|
1424
|
+
...style
|
|
1425
|
+
};
|
|
1426
|
+
return /* @__PURE__ */ jsxs("div", { className, style: containerStyles, children: [
|
|
1427
|
+
/* @__PURE__ */ jsxs(
|
|
1428
|
+
"div",
|
|
1429
|
+
{
|
|
1430
|
+
style: {
|
|
1431
|
+
...quickChatStyles.header,
|
|
1432
|
+
padding: isPinned ? "12px 12px 8px 12px" : "6px 8px"
|
|
1433
|
+
},
|
|
1434
|
+
children: [
|
|
1435
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
|
|
1436
|
+
!isPinned && /* @__PURE__ */ jsx(
|
|
1437
|
+
"button",
|
|
1438
|
+
{
|
|
1439
|
+
type: "button",
|
|
1440
|
+
onClick: onClose,
|
|
1441
|
+
style: {
|
|
1442
|
+
...quickChatStyles.iconButton,
|
|
1443
|
+
marginLeft: "-4px"
|
|
1444
|
+
},
|
|
1445
|
+
title: "Back to menu",
|
|
1446
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { size: 16 })
|
|
1447
|
+
}
|
|
1448
|
+
),
|
|
1449
|
+
mergedConfig.showRedactionUI && contextChunks.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1450
|
+
/* @__PURE__ */ jsxs(
|
|
1451
|
+
"button",
|
|
1452
|
+
{
|
|
1453
|
+
type: "button",
|
|
1454
|
+
onClick: () => setShowContext(!showContext),
|
|
1455
|
+
style: {
|
|
1456
|
+
...quickChatStyles.contextBadge,
|
|
1457
|
+
...showContext ? quickChatStyles.contextBadgeActive : {}
|
|
1458
|
+
},
|
|
1459
|
+
title: "Edit context",
|
|
1460
|
+
children: [
|
|
1461
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
1462
|
+
includedCount,
|
|
1463
|
+
"/",
|
|
1464
|
+
contextChunks.length
|
|
1465
|
+
] }),
|
|
1466
|
+
showContext ? /* @__PURE__ */ jsx(ChevronUp, { size: 10 }) : /* @__PURE__ */ jsx(ChevronDown, { size: 10 })
|
|
1467
|
+
]
|
|
1468
|
+
}
|
|
1469
|
+
),
|
|
1470
|
+
showContext && /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "2px" }, children: [
|
|
1471
|
+
/* @__PURE__ */ jsx(
|
|
1472
|
+
"button",
|
|
1473
|
+
{
|
|
1474
|
+
type: "button",
|
|
1475
|
+
onClick: () => toggleAllChunks(true),
|
|
1476
|
+
style: quickChatStyles.contextToggleSmall,
|
|
1477
|
+
title: "Include all",
|
|
1478
|
+
children: "All"
|
|
1479
|
+
}
|
|
1480
|
+
),
|
|
1481
|
+
/* @__PURE__ */ jsx(
|
|
1482
|
+
"button",
|
|
1483
|
+
{
|
|
1484
|
+
type: "button",
|
|
1485
|
+
onClick: () => toggleAllChunks(false),
|
|
1486
|
+
style: quickChatStyles.contextToggleSmall,
|
|
1487
|
+
title: "Exclude all",
|
|
1488
|
+
children: "None"
|
|
1489
|
+
}
|
|
1490
|
+
)
|
|
1491
|
+
] })
|
|
1492
|
+
] })
|
|
1493
|
+
] }),
|
|
1494
|
+
/* @__PURE__ */ jsxs("div", { style: quickChatStyles.headerActions, children: [
|
|
1495
|
+
messages.length > 0 && /* @__PURE__ */ jsx(
|
|
1496
|
+
"button",
|
|
1497
|
+
{
|
|
1498
|
+
type: "button",
|
|
1499
|
+
onClick: clearMessages,
|
|
1500
|
+
style: quickChatStyles.iconButton,
|
|
1501
|
+
title: "Clear chat",
|
|
1502
|
+
children: /* @__PURE__ */ jsx(RefreshCw, { size: 14 })
|
|
1503
|
+
}
|
|
1504
|
+
),
|
|
1505
|
+
/* @__PURE__ */ jsx(
|
|
1506
|
+
"button",
|
|
1507
|
+
{
|
|
1508
|
+
type: "button",
|
|
1509
|
+
onClick: handlePinToggle,
|
|
1510
|
+
style: {
|
|
1511
|
+
...quickChatStyles.iconButton,
|
|
1512
|
+
...isPinned ? quickChatStyles.iconButtonActive : {}
|
|
1513
|
+
},
|
|
1514
|
+
title: isPinned ? "Unpin (closes with menu)" : "Pin (stays open)",
|
|
1515
|
+
children: isPinned ? /* @__PURE__ */ jsx(PinOff, { size: 14 }) : /* @__PURE__ */ jsx(Pin, { size: 14 })
|
|
1516
|
+
}
|
|
1517
|
+
),
|
|
1518
|
+
/* @__PURE__ */ jsx(
|
|
1519
|
+
"button",
|
|
1520
|
+
{
|
|
1521
|
+
type: "button",
|
|
1522
|
+
onClick: handleClose,
|
|
1523
|
+
style: quickChatStyles.iconButton,
|
|
1524
|
+
title: "Close",
|
|
1525
|
+
children: /* @__PURE__ */ jsx(X, { size: 14 })
|
|
1526
|
+
}
|
|
1527
|
+
)
|
|
1528
|
+
] })
|
|
1529
|
+
]
|
|
1530
|
+
}
|
|
1531
|
+
),
|
|
1532
|
+
showContext && contextChunks.length > 0 && /* @__PURE__ */ jsx("div", { style: quickChatStyles.contextDropdown, children: contextChunks.map((chunk) => /* @__PURE__ */ jsxs(
|
|
1533
|
+
"label",
|
|
1534
|
+
{
|
|
1535
|
+
style: {
|
|
1536
|
+
...quickChatStyles.contextChunkCompact,
|
|
1537
|
+
...chunk.included ? {} : quickChatStyles.contextChunkExcluded
|
|
1538
|
+
},
|
|
1539
|
+
children: [
|
|
1540
|
+
/* @__PURE__ */ jsx(
|
|
1541
|
+
"input",
|
|
1542
|
+
{
|
|
1543
|
+
type: "checkbox",
|
|
1544
|
+
checked: chunk.included,
|
|
1545
|
+
onChange: () => toggleChunk(chunk.id),
|
|
1546
|
+
style: quickChatStyles.contextCheckbox
|
|
1547
|
+
}
|
|
1548
|
+
),
|
|
1549
|
+
/* @__PURE__ */ jsx("span", { style: quickChatStyles.contextLabel, children: chunk.label })
|
|
1550
|
+
]
|
|
1551
|
+
},
|
|
1552
|
+
chunk.id
|
|
1553
|
+
)) }),
|
|
1554
|
+
mergedConfig.showSuggestions && messages.length === 0 && suggestedPrompts.length > 0 && /* @__PURE__ */ jsx("div", { style: quickChatStyles.suggestionsContainer, children: isLoadingSuggestions ? /* @__PURE__ */ jsx(LoadingDots, {}) : suggestedPrompts.map((prompt) => /* @__PURE__ */ jsx(
|
|
1555
|
+
"button",
|
|
1556
|
+
{
|
|
1557
|
+
type: "button",
|
|
1558
|
+
onClick: () => selectSuggestion(prompt),
|
|
1559
|
+
onMouseEnter: () => setHoveredSuggestion(prompt.id),
|
|
1560
|
+
onMouseLeave: () => setHoveredSuggestion(null),
|
|
1561
|
+
style: {
|
|
1562
|
+
...quickChatStyles.suggestionChip,
|
|
1563
|
+
...hoveredSuggestion === prompt.id ? quickChatStyles.suggestionChipHover : {}
|
|
1564
|
+
},
|
|
1565
|
+
children: prompt.text
|
|
1566
|
+
},
|
|
1567
|
+
prompt.id
|
|
1568
|
+
)) }),
|
|
1569
|
+
/* @__PURE__ */ jsxs(
|
|
1570
|
+
"div",
|
|
1571
|
+
{
|
|
1572
|
+
style: isPinned ? quickChatStyles.pinnedMessagesArea : quickChatStyles.messagesArea,
|
|
1573
|
+
children: [
|
|
1574
|
+
error && !rateLimitNotice && /* @__PURE__ */ jsxs("div", { style: quickChatStyles.errorContainer, children: [
|
|
1575
|
+
/* @__PURE__ */ jsx(AlertCircle, { size: 20, style: quickChatStyles.errorIcon }),
|
|
1576
|
+
/* @__PURE__ */ jsx("span", { style: quickChatStyles.errorText, children: error }),
|
|
1577
|
+
/* @__PURE__ */ jsxs(
|
|
1578
|
+
"button",
|
|
1579
|
+
{
|
|
1580
|
+
type: "button",
|
|
1581
|
+
onClick: () => sendMessage(),
|
|
1582
|
+
style: quickChatStyles.errorRetry,
|
|
1583
|
+
children: [
|
|
1584
|
+
/* @__PURE__ */ jsx(RefreshCw, { size: 10 }),
|
|
1585
|
+
"Retry"
|
|
1586
|
+
]
|
|
1587
|
+
}
|
|
1588
|
+
)
|
|
1589
|
+
] }),
|
|
1590
|
+
debugInfo && /* @__PURE__ */ jsxs(
|
|
1591
|
+
"div",
|
|
1592
|
+
{
|
|
1593
|
+
style: {
|
|
1594
|
+
backgroundColor: "#0f172a",
|
|
1595
|
+
color: "#e2e8f0",
|
|
1596
|
+
border: "1px solid #334155",
|
|
1597
|
+
borderRadius: "8px",
|
|
1598
|
+
padding: "8px",
|
|
1599
|
+
margin: "0 0 8px",
|
|
1600
|
+
fontSize: "12px",
|
|
1601
|
+
lineHeight: 1.4,
|
|
1602
|
+
wordBreak: "break-word"
|
|
1603
|
+
},
|
|
1604
|
+
children: [
|
|
1605
|
+
/* @__PURE__ */ jsxs(
|
|
1606
|
+
"div",
|
|
1607
|
+
{
|
|
1608
|
+
style: {
|
|
1609
|
+
display: "flex",
|
|
1610
|
+
justifyContent: "space-between",
|
|
1611
|
+
gap: "8px"
|
|
1612
|
+
},
|
|
1613
|
+
children: [
|
|
1614
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
1615
|
+
"Last request: ",
|
|
1616
|
+
debugInfo.status,
|
|
1617
|
+
" ",
|
|
1618
|
+
debugInfo.ok ? "(ok)" : "(error)"
|
|
1619
|
+
] }),
|
|
1620
|
+
/* @__PURE__ */ jsx("span", { style: { opacity: 0.7 }, children: new Date(debugInfo.timestamp).toLocaleTimeString() })
|
|
1621
|
+
]
|
|
1622
|
+
}
|
|
1623
|
+
),
|
|
1624
|
+
debugInfo.error && /* @__PURE__ */ jsxs("div", { style: { color: "#f87171", marginTop: "4px" }, children: [
|
|
1625
|
+
"Error: ",
|
|
1626
|
+
debugInfo.error
|
|
1627
|
+
] }),
|
|
1628
|
+
debugInfo.contentPreview && /* @__PURE__ */ jsxs("div", { style: { marginTop: "4px" }, children: [
|
|
1629
|
+
"Content: ",
|
|
1630
|
+
debugInfo.contentPreview
|
|
1631
|
+
] }),
|
|
1632
|
+
/* @__PURE__ */ jsxs("div", { style: { marginTop: "4px", opacity: 0.8 }, children: [
|
|
1633
|
+
"Raw: ",
|
|
1634
|
+
debugInfo.rawTextPreview || "(empty)"
|
|
1635
|
+
] })
|
|
1636
|
+
]
|
|
1637
|
+
}
|
|
1638
|
+
),
|
|
1639
|
+
messages.length > 0 && messages.map((message) => /* @__PURE__ */ jsxs(
|
|
1640
|
+
"div",
|
|
1641
|
+
{
|
|
1642
|
+
style: {
|
|
1643
|
+
...quickChatStyles.message,
|
|
1644
|
+
animation: "fadeIn 0.2s ease-out"
|
|
1645
|
+
},
|
|
1646
|
+
children: [
|
|
1647
|
+
/* @__PURE__ */ jsxs(
|
|
1648
|
+
"div",
|
|
1649
|
+
{
|
|
1650
|
+
style: message.role === "user" ? quickChatStyles.messageUser : quickChatStyles.messageAssistant,
|
|
1651
|
+
children: [
|
|
1652
|
+
message.content,
|
|
1653
|
+
message.isStreaming && /* @__PURE__ */ jsx("span", { style: quickChatStyles.streamingIndicator }),
|
|
1654
|
+
message.role === "assistant" && !message.isStreaming && message.content.endsWith("...") && /* @__PURE__ */ jsx("span", { style: quickChatStyles.truncated, children: "(truncated)" })
|
|
1655
|
+
]
|
|
1656
|
+
}
|
|
1657
|
+
),
|
|
1658
|
+
message.role === "assistant" && !message.isStreaming && message.content && /* @__PURE__ */ jsxs("div", { style: quickChatStyles.messageActions, children: [
|
|
1659
|
+
/* @__PURE__ */ jsxs(
|
|
1660
|
+
"button",
|
|
1661
|
+
{
|
|
1662
|
+
type: "button",
|
|
1663
|
+
onClick: () => handleCopy(message.content),
|
|
1664
|
+
style: quickChatStyles.actionButton,
|
|
1665
|
+
children: [
|
|
1666
|
+
/* @__PURE__ */ jsx(Copy, { size: 10 }),
|
|
1667
|
+
"Copy"
|
|
1668
|
+
]
|
|
1669
|
+
}
|
|
1670
|
+
),
|
|
1671
|
+
message.actions?.map((action) => /* @__PURE__ */ jsxs(
|
|
1672
|
+
"button",
|
|
1673
|
+
{
|
|
1674
|
+
type: "button",
|
|
1675
|
+
onClick: action.onClick,
|
|
1676
|
+
style: quickChatStyles.actionButton,
|
|
1677
|
+
children: [
|
|
1678
|
+
action.icon,
|
|
1679
|
+
action.label
|
|
1680
|
+
]
|
|
1681
|
+
},
|
|
1682
|
+
action.id
|
|
1683
|
+
))
|
|
1684
|
+
] })
|
|
1685
|
+
]
|
|
1686
|
+
},
|
|
1687
|
+
message.id
|
|
1688
|
+
)),
|
|
1689
|
+
/* @__PURE__ */ jsx("div", { ref: messagesEndRef })
|
|
1690
|
+
]
|
|
1691
|
+
}
|
|
1692
|
+
),
|
|
1693
|
+
rateLimitNotice && /* @__PURE__ */ jsxs(
|
|
1694
|
+
"div",
|
|
1695
|
+
{
|
|
1696
|
+
style: {
|
|
1697
|
+
borderTop: "1px solid rgba(148, 163, 184, 0.25)",
|
|
1698
|
+
background: "linear-gradient(180deg, rgba(15, 23, 42, 0.92), rgba(15, 23, 42, 0.96))",
|
|
1699
|
+
color: "#e2e8f0",
|
|
1700
|
+
padding: "8px 10px"
|
|
1701
|
+
},
|
|
1702
|
+
children: [
|
|
1703
|
+
/* @__PURE__ */ jsxs(
|
|
1704
|
+
"div",
|
|
1705
|
+
{
|
|
1706
|
+
style: {
|
|
1707
|
+
display: "flex",
|
|
1708
|
+
alignItems: "center",
|
|
1709
|
+
justifyContent: "space-between",
|
|
1710
|
+
gap: "8px"
|
|
1711
|
+
},
|
|
1712
|
+
children: [
|
|
1713
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
1714
|
+
/* @__PURE__ */ jsx(AlertCircle, { size: 16, style: { color: "#fbbf24" } }),
|
|
1715
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: "13px", lineHeight: 1.2 }, children: rateLimitNotice.message })
|
|
1716
|
+
] }),
|
|
1717
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
|
|
1718
|
+
/* @__PURE__ */ jsx(
|
|
1719
|
+
"button",
|
|
1720
|
+
{
|
|
1721
|
+
type: "button",
|
|
1722
|
+
onClick: () => setRateLimitExpanded((v) => !v),
|
|
1723
|
+
style: {
|
|
1724
|
+
border: "1px solid rgba(148, 163, 184, 0.25)",
|
|
1725
|
+
background: "rgba(30, 41, 59, 0.6)",
|
|
1726
|
+
color: "#e2e8f0",
|
|
1727
|
+
borderRadius: "6px",
|
|
1728
|
+
padding: "4px 8px",
|
|
1729
|
+
fontSize: "12px",
|
|
1730
|
+
cursor: "pointer"
|
|
1731
|
+
},
|
|
1732
|
+
children: rateLimitExpanded ? "Hide" : "Details"
|
|
1733
|
+
}
|
|
1734
|
+
),
|
|
1735
|
+
/* @__PURE__ */ jsx(
|
|
1736
|
+
"button",
|
|
1737
|
+
{
|
|
1738
|
+
type: "button",
|
|
1739
|
+
onClick: handleReportIssue,
|
|
1740
|
+
disabled: reportStatus === "sending" || reportStatus === "sent",
|
|
1741
|
+
style: {
|
|
1742
|
+
border: "1px solid rgba(148, 163, 184, 0.25)",
|
|
1743
|
+
background: reportStatus === "sent" ? "rgba(34, 197, 94, 0.22)" : "rgba(30, 41, 59, 0.6)",
|
|
1744
|
+
color: "#e2e8f0",
|
|
1745
|
+
borderRadius: "6px",
|
|
1746
|
+
padding: "4px 8px",
|
|
1747
|
+
fontSize: "12px",
|
|
1748
|
+
cursor: reportStatus === "sending" || reportStatus === "sent" ? "not-allowed" : "pointer",
|
|
1749
|
+
opacity: reportStatus === "sending" ? 0.7 : 1
|
|
1750
|
+
},
|
|
1751
|
+
title: "Create a GitHub issue via /api/feedback",
|
|
1752
|
+
children: reportStatus === "sending" ? "Reporting..." : reportStatus === "sent" ? "Reported" : "Report"
|
|
1753
|
+
}
|
|
1754
|
+
),
|
|
1755
|
+
/* @__PURE__ */ jsx(
|
|
1756
|
+
"button",
|
|
1757
|
+
{
|
|
1758
|
+
type: "button",
|
|
1759
|
+
onClick: () => {
|
|
1760
|
+
clearRateLimitNotice();
|
|
1761
|
+
setRateLimitExpanded(false);
|
|
1762
|
+
},
|
|
1763
|
+
style: {
|
|
1764
|
+
border: "none",
|
|
1765
|
+
background: "transparent",
|
|
1766
|
+
color: "rgba(226, 232, 240, 0.8)",
|
|
1767
|
+
padding: "4px",
|
|
1768
|
+
cursor: "pointer"
|
|
1769
|
+
},
|
|
1770
|
+
title: "Dismiss",
|
|
1771
|
+
children: /* @__PURE__ */ jsx(X, { size: 14 })
|
|
1772
|
+
}
|
|
1773
|
+
)
|
|
1774
|
+
] })
|
|
1775
|
+
]
|
|
1776
|
+
}
|
|
1777
|
+
),
|
|
1778
|
+
reportUrl && /* @__PURE__ */ jsxs("div", { style: { marginTop: "6px", fontSize: "12px" }, children: [
|
|
1779
|
+
"Created:",
|
|
1780
|
+
" ",
|
|
1781
|
+
/* @__PURE__ */ jsx(
|
|
1782
|
+
"a",
|
|
1783
|
+
{
|
|
1784
|
+
href: reportUrl,
|
|
1785
|
+
target: "_blank",
|
|
1786
|
+
rel: "noopener noreferrer",
|
|
1787
|
+
style: { color: "#93c5fd" },
|
|
1788
|
+
children: "Open issue"
|
|
1789
|
+
}
|
|
1790
|
+
)
|
|
1791
|
+
] }),
|
|
1792
|
+
reportError && /* @__PURE__ */ jsx(
|
|
1793
|
+
"div",
|
|
1794
|
+
{
|
|
1795
|
+
style: { marginTop: "6px", fontSize: "12px", color: "#fca5a5" },
|
|
1796
|
+
children: reportError
|
|
1797
|
+
}
|
|
1798
|
+
),
|
|
1799
|
+
rateLimitExpanded && /* @__PURE__ */ jsxs(
|
|
1800
|
+
"div",
|
|
1801
|
+
{
|
|
1802
|
+
style: {
|
|
1803
|
+
marginTop: "8px",
|
|
1804
|
+
fontSize: "12px",
|
|
1805
|
+
lineHeight: 1.4,
|
|
1806
|
+
backgroundColor: "rgba(2, 6, 23, 0.55)",
|
|
1807
|
+
border: "1px solid rgba(148, 163, 184, 0.25)",
|
|
1808
|
+
borderRadius: "8px",
|
|
1809
|
+
padding: "8px",
|
|
1810
|
+
wordBreak: "break-word"
|
|
1811
|
+
},
|
|
1812
|
+
children: [
|
|
1813
|
+
/* @__PURE__ */ jsxs("div", { style: { opacity: 0.85 }, children: [
|
|
1814
|
+
"Status: ",
|
|
1815
|
+
rateLimitNotice.status,
|
|
1816
|
+
rateLimitNotice.requestId ? ` \u2022 Request: ${rateLimitNotice.requestId}` : ""
|
|
1817
|
+
] }),
|
|
1818
|
+
rateLimitNotice.endpoint && /* @__PURE__ */ jsxs("div", { style: { opacity: 0.75, marginTop: "4px" }, children: [
|
|
1819
|
+
"Endpoint: ",
|
|
1820
|
+
rateLimitNotice.endpoint
|
|
1821
|
+
] }),
|
|
1822
|
+
rateLimitNotice.retryAt && /* @__PURE__ */ jsxs("div", { style: { opacity: 0.75, marginTop: "4px" }, children: [
|
|
1823
|
+
"RetryAt: ",
|
|
1824
|
+
new Date(rateLimitNotice.retryAt).toLocaleString()
|
|
1825
|
+
] }),
|
|
1826
|
+
rateLimitNotice.raw && /* @__PURE__ */ jsxs("div", { style: { marginTop: "6px", opacity: 0.85 }, children: [
|
|
1827
|
+
"Raw: ",
|
|
1828
|
+
rateLimitNotice.raw
|
|
1829
|
+
] }),
|
|
1830
|
+
debugInfo && /* @__PURE__ */ jsxs("div", { style: { marginTop: "6px", opacity: 0.85 }, children: [
|
|
1831
|
+
"Debug: ",
|
|
1832
|
+
debugInfo.rawTextPreview || "(empty)"
|
|
1833
|
+
] })
|
|
1834
|
+
]
|
|
1835
|
+
}
|
|
1836
|
+
)
|
|
1837
|
+
]
|
|
1838
|
+
}
|
|
1839
|
+
),
|
|
1840
|
+
/* @__PURE__ */ jsxs("div", { style: quickChatStyles.inputContainer, children: [
|
|
1841
|
+
/* @__PURE__ */ jsx(
|
|
1842
|
+
"textarea",
|
|
1843
|
+
{
|
|
1844
|
+
ref: inputRef,
|
|
1845
|
+
value: input,
|
|
1846
|
+
onChange: handleInputChange,
|
|
1847
|
+
onKeyDown: handleKeyDown,
|
|
1848
|
+
onFocus: () => setInputFocused(true),
|
|
1849
|
+
onBlur: () => setInputFocused(false),
|
|
1850
|
+
placeholder: mergedConfig.placeholder,
|
|
1851
|
+
disabled: isSending,
|
|
1852
|
+
rows: 1,
|
|
1853
|
+
style: {
|
|
1854
|
+
...quickChatStyles.input,
|
|
1855
|
+
...inputFocused ? quickChatStyles.inputFocused : {}
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
),
|
|
1859
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "4px" }, children: [
|
|
1860
|
+
mergedConfig.t3chat?.enabled !== false && /* @__PURE__ */ jsx(
|
|
1861
|
+
"button",
|
|
1862
|
+
{
|
|
1863
|
+
type: "button",
|
|
1864
|
+
onClick: handleSendToT3Chat,
|
|
1865
|
+
disabled: !input.trim(),
|
|
1866
|
+
title: mergedConfig.t3chat?.label ?? "Ask t3.chat",
|
|
1867
|
+
style: {
|
|
1868
|
+
...quickChatStyles.sendButton,
|
|
1869
|
+
backgroundColor: "#7c3aed",
|
|
1870
|
+
...!input.trim() ? quickChatStyles.sendButtonDisabled : {}
|
|
1871
|
+
},
|
|
1872
|
+
children: /* @__PURE__ */ jsx(ExternalLink, { size: 14 })
|
|
1873
|
+
}
|
|
1874
|
+
),
|
|
1875
|
+
/* @__PURE__ */ jsx(
|
|
1876
|
+
"button",
|
|
1877
|
+
{
|
|
1878
|
+
type: "button",
|
|
1879
|
+
onClick: handleSend,
|
|
1880
|
+
disabled: isSending || !input.trim(),
|
|
1881
|
+
style: {
|
|
1882
|
+
...quickChatStyles.sendButton,
|
|
1883
|
+
...isSending || !input.trim() ? quickChatStyles.sendButtonDisabled : {}
|
|
1884
|
+
},
|
|
1885
|
+
children: isSending ? /* @__PURE__ */ jsx(
|
|
1886
|
+
"div",
|
|
1887
|
+
{
|
|
1888
|
+
style: {
|
|
1889
|
+
width: "14px",
|
|
1890
|
+
height: "14px",
|
|
1891
|
+
border: "2px solid transparent",
|
|
1892
|
+
borderTopColor: "#fff",
|
|
1893
|
+
borderRadius: "50%",
|
|
1894
|
+
animation: "spin 0.8s linear infinite"
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
) : /* @__PURE__ */ jsx(Send, { size: 14 })
|
|
1898
|
+
}
|
|
1899
|
+
)
|
|
1900
|
+
] })
|
|
1901
|
+
] })
|
|
1902
|
+
] });
|
|
1903
|
+
}
|
|
1904
|
+
|
|
32
1905
|
// src/ScreenshotPreview.tsx
|
|
33
|
-
import
|
|
1906
|
+
import React2, { useMemo as useMemo3, useState as useState3 } from "react";
|
|
34
1907
|
import { estimateTotalSize, formatBytes } from "@ewjdev/anyclick-core";
|
|
35
1908
|
import {
|
|
36
1909
|
AlertCircleIcon,
|
|
@@ -516,8 +2389,8 @@ var screenshotPreviewStyles = {
|
|
|
516
2389
|
};
|
|
517
2390
|
|
|
518
2391
|
// src/ScreenshotPreview.tsx
|
|
519
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
520
|
-
var ScreenshotPreview =
|
|
2392
|
+
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
2393
|
+
var ScreenshotPreview = React2.memo(function ScreenshotPreview2({
|
|
521
2394
|
isLoading,
|
|
522
2395
|
isSubmitting,
|
|
523
2396
|
onCancel,
|
|
@@ -525,12 +2398,12 @@ var ScreenshotPreview = React.memo(function ScreenshotPreview2({
|
|
|
525
2398
|
onRetake,
|
|
526
2399
|
screenshots
|
|
527
2400
|
}) {
|
|
528
|
-
const [activeTab, setActiveTab] =
|
|
529
|
-
const [isExpanded, setIsExpanded] =
|
|
2401
|
+
const [activeTab, setActiveTab] = useState3("element");
|
|
2402
|
+
const [isExpanded, setIsExpanded] = useState3(false);
|
|
530
2403
|
const getError = (key) => {
|
|
531
2404
|
return screenshots?.errors?.[key];
|
|
532
2405
|
};
|
|
533
|
-
const tabs =
|
|
2406
|
+
const tabs = useMemo3(() => {
|
|
534
2407
|
if (!screenshots) return [];
|
|
535
2408
|
const allTabs = [
|
|
536
2409
|
{
|
|
@@ -554,29 +2427,29 @@ var ScreenshotPreview = React.memo(function ScreenshotPreview2({
|
|
|
554
2427
|
];
|
|
555
2428
|
return allTabs.filter((tab) => tab.data || tab.error);
|
|
556
2429
|
}, [screenshots]);
|
|
557
|
-
const totalSize =
|
|
2430
|
+
const totalSize = useMemo3(
|
|
558
2431
|
() => screenshots ? estimateTotalSize(screenshots) : 0,
|
|
559
2432
|
[screenshots]
|
|
560
2433
|
);
|
|
561
2434
|
if (isLoading) {
|
|
562
|
-
return /* @__PURE__ */
|
|
563
|
-
/* @__PURE__ */
|
|
2435
|
+
return /* @__PURE__ */ jsx2("div", { style: screenshotPreviewStyles.container, children: /* @__PURE__ */ jsxs2("div", { style: screenshotPreviewStyles.loadingContainer, children: [
|
|
2436
|
+
/* @__PURE__ */ jsx2(
|
|
564
2437
|
Loader2Icon,
|
|
565
2438
|
{
|
|
566
2439
|
className: "w-6 h-6 animate-spin",
|
|
567
2440
|
style: { color: "#3b82f6" }
|
|
568
2441
|
}
|
|
569
2442
|
),
|
|
570
|
-
/* @__PURE__ */
|
|
2443
|
+
/* @__PURE__ */ jsx2("span", { style: screenshotPreviewStyles.loadingText, children: "Capturing screenshots..." })
|
|
571
2444
|
] }) });
|
|
572
2445
|
}
|
|
573
2446
|
if (!screenshots) {
|
|
574
|
-
return /* @__PURE__ */
|
|
575
|
-
/* @__PURE__ */
|
|
576
|
-
/* @__PURE__ */
|
|
577
|
-
/* @__PURE__ */
|
|
578
|
-
/* @__PURE__ */
|
|
579
|
-
/* @__PURE__ */
|
|
2447
|
+
return /* @__PURE__ */ jsx2("div", { style: screenshotPreviewStyles.container, children: /* @__PURE__ */ jsxs2("div", { style: screenshotPreviewStyles.emptyContainer, children: [
|
|
2448
|
+
/* @__PURE__ */ jsx2(ImageIcon, { className: "w-8 h-8", style: { color: "#9ca3af" } }),
|
|
2449
|
+
/* @__PURE__ */ jsx2("span", { style: screenshotPreviewStyles.emptyText, children: "Screenshots unavailable" }),
|
|
2450
|
+
/* @__PURE__ */ jsx2("span", { style: screenshotPreviewStyles.emptySubtext, children: "Some elements can't be captured (e.g., gradient text)" }),
|
|
2451
|
+
/* @__PURE__ */ jsxs2("div", { style: screenshotPreviewStyles.emptyActions, children: [
|
|
2452
|
+
/* @__PURE__ */ jsxs2(
|
|
580
2453
|
"button",
|
|
581
2454
|
{
|
|
582
2455
|
type: "button",
|
|
@@ -584,12 +2457,12 @@ var ScreenshotPreview = React.memo(function ScreenshotPreview2({
|
|
|
584
2457
|
onClick: onRetake,
|
|
585
2458
|
style: screenshotPreviewStyles.retakeButtonOutline,
|
|
586
2459
|
children: [
|
|
587
|
-
/* @__PURE__ */
|
|
2460
|
+
/* @__PURE__ */ jsx2(RefreshCwIcon, { className: "w-4 h-4" }),
|
|
588
2461
|
"Try Again"
|
|
589
2462
|
]
|
|
590
2463
|
}
|
|
591
2464
|
),
|
|
592
|
-
/* @__PURE__ */
|
|
2465
|
+
/* @__PURE__ */ jsxs2(
|
|
593
2466
|
"button",
|
|
594
2467
|
{
|
|
595
2468
|
type: "button",
|
|
@@ -597,7 +2470,7 @@ var ScreenshotPreview = React.memo(function ScreenshotPreview2({
|
|
|
597
2470
|
onClick: () => onConfirm({ capturedAt: (/* @__PURE__ */ new Date()).toISOString() }),
|
|
598
2471
|
style: screenshotPreviewStyles.continueButton,
|
|
599
2472
|
children: [
|
|
600
|
-
/* @__PURE__ */
|
|
2473
|
+
/* @__PURE__ */ jsx2(CheckIcon, { className: "w-4 h-4" }),
|
|
601
2474
|
"Continue Without"
|
|
602
2475
|
]
|
|
603
2476
|
}
|
|
@@ -607,7 +2480,7 @@ var ScreenshotPreview = React.memo(function ScreenshotPreview2({
|
|
|
607
2480
|
}
|
|
608
2481
|
const activeScreenshot = activeTab === "element" ? screenshots.element : activeTab === "container" ? screenshots.container : screenshots.viewport;
|
|
609
2482
|
const activeError = getError(activeTab);
|
|
610
|
-
return /* @__PURE__ */
|
|
2483
|
+
return /* @__PURE__ */ jsxs2(
|
|
611
2484
|
"div",
|
|
612
2485
|
{
|
|
613
2486
|
style: {
|
|
@@ -616,23 +2489,23 @@ var ScreenshotPreview = React.memo(function ScreenshotPreview2({
|
|
|
616
2489
|
padding: "8px"
|
|
617
2490
|
},
|
|
618
2491
|
children: [
|
|
619
|
-
/* @__PURE__ */
|
|
620
|
-
/* @__PURE__ */
|
|
621
|
-
/* @__PURE__ */
|
|
622
|
-
/* @__PURE__ */
|
|
623
|
-
/* @__PURE__ */
|
|
2492
|
+
/* @__PURE__ */ jsxs2("div", { style: screenshotPreviewStyles.header, children: [
|
|
2493
|
+
/* @__PURE__ */ jsx2("span", { style: screenshotPreviewStyles.headerTitle, children: "Review Screenshots" }),
|
|
2494
|
+
/* @__PURE__ */ jsxs2("div", { style: screenshotPreviewStyles.headerActions, children: [
|
|
2495
|
+
/* @__PURE__ */ jsx2("span", { style: screenshotPreviewStyles.sizeLabel, children: formatBytes(totalSize) }),
|
|
2496
|
+
/* @__PURE__ */ jsx2(
|
|
624
2497
|
"button",
|
|
625
2498
|
{
|
|
626
2499
|
type: "button",
|
|
627
2500
|
onClick: () => setIsExpanded(!isExpanded),
|
|
628
2501
|
style: screenshotPreviewStyles.iconButton,
|
|
629
2502
|
title: isExpanded ? "Collapse" : "Expand",
|
|
630
|
-
children: isExpanded ? /* @__PURE__ */
|
|
2503
|
+
children: isExpanded ? /* @__PURE__ */ jsx2(ShrinkIcon, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx2(ExpandIcon, { className: "w-4 h-4" })
|
|
631
2504
|
}
|
|
632
2505
|
)
|
|
633
2506
|
] })
|
|
634
2507
|
] }),
|
|
635
|
-
/* @__PURE__ */
|
|
2508
|
+
/* @__PURE__ */ jsx2("div", { style: screenshotPreviewStyles.tabContainer, children: tabs.map((tab) => /* @__PURE__ */ jsxs2(
|
|
636
2509
|
"button",
|
|
637
2510
|
{
|
|
638
2511
|
type: "button",
|
|
@@ -643,7 +2516,7 @@ var ScreenshotPreview = React.memo(function ScreenshotPreview2({
|
|
|
643
2516
|
...tab.error && !tab.data ? screenshotPreviewStyles.tabError : {}
|
|
644
2517
|
},
|
|
645
2518
|
children: [
|
|
646
|
-
tab.error && !tab.data && /* @__PURE__ */
|
|
2519
|
+
tab.error && !tab.data && /* @__PURE__ */ jsx2(
|
|
647
2520
|
AlertCircleIcon,
|
|
648
2521
|
{
|
|
649
2522
|
className: "w-3 h-3",
|
|
@@ -651,32 +2524,32 @@ var ScreenshotPreview = React.memo(function ScreenshotPreview2({
|
|
|
651
2524
|
}
|
|
652
2525
|
),
|
|
653
2526
|
tab.label,
|
|
654
|
-
tab.data && /* @__PURE__ */
|
|
2527
|
+
tab.data && /* @__PURE__ */ jsx2("span", { style: screenshotPreviewStyles.tabSize, children: formatBytes(tab.data.sizeBytes) })
|
|
655
2528
|
]
|
|
656
2529
|
},
|
|
657
2530
|
tab.key
|
|
658
2531
|
)) }),
|
|
659
|
-
/* @__PURE__ */
|
|
2532
|
+
/* @__PURE__ */ jsx2(
|
|
660
2533
|
"div",
|
|
661
2534
|
{
|
|
662
2535
|
style: {
|
|
663
2536
|
...screenshotPreviewStyles.previewContainer,
|
|
664
2537
|
...isExpanded ? screenshotPreviewStyles.previewContainerExpanded : {}
|
|
665
2538
|
},
|
|
666
|
-
children: activeScreenshot ? /* @__PURE__ */
|
|
2539
|
+
children: activeScreenshot ? /* @__PURE__ */ jsx2(
|
|
667
2540
|
"img",
|
|
668
2541
|
{
|
|
669
2542
|
alt: `${activeTab} screenshot`,
|
|
670
2543
|
src: activeScreenshot.dataUrl,
|
|
671
2544
|
style: screenshotPreviewStyles.previewImage
|
|
672
2545
|
}
|
|
673
|
-
) : activeError ? /* @__PURE__ */
|
|
674
|
-
/* @__PURE__ */
|
|
675
|
-
/* @__PURE__ */
|
|
676
|
-
/* @__PURE__ */
|
|
677
|
-
] }) : /* @__PURE__ */
|
|
678
|
-
/* @__PURE__ */
|
|
679
|
-
/* @__PURE__ */
|
|
2546
|
+
) : activeError ? /* @__PURE__ */ jsxs2("div", { style: screenshotPreviewStyles.errorPreview, children: [
|
|
2547
|
+
/* @__PURE__ */ jsx2(AlertCircleIcon, { className: "w-8 h-8", style: { color: "#ef4444" } }),
|
|
2548
|
+
/* @__PURE__ */ jsx2("span", { style: screenshotPreviewStyles.errorTitle, children: "Capture Failed" }),
|
|
2549
|
+
/* @__PURE__ */ jsx2("span", { style: screenshotPreviewStyles.errorMessage, children: activeError.message })
|
|
2550
|
+
] }) : /* @__PURE__ */ jsxs2("div", { style: screenshotPreviewStyles.noPreview, children: [
|
|
2551
|
+
/* @__PURE__ */ jsx2(ImageIcon, { className: "w-6 h-6", style: { color: "#9ca3af" } }),
|
|
2552
|
+
/* @__PURE__ */ jsxs2("span", { children: [
|
|
680
2553
|
"No ",
|
|
681
2554
|
activeTab,
|
|
682
2555
|
" screenshot"
|
|
@@ -684,14 +2557,14 @@ var ScreenshotPreview = React.memo(function ScreenshotPreview2({
|
|
|
684
2557
|
] })
|
|
685
2558
|
}
|
|
686
2559
|
),
|
|
687
|
-
activeScreenshot && /* @__PURE__ */
|
|
2560
|
+
activeScreenshot && /* @__PURE__ */ jsxs2("div", { style: screenshotPreviewStyles.dimensionsInfo, children: [
|
|
688
2561
|
activeScreenshot.width,
|
|
689
2562
|
" \xD7 ",
|
|
690
2563
|
activeScreenshot.height,
|
|
691
2564
|
"px"
|
|
692
2565
|
] }),
|
|
693
|
-
/* @__PURE__ */
|
|
694
|
-
/* @__PURE__ */
|
|
2566
|
+
/* @__PURE__ */ jsxs2("div", { style: screenshotPreviewStyles.actions, children: [
|
|
2567
|
+
/* @__PURE__ */ jsxs2(
|
|
695
2568
|
"button",
|
|
696
2569
|
{
|
|
697
2570
|
type: "button",
|
|
@@ -699,13 +2572,13 @@ var ScreenshotPreview = React.memo(function ScreenshotPreview2({
|
|
|
699
2572
|
onClick: onRetake,
|
|
700
2573
|
style: screenshotPreviewStyles.retakeButtonSmall,
|
|
701
2574
|
children: [
|
|
702
|
-
/* @__PURE__ */
|
|
2575
|
+
/* @__PURE__ */ jsx2(RefreshCwIcon, { className: "w-3 h-3" }),
|
|
703
2576
|
"Retake"
|
|
704
2577
|
]
|
|
705
2578
|
}
|
|
706
2579
|
),
|
|
707
|
-
/* @__PURE__ */
|
|
708
|
-
/* @__PURE__ */
|
|
2580
|
+
/* @__PURE__ */ jsxs2("div", { style: screenshotPreviewStyles.actionsRight, children: [
|
|
2581
|
+
/* @__PURE__ */ jsxs2(
|
|
709
2582
|
"button",
|
|
710
2583
|
{
|
|
711
2584
|
type: "button",
|
|
@@ -714,12 +2587,12 @@ var ScreenshotPreview = React.memo(function ScreenshotPreview2({
|
|
|
714
2587
|
onClick: onCancel,
|
|
715
2588
|
style: { ...menuStyles.button, ...menuStyles.cancelButton },
|
|
716
2589
|
children: [
|
|
717
|
-
/* @__PURE__ */
|
|
2590
|
+
/* @__PURE__ */ jsx2(XIcon, { className: "w-3 h-3" }),
|
|
718
2591
|
"Cancel"
|
|
719
2592
|
]
|
|
720
2593
|
}
|
|
721
2594
|
),
|
|
722
|
-
/* @__PURE__ */
|
|
2595
|
+
/* @__PURE__ */ jsx2(
|
|
723
2596
|
"button",
|
|
724
2597
|
{
|
|
725
2598
|
type: "button",
|
|
@@ -730,11 +2603,11 @@ var ScreenshotPreview = React.memo(function ScreenshotPreview2({
|
|
|
730
2603
|
...menuStyles.submitButton,
|
|
731
2604
|
...isSubmitting ? menuStyles.submitButtonDisabled : {}
|
|
732
2605
|
},
|
|
733
|
-
children: isSubmitting ? /* @__PURE__ */
|
|
734
|
-
/* @__PURE__ */
|
|
2606
|
+
children: isSubmitting ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
2607
|
+
/* @__PURE__ */ jsx2(Loader2Icon, { className: "w-3 h-3 animate-spin" }),
|
|
735
2608
|
"Sending..."
|
|
736
|
-
] }) : /* @__PURE__ */
|
|
737
|
-
/* @__PURE__ */
|
|
2609
|
+
] }) : /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
2610
|
+
/* @__PURE__ */ jsx2(CheckIcon, { className: "w-3 h-3" }),
|
|
738
2611
|
"Send"
|
|
739
2612
|
] })
|
|
740
2613
|
}
|
|
@@ -831,7 +2704,7 @@ svg.${HIGHLIGHT_CONTAINER_CLASS},
|
|
|
831
2704
|
}
|
|
832
2705
|
`;
|
|
833
2706
|
}
|
|
834
|
-
function
|
|
2707
|
+
function injectStyles2(colors) {
|
|
835
2708
|
if (typeof document === "undefined") return;
|
|
836
2709
|
const existingStyle = document.getElementById(STYLE_ID);
|
|
837
2710
|
if (existingStyle) {
|
|
@@ -879,12 +2752,12 @@ function findContainerParent(element, config) {
|
|
|
879
2752
|
}
|
|
880
2753
|
function highlightTarget(element, colors) {
|
|
881
2754
|
const mergedColors = { ...defaultHighlightColors, ...colors };
|
|
882
|
-
|
|
2755
|
+
injectStyles2(mergedColors);
|
|
883
2756
|
element.classList.add(HIGHLIGHT_TARGET_CLASS);
|
|
884
2757
|
}
|
|
885
2758
|
function highlightContainer(element, colors) {
|
|
886
2759
|
const mergedColors = { ...defaultHighlightColors, ...colors };
|
|
887
|
-
|
|
2760
|
+
injectStyles2(mergedColors);
|
|
888
2761
|
element.classList.add(HIGHLIGHT_CONTAINER_CLASS);
|
|
889
2762
|
}
|
|
890
2763
|
function clearHighlights() {
|
|
@@ -911,12 +2784,12 @@ function applyHighlights(targetElement, config) {
|
|
|
911
2784
|
}
|
|
912
2785
|
|
|
913
2786
|
// src/ContextMenu.tsx
|
|
914
|
-
import { jsx as
|
|
2787
|
+
import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
915
2788
|
var VIEWPORT_PADDING = 10;
|
|
916
2789
|
var defaultIcons = {
|
|
917
|
-
feature: /* @__PURE__ */
|
|
918
|
-
issue: /* @__PURE__ */
|
|
919
|
-
like: /* @__PURE__ */
|
|
2790
|
+
feature: /* @__PURE__ */ jsx3(PlusIcon, { className: "w-4 h-4" }),
|
|
2791
|
+
issue: /* @__PURE__ */ jsx3(FlagIcon, { className: "w-4 h-4" }),
|
|
2792
|
+
like: /* @__PURE__ */ jsx3(ThumbsUpIcon, { className: "w-4 h-4" })
|
|
920
2793
|
};
|
|
921
2794
|
var OFFSCREEN_POSITION = { x: -9999, y: -9999 };
|
|
922
2795
|
var DefaultHeader = ({
|
|
@@ -925,25 +2798,25 @@ var DefaultHeader = ({
|
|
|
925
2798
|
styles,
|
|
926
2799
|
title = "Send Feedback"
|
|
927
2800
|
}) => {
|
|
928
|
-
return /* @__PURE__ */
|
|
929
|
-
/* @__PURE__ */
|
|
2801
|
+
return /* @__PURE__ */ jsxs3("div", { style: styles, className, children: [
|
|
2802
|
+
/* @__PURE__ */ jsx3("span", { children: title }),
|
|
930
2803
|
children
|
|
931
2804
|
] });
|
|
932
2805
|
};
|
|
933
|
-
var MenuItem =
|
|
2806
|
+
var MenuItem = React3.memo(function MenuItem2({
|
|
934
2807
|
disabled,
|
|
935
2808
|
hasChildren,
|
|
936
2809
|
item,
|
|
937
2810
|
onClick
|
|
938
2811
|
}) {
|
|
939
|
-
const [isHovered, setIsHovered] =
|
|
940
|
-
const [isPressed, setIsPressed] =
|
|
2812
|
+
const [isHovered, setIsHovered] = useState4(false);
|
|
2813
|
+
const [isPressed, setIsPressed] = useState4(false);
|
|
941
2814
|
const isComingSoon = item.status === "comingSoon";
|
|
942
2815
|
const badgeLabel = item.badge?.label ?? (isComingSoon ? "Coming soon" : null);
|
|
943
2816
|
const badgeTone = item.badge?.tone ?? (isComingSoon ? "neutral" : "neutral");
|
|
944
2817
|
const badgeStyle = badgeLabel ? getBadgeStyle(badgeTone) : void 0;
|
|
945
2818
|
const iconNode = item.icon ?? defaultIcons[item.type];
|
|
946
|
-
return /* @__PURE__ */
|
|
2819
|
+
return /* @__PURE__ */ jsxs3(
|
|
947
2820
|
"button",
|
|
948
2821
|
{
|
|
949
2822
|
type: "button",
|
|
@@ -964,22 +2837,22 @@ var MenuItem = React2.memo(function MenuItem2({
|
|
|
964
2837
|
...disabled ? menuStyles.itemDisabled : {}
|
|
965
2838
|
},
|
|
966
2839
|
children: [
|
|
967
|
-
iconNode ? /* @__PURE__ */
|
|
968
|
-
/* @__PURE__ */
|
|
2840
|
+
iconNode ? /* @__PURE__ */ jsx3("span", { style: menuStyles.itemIcon, children: iconNode }) : null,
|
|
2841
|
+
/* @__PURE__ */ jsxs3("span", { style: menuStyles.itemLabel, children: [
|
|
969
2842
|
item.label,
|
|
970
|
-
badgeLabel && /* @__PURE__ */
|
|
2843
|
+
badgeLabel && /* @__PURE__ */ jsx3("span", { style: badgeStyle, children: badgeLabel })
|
|
971
2844
|
] }),
|
|
972
|
-
hasChildren && /* @__PURE__ */
|
|
2845
|
+
hasChildren && /* @__PURE__ */ jsx3(ChevronRightIcon, { className: "w-4 h-4", style: menuStyles.submenuIcon })
|
|
973
2846
|
]
|
|
974
2847
|
}
|
|
975
2848
|
);
|
|
976
2849
|
});
|
|
977
|
-
var BackButton =
|
|
2850
|
+
var BackButton = React3.memo(function BackButton2({
|
|
978
2851
|
onClick
|
|
979
2852
|
}) {
|
|
980
|
-
const [isHovered, setIsHovered] =
|
|
981
|
-
const [isPressed, setIsPressed] =
|
|
982
|
-
return /* @__PURE__ */
|
|
2853
|
+
const [isHovered, setIsHovered] = useState4(false);
|
|
2854
|
+
const [isPressed, setIsPressed] = useState4(false);
|
|
2855
|
+
return /* @__PURE__ */ jsxs3(
|
|
983
2856
|
"button",
|
|
984
2857
|
{
|
|
985
2858
|
type: "button",
|
|
@@ -999,26 +2872,26 @@ var BackButton = React2.memo(function BackButton2({
|
|
|
999
2872
|
...isHovered || isPressed ? menuStyles.itemHover : {}
|
|
1000
2873
|
},
|
|
1001
2874
|
children: [
|
|
1002
|
-
/* @__PURE__ */
|
|
1003
|
-
/* @__PURE__ */
|
|
2875
|
+
/* @__PURE__ */ jsx3(ChevronLeftIcon, { className: "w-4 h-4", style: { opacity: 0.5 } }),
|
|
2876
|
+
/* @__PURE__ */ jsx3("span", { style: { opacity: 0.7 }, children: "Back" })
|
|
1004
2877
|
]
|
|
1005
2878
|
}
|
|
1006
2879
|
);
|
|
1007
2880
|
});
|
|
1008
|
-
var CommentForm =
|
|
2881
|
+
var CommentForm = React3.memo(function CommentForm2({
|
|
1009
2882
|
isSubmitting,
|
|
1010
2883
|
onCancel,
|
|
1011
2884
|
onSubmit
|
|
1012
2885
|
}) {
|
|
1013
|
-
const [comment, setComment] =
|
|
1014
|
-
const inputRef =
|
|
1015
|
-
|
|
2886
|
+
const [comment, setComment] = useState4("");
|
|
2887
|
+
const inputRef = useRef3(null);
|
|
2888
|
+
useEffect3(() => {
|
|
1016
2889
|
inputRef.current?.focus();
|
|
1017
2890
|
}, []);
|
|
1018
|
-
const handleSubmit =
|
|
2891
|
+
const handleSubmit = useCallback3(() => {
|
|
1019
2892
|
onSubmit(comment);
|
|
1020
2893
|
}, [comment, onSubmit]);
|
|
1021
|
-
const handleKeyDown =
|
|
2894
|
+
const handleKeyDown = useCallback3(
|
|
1022
2895
|
(e) => {
|
|
1023
2896
|
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
1024
2897
|
handleSubmit();
|
|
@@ -1028,8 +2901,8 @@ var CommentForm = React2.memo(function CommentForm2({
|
|
|
1028
2901
|
},
|
|
1029
2902
|
[handleSubmit, onCancel]
|
|
1030
2903
|
);
|
|
1031
|
-
return /* @__PURE__ */
|
|
1032
|
-
/* @__PURE__ */
|
|
2904
|
+
return /* @__PURE__ */ jsxs3("div", { style: menuStyles.commentSection, children: [
|
|
2905
|
+
/* @__PURE__ */ jsx3(
|
|
1033
2906
|
"textarea",
|
|
1034
2907
|
{
|
|
1035
2908
|
ref: inputRef,
|
|
@@ -1041,8 +2914,8 @@ var CommentForm = React2.memo(function CommentForm2({
|
|
|
1041
2914
|
value: comment
|
|
1042
2915
|
}
|
|
1043
2916
|
),
|
|
1044
|
-
/* @__PURE__ */
|
|
1045
|
-
/* @__PURE__ */
|
|
2917
|
+
/* @__PURE__ */ jsxs3("div", { style: menuStyles.buttonRow, children: [
|
|
2918
|
+
/* @__PURE__ */ jsx3(
|
|
1046
2919
|
"button",
|
|
1047
2920
|
{
|
|
1048
2921
|
type: "button",
|
|
@@ -1052,7 +2925,7 @@ var CommentForm = React2.memo(function CommentForm2({
|
|
|
1052
2925
|
children: "Cancel"
|
|
1053
2926
|
}
|
|
1054
2927
|
),
|
|
1055
|
-
/* @__PURE__ */
|
|
2928
|
+
/* @__PURE__ */ jsx3(
|
|
1056
2929
|
"button",
|
|
1057
2930
|
{
|
|
1058
2931
|
type: "button",
|
|
@@ -1100,26 +2973,35 @@ function ContextMenu({
|
|
|
1100
2973
|
onSelect,
|
|
1101
2974
|
position,
|
|
1102
2975
|
positionMode = "inView",
|
|
2976
|
+
quickChatConfig,
|
|
1103
2977
|
screenshotConfig,
|
|
1104
2978
|
style,
|
|
1105
2979
|
targetElement,
|
|
1106
2980
|
visible
|
|
1107
2981
|
}) {
|
|
1108
|
-
const [selectedType, setSelectedType] =
|
|
1109
|
-
const [currentView, setCurrentView] =
|
|
1110
|
-
const [pendingComment, setPendingComment] =
|
|
1111
|
-
const [submenuStack, setSubmenuStack] =
|
|
1112
|
-
const [screenshots, setScreenshots] =
|
|
1113
|
-
const [isCapturing, setIsCapturing] =
|
|
1114
|
-
const
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
2982
|
+
const [selectedType, setSelectedType] = useState4(null);
|
|
2983
|
+
const [currentView, setCurrentView] = useState4("menu");
|
|
2984
|
+
const [pendingComment, setPendingComment] = useState4();
|
|
2985
|
+
const [submenuStack, setSubmenuStack] = useState4([]);
|
|
2986
|
+
const [screenshots, setScreenshots] = useState4(null);
|
|
2987
|
+
const [isCapturing, setIsCapturing] = useState4(false);
|
|
2988
|
+
const [isQuickChatPinned, setIsQuickChatPinned] = useState4(() => {
|
|
2989
|
+
if (typeof window === "undefined") return false;
|
|
2990
|
+
try {
|
|
2991
|
+
return sessionStorage.getItem("anyclick-quick-chat-pinned") === "true";
|
|
2992
|
+
} catch {
|
|
2993
|
+
return false;
|
|
2994
|
+
}
|
|
2995
|
+
});
|
|
2996
|
+
const menuRef = useRef3(null);
|
|
2997
|
+
const [adjustedPosition, setAdjustedPosition] = useState4(OFFSCREEN_POSITION);
|
|
2998
|
+
const [isDragging, setIsDragging] = useState4(false);
|
|
2999
|
+
const [dragOffset, setDragOffset] = useState4({
|
|
1118
3000
|
x: 0,
|
|
1119
3001
|
y: 0
|
|
1120
3002
|
});
|
|
1121
|
-
const dragStartRef =
|
|
1122
|
-
const mergedScreenshotConfig =
|
|
3003
|
+
const dragStartRef = useRef3(null);
|
|
3004
|
+
const mergedScreenshotConfig = React3.useMemo(
|
|
1123
3005
|
() => ({
|
|
1124
3006
|
...DEFAULT_SCREENSHOT_CONFIG,
|
|
1125
3007
|
...screenshotConfig
|
|
@@ -1128,7 +3010,7 @@ function ContextMenu({
|
|
|
1128
3010
|
);
|
|
1129
3011
|
const showPreview = mergedScreenshotConfig.showPreview && isScreenshotSupported();
|
|
1130
3012
|
const currentItems = submenuStack.length > 0 ? submenuStack[submenuStack.length - 1] : items;
|
|
1131
|
-
const captureScreenshots =
|
|
3013
|
+
const captureScreenshots = useCallback3(async () => {
|
|
1132
3014
|
if (!targetElement || !showPreview) return;
|
|
1133
3015
|
setIsCapturing(true);
|
|
1134
3016
|
try {
|
|
@@ -1145,7 +3027,7 @@ function ContextMenu({
|
|
|
1145
3027
|
setIsCapturing(false);
|
|
1146
3028
|
}
|
|
1147
3029
|
}, [containerElement, mergedScreenshotConfig, showPreview, targetElement]);
|
|
1148
|
-
|
|
3030
|
+
useEffect3(() => {
|
|
1149
3031
|
if (!visible) {
|
|
1150
3032
|
setSelectedType(null);
|
|
1151
3033
|
setCurrentView("menu");
|
|
@@ -1159,7 +3041,7 @@ function ContextMenu({
|
|
|
1159
3041
|
dragStartRef.current = null;
|
|
1160
3042
|
}
|
|
1161
3043
|
}, [visible]);
|
|
1162
|
-
|
|
3044
|
+
useEffect3(() => {
|
|
1163
3045
|
if (visible && targetElement) {
|
|
1164
3046
|
clearHighlights();
|
|
1165
3047
|
applyHighlights(targetElement, highlightConfig);
|
|
@@ -1170,7 +3052,7 @@ function ContextMenu({
|
|
|
1170
3052
|
clearHighlights();
|
|
1171
3053
|
};
|
|
1172
3054
|
}, [highlightConfig, targetElement, visible]);
|
|
1173
|
-
|
|
3055
|
+
useEffect3(() => {
|
|
1174
3056
|
if (!visible) {
|
|
1175
3057
|
return;
|
|
1176
3058
|
}
|
|
@@ -1189,13 +3071,13 @@ function ContextMenu({
|
|
|
1189
3071
|
document.removeEventListener("pointerdown", handlePointerDown);
|
|
1190
3072
|
};
|
|
1191
3073
|
}, [onClose, visible]);
|
|
1192
|
-
|
|
3074
|
+
useEffect3(() => {
|
|
1193
3075
|
if (visible) {
|
|
1194
3076
|
setAdjustedPosition(position);
|
|
1195
3077
|
setDragOffset({ x: 0, y: 0 });
|
|
1196
3078
|
}
|
|
1197
3079
|
}, [position.x, position.y, visible]);
|
|
1198
|
-
|
|
3080
|
+
useEffect3(() => {
|
|
1199
3081
|
if (!visible || !menuRef.current) return;
|
|
1200
3082
|
const updatePosition = () => {
|
|
1201
3083
|
const menuElement = menuRef.current;
|
|
@@ -1219,7 +3101,7 @@ function ContextMenu({
|
|
|
1219
3101
|
window.addEventListener("resize", updatePosition);
|
|
1220
3102
|
return () => window.removeEventListener("resize", updatePosition);
|
|
1221
3103
|
}, [currentView, dragOffset, position, positionMode, visible]);
|
|
1222
|
-
|
|
3104
|
+
useEffect3(() => {
|
|
1223
3105
|
if (!visible || positionMode !== "dynamic") return;
|
|
1224
3106
|
const handlePointerMove = (event) => {
|
|
1225
3107
|
if (!isDragging || !dragStartRef.current) return;
|
|
@@ -1246,7 +3128,7 @@ function ContextMenu({
|
|
|
1246
3128
|
};
|
|
1247
3129
|
}
|
|
1248
3130
|
}, [isDragging, positionMode, visible]);
|
|
1249
|
-
const handleDragStart =
|
|
3131
|
+
const handleDragStart = useCallback3(
|
|
1250
3132
|
(event) => {
|
|
1251
3133
|
if (positionMode !== "dynamic") return;
|
|
1252
3134
|
event.preventDefault();
|
|
@@ -1255,7 +3137,8 @@ function ContextMenu({
|
|
|
1255
3137
|
},
|
|
1256
3138
|
[positionMode]
|
|
1257
3139
|
);
|
|
1258
|
-
|
|
3140
|
+
const [initialChatInput, setInitialChatInput] = useState4("");
|
|
3141
|
+
useEffect3(() => {
|
|
1259
3142
|
const handleKeyDown = (e) => {
|
|
1260
3143
|
if (e.key === "Escape") {
|
|
1261
3144
|
if (currentView === "screenshot-preview") {
|
|
@@ -1264,19 +3147,38 @@ function ContextMenu({
|
|
|
1264
3147
|
setCurrentView("menu");
|
|
1265
3148
|
setSelectedType(null);
|
|
1266
3149
|
setPendingComment(void 0);
|
|
3150
|
+
} else if (currentView === "quick-chat") {
|
|
3151
|
+
if (!isQuickChatPinned) {
|
|
3152
|
+
setCurrentView("menu");
|
|
3153
|
+
}
|
|
1267
3154
|
} else if (submenuStack.length > 0) {
|
|
1268
3155
|
setSubmenuStack((prev) => prev.slice(0, -1));
|
|
1269
3156
|
} else {
|
|
1270
3157
|
onClose();
|
|
1271
3158
|
}
|
|
3159
|
+
return;
|
|
3160
|
+
}
|
|
3161
|
+
if (quickChatConfig && currentView === "menu" && !isQuickChatPinned && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
3162
|
+
if (e.key.length === 1 && e.key.match(/[a-zA-Z0-9\s.,!?'"]/)) {
|
|
3163
|
+
e.preventDefault();
|
|
3164
|
+
setInitialChatInput(e.key);
|
|
3165
|
+
setCurrentView("quick-chat");
|
|
3166
|
+
}
|
|
1272
3167
|
}
|
|
1273
3168
|
};
|
|
1274
3169
|
if (visible) {
|
|
1275
3170
|
document.addEventListener("keydown", handleKeyDown);
|
|
1276
3171
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
1277
3172
|
}
|
|
1278
|
-
}, [
|
|
1279
|
-
|
|
3173
|
+
}, [
|
|
3174
|
+
currentView,
|
|
3175
|
+
isQuickChatPinned,
|
|
3176
|
+
onClose,
|
|
3177
|
+
quickChatConfig,
|
|
3178
|
+
submenuStack.length,
|
|
3179
|
+
visible
|
|
3180
|
+
]);
|
|
3181
|
+
useEffect3(() => {
|
|
1280
3182
|
const menuElement = menuRef.current;
|
|
1281
3183
|
if (!visible || !menuElement) return;
|
|
1282
3184
|
const preventTouchDefault = (e) => {
|
|
@@ -1293,9 +3195,6 @@ function ContextMenu({
|
|
|
1293
3195
|
menuElement.removeEventListener("touchmove", preventTouchDefault);
|
|
1294
3196
|
};
|
|
1295
3197
|
}, [visible]);
|
|
1296
|
-
if (!visible || !targetElement) {
|
|
1297
|
-
return null;
|
|
1298
|
-
}
|
|
1299
3198
|
const handleItemClick = (item) => {
|
|
1300
3199
|
if (item.status === "comingSoon") {
|
|
1301
3200
|
return;
|
|
@@ -1364,85 +3263,166 @@ function ContextMenu({
|
|
|
1364
3263
|
const handleRetakeScreenshots = () => {
|
|
1365
3264
|
captureScreenshots();
|
|
1366
3265
|
};
|
|
1367
|
-
const
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
{
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
3266
|
+
const handleQuickChatToggle = () => {
|
|
3267
|
+
if (currentView === "quick-chat" && !isQuickChatPinned) {
|
|
3268
|
+
setCurrentView("menu");
|
|
3269
|
+
} else {
|
|
3270
|
+
setCurrentView("quick-chat");
|
|
3271
|
+
}
|
|
3272
|
+
};
|
|
3273
|
+
const handleQuickChatPin = (pinned) => {
|
|
3274
|
+
setIsQuickChatPinned(pinned);
|
|
3275
|
+
try {
|
|
3276
|
+
if (pinned) {
|
|
3277
|
+
sessionStorage.setItem("anyclick-quick-chat-pinned", "true");
|
|
3278
|
+
} else {
|
|
3279
|
+
sessionStorage.removeItem("anyclick-quick-chat-pinned");
|
|
3280
|
+
}
|
|
3281
|
+
} catch {
|
|
3282
|
+
}
|
|
3283
|
+
if (pinned) {
|
|
3284
|
+
setCurrentView("menu");
|
|
3285
|
+
}
|
|
3286
|
+
};
|
|
3287
|
+
const handleQuickChatClose = () => {
|
|
3288
|
+
setIsQuickChatPinned(false);
|
|
3289
|
+
try {
|
|
3290
|
+
sessionStorage.removeItem("anyclick-quick-chat-pinned");
|
|
3291
|
+
} catch {
|
|
3292
|
+
}
|
|
3293
|
+
setCurrentView("menu");
|
|
3294
|
+
};
|
|
3295
|
+
const containerWidth = currentView === "screenshot-preview" ? 360 : currentView === "quick-chat" && !isQuickChatPinned ? 320 : void 0;
|
|
3296
|
+
const showPinnedDrawer = isQuickChatPinned && quickChatConfig;
|
|
3297
|
+
const showMenu = visible && targetElement;
|
|
3298
|
+
return /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
3299
|
+
showPinnedDrawer && /* @__PURE__ */ jsx3(
|
|
3300
|
+
QuickChat,
|
|
3301
|
+
{
|
|
3302
|
+
visible: true,
|
|
3303
|
+
targetElement,
|
|
3304
|
+
containerElement,
|
|
3305
|
+
onClose: handleQuickChatClose,
|
|
3306
|
+
onPin: handleQuickChatPin,
|
|
3307
|
+
isPinned: true,
|
|
3308
|
+
config: quickChatConfig
|
|
3309
|
+
}
|
|
3310
|
+
),
|
|
3311
|
+
showMenu && /* @__PURE__ */ jsxs3(
|
|
3312
|
+
"div",
|
|
3313
|
+
{
|
|
3314
|
+
ref: menuRef,
|
|
3315
|
+
"aria-label": "Feedback options",
|
|
3316
|
+
className,
|
|
3317
|
+
role: "menu",
|
|
3318
|
+
style: {
|
|
3319
|
+
...menuStyles.container,
|
|
3320
|
+
left: adjustedPosition.x,
|
|
3321
|
+
top: adjustedPosition.y,
|
|
3322
|
+
...containerWidth ? { minWidth: containerWidth, width: containerWidth } : {},
|
|
3323
|
+
touchAction: "none",
|
|
3324
|
+
userSelect: "none",
|
|
3325
|
+
WebkitTouchCallout: "none",
|
|
3326
|
+
WebkitUserSelect: "none",
|
|
3327
|
+
...isDragging ? { cursor: "grabbing" } : {},
|
|
3328
|
+
...style
|
|
3329
|
+
},
|
|
3330
|
+
children: [
|
|
3331
|
+
!header && currentView !== "screenshot-preview" && currentView !== "quick-chat" && /* @__PURE__ */ jsxs3(DefaultHeader, { styles: menuStyles.header, title: "Send Feedback", children: [
|
|
3332
|
+
positionMode === "dynamic" && /* @__PURE__ */ jsx3(
|
|
3333
|
+
"div",
|
|
3334
|
+
{
|
|
3335
|
+
"data-drag-handle": true,
|
|
3336
|
+
onMouseEnter: (e) => {
|
|
3337
|
+
e.currentTarget.style.opacity = "1";
|
|
3338
|
+
},
|
|
3339
|
+
onMouseLeave: (e) => {
|
|
3340
|
+
e.currentTarget.style.opacity = "0.5";
|
|
3341
|
+
},
|
|
3342
|
+
onPointerDown: handleDragStart,
|
|
3343
|
+
style: {
|
|
3344
|
+
...menuStyles.dragHandle,
|
|
3345
|
+
cursor: isDragging ? "grabbing" : "grab"
|
|
3346
|
+
},
|
|
3347
|
+
title: "Drag to move",
|
|
3348
|
+
children: /* @__PURE__ */ jsx3(GripVertical, { className: "w-4 h-4" })
|
|
3349
|
+
}
|
|
3350
|
+
),
|
|
3351
|
+
showPreview && /* @__PURE__ */ jsx3("div", { style: menuStyles.screenshotIndicator, children: /* @__PURE__ */ jsx3(CameraIcon, { className: "w-3 h-3" }) }),
|
|
3352
|
+
quickChatConfig && /* @__PURE__ */ jsx3(
|
|
3353
|
+
"button",
|
|
3354
|
+
{
|
|
3355
|
+
type: "button",
|
|
3356
|
+
onClick: handleQuickChatToggle,
|
|
3357
|
+
style: {
|
|
3358
|
+
display: "flex",
|
|
3359
|
+
alignItems: "center",
|
|
3360
|
+
justifyContent: "center",
|
|
3361
|
+
width: "24px",
|
|
3362
|
+
height: "24px",
|
|
3363
|
+
border: "none",
|
|
3364
|
+
borderRadius: "4px",
|
|
3365
|
+
backgroundColor: isQuickChatPinned ? "var(--anyclick-menu-accent, #0066cc)" : "transparent",
|
|
3366
|
+
color: isQuickChatPinned ? "#fff" : "var(--anyclick-menu-accent, #0066cc)",
|
|
3367
|
+
cursor: "pointer",
|
|
3368
|
+
transition: "all 0.15s ease"
|
|
3369
|
+
},
|
|
3370
|
+
title: isQuickChatPinned ? "Quick Chat (pinned)" : "Quick Ask AI",
|
|
3371
|
+
children: /* @__PURE__ */ jsx3(Sparkles, { className: "w-3.5 h-3.5" })
|
|
3372
|
+
}
|
|
3373
|
+
)
|
|
3374
|
+
] }),
|
|
3375
|
+
!!header && header,
|
|
3376
|
+
currentView === "menu" && /* @__PURE__ */ jsxs3("div", { style: menuStyles.itemList, children: [
|
|
3377
|
+
submenuStack.length > 0 && /* @__PURE__ */ jsx3(BackButton, { onClick: handleBack }),
|
|
3378
|
+
currentItems.map((item) => /* @__PURE__ */ jsx3(
|
|
3379
|
+
MenuItem,
|
|
3380
|
+
{
|
|
3381
|
+
disabled: isSubmitting,
|
|
3382
|
+
hasChildren: item.children && item.children.length > 0,
|
|
3383
|
+
item,
|
|
3384
|
+
onClick: () => handleItemClick(item)
|
|
1404
3385
|
},
|
|
1405
|
-
|
|
1406
|
-
|
|
3386
|
+
item.type
|
|
3387
|
+
))
|
|
3388
|
+
] }),
|
|
3389
|
+
currentView === "comment" && /* @__PURE__ */ jsx3(
|
|
3390
|
+
CommentForm,
|
|
3391
|
+
{
|
|
3392
|
+
isSubmitting,
|
|
3393
|
+
onCancel: handleCommentCancel,
|
|
3394
|
+
onSubmit: handleCommentSubmit
|
|
1407
3395
|
}
|
|
1408
|
-
)
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
currentView === "menu" && /* @__PURE__ */ jsxs2("div", { style: menuStyles.itemList, children: [
|
|
1412
|
-
submenuStack.length > 0 && /* @__PURE__ */ jsx2(BackButton, { onClick: handleBack }),
|
|
1413
|
-
currentItems.map((item) => /* @__PURE__ */ jsx2(
|
|
1414
|
-
MenuItem,
|
|
3396
|
+
),
|
|
3397
|
+
currentView === "screenshot-preview" && /* @__PURE__ */ jsx3(
|
|
3398
|
+
ScreenshotPreview,
|
|
1415
3399
|
{
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
)
|
|
1443
|
-
]
|
|
1444
|
-
}
|
|
1445
|
-
);
|
|
3400
|
+
isLoading: isCapturing,
|
|
3401
|
+
isSubmitting,
|
|
3402
|
+
onCancel: handleScreenshotCancel,
|
|
3403
|
+
onConfirm: handleScreenshotConfirm,
|
|
3404
|
+
onRetake: handleRetakeScreenshots,
|
|
3405
|
+
screenshots
|
|
3406
|
+
}
|
|
3407
|
+
),
|
|
3408
|
+
currentView === "quick-chat" && quickChatConfig && !isQuickChatPinned && /* @__PURE__ */ jsx3(
|
|
3409
|
+
QuickChat,
|
|
3410
|
+
{
|
|
3411
|
+
visible: true,
|
|
3412
|
+
targetElement,
|
|
3413
|
+
containerElement,
|
|
3414
|
+
onClose: handleQuickChatClose,
|
|
3415
|
+
onPin: handleQuickChatPin,
|
|
3416
|
+
isPinned: false,
|
|
3417
|
+
config: quickChatConfig,
|
|
3418
|
+
initialInput: initialChatInput,
|
|
3419
|
+
onInitialInputConsumed: () => setInitialChatInput("")
|
|
3420
|
+
}
|
|
3421
|
+
)
|
|
3422
|
+
]
|
|
3423
|
+
}
|
|
3424
|
+
)
|
|
3425
|
+
] });
|
|
1446
3426
|
}
|
|
1447
3427
|
|
|
1448
3428
|
// src/context.ts
|
|
@@ -1465,12 +3445,12 @@ function useFeedback() {
|
|
|
1465
3445
|
}
|
|
1466
3446
|
|
|
1467
3447
|
// src/store.ts
|
|
1468
|
-
import { create } from "zustand";
|
|
3448
|
+
import { create as create2 } from "zustand";
|
|
1469
3449
|
var providerIdCounter = 0;
|
|
1470
3450
|
function generateProviderId() {
|
|
1471
3451
|
return `anyclick-provider-${++providerIdCounter}`;
|
|
1472
3452
|
}
|
|
1473
|
-
var useProviderStore =
|
|
3453
|
+
var useProviderStore = create2((set, get) => ({
|
|
1474
3454
|
providers: /* @__PURE__ */ new Map(),
|
|
1475
3455
|
findProvidersForElement: (element) => {
|
|
1476
3456
|
const { providers } = get();
|
|
@@ -1626,7 +3606,7 @@ function dispatchContextMenuEvent(event, element) {
|
|
|
1626
3606
|
}
|
|
1627
3607
|
|
|
1628
3608
|
// src/AnyclickProvider.tsx
|
|
1629
|
-
import { jsx as
|
|
3609
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1630
3610
|
var defaultMenuItems = [
|
|
1631
3611
|
{ label: "Report an issue", showComment: true, type: "issue" },
|
|
1632
3612
|
{ label: "Request a feature", showComment: true, type: "feature" },
|
|
@@ -1649,6 +3629,7 @@ function AnyclickProvider({
|
|
|
1649
3629
|
metadata,
|
|
1650
3630
|
onSubmitError,
|
|
1651
3631
|
onSubmitSuccess,
|
|
3632
|
+
quickChatConfig,
|
|
1652
3633
|
scoped = false,
|
|
1653
3634
|
screenshotConfig,
|
|
1654
3635
|
stripAttributes,
|
|
@@ -1657,18 +3638,18 @@ function AnyclickProvider({
|
|
|
1657
3638
|
touchHoldDurationMs,
|
|
1658
3639
|
touchMoveThreshold
|
|
1659
3640
|
}) {
|
|
1660
|
-
const [isSubmitting, setIsSubmitting] =
|
|
1661
|
-
const [menuVisible, setMenuVisible] =
|
|
1662
|
-
const [menuPosition, setMenuPosition] =
|
|
1663
|
-
const [targetElement, setTargetElement] =
|
|
1664
|
-
const [containerElement, setContainerElement] =
|
|
3641
|
+
const [isSubmitting, setIsSubmitting] = useState5(false);
|
|
3642
|
+
const [menuVisible, setMenuVisible] = useState5(false);
|
|
3643
|
+
const [menuPosition, setMenuPosition] = useState5(OFFSCREEN_POSITION2);
|
|
3644
|
+
const [targetElement, setTargetElement] = useState5(null);
|
|
3645
|
+
const [containerElement, setContainerElement] = useState5(
|
|
1665
3646
|
null
|
|
1666
3647
|
);
|
|
1667
3648
|
const providerId = useId();
|
|
1668
|
-
const containerRef =
|
|
1669
|
-
const [containerReady, setContainerReady] =
|
|
1670
|
-
const clientRef =
|
|
1671
|
-
const setContainerRef =
|
|
3649
|
+
const containerRef = useRef4(null);
|
|
3650
|
+
const [containerReady, setContainerReady] = useState5(!scoped);
|
|
3651
|
+
const clientRef = useRef4(null);
|
|
3652
|
+
const setContainerRef = useCallback4(
|
|
1672
3653
|
(node) => {
|
|
1673
3654
|
containerRef.current = node;
|
|
1674
3655
|
if (scoped && node) {
|
|
@@ -1697,7 +3678,7 @@ function AnyclickProvider({
|
|
|
1697
3678
|
updateProvider
|
|
1698
3679
|
} = useProviderStore();
|
|
1699
3680
|
const parentId = parentContext?.providerId ?? null;
|
|
1700
|
-
const actualDepth =
|
|
3681
|
+
const actualDepth = useMemo4(() => {
|
|
1701
3682
|
if (!parentContext) return 0;
|
|
1702
3683
|
let d = 0;
|
|
1703
3684
|
let currentId = parentId;
|
|
@@ -1711,7 +3692,7 @@ function AnyclickProvider({
|
|
|
1711
3692
|
}, [parentContext, parentId]);
|
|
1712
3693
|
const isDisabledByTheme = theme === null || theme?.disabled === true;
|
|
1713
3694
|
const effectiveDisabled = disabled || isDisabledByTheme;
|
|
1714
|
-
const localTheme =
|
|
3695
|
+
const localTheme = useMemo4(() => {
|
|
1715
3696
|
if (theme === null) {
|
|
1716
3697
|
return { disabled: true };
|
|
1717
3698
|
}
|
|
@@ -1726,7 +3707,7 @@ function AnyclickProvider({
|
|
|
1726
3707
|
...theme
|
|
1727
3708
|
};
|
|
1728
3709
|
}, [highlightConfig, menuClassName, menuStyle, screenshotConfig, theme]);
|
|
1729
|
-
const handleContextMenu =
|
|
3710
|
+
const handleContextMenu = useCallback4(
|
|
1730
3711
|
(event, element) => {
|
|
1731
3712
|
if (!scoped && isElementInDisabledScope(element)) {
|
|
1732
3713
|
return false;
|
|
@@ -1780,7 +3761,7 @@ function AnyclickProvider({
|
|
|
1780
3761
|
scoped,
|
|
1781
3762
|
unregisterProvider
|
|
1782
3763
|
]);
|
|
1783
|
-
|
|
3764
|
+
useEffect4(() => {
|
|
1784
3765
|
updateProvider(providerId, {
|
|
1785
3766
|
disabled: effectiveDisabled,
|
|
1786
3767
|
onContextMenu: handleContextMenu,
|
|
@@ -1793,7 +3774,7 @@ function AnyclickProvider({
|
|
|
1793
3774
|
providerId,
|
|
1794
3775
|
updateProvider
|
|
1795
3776
|
]);
|
|
1796
|
-
|
|
3777
|
+
useEffect4(() => {
|
|
1797
3778
|
if (isDisabledByAncestor(providerId)) {
|
|
1798
3779
|
return;
|
|
1799
3780
|
}
|
|
@@ -1841,7 +3822,7 @@ function AnyclickProvider({
|
|
|
1841
3822
|
touchHoldDurationMs,
|
|
1842
3823
|
touchMoveThreshold
|
|
1843
3824
|
]);
|
|
1844
|
-
const submitAnyclick =
|
|
3825
|
+
const submitAnyclick = useCallback4(
|
|
1845
3826
|
async (element, type, comment, screenshots) => {
|
|
1846
3827
|
const client = clientRef.current;
|
|
1847
3828
|
if (!client) return;
|
|
@@ -1862,7 +3843,7 @@ function AnyclickProvider({
|
|
|
1862
3843
|
},
|
|
1863
3844
|
[metadata]
|
|
1864
3845
|
);
|
|
1865
|
-
const openMenu =
|
|
3846
|
+
const openMenu = useCallback4(
|
|
1866
3847
|
(element, position) => {
|
|
1867
3848
|
setTargetElement(element);
|
|
1868
3849
|
const mergedTheme2 = getMergedTheme(providerId);
|
|
@@ -1876,13 +3857,13 @@ function AnyclickProvider({
|
|
|
1876
3857
|
},
|
|
1877
3858
|
[getMergedTheme, highlightConfig, providerId]
|
|
1878
3859
|
);
|
|
1879
|
-
const closeMenu =
|
|
3860
|
+
const closeMenu = useCallback4(() => {
|
|
1880
3861
|
setMenuVisible(false);
|
|
1881
3862
|
setMenuPosition(OFFSCREEN_POSITION2);
|
|
1882
3863
|
setTargetElement(null);
|
|
1883
3864
|
setContainerElement(null);
|
|
1884
3865
|
}, []);
|
|
1885
|
-
const handleMenuSelect =
|
|
3866
|
+
const handleMenuSelect = useCallback4(
|
|
1886
3867
|
(type, comment, screenshots) => {
|
|
1887
3868
|
if (targetElement) {
|
|
1888
3869
|
submitAnyclick(targetElement, type, comment, screenshots);
|
|
@@ -1891,7 +3872,7 @@ function AnyclickProvider({
|
|
|
1891
3872
|
[submitAnyclick, targetElement]
|
|
1892
3873
|
);
|
|
1893
3874
|
const inheritedTheme = getMergedTheme(providerId);
|
|
1894
|
-
const mergedTheme =
|
|
3875
|
+
const mergedTheme = useMemo4(
|
|
1895
3876
|
() => ({
|
|
1896
3877
|
...inheritedTheme,
|
|
1897
3878
|
...localTheme,
|
|
@@ -1914,7 +3895,7 @@ function AnyclickProvider({
|
|
|
1914
3895
|
const effectiveMenuClassName = mergedTheme.menuClassName ?? menuClassName;
|
|
1915
3896
|
const effectiveHighlightConfig = mergedTheme.highlightConfig ?? highlightConfig;
|
|
1916
3897
|
const effectiveScreenshotConfig = mergedTheme.screenshotConfig ?? screenshotConfig;
|
|
1917
|
-
const contextValue =
|
|
3898
|
+
const contextValue = useMemo4(
|
|
1918
3899
|
() => ({
|
|
1919
3900
|
closeMenu,
|
|
1920
3901
|
isEnabled: !effectiveDisabled && !isDisabledByAncestor(providerId),
|
|
@@ -1937,7 +3918,7 @@ function AnyclickProvider({
|
|
|
1937
3918
|
submitAnyclick
|
|
1938
3919
|
]
|
|
1939
3920
|
);
|
|
1940
|
-
const content = scoped ? /* @__PURE__ */
|
|
3921
|
+
const content = scoped ? /* @__PURE__ */ jsx4(
|
|
1941
3922
|
"div",
|
|
1942
3923
|
{
|
|
1943
3924
|
ref: setContainerRef,
|
|
@@ -1946,9 +3927,9 @@ function AnyclickProvider({
|
|
|
1946
3927
|
children
|
|
1947
3928
|
}
|
|
1948
3929
|
) : children;
|
|
1949
|
-
return /* @__PURE__ */
|
|
3930
|
+
return /* @__PURE__ */ jsx4(AnyclickContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs4("div", { "data-anyclick-root": true, children: [
|
|
1950
3931
|
content,
|
|
1951
|
-
/* @__PURE__ */
|
|
3932
|
+
/* @__PURE__ */ jsx4(
|
|
1952
3933
|
ContextMenu,
|
|
1953
3934
|
{
|
|
1954
3935
|
className: effectiveMenuClassName,
|
|
@@ -1960,18 +3941,19 @@ function AnyclickProvider({
|
|
|
1960
3941
|
onClose: closeMenu,
|
|
1961
3942
|
onSelect: handleMenuSelect,
|
|
1962
3943
|
position: menuPosition,
|
|
3944
|
+
quickChatConfig,
|
|
1963
3945
|
screenshotConfig: effectiveScreenshotConfig,
|
|
1964
3946
|
style: effectiveMenuStyle,
|
|
1965
3947
|
targetElement,
|
|
1966
3948
|
visible: menuVisible && !effectiveDisabled
|
|
1967
3949
|
}
|
|
1968
3950
|
)
|
|
1969
|
-
] });
|
|
3951
|
+
] }) });
|
|
1970
3952
|
}
|
|
1971
3953
|
var FeedbackProvider = AnyclickProvider;
|
|
1972
3954
|
|
|
1973
3955
|
// src/FunModeBridge.tsx
|
|
1974
|
-
import { useEffect as
|
|
3956
|
+
import { useEffect as useEffect5, useMemo as useMemo5, useRef as useRef5 } from "react";
|
|
1975
3957
|
import {
|
|
1976
3958
|
usePointer
|
|
1977
3959
|
} from "@ewjdev/anyclick-pointer";
|
|
@@ -2020,9 +4002,9 @@ function buildFunConfig(theme, container) {
|
|
|
2020
4002
|
function FunModeBridge() {
|
|
2021
4003
|
const { setConfig } = usePointer();
|
|
2022
4004
|
const providerStore = useProviderStore();
|
|
2023
|
-
const activeProviderRef =
|
|
2024
|
-
const cachedConfigs =
|
|
2025
|
-
const findActiveFunProvider =
|
|
4005
|
+
const activeProviderRef = useRef5(null);
|
|
4006
|
+
const cachedConfigs = useRef5({});
|
|
4007
|
+
const findActiveFunProvider = useMemo5(() => {
|
|
2026
4008
|
return (el) => {
|
|
2027
4009
|
if (!el) return null;
|
|
2028
4010
|
const providers = providerStore.findProvidersForElement(el);
|
|
@@ -2034,7 +4016,7 @@ function FunModeBridge() {
|
|
|
2034
4016
|
return null;
|
|
2035
4017
|
};
|
|
2036
4018
|
}, [providerStore]);
|
|
2037
|
-
|
|
4019
|
+
useEffect5(() => {
|
|
2038
4020
|
const handleMove = (event) => {
|
|
2039
4021
|
const el = document.elementFromPoint(event.clientX, event.clientY);
|
|
2040
4022
|
const provider = findActiveFunProvider(el);
|
|
@@ -2068,16 +4050,76 @@ function FunModeBridge() {
|
|
|
2068
4050
|
return null;
|
|
2069
4051
|
}
|
|
2070
4052
|
|
|
4053
|
+
// src/ui/button.tsx
|
|
4054
|
+
import { forwardRef } from "react";
|
|
4055
|
+
|
|
4056
|
+
// src/utils/cn.ts
|
|
4057
|
+
function cn(...classes) {
|
|
4058
|
+
return classes.filter(Boolean).join(" ");
|
|
4059
|
+
}
|
|
4060
|
+
|
|
4061
|
+
// src/ui/button.tsx
|
|
4062
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
4063
|
+
var variantClasses = {
|
|
4064
|
+
default: "ac-bg-accent ac-text-accent-foreground hover:ac-bg-accent-muted ac-border ac-border-border",
|
|
4065
|
+
ghost: "ac-bg-transparent hover:ac-bg-surface-muted ac-text-text",
|
|
4066
|
+
outline: "ac-bg-transparent ac-text-text ac-border ac-border-border hover:ac-bg-surface-muted",
|
|
4067
|
+
destructive: "ac-bg-destructive ac-text-accent-foreground hover:ac-bg-destructive/80"
|
|
4068
|
+
};
|
|
4069
|
+
var sizeClasses = {
|
|
4070
|
+
sm: "ac-h-8 ac-px-3 ac-text-sm",
|
|
4071
|
+
md: "ac-h-10 ac-px-4 ac-text-sm",
|
|
4072
|
+
lg: "ac-h-11 ac-px-5 ac-text-base"
|
|
4073
|
+
};
|
|
4074
|
+
var Button = forwardRef(
|
|
4075
|
+
({ className, variant = "default", size = "md", ...props }, ref) => {
|
|
4076
|
+
return /* @__PURE__ */ jsx5(
|
|
4077
|
+
"button",
|
|
4078
|
+
{
|
|
4079
|
+
ref,
|
|
4080
|
+
className: cn(
|
|
4081
|
+
"ac-inline-flex ac-items-center ac-justify-center ac-gap-2 ac-rounded-md ac-font-medium ac-transition-colors focus-visible:ac-outline focus-visible:ac-outline-2 focus-visible:ac-outline-offset-2 focus-visible:ac-outline-accent disabled:ac-opacity-50 disabled:ac-cursor-not-allowed",
|
|
4082
|
+
variantClasses[variant],
|
|
4083
|
+
sizeClasses[size],
|
|
4084
|
+
className
|
|
4085
|
+
),
|
|
4086
|
+
...props
|
|
4087
|
+
}
|
|
4088
|
+
);
|
|
4089
|
+
}
|
|
4090
|
+
);
|
|
4091
|
+
Button.displayName = "Button";
|
|
4092
|
+
|
|
4093
|
+
// src/ui/input.tsx
|
|
4094
|
+
import { forwardRef as forwardRef2 } from "react";
|
|
4095
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
4096
|
+
var Input = forwardRef2(
|
|
4097
|
+
({ className, ...props }, ref) => {
|
|
4098
|
+
return /* @__PURE__ */ jsx6(
|
|
4099
|
+
"input",
|
|
4100
|
+
{
|
|
4101
|
+
ref,
|
|
4102
|
+
className: cn(
|
|
4103
|
+
"ac-h-10 ac-w-full ac-rounded-md ac-border ac-border-border ac-bg-surface ac-text-text ac-placeholder-text-muted ac-px-3 ac-py-2 ac-text-sm focus-visible:ac-outline focus-visible:ac-outline-2 focus-visible:ac-outline-offset-2 focus-visible:ac-outline-accent disabled:ac-opacity-50 disabled:ac-cursor-not-allowed",
|
|
4104
|
+
className
|
|
4105
|
+
),
|
|
4106
|
+
...props
|
|
4107
|
+
}
|
|
4108
|
+
);
|
|
4109
|
+
}
|
|
4110
|
+
);
|
|
4111
|
+
Input.displayName = "Input";
|
|
4112
|
+
|
|
2071
4113
|
// src/InspectDialog/InspectDialogManager.tsx
|
|
2072
|
-
import { useCallback as
|
|
4114
|
+
import { useCallback as useCallback5, useEffect as useEffect7, useState as useState7 } from "react";
|
|
2073
4115
|
|
|
2074
4116
|
// src/InspectDialog/InspectSimple.tsx
|
|
2075
|
-
import { useEffect as
|
|
4117
|
+
import { useEffect as useEffect6, useMemo as useMemo6, useRef as useRef6, useState as useState6 } from "react";
|
|
2076
4118
|
import {
|
|
2077
4119
|
captureScreenshot,
|
|
2078
|
-
getElementInspectInfo
|
|
4120
|
+
getElementInspectInfo as getElementInspectInfo2
|
|
2079
4121
|
} from "@ewjdev/anyclick-core";
|
|
2080
|
-
import { Camera, Code, Copy, ExternalLink, FileText, X } from "lucide-react";
|
|
4122
|
+
import { Camera, Code, Copy as Copy2, ExternalLink as ExternalLink2, FileText, X as X2 } from "lucide-react";
|
|
2081
4123
|
|
|
2082
4124
|
// src/ide.ts
|
|
2083
4125
|
var DEFAULT_IDE_CONFIG = {
|
|
@@ -2179,7 +4221,7 @@ function formatSourceLocation(location) {
|
|
|
2179
4221
|
}
|
|
2180
4222
|
|
|
2181
4223
|
// src/InspectDialog/InspectSimple.tsx
|
|
2182
|
-
import { Fragment as
|
|
4224
|
+
import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2183
4225
|
var DEFAULT_COMPACT_CONFIG = {
|
|
2184
4226
|
scale: 0.5,
|
|
2185
4227
|
fonts: {
|
|
@@ -2241,8 +4283,8 @@ function downloadDataUrl(dataUrl, filename) {
|
|
|
2241
4283
|
link.click();
|
|
2242
4284
|
}
|
|
2243
4285
|
function useIsMobile() {
|
|
2244
|
-
const [isMobile, setIsMobile] =
|
|
2245
|
-
|
|
4286
|
+
const [isMobile, setIsMobile] = useState6(false);
|
|
4287
|
+
useEffect6(() => {
|
|
2246
4288
|
const mq = window.matchMedia("(max-width: 640px)");
|
|
2247
4289
|
setIsMobile(mq.matches);
|
|
2248
4290
|
const handler = (e) => setIsMobile(e.matches);
|
|
@@ -2260,20 +4302,20 @@ function InspectSimple({
|
|
|
2260
4302
|
className,
|
|
2261
4303
|
highlightColors
|
|
2262
4304
|
}) {
|
|
2263
|
-
const [info, setInfo] =
|
|
2264
|
-
const [sourceLocation, setSourceLocation] =
|
|
4305
|
+
const [info, setInfo] = useState6(null);
|
|
4306
|
+
const [sourceLocation, setSourceLocation] = useState6(
|
|
2265
4307
|
null
|
|
2266
4308
|
);
|
|
2267
|
-
const [status, setStatus] =
|
|
2268
|
-
const [saving, setSaving] =
|
|
2269
|
-
const dialogRef =
|
|
4309
|
+
const [status, setStatus] = useState6(null);
|
|
4310
|
+
const [saving, setSaving] = useState6(false);
|
|
4311
|
+
const dialogRef = useRef6(null);
|
|
2270
4312
|
const isMobile = useIsMobile();
|
|
2271
|
-
|
|
4313
|
+
useEffect6(() => {
|
|
2272
4314
|
if (!status) return;
|
|
2273
4315
|
const timer = setTimeout(() => setStatus(null), 5e3);
|
|
2274
4316
|
return () => clearTimeout(timer);
|
|
2275
4317
|
}, [status]);
|
|
2276
|
-
|
|
4318
|
+
useEffect6(() => {
|
|
2277
4319
|
if (!visible || !targetElement) return;
|
|
2278
4320
|
try {
|
|
2279
4321
|
clearHighlights();
|
|
@@ -2282,7 +4324,7 @@ function InspectSimple({
|
|
|
2282
4324
|
if (container) highlightContainer(container, highlightColors);
|
|
2283
4325
|
} catch {
|
|
2284
4326
|
}
|
|
2285
|
-
const nextInfo =
|
|
4327
|
+
const nextInfo = getElementInspectInfo2(targetElement);
|
|
2286
4328
|
setInfo(nextInfo);
|
|
2287
4329
|
setSourceLocation(
|
|
2288
4330
|
findSourceLocationInAncestors(targetElement) ?? nextInfo.sourceLocation ?? null
|
|
@@ -2291,7 +4333,7 @@ function InspectSimple({
|
|
|
2291
4333
|
clearHighlights();
|
|
2292
4334
|
};
|
|
2293
4335
|
}, [visible, targetElement, highlightColors]);
|
|
2294
|
-
|
|
4336
|
+
useEffect6(() => {
|
|
2295
4337
|
if (!visible) return;
|
|
2296
4338
|
const handleClickOutside = (e) => {
|
|
2297
4339
|
if (dialogRef.current && !dialogRef.current.contains(e.target)) {
|
|
@@ -2306,7 +4348,7 @@ function InspectSimple({
|
|
|
2306
4348
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
2307
4349
|
};
|
|
2308
4350
|
}, [visible, onClose]);
|
|
2309
|
-
const identityLabel =
|
|
4351
|
+
const identityLabel = useMemo6(() => {
|
|
2310
4352
|
if (!info) return "Select an element";
|
|
2311
4353
|
const classes = info.classNames[0] ? `.${info.classNames[0]}` : "";
|
|
2312
4354
|
const id = info.id ? `#${info.id}` : "";
|
|
@@ -2392,8 +4434,8 @@ function InspectSimple({
|
|
|
2392
4434
|
overflow: "hidden",
|
|
2393
4435
|
...style
|
|
2394
4436
|
};
|
|
2395
|
-
return /* @__PURE__ */
|
|
2396
|
-
/* @__PURE__ */
|
|
4437
|
+
return /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
|
4438
|
+
/* @__PURE__ */ jsx7(
|
|
2397
4439
|
"div",
|
|
2398
4440
|
{
|
|
2399
4441
|
style: {
|
|
@@ -2408,14 +4450,14 @@ function InspectSimple({
|
|
|
2408
4450
|
role: "presentation"
|
|
2409
4451
|
}
|
|
2410
4452
|
),
|
|
2411
|
-
/* @__PURE__ */
|
|
4453
|
+
/* @__PURE__ */ jsxs5(
|
|
2412
4454
|
"div",
|
|
2413
4455
|
{
|
|
2414
4456
|
ref: dialogRef,
|
|
2415
4457
|
className: `anyclick-tiny-inspect ${className ?? ""}`,
|
|
2416
4458
|
style: dialogStyles,
|
|
2417
4459
|
children: [
|
|
2418
|
-
/* @__PURE__ */
|
|
4460
|
+
/* @__PURE__ */ jsxs5(
|
|
2419
4461
|
"div",
|
|
2420
4462
|
{
|
|
2421
4463
|
style: {
|
|
@@ -2427,7 +4469,7 @@ function InspectSimple({
|
|
|
2427
4469
|
borderBottom: "1px solid #1e293b"
|
|
2428
4470
|
},
|
|
2429
4471
|
children: [
|
|
2430
|
-
isMobile && /* @__PURE__ */
|
|
4472
|
+
isMobile && /* @__PURE__ */ jsx7(
|
|
2431
4473
|
"div",
|
|
2432
4474
|
{
|
|
2433
4475
|
style: {
|
|
@@ -2442,8 +4484,8 @@ function InspectSimple({
|
|
|
2442
4484
|
}
|
|
2443
4485
|
}
|
|
2444
4486
|
),
|
|
2445
|
-
/* @__PURE__ */
|
|
2446
|
-
/* @__PURE__ */
|
|
4487
|
+
/* @__PURE__ */ jsxs5("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
4488
|
+
/* @__PURE__ */ jsx7(
|
|
2447
4489
|
"span",
|
|
2448
4490
|
{
|
|
2449
4491
|
style: {
|
|
@@ -2458,31 +4500,31 @@ function InspectSimple({
|
|
|
2458
4500
|
children: identityLabel
|
|
2459
4501
|
}
|
|
2460
4502
|
),
|
|
2461
|
-
sourceLocation && /* @__PURE__ */
|
|
4503
|
+
sourceLocation && /* @__PURE__ */ jsx7(
|
|
2462
4504
|
"button",
|
|
2463
4505
|
{
|
|
2464
4506
|
type: "button",
|
|
2465
4507
|
onClick: handleOpenIDE,
|
|
2466
4508
|
title: formatSourceLocation(sourceLocation),
|
|
2467
4509
|
style: iconBtnStyle,
|
|
2468
|
-
children: /* @__PURE__ */
|
|
4510
|
+
children: /* @__PURE__ */ jsx7(ExternalLink2, { size: 14 })
|
|
2469
4511
|
}
|
|
2470
4512
|
)
|
|
2471
4513
|
] }),
|
|
2472
|
-
/* @__PURE__ */
|
|
4514
|
+
/* @__PURE__ */ jsx7(
|
|
2473
4515
|
"button",
|
|
2474
4516
|
{
|
|
2475
4517
|
type: "button",
|
|
2476
4518
|
onClick: onClose,
|
|
2477
4519
|
style: iconBtnStyle,
|
|
2478
4520
|
"aria-label": "Close inspector",
|
|
2479
|
-
children: /* @__PURE__ */
|
|
4521
|
+
children: /* @__PURE__ */ jsx7(X2, { size: 16 })
|
|
2480
4522
|
}
|
|
2481
4523
|
)
|
|
2482
4524
|
]
|
|
2483
4525
|
}
|
|
2484
4526
|
),
|
|
2485
|
-
/* @__PURE__ */
|
|
4527
|
+
/* @__PURE__ */ jsxs5(
|
|
2486
4528
|
"div",
|
|
2487
4529
|
{
|
|
2488
4530
|
style: {
|
|
@@ -2492,7 +4534,7 @@ function InspectSimple({
|
|
|
2492
4534
|
gap: 8
|
|
2493
4535
|
},
|
|
2494
4536
|
children: [
|
|
2495
|
-
info?.selector && /* @__PURE__ */
|
|
4537
|
+
info?.selector && /* @__PURE__ */ jsx7(
|
|
2496
4538
|
"code",
|
|
2497
4539
|
{
|
|
2498
4540
|
style: {
|
|
@@ -2507,7 +4549,7 @@ function InspectSimple({
|
|
|
2507
4549
|
children: info.selector
|
|
2508
4550
|
}
|
|
2509
4551
|
),
|
|
2510
|
-
status && /* @__PURE__ */
|
|
4552
|
+
status && /* @__PURE__ */ jsx7(
|
|
2511
4553
|
"div",
|
|
2512
4554
|
{
|
|
2513
4555
|
style: {
|
|
@@ -2519,7 +4561,7 @@ function InspectSimple({
|
|
|
2519
4561
|
children: status
|
|
2520
4562
|
}
|
|
2521
4563
|
),
|
|
2522
|
-
/* @__PURE__ */
|
|
4564
|
+
/* @__PURE__ */ jsxs5(
|
|
2523
4565
|
"div",
|
|
2524
4566
|
{
|
|
2525
4567
|
style: {
|
|
@@ -2528,7 +4570,7 @@ function InspectSimple({
|
|
|
2528
4570
|
gap: 6
|
|
2529
4571
|
},
|
|
2530
4572
|
children: [
|
|
2531
|
-
/* @__PURE__ */
|
|
4573
|
+
/* @__PURE__ */ jsx7(
|
|
2532
4574
|
"button",
|
|
2533
4575
|
{
|
|
2534
4576
|
type: "button",
|
|
@@ -2536,10 +4578,10 @@ function InspectSimple({
|
|
|
2536
4578
|
style: iconActionStyle,
|
|
2537
4579
|
title: "Copy CSS selector",
|
|
2538
4580
|
"aria-label": "Copy CSS selector",
|
|
2539
|
-
children: /* @__PURE__ */
|
|
4581
|
+
children: /* @__PURE__ */ jsx7(Copy2, { size: 15 })
|
|
2540
4582
|
}
|
|
2541
4583
|
),
|
|
2542
|
-
/* @__PURE__ */
|
|
4584
|
+
/* @__PURE__ */ jsx7(
|
|
2543
4585
|
"button",
|
|
2544
4586
|
{
|
|
2545
4587
|
type: "button",
|
|
@@ -2547,10 +4589,10 @@ function InspectSimple({
|
|
|
2547
4589
|
style: iconActionStyle,
|
|
2548
4590
|
title: "Copy text content",
|
|
2549
4591
|
"aria-label": "Copy text content",
|
|
2550
|
-
children: /* @__PURE__ */
|
|
4592
|
+
children: /* @__PURE__ */ jsx7(FileText, { size: 15 })
|
|
2551
4593
|
}
|
|
2552
4594
|
),
|
|
2553
|
-
/* @__PURE__ */
|
|
4595
|
+
/* @__PURE__ */ jsx7(
|
|
2554
4596
|
"button",
|
|
2555
4597
|
{
|
|
2556
4598
|
type: "button",
|
|
@@ -2558,10 +4600,10 @@ function InspectSimple({
|
|
|
2558
4600
|
style: iconActionStyle,
|
|
2559
4601
|
title: "Copy HTML markup",
|
|
2560
4602
|
"aria-label": "Copy HTML markup",
|
|
2561
|
-
children: /* @__PURE__ */
|
|
4603
|
+
children: /* @__PURE__ */ jsx7(Code, { size: 15 })
|
|
2562
4604
|
}
|
|
2563
4605
|
),
|
|
2564
|
-
/* @__PURE__ */
|
|
4606
|
+
/* @__PURE__ */ jsx7(
|
|
2565
4607
|
"button",
|
|
2566
4608
|
{
|
|
2567
4609
|
type: "button",
|
|
@@ -2573,7 +4615,7 @@ function InspectSimple({
|
|
|
2573
4615
|
disabled: saving,
|
|
2574
4616
|
title: "Save screenshot",
|
|
2575
4617
|
"aria-label": "Save screenshot",
|
|
2576
|
-
children: /* @__PURE__ */
|
|
4618
|
+
children: /* @__PURE__ */ jsx7(Camera, { size: 15 })
|
|
2577
4619
|
}
|
|
2578
4620
|
)
|
|
2579
4621
|
]
|
|
@@ -2616,7 +4658,7 @@ var iconActionStyle = {
|
|
|
2616
4658
|
};
|
|
2617
4659
|
|
|
2618
4660
|
// src/InspectDialog/InspectDialogManager.tsx
|
|
2619
|
-
import { jsx as
|
|
4661
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
2620
4662
|
var INSPECT_DIALOG_EVENT = "anyclick:inspect";
|
|
2621
4663
|
function openInspectDialog(targetElement) {
|
|
2622
4664
|
if (typeof window === "undefined") return;
|
|
@@ -2639,16 +4681,16 @@ function InspectDialogManager({
|
|
|
2639
4681
|
initialPinnedPosition = "floating",
|
|
2640
4682
|
compactConfig
|
|
2641
4683
|
}) {
|
|
2642
|
-
const [visible, setVisible] =
|
|
2643
|
-
const [targetElement, setTargetElement] =
|
|
2644
|
-
const handleClose =
|
|
4684
|
+
const [visible, setVisible] = useState7(false);
|
|
4685
|
+
const [targetElement, setTargetElement] = useState7(null);
|
|
4686
|
+
const handleClose = useCallback5(() => {
|
|
2645
4687
|
setVisible(false);
|
|
2646
4688
|
setTargetElement(null);
|
|
2647
4689
|
}, []);
|
|
2648
|
-
const handleSelectElement =
|
|
4690
|
+
const handleSelectElement = useCallback5((element) => {
|
|
2649
4691
|
setTargetElement(element);
|
|
2650
4692
|
}, []);
|
|
2651
|
-
|
|
4693
|
+
useEffect7(() => {
|
|
2652
4694
|
const handleInspectEvent = (event) => {
|
|
2653
4695
|
const customEvent = event;
|
|
2654
4696
|
if (customEvent.detail?.targetElement) {
|
|
@@ -2661,7 +4703,7 @@ function InspectDialogManager({
|
|
|
2661
4703
|
window.removeEventListener(INSPECT_DIALOG_EVENT, handleInspectEvent);
|
|
2662
4704
|
};
|
|
2663
4705
|
}, []);
|
|
2664
|
-
return /* @__PURE__ */
|
|
4706
|
+
return /* @__PURE__ */ jsx8(
|
|
2665
4707
|
InspectSimple,
|
|
2666
4708
|
{
|
|
2667
4709
|
visible,
|
|
@@ -2723,6 +4765,20 @@ var presetDefaults = {
|
|
|
2723
4765
|
showComment: false,
|
|
2724
4766
|
type: "search_google"
|
|
2725
4767
|
},
|
|
4768
|
+
{
|
|
4769
|
+
label: "Ask t3.chat",
|
|
4770
|
+
onClick: ({ closeMenu }) => {
|
|
4771
|
+
closeMenu();
|
|
4772
|
+
if (typeof window === "undefined") return false;
|
|
4773
|
+
const selection = window.getSelection()?.toString().trim();
|
|
4774
|
+
const query = selection && selection.length > 0 ? selection : "";
|
|
4775
|
+
const url = query ? `https://t3.chat/?q=${encodeURIComponent(query)}` : "https://t3.chat";
|
|
4776
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
4777
|
+
return false;
|
|
4778
|
+
},
|
|
4779
|
+
showComment: false,
|
|
4780
|
+
type: "ask_t3chat"
|
|
4781
|
+
},
|
|
2726
4782
|
{
|
|
2727
4783
|
label: "Share\u2026",
|
|
2728
4784
|
onClick: async ({ closeMenu }) => {
|
|
@@ -2992,6 +5048,172 @@ function listPresets() {
|
|
|
2992
5048
|
}))
|
|
2993
5049
|
}));
|
|
2994
5050
|
}
|
|
5051
|
+
function createT3ChatMenuItem(options = {}) {
|
|
5052
|
+
const { label = "Ask t3.chat", baseUrl = "https://t3.chat" } = options;
|
|
5053
|
+
return {
|
|
5054
|
+
label,
|
|
5055
|
+
onClick: ({ closeMenu }) => {
|
|
5056
|
+
closeMenu();
|
|
5057
|
+
if (typeof window === "undefined") return false;
|
|
5058
|
+
const selection = window.getSelection()?.toString().trim();
|
|
5059
|
+
const query = selection && selection.length > 0 ? selection : "";
|
|
5060
|
+
const url = query ? `${baseUrl}/?q=${encodeURIComponent(query)}` : baseUrl;
|
|
5061
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
5062
|
+
return false;
|
|
5063
|
+
},
|
|
5064
|
+
showComment: false,
|
|
5065
|
+
type: "ask_t3chat"
|
|
5066
|
+
};
|
|
5067
|
+
}
|
|
5068
|
+
function getSelectedText() {
|
|
5069
|
+
if (typeof window === "undefined") return "";
|
|
5070
|
+
return window.getSelection()?.toString().trim() ?? "";
|
|
5071
|
+
}
|
|
5072
|
+
function hasTextSelection() {
|
|
5073
|
+
return getSelectedText().length > 0;
|
|
5074
|
+
}
|
|
5075
|
+
function detectImageElement(element) {
|
|
5076
|
+
if (!element) return { isImage: false };
|
|
5077
|
+
if (element.tagName === "IMG") {
|
|
5078
|
+
const img = element;
|
|
5079
|
+
return {
|
|
5080
|
+
isImage: true,
|
|
5081
|
+
src: img.src || img.currentSrc,
|
|
5082
|
+
type: "img"
|
|
5083
|
+
};
|
|
5084
|
+
}
|
|
5085
|
+
if (element.tagName === "PICTURE") {
|
|
5086
|
+
const img = element.querySelector("img");
|
|
5087
|
+
return {
|
|
5088
|
+
isImage: true,
|
|
5089
|
+
src: img?.src || img?.currentSrc,
|
|
5090
|
+
type: "picture"
|
|
5091
|
+
};
|
|
5092
|
+
}
|
|
5093
|
+
if (element.tagName === "SVG" || element.tagName === "svg") {
|
|
5094
|
+
return {
|
|
5095
|
+
isImage: true,
|
|
5096
|
+
type: "svg"
|
|
5097
|
+
};
|
|
5098
|
+
}
|
|
5099
|
+
if (element.tagName === "CANVAS") {
|
|
5100
|
+
return {
|
|
5101
|
+
isImage: true,
|
|
5102
|
+
type: "canvas"
|
|
5103
|
+
};
|
|
5104
|
+
}
|
|
5105
|
+
if (typeof window !== "undefined") {
|
|
5106
|
+
const computedStyle = window.getComputedStyle(element);
|
|
5107
|
+
const backgroundImage = computedStyle.backgroundImage;
|
|
5108
|
+
if (backgroundImage && backgroundImage !== "none") {
|
|
5109
|
+
const urlMatch = backgroundImage.match(/url\(["']?(.+?)["']?\)/);
|
|
5110
|
+
if (urlMatch) {
|
|
5111
|
+
return {
|
|
5112
|
+
isImage: true,
|
|
5113
|
+
src: urlMatch[1],
|
|
5114
|
+
type: "background"
|
|
5115
|
+
};
|
|
5116
|
+
}
|
|
5117
|
+
}
|
|
5118
|
+
}
|
|
5119
|
+
const imgChild = element.querySelector("img");
|
|
5120
|
+
if (imgChild) {
|
|
5121
|
+
return {
|
|
5122
|
+
isImage: true,
|
|
5123
|
+
src: imgChild.src || imgChild.currentSrc,
|
|
5124
|
+
type: "img"
|
|
5125
|
+
};
|
|
5126
|
+
}
|
|
5127
|
+
return { isImage: false };
|
|
5128
|
+
}
|
|
5129
|
+
function createUploadThingMenuItem(options = {}) {
|
|
5130
|
+
const {
|
|
5131
|
+
label = "Upload to UploadThing",
|
|
5132
|
+
endpoint = "/api/uploadthing",
|
|
5133
|
+
onUploadComplete,
|
|
5134
|
+
onUploadError
|
|
5135
|
+
} = options;
|
|
5136
|
+
return {
|
|
5137
|
+
label,
|
|
5138
|
+
onClick: async ({ closeMenu, targetElement }) => {
|
|
5139
|
+
if (!targetElement) {
|
|
5140
|
+
onUploadError?.(new Error("No target element"));
|
|
5141
|
+
return false;
|
|
5142
|
+
}
|
|
5143
|
+
try {
|
|
5144
|
+
const imageInfo = detectImageElement(targetElement);
|
|
5145
|
+
if (imageInfo.isImage && imageInfo.src) {
|
|
5146
|
+
const response = await fetch(imageInfo.src);
|
|
5147
|
+
const blob = await response.blob();
|
|
5148
|
+
const formData = new FormData();
|
|
5149
|
+
const filename = `image-${Date.now()}.${blob.type.split("/")[1] || "png"}`;
|
|
5150
|
+
formData.append("file", blob, filename);
|
|
5151
|
+
const uploadResponse = await fetch(endpoint, {
|
|
5152
|
+
method: "POST",
|
|
5153
|
+
body: formData
|
|
5154
|
+
});
|
|
5155
|
+
if (!uploadResponse.ok) {
|
|
5156
|
+
throw new Error(`Upload failed: ${uploadResponse.status}`);
|
|
5157
|
+
}
|
|
5158
|
+
const result = await uploadResponse.json();
|
|
5159
|
+
onUploadComplete?.(result);
|
|
5160
|
+
} else if (imageInfo.isImage && imageInfo.type === "canvas") {
|
|
5161
|
+
const canvas = targetElement;
|
|
5162
|
+
const dataUrl = canvas.toDataURL("image/png");
|
|
5163
|
+
const response = await fetch(dataUrl);
|
|
5164
|
+
const blob = await response.blob();
|
|
5165
|
+
const formData = new FormData();
|
|
5166
|
+
formData.append("file", blob, `canvas-${Date.now()}.png`);
|
|
5167
|
+
const uploadResponse = await fetch(endpoint, {
|
|
5168
|
+
method: "POST",
|
|
5169
|
+
body: formData
|
|
5170
|
+
});
|
|
5171
|
+
if (!uploadResponse.ok) {
|
|
5172
|
+
throw new Error(`Upload failed: ${uploadResponse.status}`);
|
|
5173
|
+
}
|
|
5174
|
+
const result = await uploadResponse.json();
|
|
5175
|
+
onUploadComplete?.(result);
|
|
5176
|
+
} else {
|
|
5177
|
+
onUploadError?.(
|
|
5178
|
+
new Error(
|
|
5179
|
+
"Element is not an image. Screenshot upload requires anyclick-core."
|
|
5180
|
+
)
|
|
5181
|
+
);
|
|
5182
|
+
}
|
|
5183
|
+
} catch (error) {
|
|
5184
|
+
onUploadError?.(
|
|
5185
|
+
error instanceof Error ? error : new Error(String(error))
|
|
5186
|
+
);
|
|
5187
|
+
}
|
|
5188
|
+
closeMenu();
|
|
5189
|
+
return false;
|
|
5190
|
+
},
|
|
5191
|
+
showComment: false,
|
|
5192
|
+
type: "upload_image"
|
|
5193
|
+
};
|
|
5194
|
+
}
|
|
5195
|
+
function createUploadScreenshotMenuItem(options = {}) {
|
|
5196
|
+
const {
|
|
5197
|
+
label = "Upload Screenshot",
|
|
5198
|
+
endpoint = "/api/uploadthing",
|
|
5199
|
+
onUploadComplete,
|
|
5200
|
+
onUploadError
|
|
5201
|
+
} = options;
|
|
5202
|
+
return {
|
|
5203
|
+
label,
|
|
5204
|
+
badge: { label: "Coming soon", tone: "info" },
|
|
5205
|
+
status: "comingSoon",
|
|
5206
|
+
onClick: async ({ closeMenu }) => {
|
|
5207
|
+
onUploadError?.(
|
|
5208
|
+
new Error("Screenshot upload will be available in a future release")
|
|
5209
|
+
);
|
|
5210
|
+
closeMenu();
|
|
5211
|
+
return false;
|
|
5212
|
+
},
|
|
5213
|
+
showComment: false,
|
|
5214
|
+
type: "upload_screenshot"
|
|
5215
|
+
};
|
|
5216
|
+
}
|
|
2995
5217
|
|
|
2996
5218
|
// src/types.ts
|
|
2997
5219
|
function filterMenuItemsByRole(items, userContext) {
|
|
@@ -3021,7 +5243,7 @@ import {
|
|
|
3021
5243
|
} from "@ewjdev/anyclick-core";
|
|
3022
5244
|
|
|
3023
5245
|
// src/AnyclickLogo.tsx
|
|
3024
|
-
import { jsx as
|
|
5246
|
+
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
3025
5247
|
function AnyclickLogo({
|
|
3026
5248
|
size = 64,
|
|
3027
5249
|
borderWidth = 2,
|
|
@@ -3033,7 +5255,7 @@ function AnyclickLogo({
|
|
|
3033
5255
|
}) {
|
|
3034
5256
|
const cursorSize = size * 0.45;
|
|
3035
5257
|
const cursorStroke = borderWidth;
|
|
3036
|
-
return /* @__PURE__ */
|
|
5258
|
+
return /* @__PURE__ */ jsxs6(
|
|
3037
5259
|
"svg",
|
|
3038
5260
|
{
|
|
3039
5261
|
width: size,
|
|
@@ -3047,7 +5269,7 @@ function AnyclickLogo({
|
|
|
3047
5269
|
role: onClick ? "button" : "img",
|
|
3048
5270
|
"aria-label": "Anyclick Logo",
|
|
3049
5271
|
children: [
|
|
3050
|
-
/* @__PURE__ */
|
|
5272
|
+
/* @__PURE__ */ jsx9(
|
|
3051
5273
|
"circle",
|
|
3052
5274
|
{
|
|
3053
5275
|
cx: size / 2,
|
|
@@ -3058,11 +5280,11 @@ function AnyclickLogo({
|
|
|
3058
5280
|
strokeWidth: borderWidth
|
|
3059
5281
|
}
|
|
3060
5282
|
),
|
|
3061
|
-
/* @__PURE__ */
|
|
5283
|
+
/* @__PURE__ */ jsx9(
|
|
3062
5284
|
"g",
|
|
3063
5285
|
{
|
|
3064
5286
|
transform: `translate(${(size - cursorSize) / 2}, ${(size - cursorSize) / 2})`,
|
|
3065
|
-
children: /* @__PURE__ */
|
|
5287
|
+
children: /* @__PURE__ */ jsx9(
|
|
3066
5288
|
"path",
|
|
3067
5289
|
{
|
|
3068
5290
|
d: `
|
|
@@ -3095,7 +5317,7 @@ import {
|
|
|
3095
5317
|
getAccessibilityInfo,
|
|
3096
5318
|
getBoxModelInfo,
|
|
3097
5319
|
getAttributes,
|
|
3098
|
-
getElementInspectInfo as
|
|
5320
|
+
getElementInspectInfo as getElementInspectInfo3,
|
|
3099
5321
|
formatStylesAsCSS,
|
|
3100
5322
|
formatBoxModel,
|
|
3101
5323
|
CURATED_STYLE_PROPERTIES,
|
|
@@ -3106,17 +5328,21 @@ export {
|
|
|
3106
5328
|
AnyclickContext,
|
|
3107
5329
|
AnyclickLogo,
|
|
3108
5330
|
AnyclickProvider,
|
|
5331
|
+
Button,
|
|
3109
5332
|
CURATED_STYLE_PROPERTIES,
|
|
3110
5333
|
ContextMenu,
|
|
3111
5334
|
DEFAULT_COMPACT_CONFIG,
|
|
5335
|
+
DEFAULT_QUICK_CHAT_CONFIG,
|
|
3112
5336
|
DEFAULT_SCREENSHOT_CONFIG2 as DEFAULT_SCREENSHOT_CONFIG,
|
|
3113
5337
|
DEFAULT_SENSITIVE_SELECTORS,
|
|
3114
5338
|
FeedbackContext,
|
|
3115
5339
|
FeedbackProvider,
|
|
3116
5340
|
FunModeBridge,
|
|
3117
5341
|
INSPECT_DIALOG_EVENT,
|
|
5342
|
+
Input,
|
|
3118
5343
|
InspectDialogManager,
|
|
3119
5344
|
InspectSimple,
|
|
5345
|
+
QuickChat,
|
|
3120
5346
|
ScreenshotPreview,
|
|
3121
5347
|
applyHighlights,
|
|
3122
5348
|
buildIDEUrl,
|
|
@@ -3125,9 +5351,13 @@ export {
|
|
|
3125
5351
|
clearHighlights,
|
|
3126
5352
|
createIDEOpener,
|
|
3127
5353
|
createPresetMenu,
|
|
5354
|
+
createT3ChatMenuItem,
|
|
5355
|
+
createUploadScreenshotMenuItem,
|
|
5356
|
+
createUploadThingMenuItem,
|
|
3128
5357
|
darkMenuStyles,
|
|
3129
5358
|
defaultContainerSelectors,
|
|
3130
5359
|
defaultHighlightColors,
|
|
5360
|
+
detectImageElement,
|
|
3131
5361
|
detectPreferredIDE,
|
|
3132
5362
|
dispatchContextMenuEvent,
|
|
3133
5363
|
estimateTotalSize2 as estimateTotalSize,
|
|
@@ -3144,8 +5374,10 @@ export {
|
|
|
3144
5374
|
getBadgeStyle,
|
|
3145
5375
|
getBoxModelInfo,
|
|
3146
5376
|
getComputedStyles,
|
|
3147
|
-
|
|
5377
|
+
getElementInspectInfo3 as getElementInspectInfo,
|
|
5378
|
+
getSelectedText,
|
|
3148
5379
|
getSourceLocationFromElement,
|
|
5380
|
+
hasTextSelection,
|
|
3149
5381
|
highlightContainer,
|
|
3150
5382
|
highlightTarget,
|
|
3151
5383
|
isIDEProtocolSupported,
|
|
@@ -3156,8 +5388,11 @@ export {
|
|
|
3156
5388
|
openInIDE,
|
|
3157
5389
|
openInspectDialog,
|
|
3158
5390
|
presetDefaults,
|
|
5391
|
+
quickChatKeyframes,
|
|
5392
|
+
quickChatStyles,
|
|
3159
5393
|
useAnyclick,
|
|
3160
5394
|
useFeedback,
|
|
3161
|
-
useProviderStore
|
|
5395
|
+
useProviderStore,
|
|
5396
|
+
useQuickChat
|
|
3162
5397
|
};
|
|
3163
5398
|
//# sourceMappingURL=index.mjs.map
|