@salesforcedevs/docs-components 1.17.8-hover-edit → 1.17.11-hover-edit

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforcedevs/docs-components",
3
- "version": "1.17.8-hover-edit",
3
+ "version": "1.17.11-hover-edit",
4
4
  "description": "Docs Lightning web components for DSC",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
@@ -19,17 +19,28 @@ export default class TextSelectionSearch extends LightningElement {
19
19
  private selectionStart: number = 0;
20
20
  private selectionEnd: number = 0;
21
21
  private initialPopoverStyle: string = ""; // Store initial position
22
+ private mutationObserver: MutationObserver | null = null;
23
+ private lastMouseX: number = 0;
24
+ private lastMouseY: number = 0;
22
25
 
23
26
  connectedCallback() {
24
27
  console.log('TextSelectionSearch: Component connected');
25
28
  console.log('TextSelectionSearch: Document ready state:', document.readyState);
26
29
  console.log('TextSelectionSearch: Current page URL:', window.location.href);
27
30
  this.setupTextSelectionListener();
31
+ this.setupContentObserver();
32
+
33
+ // Additional initialization for spec-based references
34
+ if (this.isSpecBasedReferencePage()) {
35
+ console.log('TextSelectionSearch: Detected spec-based reference page, setting up additional listeners');
36
+ this.setupSpecBasedReferenceHandling();
37
+ }
28
38
  }
29
39
 
30
40
  disconnectedCallback() {
31
41
  console.log('TextSelectionSearch: Component disconnected');
32
42
  this.removeTextSelectionListener();
43
+ this.removeContentObserver();
33
44
  }
34
45
 
35
46
  // Setup text selection listener
@@ -37,7 +48,11 @@ export default class TextSelectionSearch extends LightningElement {
37
48
  console.log('TextSelectionSearch: Setting up text selection listeners');
38
49
  try {
39
50
  // Use capture phase to ensure we get the events
40
- document.addEventListener("mouseup", (event) => this.handleTextSelection(event), true);
51
+ document.addEventListener("mouseup", (event) => {
52
+ this.lastMouseX = event.clientX;
53
+ this.lastMouseY = event.clientY;
54
+ this.handleTextSelection(event);
55
+ }, true);
41
56
  document.addEventListener("keyup", (event) => this.handleTextSelection(event), true);
42
57
  console.log('TextSelectionSearch: Event listeners attached successfully');
43
58
  } catch (error) {
@@ -56,6 +71,84 @@ export default class TextSelectionSearch extends LightningElement {
56
71
  }
57
72
  }
58
73
 
74
+ // Setup observer to detect when content is dynamically loaded
75
+ setupContentObserver() {
76
+ console.log('TextSelectionSearch: Setting up content observer');
77
+ try {
78
+ this.mutationObserver = new MutationObserver((mutations) => {
79
+ let shouldReinitialize = false;
80
+
81
+ for (const mutation of mutations) {
82
+ if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
83
+ // Check if any added nodes contain text content
84
+ for (const node of Array.from(mutation.addedNodes)) {
85
+ if (node.nodeType === Node.ELEMENT_NODE) {
86
+ const element = node as Element;
87
+
88
+ // Check for spec-based reference content (.api-documentation)
89
+ if (element.classList && element.classList.contains('api-documentation')) {
90
+ console.log('TextSelectionSearch: Detected .api-documentation container');
91
+ shouldReinitialize = true;
92
+ break;
93
+ }
94
+
95
+ // Check for doc-amf-topic component
96
+ if (element.tagName && element.tagName.toLowerCase() === 'doc-amf-topic') {
97
+ console.log('TextSelectionSearch: Detected doc-amf-topic component');
98
+ shouldReinitialize = true;
99
+ break;
100
+ }
101
+
102
+ // Check for shadow DOM content in spec-based references
103
+ if (this.isSpecBasedReferencePage() && element.shadowRoot) {
104
+ console.log('TextSelectionSearch: Detected shadow DOM content');
105
+ shouldReinitialize = true;
106
+ break;
107
+ }
108
+
109
+ // Check for common content containers
110
+ if (element.querySelector && (
111
+ element.querySelector('p, h1, h2, h3, h4, h5, h6, li, td, th, div') ||
112
+ element.matches('p, h1, h2, h3, h4, h5, h6, li, td, th, div')
113
+ )) {
114
+ shouldReinitialize = true;
115
+ break;
116
+ }
117
+ }
118
+ }
119
+ }
120
+ }
121
+
122
+ if (shouldReinitialize) {
123
+ console.log('TextSelectionSearch: Content detected, reinitializing listeners');
124
+ // Small delay to ensure content is fully rendered
125
+ setTimeout(() => {
126
+ this.setupTextSelectionListener();
127
+ }, 200); // Increased delay for spec-based references
128
+ }
129
+ });
130
+
131
+ // Observe the entire document for content changes
132
+ this.mutationObserver.observe(document.body, {
133
+ childList: true,
134
+ subtree: true
135
+ });
136
+
137
+ console.log('TextSelectionSearch: Content observer set up successfully');
138
+ } catch (error) {
139
+ console.error('TextSelectionSearch: Error setting up content observer:', error);
140
+ }
141
+ }
142
+
143
+ removeContentObserver() {
144
+ console.log('TextSelectionSearch: Removing content observer');
145
+ if (this.mutationObserver) {
146
+ this.mutationObserver.disconnect();
147
+ this.mutationObserver = null;
148
+ console.log('TextSelectionSearch: Content observer removed successfully');
149
+ }
150
+ }
151
+
59
152
  // Handle text selection
60
153
  handleTextSelection(event?: Event) {
61
154
  // If popover is visible, completely ignore all text selection events
@@ -97,6 +190,31 @@ export default class TextSelectionSearch extends LightningElement {
97
190
  this.selectedText = selection.toString().trim();
98
191
  console.log('TextSelectionSearch: Selected text:', this.selectedText);
99
192
 
193
+ // For spec-based references, check if selection is within the API documentation container
194
+ if (this.isSpecBasedReferencePage()) {
195
+ const apiDocContainer = document.querySelector('.api-documentation');
196
+ if (apiDocContainer) {
197
+ const range = selection.getRangeAt(0);
198
+ const rect = range.getBoundingClientRect();
199
+ const containerRect = apiDocContainer.getBoundingClientRect();
200
+
201
+ // Check if the selection is within the API documentation container
202
+ const isWithinContainer = (
203
+ rect.top >= containerRect.top &&
204
+ rect.bottom <= containerRect.bottom &&
205
+ rect.left >= containerRect.left &&
206
+ rect.right <= containerRect.right
207
+ );
208
+
209
+ console.log('TextSelectionSearch: Selection within API container:', isWithinContainer);
210
+
211
+ if (!isWithinContainer) {
212
+ console.log('TextSelectionSearch: Selection outside API container, ignoring');
213
+ return;
214
+ }
215
+ }
216
+ }
217
+
100
218
  if (this.selectedText.length > 0) {
101
219
  this.showPopover();
102
220
  }
@@ -111,24 +229,28 @@ export default class TextSelectionSearch extends LightningElement {
111
229
  return;
112
230
  }
113
231
 
114
- const range = selection.getRangeAt(0);
115
- const rect = range.getBoundingClientRect();
116
-
232
+ // Use a simpler, more reliable positioning approach
233
+ const rect = selection.getRangeAt(0).getBoundingClientRect();
117
234
  console.log('TextSelectionSearch: Selection rect:', rect);
118
- console.log('TextSelectionSearch: Window dimensions:', window.innerWidth, window.innerHeight);
119
- console.log('TextSelectionSearch: Scroll position:', window.scrollX, window.scrollY);
120
- console.log('TextSelectionSearch: Document height:', document.documentElement.scrollHeight);
121
235
 
122
- // Calculate popover position with better positioning logic
236
+ // Check if we're on a spec-based reference page
237
+ const isSpecBased = this.isSpecBasedReferencePage();
238
+ console.log('TextSelectionSearch: Is spec-based reference:', isSpecBased);
239
+
240
+ // Use mouse position as fallback for better positioning
241
+ const mouseX = this.lastMouseX || rect.left + rect.width / 2;
242
+ const mouseY = this.lastMouseY || rect.top;
243
+
244
+ console.log('TextSelectionSearch: Using mouse position:', mouseX, mouseY);
245
+
246
+ // Calculate popover position
247
+ const popoverLeft = Math.max(10, Math.min(window.innerWidth - 360, mouseX - 175)); // Center on mouse
123
248
  let popoverTop: number;
124
- const popoverLeft = Math.max(10, Math.min(window.innerWidth - 360, rect.left + (rect.width / 2) - 180));
125
249
 
126
250
  if (this.popoverPosition === "top") {
127
- // Position above the selection
128
- popoverTop = Math.max(10, rect.top - 200); // 200px above selection
251
+ popoverTop = Math.max(10, mouseY - 220); // Above mouse cursor
129
252
  } else {
130
- // Position below the selection
131
- popoverTop = Math.min(window.innerHeight - 250, rect.bottom + 20);
253
+ popoverTop = Math.min(window.innerHeight - 250, mouseY + 20); // Below mouse cursor
132
254
  }
133
255
 
134
256
  // Ensure the popover doesn't go off-screen
@@ -139,10 +261,15 @@ export default class TextSelectionSearch extends LightningElement {
139
261
  popoverTop = window.innerHeight - 250;
140
262
  }
141
263
 
142
- this.popoverStyle = `position: fixed; top: ${popoverTop}px; left: ${popoverLeft}px; z-index: 9999; width: 350px;`;
143
- this.initialPopoverStyle = this.popoverStyle; // Store the initial position
144
- console.log('TextSelectionSearch: Popover style:', this.popoverStyle);
145
- console.log('TextSelectionSearch: Calculated position - top:', popoverTop, 'left:', popoverLeft);
264
+ this.setPopoverPosition(popoverTop, popoverLeft);
265
+ }
266
+
267
+ // Set the popover position and show it
268
+ setPopoverPosition(top: number, left: number) {
269
+ this.popoverStyle = `position: fixed; top: ${top}px; left: ${left}px; z-index: 9999; width: 350px;`;
270
+ this.initialPopoverStyle = this.popoverStyle;
271
+ console.log('TextSelectionSearch: Final popover style:', this.popoverStyle);
272
+ console.log('TextSelectionSearch: Final position - top:', top, 'left:', left);
146
273
 
147
274
  this.isVisible = true;
148
275
  this.isHidden = false;
@@ -277,4 +404,43 @@ export default class TextSelectionSearch extends LightningElement {
277
404
  get searchButtonDisabled() {
278
405
  return this.isLoading || !this.searchQuery.trim();
279
406
  }
407
+
408
+ // Check if current page is a spec-based reference
409
+ isSpecBasedReferencePage(): boolean {
410
+ const url = window.location.href;
411
+ const hasMetaParam = url.includes('?meta=');
412
+ const isReferencePage = url.includes('/references/');
413
+ console.log('TextSelectionSearch: URL analysis - hasMetaParam:', hasMetaParam, 'isReferencePage:', isReferencePage);
414
+ return hasMetaParam && isReferencePage;
415
+ }
416
+
417
+ // Additional setup for spec-based references
418
+ setupSpecBasedReferenceHandling() {
419
+ // Wait for the page to be fully loaded
420
+ if (document.readyState === 'loading') {
421
+ document.addEventListener('DOMContentLoaded', () => {
422
+ this.initializeForSpecBasedReference();
423
+ });
424
+ } else {
425
+ this.initializeForSpecBasedReference();
426
+ }
427
+ }
428
+
429
+ initializeForSpecBasedReference() {
430
+ console.log('TextSelectionSearch: Initializing for spec-based reference');
431
+
432
+ // Wait for the .api-documentation container to appear
433
+ const checkForApiDocumentation = () => {
434
+ const apiDocContainer = document.querySelector('.api-documentation');
435
+ if (apiDocContainer) {
436
+ console.log('TextSelectionSearch: Found .api-documentation container, setting up listeners');
437
+ this.setupTextSelectionListener();
438
+ } else {
439
+ console.log('TextSelectionSearch: .api-documentation container not found yet, retrying...');
440
+ setTimeout(checkForApiDocumentation, 500);
441
+ }
442
+ };
443
+
444
+ checkForApiDocumentation();
445
+ }
280
446
  }