@trustquery/browser 0.2.6 → 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.
- package/dist/trustquery.js +160 -3
- package/dist/trustquery.js.map +1 -1
- package/package.json +1 -1
- package/src/InteractionHandler.js +48 -2
- package/src/TrustQuery.js +112 -1
package/package.json
CHANGED
|
@@ -139,16 +139,42 @@ export default class InteractionHandler {
|
|
|
139
139
|
const behavior = matchEl.getAttribute('data-behavior');
|
|
140
140
|
const matchData = this.getMatchData(matchEl);
|
|
141
141
|
|
|
142
|
-
console.log('[InteractionHandler]
|
|
142
|
+
console.log('[InteractionHandler] ===== CLICK EVENT START =====');
|
|
143
|
+
console.log('[InteractionHandler] Click details:', {
|
|
144
|
+
behavior: behavior,
|
|
145
|
+
matchText: matchData.text,
|
|
146
|
+
eventType: e.type,
|
|
147
|
+
target: e.target.tagName,
|
|
148
|
+
currentTarget: e.currentTarget.tagName,
|
|
149
|
+
button: e.button,
|
|
150
|
+
buttons: e.buttons,
|
|
151
|
+
clientX: e.clientX,
|
|
152
|
+
clientY: e.clientY,
|
|
153
|
+
offsetX: e.offsetX,
|
|
154
|
+
offsetY: e.offsetY
|
|
155
|
+
});
|
|
156
|
+
console.log('[InteractionHandler] Match element:', {
|
|
157
|
+
textContent: matchEl.textContent,
|
|
158
|
+
offsetWidth: matchEl.offsetWidth,
|
|
159
|
+
offsetHeight: matchEl.offsetHeight,
|
|
160
|
+
attributes: {
|
|
161
|
+
'data-line': matchEl.getAttribute('data-line'),
|
|
162
|
+
'data-col': matchEl.getAttribute('data-col'),
|
|
163
|
+
'data-behavior': behavior
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
console.log('[InteractionHandler] Active element before click:', document.activeElement.tagName, document.activeElement.id || '(no id)');
|
|
143
167
|
|
|
144
168
|
// For non-interactive elements (bubbles), manually pass click to textarea
|
|
145
169
|
if (behavior !== 'dropdown' && behavior !== 'action') {
|
|
170
|
+
console.log('[InteractionHandler] Non-interactive match - manually focusing textarea');
|
|
146
171
|
e.preventDefault();
|
|
147
172
|
e.stopPropagation();
|
|
148
173
|
|
|
149
174
|
// Focus textarea and position cursor at click location
|
|
150
175
|
if (this.options.textarea) {
|
|
151
176
|
this.options.textarea.focus();
|
|
177
|
+
console.log('[InteractionHandler] Textarea focused. Active element now:', document.activeElement.tagName, document.activeElement.id || '(no id)');
|
|
152
178
|
|
|
153
179
|
// Get the character offset by finding the match position
|
|
154
180
|
const line = parseInt(matchEl.getAttribute('data-line'));
|
|
@@ -160,15 +186,33 @@ export default class InteractionHandler {
|
|
|
160
186
|
for (let i = 0; i < line; i++) {
|
|
161
187
|
offset += lines[i].length + 1; // +1 for newline
|
|
162
188
|
}
|
|
163
|
-
|
|
189
|
+
const clickOffsetInMatch = (e.offsetX / matchEl.offsetWidth * matchEl.textContent.length);
|
|
190
|
+
offset += col + clickOffsetInMatch;
|
|
191
|
+
|
|
192
|
+
console.log('[InteractionHandler] Cursor positioning:', {
|
|
193
|
+
line: line,
|
|
194
|
+
col: col,
|
|
195
|
+
clickOffsetInMatch: clickOffsetInMatch,
|
|
196
|
+
finalOffset: offset,
|
|
197
|
+
textareaValue: this.options.textarea.value,
|
|
198
|
+
textareaValueLength: this.options.textarea.value.length
|
|
199
|
+
});
|
|
164
200
|
|
|
165
201
|
// Set cursor position
|
|
166
202
|
this.options.textarea.setSelectionRange(offset, offset);
|
|
203
|
+
|
|
204
|
+
console.log('[InteractionHandler] Selection set:', {
|
|
205
|
+
selectionStart: this.options.textarea.selectionStart,
|
|
206
|
+
selectionEnd: this.options.textarea.selectionEnd,
|
|
207
|
+
selectedText: this.options.textarea.value.substring(this.options.textarea.selectionStart, this.options.textarea.selectionEnd)
|
|
208
|
+
});
|
|
167
209
|
}
|
|
168
210
|
|
|
211
|
+
console.log('[InteractionHandler] ===== CLICK EVENT END (non-interactive) =====');
|
|
169
212
|
return; // Don't process further for bubbles
|
|
170
213
|
}
|
|
171
214
|
|
|
215
|
+
console.log('[InteractionHandler] Interactive match - handling dropdown/action');
|
|
172
216
|
// Prevent default for interactive elements (dropdown/action)
|
|
173
217
|
e.preventDefault();
|
|
174
218
|
e.stopPropagation();
|
|
@@ -192,6 +236,8 @@ export default class InteractionHandler {
|
|
|
192
236
|
if (this.options.onWordClick && !(behavior === 'dropdown' && this.dropdownManager.activeDropdownMatch === matchEl)) {
|
|
193
237
|
this.options.onWordClick(matchData);
|
|
194
238
|
}
|
|
239
|
+
|
|
240
|
+
console.log('[InteractionHandler] ===== CLICK EVENT END (interactive) =====');
|
|
195
241
|
}
|
|
196
242
|
|
|
197
243
|
/**
|
package/src/TrustQuery.js
CHANGED
|
@@ -284,12 +284,121 @@ export default class TrustQuery {
|
|
|
284
284
|
this.overlay.scrollLeft = this.textarea.scrollLeft;
|
|
285
285
|
});
|
|
286
286
|
|
|
287
|
+
// Keyboard event logging for debugging selection issues
|
|
288
|
+
this.textarea.addEventListener('keydown', (e) => {
|
|
289
|
+
const isCmdOrCtrl = e.metaKey || e.ctrlKey;
|
|
290
|
+
const isSelectAll = (e.metaKey || e.ctrlKey) && e.key === 'a';
|
|
291
|
+
|
|
292
|
+
if (isCmdOrCtrl || isSelectAll) {
|
|
293
|
+
console.log('[TrustQuery] ===== KEYBOARD EVENT =====');
|
|
294
|
+
console.log('[TrustQuery] Key pressed:', {
|
|
295
|
+
key: e.key,
|
|
296
|
+
code: e.code,
|
|
297
|
+
metaKey: e.metaKey,
|
|
298
|
+
ctrlKey: e.ctrlKey,
|
|
299
|
+
shiftKey: e.shiftKey,
|
|
300
|
+
altKey: e.altKey,
|
|
301
|
+
isSelectAll: isSelectAll
|
|
302
|
+
});
|
|
303
|
+
console.log('[TrustQuery] Active element:', document.activeElement.tagName, document.activeElement.id || '(no id)');
|
|
304
|
+
console.log('[TrustQuery] Textarea state BEFORE:', {
|
|
305
|
+
value: this.textarea.value,
|
|
306
|
+
valueLength: this.textarea.value.length,
|
|
307
|
+
selectionStart: this.textarea.selectionStart,
|
|
308
|
+
selectionEnd: this.textarea.selectionEnd,
|
|
309
|
+
selectedText: this.textarea.value.substring(this.textarea.selectionStart, this.textarea.selectionEnd)
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
if (isSelectAll) {
|
|
313
|
+
// Log state after select all (use setTimeout to let browser process the event)
|
|
314
|
+
setTimeout(() => {
|
|
315
|
+
console.log('[TrustQuery] Textarea state AFTER CMD+A:', {
|
|
316
|
+
selectionStart: this.textarea.selectionStart,
|
|
317
|
+
selectionEnd: this.textarea.selectionEnd,
|
|
318
|
+
selectedText: this.textarea.value.substring(this.textarea.selectionStart, this.textarea.selectionEnd),
|
|
319
|
+
selectedLength: this.textarea.selectionEnd - this.textarea.selectionStart
|
|
320
|
+
});
|
|
321
|
+
console.log('[TrustQuery] ===== KEYBOARD EVENT END =====');
|
|
322
|
+
}, 0);
|
|
323
|
+
} else {
|
|
324
|
+
console.log('[TrustQuery] ===== KEYBOARD EVENT END =====');
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
// Selection change event
|
|
330
|
+
this.textarea.addEventListener('select', (e) => {
|
|
331
|
+
console.log('[TrustQuery] ===== SELECTION CHANGE EVENT =====');
|
|
332
|
+
console.log('[TrustQuery] Selection:', {
|
|
333
|
+
selectionStart: this.textarea.selectionStart,
|
|
334
|
+
selectionEnd: this.textarea.selectionEnd,
|
|
335
|
+
selectedText: this.textarea.value.substring(this.textarea.selectionStart, this.textarea.selectionEnd),
|
|
336
|
+
selectedLength: this.textarea.selectionEnd - this.textarea.selectionStart
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
// Context menu event - prevent keyboard-triggered context menu
|
|
341
|
+
this.textarea.addEventListener('contextmenu', (e) => {
|
|
342
|
+
console.log('[TrustQuery] ===== CONTEXTMENU EVENT =====');
|
|
343
|
+
console.log('[TrustQuery] Context menu triggered:', {
|
|
344
|
+
type: e.type,
|
|
345
|
+
isTrusted: e.isTrusted,
|
|
346
|
+
button: e.button,
|
|
347
|
+
buttons: e.buttons,
|
|
348
|
+
clientX: e.clientX,
|
|
349
|
+
clientY: e.clientY,
|
|
350
|
+
ctrlKey: e.ctrlKey,
|
|
351
|
+
metaKey: e.metaKey,
|
|
352
|
+
target: e.target.tagName
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
// Prevent context menu if triggered by keyboard (button === -1)
|
|
356
|
+
// This prevents the macOS context menu from opening after CMD+A
|
|
357
|
+
if (e.button === -1 && e.buttons === 0) {
|
|
358
|
+
console.log('[TrustQuery] Preventing keyboard-triggered context menu');
|
|
359
|
+
e.preventDefault();
|
|
360
|
+
e.stopPropagation();
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
console.log('[TrustQuery] Allowing mouse-triggered context menu');
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
// Also prevent context menu on overlay (it interferes with text selection)
|
|
368
|
+
this.overlay.addEventListener('contextmenu', (e) => {
|
|
369
|
+
console.log('[TrustQuery] ===== CONTEXTMENU EVENT ON OVERLAY =====');
|
|
370
|
+
console.log('[TrustQuery] Context menu on overlay - preventing');
|
|
371
|
+
|
|
372
|
+
// Always prevent context menu on overlay
|
|
373
|
+
// The overlay should be transparent to user interactions
|
|
374
|
+
e.preventDefault();
|
|
375
|
+
e.stopPropagation();
|
|
376
|
+
});
|
|
377
|
+
|
|
287
378
|
// Focus/blur events - add/remove focus class
|
|
288
|
-
this.textarea.addEventListener('focus', () => {
|
|
379
|
+
this.textarea.addEventListener('focus', (e) => {
|
|
380
|
+
console.log('[TrustQuery] ===== FOCUS EVENT =====');
|
|
381
|
+
console.log('[TrustQuery] Textarea focused. Active element:', document.activeElement.tagName, document.activeElement.id || '(no id)');
|
|
382
|
+
console.log('[TrustQuery] Current selection:', {
|
|
383
|
+
selectionStart: this.textarea.selectionStart,
|
|
384
|
+
selectionEnd: this.textarea.selectionEnd
|
|
385
|
+
});
|
|
289
386
|
this.wrapper.classList.add('tq-focused');
|
|
290
387
|
});
|
|
291
388
|
|
|
292
389
|
this.textarea.addEventListener('blur', (e) => {
|
|
390
|
+
console.log('[TrustQuery] ===== BLUR EVENT =====');
|
|
391
|
+
console.log('[TrustQuery] Textarea blurred. Related target:', e.relatedTarget?.tagName || '(none)');
|
|
392
|
+
console.log('[TrustQuery] Blur event details:', {
|
|
393
|
+
type: e.type,
|
|
394
|
+
isTrusted: e.isTrusted,
|
|
395
|
+
eventPhase: e.eventPhase,
|
|
396
|
+
target: e.target.tagName,
|
|
397
|
+
currentTarget: e.currentTarget.tagName
|
|
398
|
+
});
|
|
399
|
+
console.log('[TrustQuery] Stack trace at blur:');
|
|
400
|
+
console.trace();
|
|
401
|
+
|
|
293
402
|
// Close dropdown when textarea loses focus (unless interacting with dropdown)
|
|
294
403
|
if (this.interactionHandler) {
|
|
295
404
|
// Use setTimeout to let the new focus target be set and check if clicking on dropdown
|
|
@@ -300,6 +409,8 @@ export default class TrustQuery {
|
|
|
300
409
|
activeElement.closest('.tq-dropdown') // Check if clicking anywhere in dropdown
|
|
301
410
|
);
|
|
302
411
|
|
|
412
|
+
console.log('[TrustQuery] After blur - active element:', activeElement?.tagName || '(none)', 'isDropdownRelated:', isDropdownRelated);
|
|
413
|
+
|
|
303
414
|
// Only close if not interacting with dropdown
|
|
304
415
|
if (!isDropdownRelated) {
|
|
305
416
|
this.interactionHandler.hideDropdown();
|