@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.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: () => import_anyclick_core6.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: () => import_anyclick_core6.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
- DEFAULT_SCREENSHOT_CONFIG: () => import_anyclick_core5.DEFAULT_SCREENSHOT_CONFIG,
42
- DEFAULT_SENSITIVE_SELECTORS: () => import_anyclick_core5.DEFAULT_SENSITIVE_SELECTORS,
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: () => import_anyclick_core5.captureAllScreenshots,
53
- captureScreenshot: () => import_anyclick_core5.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: () => import_anyclick_core5.estimateTotalSize,
68
+ estimateTotalSize: () => import_anyclick_core6.estimateTotalSize,
63
69
  filterMenuItemsByRole: () => filterMenuItemsByRole,
64
70
  findContainerParent: () => findContainerParent,
65
71
  findSourceLocationInAncestors: () => findSourceLocationInAncestors,
66
- formatBoxModel: () => import_anyclick_core6.formatBoxModel,
67
- formatBytes: () => import_anyclick_core5.formatBytes,
72
+ formatBoxModel: () => import_anyclick_core7.formatBoxModel,
73
+ formatBytes: () => import_anyclick_core6.formatBytes,
68
74
  formatSourceLocation: () => formatSourceLocation,
69
- formatStylesAsCSS: () => import_anyclick_core6.formatStylesAsCSS,
75
+ formatStylesAsCSS: () => import_anyclick_core7.formatStylesAsCSS,
70
76
  generateProviderId: () => generateProviderId,
71
- getAccessibilityInfo: () => import_anyclick_core6.getAccessibilityInfo,
72
- getAttributes: () => import_anyclick_core6.getAttributes,
77
+ getAccessibilityInfo: () => import_anyclick_core7.getAccessibilityInfo,
78
+ getAttributes: () => import_anyclick_core7.getAttributes,
73
79
  getBadgeStyle: () => getBadgeStyle,
74
- getBoxModelInfo: () => import_anyclick_core6.getBoxModelInfo,
75
- getComputedStyles: () => import_anyclick_core6.getComputedStyles,
76
- getElementInspectInfo: () => import_anyclick_core6.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: () => import_anyclick_core5.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 import_react4 = require("react");
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/ContextMenu.tsx
99
- var import_react2 = __toESM(require("react"));
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 import_jsx_runtime = require("react/jsx-runtime");
582
- var ScreenshotPreview = import_react.default.memo(function ScreenshotPreview2({
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, import_react.useState)("element");
591
- const [isExpanded, setIsExpanded] = (0, import_react.useState)(false);
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, import_react.useMemo)(() => {
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, import_react.useMemo)(
620
- () => screenshots ? (0, import_anyclick_core.estimateTotalSize)(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, import_jsx_runtime.jsx)("div", { style: screenshotPreviewStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.loadingContainer, children: [
625
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
626
- import_lucide_react.Loader2Icon,
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, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.loadingText, children: "Capturing screenshots..." })
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, import_jsx_runtime.jsx)("div", { style: screenshotPreviewStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.emptyContainer, children: [
637
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ImageIcon, { className: "w-8 h-8", style: { color: "#9ca3af" } }),
638
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.emptyText, children: "Screenshots unavailable" }),
639
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.emptySubtext, children: "Some elements can't be captured (e.g., gradient text)" }),
640
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.emptyActions, children: [
641
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
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, import_jsx_runtime.jsx)(import_lucide_react.RefreshCwIcon, { className: "w-4 h-4" }),
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, import_jsx_runtime.jsxs)(
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, import_jsx_runtime.jsx)(import_lucide_react.CheckIcon, { className: "w-4 h-4" }),
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, import_jsx_runtime.jsxs)(
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, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.header, children: [
682
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.headerTitle, children: "Review Screenshots" }),
683
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.headerActions, children: [
684
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.sizeLabel, children: (0, import_anyclick_core.formatBytes)(totalSize) }),
685
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
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, import_jsx_runtime.jsx)(import_lucide_react.ShrinkIcon, { className: "w-4 h-4" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ExpandIcon, { className: "w-4 h-4" })
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, import_jsx_runtime.jsx)("div", { style: screenshotPreviewStyles.tabContainer, children: tabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
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, import_jsx_runtime.jsx)(
709
- import_lucide_react.AlertCircleIcon,
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, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.tabSize, children: (0, import_anyclick_core.formatBytes)(tab.data.sizeBytes) })
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, import_jsx_runtime.jsx)(
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, import_jsx_runtime.jsx)(
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, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.errorPreview, children: [
736
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.AlertCircleIcon, { className: "w-8 h-8", style: { color: "#ef4444" } }),
737
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.errorTitle, children: "Capture Failed" }),
738
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.errorMessage, children: activeError.message })
739
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.noPreview, children: [
740
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ImageIcon, { className: "w-6 h-6", style: { color: "#9ca3af" } }),
741
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
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, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.dimensionsInfo, children: [
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, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.actions, children: [
756
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
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, import_jsx_runtime.jsx)(import_lucide_react.RefreshCwIcon, { className: "w-3 h-3" }),
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, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.actionsRight, children: [
770
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
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, import_jsx_runtime.jsx)(import_lucide_react.XIcon, { className: "w-3 h-3" }),
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, import_jsx_runtime.jsx)(
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, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
796
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Loader2Icon, { className: "w-3 h-3 animate-spin" }),
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, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
799
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.CheckIcon, { className: "w-3 h-3" }),
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 injectStyles(colors) {
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
- injectStyles(mergedColors);
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
- injectStyles(mergedColors);
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 import_jsx_runtime2 = require("react/jsx-runtime");
2313
+ var import_jsx_runtime3 = require("react/jsx-runtime");
977
2314
  var VIEWPORT_PADDING = 10;
978
2315
  var defaultIcons = {
979
- feature: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.PlusIcon, { className: "w-4 h-4" }),
980
- issue: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.FlagIcon, { className: "w-4 h-4" }),
981
- like: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.ThumbsUpIcon, { className: "w-4 h-4" })
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, import_jsx_runtime2.jsxs)("div", { style: styles, className, children: [
991
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: title }),
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 = import_react2.default.memo(function MenuItem2({
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, import_react2.useState)(false);
1002
- const [isPressed, setIsPressed] = (0, import_react2.useState)(false);
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, import_jsx_runtime2.jsxs)(
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, import_jsx_runtime2.jsx)("span", { style: menuStyles.itemIcon, children: iconNode }) : null,
1030
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: menuStyles.itemLabel, children: [
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, import_jsx_runtime2.jsx)("span", { style: badgeStyle, children: badgeLabel })
2369
+ badgeLabel && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: badgeStyle, children: badgeLabel })
1033
2370
  ] }),
1034
- hasChildren && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.ChevronRightIcon, { className: "w-4 h-4", style: menuStyles.submenuIcon })
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 = import_react2.default.memo(function BackButton2({
2376
+ var BackButton = import_react4.default.memo(function BackButton2({
1040
2377
  onClick
1041
2378
  }) {
1042
- const [isHovered, setIsHovered] = (0, import_react2.useState)(false);
1043
- const [isPressed, setIsPressed] = (0, import_react2.useState)(false);
1044
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
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, import_jsx_runtime2.jsx)(import_lucide_react2.ChevronLeftIcon, { className: "w-4 h-4", style: { opacity: 0.5 } }),
1065
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { opacity: 0.7 }, children: "Back" })
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 = import_react2.default.memo(function CommentForm2({
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, import_react2.useState)("");
1076
- const inputRef = (0, import_react2.useRef)(null);
1077
- (0, import_react2.useEffect)(() => {
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, import_react2.useCallback)(() => {
2417
+ const handleSubmit = (0, import_react4.useCallback)(() => {
1081
2418
  onSubmit(comment);
1082
2419
  }, [comment, onSubmit]);
1083
- const handleKeyDown = (0, import_react2.useCallback)(
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, import_jsx_runtime2.jsxs)("div", { style: menuStyles.commentSection, children: [
1094
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
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, import_jsx_runtime2.jsxs)("div", { style: menuStyles.buttonRow, children: [
1107
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
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, import_jsx_runtime2.jsx)(
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, import_react2.useState)(null);
1171
- const [currentView, setCurrentView] = (0, import_react2.useState)("menu");
1172
- const [pendingComment, setPendingComment] = (0, import_react2.useState)();
1173
- const [submenuStack, setSubmenuStack] = (0, import_react2.useState)([]);
1174
- const [screenshots, setScreenshots] = (0, import_react2.useState)(null);
1175
- const [isCapturing, setIsCapturing] = (0, import_react2.useState)(false);
1176
- const menuRef = (0, import_react2.useRef)(null);
1177
- const [adjustedPosition, setAdjustedPosition] = (0, import_react2.useState)(OFFSCREEN_POSITION);
1178
- const [isDragging, setIsDragging] = (0, import_react2.useState)(false);
1179
- const [dragOffset, setDragOffset] = (0, import_react2.useState)({
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, import_react2.useRef)(null);
1184
- const mergedScreenshotConfig = import_react2.default.useMemo(
2529
+ const dragStartRef = (0, import_react4.useRef)(null);
2530
+ const mergedScreenshotConfig = import_react4.default.useMemo(
1185
2531
  () => ({
1186
- ...import_anyclick_core2.DEFAULT_SCREENSHOT_CONFIG,
2532
+ ...import_anyclick_core3.DEFAULT_SCREENSHOT_CONFIG,
1187
2533
  ...screenshotConfig
1188
2534
  }),
1189
2535
  [screenshotConfig]
1190
2536
  );
1191
- const showPreview = mergedScreenshotConfig.showPreview && (0, import_anyclick_core2.isScreenshotSupported)();
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, import_react2.useCallback)(async () => {
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, import_anyclick_core2.captureAllScreenshots)(
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, import_react2.useEffect)(() => {
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, import_react2.useEffect)(() => {
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, import_react2.useEffect)(() => {
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, import_react2.useEffect)(() => {
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, import_react2.useEffect)(() => {
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, import_react2.useEffect)(() => {
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, import_react2.useCallback)(
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, import_react2.useEffect)(() => {
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
- }, [currentView, onClose, submenuStack.length, visible]);
1341
- (0, import_react2.useEffect)(() => {
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 containerWidth = currentView === "screenshot-preview" ? 360 : void 0;
1430
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1431
- "div",
1432
- {
1433
- ref: menuRef,
1434
- "aria-label": "Feedback options",
1435
- className,
1436
- role: "menu",
1437
- style: {
1438
- ...menuStyles.container,
1439
- left: adjustedPosition.x,
1440
- top: adjustedPosition.y,
1441
- ...containerWidth ? { minWidth: containerWidth, width: containerWidth } : {},
1442
- touchAction: "none",
1443
- userSelect: "none",
1444
- WebkitTouchCallout: "none",
1445
- WebkitUserSelect: "none",
1446
- ...isDragging ? { cursor: "grabbing" } : {},
1447
- ...style
1448
- },
1449
- children: [
1450
- !header && currentView !== "screenshot-preview" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(DefaultHeader, { styles: menuStyles.header, title: "Send Feedback", children: [
1451
- showPreview && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: menuStyles.screenshotIndicator, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.CameraIcon, { className: "w-3 h-3" }) }),
1452
- positionMode === "dynamic" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1453
- "div",
1454
- {
1455
- "data-drag-handle": true,
1456
- onMouseEnter: (e) => {
1457
- e.currentTarget.style.opacity = "1";
1458
- },
1459
- onMouseLeave: (e) => {
1460
- e.currentTarget.style.opacity = "0.5";
1461
- },
1462
- onPointerDown: handleDragStart,
1463
- style: {
1464
- ...menuStyles.dragHandle,
1465
- cursor: isDragging ? "grabbing" : "grab"
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
- title: "Drag to move",
1468
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.GripVertical, { className: "w-4 h-4" })
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
- !!header && header,
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
- disabled: isSubmitting,
1479
- hasChildren: item.children && item.children.length > 0,
1480
- item,
1481
- onClick: () => handleItemClick(item)
1482
- },
1483
- item.type
1484
- ))
1485
- ] }),
1486
- currentView === "comment" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1487
- CommentForm,
1488
- {
1489
- isSubmitting,
1490
- onCancel: handleCommentCancel,
1491
- onSubmit: handleCommentSubmit
1492
- }
1493
- ),
1494
- currentView === "screenshot-preview" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1495
- ScreenshotPreview,
1496
- {
1497
- isLoading: isCapturing,
1498
- isSubmitting,
1499
- onCancel: handleScreenshotCancel,
1500
- onConfirm: handleScreenshotConfirm,
1501
- onRetake: handleRetakeScreenshots,
1502
- screenshots
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 import_react3 = require("react");
1512
- var AnyclickContext = (0, import_react3.createContext)(null);
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, import_react3.useContext)(AnyclickContext);
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, import_react3.useContext)(AnyclickContext);
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 import_jsx_runtime3 = require("react/jsx-runtime");
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, import_react4.useState)(false);
1723
- const [menuVisible, setMenuVisible] = (0, import_react4.useState)(false);
1724
- const [menuPosition, setMenuPosition] = (0, import_react4.useState)(OFFSCREEN_POSITION2);
1725
- const [targetElement, setTargetElement] = (0, import_react4.useState)(null);
1726
- const [containerElement, setContainerElement] = (0, import_react4.useState)(
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, import_react4.useId)();
1730
- const containerRef = (0, import_react4.useRef)(null);
1731
- const [containerReady, setContainerReady] = (0, import_react4.useState)(!scoped);
1732
- const clientRef = (0, import_react4.useRef)(null);
1733
- const setContainerRef = (0, import_react4.useCallback)(
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, import_react4.useMemo)(() => {
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, import_react4.useMemo)(() => {
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, import_react4.useCallback)(
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, import_react4.useLayoutEffect)(() => {
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, import_react4.useEffect)(() => {
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, import_react4.useEffect)(() => {
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, import_anyclick_core3.createAnyclickClient)({
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, import_react4.useCallback)(
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, import_react4.useCallback)(
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, import_react4.useCallback)(() => {
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, import_react4.useCallback)(
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, import_react4.useMemo)(
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, import_react4.useMemo)(
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, import_jsx_runtime3.jsx)(
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, import_jsx_runtime3.jsxs)(AnyclickContext.Provider, { value: contextValue, children: [
3456
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(AnyclickContext.Provider, { value: contextValue, children: [
2012
3457
  content,
2013
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
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 import_react5 = require("react");
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, import_react5.useRef)(null);
2084
- const cachedConfigs = (0, import_react5.useRef)({});
2085
- const findActiveFunProvider = (0, import_react5.useMemo)(() => {
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, import_react5.useEffect)(() => {
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 import_react7 = require("react");
3578
+ var import_react9 = require("react");
2133
3579
 
2134
3580
  // src/InspectDialog/InspectSimple.tsx
2135
- var import_react6 = require("react");
2136
- var import_anyclick_core4 = require("@ewjdev/anyclick-core");
2137
- var import_lucide_react3 = require("lucide-react");
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 import_jsx_runtime4 = require("react/jsx-runtime");
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, import_react6.useState)(false);
2302
- (0, import_react6.useEffect)(() => {
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, import_react6.useState)(null);
2321
- const [sourceLocation, setSourceLocation] = (0, import_react6.useState)(
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, import_react6.useState)(null);
2325
- const [saving, setSaving] = (0, import_react6.useState)(false);
2326
- const dialogRef = (0, import_react6.useRef)(null);
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, import_react6.useEffect)(() => {
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, import_react6.useEffect)(() => {
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, import_anyclick_core4.getElementInspectInfo)(targetElement);
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, import_react6.useEffect)(() => {
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, import_react6.useMemo)(() => {
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, import_anyclick_core4.captureScreenshot)(targetElement, null, "element");
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, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
2453
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
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, import_jsx_runtime4.jsxs)(
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, import_jsx_runtime4.jsxs)(
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, import_jsx_runtime4.jsx)(
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, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
2503
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
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, import_jsx_runtime4.jsx)(
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, import_jsx_runtime4.jsx)(import_lucide_react3.ExternalLink, { size: 14 })
3971
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.ExternalLink, { size: 14 })
2526
3972
  }
2527
3973
  )
2528
3974
  ] }),
2529
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
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, import_jsx_runtime4.jsx)(import_lucide_react3.X, { size: 16 })
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, import_jsx_runtime4.jsxs)(
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, import_jsx_runtime4.jsx)(
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, import_jsx_runtime4.jsx)(
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, import_jsx_runtime4.jsxs)(
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, import_jsx_runtime4.jsx)(
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, import_jsx_runtime4.jsx)(import_lucide_react3.Copy, { size: 15 })
4042
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Copy, { size: 15 })
2597
4043
  }
2598
4044
  ),
2599
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
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, import_jsx_runtime4.jsx)(import_lucide_react3.FileText, { size: 15 })
4053
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.FileText, { size: 15 })
2608
4054
  }
2609
4055
  ),
2610
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
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, import_jsx_runtime4.jsx)(import_lucide_react3.Code, { size: 15 })
4064
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Code, { size: 15 })
2619
4065
  }
2620
4066
  ),
2621
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
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, import_jsx_runtime4.jsx)(import_lucide_react3.Camera, { size: 15 })
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 import_jsx_runtime5 = require("react/jsx-runtime");
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, import_react7.useState)(false);
2700
- const [targetElement, setTargetElement] = (0, import_react7.useState)(null);
2701
- const handleClose = (0, import_react7.useCallback)(() => {
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, import_react7.useCallback)((element) => {
4151
+ const handleSelectElement = (0, import_react9.useCallback)((element) => {
2706
4152
  setTargetElement(element);
2707
4153
  }, []);
2708
- (0, import_react7.useEffect)(() => {
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, import_jsx_runtime5.jsx)(
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 import_anyclick_core5 = require("@ewjdev/anyclick-core");
4696
+ var import_anyclick_core6 = require("@ewjdev/anyclick-core");
3071
4697
 
3072
4698
  // src/AnyclickLogo.tsx
3073
- var import_jsx_runtime6 = require("react/jsx-runtime");
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, import_jsx_runtime6.jsxs)(
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, import_jsx_runtime6.jsx)(
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, import_jsx_runtime6.jsx)(
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, import_jsx_runtime6.jsx)(
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 import_anyclick_core6 = require("@ewjdev/anyclick-core");
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