@ewjdev/anyclick-react 2.0.0 → 3.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/index.d.mts +375 -4
- package/dist/index.d.ts +375 -4
- package/dist/index.js +1945 -308
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1921 -276
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -31,80 +31,1417 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
// src/index.ts
|
|
32
32
|
var index_exports = {};
|
|
33
33
|
__export(index_exports, {
|
|
34
|
-
ALL_CURATED_PROPERTIES: () =>
|
|
34
|
+
ALL_CURATED_PROPERTIES: () => import_anyclick_core7.ALL_CURATED_PROPERTIES,
|
|
35
35
|
AnyclickContext: () => AnyclickContext,
|
|
36
36
|
AnyclickLogo: () => AnyclickLogo,
|
|
37
37
|
AnyclickProvider: () => AnyclickProvider,
|
|
38
|
-
CURATED_STYLE_PROPERTIES: () =>
|
|
38
|
+
CURATED_STYLE_PROPERTIES: () => import_anyclick_core7.CURATED_STYLE_PROPERTIES,
|
|
39
39
|
ContextMenu: () => ContextMenu,
|
|
40
40
|
DEFAULT_COMPACT_CONFIG: () => DEFAULT_COMPACT_CONFIG,
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
DEFAULT_QUICK_CHAT_CONFIG: () => DEFAULT_QUICK_CHAT_CONFIG,
|
|
42
|
+
DEFAULT_SCREENSHOT_CONFIG: () => import_anyclick_core6.DEFAULT_SCREENSHOT_CONFIG,
|
|
43
|
+
DEFAULT_SENSITIVE_SELECTORS: () => import_anyclick_core6.DEFAULT_SENSITIVE_SELECTORS,
|
|
43
44
|
FeedbackContext: () => FeedbackContext,
|
|
44
45
|
FeedbackProvider: () => FeedbackProvider,
|
|
45
46
|
FunModeBridge: () => FunModeBridge,
|
|
46
47
|
INSPECT_DIALOG_EVENT: () => INSPECT_DIALOG_EVENT,
|
|
47
48
|
InspectDialogManager: () => InspectDialogManager,
|
|
48
49
|
InspectSimple: () => InspectSimple,
|
|
50
|
+
QuickChat: () => QuickChat,
|
|
49
51
|
ScreenshotPreview: () => ScreenshotPreview,
|
|
50
52
|
applyHighlights: () => applyHighlights,
|
|
51
53
|
buildIDEUrl: () => buildIDEUrl,
|
|
52
|
-
captureAllScreenshots: () =>
|
|
53
|
-
captureScreenshot: () =>
|
|
54
|
+
captureAllScreenshots: () => import_anyclick_core6.captureAllScreenshots,
|
|
55
|
+
captureScreenshot: () => import_anyclick_core6.captureScreenshot,
|
|
54
56
|
clearHighlights: () => clearHighlights,
|
|
55
57
|
createIDEOpener: () => createIDEOpener,
|
|
56
58
|
createPresetMenu: () => createPresetMenu,
|
|
59
|
+
createT3ChatMenuItem: () => createT3ChatMenuItem,
|
|
60
|
+
createUploadScreenshotMenuItem: () => createUploadScreenshotMenuItem,
|
|
61
|
+
createUploadThingMenuItem: () => createUploadThingMenuItem,
|
|
57
62
|
darkMenuStyles: () => darkMenuStyles,
|
|
58
63
|
defaultContainerSelectors: () => defaultContainerSelectors,
|
|
59
64
|
defaultHighlightColors: () => defaultHighlightColors,
|
|
65
|
+
detectImageElement: () => detectImageElement,
|
|
60
66
|
detectPreferredIDE: () => detectPreferredIDE,
|
|
61
67
|
dispatchContextMenuEvent: () => dispatchContextMenuEvent,
|
|
62
|
-
estimateTotalSize: () =>
|
|
68
|
+
estimateTotalSize: () => import_anyclick_core6.estimateTotalSize,
|
|
63
69
|
filterMenuItemsByRole: () => filterMenuItemsByRole,
|
|
64
70
|
findContainerParent: () => findContainerParent,
|
|
65
71
|
findSourceLocationInAncestors: () => findSourceLocationInAncestors,
|
|
66
|
-
formatBoxModel: () =>
|
|
67
|
-
formatBytes: () =>
|
|
72
|
+
formatBoxModel: () => import_anyclick_core7.formatBoxModel,
|
|
73
|
+
formatBytes: () => import_anyclick_core6.formatBytes,
|
|
68
74
|
formatSourceLocation: () => formatSourceLocation,
|
|
69
|
-
formatStylesAsCSS: () =>
|
|
75
|
+
formatStylesAsCSS: () => import_anyclick_core7.formatStylesAsCSS,
|
|
70
76
|
generateProviderId: () => generateProviderId,
|
|
71
|
-
getAccessibilityInfo: () =>
|
|
72
|
-
getAttributes: () =>
|
|
77
|
+
getAccessibilityInfo: () => import_anyclick_core7.getAccessibilityInfo,
|
|
78
|
+
getAttributes: () => import_anyclick_core7.getAttributes,
|
|
73
79
|
getBadgeStyle: () => getBadgeStyle,
|
|
74
|
-
getBoxModelInfo: () =>
|
|
75
|
-
getComputedStyles: () =>
|
|
76
|
-
getElementInspectInfo: () =>
|
|
80
|
+
getBoxModelInfo: () => import_anyclick_core7.getBoxModelInfo,
|
|
81
|
+
getComputedStyles: () => import_anyclick_core7.getComputedStyles,
|
|
82
|
+
getElementInspectInfo: () => import_anyclick_core7.getElementInspectInfo,
|
|
83
|
+
getSelectedText: () => getSelectedText,
|
|
77
84
|
getSourceLocationFromElement: () => getSourceLocationFromElement,
|
|
85
|
+
hasTextSelection: () => hasTextSelection,
|
|
78
86
|
highlightContainer: () => highlightContainer,
|
|
79
87
|
highlightTarget: () => highlightTarget,
|
|
80
88
|
isIDEProtocolSupported: () => isIDEProtocolSupported,
|
|
81
|
-
isScreenshotSupported: () =>
|
|
89
|
+
isScreenshotSupported: () => import_anyclick_core6.isScreenshotSupported,
|
|
82
90
|
listPresets: () => listPresets,
|
|
83
91
|
menuCSSVariables: () => menuCSSVariables,
|
|
84
92
|
menuStyles: () => menuStyles,
|
|
85
93
|
openInIDE: () => openInIDE,
|
|
86
94
|
openInspectDialog: () => openInspectDialog,
|
|
87
95
|
presetDefaults: () => presetDefaults,
|
|
96
|
+
quickChatKeyframes: () => quickChatKeyframes,
|
|
97
|
+
quickChatStyles: () => quickChatStyles,
|
|
88
98
|
useAnyclick: () => useAnyclick,
|
|
89
99
|
useFeedback: () => useFeedback,
|
|
90
|
-
useProviderStore: () => useProviderStore
|
|
100
|
+
useProviderStore: () => useProviderStore,
|
|
101
|
+
useQuickChat: () => useQuickChat
|
|
91
102
|
});
|
|
92
103
|
module.exports = __toCommonJS(index_exports);
|
|
93
104
|
|
|
94
105
|
// src/AnyclickProvider.tsx
|
|
95
|
-
var
|
|
106
|
+
var import_react6 = require("react");
|
|
107
|
+
var import_anyclick_core4 = require("@ewjdev/anyclick-core");
|
|
108
|
+
|
|
109
|
+
// src/ContextMenu.tsx
|
|
110
|
+
var import_react4 = __toESM(require("react"));
|
|
96
111
|
var import_anyclick_core3 = require("@ewjdev/anyclick-core");
|
|
112
|
+
var import_lucide_react3 = require("lucide-react");
|
|
113
|
+
|
|
114
|
+
// src/QuickChat/QuickChat.tsx
|
|
115
|
+
var import_react2 = __toESM(require("react"));
|
|
116
|
+
var import_lucide_react = require("lucide-react");
|
|
117
|
+
|
|
118
|
+
// src/QuickChat/styles.ts
|
|
119
|
+
var quickChatStyles = {
|
|
120
|
+
// Inline container - inside the context menu
|
|
121
|
+
container: {
|
|
122
|
+
display: "flex",
|
|
123
|
+
flexDirection: "column",
|
|
124
|
+
width: "100%",
|
|
125
|
+
maxHeight: "320px",
|
|
126
|
+
overflow: "hidden"
|
|
127
|
+
},
|
|
128
|
+
// Pinned drawer - anchored to right side of screen
|
|
129
|
+
pinnedContainer: {
|
|
130
|
+
position: "fixed",
|
|
131
|
+
top: 0,
|
|
132
|
+
right: 0,
|
|
133
|
+
bottom: 0,
|
|
134
|
+
width: "340px",
|
|
135
|
+
display: "flex",
|
|
136
|
+
flexDirection: "column",
|
|
137
|
+
backgroundColor: "var(--anyclick-menu-bg, #ffffff)",
|
|
138
|
+
borderLeft: "1px solid var(--anyclick-menu-border, #e5e5e5)",
|
|
139
|
+
boxShadow: "-4px 0 24px rgba(0, 0, 0, 0.15)",
|
|
140
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
141
|
+
fontSize: "14px",
|
|
142
|
+
overflow: "hidden",
|
|
143
|
+
zIndex: 9998
|
|
144
|
+
},
|
|
145
|
+
// Pinned messages area (taller)
|
|
146
|
+
pinnedMessagesArea: {
|
|
147
|
+
flex: 1,
|
|
148
|
+
overflowY: "auto",
|
|
149
|
+
padding: "12px",
|
|
150
|
+
display: "flex",
|
|
151
|
+
flexDirection: "column",
|
|
152
|
+
gap: "8px",
|
|
153
|
+
minHeight: "200px"
|
|
154
|
+
},
|
|
155
|
+
// Header - minimal design
|
|
156
|
+
header: {
|
|
157
|
+
display: "flex",
|
|
158
|
+
alignItems: "center",
|
|
159
|
+
justifyContent: "space-between",
|
|
160
|
+
padding: "6px 8px",
|
|
161
|
+
gap: "8px"
|
|
162
|
+
},
|
|
163
|
+
headerTitle: {
|
|
164
|
+
fontSize: "11px",
|
|
165
|
+
fontWeight: 600,
|
|
166
|
+
textTransform: "uppercase",
|
|
167
|
+
letterSpacing: "0.5px",
|
|
168
|
+
color: "var(--anyclick-menu-text-muted, #666)"
|
|
169
|
+
},
|
|
170
|
+
headerActions: {
|
|
171
|
+
display: "flex",
|
|
172
|
+
alignItems: "center",
|
|
173
|
+
gap: "2px"
|
|
174
|
+
},
|
|
175
|
+
iconButton: {
|
|
176
|
+
display: "flex",
|
|
177
|
+
alignItems: "center",
|
|
178
|
+
justifyContent: "center",
|
|
179
|
+
width: "24px",
|
|
180
|
+
height: "24px",
|
|
181
|
+
border: "none",
|
|
182
|
+
borderRadius: "4px",
|
|
183
|
+
backgroundColor: "transparent",
|
|
184
|
+
color: "var(--anyclick-menu-text-muted, #666)",
|
|
185
|
+
cursor: "pointer",
|
|
186
|
+
transition: "all 0.15s ease"
|
|
187
|
+
},
|
|
188
|
+
iconButtonActive: {
|
|
189
|
+
backgroundColor: "var(--anyclick-menu-accent, #0066cc)",
|
|
190
|
+
color: "#fff"
|
|
191
|
+
},
|
|
192
|
+
// Context badge in header
|
|
193
|
+
contextBadge: {
|
|
194
|
+
display: "inline-flex",
|
|
195
|
+
alignItems: "center",
|
|
196
|
+
gap: "4px",
|
|
197
|
+
padding: "3px 8px",
|
|
198
|
+
fontSize: "10px",
|
|
199
|
+
fontWeight: 500,
|
|
200
|
+
border: "1px solid var(--anyclick-menu-border, #e5e5e5)",
|
|
201
|
+
borderRadius: "10px",
|
|
202
|
+
backgroundColor: "transparent",
|
|
203
|
+
color: "var(--anyclick-menu-text-muted, #666)",
|
|
204
|
+
cursor: "pointer",
|
|
205
|
+
transition: "all 0.15s ease"
|
|
206
|
+
},
|
|
207
|
+
contextBadgeActive: {
|
|
208
|
+
borderColor: "var(--anyclick-menu-accent, #0066cc)",
|
|
209
|
+
backgroundColor: "rgba(0, 102, 204, 0.08)"
|
|
210
|
+
},
|
|
211
|
+
// Context dropdown (in normal flow, not absolute)
|
|
212
|
+
contextDropdown: {
|
|
213
|
+
display: "flex",
|
|
214
|
+
flexDirection: "column",
|
|
215
|
+
gap: "2px",
|
|
216
|
+
padding: "6px 8px",
|
|
217
|
+
margin: "0 8px 6px 8px",
|
|
218
|
+
backgroundColor: "var(--anyclick-menu-hover, #f5f5f5)",
|
|
219
|
+
borderRadius: "6px",
|
|
220
|
+
maxHeight: "80px",
|
|
221
|
+
overflowY: "auto"
|
|
222
|
+
},
|
|
223
|
+
// Messages area
|
|
224
|
+
messagesArea: {
|
|
225
|
+
flex: 1,
|
|
226
|
+
overflowY: "auto",
|
|
227
|
+
padding: "8px 12px",
|
|
228
|
+
display: "flex",
|
|
229
|
+
flexDirection: "column",
|
|
230
|
+
gap: "8px",
|
|
231
|
+
minHeight: "40px",
|
|
232
|
+
maxHeight: "140px"
|
|
233
|
+
},
|
|
234
|
+
emptyState: {
|
|
235
|
+
display: "none"
|
|
236
|
+
// Hide empty state, placeholder in input is enough
|
|
237
|
+
},
|
|
238
|
+
// Message bubble
|
|
239
|
+
message: {
|
|
240
|
+
display: "flex",
|
|
241
|
+
flexDirection: "column",
|
|
242
|
+
gap: "4px",
|
|
243
|
+
maxWidth: "100%"
|
|
244
|
+
},
|
|
245
|
+
messageUser: {
|
|
246
|
+
alignSelf: "flex-end",
|
|
247
|
+
backgroundColor: "var(--anyclick-menu-accent, #0066cc)",
|
|
248
|
+
color: "#fff",
|
|
249
|
+
padding: "6px 10px",
|
|
250
|
+
borderRadius: "12px 12px 4px 12px",
|
|
251
|
+
fontSize: "13px",
|
|
252
|
+
maxWidth: "85%",
|
|
253
|
+
wordBreak: "break-word"
|
|
254
|
+
},
|
|
255
|
+
messageAssistant: {
|
|
256
|
+
alignSelf: "flex-start",
|
|
257
|
+
backgroundColor: "var(--anyclick-menu-hover, #f5f5f5)",
|
|
258
|
+
color: "var(--anyclick-menu-text, #333)",
|
|
259
|
+
padding: "8px 10px",
|
|
260
|
+
borderRadius: "12px 12px 12px 4px",
|
|
261
|
+
fontSize: "13px",
|
|
262
|
+
maxWidth: "100%",
|
|
263
|
+
wordBreak: "break-word",
|
|
264
|
+
lineHeight: 1.4
|
|
265
|
+
},
|
|
266
|
+
messageActions: {
|
|
267
|
+
display: "flex",
|
|
268
|
+
gap: "4px",
|
|
269
|
+
marginTop: "4px",
|
|
270
|
+
flexWrap: "wrap"
|
|
271
|
+
},
|
|
272
|
+
actionButton: {
|
|
273
|
+
display: "inline-flex",
|
|
274
|
+
alignItems: "center",
|
|
275
|
+
gap: "4px",
|
|
276
|
+
padding: "3px 8px",
|
|
277
|
+
fontSize: "11px",
|
|
278
|
+
fontWeight: 500,
|
|
279
|
+
border: "1px solid var(--anyclick-menu-border, #e5e5e5)",
|
|
280
|
+
borderRadius: "4px",
|
|
281
|
+
backgroundColor: "transparent",
|
|
282
|
+
color: "var(--anyclick-menu-text-muted, #666)",
|
|
283
|
+
cursor: "pointer",
|
|
284
|
+
transition: "all 0.15s ease"
|
|
285
|
+
},
|
|
286
|
+
streamingIndicator: {
|
|
287
|
+
display: "inline-block",
|
|
288
|
+
width: "4px",
|
|
289
|
+
height: "14px",
|
|
290
|
+
backgroundColor: "var(--anyclick-menu-accent, #0066cc)",
|
|
291
|
+
borderRadius: "1px",
|
|
292
|
+
animation: "blink 1s infinite"
|
|
293
|
+
},
|
|
294
|
+
// Suggestions - compact horizontal scroll
|
|
295
|
+
suggestionsContainer: {
|
|
296
|
+
display: "flex",
|
|
297
|
+
gap: "6px",
|
|
298
|
+
padding: "6px 8px",
|
|
299
|
+
overflowX: "auto",
|
|
300
|
+
overflowY: "hidden",
|
|
301
|
+
scrollbarWidth: "none",
|
|
302
|
+
msOverflowStyle: "none"
|
|
303
|
+
},
|
|
304
|
+
suggestionChip: {
|
|
305
|
+
display: "inline-flex",
|
|
306
|
+
alignItems: "center",
|
|
307
|
+
padding: "4px 10px",
|
|
308
|
+
fontSize: "11px",
|
|
309
|
+
border: "1px solid var(--anyclick-menu-border, #e5e5e5)",
|
|
310
|
+
borderRadius: "12px",
|
|
311
|
+
backgroundColor: "var(--anyclick-menu-hover, #f5f5f5)",
|
|
312
|
+
color: "var(--anyclick-menu-text, #333)",
|
|
313
|
+
cursor: "pointer",
|
|
314
|
+
transition: "all 0.15s ease",
|
|
315
|
+
whiteSpace: "nowrap",
|
|
316
|
+
flexShrink: 0
|
|
317
|
+
},
|
|
318
|
+
suggestionChipHover: {
|
|
319
|
+
backgroundColor: "var(--anyclick-menu-bg, #fff)",
|
|
320
|
+
borderColor: "var(--anyclick-menu-accent, #0066cc)"
|
|
321
|
+
},
|
|
322
|
+
// Context redaction - now in dropdown
|
|
323
|
+
contextContainer: {
|
|
324
|
+
display: "flex",
|
|
325
|
+
flexDirection: "column",
|
|
326
|
+
gap: "4px"
|
|
327
|
+
},
|
|
328
|
+
contextHeader: {
|
|
329
|
+
display: "flex",
|
|
330
|
+
alignItems: "center",
|
|
331
|
+
justifyContent: "space-between",
|
|
332
|
+
marginBottom: "4px"
|
|
333
|
+
},
|
|
334
|
+
contextTitle: {
|
|
335
|
+
fontSize: "10px",
|
|
336
|
+
fontWeight: 600,
|
|
337
|
+
textTransform: "uppercase",
|
|
338
|
+
letterSpacing: "0.5px",
|
|
339
|
+
color: "var(--anyclick-menu-text-muted, #666)"
|
|
340
|
+
},
|
|
341
|
+
contextToggle: {
|
|
342
|
+
fontSize: "10px",
|
|
343
|
+
color: "var(--anyclick-menu-accent, #0066cc)",
|
|
344
|
+
background: "none",
|
|
345
|
+
border: "none",
|
|
346
|
+
cursor: "pointer",
|
|
347
|
+
padding: 0
|
|
348
|
+
},
|
|
349
|
+
contextToggleSmall: {
|
|
350
|
+
fontSize: "9px",
|
|
351
|
+
fontWeight: 500,
|
|
352
|
+
color: "var(--anyclick-menu-text-muted, #666)",
|
|
353
|
+
background: "none",
|
|
354
|
+
border: "none",
|
|
355
|
+
cursor: "pointer",
|
|
356
|
+
padding: "2px 4px",
|
|
357
|
+
borderRadius: "3px",
|
|
358
|
+
transition: "all 0.15s ease"
|
|
359
|
+
},
|
|
360
|
+
contextChunks: {
|
|
361
|
+
display: "flex",
|
|
362
|
+
flexDirection: "column",
|
|
363
|
+
gap: "4px"
|
|
364
|
+
},
|
|
365
|
+
contextChunk: {
|
|
366
|
+
display: "flex",
|
|
367
|
+
alignItems: "center",
|
|
368
|
+
gap: "6px",
|
|
369
|
+
padding: "4px 6px",
|
|
370
|
+
borderRadius: "4px",
|
|
371
|
+
fontSize: "11px",
|
|
372
|
+
backgroundColor: "var(--anyclick-menu-hover, #f5f5f5)",
|
|
373
|
+
cursor: "pointer",
|
|
374
|
+
transition: "opacity 0.15s ease"
|
|
375
|
+
},
|
|
376
|
+
contextChunkCompact: {
|
|
377
|
+
display: "flex",
|
|
378
|
+
alignItems: "center",
|
|
379
|
+
gap: "6px",
|
|
380
|
+
padding: "2px 4px",
|
|
381
|
+
borderRadius: "3px",
|
|
382
|
+
fontSize: "10px",
|
|
383
|
+
cursor: "pointer",
|
|
384
|
+
transition: "opacity 0.15s ease"
|
|
385
|
+
},
|
|
386
|
+
contextChunkExcluded: {
|
|
387
|
+
opacity: 0.5,
|
|
388
|
+
textDecoration: "line-through"
|
|
389
|
+
},
|
|
390
|
+
contextCheckbox: {
|
|
391
|
+
width: "12px",
|
|
392
|
+
height: "12px",
|
|
393
|
+
accentColor: "var(--anyclick-menu-accent, #0066cc)"
|
|
394
|
+
},
|
|
395
|
+
contextLabel: {
|
|
396
|
+
flex: 1,
|
|
397
|
+
overflow: "hidden",
|
|
398
|
+
textOverflow: "ellipsis",
|
|
399
|
+
whiteSpace: "nowrap",
|
|
400
|
+
color: "var(--anyclick-menu-text, #333)"
|
|
401
|
+
},
|
|
402
|
+
contextSize: {
|
|
403
|
+
fontSize: "10px",
|
|
404
|
+
color: "var(--anyclick-menu-text-muted, #666)"
|
|
405
|
+
},
|
|
406
|
+
// Input area
|
|
407
|
+
inputContainer: {
|
|
408
|
+
display: "flex",
|
|
409
|
+
alignItems: "flex-end",
|
|
410
|
+
gap: "8px",
|
|
411
|
+
padding: "8px"
|
|
412
|
+
},
|
|
413
|
+
input: {
|
|
414
|
+
flex: 1,
|
|
415
|
+
padding: "8px 12px",
|
|
416
|
+
fontSize: "13px",
|
|
417
|
+
border: "1px solid var(--anyclick-menu-input-border, #ddd)",
|
|
418
|
+
borderRadius: "18px",
|
|
419
|
+
backgroundColor: "var(--anyclick-menu-input-bg, #fff)",
|
|
420
|
+
color: "var(--anyclick-menu-text, #333)",
|
|
421
|
+
outline: "none",
|
|
422
|
+
resize: "none",
|
|
423
|
+
fontFamily: "inherit",
|
|
424
|
+
lineHeight: 1.4,
|
|
425
|
+
maxHeight: "80px",
|
|
426
|
+
minHeight: "36px"
|
|
427
|
+
},
|
|
428
|
+
inputFocused: {
|
|
429
|
+
borderColor: "var(--anyclick-menu-accent, #0066cc)",
|
|
430
|
+
boxShadow: "0 0 0 2px rgba(0, 102, 204, 0.1)"
|
|
431
|
+
},
|
|
432
|
+
sendButton: {
|
|
433
|
+
display: "flex",
|
|
434
|
+
alignItems: "center",
|
|
435
|
+
justifyContent: "center",
|
|
436
|
+
width: "32px",
|
|
437
|
+
height: "32px",
|
|
438
|
+
border: "none",
|
|
439
|
+
borderRadius: "50%",
|
|
440
|
+
backgroundColor: "var(--anyclick-menu-accent, #0066cc)",
|
|
441
|
+
color: "#fff",
|
|
442
|
+
cursor: "pointer",
|
|
443
|
+
transition: "all 0.15s ease",
|
|
444
|
+
flexShrink: 0
|
|
445
|
+
},
|
|
446
|
+
sendButtonDisabled: {
|
|
447
|
+
backgroundColor: "var(--anyclick-menu-border, #e5e5e5)",
|
|
448
|
+
cursor: "not-allowed"
|
|
449
|
+
},
|
|
450
|
+
// Loading states
|
|
451
|
+
loadingDots: {
|
|
452
|
+
display: "flex",
|
|
453
|
+
gap: "4px",
|
|
454
|
+
padding: "8px"
|
|
455
|
+
},
|
|
456
|
+
loadingDot: {
|
|
457
|
+
width: "6px",
|
|
458
|
+
height: "6px",
|
|
459
|
+
borderRadius: "50%",
|
|
460
|
+
backgroundColor: "var(--anyclick-menu-text-muted, #666)",
|
|
461
|
+
animation: "bounce 1.4s infinite ease-in-out both"
|
|
462
|
+
},
|
|
463
|
+
// Error states
|
|
464
|
+
errorContainer: {
|
|
465
|
+
display: "flex",
|
|
466
|
+
flexDirection: "column",
|
|
467
|
+
alignItems: "center",
|
|
468
|
+
gap: "8px",
|
|
469
|
+
padding: "16px",
|
|
470
|
+
textAlign: "center"
|
|
471
|
+
},
|
|
472
|
+
errorIcon: {
|
|
473
|
+
color: "#ef4444"
|
|
474
|
+
},
|
|
475
|
+
errorText: {
|
|
476
|
+
fontSize: "12px",
|
|
477
|
+
color: "#ef4444",
|
|
478
|
+
maxWidth: "200px"
|
|
479
|
+
},
|
|
480
|
+
errorRetry: {
|
|
481
|
+
display: "inline-flex",
|
|
482
|
+
alignItems: "center",
|
|
483
|
+
gap: "4px",
|
|
484
|
+
padding: "4px 10px",
|
|
485
|
+
fontSize: "11px",
|
|
486
|
+
fontWeight: 500,
|
|
487
|
+
border: "1px solid #ef4444",
|
|
488
|
+
borderRadius: "4px",
|
|
489
|
+
backgroundColor: "transparent",
|
|
490
|
+
color: "#ef4444",
|
|
491
|
+
cursor: "pointer",
|
|
492
|
+
transition: "all 0.15s ease"
|
|
493
|
+
},
|
|
494
|
+
// Truncation indicator
|
|
495
|
+
truncated: {
|
|
496
|
+
fontSize: "10px",
|
|
497
|
+
color: "var(--anyclick-menu-text-muted, #666)",
|
|
498
|
+
fontStyle: "italic",
|
|
499
|
+
marginTop: "4px"
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
var quickChatKeyframes = `
|
|
503
|
+
@keyframes blink {
|
|
504
|
+
0%, 50% { opacity: 1; }
|
|
505
|
+
51%, 100% { opacity: 0; }
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
@keyframes bounce {
|
|
509
|
+
0%, 80%, 100% { transform: scale(0); }
|
|
510
|
+
40% { transform: scale(1); }
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
@keyframes slideIn {
|
|
514
|
+
from {
|
|
515
|
+
opacity: 0;
|
|
516
|
+
transform: translateY(-8px);
|
|
517
|
+
}
|
|
518
|
+
to {
|
|
519
|
+
opacity: 1;
|
|
520
|
+
transform: translateY(0);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
@keyframes slideInFromRight {
|
|
525
|
+
from {
|
|
526
|
+
transform: translateX(100%);
|
|
527
|
+
}
|
|
528
|
+
to {
|
|
529
|
+
transform: translateX(0);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
@keyframes slideOutToRight {
|
|
534
|
+
from {
|
|
535
|
+
transform: translateX(0);
|
|
536
|
+
}
|
|
537
|
+
to {
|
|
538
|
+
transform: translateX(100%);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
@keyframes fadeIn {
|
|
543
|
+
from { opacity: 0; }
|
|
544
|
+
to { opacity: 1; }
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
@keyframes spin {
|
|
548
|
+
from { transform: rotate(0deg); }
|
|
549
|
+
to { transform: rotate(360deg); }
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
@keyframes pulse {
|
|
553
|
+
0%, 100% { opacity: 1; }
|
|
554
|
+
50% { opacity: 0.5; }
|
|
555
|
+
}
|
|
556
|
+
`;
|
|
557
|
+
|
|
558
|
+
// src/QuickChat/useQuickChat.ts
|
|
559
|
+
var import_react = require("react");
|
|
560
|
+
var import_anyclick_core = require("@ewjdev/anyclick-core");
|
|
561
|
+
|
|
562
|
+
// src/QuickChat/types.ts
|
|
563
|
+
var DEFAULT_T3CHAT_CONFIG = {
|
|
564
|
+
enabled: true,
|
|
565
|
+
baseUrl: "https://t3.chat",
|
|
566
|
+
label: "Ask t3.chat"
|
|
567
|
+
};
|
|
568
|
+
var DEFAULT_QUICK_CHAT_CONFIG = {
|
|
569
|
+
endpoint: "/api/anyclick/chat",
|
|
570
|
+
model: "gpt-5-mini",
|
|
571
|
+
prePassModel: "gpt-5-nano",
|
|
572
|
+
maxResponseLength: 500,
|
|
573
|
+
showRedactionUI: true,
|
|
574
|
+
showSuggestions: true,
|
|
575
|
+
systemPrompt: "You are a helpful assistant that provides quick, concise answers about web elements and UI. Keep responses brief and actionable.",
|
|
576
|
+
placeholder: "Ask about this element...",
|
|
577
|
+
title: "Quick Ask",
|
|
578
|
+
t3chat: DEFAULT_T3CHAT_CONFIG
|
|
579
|
+
};
|
|
580
|
+
|
|
581
|
+
// src/QuickChat/useQuickChat.ts
|
|
582
|
+
var PINNED_STATE_KEY = "anyclick-quick-chat-pinned";
|
|
583
|
+
var CHAT_HISTORY_KEY = "anyclick-quick-chat-history";
|
|
584
|
+
function generateId() {
|
|
585
|
+
return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
586
|
+
}
|
|
587
|
+
function getPinnedState() {
|
|
588
|
+
if (typeof window === "undefined") return false;
|
|
589
|
+
try {
|
|
590
|
+
return sessionStorage.getItem(PINNED_STATE_KEY) === "true";
|
|
591
|
+
} catch {
|
|
592
|
+
return false;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
function getChatHistory() {
|
|
596
|
+
if (typeof window === "undefined") return [];
|
|
597
|
+
try {
|
|
598
|
+
const stored = sessionStorage.getItem(CHAT_HISTORY_KEY);
|
|
599
|
+
if (stored) {
|
|
600
|
+
const parsed = JSON.parse(stored);
|
|
601
|
+
return parsed.map((msg) => ({
|
|
602
|
+
...msg,
|
|
603
|
+
isStreaming: false,
|
|
604
|
+
actions: void 0
|
|
605
|
+
}));
|
|
606
|
+
}
|
|
607
|
+
} catch {
|
|
608
|
+
}
|
|
609
|
+
return [];
|
|
610
|
+
}
|
|
611
|
+
function saveChatHistory(messages) {
|
|
612
|
+
if (typeof window === "undefined") return;
|
|
613
|
+
try {
|
|
614
|
+
const toStore = messages.slice(-10).map((msg) => ({
|
|
615
|
+
id: msg.id,
|
|
616
|
+
role: msg.role,
|
|
617
|
+
content: msg.content,
|
|
618
|
+
timestamp: msg.timestamp
|
|
619
|
+
}));
|
|
620
|
+
sessionStorage.setItem(CHAT_HISTORY_KEY, JSON.stringify(toStore));
|
|
621
|
+
} catch {
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
function clearChatHistory() {
|
|
625
|
+
if (typeof window === "undefined") return;
|
|
626
|
+
try {
|
|
627
|
+
sessionStorage.removeItem(CHAT_HISTORY_KEY);
|
|
628
|
+
} catch {
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
function extractContextChunks(targetElement, containerElement) {
|
|
632
|
+
const chunks = [];
|
|
633
|
+
if (!targetElement) return chunks;
|
|
634
|
+
try {
|
|
635
|
+
const info = (0, import_anyclick_core.getElementInspectInfo)(targetElement);
|
|
636
|
+
const tagContent = `<${info.tagName.toLowerCase()}${info.id ? ` id="${info.id}"` : ""}${info.classNames.length > 0 ? ` class="${info.classNames.join(" ")}"` : ""}>`;
|
|
637
|
+
chunks.push({
|
|
638
|
+
id: "element-tag",
|
|
639
|
+
label: "Element Tag",
|
|
640
|
+
content: tagContent,
|
|
641
|
+
type: "element",
|
|
642
|
+
included: true,
|
|
643
|
+
size: tagContent.length
|
|
644
|
+
});
|
|
645
|
+
if (info.innerText && info.innerText.length > 0) {
|
|
646
|
+
const textContent = info.innerText.slice(0, 200);
|
|
647
|
+
chunks.push({
|
|
648
|
+
id: "element-text",
|
|
649
|
+
label: "Text Content",
|
|
650
|
+
content: textContent,
|
|
651
|
+
type: "text",
|
|
652
|
+
included: true,
|
|
653
|
+
size: textContent.length
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
if (info.computedStyles) {
|
|
657
|
+
const styleEntries = [];
|
|
658
|
+
for (const [category, styles] of Object.entries(info.computedStyles)) {
|
|
659
|
+
if (styles && typeof styles === "object") {
|
|
660
|
+
const entries = Object.entries(styles).slice(0, 2);
|
|
661
|
+
for (const [k, v] of entries) {
|
|
662
|
+
if (v) styleEntries.push(`${k}: ${v}`);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
if (styleEntries.length >= 8) break;
|
|
666
|
+
}
|
|
667
|
+
const stylesContent = styleEntries.join("; ");
|
|
668
|
+
if (stylesContent) {
|
|
669
|
+
chunks.push({
|
|
670
|
+
id: "element-styles",
|
|
671
|
+
label: "Key Styles",
|
|
672
|
+
content: stylesContent,
|
|
673
|
+
type: "element",
|
|
674
|
+
included: true,
|
|
675
|
+
size: stylesContent.length
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
if (info.accessibility) {
|
|
680
|
+
const a11yContent = [
|
|
681
|
+
info.accessibility.role && `role="${info.accessibility.role}"`,
|
|
682
|
+
info.accessibility.accessibleName && `aria-label="${info.accessibility.accessibleName}"`
|
|
683
|
+
].filter(Boolean).join(", ");
|
|
684
|
+
if (a11yContent) {
|
|
685
|
+
chunks.push({
|
|
686
|
+
id: "element-a11y",
|
|
687
|
+
label: "Accessibility",
|
|
688
|
+
content: a11yContent,
|
|
689
|
+
type: "element",
|
|
690
|
+
included: true,
|
|
691
|
+
size: a11yContent.length
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
if (info.boxModel) {
|
|
696
|
+
const boxContent = `${Math.round(info.boxModel.content.width)}x${Math.round(info.boxModel.content.height)}px`;
|
|
697
|
+
chunks.push({
|
|
698
|
+
id: "element-dimensions",
|
|
699
|
+
label: "Dimensions",
|
|
700
|
+
content: boxContent,
|
|
701
|
+
type: "element",
|
|
702
|
+
included: true,
|
|
703
|
+
size: boxContent.length
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
} catch (error) {
|
|
707
|
+
console.error("Failed to extract context:", error);
|
|
708
|
+
}
|
|
709
|
+
return chunks;
|
|
710
|
+
}
|
|
711
|
+
function buildContextString(chunks) {
|
|
712
|
+
const includedChunks = chunks.filter((c) => c.included);
|
|
713
|
+
if (includedChunks.length === 0) return "";
|
|
714
|
+
return includedChunks.map((c) => `[${c.label}]: ${c.content}`).join("\n");
|
|
715
|
+
}
|
|
716
|
+
function useQuickChat(targetElement, containerElement, config = {}) {
|
|
717
|
+
const mergedConfig = { ...DEFAULT_QUICK_CHAT_CONFIG, ...config };
|
|
718
|
+
const abortControllerRef = (0, import_react.useRef)(null);
|
|
719
|
+
const initializedRef = (0, import_react.useRef)(false);
|
|
720
|
+
const [state, setState] = (0, import_react.useState)({
|
|
721
|
+
input: "",
|
|
722
|
+
messages: [],
|
|
723
|
+
isLoadingSuggestions: false,
|
|
724
|
+
isSending: false,
|
|
725
|
+
isStreaming: false,
|
|
726
|
+
suggestedPrompts: [],
|
|
727
|
+
contextChunks: [],
|
|
728
|
+
error: null
|
|
729
|
+
});
|
|
730
|
+
(0, import_react.useEffect)(() => {
|
|
731
|
+
if (initializedRef.current) return;
|
|
732
|
+
initializedRef.current = true;
|
|
733
|
+
const isPinned = getPinnedState();
|
|
734
|
+
if (isPinned) {
|
|
735
|
+
const history = getChatHistory();
|
|
736
|
+
if (history.length > 0) {
|
|
737
|
+
setState((prev) => ({ ...prev, messages: history }));
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
}, []);
|
|
741
|
+
(0, import_react.useEffect)(() => {
|
|
742
|
+
if (targetElement) {
|
|
743
|
+
const chunks = extractContextChunks(targetElement, containerElement);
|
|
744
|
+
setState((prev) => ({ ...prev, contextChunks: chunks }));
|
|
745
|
+
}
|
|
746
|
+
}, [targetElement, containerElement]);
|
|
747
|
+
(0, import_react.useEffect)(() => {
|
|
748
|
+
if (!mergedConfig.showSuggestions || state.contextChunks.length === 0 || state.suggestedPrompts.length > 0) {
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
const fetchSuggestions = async () => {
|
|
752
|
+
setState((prev) => ({ ...prev, isLoadingSuggestions: true }));
|
|
753
|
+
try {
|
|
754
|
+
const contextString = buildContextString(state.contextChunks);
|
|
755
|
+
const response = await fetch(mergedConfig.endpoint, {
|
|
756
|
+
method: "POST",
|
|
757
|
+
headers: { "Content-Type": "application/json" },
|
|
758
|
+
body: JSON.stringify({
|
|
759
|
+
action: "suggest",
|
|
760
|
+
context: contextString,
|
|
761
|
+
model: mergedConfig.prePassModel
|
|
762
|
+
})
|
|
763
|
+
});
|
|
764
|
+
if (response.ok) {
|
|
765
|
+
const data = await response.json();
|
|
766
|
+
if (data.suggestions && Array.isArray(data.suggestions)) {
|
|
767
|
+
setState((prev) => ({
|
|
768
|
+
...prev,
|
|
769
|
+
suggestedPrompts: data.suggestions.map(
|
|
770
|
+
(text, i) => ({
|
|
771
|
+
id: `suggestion-${i}`,
|
|
772
|
+
text
|
|
773
|
+
})
|
|
774
|
+
),
|
|
775
|
+
isLoadingSuggestions: false
|
|
776
|
+
}));
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
} catch (error) {
|
|
781
|
+
console.error("Failed to fetch suggestions:", error);
|
|
782
|
+
}
|
|
783
|
+
setState((prev) => ({
|
|
784
|
+
...prev,
|
|
785
|
+
suggestedPrompts: [
|
|
786
|
+
{ id: "s1", text: "What is this element?" },
|
|
787
|
+
{ id: "s2", text: "How can I style this?" },
|
|
788
|
+
{ id: "s3", text: "Is this accessible?" }
|
|
789
|
+
],
|
|
790
|
+
isLoadingSuggestions: false
|
|
791
|
+
}));
|
|
792
|
+
};
|
|
793
|
+
fetchSuggestions();
|
|
794
|
+
}, [
|
|
795
|
+
state.contextChunks,
|
|
796
|
+
state.suggestedPrompts.length,
|
|
797
|
+
mergedConfig.showSuggestions,
|
|
798
|
+
mergedConfig.endpoint,
|
|
799
|
+
mergedConfig.prePassModel
|
|
800
|
+
]);
|
|
801
|
+
const setInput = (0, import_react.useCallback)((value) => {
|
|
802
|
+
setState((prev) => ({ ...prev, input: value }));
|
|
803
|
+
}, []);
|
|
804
|
+
const toggleChunk = (0, import_react.useCallback)((chunkId) => {
|
|
805
|
+
setState((prev) => ({
|
|
806
|
+
...prev,
|
|
807
|
+
contextChunks: prev.contextChunks.map(
|
|
808
|
+
(chunk) => chunk.id === chunkId ? { ...chunk, included: !chunk.included } : chunk
|
|
809
|
+
)
|
|
810
|
+
}));
|
|
811
|
+
}, []);
|
|
812
|
+
const toggleAllChunks = (0, import_react.useCallback)((included) => {
|
|
813
|
+
setState((prev) => ({
|
|
814
|
+
...prev,
|
|
815
|
+
contextChunks: prev.contextChunks.map((chunk) => ({
|
|
816
|
+
...chunk,
|
|
817
|
+
included
|
|
818
|
+
}))
|
|
819
|
+
}));
|
|
820
|
+
}, []);
|
|
821
|
+
const selectSuggestion = (0, import_react.useCallback)((prompt) => {
|
|
822
|
+
setState((prev) => ({ ...prev, input: prompt.text }));
|
|
823
|
+
}, []);
|
|
824
|
+
const sendMessage = (0, import_react.useCallback)(
|
|
825
|
+
async (messageText) => {
|
|
826
|
+
const text = (messageText || state.input).trim();
|
|
827
|
+
if (!text) return;
|
|
828
|
+
if (abortControllerRef.current) {
|
|
829
|
+
abortControllerRef.current.abort();
|
|
830
|
+
}
|
|
831
|
+
abortControllerRef.current = new AbortController();
|
|
832
|
+
const userMessage = {
|
|
833
|
+
id: generateId(),
|
|
834
|
+
role: "user",
|
|
835
|
+
content: text,
|
|
836
|
+
timestamp: Date.now()
|
|
837
|
+
};
|
|
838
|
+
const assistantMessageId = generateId();
|
|
839
|
+
const assistantMessage = {
|
|
840
|
+
id: assistantMessageId,
|
|
841
|
+
role: "assistant",
|
|
842
|
+
content: "",
|
|
843
|
+
timestamp: Date.now(),
|
|
844
|
+
isStreaming: true
|
|
845
|
+
};
|
|
846
|
+
setState((prev) => ({
|
|
847
|
+
...prev,
|
|
848
|
+
input: "",
|
|
849
|
+
messages: [...prev.messages, userMessage, assistantMessage],
|
|
850
|
+
isSending: true,
|
|
851
|
+
isStreaming: true,
|
|
852
|
+
error: null
|
|
853
|
+
}));
|
|
854
|
+
try {
|
|
855
|
+
const contextString = buildContextString(state.contextChunks);
|
|
856
|
+
const response = await fetch(mergedConfig.endpoint, {
|
|
857
|
+
method: "POST",
|
|
858
|
+
headers: { "Content-Type": "application/json" },
|
|
859
|
+
body: JSON.stringify({
|
|
860
|
+
action: "chat",
|
|
861
|
+
message: text,
|
|
862
|
+
context: contextString,
|
|
863
|
+
model: mergedConfig.model,
|
|
864
|
+
systemPrompt: mergedConfig.systemPrompt,
|
|
865
|
+
maxLength: mergedConfig.maxResponseLength
|
|
866
|
+
}),
|
|
867
|
+
signal: abortControllerRef.current.signal
|
|
868
|
+
});
|
|
869
|
+
if (!response.ok) {
|
|
870
|
+
throw new Error(`Request failed: ${response.status}`);
|
|
871
|
+
}
|
|
872
|
+
const reader = response.body?.getReader();
|
|
873
|
+
if (!reader) {
|
|
874
|
+
throw new Error("No response body");
|
|
875
|
+
}
|
|
876
|
+
const decoder = new TextDecoder();
|
|
877
|
+
let fullContent = "";
|
|
878
|
+
while (true) {
|
|
879
|
+
const { done, value } = await reader.read();
|
|
880
|
+
if (done) break;
|
|
881
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
882
|
+
fullContent += chunk;
|
|
883
|
+
if (fullContent.length > mergedConfig.maxResponseLength) {
|
|
884
|
+
fullContent = fullContent.slice(0, mergedConfig.maxResponseLength) + "...";
|
|
885
|
+
}
|
|
886
|
+
setState((prev) => ({
|
|
887
|
+
...prev,
|
|
888
|
+
messages: prev.messages.map(
|
|
889
|
+
(msg) => msg.id === assistantMessageId ? { ...msg, content: fullContent } : msg
|
|
890
|
+
)
|
|
891
|
+
}));
|
|
892
|
+
}
|
|
893
|
+
setState((prev) => ({
|
|
894
|
+
...prev,
|
|
895
|
+
messages: prev.messages.map(
|
|
896
|
+
(msg) => msg.id === assistantMessageId ? {
|
|
897
|
+
...msg,
|
|
898
|
+
content: fullContent,
|
|
899
|
+
isStreaming: false,
|
|
900
|
+
actions: [
|
|
901
|
+
{
|
|
902
|
+
id: "copy",
|
|
903
|
+
label: "Copy",
|
|
904
|
+
onClick: () => {
|
|
905
|
+
navigator.clipboard.writeText(fullContent);
|
|
906
|
+
}
|
|
907
|
+
},
|
|
908
|
+
{
|
|
909
|
+
id: "research",
|
|
910
|
+
label: "Research more",
|
|
911
|
+
onClick: () => {
|
|
912
|
+
setState((p) => ({
|
|
913
|
+
...p,
|
|
914
|
+
input: `Tell me more about: ${text}`
|
|
915
|
+
}));
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
]
|
|
919
|
+
} : msg
|
|
920
|
+
),
|
|
921
|
+
isSending: false,
|
|
922
|
+
isStreaming: false
|
|
923
|
+
}));
|
|
924
|
+
} catch (error) {
|
|
925
|
+
if (error.name === "AbortError") {
|
|
926
|
+
return;
|
|
927
|
+
}
|
|
928
|
+
console.error("Chat error:", error);
|
|
929
|
+
setState((prev) => ({
|
|
930
|
+
...prev,
|
|
931
|
+
messages: prev.messages.map(
|
|
932
|
+
(msg) => msg.id === assistantMessageId ? {
|
|
933
|
+
...msg,
|
|
934
|
+
content: "Sorry, I couldn't process your request. Please try again.",
|
|
935
|
+
isStreaming: false
|
|
936
|
+
} : msg
|
|
937
|
+
),
|
|
938
|
+
isSending: false,
|
|
939
|
+
isStreaming: false,
|
|
940
|
+
error: error.message
|
|
941
|
+
}));
|
|
942
|
+
}
|
|
943
|
+
},
|
|
944
|
+
[state.input, state.contextChunks, mergedConfig]
|
|
945
|
+
);
|
|
946
|
+
const clearMessages = (0, import_react.useCallback)(() => {
|
|
947
|
+
if (abortControllerRef.current) {
|
|
948
|
+
abortControllerRef.current.abort();
|
|
949
|
+
}
|
|
950
|
+
clearChatHistory();
|
|
951
|
+
setState((prev) => ({
|
|
952
|
+
...prev,
|
|
953
|
+
messages: [],
|
|
954
|
+
error: null
|
|
955
|
+
}));
|
|
956
|
+
}, []);
|
|
957
|
+
(0, import_react.useEffect)(() => {
|
|
958
|
+
if (state.messages.length > 0 && getPinnedState()) {
|
|
959
|
+
const completedMessages = state.messages.filter(
|
|
960
|
+
(msg) => !msg.isStreaming
|
|
961
|
+
);
|
|
962
|
+
if (completedMessages.length > 0) {
|
|
963
|
+
saveChatHistory(completedMessages);
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
}, [state.messages]);
|
|
967
|
+
(0, import_react.useEffect)(() => {
|
|
968
|
+
return () => {
|
|
969
|
+
if (abortControllerRef.current) {
|
|
970
|
+
abortControllerRef.current.abort();
|
|
971
|
+
}
|
|
972
|
+
};
|
|
973
|
+
}, []);
|
|
974
|
+
return {
|
|
975
|
+
...state,
|
|
976
|
+
config: mergedConfig,
|
|
977
|
+
setInput,
|
|
978
|
+
toggleChunk,
|
|
979
|
+
toggleAllChunks,
|
|
980
|
+
selectSuggestion,
|
|
981
|
+
sendMessage,
|
|
982
|
+
clearMessages
|
|
983
|
+
};
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
// src/QuickChat/QuickChat.tsx
|
|
987
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
988
|
+
var PINNED_STATE_KEY2 = "anyclick-quick-chat-pinned";
|
|
989
|
+
function getStoredPinnedState() {
|
|
990
|
+
if (typeof window === "undefined") return false;
|
|
991
|
+
try {
|
|
992
|
+
return sessionStorage.getItem(PINNED_STATE_KEY2) === "true";
|
|
993
|
+
} catch {
|
|
994
|
+
return false;
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
function setStoredPinnedState(pinned) {
|
|
998
|
+
if (typeof window === "undefined") return;
|
|
999
|
+
try {
|
|
1000
|
+
if (pinned) {
|
|
1001
|
+
sessionStorage.setItem(PINNED_STATE_KEY2, "true");
|
|
1002
|
+
} else {
|
|
1003
|
+
sessionStorage.removeItem(PINNED_STATE_KEY2);
|
|
1004
|
+
}
|
|
1005
|
+
} catch {
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
var stylesInjected = false;
|
|
1009
|
+
function injectStyles() {
|
|
1010
|
+
if (stylesInjected || typeof document === "undefined") return;
|
|
1011
|
+
const style = document.createElement("style");
|
|
1012
|
+
style.textContent = quickChatKeyframes;
|
|
1013
|
+
document.head.appendChild(style);
|
|
1014
|
+
stylesInjected = true;
|
|
1015
|
+
}
|
|
1016
|
+
var LoadingDots = import_react2.default.memo(function LoadingDots2() {
|
|
1017
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: quickChatStyles.loadingDots, children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1018
|
+
"div",
|
|
1019
|
+
{
|
|
1020
|
+
style: {
|
|
1021
|
+
...quickChatStyles.loadingDot,
|
|
1022
|
+
animationDelay: `${i * 0.16}s`
|
|
1023
|
+
}
|
|
1024
|
+
},
|
|
1025
|
+
i
|
|
1026
|
+
)) });
|
|
1027
|
+
});
|
|
1028
|
+
function QuickChat({
|
|
1029
|
+
visible,
|
|
1030
|
+
targetElement,
|
|
1031
|
+
containerElement,
|
|
1032
|
+
onClose,
|
|
1033
|
+
onPin,
|
|
1034
|
+
isPinned: isPinnedProp = false,
|
|
1035
|
+
config,
|
|
1036
|
+
style,
|
|
1037
|
+
className,
|
|
1038
|
+
initialInput,
|
|
1039
|
+
onInitialInputConsumed
|
|
1040
|
+
}) {
|
|
1041
|
+
const inputRef = (0, import_react2.useRef)(null);
|
|
1042
|
+
const messagesEndRef = (0, import_react2.useRef)(null);
|
|
1043
|
+
const [inputFocused, setInputFocused] = (0, import_react2.useState)(false);
|
|
1044
|
+
const [showContext, setShowContext] = (0, import_react2.useState)(false);
|
|
1045
|
+
const [hoveredSuggestion, setHoveredSuggestion] = (0, import_react2.useState)(
|
|
1046
|
+
null
|
|
1047
|
+
);
|
|
1048
|
+
const [localPinned, setLocalPinned] = (0, import_react2.useState)(() => getStoredPinnedState());
|
|
1049
|
+
const isPinned = isPinnedProp || localPinned;
|
|
1050
|
+
const handlePinToggle = (0, import_react2.useCallback)(() => {
|
|
1051
|
+
const newPinned = !isPinned;
|
|
1052
|
+
setLocalPinned(newPinned);
|
|
1053
|
+
setStoredPinnedState(newPinned);
|
|
1054
|
+
onPin?.(newPinned);
|
|
1055
|
+
}, [isPinned, onPin]);
|
|
1056
|
+
const handleClose = (0, import_react2.useCallback)(() => {
|
|
1057
|
+
if (isPinned) {
|
|
1058
|
+
setLocalPinned(false);
|
|
1059
|
+
setStoredPinnedState(false);
|
|
1060
|
+
onPin?.(false);
|
|
1061
|
+
}
|
|
1062
|
+
onClose();
|
|
1063
|
+
}, [isPinned, onPin, onClose]);
|
|
1064
|
+
const {
|
|
1065
|
+
input,
|
|
1066
|
+
messages,
|
|
1067
|
+
isLoadingSuggestions,
|
|
1068
|
+
isSending,
|
|
1069
|
+
isStreaming,
|
|
1070
|
+
suggestedPrompts,
|
|
1071
|
+
contextChunks,
|
|
1072
|
+
error,
|
|
1073
|
+
setInput,
|
|
1074
|
+
toggleChunk,
|
|
1075
|
+
toggleAllChunks,
|
|
1076
|
+
selectSuggestion,
|
|
1077
|
+
sendMessage,
|
|
1078
|
+
clearMessages,
|
|
1079
|
+
config: mergedConfig
|
|
1080
|
+
} = useQuickChat(targetElement, containerElement, config);
|
|
1081
|
+
(0, import_react2.useEffect)(() => {
|
|
1082
|
+
injectStyles();
|
|
1083
|
+
}, []);
|
|
1084
|
+
(0, import_react2.useEffect)(() => {
|
|
1085
|
+
if (visible && inputRef.current) {
|
|
1086
|
+
const timer = setTimeout(() => {
|
|
1087
|
+
inputRef.current?.focus();
|
|
1088
|
+
}, 100);
|
|
1089
|
+
return () => clearTimeout(timer);
|
|
1090
|
+
}
|
|
1091
|
+
}, [visible]);
|
|
1092
|
+
(0, import_react2.useEffect)(() => {
|
|
1093
|
+
if (initialInput && visible) {
|
|
1094
|
+
setInput(initialInput);
|
|
1095
|
+
onInitialInputConsumed?.();
|
|
1096
|
+
if (inputRef.current) {
|
|
1097
|
+
inputRef.current.focus();
|
|
1098
|
+
inputRef.current.setSelectionRange(
|
|
1099
|
+
initialInput.length,
|
|
1100
|
+
initialInput.length
|
|
1101
|
+
);
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
}, [initialInput, visible, setInput, onInitialInputConsumed]);
|
|
1105
|
+
(0, import_react2.useEffect)(() => {
|
|
1106
|
+
if (messagesEndRef.current) {
|
|
1107
|
+
messagesEndRef.current.scrollIntoView({ behavior: "smooth" });
|
|
1108
|
+
}
|
|
1109
|
+
}, [messages]);
|
|
1110
|
+
const handleInputChange = (0, import_react2.useCallback)(
|
|
1111
|
+
(e) => {
|
|
1112
|
+
setInput(e.target.value);
|
|
1113
|
+
const target = e.target;
|
|
1114
|
+
target.style.height = "auto";
|
|
1115
|
+
target.style.height = `${Math.min(target.scrollHeight, 80)}px`;
|
|
1116
|
+
},
|
|
1117
|
+
[setInput]
|
|
1118
|
+
);
|
|
1119
|
+
const handleKeyDown = (0, import_react2.useCallback)(
|
|
1120
|
+
(e) => {
|
|
1121
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
1122
|
+
e.preventDefault();
|
|
1123
|
+
sendMessage();
|
|
1124
|
+
} else if (e.key === "Escape") {
|
|
1125
|
+
onClose();
|
|
1126
|
+
}
|
|
1127
|
+
},
|
|
1128
|
+
[sendMessage, onClose]
|
|
1129
|
+
);
|
|
1130
|
+
const handleSend = (0, import_react2.useCallback)(() => {
|
|
1131
|
+
sendMessage();
|
|
1132
|
+
}, [sendMessage]);
|
|
1133
|
+
const handleSendToT3Chat = (0, import_react2.useCallback)(() => {
|
|
1134
|
+
if (typeof window === "undefined") return;
|
|
1135
|
+
const query = input.trim();
|
|
1136
|
+
const baseUrl = mergedConfig.t3chat?.baseUrl ?? "https://t3.chat";
|
|
1137
|
+
const url = query ? `${baseUrl}/?q=${encodeURIComponent(query)}` : baseUrl;
|
|
1138
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
1139
|
+
}, [input, mergedConfig.t3chat?.baseUrl]);
|
|
1140
|
+
const handleCopy = (0, import_react2.useCallback)((text) => {
|
|
1141
|
+
navigator.clipboard.writeText(text);
|
|
1142
|
+
}, []);
|
|
1143
|
+
const includedCount = (0, import_react2.useMemo)(
|
|
1144
|
+
() => contextChunks.filter((c) => c.included).length,
|
|
1145
|
+
[contextChunks]
|
|
1146
|
+
);
|
|
1147
|
+
if (!visible) return null;
|
|
1148
|
+
const containerStyles = isPinned ? {
|
|
1149
|
+
...quickChatStyles.pinnedContainer,
|
|
1150
|
+
animation: "slideInFromRight 0.25s ease-out",
|
|
1151
|
+
...style
|
|
1152
|
+
} : {
|
|
1153
|
+
...quickChatStyles.container,
|
|
1154
|
+
animation: "fadeIn 0.15s ease-out",
|
|
1155
|
+
...style
|
|
1156
|
+
};
|
|
1157
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className, style: containerStyles, children: [
|
|
1158
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1159
|
+
"div",
|
|
1160
|
+
{
|
|
1161
|
+
style: {
|
|
1162
|
+
...quickChatStyles.header,
|
|
1163
|
+
padding: isPinned ? "12px 12px 8px 12px" : "6px 8px"
|
|
1164
|
+
},
|
|
1165
|
+
children: [
|
|
1166
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
|
|
1167
|
+
!isPinned && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1168
|
+
"button",
|
|
1169
|
+
{
|
|
1170
|
+
type: "button",
|
|
1171
|
+
onClick: onClose,
|
|
1172
|
+
style: {
|
|
1173
|
+
...quickChatStyles.iconButton,
|
|
1174
|
+
marginLeft: "-4px"
|
|
1175
|
+
},
|
|
1176
|
+
title: "Back to menu",
|
|
1177
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ChevronLeft, { size: 16 })
|
|
1178
|
+
}
|
|
1179
|
+
),
|
|
1180
|
+
mergedConfig.showRedactionUI && contextChunks.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1181
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1182
|
+
"button",
|
|
1183
|
+
{
|
|
1184
|
+
type: "button",
|
|
1185
|
+
onClick: () => setShowContext(!showContext),
|
|
1186
|
+
style: {
|
|
1187
|
+
...quickChatStyles.contextBadge,
|
|
1188
|
+
...showContext ? quickChatStyles.contextBadgeActive : {}
|
|
1189
|
+
},
|
|
1190
|
+
title: "Edit context",
|
|
1191
|
+
children: [
|
|
1192
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
1193
|
+
includedCount,
|
|
1194
|
+
"/",
|
|
1195
|
+
contextChunks.length
|
|
1196
|
+
] }),
|
|
1197
|
+
showContext ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ChevronUp, { size: 10 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ChevronDown, { size: 10 })
|
|
1198
|
+
]
|
|
1199
|
+
}
|
|
1200
|
+
),
|
|
1201
|
+
showContext && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: "2px" }, children: [
|
|
1202
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1203
|
+
"button",
|
|
1204
|
+
{
|
|
1205
|
+
type: "button",
|
|
1206
|
+
onClick: () => toggleAllChunks(true),
|
|
1207
|
+
style: quickChatStyles.contextToggleSmall,
|
|
1208
|
+
title: "Include all",
|
|
1209
|
+
children: "All"
|
|
1210
|
+
}
|
|
1211
|
+
),
|
|
1212
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1213
|
+
"button",
|
|
1214
|
+
{
|
|
1215
|
+
type: "button",
|
|
1216
|
+
onClick: () => toggleAllChunks(false),
|
|
1217
|
+
style: quickChatStyles.contextToggleSmall,
|
|
1218
|
+
title: "Exclude all",
|
|
1219
|
+
children: "None"
|
|
1220
|
+
}
|
|
1221
|
+
)
|
|
1222
|
+
] })
|
|
1223
|
+
] })
|
|
1224
|
+
] }),
|
|
1225
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: quickChatStyles.headerActions, children: [
|
|
1226
|
+
messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1227
|
+
"button",
|
|
1228
|
+
{
|
|
1229
|
+
type: "button",
|
|
1230
|
+
onClick: clearMessages,
|
|
1231
|
+
style: quickChatStyles.iconButton,
|
|
1232
|
+
title: "Clear chat",
|
|
1233
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.RefreshCw, { size: 14 })
|
|
1234
|
+
}
|
|
1235
|
+
),
|
|
1236
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1237
|
+
"button",
|
|
1238
|
+
{
|
|
1239
|
+
type: "button",
|
|
1240
|
+
onClick: handlePinToggle,
|
|
1241
|
+
style: {
|
|
1242
|
+
...quickChatStyles.iconButton,
|
|
1243
|
+
...isPinned ? quickChatStyles.iconButtonActive : {}
|
|
1244
|
+
},
|
|
1245
|
+
title: isPinned ? "Unpin (closes with menu)" : "Pin (stays open)",
|
|
1246
|
+
children: isPinned ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.PinOff, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Pin, { size: 14 })
|
|
1247
|
+
}
|
|
1248
|
+
),
|
|
1249
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1250
|
+
"button",
|
|
1251
|
+
{
|
|
1252
|
+
type: "button",
|
|
1253
|
+
onClick: handleClose,
|
|
1254
|
+
style: quickChatStyles.iconButton,
|
|
1255
|
+
title: "Close",
|
|
1256
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.X, { size: 14 })
|
|
1257
|
+
}
|
|
1258
|
+
)
|
|
1259
|
+
] })
|
|
1260
|
+
]
|
|
1261
|
+
}
|
|
1262
|
+
),
|
|
1263
|
+
showContext && contextChunks.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: quickChatStyles.contextDropdown, children: contextChunks.map((chunk) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1264
|
+
"label",
|
|
1265
|
+
{
|
|
1266
|
+
style: {
|
|
1267
|
+
...quickChatStyles.contextChunkCompact,
|
|
1268
|
+
...chunk.included ? {} : quickChatStyles.contextChunkExcluded
|
|
1269
|
+
},
|
|
1270
|
+
children: [
|
|
1271
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1272
|
+
"input",
|
|
1273
|
+
{
|
|
1274
|
+
type: "checkbox",
|
|
1275
|
+
checked: chunk.included,
|
|
1276
|
+
onChange: () => toggleChunk(chunk.id),
|
|
1277
|
+
style: quickChatStyles.contextCheckbox
|
|
1278
|
+
}
|
|
1279
|
+
),
|
|
1280
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: quickChatStyles.contextLabel, children: chunk.label })
|
|
1281
|
+
]
|
|
1282
|
+
},
|
|
1283
|
+
chunk.id
|
|
1284
|
+
)) }),
|
|
1285
|
+
mergedConfig.showSuggestions && messages.length === 0 && suggestedPrompts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: quickChatStyles.suggestionsContainer, children: isLoadingSuggestions ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoadingDots, {}) : suggestedPrompts.map((prompt) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1286
|
+
"button",
|
|
1287
|
+
{
|
|
1288
|
+
type: "button",
|
|
1289
|
+
onClick: () => selectSuggestion(prompt),
|
|
1290
|
+
onMouseEnter: () => setHoveredSuggestion(prompt.id),
|
|
1291
|
+
onMouseLeave: () => setHoveredSuggestion(null),
|
|
1292
|
+
style: {
|
|
1293
|
+
...quickChatStyles.suggestionChip,
|
|
1294
|
+
...hoveredSuggestion === prompt.id ? quickChatStyles.suggestionChipHover : {}
|
|
1295
|
+
},
|
|
1296
|
+
children: prompt.text
|
|
1297
|
+
},
|
|
1298
|
+
prompt.id
|
|
1299
|
+
)) }),
|
|
1300
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1301
|
+
"div",
|
|
1302
|
+
{
|
|
1303
|
+
style: isPinned ? quickChatStyles.pinnedMessagesArea : quickChatStyles.messagesArea,
|
|
1304
|
+
children: [
|
|
1305
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: quickChatStyles.errorContainer, children: [
|
|
1306
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.AlertCircle, { size: 20, style: quickChatStyles.errorIcon }),
|
|
1307
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: quickChatStyles.errorText, children: error }),
|
|
1308
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1309
|
+
"button",
|
|
1310
|
+
{
|
|
1311
|
+
type: "button",
|
|
1312
|
+
onClick: () => sendMessage(),
|
|
1313
|
+
style: quickChatStyles.errorRetry,
|
|
1314
|
+
children: [
|
|
1315
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.RefreshCw, { size: 10 }),
|
|
1316
|
+
"Retry"
|
|
1317
|
+
]
|
|
1318
|
+
}
|
|
1319
|
+
)
|
|
1320
|
+
] }),
|
|
1321
|
+
messages.length > 0 && messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1322
|
+
"div",
|
|
1323
|
+
{
|
|
1324
|
+
style: {
|
|
1325
|
+
...quickChatStyles.message,
|
|
1326
|
+
animation: "fadeIn 0.2s ease-out"
|
|
1327
|
+
},
|
|
1328
|
+
children: [
|
|
1329
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1330
|
+
"div",
|
|
1331
|
+
{
|
|
1332
|
+
style: message.role === "user" ? quickChatStyles.messageUser : quickChatStyles.messageAssistant,
|
|
1333
|
+
children: [
|
|
1334
|
+
message.content,
|
|
1335
|
+
message.isStreaming && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: quickChatStyles.streamingIndicator }),
|
|
1336
|
+
message.role === "assistant" && !message.isStreaming && message.content.endsWith("...") && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: quickChatStyles.truncated, children: "(truncated)" })
|
|
1337
|
+
]
|
|
1338
|
+
}
|
|
1339
|
+
),
|
|
1340
|
+
message.role === "assistant" && !message.isStreaming && message.content && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: quickChatStyles.messageActions, children: [
|
|
1341
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1342
|
+
"button",
|
|
1343
|
+
{
|
|
1344
|
+
type: "button",
|
|
1345
|
+
onClick: () => handleCopy(message.content),
|
|
1346
|
+
style: quickChatStyles.actionButton,
|
|
1347
|
+
children: [
|
|
1348
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Copy, { size: 10 }),
|
|
1349
|
+
"Copy"
|
|
1350
|
+
]
|
|
1351
|
+
}
|
|
1352
|
+
),
|
|
1353
|
+
message.actions?.map((action) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1354
|
+
"button",
|
|
1355
|
+
{
|
|
1356
|
+
type: "button",
|
|
1357
|
+
onClick: action.onClick,
|
|
1358
|
+
style: quickChatStyles.actionButton,
|
|
1359
|
+
children: [
|
|
1360
|
+
action.icon,
|
|
1361
|
+
action.label
|
|
1362
|
+
]
|
|
1363
|
+
},
|
|
1364
|
+
action.id
|
|
1365
|
+
))
|
|
1366
|
+
] })
|
|
1367
|
+
]
|
|
1368
|
+
},
|
|
1369
|
+
message.id
|
|
1370
|
+
)),
|
|
1371
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: messagesEndRef })
|
|
1372
|
+
]
|
|
1373
|
+
}
|
|
1374
|
+
),
|
|
1375
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: quickChatStyles.inputContainer, children: [
|
|
1376
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1377
|
+
"textarea",
|
|
1378
|
+
{
|
|
1379
|
+
ref: inputRef,
|
|
1380
|
+
value: input,
|
|
1381
|
+
onChange: handleInputChange,
|
|
1382
|
+
onKeyDown: handleKeyDown,
|
|
1383
|
+
onFocus: () => setInputFocused(true),
|
|
1384
|
+
onBlur: () => setInputFocused(false),
|
|
1385
|
+
placeholder: mergedConfig.placeholder,
|
|
1386
|
+
disabled: isSending,
|
|
1387
|
+
rows: 1,
|
|
1388
|
+
style: {
|
|
1389
|
+
...quickChatStyles.input,
|
|
1390
|
+
...inputFocused ? quickChatStyles.inputFocused : {}
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
),
|
|
1394
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: "4px" }, children: [
|
|
1395
|
+
mergedConfig.t3chat?.enabled !== false && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1396
|
+
"button",
|
|
1397
|
+
{
|
|
1398
|
+
type: "button",
|
|
1399
|
+
onClick: handleSendToT3Chat,
|
|
1400
|
+
disabled: !input.trim(),
|
|
1401
|
+
title: mergedConfig.t3chat?.label ?? "Ask t3.chat",
|
|
1402
|
+
style: {
|
|
1403
|
+
...quickChatStyles.sendButton,
|
|
1404
|
+
backgroundColor: "#7c3aed",
|
|
1405
|
+
...!input.trim() ? quickChatStyles.sendButtonDisabled : {}
|
|
1406
|
+
},
|
|
1407
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ExternalLink, { size: 14 })
|
|
1408
|
+
}
|
|
1409
|
+
),
|
|
1410
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1411
|
+
"button",
|
|
1412
|
+
{
|
|
1413
|
+
type: "button",
|
|
1414
|
+
onClick: handleSend,
|
|
1415
|
+
disabled: isSending || !input.trim(),
|
|
1416
|
+
style: {
|
|
1417
|
+
...quickChatStyles.sendButton,
|
|
1418
|
+
...isSending || !input.trim() ? quickChatStyles.sendButtonDisabled : {}
|
|
1419
|
+
},
|
|
1420
|
+
children: isSending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1421
|
+
"div",
|
|
1422
|
+
{
|
|
1423
|
+
style: {
|
|
1424
|
+
width: "14px",
|
|
1425
|
+
height: "14px",
|
|
1426
|
+
border: "2px solid transparent",
|
|
1427
|
+
borderTopColor: "#fff",
|
|
1428
|
+
borderRadius: "50%",
|
|
1429
|
+
animation: "spin 0.8s linear infinite"
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Send, { size: 14 })
|
|
1433
|
+
}
|
|
1434
|
+
)
|
|
1435
|
+
] })
|
|
1436
|
+
] })
|
|
1437
|
+
] });
|
|
1438
|
+
}
|
|
97
1439
|
|
|
98
|
-
// src/
|
|
99
|
-
var
|
|
1440
|
+
// src/ScreenshotPreview.tsx
|
|
1441
|
+
var import_react3 = __toESM(require("react"));
|
|
100
1442
|
var import_anyclick_core2 = require("@ewjdev/anyclick-core");
|
|
101
1443
|
var import_lucide_react2 = require("lucide-react");
|
|
102
1444
|
|
|
103
|
-
// src/ScreenshotPreview.tsx
|
|
104
|
-
var import_react = __toESM(require("react"));
|
|
105
|
-
var import_anyclick_core = require("@ewjdev/anyclick-core");
|
|
106
|
-
var import_lucide_react = require("lucide-react");
|
|
107
|
-
|
|
108
1445
|
// src/styles.ts
|
|
109
1446
|
var menuCSSVariables = {
|
|
110
1447
|
"--anyclick-menu-accent": "#0066cc",
|
|
@@ -578,8 +1915,8 @@ var screenshotPreviewStyles = {
|
|
|
578
1915
|
};
|
|
579
1916
|
|
|
580
1917
|
// src/ScreenshotPreview.tsx
|
|
581
|
-
var
|
|
582
|
-
var ScreenshotPreview =
|
|
1918
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1919
|
+
var ScreenshotPreview = import_react3.default.memo(function ScreenshotPreview2({
|
|
583
1920
|
isLoading,
|
|
584
1921
|
isSubmitting,
|
|
585
1922
|
onCancel,
|
|
@@ -587,12 +1924,12 @@ var ScreenshotPreview = import_react.default.memo(function ScreenshotPreview2({
|
|
|
587
1924
|
onRetake,
|
|
588
1925
|
screenshots
|
|
589
1926
|
}) {
|
|
590
|
-
const [activeTab, setActiveTab] = (0,
|
|
591
|
-
const [isExpanded, setIsExpanded] = (0,
|
|
1927
|
+
const [activeTab, setActiveTab] = (0, import_react3.useState)("element");
|
|
1928
|
+
const [isExpanded, setIsExpanded] = (0, import_react3.useState)(false);
|
|
592
1929
|
const getError = (key) => {
|
|
593
1930
|
return screenshots?.errors?.[key];
|
|
594
1931
|
};
|
|
595
|
-
const tabs = (0,
|
|
1932
|
+
const tabs = (0, import_react3.useMemo)(() => {
|
|
596
1933
|
if (!screenshots) return [];
|
|
597
1934
|
const allTabs = [
|
|
598
1935
|
{
|
|
@@ -616,29 +1953,29 @@ var ScreenshotPreview = import_react.default.memo(function ScreenshotPreview2({
|
|
|
616
1953
|
];
|
|
617
1954
|
return allTabs.filter((tab) => tab.data || tab.error);
|
|
618
1955
|
}, [screenshots]);
|
|
619
|
-
const totalSize = (0,
|
|
620
|
-
() => screenshots ? (0,
|
|
1956
|
+
const totalSize = (0, import_react3.useMemo)(
|
|
1957
|
+
() => screenshots ? (0, import_anyclick_core2.estimateTotalSize)(screenshots) : 0,
|
|
621
1958
|
[screenshots]
|
|
622
1959
|
);
|
|
623
1960
|
if (isLoading) {
|
|
624
|
-
return /* @__PURE__ */ (0,
|
|
625
|
-
/* @__PURE__ */ (0,
|
|
626
|
-
|
|
1961
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: screenshotPreviewStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: screenshotPreviewStyles.loadingContainer, children: [
|
|
1962
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1963
|
+
import_lucide_react2.Loader2Icon,
|
|
627
1964
|
{
|
|
628
1965
|
className: "w-6 h-6 animate-spin",
|
|
629
1966
|
style: { color: "#3b82f6" }
|
|
630
1967
|
}
|
|
631
1968
|
),
|
|
632
|
-
/* @__PURE__ */ (0,
|
|
1969
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: screenshotPreviewStyles.loadingText, children: "Capturing screenshots..." })
|
|
633
1970
|
] }) });
|
|
634
1971
|
}
|
|
635
1972
|
if (!screenshots) {
|
|
636
|
-
return /* @__PURE__ */ (0,
|
|
637
|
-
/* @__PURE__ */ (0,
|
|
638
|
-
/* @__PURE__ */ (0,
|
|
639
|
-
/* @__PURE__ */ (0,
|
|
640
|
-
/* @__PURE__ */ (0,
|
|
641
|
-
/* @__PURE__ */ (0,
|
|
1973
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: screenshotPreviewStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: screenshotPreviewStyles.emptyContainer, children: [
|
|
1974
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.ImageIcon, { className: "w-8 h-8", style: { color: "#9ca3af" } }),
|
|
1975
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: screenshotPreviewStyles.emptyText, children: "Screenshots unavailable" }),
|
|
1976
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: screenshotPreviewStyles.emptySubtext, children: "Some elements can't be captured (e.g., gradient text)" }),
|
|
1977
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: screenshotPreviewStyles.emptyActions, children: [
|
|
1978
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
642
1979
|
"button",
|
|
643
1980
|
{
|
|
644
1981
|
type: "button",
|
|
@@ -646,12 +1983,12 @@ var ScreenshotPreview = import_react.default.memo(function ScreenshotPreview2({
|
|
|
646
1983
|
onClick: onRetake,
|
|
647
1984
|
style: screenshotPreviewStyles.retakeButtonOutline,
|
|
648
1985
|
children: [
|
|
649
|
-
/* @__PURE__ */ (0,
|
|
1986
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.RefreshCwIcon, { className: "w-4 h-4" }),
|
|
650
1987
|
"Try Again"
|
|
651
1988
|
]
|
|
652
1989
|
}
|
|
653
1990
|
),
|
|
654
|
-
/* @__PURE__ */ (0,
|
|
1991
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
655
1992
|
"button",
|
|
656
1993
|
{
|
|
657
1994
|
type: "button",
|
|
@@ -659,7 +1996,7 @@ var ScreenshotPreview = import_react.default.memo(function ScreenshotPreview2({
|
|
|
659
1996
|
onClick: () => onConfirm({ capturedAt: (/* @__PURE__ */ new Date()).toISOString() }),
|
|
660
1997
|
style: screenshotPreviewStyles.continueButton,
|
|
661
1998
|
children: [
|
|
662
|
-
/* @__PURE__ */ (0,
|
|
1999
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.CheckIcon, { className: "w-4 h-4" }),
|
|
663
2000
|
"Continue Without"
|
|
664
2001
|
]
|
|
665
2002
|
}
|
|
@@ -669,7 +2006,7 @@ var ScreenshotPreview = import_react.default.memo(function ScreenshotPreview2({
|
|
|
669
2006
|
}
|
|
670
2007
|
const activeScreenshot = activeTab === "element" ? screenshots.element : activeTab === "container" ? screenshots.container : screenshots.viewport;
|
|
671
2008
|
const activeError = getError(activeTab);
|
|
672
|
-
return /* @__PURE__ */ (0,
|
|
2009
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
673
2010
|
"div",
|
|
674
2011
|
{
|
|
675
2012
|
style: {
|
|
@@ -678,23 +2015,23 @@ var ScreenshotPreview = import_react.default.memo(function ScreenshotPreview2({
|
|
|
678
2015
|
padding: "8px"
|
|
679
2016
|
},
|
|
680
2017
|
children: [
|
|
681
|
-
/* @__PURE__ */ (0,
|
|
682
|
-
/* @__PURE__ */ (0,
|
|
683
|
-
/* @__PURE__ */ (0,
|
|
684
|
-
/* @__PURE__ */ (0,
|
|
685
|
-
/* @__PURE__ */ (0,
|
|
2018
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: screenshotPreviewStyles.header, children: [
|
|
2019
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: screenshotPreviewStyles.headerTitle, children: "Review Screenshots" }),
|
|
2020
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: screenshotPreviewStyles.headerActions, children: [
|
|
2021
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: screenshotPreviewStyles.sizeLabel, children: (0, import_anyclick_core2.formatBytes)(totalSize) }),
|
|
2022
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
686
2023
|
"button",
|
|
687
2024
|
{
|
|
688
2025
|
type: "button",
|
|
689
2026
|
onClick: () => setIsExpanded(!isExpanded),
|
|
690
2027
|
style: screenshotPreviewStyles.iconButton,
|
|
691
2028
|
title: isExpanded ? "Collapse" : "Expand",
|
|
692
|
-
children: isExpanded ? /* @__PURE__ */ (0,
|
|
2029
|
+
children: isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.ShrinkIcon, { className: "w-4 h-4" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.ExpandIcon, { className: "w-4 h-4" })
|
|
693
2030
|
}
|
|
694
2031
|
)
|
|
695
2032
|
] })
|
|
696
2033
|
] }),
|
|
697
|
-
/* @__PURE__ */ (0,
|
|
2034
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: screenshotPreviewStyles.tabContainer, children: tabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
698
2035
|
"button",
|
|
699
2036
|
{
|
|
700
2037
|
type: "button",
|
|
@@ -705,40 +2042,40 @@ var ScreenshotPreview = import_react.default.memo(function ScreenshotPreview2({
|
|
|
705
2042
|
...tab.error && !tab.data ? screenshotPreviewStyles.tabError : {}
|
|
706
2043
|
},
|
|
707
2044
|
children: [
|
|
708
|
-
tab.error && !tab.data && /* @__PURE__ */ (0,
|
|
709
|
-
|
|
2045
|
+
tab.error && !tab.data && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2046
|
+
import_lucide_react2.AlertCircleIcon,
|
|
710
2047
|
{
|
|
711
2048
|
className: "w-3 h-3",
|
|
712
2049
|
style: { color: "#ef4444" }
|
|
713
2050
|
}
|
|
714
2051
|
),
|
|
715
2052
|
tab.label,
|
|
716
|
-
tab.data && /* @__PURE__ */ (0,
|
|
2053
|
+
tab.data && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: screenshotPreviewStyles.tabSize, children: (0, import_anyclick_core2.formatBytes)(tab.data.sizeBytes) })
|
|
717
2054
|
]
|
|
718
2055
|
},
|
|
719
2056
|
tab.key
|
|
720
2057
|
)) }),
|
|
721
|
-
/* @__PURE__ */ (0,
|
|
2058
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
722
2059
|
"div",
|
|
723
2060
|
{
|
|
724
2061
|
style: {
|
|
725
2062
|
...screenshotPreviewStyles.previewContainer,
|
|
726
2063
|
...isExpanded ? screenshotPreviewStyles.previewContainerExpanded : {}
|
|
727
2064
|
},
|
|
728
|
-
children: activeScreenshot ? /* @__PURE__ */ (0,
|
|
2065
|
+
children: activeScreenshot ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
729
2066
|
"img",
|
|
730
2067
|
{
|
|
731
2068
|
alt: `${activeTab} screenshot`,
|
|
732
2069
|
src: activeScreenshot.dataUrl,
|
|
733
2070
|
style: screenshotPreviewStyles.previewImage
|
|
734
2071
|
}
|
|
735
|
-
) : activeError ? /* @__PURE__ */ (0,
|
|
736
|
-
/* @__PURE__ */ (0,
|
|
737
|
-
/* @__PURE__ */ (0,
|
|
738
|
-
/* @__PURE__ */ (0,
|
|
739
|
-
] }) : /* @__PURE__ */ (0,
|
|
740
|
-
/* @__PURE__ */ (0,
|
|
741
|
-
/* @__PURE__ */ (0,
|
|
2072
|
+
) : activeError ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: screenshotPreviewStyles.errorPreview, children: [
|
|
2073
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.AlertCircleIcon, { className: "w-8 h-8", style: { color: "#ef4444" } }),
|
|
2074
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: screenshotPreviewStyles.errorTitle, children: "Capture Failed" }),
|
|
2075
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: screenshotPreviewStyles.errorMessage, children: activeError.message })
|
|
2076
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: screenshotPreviewStyles.noPreview, children: [
|
|
2077
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.ImageIcon, { className: "w-6 h-6", style: { color: "#9ca3af" } }),
|
|
2078
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
|
|
742
2079
|
"No ",
|
|
743
2080
|
activeTab,
|
|
744
2081
|
" screenshot"
|
|
@@ -746,14 +2083,14 @@ var ScreenshotPreview = import_react.default.memo(function ScreenshotPreview2({
|
|
|
746
2083
|
] })
|
|
747
2084
|
}
|
|
748
2085
|
),
|
|
749
|
-
activeScreenshot && /* @__PURE__ */ (0,
|
|
2086
|
+
activeScreenshot && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: screenshotPreviewStyles.dimensionsInfo, children: [
|
|
750
2087
|
activeScreenshot.width,
|
|
751
2088
|
" \xD7 ",
|
|
752
2089
|
activeScreenshot.height,
|
|
753
2090
|
"px"
|
|
754
2091
|
] }),
|
|
755
|
-
/* @__PURE__ */ (0,
|
|
756
|
-
/* @__PURE__ */ (0,
|
|
2092
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: screenshotPreviewStyles.actions, children: [
|
|
2093
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
757
2094
|
"button",
|
|
758
2095
|
{
|
|
759
2096
|
type: "button",
|
|
@@ -761,13 +2098,13 @@ var ScreenshotPreview = import_react.default.memo(function ScreenshotPreview2({
|
|
|
761
2098
|
onClick: onRetake,
|
|
762
2099
|
style: screenshotPreviewStyles.retakeButtonSmall,
|
|
763
2100
|
children: [
|
|
764
|
-
/* @__PURE__ */ (0,
|
|
2101
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.RefreshCwIcon, { className: "w-3 h-3" }),
|
|
765
2102
|
"Retake"
|
|
766
2103
|
]
|
|
767
2104
|
}
|
|
768
2105
|
),
|
|
769
|
-
/* @__PURE__ */ (0,
|
|
770
|
-
/* @__PURE__ */ (0,
|
|
2106
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: screenshotPreviewStyles.actionsRight, children: [
|
|
2107
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
771
2108
|
"button",
|
|
772
2109
|
{
|
|
773
2110
|
type: "button",
|
|
@@ -776,12 +2113,12 @@ var ScreenshotPreview = import_react.default.memo(function ScreenshotPreview2({
|
|
|
776
2113
|
onClick: onCancel,
|
|
777
2114
|
style: { ...menuStyles.button, ...menuStyles.cancelButton },
|
|
778
2115
|
children: [
|
|
779
|
-
/* @__PURE__ */ (0,
|
|
2116
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.XIcon, { className: "w-3 h-3" }),
|
|
780
2117
|
"Cancel"
|
|
781
2118
|
]
|
|
782
2119
|
}
|
|
783
2120
|
),
|
|
784
|
-
/* @__PURE__ */ (0,
|
|
2121
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
785
2122
|
"button",
|
|
786
2123
|
{
|
|
787
2124
|
type: "button",
|
|
@@ -792,11 +2129,11 @@ var ScreenshotPreview = import_react.default.memo(function ScreenshotPreview2({
|
|
|
792
2129
|
...menuStyles.submitButton,
|
|
793
2130
|
...isSubmitting ? menuStyles.submitButtonDisabled : {}
|
|
794
2131
|
},
|
|
795
|
-
children: isSubmitting ? /* @__PURE__ */ (0,
|
|
796
|
-
/* @__PURE__ */ (0,
|
|
2132
|
+
children: isSubmitting ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
2133
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.Loader2Icon, { className: "w-3 h-3 animate-spin" }),
|
|
797
2134
|
"Sending..."
|
|
798
|
-
] }) : /* @__PURE__ */ (0,
|
|
799
|
-
/* @__PURE__ */ (0,
|
|
2135
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
2136
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.CheckIcon, { className: "w-3 h-3" }),
|
|
800
2137
|
"Send"
|
|
801
2138
|
] })
|
|
802
2139
|
}
|
|
@@ -893,7 +2230,7 @@ svg.${HIGHLIGHT_CONTAINER_CLASS},
|
|
|
893
2230
|
}
|
|
894
2231
|
`;
|
|
895
2232
|
}
|
|
896
|
-
function
|
|
2233
|
+
function injectStyles2(colors) {
|
|
897
2234
|
if (typeof document === "undefined") return;
|
|
898
2235
|
const existingStyle = document.getElementById(STYLE_ID);
|
|
899
2236
|
if (existingStyle) {
|
|
@@ -941,12 +2278,12 @@ function findContainerParent(element, config) {
|
|
|
941
2278
|
}
|
|
942
2279
|
function highlightTarget(element, colors) {
|
|
943
2280
|
const mergedColors = { ...defaultHighlightColors, ...colors };
|
|
944
|
-
|
|
2281
|
+
injectStyles2(mergedColors);
|
|
945
2282
|
element.classList.add(HIGHLIGHT_TARGET_CLASS);
|
|
946
2283
|
}
|
|
947
2284
|
function highlightContainer(element, colors) {
|
|
948
2285
|
const mergedColors = { ...defaultHighlightColors, ...colors };
|
|
949
|
-
|
|
2286
|
+
injectStyles2(mergedColors);
|
|
950
2287
|
element.classList.add(HIGHLIGHT_CONTAINER_CLASS);
|
|
951
2288
|
}
|
|
952
2289
|
function clearHighlights() {
|
|
@@ -973,12 +2310,12 @@ function applyHighlights(targetElement, config) {
|
|
|
973
2310
|
}
|
|
974
2311
|
|
|
975
2312
|
// src/ContextMenu.tsx
|
|
976
|
-
var
|
|
2313
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
977
2314
|
var VIEWPORT_PADDING = 10;
|
|
978
2315
|
var defaultIcons = {
|
|
979
|
-
feature: /* @__PURE__ */ (0,
|
|
980
|
-
issue: /* @__PURE__ */ (0,
|
|
981
|
-
like: /* @__PURE__ */ (0,
|
|
2316
|
+
feature: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react3.PlusIcon, { className: "w-4 h-4" }),
|
|
2317
|
+
issue: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react3.FlagIcon, { className: "w-4 h-4" }),
|
|
2318
|
+
like: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react3.ThumbsUpIcon, { className: "w-4 h-4" })
|
|
982
2319
|
};
|
|
983
2320
|
var OFFSCREEN_POSITION = { x: -9999, y: -9999 };
|
|
984
2321
|
var DefaultHeader = ({
|
|
@@ -987,25 +2324,25 @@ var DefaultHeader = ({
|
|
|
987
2324
|
styles,
|
|
988
2325
|
title = "Send Feedback"
|
|
989
2326
|
}) => {
|
|
990
|
-
return /* @__PURE__ */ (0,
|
|
991
|
-
/* @__PURE__ */ (0,
|
|
2327
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles, className, children: [
|
|
2328
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: title }),
|
|
992
2329
|
children
|
|
993
2330
|
] });
|
|
994
2331
|
};
|
|
995
|
-
var MenuItem =
|
|
2332
|
+
var MenuItem = import_react4.default.memo(function MenuItem2({
|
|
996
2333
|
disabled,
|
|
997
2334
|
hasChildren,
|
|
998
2335
|
item,
|
|
999
2336
|
onClick
|
|
1000
2337
|
}) {
|
|
1001
|
-
const [isHovered, setIsHovered] = (0,
|
|
1002
|
-
const [isPressed, setIsPressed] = (0,
|
|
2338
|
+
const [isHovered, setIsHovered] = (0, import_react4.useState)(false);
|
|
2339
|
+
const [isPressed, setIsPressed] = (0, import_react4.useState)(false);
|
|
1003
2340
|
const isComingSoon = item.status === "comingSoon";
|
|
1004
2341
|
const badgeLabel = item.badge?.label ?? (isComingSoon ? "Coming soon" : null);
|
|
1005
2342
|
const badgeTone = item.badge?.tone ?? (isComingSoon ? "neutral" : "neutral");
|
|
1006
2343
|
const badgeStyle = badgeLabel ? getBadgeStyle(badgeTone) : void 0;
|
|
1007
2344
|
const iconNode = item.icon ?? defaultIcons[item.type];
|
|
1008
|
-
return /* @__PURE__ */ (0,
|
|
2345
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1009
2346
|
"button",
|
|
1010
2347
|
{
|
|
1011
2348
|
type: "button",
|
|
@@ -1026,22 +2363,22 @@ var MenuItem = import_react2.default.memo(function MenuItem2({
|
|
|
1026
2363
|
...disabled ? menuStyles.itemDisabled : {}
|
|
1027
2364
|
},
|
|
1028
2365
|
children: [
|
|
1029
|
-
iconNode ? /* @__PURE__ */ (0,
|
|
1030
|
-
/* @__PURE__ */ (0,
|
|
2366
|
+
iconNode ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: menuStyles.itemIcon, children: iconNode }) : null,
|
|
2367
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: menuStyles.itemLabel, children: [
|
|
1031
2368
|
item.label,
|
|
1032
|
-
badgeLabel && /* @__PURE__ */ (0,
|
|
2369
|
+
badgeLabel && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: badgeStyle, children: badgeLabel })
|
|
1033
2370
|
] }),
|
|
1034
|
-
hasChildren && /* @__PURE__ */ (0,
|
|
2371
|
+
hasChildren && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react3.ChevronRightIcon, { className: "w-4 h-4", style: menuStyles.submenuIcon })
|
|
1035
2372
|
]
|
|
1036
2373
|
}
|
|
1037
2374
|
);
|
|
1038
2375
|
});
|
|
1039
|
-
var BackButton =
|
|
2376
|
+
var BackButton = import_react4.default.memo(function BackButton2({
|
|
1040
2377
|
onClick
|
|
1041
2378
|
}) {
|
|
1042
|
-
const [isHovered, setIsHovered] = (0,
|
|
1043
|
-
const [isPressed, setIsPressed] = (0,
|
|
1044
|
-
return /* @__PURE__ */ (0,
|
|
2379
|
+
const [isHovered, setIsHovered] = (0, import_react4.useState)(false);
|
|
2380
|
+
const [isPressed, setIsPressed] = (0, import_react4.useState)(false);
|
|
2381
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1045
2382
|
"button",
|
|
1046
2383
|
{
|
|
1047
2384
|
type: "button",
|
|
@@ -1061,26 +2398,26 @@ var BackButton = import_react2.default.memo(function BackButton2({
|
|
|
1061
2398
|
...isHovered || isPressed ? menuStyles.itemHover : {}
|
|
1062
2399
|
},
|
|
1063
2400
|
children: [
|
|
1064
|
-
/* @__PURE__ */ (0,
|
|
1065
|
-
/* @__PURE__ */ (0,
|
|
2401
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react3.ChevronLeftIcon, { className: "w-4 h-4", style: { opacity: 0.5 } }),
|
|
2402
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { opacity: 0.7 }, children: "Back" })
|
|
1066
2403
|
]
|
|
1067
2404
|
}
|
|
1068
2405
|
);
|
|
1069
2406
|
});
|
|
1070
|
-
var CommentForm =
|
|
2407
|
+
var CommentForm = import_react4.default.memo(function CommentForm2({
|
|
1071
2408
|
isSubmitting,
|
|
1072
2409
|
onCancel,
|
|
1073
2410
|
onSubmit
|
|
1074
2411
|
}) {
|
|
1075
|
-
const [comment, setComment] = (0,
|
|
1076
|
-
const inputRef = (0,
|
|
1077
|
-
(0,
|
|
2412
|
+
const [comment, setComment] = (0, import_react4.useState)("");
|
|
2413
|
+
const inputRef = (0, import_react4.useRef)(null);
|
|
2414
|
+
(0, import_react4.useEffect)(() => {
|
|
1078
2415
|
inputRef.current?.focus();
|
|
1079
2416
|
}, []);
|
|
1080
|
-
const handleSubmit = (0,
|
|
2417
|
+
const handleSubmit = (0, import_react4.useCallback)(() => {
|
|
1081
2418
|
onSubmit(comment);
|
|
1082
2419
|
}, [comment, onSubmit]);
|
|
1083
|
-
const handleKeyDown = (0,
|
|
2420
|
+
const handleKeyDown = (0, import_react4.useCallback)(
|
|
1084
2421
|
(e) => {
|
|
1085
2422
|
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
1086
2423
|
handleSubmit();
|
|
@@ -1090,8 +2427,8 @@ var CommentForm = import_react2.default.memo(function CommentForm2({
|
|
|
1090
2427
|
},
|
|
1091
2428
|
[handleSubmit, onCancel]
|
|
1092
2429
|
);
|
|
1093
|
-
return /* @__PURE__ */ (0,
|
|
1094
|
-
/* @__PURE__ */ (0,
|
|
2430
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: menuStyles.commentSection, children: [
|
|
2431
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1095
2432
|
"textarea",
|
|
1096
2433
|
{
|
|
1097
2434
|
ref: inputRef,
|
|
@@ -1103,8 +2440,8 @@ var CommentForm = import_react2.default.memo(function CommentForm2({
|
|
|
1103
2440
|
value: comment
|
|
1104
2441
|
}
|
|
1105
2442
|
),
|
|
1106
|
-
/* @__PURE__ */ (0,
|
|
1107
|
-
/* @__PURE__ */ (0,
|
|
2443
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: menuStyles.buttonRow, children: [
|
|
2444
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1108
2445
|
"button",
|
|
1109
2446
|
{
|
|
1110
2447
|
type: "button",
|
|
@@ -1114,7 +2451,7 @@ var CommentForm = import_react2.default.memo(function CommentForm2({
|
|
|
1114
2451
|
children: "Cancel"
|
|
1115
2452
|
}
|
|
1116
2453
|
),
|
|
1117
|
-
/* @__PURE__ */ (0,
|
|
2454
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1118
2455
|
"button",
|
|
1119
2456
|
{
|
|
1120
2457
|
type: "button",
|
|
@@ -1162,39 +2499,48 @@ function ContextMenu({
|
|
|
1162
2499
|
onSelect,
|
|
1163
2500
|
position,
|
|
1164
2501
|
positionMode = "inView",
|
|
2502
|
+
quickChatConfig,
|
|
1165
2503
|
screenshotConfig,
|
|
1166
2504
|
style,
|
|
1167
2505
|
targetElement,
|
|
1168
2506
|
visible
|
|
1169
2507
|
}) {
|
|
1170
|
-
const [selectedType, setSelectedType] = (0,
|
|
1171
|
-
const [currentView, setCurrentView] = (0,
|
|
1172
|
-
const [pendingComment, setPendingComment] = (0,
|
|
1173
|
-
const [submenuStack, setSubmenuStack] = (0,
|
|
1174
|
-
const [screenshots, setScreenshots] = (0,
|
|
1175
|
-
const [isCapturing, setIsCapturing] = (0,
|
|
1176
|
-
const
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
2508
|
+
const [selectedType, setSelectedType] = (0, import_react4.useState)(null);
|
|
2509
|
+
const [currentView, setCurrentView] = (0, import_react4.useState)("menu");
|
|
2510
|
+
const [pendingComment, setPendingComment] = (0, import_react4.useState)();
|
|
2511
|
+
const [submenuStack, setSubmenuStack] = (0, import_react4.useState)([]);
|
|
2512
|
+
const [screenshots, setScreenshots] = (0, import_react4.useState)(null);
|
|
2513
|
+
const [isCapturing, setIsCapturing] = (0, import_react4.useState)(false);
|
|
2514
|
+
const [isQuickChatPinned, setIsQuickChatPinned] = (0, import_react4.useState)(() => {
|
|
2515
|
+
if (typeof window === "undefined") return false;
|
|
2516
|
+
try {
|
|
2517
|
+
return sessionStorage.getItem("anyclick-quick-chat-pinned") === "true";
|
|
2518
|
+
} catch {
|
|
2519
|
+
return false;
|
|
2520
|
+
}
|
|
2521
|
+
});
|
|
2522
|
+
const menuRef = (0, import_react4.useRef)(null);
|
|
2523
|
+
const [adjustedPosition, setAdjustedPosition] = (0, import_react4.useState)(OFFSCREEN_POSITION);
|
|
2524
|
+
const [isDragging, setIsDragging] = (0, import_react4.useState)(false);
|
|
2525
|
+
const [dragOffset, setDragOffset] = (0, import_react4.useState)({
|
|
1180
2526
|
x: 0,
|
|
1181
2527
|
y: 0
|
|
1182
2528
|
});
|
|
1183
|
-
const dragStartRef = (0,
|
|
1184
|
-
const mergedScreenshotConfig =
|
|
2529
|
+
const dragStartRef = (0, import_react4.useRef)(null);
|
|
2530
|
+
const mergedScreenshotConfig = import_react4.default.useMemo(
|
|
1185
2531
|
() => ({
|
|
1186
|
-
...
|
|
2532
|
+
...import_anyclick_core3.DEFAULT_SCREENSHOT_CONFIG,
|
|
1187
2533
|
...screenshotConfig
|
|
1188
2534
|
}),
|
|
1189
2535
|
[screenshotConfig]
|
|
1190
2536
|
);
|
|
1191
|
-
const showPreview = mergedScreenshotConfig.showPreview && (0,
|
|
2537
|
+
const showPreview = mergedScreenshotConfig.showPreview && (0, import_anyclick_core3.isScreenshotSupported)();
|
|
1192
2538
|
const currentItems = submenuStack.length > 0 ? submenuStack[submenuStack.length - 1] : items;
|
|
1193
|
-
const captureScreenshots = (0,
|
|
2539
|
+
const captureScreenshots = (0, import_react4.useCallback)(async () => {
|
|
1194
2540
|
if (!targetElement || !showPreview) return;
|
|
1195
2541
|
setIsCapturing(true);
|
|
1196
2542
|
try {
|
|
1197
|
-
const captured = await (0,
|
|
2543
|
+
const captured = await (0, import_anyclick_core3.captureAllScreenshots)(
|
|
1198
2544
|
targetElement,
|
|
1199
2545
|
containerElement,
|
|
1200
2546
|
mergedScreenshotConfig
|
|
@@ -1207,7 +2553,7 @@ function ContextMenu({
|
|
|
1207
2553
|
setIsCapturing(false);
|
|
1208
2554
|
}
|
|
1209
2555
|
}, [containerElement, mergedScreenshotConfig, showPreview, targetElement]);
|
|
1210
|
-
(0,
|
|
2556
|
+
(0, import_react4.useEffect)(() => {
|
|
1211
2557
|
if (!visible) {
|
|
1212
2558
|
setSelectedType(null);
|
|
1213
2559
|
setCurrentView("menu");
|
|
@@ -1221,7 +2567,7 @@ function ContextMenu({
|
|
|
1221
2567
|
dragStartRef.current = null;
|
|
1222
2568
|
}
|
|
1223
2569
|
}, [visible]);
|
|
1224
|
-
(0,
|
|
2570
|
+
(0, import_react4.useEffect)(() => {
|
|
1225
2571
|
if (visible && targetElement) {
|
|
1226
2572
|
clearHighlights();
|
|
1227
2573
|
applyHighlights(targetElement, highlightConfig);
|
|
@@ -1232,7 +2578,7 @@ function ContextMenu({
|
|
|
1232
2578
|
clearHighlights();
|
|
1233
2579
|
};
|
|
1234
2580
|
}, [highlightConfig, targetElement, visible]);
|
|
1235
|
-
(0,
|
|
2581
|
+
(0, import_react4.useEffect)(() => {
|
|
1236
2582
|
if (!visible) {
|
|
1237
2583
|
return;
|
|
1238
2584
|
}
|
|
@@ -1251,13 +2597,13 @@ function ContextMenu({
|
|
|
1251
2597
|
document.removeEventListener("pointerdown", handlePointerDown);
|
|
1252
2598
|
};
|
|
1253
2599
|
}, [onClose, visible]);
|
|
1254
|
-
(0,
|
|
2600
|
+
(0, import_react4.useEffect)(() => {
|
|
1255
2601
|
if (visible) {
|
|
1256
2602
|
setAdjustedPosition(position);
|
|
1257
2603
|
setDragOffset({ x: 0, y: 0 });
|
|
1258
2604
|
}
|
|
1259
2605
|
}, [position.x, position.y, visible]);
|
|
1260
|
-
(0,
|
|
2606
|
+
(0, import_react4.useEffect)(() => {
|
|
1261
2607
|
if (!visible || !menuRef.current) return;
|
|
1262
2608
|
const updatePosition = () => {
|
|
1263
2609
|
const menuElement = menuRef.current;
|
|
@@ -1281,7 +2627,7 @@ function ContextMenu({
|
|
|
1281
2627
|
window.addEventListener("resize", updatePosition);
|
|
1282
2628
|
return () => window.removeEventListener("resize", updatePosition);
|
|
1283
2629
|
}, [currentView, dragOffset, position, positionMode, visible]);
|
|
1284
|
-
(0,
|
|
2630
|
+
(0, import_react4.useEffect)(() => {
|
|
1285
2631
|
if (!visible || positionMode !== "dynamic") return;
|
|
1286
2632
|
const handlePointerMove = (event) => {
|
|
1287
2633
|
if (!isDragging || !dragStartRef.current) return;
|
|
@@ -1308,7 +2654,7 @@ function ContextMenu({
|
|
|
1308
2654
|
};
|
|
1309
2655
|
}
|
|
1310
2656
|
}, [isDragging, positionMode, visible]);
|
|
1311
|
-
const handleDragStart = (0,
|
|
2657
|
+
const handleDragStart = (0, import_react4.useCallback)(
|
|
1312
2658
|
(event) => {
|
|
1313
2659
|
if (positionMode !== "dynamic") return;
|
|
1314
2660
|
event.preventDefault();
|
|
@@ -1317,7 +2663,8 @@ function ContextMenu({
|
|
|
1317
2663
|
},
|
|
1318
2664
|
[positionMode]
|
|
1319
2665
|
);
|
|
1320
|
-
(0,
|
|
2666
|
+
const [initialChatInput, setInitialChatInput] = (0, import_react4.useState)("");
|
|
2667
|
+
(0, import_react4.useEffect)(() => {
|
|
1321
2668
|
const handleKeyDown = (e) => {
|
|
1322
2669
|
if (e.key === "Escape") {
|
|
1323
2670
|
if (currentView === "screenshot-preview") {
|
|
@@ -1326,19 +2673,38 @@ function ContextMenu({
|
|
|
1326
2673
|
setCurrentView("menu");
|
|
1327
2674
|
setSelectedType(null);
|
|
1328
2675
|
setPendingComment(void 0);
|
|
2676
|
+
} else if (currentView === "quick-chat") {
|
|
2677
|
+
if (!isQuickChatPinned) {
|
|
2678
|
+
setCurrentView("menu");
|
|
2679
|
+
}
|
|
1329
2680
|
} else if (submenuStack.length > 0) {
|
|
1330
2681
|
setSubmenuStack((prev) => prev.slice(0, -1));
|
|
1331
2682
|
} else {
|
|
1332
2683
|
onClose();
|
|
1333
2684
|
}
|
|
2685
|
+
return;
|
|
2686
|
+
}
|
|
2687
|
+
if (quickChatConfig && currentView === "menu" && !isQuickChatPinned && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
2688
|
+
if (e.key.length === 1 && e.key.match(/[a-zA-Z0-9\s.,!?'"]/)) {
|
|
2689
|
+
e.preventDefault();
|
|
2690
|
+
setInitialChatInput(e.key);
|
|
2691
|
+
setCurrentView("quick-chat");
|
|
2692
|
+
}
|
|
1334
2693
|
}
|
|
1335
2694
|
};
|
|
1336
2695
|
if (visible) {
|
|
1337
2696
|
document.addEventListener("keydown", handleKeyDown);
|
|
1338
2697
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
1339
2698
|
}
|
|
1340
|
-
}, [
|
|
1341
|
-
|
|
2699
|
+
}, [
|
|
2700
|
+
currentView,
|
|
2701
|
+
isQuickChatPinned,
|
|
2702
|
+
onClose,
|
|
2703
|
+
quickChatConfig,
|
|
2704
|
+
submenuStack.length,
|
|
2705
|
+
visible
|
|
2706
|
+
]);
|
|
2707
|
+
(0, import_react4.useEffect)(() => {
|
|
1342
2708
|
const menuElement = menuRef.current;
|
|
1343
2709
|
if (!visible || !menuElement) return;
|
|
1344
2710
|
const preventTouchDefault = (e) => {
|
|
@@ -1355,9 +2721,6 @@ function ContextMenu({
|
|
|
1355
2721
|
menuElement.removeEventListener("touchmove", preventTouchDefault);
|
|
1356
2722
|
};
|
|
1357
2723
|
}, [visible]);
|
|
1358
|
-
if (!visible || !targetElement) {
|
|
1359
|
-
return null;
|
|
1360
|
-
}
|
|
1361
2724
|
const handleItemClick = (item) => {
|
|
1362
2725
|
if (item.status === "comingSoon") {
|
|
1363
2726
|
return;
|
|
@@ -1426,100 +2789,181 @@ function ContextMenu({
|
|
|
1426
2789
|
const handleRetakeScreenshots = () => {
|
|
1427
2790
|
captureScreenshots();
|
|
1428
2791
|
};
|
|
1429
|
-
const
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
{
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
2792
|
+
const handleQuickChatToggle = () => {
|
|
2793
|
+
if (currentView === "quick-chat" && !isQuickChatPinned) {
|
|
2794
|
+
setCurrentView("menu");
|
|
2795
|
+
} else {
|
|
2796
|
+
setCurrentView("quick-chat");
|
|
2797
|
+
}
|
|
2798
|
+
};
|
|
2799
|
+
const handleQuickChatPin = (pinned) => {
|
|
2800
|
+
setIsQuickChatPinned(pinned);
|
|
2801
|
+
try {
|
|
2802
|
+
if (pinned) {
|
|
2803
|
+
sessionStorage.setItem("anyclick-quick-chat-pinned", "true");
|
|
2804
|
+
} else {
|
|
2805
|
+
sessionStorage.removeItem("anyclick-quick-chat-pinned");
|
|
2806
|
+
}
|
|
2807
|
+
} catch {
|
|
2808
|
+
}
|
|
2809
|
+
if (pinned) {
|
|
2810
|
+
setCurrentView("menu");
|
|
2811
|
+
}
|
|
2812
|
+
};
|
|
2813
|
+
const handleQuickChatClose = () => {
|
|
2814
|
+
setIsQuickChatPinned(false);
|
|
2815
|
+
try {
|
|
2816
|
+
sessionStorage.removeItem("anyclick-quick-chat-pinned");
|
|
2817
|
+
} catch {
|
|
2818
|
+
}
|
|
2819
|
+
setCurrentView("menu");
|
|
2820
|
+
};
|
|
2821
|
+
const containerWidth = currentView === "screenshot-preview" ? 360 : currentView === "quick-chat" && !isQuickChatPinned ? 320 : void 0;
|
|
2822
|
+
const showPinnedDrawer = isQuickChatPinned && quickChatConfig;
|
|
2823
|
+
const showMenu = visible && targetElement;
|
|
2824
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
2825
|
+
showPinnedDrawer && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2826
|
+
QuickChat,
|
|
2827
|
+
{
|
|
2828
|
+
visible: true,
|
|
2829
|
+
targetElement,
|
|
2830
|
+
containerElement,
|
|
2831
|
+
onClose: handleQuickChatClose,
|
|
2832
|
+
onPin: handleQuickChatPin,
|
|
2833
|
+
isPinned: true,
|
|
2834
|
+
config: quickChatConfig
|
|
2835
|
+
}
|
|
2836
|
+
),
|
|
2837
|
+
showMenu && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2838
|
+
"div",
|
|
2839
|
+
{
|
|
2840
|
+
ref: menuRef,
|
|
2841
|
+
"aria-label": "Feedback options",
|
|
2842
|
+
className,
|
|
2843
|
+
role: "menu",
|
|
2844
|
+
style: {
|
|
2845
|
+
...menuStyles.container,
|
|
2846
|
+
left: adjustedPosition.x,
|
|
2847
|
+
top: adjustedPosition.y,
|
|
2848
|
+
...containerWidth ? { minWidth: containerWidth, width: containerWidth } : {},
|
|
2849
|
+
touchAction: "none",
|
|
2850
|
+
userSelect: "none",
|
|
2851
|
+
WebkitTouchCallout: "none",
|
|
2852
|
+
WebkitUserSelect: "none",
|
|
2853
|
+
...isDragging ? { cursor: "grabbing" } : {},
|
|
2854
|
+
...style
|
|
2855
|
+
},
|
|
2856
|
+
children: [
|
|
2857
|
+
!header && currentView !== "screenshot-preview" && currentView !== "quick-chat" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(DefaultHeader, { styles: menuStyles.header, title: "Send Feedback", children: [
|
|
2858
|
+
positionMode === "dynamic" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2859
|
+
"div",
|
|
2860
|
+
{
|
|
2861
|
+
"data-drag-handle": true,
|
|
2862
|
+
onMouseEnter: (e) => {
|
|
2863
|
+
e.currentTarget.style.opacity = "1";
|
|
2864
|
+
},
|
|
2865
|
+
onMouseLeave: (e) => {
|
|
2866
|
+
e.currentTarget.style.opacity = "0.5";
|
|
2867
|
+
},
|
|
2868
|
+
onPointerDown: handleDragStart,
|
|
2869
|
+
style: {
|
|
2870
|
+
...menuStyles.dragHandle,
|
|
2871
|
+
cursor: isDragging ? "grabbing" : "grab"
|
|
2872
|
+
},
|
|
2873
|
+
title: "Drag to move",
|
|
2874
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react3.GripVertical, { className: "w-4 h-4" })
|
|
2875
|
+
}
|
|
2876
|
+
),
|
|
2877
|
+
showPreview && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: menuStyles.screenshotIndicator, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react3.CameraIcon, { className: "w-3 h-3" }) }),
|
|
2878
|
+
quickChatConfig && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2879
|
+
"button",
|
|
2880
|
+
{
|
|
2881
|
+
type: "button",
|
|
2882
|
+
onClick: handleQuickChatToggle,
|
|
2883
|
+
style: {
|
|
2884
|
+
display: "flex",
|
|
2885
|
+
alignItems: "center",
|
|
2886
|
+
justifyContent: "center",
|
|
2887
|
+
width: "24px",
|
|
2888
|
+
height: "24px",
|
|
2889
|
+
border: "none",
|
|
2890
|
+
borderRadius: "4px",
|
|
2891
|
+
backgroundColor: isQuickChatPinned ? "var(--anyclick-menu-accent, #0066cc)" : "transparent",
|
|
2892
|
+
color: isQuickChatPinned ? "#fff" : "var(--anyclick-menu-accent, #0066cc)",
|
|
2893
|
+
cursor: "pointer",
|
|
2894
|
+
transition: "all 0.15s ease"
|
|
2895
|
+
},
|
|
2896
|
+
title: isQuickChatPinned ? "Quick Chat (pinned)" : "Quick Ask AI",
|
|
2897
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react3.Sparkles, { className: "w-3.5 h-3.5" })
|
|
2898
|
+
}
|
|
2899
|
+
)
|
|
2900
|
+
] }),
|
|
2901
|
+
!!header && header,
|
|
2902
|
+
currentView === "menu" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: menuStyles.itemList, children: [
|
|
2903
|
+
submenuStack.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(BackButton, { onClick: handleBack }),
|
|
2904
|
+
currentItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2905
|
+
MenuItem,
|
|
2906
|
+
{
|
|
2907
|
+
disabled: isSubmitting,
|
|
2908
|
+
hasChildren: item.children && item.children.length > 0,
|
|
2909
|
+
item,
|
|
2910
|
+
onClick: () => handleItemClick(item)
|
|
1466
2911
|
},
|
|
1467
|
-
|
|
1468
|
-
|
|
2912
|
+
item.type
|
|
2913
|
+
))
|
|
2914
|
+
] }),
|
|
2915
|
+
currentView === "comment" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2916
|
+
CommentForm,
|
|
2917
|
+
{
|
|
2918
|
+
isSubmitting,
|
|
2919
|
+
onCancel: handleCommentCancel,
|
|
2920
|
+
onSubmit: handleCommentSubmit
|
|
1469
2921
|
}
|
|
1470
|
-
)
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
currentView === "menu" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: menuStyles.itemList, children: [
|
|
1474
|
-
submenuStack.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BackButton, { onClick: handleBack }),
|
|
1475
|
-
currentItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1476
|
-
MenuItem,
|
|
2922
|
+
),
|
|
2923
|
+
currentView === "screenshot-preview" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2924
|
+
ScreenshotPreview,
|
|
1477
2925
|
{
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
)
|
|
1505
|
-
]
|
|
1506
|
-
}
|
|
1507
|
-
);
|
|
2926
|
+
isLoading: isCapturing,
|
|
2927
|
+
isSubmitting,
|
|
2928
|
+
onCancel: handleScreenshotCancel,
|
|
2929
|
+
onConfirm: handleScreenshotConfirm,
|
|
2930
|
+
onRetake: handleRetakeScreenshots,
|
|
2931
|
+
screenshots
|
|
2932
|
+
}
|
|
2933
|
+
),
|
|
2934
|
+
currentView === "quick-chat" && quickChatConfig && !isQuickChatPinned && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2935
|
+
QuickChat,
|
|
2936
|
+
{
|
|
2937
|
+
visible: true,
|
|
2938
|
+
targetElement,
|
|
2939
|
+
containerElement,
|
|
2940
|
+
onClose: handleQuickChatClose,
|
|
2941
|
+
onPin: handleQuickChatPin,
|
|
2942
|
+
isPinned: false,
|
|
2943
|
+
config: quickChatConfig,
|
|
2944
|
+
initialInput: initialChatInput,
|
|
2945
|
+
onInitialInputConsumed: () => setInitialChatInput("")
|
|
2946
|
+
}
|
|
2947
|
+
)
|
|
2948
|
+
]
|
|
2949
|
+
}
|
|
2950
|
+
)
|
|
2951
|
+
] });
|
|
1508
2952
|
}
|
|
1509
2953
|
|
|
1510
2954
|
// src/context.ts
|
|
1511
|
-
var
|
|
1512
|
-
var AnyclickContext = (0,
|
|
2955
|
+
var import_react5 = require("react");
|
|
2956
|
+
var AnyclickContext = (0, import_react5.createContext)(null);
|
|
1513
2957
|
var FeedbackContext = AnyclickContext;
|
|
1514
2958
|
function useAnyclick() {
|
|
1515
|
-
const context = (0,
|
|
2959
|
+
const context = (0, import_react5.useContext)(AnyclickContext);
|
|
1516
2960
|
if (!context) {
|
|
1517
2961
|
throw new Error("useAnyclick must be used within an AnyclickProvider");
|
|
1518
2962
|
}
|
|
1519
2963
|
return context;
|
|
1520
2964
|
}
|
|
1521
2965
|
function useFeedback() {
|
|
1522
|
-
const context = (0,
|
|
2966
|
+
const context = (0, import_react5.useContext)(AnyclickContext);
|
|
1523
2967
|
if (!context) {
|
|
1524
2968
|
throw new Error("useFeedback must be used within a FeedbackProvider");
|
|
1525
2969
|
}
|
|
@@ -1688,7 +3132,7 @@ function dispatchContextMenuEvent(event, element) {
|
|
|
1688
3132
|
}
|
|
1689
3133
|
|
|
1690
3134
|
// src/AnyclickProvider.tsx
|
|
1691
|
-
var
|
|
3135
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1692
3136
|
var defaultMenuItems = [
|
|
1693
3137
|
{ label: "Report an issue", showComment: true, type: "issue" },
|
|
1694
3138
|
{ label: "Request a feature", showComment: true, type: "feature" },
|
|
@@ -1711,6 +3155,7 @@ function AnyclickProvider({
|
|
|
1711
3155
|
metadata,
|
|
1712
3156
|
onSubmitError,
|
|
1713
3157
|
onSubmitSuccess,
|
|
3158
|
+
quickChatConfig,
|
|
1714
3159
|
scoped = false,
|
|
1715
3160
|
screenshotConfig,
|
|
1716
3161
|
stripAttributes,
|
|
@@ -1719,18 +3164,18 @@ function AnyclickProvider({
|
|
|
1719
3164
|
touchHoldDurationMs,
|
|
1720
3165
|
touchMoveThreshold
|
|
1721
3166
|
}) {
|
|
1722
|
-
const [isSubmitting, setIsSubmitting] = (0,
|
|
1723
|
-
const [menuVisible, setMenuVisible] = (0,
|
|
1724
|
-
const [menuPosition, setMenuPosition] = (0,
|
|
1725
|
-
const [targetElement, setTargetElement] = (0,
|
|
1726
|
-
const [containerElement, setContainerElement] = (0,
|
|
3167
|
+
const [isSubmitting, setIsSubmitting] = (0, import_react6.useState)(false);
|
|
3168
|
+
const [menuVisible, setMenuVisible] = (0, import_react6.useState)(false);
|
|
3169
|
+
const [menuPosition, setMenuPosition] = (0, import_react6.useState)(OFFSCREEN_POSITION2);
|
|
3170
|
+
const [targetElement, setTargetElement] = (0, import_react6.useState)(null);
|
|
3171
|
+
const [containerElement, setContainerElement] = (0, import_react6.useState)(
|
|
1727
3172
|
null
|
|
1728
3173
|
);
|
|
1729
|
-
const providerId = (0,
|
|
1730
|
-
const containerRef = (0,
|
|
1731
|
-
const [containerReady, setContainerReady] = (0,
|
|
1732
|
-
const clientRef = (0,
|
|
1733
|
-
const setContainerRef = (0,
|
|
3174
|
+
const providerId = (0, import_react6.useId)();
|
|
3175
|
+
const containerRef = (0, import_react6.useRef)(null);
|
|
3176
|
+
const [containerReady, setContainerReady] = (0, import_react6.useState)(!scoped);
|
|
3177
|
+
const clientRef = (0, import_react6.useRef)(null);
|
|
3178
|
+
const setContainerRef = (0, import_react6.useCallback)(
|
|
1734
3179
|
(node) => {
|
|
1735
3180
|
containerRef.current = node;
|
|
1736
3181
|
if (scoped && node) {
|
|
@@ -1759,7 +3204,7 @@ function AnyclickProvider({
|
|
|
1759
3204
|
updateProvider
|
|
1760
3205
|
} = useProviderStore();
|
|
1761
3206
|
const parentId = parentContext?.providerId ?? null;
|
|
1762
|
-
const actualDepth = (0,
|
|
3207
|
+
const actualDepth = (0, import_react6.useMemo)(() => {
|
|
1763
3208
|
if (!parentContext) return 0;
|
|
1764
3209
|
let d = 0;
|
|
1765
3210
|
let currentId = parentId;
|
|
@@ -1773,7 +3218,7 @@ function AnyclickProvider({
|
|
|
1773
3218
|
}, [parentContext, parentId]);
|
|
1774
3219
|
const isDisabledByTheme = theme === null || theme?.disabled === true;
|
|
1775
3220
|
const effectiveDisabled = disabled || isDisabledByTheme;
|
|
1776
|
-
const localTheme = (0,
|
|
3221
|
+
const localTheme = (0, import_react6.useMemo)(() => {
|
|
1777
3222
|
if (theme === null) {
|
|
1778
3223
|
return { disabled: true };
|
|
1779
3224
|
}
|
|
@@ -1788,7 +3233,7 @@ function AnyclickProvider({
|
|
|
1788
3233
|
...theme
|
|
1789
3234
|
};
|
|
1790
3235
|
}, [highlightConfig, menuClassName, menuStyle, screenshotConfig, theme]);
|
|
1791
|
-
const handleContextMenu = (0,
|
|
3236
|
+
const handleContextMenu = (0, import_react6.useCallback)(
|
|
1792
3237
|
(event, element) => {
|
|
1793
3238
|
if (!scoped && isElementInDisabledScope(element)) {
|
|
1794
3239
|
return false;
|
|
@@ -1816,7 +3261,7 @@ function AnyclickProvider({
|
|
|
1816
3261
|
scoped
|
|
1817
3262
|
]
|
|
1818
3263
|
);
|
|
1819
|
-
(0,
|
|
3264
|
+
(0, import_react6.useLayoutEffect)(() => {
|
|
1820
3265
|
const providerInstance = {
|
|
1821
3266
|
containerRef,
|
|
1822
3267
|
depth: actualDepth,
|
|
@@ -1842,7 +3287,7 @@ function AnyclickProvider({
|
|
|
1842
3287
|
scoped,
|
|
1843
3288
|
unregisterProvider
|
|
1844
3289
|
]);
|
|
1845
|
-
(0,
|
|
3290
|
+
(0, import_react6.useEffect)(() => {
|
|
1846
3291
|
updateProvider(providerId, {
|
|
1847
3292
|
disabled: effectiveDisabled,
|
|
1848
3293
|
onContextMenu: handleContextMenu,
|
|
@@ -1855,14 +3300,14 @@ function AnyclickProvider({
|
|
|
1855
3300
|
providerId,
|
|
1856
3301
|
updateProvider
|
|
1857
3302
|
]);
|
|
1858
|
-
(0,
|
|
3303
|
+
(0, import_react6.useEffect)(() => {
|
|
1859
3304
|
if (isDisabledByAncestor(providerId)) {
|
|
1860
3305
|
return;
|
|
1861
3306
|
}
|
|
1862
3307
|
if (scoped && !containerReady) {
|
|
1863
3308
|
return;
|
|
1864
3309
|
}
|
|
1865
|
-
const client = (0,
|
|
3310
|
+
const client = (0, import_anyclick_core4.createAnyclickClient)({
|
|
1866
3311
|
adapter,
|
|
1867
3312
|
container: scoped ? containerRef.current : null,
|
|
1868
3313
|
cooldownMs,
|
|
@@ -1903,7 +3348,7 @@ function AnyclickProvider({
|
|
|
1903
3348
|
touchHoldDurationMs,
|
|
1904
3349
|
touchMoveThreshold
|
|
1905
3350
|
]);
|
|
1906
|
-
const submitAnyclick = (0,
|
|
3351
|
+
const submitAnyclick = (0, import_react6.useCallback)(
|
|
1907
3352
|
async (element, type, comment, screenshots) => {
|
|
1908
3353
|
const client = clientRef.current;
|
|
1909
3354
|
if (!client) return;
|
|
@@ -1924,7 +3369,7 @@ function AnyclickProvider({
|
|
|
1924
3369
|
},
|
|
1925
3370
|
[metadata]
|
|
1926
3371
|
);
|
|
1927
|
-
const openMenu = (0,
|
|
3372
|
+
const openMenu = (0, import_react6.useCallback)(
|
|
1928
3373
|
(element, position) => {
|
|
1929
3374
|
setTargetElement(element);
|
|
1930
3375
|
const mergedTheme2 = getMergedTheme(providerId);
|
|
@@ -1938,13 +3383,13 @@ function AnyclickProvider({
|
|
|
1938
3383
|
},
|
|
1939
3384
|
[getMergedTheme, highlightConfig, providerId]
|
|
1940
3385
|
);
|
|
1941
|
-
const closeMenu = (0,
|
|
3386
|
+
const closeMenu = (0, import_react6.useCallback)(() => {
|
|
1942
3387
|
setMenuVisible(false);
|
|
1943
3388
|
setMenuPosition(OFFSCREEN_POSITION2);
|
|
1944
3389
|
setTargetElement(null);
|
|
1945
3390
|
setContainerElement(null);
|
|
1946
3391
|
}, []);
|
|
1947
|
-
const handleMenuSelect = (0,
|
|
3392
|
+
const handleMenuSelect = (0, import_react6.useCallback)(
|
|
1948
3393
|
(type, comment, screenshots) => {
|
|
1949
3394
|
if (targetElement) {
|
|
1950
3395
|
submitAnyclick(targetElement, type, comment, screenshots);
|
|
@@ -1953,7 +3398,7 @@ function AnyclickProvider({
|
|
|
1953
3398
|
[submitAnyclick, targetElement]
|
|
1954
3399
|
);
|
|
1955
3400
|
const inheritedTheme = getMergedTheme(providerId);
|
|
1956
|
-
const mergedTheme = (0,
|
|
3401
|
+
const mergedTheme = (0, import_react6.useMemo)(
|
|
1957
3402
|
() => ({
|
|
1958
3403
|
...inheritedTheme,
|
|
1959
3404
|
...localTheme,
|
|
@@ -1976,7 +3421,7 @@ function AnyclickProvider({
|
|
|
1976
3421
|
const effectiveMenuClassName = mergedTheme.menuClassName ?? menuClassName;
|
|
1977
3422
|
const effectiveHighlightConfig = mergedTheme.highlightConfig ?? highlightConfig;
|
|
1978
3423
|
const effectiveScreenshotConfig = mergedTheme.screenshotConfig ?? screenshotConfig;
|
|
1979
|
-
const contextValue = (0,
|
|
3424
|
+
const contextValue = (0, import_react6.useMemo)(
|
|
1980
3425
|
() => ({
|
|
1981
3426
|
closeMenu,
|
|
1982
3427
|
isEnabled: !effectiveDisabled && !isDisabledByAncestor(providerId),
|
|
@@ -1999,7 +3444,7 @@ function AnyclickProvider({
|
|
|
1999
3444
|
submitAnyclick
|
|
2000
3445
|
]
|
|
2001
3446
|
);
|
|
2002
|
-
const content = scoped ? /* @__PURE__ */ (0,
|
|
3447
|
+
const content = scoped ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2003
3448
|
"div",
|
|
2004
3449
|
{
|
|
2005
3450
|
ref: setContainerRef,
|
|
@@ -2008,9 +3453,9 @@ function AnyclickProvider({
|
|
|
2008
3453
|
children
|
|
2009
3454
|
}
|
|
2010
3455
|
) : children;
|
|
2011
|
-
return /* @__PURE__ */ (0,
|
|
3456
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(AnyclickContext.Provider, { value: contextValue, children: [
|
|
2012
3457
|
content,
|
|
2013
|
-
/* @__PURE__ */ (0,
|
|
3458
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2014
3459
|
ContextMenu,
|
|
2015
3460
|
{
|
|
2016
3461
|
className: effectiveMenuClassName,
|
|
@@ -2022,6 +3467,7 @@ function AnyclickProvider({
|
|
|
2022
3467
|
onClose: closeMenu,
|
|
2023
3468
|
onSelect: handleMenuSelect,
|
|
2024
3469
|
position: menuPosition,
|
|
3470
|
+
quickChatConfig,
|
|
2025
3471
|
screenshotConfig: effectiveScreenshotConfig,
|
|
2026
3472
|
style: effectiveMenuStyle,
|
|
2027
3473
|
targetElement,
|
|
@@ -2033,7 +3479,7 @@ function AnyclickProvider({
|
|
|
2033
3479
|
var FeedbackProvider = AnyclickProvider;
|
|
2034
3480
|
|
|
2035
3481
|
// src/FunModeBridge.tsx
|
|
2036
|
-
var
|
|
3482
|
+
var import_react7 = require("react");
|
|
2037
3483
|
var import_anyclick_pointer = require("@ewjdev/anyclick-pointer");
|
|
2038
3484
|
function isFunModeEnabled(theme) {
|
|
2039
3485
|
if (!theme) return false;
|
|
@@ -2080,9 +3526,9 @@ function buildFunConfig(theme, container) {
|
|
|
2080
3526
|
function FunModeBridge() {
|
|
2081
3527
|
const { setConfig } = (0, import_anyclick_pointer.usePointer)();
|
|
2082
3528
|
const providerStore = useProviderStore();
|
|
2083
|
-
const activeProviderRef = (0,
|
|
2084
|
-
const cachedConfigs = (0,
|
|
2085
|
-
const findActiveFunProvider = (0,
|
|
3529
|
+
const activeProviderRef = (0, import_react7.useRef)(null);
|
|
3530
|
+
const cachedConfigs = (0, import_react7.useRef)({});
|
|
3531
|
+
const findActiveFunProvider = (0, import_react7.useMemo)(() => {
|
|
2086
3532
|
return (el) => {
|
|
2087
3533
|
if (!el) return null;
|
|
2088
3534
|
const providers = providerStore.findProvidersForElement(el);
|
|
@@ -2094,7 +3540,7 @@ function FunModeBridge() {
|
|
|
2094
3540
|
return null;
|
|
2095
3541
|
};
|
|
2096
3542
|
}, [providerStore]);
|
|
2097
|
-
(0,
|
|
3543
|
+
(0, import_react7.useEffect)(() => {
|
|
2098
3544
|
const handleMove = (event) => {
|
|
2099
3545
|
const el = document.elementFromPoint(event.clientX, event.clientY);
|
|
2100
3546
|
const provider = findActiveFunProvider(el);
|
|
@@ -2129,12 +3575,12 @@ function FunModeBridge() {
|
|
|
2129
3575
|
}
|
|
2130
3576
|
|
|
2131
3577
|
// src/InspectDialog/InspectDialogManager.tsx
|
|
2132
|
-
var
|
|
3578
|
+
var import_react9 = require("react");
|
|
2133
3579
|
|
|
2134
3580
|
// src/InspectDialog/InspectSimple.tsx
|
|
2135
|
-
var
|
|
2136
|
-
var
|
|
2137
|
-
var
|
|
3581
|
+
var import_react8 = require("react");
|
|
3582
|
+
var import_anyclick_core5 = require("@ewjdev/anyclick-core");
|
|
3583
|
+
var import_lucide_react4 = require("lucide-react");
|
|
2138
3584
|
|
|
2139
3585
|
// src/ide.ts
|
|
2140
3586
|
var DEFAULT_IDE_CONFIG = {
|
|
@@ -2236,7 +3682,7 @@ function formatSourceLocation(location) {
|
|
|
2236
3682
|
}
|
|
2237
3683
|
|
|
2238
3684
|
// src/InspectDialog/InspectSimple.tsx
|
|
2239
|
-
var
|
|
3685
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
2240
3686
|
var DEFAULT_COMPACT_CONFIG = {
|
|
2241
3687
|
scale: 0.5,
|
|
2242
3688
|
fonts: {
|
|
@@ -2298,8 +3744,8 @@ function downloadDataUrl(dataUrl, filename) {
|
|
|
2298
3744
|
link.click();
|
|
2299
3745
|
}
|
|
2300
3746
|
function useIsMobile() {
|
|
2301
|
-
const [isMobile, setIsMobile] = (0,
|
|
2302
|
-
(0,
|
|
3747
|
+
const [isMobile, setIsMobile] = (0, import_react8.useState)(false);
|
|
3748
|
+
(0, import_react8.useEffect)(() => {
|
|
2303
3749
|
const mq = window.matchMedia("(max-width: 640px)");
|
|
2304
3750
|
setIsMobile(mq.matches);
|
|
2305
3751
|
const handler = (e) => setIsMobile(e.matches);
|
|
@@ -2317,20 +3763,20 @@ function InspectSimple({
|
|
|
2317
3763
|
className,
|
|
2318
3764
|
highlightColors
|
|
2319
3765
|
}) {
|
|
2320
|
-
const [info, setInfo] = (0,
|
|
2321
|
-
const [sourceLocation, setSourceLocation] = (0,
|
|
3766
|
+
const [info, setInfo] = (0, import_react8.useState)(null);
|
|
3767
|
+
const [sourceLocation, setSourceLocation] = (0, import_react8.useState)(
|
|
2322
3768
|
null
|
|
2323
3769
|
);
|
|
2324
|
-
const [status, setStatus] = (0,
|
|
2325
|
-
const [saving, setSaving] = (0,
|
|
2326
|
-
const dialogRef = (0,
|
|
3770
|
+
const [status, setStatus] = (0, import_react8.useState)(null);
|
|
3771
|
+
const [saving, setSaving] = (0, import_react8.useState)(false);
|
|
3772
|
+
const dialogRef = (0, import_react8.useRef)(null);
|
|
2327
3773
|
const isMobile = useIsMobile();
|
|
2328
|
-
(0,
|
|
3774
|
+
(0, import_react8.useEffect)(() => {
|
|
2329
3775
|
if (!status) return;
|
|
2330
3776
|
const timer = setTimeout(() => setStatus(null), 5e3);
|
|
2331
3777
|
return () => clearTimeout(timer);
|
|
2332
3778
|
}, [status]);
|
|
2333
|
-
(0,
|
|
3779
|
+
(0, import_react8.useEffect)(() => {
|
|
2334
3780
|
if (!visible || !targetElement) return;
|
|
2335
3781
|
try {
|
|
2336
3782
|
clearHighlights();
|
|
@@ -2339,7 +3785,7 @@ function InspectSimple({
|
|
|
2339
3785
|
if (container) highlightContainer(container, highlightColors);
|
|
2340
3786
|
} catch {
|
|
2341
3787
|
}
|
|
2342
|
-
const nextInfo = (0,
|
|
3788
|
+
const nextInfo = (0, import_anyclick_core5.getElementInspectInfo)(targetElement);
|
|
2343
3789
|
setInfo(nextInfo);
|
|
2344
3790
|
setSourceLocation(
|
|
2345
3791
|
findSourceLocationInAncestors(targetElement) ?? nextInfo.sourceLocation ?? null
|
|
@@ -2348,7 +3794,7 @@ function InspectSimple({
|
|
|
2348
3794
|
clearHighlights();
|
|
2349
3795
|
};
|
|
2350
3796
|
}, [visible, targetElement, highlightColors]);
|
|
2351
|
-
(0,
|
|
3797
|
+
(0, import_react8.useEffect)(() => {
|
|
2352
3798
|
if (!visible) return;
|
|
2353
3799
|
const handleClickOutside = (e) => {
|
|
2354
3800
|
if (dialogRef.current && !dialogRef.current.contains(e.target)) {
|
|
@@ -2363,7 +3809,7 @@ function InspectSimple({
|
|
|
2363
3809
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
2364
3810
|
};
|
|
2365
3811
|
}, [visible, onClose]);
|
|
2366
|
-
const identityLabel = (0,
|
|
3812
|
+
const identityLabel = (0, import_react8.useMemo)(() => {
|
|
2367
3813
|
if (!info) return "Select an element";
|
|
2368
3814
|
const classes = info.classNames[0] ? `.${info.classNames[0]}` : "";
|
|
2369
3815
|
const id = info.id ? `#${info.id}` : "";
|
|
@@ -2393,7 +3839,7 @@ function InspectSimple({
|
|
|
2393
3839
|
if (!targetElement) return;
|
|
2394
3840
|
setSaving(true);
|
|
2395
3841
|
setStatus("Capturing screenshot\u2026");
|
|
2396
|
-
const result = await (0,
|
|
3842
|
+
const result = await (0, import_anyclick_core5.captureScreenshot)(targetElement, null, "element");
|
|
2397
3843
|
setSaving(false);
|
|
2398
3844
|
if (result.capture?.dataUrl) {
|
|
2399
3845
|
downloadDataUrl(result.capture.dataUrl, "anyclick-inspect.png");
|
|
@@ -2449,8 +3895,8 @@ function InspectSimple({
|
|
|
2449
3895
|
overflow: "hidden",
|
|
2450
3896
|
...style
|
|
2451
3897
|
};
|
|
2452
|
-
return /* @__PURE__ */ (0,
|
|
2453
|
-
/* @__PURE__ */ (0,
|
|
3898
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
3899
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2454
3900
|
"div",
|
|
2455
3901
|
{
|
|
2456
3902
|
style: {
|
|
@@ -2465,14 +3911,14 @@ function InspectSimple({
|
|
|
2465
3911
|
role: "presentation"
|
|
2466
3912
|
}
|
|
2467
3913
|
),
|
|
2468
|
-
/* @__PURE__ */ (0,
|
|
3914
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2469
3915
|
"div",
|
|
2470
3916
|
{
|
|
2471
3917
|
ref: dialogRef,
|
|
2472
3918
|
className: `anyclick-tiny-inspect ${className ?? ""}`,
|
|
2473
3919
|
style: dialogStyles,
|
|
2474
3920
|
children: [
|
|
2475
|
-
/* @__PURE__ */ (0,
|
|
3921
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2476
3922
|
"div",
|
|
2477
3923
|
{
|
|
2478
3924
|
style: {
|
|
@@ -2484,7 +3930,7 @@ function InspectSimple({
|
|
|
2484
3930
|
borderBottom: "1px solid #1e293b"
|
|
2485
3931
|
},
|
|
2486
3932
|
children: [
|
|
2487
|
-
isMobile && /* @__PURE__ */ (0,
|
|
3933
|
+
isMobile && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2488
3934
|
"div",
|
|
2489
3935
|
{
|
|
2490
3936
|
style: {
|
|
@@ -2499,8 +3945,8 @@ function InspectSimple({
|
|
|
2499
3945
|
}
|
|
2500
3946
|
}
|
|
2501
3947
|
),
|
|
2502
|
-
/* @__PURE__ */ (0,
|
|
2503
|
-
/* @__PURE__ */ (0,
|
|
3948
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
3949
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2504
3950
|
"span",
|
|
2505
3951
|
{
|
|
2506
3952
|
style: {
|
|
@@ -2515,31 +3961,31 @@ function InspectSimple({
|
|
|
2515
3961
|
children: identityLabel
|
|
2516
3962
|
}
|
|
2517
3963
|
),
|
|
2518
|
-
sourceLocation && /* @__PURE__ */ (0,
|
|
3964
|
+
sourceLocation && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2519
3965
|
"button",
|
|
2520
3966
|
{
|
|
2521
3967
|
type: "button",
|
|
2522
3968
|
onClick: handleOpenIDE,
|
|
2523
3969
|
title: formatSourceLocation(sourceLocation),
|
|
2524
3970
|
style: iconBtnStyle,
|
|
2525
|
-
children: /* @__PURE__ */ (0,
|
|
3971
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.ExternalLink, { size: 14 })
|
|
2526
3972
|
}
|
|
2527
3973
|
)
|
|
2528
3974
|
] }),
|
|
2529
|
-
/* @__PURE__ */ (0,
|
|
3975
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2530
3976
|
"button",
|
|
2531
3977
|
{
|
|
2532
3978
|
type: "button",
|
|
2533
3979
|
onClick: onClose,
|
|
2534
3980
|
style: iconBtnStyle,
|
|
2535
3981
|
"aria-label": "Close inspector",
|
|
2536
|
-
children: /* @__PURE__ */ (0,
|
|
3982
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.X, { size: 16 })
|
|
2537
3983
|
}
|
|
2538
3984
|
)
|
|
2539
3985
|
]
|
|
2540
3986
|
}
|
|
2541
3987
|
),
|
|
2542
|
-
/* @__PURE__ */ (0,
|
|
3988
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2543
3989
|
"div",
|
|
2544
3990
|
{
|
|
2545
3991
|
style: {
|
|
@@ -2549,7 +3995,7 @@ function InspectSimple({
|
|
|
2549
3995
|
gap: 8
|
|
2550
3996
|
},
|
|
2551
3997
|
children: [
|
|
2552
|
-
info?.selector && /* @__PURE__ */ (0,
|
|
3998
|
+
info?.selector && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2553
3999
|
"code",
|
|
2554
4000
|
{
|
|
2555
4001
|
style: {
|
|
@@ -2564,7 +4010,7 @@ function InspectSimple({
|
|
|
2564
4010
|
children: info.selector
|
|
2565
4011
|
}
|
|
2566
4012
|
),
|
|
2567
|
-
status && /* @__PURE__ */ (0,
|
|
4013
|
+
status && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2568
4014
|
"div",
|
|
2569
4015
|
{
|
|
2570
4016
|
style: {
|
|
@@ -2576,7 +4022,7 @@ function InspectSimple({
|
|
|
2576
4022
|
children: status
|
|
2577
4023
|
}
|
|
2578
4024
|
),
|
|
2579
|
-
/* @__PURE__ */ (0,
|
|
4025
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2580
4026
|
"div",
|
|
2581
4027
|
{
|
|
2582
4028
|
style: {
|
|
@@ -2585,7 +4031,7 @@ function InspectSimple({
|
|
|
2585
4031
|
gap: 6
|
|
2586
4032
|
},
|
|
2587
4033
|
children: [
|
|
2588
|
-
/* @__PURE__ */ (0,
|
|
4034
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2589
4035
|
"button",
|
|
2590
4036
|
{
|
|
2591
4037
|
type: "button",
|
|
@@ -2593,10 +4039,10 @@ function InspectSimple({
|
|
|
2593
4039
|
style: iconActionStyle,
|
|
2594
4040
|
title: "Copy CSS selector",
|
|
2595
4041
|
"aria-label": "Copy CSS selector",
|
|
2596
|
-
children: /* @__PURE__ */ (0,
|
|
4042
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Copy, { size: 15 })
|
|
2597
4043
|
}
|
|
2598
4044
|
),
|
|
2599
|
-
/* @__PURE__ */ (0,
|
|
4045
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2600
4046
|
"button",
|
|
2601
4047
|
{
|
|
2602
4048
|
type: "button",
|
|
@@ -2604,10 +4050,10 @@ function InspectSimple({
|
|
|
2604
4050
|
style: iconActionStyle,
|
|
2605
4051
|
title: "Copy text content",
|
|
2606
4052
|
"aria-label": "Copy text content",
|
|
2607
|
-
children: /* @__PURE__ */ (0,
|
|
4053
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.FileText, { size: 15 })
|
|
2608
4054
|
}
|
|
2609
4055
|
),
|
|
2610
|
-
/* @__PURE__ */ (0,
|
|
4056
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2611
4057
|
"button",
|
|
2612
4058
|
{
|
|
2613
4059
|
type: "button",
|
|
@@ -2615,10 +4061,10 @@ function InspectSimple({
|
|
|
2615
4061
|
style: iconActionStyle,
|
|
2616
4062
|
title: "Copy HTML markup",
|
|
2617
4063
|
"aria-label": "Copy HTML markup",
|
|
2618
|
-
children: /* @__PURE__ */ (0,
|
|
4064
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Code, { size: 15 })
|
|
2619
4065
|
}
|
|
2620
4066
|
),
|
|
2621
|
-
/* @__PURE__ */ (0,
|
|
4067
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2622
4068
|
"button",
|
|
2623
4069
|
{
|
|
2624
4070
|
type: "button",
|
|
@@ -2630,7 +4076,7 @@ function InspectSimple({
|
|
|
2630
4076
|
disabled: saving,
|
|
2631
4077
|
title: "Save screenshot",
|
|
2632
4078
|
"aria-label": "Save screenshot",
|
|
2633
|
-
children: /* @__PURE__ */ (0,
|
|
4079
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Camera, { size: 15 })
|
|
2634
4080
|
}
|
|
2635
4081
|
)
|
|
2636
4082
|
]
|
|
@@ -2673,7 +4119,7 @@ var iconActionStyle = {
|
|
|
2673
4119
|
};
|
|
2674
4120
|
|
|
2675
4121
|
// src/InspectDialog/InspectDialogManager.tsx
|
|
2676
|
-
var
|
|
4122
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
2677
4123
|
var INSPECT_DIALOG_EVENT = "anyclick:inspect";
|
|
2678
4124
|
function openInspectDialog(targetElement) {
|
|
2679
4125
|
if (typeof window === "undefined") return;
|
|
@@ -2696,16 +4142,16 @@ function InspectDialogManager({
|
|
|
2696
4142
|
initialPinnedPosition = "floating",
|
|
2697
4143
|
compactConfig
|
|
2698
4144
|
}) {
|
|
2699
|
-
const [visible, setVisible] = (0,
|
|
2700
|
-
const [targetElement, setTargetElement] = (0,
|
|
2701
|
-
const handleClose = (0,
|
|
4145
|
+
const [visible, setVisible] = (0, import_react9.useState)(false);
|
|
4146
|
+
const [targetElement, setTargetElement] = (0, import_react9.useState)(null);
|
|
4147
|
+
const handleClose = (0, import_react9.useCallback)(() => {
|
|
2702
4148
|
setVisible(false);
|
|
2703
4149
|
setTargetElement(null);
|
|
2704
4150
|
}, []);
|
|
2705
|
-
const handleSelectElement = (0,
|
|
4151
|
+
const handleSelectElement = (0, import_react9.useCallback)((element) => {
|
|
2706
4152
|
setTargetElement(element);
|
|
2707
4153
|
}, []);
|
|
2708
|
-
(0,
|
|
4154
|
+
(0, import_react9.useEffect)(() => {
|
|
2709
4155
|
const handleInspectEvent = (event) => {
|
|
2710
4156
|
const customEvent = event;
|
|
2711
4157
|
if (customEvent.detail?.targetElement) {
|
|
@@ -2718,7 +4164,7 @@ function InspectDialogManager({
|
|
|
2718
4164
|
window.removeEventListener(INSPECT_DIALOG_EVENT, handleInspectEvent);
|
|
2719
4165
|
};
|
|
2720
4166
|
}, []);
|
|
2721
|
-
return /* @__PURE__ */ (0,
|
|
4167
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2722
4168
|
InspectSimple,
|
|
2723
4169
|
{
|
|
2724
4170
|
visible,
|
|
@@ -2780,6 +4226,20 @@ var presetDefaults = {
|
|
|
2780
4226
|
showComment: false,
|
|
2781
4227
|
type: "search_google"
|
|
2782
4228
|
},
|
|
4229
|
+
{
|
|
4230
|
+
label: "Ask t3.chat",
|
|
4231
|
+
onClick: ({ closeMenu }) => {
|
|
4232
|
+
closeMenu();
|
|
4233
|
+
if (typeof window === "undefined") return false;
|
|
4234
|
+
const selection = window.getSelection()?.toString().trim();
|
|
4235
|
+
const query = selection && selection.length > 0 ? selection : "";
|
|
4236
|
+
const url = query ? `https://t3.chat/?q=${encodeURIComponent(query)}` : "https://t3.chat";
|
|
4237
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
4238
|
+
return false;
|
|
4239
|
+
},
|
|
4240
|
+
showComment: false,
|
|
4241
|
+
type: "ask_t3chat"
|
|
4242
|
+
},
|
|
2783
4243
|
{
|
|
2784
4244
|
label: "Share\u2026",
|
|
2785
4245
|
onClick: async ({ closeMenu }) => {
|
|
@@ -3049,6 +4509,172 @@ function listPresets() {
|
|
|
3049
4509
|
}))
|
|
3050
4510
|
}));
|
|
3051
4511
|
}
|
|
4512
|
+
function createT3ChatMenuItem(options = {}) {
|
|
4513
|
+
const { label = "Ask t3.chat", baseUrl = "https://t3.chat" } = options;
|
|
4514
|
+
return {
|
|
4515
|
+
label,
|
|
4516
|
+
onClick: ({ closeMenu }) => {
|
|
4517
|
+
closeMenu();
|
|
4518
|
+
if (typeof window === "undefined") return false;
|
|
4519
|
+
const selection = window.getSelection()?.toString().trim();
|
|
4520
|
+
const query = selection && selection.length > 0 ? selection : "";
|
|
4521
|
+
const url = query ? `${baseUrl}/?q=${encodeURIComponent(query)}` : baseUrl;
|
|
4522
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
4523
|
+
return false;
|
|
4524
|
+
},
|
|
4525
|
+
showComment: false,
|
|
4526
|
+
type: "ask_t3chat"
|
|
4527
|
+
};
|
|
4528
|
+
}
|
|
4529
|
+
function getSelectedText() {
|
|
4530
|
+
if (typeof window === "undefined") return "";
|
|
4531
|
+
return window.getSelection()?.toString().trim() ?? "";
|
|
4532
|
+
}
|
|
4533
|
+
function hasTextSelection() {
|
|
4534
|
+
return getSelectedText().length > 0;
|
|
4535
|
+
}
|
|
4536
|
+
function detectImageElement(element) {
|
|
4537
|
+
if (!element) return { isImage: false };
|
|
4538
|
+
if (element.tagName === "IMG") {
|
|
4539
|
+
const img = element;
|
|
4540
|
+
return {
|
|
4541
|
+
isImage: true,
|
|
4542
|
+
src: img.src || img.currentSrc,
|
|
4543
|
+
type: "img"
|
|
4544
|
+
};
|
|
4545
|
+
}
|
|
4546
|
+
if (element.tagName === "PICTURE") {
|
|
4547
|
+
const img = element.querySelector("img");
|
|
4548
|
+
return {
|
|
4549
|
+
isImage: true,
|
|
4550
|
+
src: img?.src || img?.currentSrc,
|
|
4551
|
+
type: "picture"
|
|
4552
|
+
};
|
|
4553
|
+
}
|
|
4554
|
+
if (element.tagName === "SVG" || element.tagName === "svg") {
|
|
4555
|
+
return {
|
|
4556
|
+
isImage: true,
|
|
4557
|
+
type: "svg"
|
|
4558
|
+
};
|
|
4559
|
+
}
|
|
4560
|
+
if (element.tagName === "CANVAS") {
|
|
4561
|
+
return {
|
|
4562
|
+
isImage: true,
|
|
4563
|
+
type: "canvas"
|
|
4564
|
+
};
|
|
4565
|
+
}
|
|
4566
|
+
if (typeof window !== "undefined") {
|
|
4567
|
+
const computedStyle = window.getComputedStyle(element);
|
|
4568
|
+
const backgroundImage = computedStyle.backgroundImage;
|
|
4569
|
+
if (backgroundImage && backgroundImage !== "none") {
|
|
4570
|
+
const urlMatch = backgroundImage.match(/url\(["']?(.+?)["']?\)/);
|
|
4571
|
+
if (urlMatch) {
|
|
4572
|
+
return {
|
|
4573
|
+
isImage: true,
|
|
4574
|
+
src: urlMatch[1],
|
|
4575
|
+
type: "background"
|
|
4576
|
+
};
|
|
4577
|
+
}
|
|
4578
|
+
}
|
|
4579
|
+
}
|
|
4580
|
+
const imgChild = element.querySelector("img");
|
|
4581
|
+
if (imgChild) {
|
|
4582
|
+
return {
|
|
4583
|
+
isImage: true,
|
|
4584
|
+
src: imgChild.src || imgChild.currentSrc,
|
|
4585
|
+
type: "img"
|
|
4586
|
+
};
|
|
4587
|
+
}
|
|
4588
|
+
return { isImage: false };
|
|
4589
|
+
}
|
|
4590
|
+
function createUploadThingMenuItem(options = {}) {
|
|
4591
|
+
const {
|
|
4592
|
+
label = "Upload to UploadThing",
|
|
4593
|
+
endpoint = "/api/uploadthing",
|
|
4594
|
+
onUploadComplete,
|
|
4595
|
+
onUploadError
|
|
4596
|
+
} = options;
|
|
4597
|
+
return {
|
|
4598
|
+
label,
|
|
4599
|
+
onClick: async ({ closeMenu, targetElement }) => {
|
|
4600
|
+
if (!targetElement) {
|
|
4601
|
+
onUploadError?.(new Error("No target element"));
|
|
4602
|
+
return false;
|
|
4603
|
+
}
|
|
4604
|
+
try {
|
|
4605
|
+
const imageInfo = detectImageElement(targetElement);
|
|
4606
|
+
if (imageInfo.isImage && imageInfo.src) {
|
|
4607
|
+
const response = await fetch(imageInfo.src);
|
|
4608
|
+
const blob = await response.blob();
|
|
4609
|
+
const formData = new FormData();
|
|
4610
|
+
const filename = `image-${Date.now()}.${blob.type.split("/")[1] || "png"}`;
|
|
4611
|
+
formData.append("file", blob, filename);
|
|
4612
|
+
const uploadResponse = await fetch(endpoint, {
|
|
4613
|
+
method: "POST",
|
|
4614
|
+
body: formData
|
|
4615
|
+
});
|
|
4616
|
+
if (!uploadResponse.ok) {
|
|
4617
|
+
throw new Error(`Upload failed: ${uploadResponse.status}`);
|
|
4618
|
+
}
|
|
4619
|
+
const result = await uploadResponse.json();
|
|
4620
|
+
onUploadComplete?.(result);
|
|
4621
|
+
} else if (imageInfo.isImage && imageInfo.type === "canvas") {
|
|
4622
|
+
const canvas = targetElement;
|
|
4623
|
+
const dataUrl = canvas.toDataURL("image/png");
|
|
4624
|
+
const response = await fetch(dataUrl);
|
|
4625
|
+
const blob = await response.blob();
|
|
4626
|
+
const formData = new FormData();
|
|
4627
|
+
formData.append("file", blob, `canvas-${Date.now()}.png`);
|
|
4628
|
+
const uploadResponse = await fetch(endpoint, {
|
|
4629
|
+
method: "POST",
|
|
4630
|
+
body: formData
|
|
4631
|
+
});
|
|
4632
|
+
if (!uploadResponse.ok) {
|
|
4633
|
+
throw new Error(`Upload failed: ${uploadResponse.status}`);
|
|
4634
|
+
}
|
|
4635
|
+
const result = await uploadResponse.json();
|
|
4636
|
+
onUploadComplete?.(result);
|
|
4637
|
+
} else {
|
|
4638
|
+
onUploadError?.(
|
|
4639
|
+
new Error(
|
|
4640
|
+
"Element is not an image. Screenshot upload requires anyclick-core."
|
|
4641
|
+
)
|
|
4642
|
+
);
|
|
4643
|
+
}
|
|
4644
|
+
} catch (error) {
|
|
4645
|
+
onUploadError?.(
|
|
4646
|
+
error instanceof Error ? error : new Error(String(error))
|
|
4647
|
+
);
|
|
4648
|
+
}
|
|
4649
|
+
closeMenu();
|
|
4650
|
+
return false;
|
|
4651
|
+
},
|
|
4652
|
+
showComment: false,
|
|
4653
|
+
type: "upload_image"
|
|
4654
|
+
};
|
|
4655
|
+
}
|
|
4656
|
+
function createUploadScreenshotMenuItem(options = {}) {
|
|
4657
|
+
const {
|
|
4658
|
+
label = "Upload Screenshot",
|
|
4659
|
+
endpoint = "/api/uploadthing",
|
|
4660
|
+
onUploadComplete,
|
|
4661
|
+
onUploadError
|
|
4662
|
+
} = options;
|
|
4663
|
+
return {
|
|
4664
|
+
label,
|
|
4665
|
+
badge: { label: "Coming soon", tone: "info" },
|
|
4666
|
+
status: "comingSoon",
|
|
4667
|
+
onClick: async ({ closeMenu }) => {
|
|
4668
|
+
onUploadError?.(
|
|
4669
|
+
new Error("Screenshot upload will be available in a future release")
|
|
4670
|
+
);
|
|
4671
|
+
closeMenu();
|
|
4672
|
+
return false;
|
|
4673
|
+
},
|
|
4674
|
+
showComment: false,
|
|
4675
|
+
type: "upload_screenshot"
|
|
4676
|
+
};
|
|
4677
|
+
}
|
|
3052
4678
|
|
|
3053
4679
|
// src/types.ts
|
|
3054
4680
|
function filterMenuItemsByRole(items, userContext) {
|
|
@@ -3067,10 +4693,10 @@ function filterMenuItemsByRole(items, userContext) {
|
|
|
3067
4693
|
}
|
|
3068
4694
|
|
|
3069
4695
|
// src/index.ts
|
|
3070
|
-
var
|
|
4696
|
+
var import_anyclick_core6 = require("@ewjdev/anyclick-core");
|
|
3071
4697
|
|
|
3072
4698
|
// src/AnyclickLogo.tsx
|
|
3073
|
-
var
|
|
4699
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
3074
4700
|
function AnyclickLogo({
|
|
3075
4701
|
size = 64,
|
|
3076
4702
|
borderWidth = 2,
|
|
@@ -3082,7 +4708,7 @@ function AnyclickLogo({
|
|
|
3082
4708
|
}) {
|
|
3083
4709
|
const cursorSize = size * 0.45;
|
|
3084
4710
|
const cursorStroke = borderWidth;
|
|
3085
|
-
return /* @__PURE__ */ (0,
|
|
4711
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
3086
4712
|
"svg",
|
|
3087
4713
|
{
|
|
3088
4714
|
width: size,
|
|
@@ -3096,7 +4722,7 @@ function AnyclickLogo({
|
|
|
3096
4722
|
role: onClick ? "button" : "img",
|
|
3097
4723
|
"aria-label": "Anyclick Logo",
|
|
3098
4724
|
children: [
|
|
3099
|
-
/* @__PURE__ */ (0,
|
|
4725
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3100
4726
|
"circle",
|
|
3101
4727
|
{
|
|
3102
4728
|
cx: size / 2,
|
|
@@ -3107,11 +4733,11 @@ function AnyclickLogo({
|
|
|
3107
4733
|
strokeWidth: borderWidth
|
|
3108
4734
|
}
|
|
3109
4735
|
),
|
|
3110
|
-
/* @__PURE__ */ (0,
|
|
4736
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3111
4737
|
"g",
|
|
3112
4738
|
{
|
|
3113
4739
|
transform: `translate(${(size - cursorSize) / 2}, ${(size - cursorSize) / 2})`,
|
|
3114
|
-
children: /* @__PURE__ */ (0,
|
|
4740
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3115
4741
|
"path",
|
|
3116
4742
|
{
|
|
3117
4743
|
d: `
|
|
@@ -3139,7 +4765,7 @@ function AnyclickLogo({
|
|
|
3139
4765
|
}
|
|
3140
4766
|
|
|
3141
4767
|
// src/index.ts
|
|
3142
|
-
var
|
|
4768
|
+
var import_anyclick_core7 = require("@ewjdev/anyclick-core");
|
|
3143
4769
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3144
4770
|
0 && (module.exports = {
|
|
3145
4771
|
ALL_CURATED_PROPERTIES,
|
|
@@ -3149,6 +4775,7 @@ var import_anyclick_core6 = require("@ewjdev/anyclick-core");
|
|
|
3149
4775
|
CURATED_STYLE_PROPERTIES,
|
|
3150
4776
|
ContextMenu,
|
|
3151
4777
|
DEFAULT_COMPACT_CONFIG,
|
|
4778
|
+
DEFAULT_QUICK_CHAT_CONFIG,
|
|
3152
4779
|
DEFAULT_SCREENSHOT_CONFIG,
|
|
3153
4780
|
DEFAULT_SENSITIVE_SELECTORS,
|
|
3154
4781
|
FeedbackContext,
|
|
@@ -3157,6 +4784,7 @@ var import_anyclick_core6 = require("@ewjdev/anyclick-core");
|
|
|
3157
4784
|
INSPECT_DIALOG_EVENT,
|
|
3158
4785
|
InspectDialogManager,
|
|
3159
4786
|
InspectSimple,
|
|
4787
|
+
QuickChat,
|
|
3160
4788
|
ScreenshotPreview,
|
|
3161
4789
|
applyHighlights,
|
|
3162
4790
|
buildIDEUrl,
|
|
@@ -3165,9 +4793,13 @@ var import_anyclick_core6 = require("@ewjdev/anyclick-core");
|
|
|
3165
4793
|
clearHighlights,
|
|
3166
4794
|
createIDEOpener,
|
|
3167
4795
|
createPresetMenu,
|
|
4796
|
+
createT3ChatMenuItem,
|
|
4797
|
+
createUploadScreenshotMenuItem,
|
|
4798
|
+
createUploadThingMenuItem,
|
|
3168
4799
|
darkMenuStyles,
|
|
3169
4800
|
defaultContainerSelectors,
|
|
3170
4801
|
defaultHighlightColors,
|
|
4802
|
+
detectImageElement,
|
|
3171
4803
|
detectPreferredIDE,
|
|
3172
4804
|
dispatchContextMenuEvent,
|
|
3173
4805
|
estimateTotalSize,
|
|
@@ -3185,7 +4817,9 @@ var import_anyclick_core6 = require("@ewjdev/anyclick-core");
|
|
|
3185
4817
|
getBoxModelInfo,
|
|
3186
4818
|
getComputedStyles,
|
|
3187
4819
|
getElementInspectInfo,
|
|
4820
|
+
getSelectedText,
|
|
3188
4821
|
getSourceLocationFromElement,
|
|
4822
|
+
hasTextSelection,
|
|
3189
4823
|
highlightContainer,
|
|
3190
4824
|
highlightTarget,
|
|
3191
4825
|
isIDEProtocolSupported,
|
|
@@ -3196,8 +4830,11 @@ var import_anyclick_core6 = require("@ewjdev/anyclick-core");
|
|
|
3196
4830
|
openInIDE,
|
|
3197
4831
|
openInspectDialog,
|
|
3198
4832
|
presetDefaults,
|
|
4833
|
+
quickChatKeyframes,
|
|
4834
|
+
quickChatStyles,
|
|
3199
4835
|
useAnyclick,
|
|
3200
4836
|
useFeedback,
|
|
3201
|
-
useProviderStore
|
|
4837
|
+
useProviderStore,
|
|
4838
|
+
useQuickChat
|
|
3202
4839
|
});
|
|
3203
4840
|
//# sourceMappingURL=index.js.map
|