@trustquery/browser 0.2.5 → 0.2.8

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.
@@ -1506,15 +1506,84 @@ class InteractionHandler {
1506
1506
  const behavior = matchEl.getAttribute('data-behavior');
1507
1507
  const matchData = this.getMatchData(matchEl);
1508
1508
 
1509
- console.log('[InteractionHandler] Match clicked:', matchData);
1509
+ console.log('[InteractionHandler] ===== CLICK EVENT START =====');
1510
+ console.log('[InteractionHandler] Click details:', {
1511
+ behavior: behavior,
1512
+ matchText: matchData.text,
1513
+ eventType: e.type,
1514
+ target: e.target.tagName,
1515
+ currentTarget: e.currentTarget.tagName,
1516
+ button: e.button,
1517
+ buttons: e.buttons,
1518
+ clientX: e.clientX,
1519
+ clientY: e.clientY,
1520
+ offsetX: e.offsetX,
1521
+ offsetY: e.offsetY
1522
+ });
1523
+ console.log('[InteractionHandler] Match element:', {
1524
+ textContent: matchEl.textContent,
1525
+ offsetWidth: matchEl.offsetWidth,
1526
+ offsetHeight: matchEl.offsetHeight,
1527
+ attributes: {
1528
+ 'data-line': matchEl.getAttribute('data-line'),
1529
+ 'data-col': matchEl.getAttribute('data-col'),
1530
+ 'data-behavior': behavior
1531
+ }
1532
+ });
1533
+ console.log('[InteractionHandler] Active element before click:', document.activeElement.tagName, document.activeElement.id || '(no id)');
1510
1534
 
1511
- // Only prevent default for interactive elements (dropdown/action)
1512
- // Let bubbles (error/warning/info messages) pass through for normal cursor positioning
1513
- if (behavior === 'dropdown' || behavior === 'action') {
1535
+ // For non-interactive elements (bubbles), manually pass click to textarea
1536
+ if (behavior !== 'dropdown' && behavior !== 'action') {
1537
+ console.log('[InteractionHandler] Non-interactive match - manually focusing textarea');
1514
1538
  e.preventDefault();
1515
1539
  e.stopPropagation();
1540
+
1541
+ // Focus textarea and position cursor at click location
1542
+ if (this.options.textarea) {
1543
+ this.options.textarea.focus();
1544
+ console.log('[InteractionHandler] Textarea focused. Active element now:', document.activeElement.tagName, document.activeElement.id || '(no id)');
1545
+
1546
+ // Get the character offset by finding the match position
1547
+ const line = parseInt(matchEl.getAttribute('data-line'));
1548
+ const col = parseInt(matchEl.getAttribute('data-col'));
1549
+
1550
+ // Calculate absolute position in textarea
1551
+ const lines = this.options.textarea.value.split('\n');
1552
+ let offset = 0;
1553
+ for (let i = 0; i < line; i++) {
1554
+ offset += lines[i].length + 1; // +1 for newline
1555
+ }
1556
+ const clickOffsetInMatch = (e.offsetX / matchEl.offsetWidth * matchEl.textContent.length);
1557
+ offset += col + clickOffsetInMatch;
1558
+
1559
+ console.log('[InteractionHandler] Cursor positioning:', {
1560
+ line: line,
1561
+ col: col,
1562
+ clickOffsetInMatch: clickOffsetInMatch,
1563
+ finalOffset: offset,
1564
+ textareaValue: this.options.textarea.value,
1565
+ textareaValueLength: this.options.textarea.value.length
1566
+ });
1567
+
1568
+ // Set cursor position
1569
+ this.options.textarea.setSelectionRange(offset, offset);
1570
+
1571
+ console.log('[InteractionHandler] Selection set:', {
1572
+ selectionStart: this.options.textarea.selectionStart,
1573
+ selectionEnd: this.options.textarea.selectionEnd,
1574
+ selectedText: this.options.textarea.value.substring(this.options.textarea.selectionStart, this.options.textarea.selectionEnd)
1575
+ });
1576
+ }
1577
+
1578
+ console.log('[InteractionHandler] ===== CLICK EVENT END (non-interactive) =====');
1579
+ return; // Don't process further for bubbles
1516
1580
  }
1517
1581
 
1582
+ console.log('[InteractionHandler] Interactive match - handling dropdown/action');
1583
+ // Prevent default for interactive elements (dropdown/action)
1584
+ e.preventDefault();
1585
+ e.stopPropagation();
1586
+
1518
1587
  // Handle different behaviors
1519
1588
  if (behavior === 'dropdown') {
1520
1589
  // Toggle dropdown - close if already open for this match, otherwise show
@@ -1534,6 +1603,8 @@ class InteractionHandler {
1534
1603
  if (this.options.onWordClick && !(behavior === 'dropdown' && this.dropdownManager.activeDropdownMatch === matchEl)) {
1535
1604
  this.options.onWordClick(matchData);
1536
1605
  }
1606
+
1607
+ console.log('[InteractionHandler] ===== CLICK EVENT END (interactive) =====');
1537
1608
  }
1538
1609
 
1539
1610
  /**
@@ -2949,12 +3020,121 @@ class TrustQuery {
2949
3020
  this.overlay.scrollLeft = this.textarea.scrollLeft;
2950
3021
  });
2951
3022
 
3023
+ // Keyboard event logging for debugging selection issues
3024
+ this.textarea.addEventListener('keydown', (e) => {
3025
+ const isCmdOrCtrl = e.metaKey || e.ctrlKey;
3026
+ const isSelectAll = (e.metaKey || e.ctrlKey) && e.key === 'a';
3027
+
3028
+ if (isCmdOrCtrl || isSelectAll) {
3029
+ console.log('[TrustQuery] ===== KEYBOARD EVENT =====');
3030
+ console.log('[TrustQuery] Key pressed:', {
3031
+ key: e.key,
3032
+ code: e.code,
3033
+ metaKey: e.metaKey,
3034
+ ctrlKey: e.ctrlKey,
3035
+ shiftKey: e.shiftKey,
3036
+ altKey: e.altKey,
3037
+ isSelectAll: isSelectAll
3038
+ });
3039
+ console.log('[TrustQuery] Active element:', document.activeElement.tagName, document.activeElement.id || '(no id)');
3040
+ console.log('[TrustQuery] Textarea state BEFORE:', {
3041
+ value: this.textarea.value,
3042
+ valueLength: this.textarea.value.length,
3043
+ selectionStart: this.textarea.selectionStart,
3044
+ selectionEnd: this.textarea.selectionEnd,
3045
+ selectedText: this.textarea.value.substring(this.textarea.selectionStart, this.textarea.selectionEnd)
3046
+ });
3047
+
3048
+ if (isSelectAll) {
3049
+ // Log state after select all (use setTimeout to let browser process the event)
3050
+ setTimeout(() => {
3051
+ console.log('[TrustQuery] Textarea state AFTER CMD+A:', {
3052
+ selectionStart: this.textarea.selectionStart,
3053
+ selectionEnd: this.textarea.selectionEnd,
3054
+ selectedText: this.textarea.value.substring(this.textarea.selectionStart, this.textarea.selectionEnd),
3055
+ selectedLength: this.textarea.selectionEnd - this.textarea.selectionStart
3056
+ });
3057
+ console.log('[TrustQuery] ===== KEYBOARD EVENT END =====');
3058
+ }, 0);
3059
+ } else {
3060
+ console.log('[TrustQuery] ===== KEYBOARD EVENT END =====');
3061
+ }
3062
+ }
3063
+ });
3064
+
3065
+ // Selection change event
3066
+ this.textarea.addEventListener('select', (e) => {
3067
+ console.log('[TrustQuery] ===== SELECTION CHANGE EVENT =====');
3068
+ console.log('[TrustQuery] Selection:', {
3069
+ selectionStart: this.textarea.selectionStart,
3070
+ selectionEnd: this.textarea.selectionEnd,
3071
+ selectedText: this.textarea.value.substring(this.textarea.selectionStart, this.textarea.selectionEnd),
3072
+ selectedLength: this.textarea.selectionEnd - this.textarea.selectionStart
3073
+ });
3074
+ });
3075
+
3076
+ // Context menu event - prevent keyboard-triggered context menu
3077
+ this.textarea.addEventListener('contextmenu', (e) => {
3078
+ console.log('[TrustQuery] ===== CONTEXTMENU EVENT =====');
3079
+ console.log('[TrustQuery] Context menu triggered:', {
3080
+ type: e.type,
3081
+ isTrusted: e.isTrusted,
3082
+ button: e.button,
3083
+ buttons: e.buttons,
3084
+ clientX: e.clientX,
3085
+ clientY: e.clientY,
3086
+ ctrlKey: e.ctrlKey,
3087
+ metaKey: e.metaKey,
3088
+ target: e.target.tagName
3089
+ });
3090
+
3091
+ // Prevent context menu if triggered by keyboard (button === -1)
3092
+ // This prevents the macOS context menu from opening after CMD+A
3093
+ if (e.button === -1 && e.buttons === 0) {
3094
+ console.log('[TrustQuery] Preventing keyboard-triggered context menu');
3095
+ e.preventDefault();
3096
+ e.stopPropagation();
3097
+ return;
3098
+ }
3099
+
3100
+ console.log('[TrustQuery] Allowing mouse-triggered context menu');
3101
+ });
3102
+
3103
+ // Also prevent context menu on overlay (it interferes with text selection)
3104
+ this.overlay.addEventListener('contextmenu', (e) => {
3105
+ console.log('[TrustQuery] ===== CONTEXTMENU EVENT ON OVERLAY =====');
3106
+ console.log('[TrustQuery] Context menu on overlay - preventing');
3107
+
3108
+ // Always prevent context menu on overlay
3109
+ // The overlay should be transparent to user interactions
3110
+ e.preventDefault();
3111
+ e.stopPropagation();
3112
+ });
3113
+
2952
3114
  // Focus/blur events - add/remove focus class
2953
- this.textarea.addEventListener('focus', () => {
3115
+ this.textarea.addEventListener('focus', (e) => {
3116
+ console.log('[TrustQuery] ===== FOCUS EVENT =====');
3117
+ console.log('[TrustQuery] Textarea focused. Active element:', document.activeElement.tagName, document.activeElement.id || '(no id)');
3118
+ console.log('[TrustQuery] Current selection:', {
3119
+ selectionStart: this.textarea.selectionStart,
3120
+ selectionEnd: this.textarea.selectionEnd
3121
+ });
2954
3122
  this.wrapper.classList.add('tq-focused');
2955
3123
  });
2956
3124
 
2957
3125
  this.textarea.addEventListener('blur', (e) => {
3126
+ console.log('[TrustQuery] ===== BLUR EVENT =====');
3127
+ console.log('[TrustQuery] Textarea blurred. Related target:', e.relatedTarget?.tagName || '(none)');
3128
+ console.log('[TrustQuery] Blur event details:', {
3129
+ type: e.type,
3130
+ isTrusted: e.isTrusted,
3131
+ eventPhase: e.eventPhase,
3132
+ target: e.target.tagName,
3133
+ currentTarget: e.currentTarget.tagName
3134
+ });
3135
+ console.log('[TrustQuery] Stack trace at blur:');
3136
+ console.trace();
3137
+
2958
3138
  // Close dropdown when textarea loses focus (unless interacting with dropdown)
2959
3139
  if (this.interactionHandler) {
2960
3140
  // Use setTimeout to let the new focus target be set and check if clicking on dropdown
@@ -2965,6 +3145,8 @@ class TrustQuery {
2965
3145
  activeElement.closest('.tq-dropdown') // Check if clicking anywhere in dropdown
2966
3146
  );
2967
3147
 
3148
+ console.log('[TrustQuery] After blur - active element:', activeElement?.tagName || '(none)', 'isDropdownRelated:', isDropdownRelated);
3149
+
2968
3150
  // Only close if not interacting with dropdown
2969
3151
  if (!isDropdownRelated) {
2970
3152
  this.interactionHandler.hideDropdown();