js.foresight-devtools 1.4.0 → 2.1.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.mjs ADDED
@@ -0,0 +1,2194 @@
1
+ import{LitElement as e,css as t,html as n}from"lit";import{customElement as r,property as i,query as a,state as o}from"lit/decorators.js";import{ForesightManager as s}from"js.foresight";import{repeat as c}from"lit/directives/repeat.js";const l=[`controlPanel`,`nameTags`,`elementOverlays`,`mouseTrajectory`,`scrollTrajectory`],u=n`
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ width="16"
5
+ height="16"
6
+ viewBox="0 0 24 24"
7
+ fill="none"
8
+ stroke="currentColor"
9
+ stroke-width="2"
10
+ stroke-linecap="round"
11
+ stroke-linejoin="round"
12
+ >
13
+ <rect x="2" y="2" width="20" height="15" rx="2" ry="2"></rect>
14
+ <line x1="2" y1="17" x2="22" y2="17"></line>
15
+ <line x1="7" y1="21" x2="17" y2="21"></line>
16
+ <line x1="12" y1="17" x2="12" y2="21"></line>
17
+ </svg>
18
+ `,d=n`
19
+ <svg
20
+ xmlns="http://www.w3.org/2000/svg"
21
+ width="16"
22
+ height="16"
23
+ viewBox="0 0 24 24"
24
+ fill="none"
25
+ stroke="currentColor"
26
+ stroke-width="2"
27
+ stroke-linecap="round"
28
+ stroke-linejoin="round"
29
+ >
30
+ <polyline points="4 17 10 11 4 5"></polyline>
31
+ <line x1="12" y1="19" x2="20" y2="19"></line>
32
+ </svg>
33
+ `,ee=n`
34
+ <svg
35
+ xmlns="http://www.w3.org/2000/svg"
36
+ width="16"
37
+ height="16"
38
+ viewBox="0 0 24 24"
39
+ fill="none"
40
+ stroke="currentColor"
41
+ stroke-width="2"
42
+ stroke-linecap="round"
43
+ stroke-linejoin="round"
44
+ >
45
+ <path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path>
46
+ <path d="M13.73 21a2 2 0 0 1-3.46 0"></path>
47
+ <line x1="1" y1="1" x2="23" y2="23"></line>
48
+ </svg>
49
+ `,te=n`
50
+ <svg
51
+ xmlns="http://www.w3.org/2000/svg"
52
+ width="16"
53
+ height="16"
54
+ viewBox="0 0 24 24"
55
+ fill="none"
56
+ stroke="currentColor"
57
+ stroke-width="2"
58
+ stroke-linecap="round"
59
+ stroke-linejoin="round"
60
+ >
61
+ <path d="M12 2v8" />
62
+ <path d="M12 10l-6 6" />
63
+ <path d="M12 10l6 6" />
64
+ <circle cx="6" cy="18" r="2" />
65
+ <circle cx="18" cy="18" r="2" />
66
+ </svg>
67
+ `,f=n`
68
+ <svg
69
+ xmlns="http://www.w3.org/2000/svg"
70
+ width="16"
71
+ height="16"
72
+ viewBox="0 0 24 24"
73
+ fill="none"
74
+ stroke="currentColor"
75
+ stroke-width="2"
76
+ stroke-linecap="round"
77
+ stroke-linejoin="round"
78
+ >
79
+ <path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z" />
80
+ <circle cx="12" cy="12" r="3" />
81
+ </svg>
82
+ `,ne=n`
83
+ <svg
84
+ xmlns="http://www.w3.org/2000/svg"
85
+ width="16"
86
+ height="16"
87
+ viewBox="0 0 24 24"
88
+ fill="none"
89
+ stroke="currentColor"
90
+ stroke-width="2"
91
+ stroke-linecap="round"
92
+ stroke-linejoin="round"
93
+ >
94
+ <path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z" />
95
+ <polyline points="14 2 14 8 20 8" />
96
+ <line x1="16" y1="13" x2="8" y2="13" />
97
+ <line x1="16" y1="17" x2="8" y2="17" />
98
+ <line x1="10" y1="9" x2="8" y2="9" />
99
+ </svg>
100
+ `,re=n`
101
+ <svg
102
+ xmlns="http://www.w3.org/2000/svg"
103
+ width="16"
104
+ height="16"
105
+ viewBox="0 0 24 24"
106
+ fill="none"
107
+ stroke="currentColor"
108
+ stroke-width="2"
109
+ stroke-linecap="round"
110
+ stroke-linejoin="round"
111
+ >
112
+ <path d="M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01" />
113
+ </svg>
114
+ `,p=n`
115
+ <svg
116
+ xmlns="http://www.w3.org/2000/svg"
117
+ width="16"
118
+ height="16"
119
+ viewBox="0 0 24 24"
120
+ fill="none"
121
+ stroke="currentColor"
122
+ stroke-width="2"
123
+ stroke-linecap="round"
124
+ stroke-linejoin="round"
125
+ >
126
+ <polygon points="22,3 2,3 10,12.46 10,19 14,21 14,12.46" />
127
+ </svg>
128
+ `,ie=n`
129
+ <svg
130
+ xmlns="http://www.w3.org/2000/svg"
131
+ width="16"
132
+ height="16"
133
+ viewBox="0 0 24 24"
134
+ fill="none"
135
+ stroke="currentColor"
136
+ stroke-width="2"
137
+ stroke-linecap="round"
138
+ stroke-linejoin="round"
139
+ >
140
+ <circle cx="12" cy="12" r="10" />
141
+ <line x1="4.93" y1="4.93" x2="19.07" y2="19.07" />
142
+ </svg>
143
+ `,ae=n`
144
+ <svg
145
+ xmlns="http://www.w3.org/2000/svg"
146
+ width="24"
147
+ height="24"
148
+ viewBox="0 0 24 24"
149
+ fill="none"
150
+ stroke="currentColor"
151
+ stroke-width="2"
152
+ stroke-linecap="round"
153
+ stroke-linejoin="round"
154
+ >
155
+ <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
156
+ <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
157
+ </svg>
158
+ `,m=n`
159
+ <svg
160
+ xmlns="http://www.w3.org/2000/svg"
161
+ width="24"
162
+ height="24"
163
+ viewBox="0 0 24 24"
164
+ fill="none"
165
+ stroke="currentColor"
166
+ stroke-width="2"
167
+ stroke-linecap="round"
168
+ stroke-linejoin="round"
169
+ >
170
+ <polyline points="20 6 9 17 4 12"></polyline>
171
+ </svg>
172
+ `,oe=n`
173
+ <svg
174
+ xmlns="http://www.w3.org/2000/svg"
175
+ width="16"
176
+ height="16"
177
+ viewBox="0 0 24 24"
178
+ fill="none"
179
+ stroke="currentColor"
180
+ stroke-width="2"
181
+ stroke-linecap="round"
182
+ stroke-linejoin="round"
183
+ >
184
+ <path
185
+ d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"
186
+ ></path>
187
+ <line x1="12" y1="9" x2="12" y2="13"></line>
188
+ <line x1="12" y1="17" x2="12.01" y2="17"></line>
189
+ </svg>
190
+ `,se=n`
191
+ <svg
192
+ xmlns="http://www.w3.org/2000/svg"
193
+ width="16"
194
+ height="16"
195
+ viewBox="0 0 24 24"
196
+ fill="none"
197
+ stroke="currentColor"
198
+ stroke-width="2"
199
+ stroke-linecap="round"
200
+ stroke-linejoin="round"
201
+ >
202
+ <circle cx="6" cy="12" r="3"></circle>
203
+ <circle cx="18" cy="12" r="3"></circle>
204
+ <path d="M9 12h6"></path>
205
+ <path d="M15 9l3 3-3 3"></path>
206
+ <circle cx="12" cy="6" r="2"></circle>
207
+ <circle cx="12" cy="18" r="2"></circle>
208
+ <path d="M10 8l2-2 2 2"></path>
209
+ <path d="M14 16l-2 2-2-2"></path>
210
+ </svg>
211
+ `,ce=n`
212
+ <svg
213
+ xmlns="http://www.w3.org/2000/svg"
214
+ width="12"
215
+ height="12"
216
+ viewBox="0 0 24 24"
217
+ fill="none"
218
+ stroke="currentColor"
219
+ stroke-width="2"
220
+ stroke-linecap="round"
221
+ stroke-linejoin="round"
222
+ >
223
+ <polyline points="3 6 5 6 21 6"></polyline>
224
+ <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
225
+ <line x1="10" y1="11" x2="10" y2="17"></line>
226
+ <line x1="14" y1="11" x2="14" y2="17"></line>
227
+ </svg>
228
+ `;n`
229
+ <svg
230
+ xmlns="http://www.w3.org/2000/svg"
231
+ width="16"
232
+ height="16"
233
+ viewBox="0 0 24 24"
234
+ fill="none"
235
+ stroke="currentColor"
236
+ stroke-width="2"
237
+ stroke-linecap="round"
238
+ stroke-linejoin="round"
239
+ >
240
+ <path d="M18 8a6 6 0 0 0-12 0c0 2 3 4 6 6 3-2 6-4 6-6z" />
241
+ <circle cx="12" cy="8" r="3" />
242
+ </svg>
243
+ `,n`
244
+ <svg
245
+ xmlns="http://www.w3.org/2000/svg"
246
+ width="16"
247
+ height="16"
248
+ viewBox="0 0 24 24"
249
+ fill="none"
250
+ stroke="currentColor"
251
+ stroke-width="2"
252
+ stroke-linecap="round"
253
+ stroke-linejoin="round"
254
+ >
255
+ <rect x="2" y="3" width="20" height="14" rx="2" ry="2" />
256
+ <line x1="8" y1="21" x2="16" y2="21" />
257
+ <line x1="12" y1="17" x2="12" y2="21" />
258
+ <circle cx="12" cy="10" r="2" />
259
+ </svg>
260
+ `;const le=n`
261
+ <svg
262
+ xmlns="http://www.w3.org/2000/svg"
263
+ width="16"
264
+ height="16"
265
+ viewBox="0 0 24 24"
266
+ fill="none"
267
+ stroke="currentColor"
268
+ stroke-width="2"
269
+ stroke-linecap="round"
270
+ stroke-linejoin="round"
271
+ >
272
+ <circle cx="12" cy="12" r="10" />
273
+ <line x1="4.93" y1="4.93" x2="19.07" y2="19.07" />
274
+ </svg>
275
+ `,h=n`
276
+ <svg
277
+ xmlns="http://www.w3.org/2000/svg"
278
+ width="12"
279
+ height="12"
280
+ viewBox="0 0 24 24"
281
+ fill="none"
282
+ stroke="currentColor"
283
+ stroke-width="2"
284
+ stroke-linecap="round"
285
+ stroke-linejoin="round"
286
+ >
287
+ <path d="M18.36 6.64a9 9 0 1 1-12.73 0" />
288
+ <line x1="12" y1="2" x2="12" y2="12" />
289
+ </svg>
290
+ `;function g(e,t){if(typeof Reflect==`object`&&typeof Reflect.metadata==`function`)return Reflect.metadata(e,t)}function _(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}let v=class extends e{constructor(...e){super(...e),this.title=``}static{this.styles=[t`
291
+ :host {
292
+ display: inline-block;
293
+ }
294
+
295
+ .chip {
296
+ display: inline-flex;
297
+ align-items: center;
298
+ padding: 3px 8px;
299
+ background-color: rgba(255, 255, 255, 0.05);
300
+ color: #e8e8e8;
301
+ font-size: 10px;
302
+ font-weight: 500;
303
+ white-space: nowrap;
304
+ border: 1px solid rgba(255, 255, 255, 0.1);
305
+ font-family: "SF Mono", "Monaco", "Consolas", "Liberation Mono", "Courier New", monospace;
306
+ letter-spacing: 0.02em;
307
+ line-height: 1.2;
308
+ transition: all 0.2s ease;
309
+ }
310
+ `]}render(){return n`
311
+ <span class="chip" title="${this.title}">
312
+ <slot></slot>
313
+ </span>
314
+ `}};_([i({type:String}),g(`design:type`,String)],v.prototype,`title`,void 0),v=_([r(`chip-element`)],v);let y=class extends e{constructor(...e){super(...e),this.noContentMessage=`No content available.`,this.hasContent=!0}static{this.styles=[t`
315
+ :host {
316
+ overflow: hidden;
317
+ }
318
+
319
+ .content-container::-webkit-scrollbar {
320
+ width: 8px;
321
+ }
322
+
323
+ .content-container::-webkit-scrollbar-track {
324
+ background: rgba(30, 30, 30, 0.5);
325
+ }
326
+
327
+ .content-container::-webkit-scrollbar-thumb {
328
+ background-color: rgba(176, 196, 222, 0.5);
329
+ border: 2px solid rgba(0, 0, 0, 0.2);
330
+ }
331
+
332
+ .content-container::-webkit-scrollbar-thumb:hover {
333
+ background-color: rgba(176, 196, 222, 0.7);
334
+ }
335
+
336
+ .content-container {
337
+ scrollbar-gutter: stable;
338
+ height: 100%;
339
+ min-height: 150px;
340
+ overflow-y: auto;
341
+ scrollbar-width: thin;
342
+ scrollbar-color: rgba(176, 196, 222, 0.5) rgba(30, 30, 30, 0.5);
343
+ }
344
+
345
+ .no-content-message {
346
+ display: flex;
347
+ justify-content: center;
348
+ align-items: center;
349
+ height: 100%;
350
+ color: #afafaf;
351
+ font-style: italic;
352
+ font-family: "Courier New", monospace;
353
+ }
354
+ `]}render(){return n`
355
+ <div class="content-container">
356
+ ${this.hasContent?n`<slot></slot>`:n`<div class="no-content-message">${this.noContentMessage}</div>`}
357
+ </div>
358
+ `}};_([i({type:String,attribute:`no-content-message`}),g(`design:type`,String)],y.prototype,`noContentMessage`,void 0),_([i({type:Boolean}),g(`design:type`,Boolean)],y.prototype,`hasContent`,void 0),y=_([r(`tab-content`)],y);let b=class extends e{static{this.styles=[t`
359
+ :host {
360
+ }
361
+ .tab-bar-info {
362
+ display: flex;
363
+ gap: 12px;
364
+ align-items: center;
365
+ flex: 1;
366
+ }
367
+
368
+ .stats-chips {
369
+ display: flex;
370
+ gap: 8px;
371
+ align-items: center;
372
+ }
373
+
374
+ .chip {
375
+ font-size: 11px;
376
+ font-weight: 500;
377
+ padding: 4px 8px;
378
+ border: 1px solid #555;
379
+ white-space: nowrap;
380
+ letter-spacing: 0.3px;
381
+ background: rgba(40, 40, 40, 0.7);
382
+ color: #b0c4de;
383
+ }
384
+
385
+ .tab-bar-actions {
386
+ display: flex;
387
+ gap: 6px;
388
+ align-items: center;
389
+ position: relative;
390
+ flex-direction: row;
391
+ }
392
+ .tab-bar-elements {
393
+ display: flex;
394
+ justify-content: space-between;
395
+ padding: 4px 0 4px 0;
396
+ border-bottom: 1px solid #444;
397
+ position: sticky;
398
+ top: 0;
399
+ z-index: 5;
400
+ min-height: 36px;
401
+ }
402
+ `]}render(){return n`
403
+ <div class="tab-bar-elements">
404
+ <div class="tab-bar-info">
405
+ <div class="stats-chips">
406
+ <slot name="chips"></slot>
407
+ </div>
408
+ </div>
409
+ <div class="tab-bar-actions">
410
+ <slot name="actions"></slot>
411
+ </div>
412
+ </div>
413
+ `}};b=_([r(`tab-header`)],b);var x=class r extends e{constructor(...e){super(...e),this.isDropdownOpen=!1,this.dropdownOptions=[],this._toggleDropdown=e=>{e.stopPropagation(),this.isDropdownOpen?this._closeDropdown():(r.currentlyOpen&&r.currentlyOpen!==this&&r.currentlyOpen._closeDropdown(),this.isDropdownOpen=!0,r.currentlyOpen=this,this._positionDropdown())},this._handleOutsideClick=e=>{this.isDropdownOpen&&(e.composedPath().includes(this)||this._closeDropdown())}}static{this.currentlyOpen=null}static{this.styles=[t`
414
+ :host {
415
+ display: inline-block;
416
+ }
417
+
418
+ .dropdown-container {
419
+ position: relative;
420
+ display: inline-block;
421
+ }
422
+
423
+ .trigger-button {
424
+ background: none;
425
+ border: none;
426
+ color: white;
427
+ cursor: pointer;
428
+ padding: 6px;
429
+ display: flex;
430
+ align-items: center;
431
+ justify-content: center;
432
+ gap: 4px;
433
+ transition: all 0.2s ease;
434
+ }
435
+
436
+ .trigger-button svg {
437
+ width: 16px;
438
+ height: 16px;
439
+ stroke: white;
440
+ transition: stroke 0.2s;
441
+ }
442
+
443
+ .trigger-button .arrow-icon {
444
+ width: 10px;
445
+ height: 10px;
446
+ stroke: white;
447
+ fill: none;
448
+ stroke-width: 2;
449
+ transition:
450
+ transform 0.2s ease,
451
+ stroke 0.2s;
452
+ }
453
+
454
+ .trigger-button:hover {
455
+ background-color: rgba(176, 196, 222, 0.1);
456
+ }
457
+
458
+ .trigger-button:hover svg,
459
+ .trigger-button:hover .arrow-icon {
460
+ stroke: #b0c4de;
461
+ }
462
+
463
+ .trigger-button.active {
464
+ background-color: rgba(176, 196, 222, 0.2);
465
+ }
466
+
467
+ .trigger-button.active svg {
468
+ stroke: #b0c4de;
469
+ }
470
+
471
+ .trigger-button.active .arrow-icon {
472
+ transform: rotate(180deg);
473
+ stroke: #b0c4de;
474
+ }
475
+
476
+ .dropdown-menu {
477
+ position: fixed;
478
+ z-index: 9999;
479
+ display: none;
480
+ flex-direction: column;
481
+ background-color: #3a3a3a;
482
+ border: 1px solid #555;
483
+ min-width: 200px;
484
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
485
+ overflow: hidden;
486
+ }
487
+
488
+ .dropdown-menu.active {
489
+ display: flex;
490
+ }
491
+
492
+ .dropdown-menu button {
493
+ background: none;
494
+ border: none;
495
+ color: #ccc;
496
+ font-size: 12px;
497
+ text-align: left;
498
+ padding: 8px 12px;
499
+ cursor: pointer;
500
+ transition: all 0.2s ease;
501
+ display: flex;
502
+ align-items: center;
503
+ position: relative;
504
+ width: 100%;
505
+ box-sizing: border-box;
506
+ }
507
+
508
+ .dropdown-menu button:hover {
509
+ background-color: #555;
510
+ color: white;
511
+ }
512
+
513
+ .dropdown-menu button.active {
514
+ color: #b0c4de;
515
+ font-weight: bold;
516
+ background-color: rgba(176, 196, 222, 0.1);
517
+ }
518
+
519
+ .dropdown-menu button.active::after {
520
+ content: "✓";
521
+ position: absolute;
522
+ right: 8px;
523
+ top: 50%;
524
+ transform: translateY(-50%);
525
+ color: #b0c4de;
526
+ font-weight: bold;
527
+ }
528
+ `]}connectedCallback(){super.connectedCallback(),document.addEventListener(`click`,this._handleOutsideClick)}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener(`click`,this._handleOutsideClick),r.currentlyOpen===this&&(r.currentlyOpen=null)}_closeDropdown(){this.isDropdownOpen=!1,r.currentlyOpen===this&&(r.currentlyOpen=null)}_positionDropdown(){if(typeof window>`u`)return;let e=this.shadowRoot?.querySelector(`.trigger-button`),t=this.shadowRoot?.querySelector(`.dropdown-menu`);if(e&&t){let n=e.getBoundingClientRect(),r=t.offsetHeight||200,i=n.bottom+5,a=window.innerWidth-n.right;window.innerHeight-n.bottom<r&&n.top>r?t.style.top=`${n.top-r-5}px`:t.style.top=`${i}px`,t.style.right=`${a}px`}}render(){let e=`trigger-button ${this.isDropdownOpen?`active`:``}`,t=`dropdown-menu ${this.isDropdownOpen?`active`:``}`;return n`
529
+ <div class="dropdown-container">
530
+ <button
531
+ class="${e}"
532
+ title="${this._getTriggerTitle()}"
533
+ @click="${this._toggleDropdown}"
534
+ aria-haspopup="true"
535
+ aria-expanded="${this.isDropdownOpen}"
536
+ aria-controls="dropdown-menu"
537
+ aria-label="${this._getTriggerLabel()}"
538
+ >
539
+ ${this._getTriggerIcon()}
540
+ <svg
541
+ class="arrow-icon"
542
+ xmlns="http://www.w3.org/2000/svg"
543
+ viewBox="0 0 24 24"
544
+ stroke="currentColor"
545
+ stroke-width="2"
546
+ stroke-linecap="round"
547
+ stroke-linejoin="round"
548
+ >
549
+ <polyline points="6 9 12 15 18 9"></polyline>
550
+ </svg>
551
+ </button>
552
+
553
+ <div class="${t}" id="dropdown-menu" role="menu">
554
+ ${this.dropdownOptions.map(e=>n`
555
+ <button
556
+ value="${e.value}"
557
+ title="${e.title}"
558
+ class="${this._isOptionSelected(e)?`active`:``}"
559
+ @click="${()=>this._handleOptionClick(e)}"
560
+ role="menuitem"
561
+ >
562
+ ${e.label}
563
+ </button>
564
+ `)}
565
+ </div>
566
+ </div>
567
+ `}};_([o(),g(`design:type`,Boolean)],x.prototype,`isDropdownOpen`,void 0),_([i({type:Array}),g(`design:type`,Array)],x.prototype,`dropdownOptions`,void 0);let S=class extends x{constructor(...e){super(...e),this.selectedOptionValue=``}connectedCallback(){super.connectedCallback(),this.dropdownOptions.length>0&&!this.selectedOptionValue&&(this.selectedOptionValue=this.dropdownOptions[0].value)}willUpdate(e){e.has(`dropdownOptions`)&&this.dropdownOptions.length>0&&!this.selectedOptionValue&&(this.selectedOptionValue=this.dropdownOptions[0].value)}_handleOptionClick(e){e.value!==this.selectedOptionValue&&(this.selectedOptionValue=e.value,this.onSelectionChange?.(e.value)),this._closeDropdown()}_getTriggerIcon(){let e=this._getSelectedOption();return e?e.icon:n``}_isOptionSelected(e){return e.value===this.selectedOptionValue}_getTriggerTitle(){let e=this._getSelectedOption();return e?e.title:`Change selection`}_getTriggerLabel(){let e=this._getSelectedOption();return e?`Current selection: ${e.label}`:`No selection`}_getSelectedOption(){return this.dropdownOptions.find(e=>e.value===this.selectedOptionValue)}};_([i({type:String}),g(`design:type`,String)],S.prototype,`selectedOptionValue`,void 0),_([i({type:Function}),g(`design:type`,Function)],S.prototype,`onSelectionChange`,void 0),S=_([r(`single-select-dropdown`)],S);let C=class extends e{constructor(...e){super(...e),this.title=`Copy to clipboard`,this.isCopied=!1,this.copyTimeout=null}static{this.styles=t`
568
+ .copy-button {
569
+ background: transparent;
570
+ border: 0px;
571
+ cursor: pointer;
572
+ padding: 6px;
573
+ display: flex;
574
+ align-items: center;
575
+ justify-content: center;
576
+ opacity: 0.6;
577
+ transition:
578
+ opacity 0.2s ease,
579
+ background-color 0.2s ease;
580
+ }
581
+
582
+ :host([positioned]) .copy-button {
583
+ position: absolute;
584
+ top: 10px;
585
+ right: 1px;
586
+ }
587
+
588
+ .copy-button:hover {
589
+ background-color: rgba(176, 196, 222, 0.1);
590
+ }
591
+
592
+ .copy-button:hover svg {
593
+ stroke: #b0c4de;
594
+ }
595
+
596
+ .copy-button svg {
597
+ width: 14px;
598
+ height: 14px;
599
+ stroke: #ddd;
600
+ stroke-width: 2.5;
601
+ }
602
+
603
+ .copy-button.copied svg {
604
+ stroke: #4caf50;
605
+ }
606
+ `}async handleClick(e){if(!this.isCopied){if(this.onCopy)try{await this.onCopy(e)}catch(e){console.error(`Error in onCopy function:`,e)}this.isCopied=!0,this.copyTimeout&&clearTimeout(this.copyTimeout),this.copyTimeout=setTimeout(()=>{this.isCopied=!1,this.copyTimeout=null},2e3)}}disconnectedCallback(){super.disconnectedCallback(),this.copyTimeout&&=(clearTimeout(this.copyTimeout),null)}render(){return n`
607
+ <button
608
+ class="copy-button ${this.isCopied?`copied`:``}"
609
+ title="${this.title}"
610
+ @click=${this.handleClick}
611
+ >
612
+ ${this.isCopied?m:ae}
613
+ </button>
614
+ `}};_([i({type:String}),g(`design:type`,String)],C.prototype,`title`,void 0),_([i({type:Function}),g(`design:type`,Function)],C.prototype,`onCopy`,void 0),_([o(),g(`design:type`,Boolean)],C.prototype,`isCopied`,void 0),_([o(),g(`design:type`,Object)],C.prototype,`copyTimeout`,void 0),C=_([r(`copy-icon`)],C);let w=class extends e{constructor(...e){super(...e),this.borderColor=`#555`,this.showCopyButton=!1,this.itemId=``,this.isExpanded=!1}static{this.styles=[t`
615
+ :host {
616
+ display: block;
617
+ }
618
+
619
+ .item-entry {
620
+ margin-bottom: 2px;
621
+ font-size: 11px;
622
+ line-height: 1.3;
623
+ overflow: hidden;
624
+ transition: all 0.2s ease;
625
+ border-left: 2px solid var(--border-color, #555);
626
+ padding-left: 6px;
627
+ }
628
+
629
+ .item-entry:hover:not(.expanded) {
630
+ background-color: rgba(255, 255, 255, 0.02);
631
+ }
632
+
633
+ .item-entry.expanded {
634
+ background-color: rgba(255, 255, 255, 0.03);
635
+ }
636
+
637
+ .item-header {
638
+ display: flex;
639
+ align-items: center;
640
+ padding: 3px 4px;
641
+ cursor: pointer;
642
+ transition: background-color 0.2s ease;
643
+ gap: 8px;
644
+ min-height: 20px;
645
+ }
646
+
647
+ .item-header:hover:not(.expanded) {
648
+ background-color: rgba(255, 255, 255, 0.03);
649
+ }
650
+
651
+ .item-details {
652
+ position: relative;
653
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
654
+ }
655
+
656
+ .item-toggle {
657
+ display: flex;
658
+ align-items: center;
659
+ justify-content: center;
660
+ width: 16px;
661
+ height: 16px;
662
+
663
+ user-select: none;
664
+ cursor: pointer;
665
+ transition: all 0.2s ease;
666
+ }
667
+
668
+ .item-toggle:hover {
669
+ background-color: rgba(255, 255, 255, 0.1);
670
+ }
671
+
672
+ .item-toggle svg {
673
+ width: 14px;
674
+ height: 14px;
675
+ fill: none;
676
+ stroke: #b0c4de;
677
+ stroke-width: 2;
678
+ stroke-linecap: round;
679
+ stroke-linejoin: round;
680
+ transition: all 0.2s ease;
681
+ }
682
+
683
+ .item-toggle:hover svg {
684
+ stroke: #d4e4f4;
685
+ }
686
+
687
+ .item-toggle.expanded svg {
688
+ transform: rotate(90deg);
689
+ }
690
+
691
+ .item-content {
692
+ flex: 1;
693
+ display: flex;
694
+ align-items: center;
695
+ gap: 8px;
696
+ min-width: 0;
697
+ overflow: hidden;
698
+ }
699
+
700
+ .item-data {
701
+ color: #e0e0e0;
702
+ white-space: pre;
703
+ font-size: 11px;
704
+ margin: 0;
705
+ padding: 0;
706
+ font-family: "Courier New", monospace;
707
+ line-height: 1.3;
708
+ display: block;
709
+ overflow-x: auto;
710
+ }
711
+ `]}toggleExpand(){this.onToggle&&this.onToggle(this.itemId)}async handleCopy(e){e.stopPropagation();let t=this.shadowRoot?.querySelector(`slot[name="details"]`);if(t){let e=t.assignedNodes().map(e=>e.textContent).join(``);try{await navigator.clipboard.writeText(e)}catch(e){console.error(`Failed to copy text: `,e)}}}render(){return this.style.setProperty(`--border-color`,this.borderColor),n`
712
+ <div class="item-entry ${this.isExpanded?`expanded`:``}">
713
+ <div class="item-header ${this.isExpanded?`expanded`:``}" @click="${this.toggleExpand}">
714
+ <div class="item-content">
715
+ <slot name="content"></slot>
716
+ </div>
717
+ <span class="item-toggle ${this.isExpanded?`expanded`:``}">
718
+ <svg viewBox="0 0 24 24">
719
+ <polyline points="9,18 15,12 9,6"></polyline>
720
+ </svg>
721
+ </span>
722
+ </div>
723
+ ${this.isExpanded?n`
724
+ <div class="item-details">
725
+ <copy-icon
726
+ positioned
727
+ title="Copy Details"
728
+ .onCopy=${e=>this.handleCopy(e)}
729
+ ></copy-icon>
730
+ <pre class="item-data">
731
+ <slot name="details"></slot>
732
+ </pre>
733
+ </div>
734
+ `:``}
735
+ </div>
736
+ `}};_([i(),g(`design:type`,String)],w.prototype,`borderColor`,void 0),_([i(),g(`design:type`,Boolean)],w.prototype,`showCopyButton`,void 0),_([i(),g(`design:type`,String)],w.prototype,`itemId`,void 0),_([i(),g(`design:type`,Boolean)],w.prototype,`isExpanded`,void 0),_([i(),g(`design:type`,Object)],w.prototype,`onToggle`,void 0),w=_([r(`expandable-item`)],w);let T=class extends e{constructor(...e){super(...e),this.remainingTime=0,this.isCountdownActive=!1,this.intervalId=null,this.startTime=0,this.lastDisplayedTime=``,this.countdownForElement=null,this.countdownReactivateAfter=0,this.handleTimerClick=e=>{e.stopPropagation(),s.instance.reactivate(this.element)}}static{this.styles=[t`
737
+ :host {
738
+ display: inline-block;
739
+ }
740
+
741
+ .reactivate-button {
742
+ all: unset;
743
+ cursor: pointer;
744
+ padding: 2px 4px;
745
+ transition: background-color 0.2s ease;
746
+ }
747
+
748
+ .reactivate-button:hover {
749
+ background-color: rgba(255, 165, 0, 0.1);
750
+ }
751
+
752
+ .countdown-time {
753
+ color: #ffa726;
754
+ font-weight: 500;
755
+ font-size: 10px;
756
+ }
757
+
758
+ .countdown-time.infinity {
759
+ font-size: 12px;
760
+ font-weight: 600;
761
+ }
762
+
763
+ .countdown-time.clickable {
764
+ cursor: pointer;
765
+ }
766
+ `]}connectedCallback(){super.connectedCallback(),this.checkAndStartCountdown()}disconnectedCallback(){super.disconnectedCallback(),this.clearCountdown()}willUpdate(e){super.willUpdate(e),e.has(`state`)&&this.checkAndStartCountdown()}checkAndStartCountdown(){let e=this.state;if(!e){this.clearCountdown();return}let t=e.status!==void 0;!e.isActive&&t&&e.reactivateAfter>0?this.startCountdown():this.clearCountdown()}startCountdown(){if(this.isCountdownActive&&this.countdownForElement===this.element&&this.countdownReactivateAfter===this.state.reactivateAfter)return;this.clearCountdown();let e=this.state;if(!e)return;if(this.countdownForElement=this.element,this.countdownReactivateAfter=e.reactivateAfter,this.isCountdownActive=!0,e.reactivateAfter===1/0){this.remainingTime=1/0;return}let t=e.reactivateAfter;this.startTime=Date.now();let n=()=>{let e=Date.now()-this.startTime,n=Math.max(0,t-e),r=this.formatTime(n);r!==this.lastDisplayedTime&&(this.lastDisplayedTime=r,this.remainingTime=n,this.requestUpdate()),(n<=0||this.state.isActive)&&this.clearCountdown()};n(),this.remainingTime>0&&typeof window<`u`&&(this.intervalId=window.setInterval(n,100))}clearCountdown(){this.intervalId!==null&&(clearInterval(this.intervalId),this.intervalId=null),this.isCountdownActive=!1,this.remainingTime=0,this.lastDisplayedTime=``,this.countdownForElement=null,this.countdownReactivateAfter=0}formatTime(e){if(e===1/0)return`∞`;let t=Math.ceil(e/1e3);if(t<60)return`${t}s`;let n=Math.floor(t/60),r=t%60;if(n<60)return r>0?`${n}m ${r}s`:`${n}m`;let i=Math.floor(n/60),a=n%60;return a>0?`${i}h ${a}m`:`${i}h`}render(){return this.isCountdownActive?this.remainingTime===1/0?n`
767
+ <button
768
+ class="reactivate-button"
769
+ @click="${this.handleTimerClick}"
770
+ title="Click to reactivate manually"
771
+ >
772
+ <span class="countdown-time infinity">∞</span>
773
+ </button>
774
+ `:this.remainingTime<=0?n``:n`
775
+ <button
776
+ class="reactivate-button"
777
+ @click="${this.handleTimerClick}"
778
+ title="Click to reactivate immediately"
779
+ >
780
+ <span class="countdown-time clickable">${this.formatTime(this.remainingTime)}</span>
781
+ </button>
782
+ `:n``}};_([i({attribute:!1}),g(`design:type`,Object)],T.prototype,`element`,void 0),_([i({attribute:!1}),g(`design:type`,Object)],T.prototype,`state`,void 0),_([o(),g(`design:type`,Number)],T.prototype,`remainingTime`,void 0),_([o(),g(`design:type`,Boolean)],T.prototype,`isCountdownActive`,void 0),T=_([r(`reactivate-countdown`)],T);let E=class extends e{constructor(...e){super(...e),this.isExpanded=!1,this.currentDeviceStrategy=`mouse`,this._abortController=null,this.handleUnregister=e=>{e.stopPropagation(),s.instance.unregister(this.element,`devtools`)},this.handleToggleEnabled=e=>{e.stopPropagation(),s.instance.updateElementOptions(this.element,{enabled:!this.state.isEnabled})}}static{this.styles=[t`
783
+ :host {
784
+ display: block;
785
+ }
786
+
787
+ .element-wrapper {
788
+ display: block;
789
+ }
790
+
791
+ .element-content {
792
+ display: flex;
793
+ align-items: center;
794
+ gap: 8px;
795
+ flex: 1;
796
+ min-width: 0;
797
+ }
798
+
799
+ .status-indicator {
800
+ margin-left: 2px;
801
+ width: 8px;
802
+ height: 8px;
803
+ flex-shrink: 0;
804
+ transition: all 0.3s ease;
805
+ }
806
+
807
+ .status-indicator.visible {
808
+ background-color: #4caf50;
809
+ box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.3);
810
+ }
811
+
812
+ .status-indicator.hidden {
813
+ background-color: #666;
814
+ box-shadow: 0 0 0 2px rgba(102, 102, 102, 0.2);
815
+ }
816
+
817
+ .status-indicator.prefetching {
818
+ background-color: #ffeb3b;
819
+ box-shadow: 0 0 0 2px rgba(255, 235, 59, 0.4);
820
+ }
821
+
822
+ .status-indicator.inactive {
823
+ background-color: #999;
824
+ box-shadow: 0 0 0 2px rgba(153, 153, 153, 0.3);
825
+ }
826
+
827
+ .reason-tags {
828
+ display: inline-flex;
829
+ align-items: baseline;
830
+ gap: 7px;
831
+ flex-shrink: 0;
832
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
833
+ font-size: 10px;
834
+ }
835
+
836
+ .reason-tag {
837
+ white-space: nowrap;
838
+ color: color-mix(in srgb, var(--reason-color) 80%, #fff);
839
+ }
840
+
841
+ .reason-tag::before {
842
+ content: "/";
843
+ margin-right: 3px;
844
+ color: #555;
845
+ }
846
+
847
+ .status-indicator.touch-device {
848
+ background-color: #ba68c8;
849
+ box-shadow: 0 0 0 2px rgba(186, 104, 200, 0.4);
850
+ }
851
+
852
+ .unregister-button,
853
+ .toggle-enabled-button,
854
+ .enable-button {
855
+ all: unset;
856
+ display: flex;
857
+ align-items: center;
858
+ justify-content: center;
859
+ width: 14px;
860
+ height: 14px;
861
+ padding: 1px;
862
+ cursor: pointer;
863
+ color: #999;
864
+ }
865
+
866
+ .unregister-button svg,
867
+ .toggle-enabled-button svg,
868
+ .enable-button svg {
869
+ width: 12px;
870
+ height: 12px;
871
+ }
872
+
873
+ .unregister-button:hover {
874
+ background-color: rgba(255, 107, 107, 0.1);
875
+ color: #ff6b6b;
876
+ }
877
+
878
+ .toggle-enabled-button:hover {
879
+ background-color: rgba(255, 165, 0, 0.1);
880
+ color: #ffa726;
881
+ }
882
+
883
+ .enable-button:hover {
884
+ background-color: rgba(76, 175, 80, 0.1);
885
+ color: #4caf50;
886
+ }
887
+
888
+ .element-name {
889
+ flex-grow: 1;
890
+ min-width: 0;
891
+ white-space: nowrap;
892
+ overflow: hidden;
893
+ text-overflow: ellipsis;
894
+ font-size: 11px;
895
+ font-weight: 500;
896
+ color: #e8e8e8;
897
+ }
898
+
899
+ .element-name.callback-active {
900
+ color: #fff;
901
+ font-weight: 600;
902
+ }
903
+
904
+ .element-name.callback-inactive {
905
+ color: #999;
906
+ font-weight: 500;
907
+ }
908
+
909
+ .reactivate-countdown {
910
+ font-size: 14px;
911
+ color: #ffa726;
912
+ font-weight: 500;
913
+ min-width: 0;
914
+ white-space: nowrap;
915
+ }
916
+
917
+ .reactivate-countdown:empty {
918
+ display: none;
919
+ }
920
+
921
+ :host(.not-visible) {
922
+ opacity: 0.5;
923
+ }
924
+
925
+ .element-wrapper.not-visible {
926
+ opacity: 0.5;
927
+ }
928
+ `]}connectedCallback(){super.connectedCallback(),this._abortController=new AbortController;let{signal:e}=this._abortController;this.currentDeviceStrategy=s.instance.getManagerData.currentDeviceStrategy,s.instance.addEventListener(`deviceStrategyChanged`,e=>{this.currentDeviceStrategy=e.newStrategy},{signal:e})}disconnectedCallback(){super.disconnectedCallback(),this._abortController?.abort(),this._abortController=null}getInactiveReasons(){let e=[];return this.state.isEnabled||e.push({label:`disabled`,color:`#9e9e9e`,description:`Element is disabled, so its callback won't run until you re-enable it.`}),this.state.isParked&&e.push({label:`parked`,color:`#7986cb`,description:`Element is detached from the DOM and parked: kept registered but inactive until it reconnects.`}),this.state.isLimitedConnection&&e.push({label:`limited`,color:`#ffb74d`,description:`Element is on a limited connection (e.g. Save-Data or slow network), so prediction is paused.`}),this.state.isEnabled&&!this.state.isParked&&!this.state.isLimitedConnection&&!this.state.isActive&&this.state.isPredicted&&e.push({label:`fired`,color:`#4dd0e1`,description:`Callback already fired. Stays inactive until reactivated (never, unless reactivateAfter is set).`}),e}getBorderColor(){return this.state.isCallbackRunning?`#ffeb3b`:this.state.isActive?this.currentDeviceStrategy===`touch`?`#ba68c8`:this.state.isIntersectingWithViewport?`#4caf50`:`#666`:`#999`}getStatusIndicatorClass(){return this.state.isCallbackRunning?`prefetching`:this.state.isActive?this.currentDeviceStrategy===`touch`?`touch-device`:this.state.isIntersectingWithViewport?`visible`:`hidden`:`inactive`}getStatusText(){if(this.state.isCallbackRunning)return`callback active`;if(!this.state.isActive){let e=this.getInactiveReasons();return e.length?`inactive: ${e.map(e=>e.label).join(`, `)}`:`inactive`}return(this.state.isIntersectingWithViewport?`in viewport`:`not in viewport`)+(this.currentDeviceStrategy===`touch`?` (touch device)`:``)}formatElementDetails(){return this.isExpanded?JSON.stringify({...this.state,status:this.getStatusText()},null,2):``}render(){let e=!this.state.isIntersectingWithViewport&&this.currentDeviceStrategy!==`touch`,t=this.getInactiveReasons();return n`
929
+ <div class="element-wrapper ${e?`not-visible`:``}">
930
+ <expandable-item
931
+ .borderColor=${this.getBorderColor()}
932
+ .showCopyButton=${!0}
933
+ .itemId=${this.state.id}
934
+ .isExpanded=${this.isExpanded}
935
+ .onToggle=${this.onToggle}
936
+ >
937
+ <div slot="content" class="element-content" title="Status: ${this.getStatusText()}">
938
+ <div class="status-indicator ${this.getStatusIndicatorClass()}"></div>
939
+ <span
940
+ class="element-name ${this.state.isCallbackRunning?`callback-active`:this.state.isActive?``:`callback-inactive`}"
941
+ >
942
+ ${this.state.name||`unnamed`}
943
+ </span>
944
+ ${t.length?n`
945
+ <span class="reason-tags">
946
+ ${t.map(e=>n`<span
947
+ class="reason-tag"
948
+ style="--reason-color: ${e.color}"
949
+ title="${e.label}: ${e.description}"
950
+ >${e.label}</span
951
+ >`)}
952
+ </span>
953
+ `:``}
954
+ ${this.state.isEnabled?n`
955
+ <reactivate-countdown .element=${this.element} .state=${this.state}>
956
+ </reactivate-countdown>
957
+ <button
958
+ class="toggle-enabled-button"
959
+ @click="${this.handleToggleEnabled}"
960
+ title="Disable element"
961
+ >
962
+ ${le}
963
+ </button>
964
+ `:n`
965
+ <button
966
+ class="enable-button"
967
+ @click="${this.handleToggleEnabled}"
968
+ title="Enable element"
969
+ >
970
+ ${h}
971
+ </button>
972
+ `}
973
+ <button
974
+ class="unregister-button"
975
+ @click="${this.handleUnregister}"
976
+ title="Unregister element"
977
+ >
978
+ ${ce}
979
+ </button>
980
+ </div>
981
+ <div slot="details">${this.formatElementDetails()}</div>
982
+ </expandable-item>
983
+ </div>
984
+ `}};_([i({attribute:!1}),g(`design:type`,Object)],E.prototype,`element`,void 0),_([i({attribute:!1}),g(`design:type`,Object)],E.prototype,`state`,void 0),_([i(),g(`design:type`,Boolean)],E.prototype,`isExpanded`,void 0),_([i(),g(`design:type`,Object)],E.prototype,`onToggle`,void 0),_([o(),g(`design:type`,String)],E.prototype,`currentDeviceStrategy`,void 0),E=_([r(`single-element`)],E);var D,O;let k=class extends e{static{this.styles=t`
985
+ :host {
986
+ display: flex;
987
+ flex-direction: column;
988
+ height: 100%;
989
+ }
990
+
991
+ .chips-container {
992
+ display: flex;
993
+ gap: 8px;
994
+ }
995
+
996
+ .element-section {
997
+ margin-bottom: 16px;
998
+ }
999
+
1000
+ .element-section:last-child {
1001
+ margin-bottom: 0;
1002
+ }
1003
+
1004
+ .section-header {
1005
+ margin: 4px 0 4px 0;
1006
+ font-size: 12px;
1007
+ font-weight: 600;
1008
+ cursor: pointer;
1009
+ user-select: none;
1010
+ display: flex;
1011
+ align-items: center;
1012
+ gap: 4px;
1013
+ }
1014
+
1015
+ .section-header:hover {
1016
+ opacity: 0.8;
1017
+ }
1018
+
1019
+ .section-header::before {
1020
+ content: "▼";
1021
+ display: inline-block;
1022
+ transition: transform 0.15s ease;
1023
+ font-size: 10px;
1024
+ }
1025
+
1026
+ .section-header.collapsed::before {
1027
+ transform: rotate(-90deg);
1028
+ }
1029
+
1030
+ .section-header.active {
1031
+ color: #e8e8e8;
1032
+ }
1033
+
1034
+ .section-header.inactive {
1035
+ color: #999;
1036
+ }
1037
+ `}get hitCount(){return s.instance.getManagerData.globalCallbackHits}constructor(){super(),this.elementListItems=new Map,this.noContentMessage=`No Elements Registered To The Foresight Manager`,this.expandedElementIds=new Set,this.activeSectionCollapsed=!1,this.inactiveSectionCollapsed=!1,this._abortController=null,this._elementSubscriptions=new Map,this._pendingElementUpdates=new Map,this._updateDebounceId=null,this._cachedActiveElements=[],this._cachedInactiveElements=[],this._elementsCacheDirty=!0,this.handleSortChange=e=>{this.sortOrder=e,this._elementsCacheDirty=!0},this.handleElementToggle=e=>{let t=new Set(this.expandedElementIds);t.has(e)?t.delete(e):t.add(e),this.expandedElementIds=t},this.sortByDocumentPosition=(e,t)=>{let n=e.element.compareDocumentPosition(t.element);return n&Node.DOCUMENT_POSITION_FOLLOWING?-1:n&Node.DOCUMENT_POSITION_PRECEDING?1:0},this.sortOrder=$.instance.devtoolsSettings.sortElementList,this.sortDropdown=[{value:`visibility`,label:`Visibility`,title:`Sort by Visibility`,icon:f},{value:`documentOrder`,label:`Document Order`,title:`Sort by Document Order`,icon:ne},{value:`insertionOrder`,label:`Insertion Order`,title:`Sort by Insertion Order`,icon:re}]}_generateHitsChipTitle(e){let t=[];t.push(`Total Callback Hits: ${e.total}`),t.push(``);let n=e.mouse.trajectory+e.mouse.hover,r=e.scroll.up+e.scroll.down+e.scroll.left+e.scroll.right,i=e.tab.forwards+e.tab.reverse;t.push(`Desktop Strategy`),n>0?t.push(` Mouse (${n}): ${e.mouse.trajectory} trajectory, ${e.mouse.hover} hover`):t.push(` Mouse: No hits`),r>0?t.push(` Scroll (${r}): Up ${e.scroll.up}, Down ${e.scroll.down}, Left ${e.scroll.left}, Right ${e.scroll.right}`):t.push(` Scroll: No hits`),i>0?t.push(` Tab (${i}): ${e.tab.forwards} forward, ${e.tab.reverse} reverse`):t.push(` Tab: No hits`),t.push(``);let a=e.touch+e.viewport;return t.push(`Touch Strategy`),e.touch>0?t.push(` Touch Start: ${e.touch}`):t.push(` Touch Start: No hits`),e.viewport>0?t.push(` Viewport Enter: ${e.viewport}`):t.push(` Viewport Enter: No hits`),a===0&&n+r+i===0&&(t.push(``),t.push(`Interact with registered elements to see callback statistics`)),t.join(`
1038
+ `)}_subscribeToElement(e){if(this._elementSubscriptions.has(e))return;let t=s.instance.subscribeToElement(e,()=>{let t=s.instance.registeredElements.get(e);!t||!t.isRegistered||(this._pendingElementUpdates.set(e,t),this._scheduleDebouncedUpdate())});t&&this._elementSubscriptions.set(e,t)}_unsubscribeFromElement(e){this._elementSubscriptions.get(e)?.(),this._elementSubscriptions.delete(e)}connectedCallback(){super.connectedCallback(),this._abortController=new AbortController;let{signal:e}=this._abortController;this.updateElementListFromManager();for(let e of this.elementListItems.keys())this._subscribeToElement(e);s.instance.addEventListener(`elementRegistered`,e=>{this.elementListItems.set(e.element,e.state),this._subscribeToElement(e.element),this._elementsCacheDirty=!0,this.requestUpdate()},{signal:e}),s.instance.addEventListener(`elementUnregistered`,e=>{this._unsubscribeFromElement(e.element),this.elementListItems.delete(e.element),this._pendingElementUpdates.delete(e.element),this.elementListItems.size||(this.noContentMessage=`No Elements Registered To The Foresight Manager`),this._elementsCacheDirty=!0,this.requestUpdate()},{signal:e}),s.instance.addEventListener(`callbackInvoked`,e=>{this._pendingElementUpdates.set(e.element,e.state),this._scheduleDebouncedUpdate()},{signal:e}),s.instance.addEventListener(`callbackCompleted`,()=>{this.requestUpdate()},{signal:e})}disconnectedCallback(){super.disconnectedCallback(),this._abortController?.abort(),this._abortController=null;for(let e of this._elementSubscriptions.values())e();this._elementSubscriptions.clear(),this._updateDebounceId!==null&&(clearTimeout(this._updateDebounceId),this._updateDebounceId=null),this._pendingElementUpdates.clear()}_scheduleDebouncedUpdate(){this._updateDebounceId===null&&(this._updateDebounceId=setTimeout(()=>{this._updateDebounceId=null,this._flushPendingUpdates()},16))}_flushPendingUpdates(){if(this._pendingElementUpdates.size!==0){for(let[e,t]of this._pendingElementUpdates){let n=this.elementListItems.get(e);(!n||n.isActive!==t.isActive||n.isIntersectingWithViewport!==t.isIntersectingWithViewport)&&(this._elementsCacheDirty=!0),this.elementListItems.set(e,t)}this._pendingElementUpdates.clear(),this.requestUpdate()}}updateElementListFromManager(){this.elementListItems=new Map(s.instance.registeredElements),this._elementsCacheDirty=!0}getSortedElements(){let e=Array.from(this.elementListItems,([e,t])=>({element:e,state:t}));switch(this.sortOrder){case`insertionOrder`:return e;case`documentOrder`:return e.sort(this.sortByDocumentPosition);case`visibility`:return e.sort((e,t)=>e.state.isIntersectingWithViewport===t.state.isIntersectingWithViewport?this.sortByDocumentPosition(e,t):e.state.isIntersectingWithViewport?-1:1);default:return this.sortOrder,e}}_recomputeElementsCache(){if(!this._elementsCacheDirty)return;let e=[],t=[];for(let n of this.getSortedElements())n.state.isActive?e.push(n.element):t.push(n.element);this._cachedActiveElements=e,this._cachedInactiveElements=t,this._elementsCacheDirty=!1}get activeElements(){return this._recomputeElementsCache(),this._cachedActiveElements}get inactiveElements(){return this._recomputeElementsCache(),this._cachedInactiveElements}renderElementSection(e,t,r,i,a){return r.length===0?``:n`
1039
+ <div class="element-section">
1040
+ <h3
1041
+ class="section-header ${t} ${i?`collapsed`:``}"
1042
+ @click=${a}
1043
+ >
1044
+ ${e} (${r.length})
1045
+ </h3>
1046
+ ${i?``:c(r,e=>this.elementListItems.get(e)?.id??``,e=>{let t=this.elementListItems.get(e);return t?n`
1047
+ <single-element
1048
+ .element=${e}
1049
+ .state=${t}
1050
+ .isExpanded=${this.expandedElementIds.has(t.id)}
1051
+ .onToggle=${this.handleElementToggle}
1052
+ >
1053
+ </single-element>
1054
+ `:``})}
1055
+ </div>
1056
+ `}render(){return n`
1057
+ <tab-header>
1058
+ <div slot="chips" class="chips-container">
1059
+ <chip-element title="${this._generateHitsChipTitle(this.hitCount)}">
1060
+ ${this.hitCount.total} hits
1061
+ </chip-element>
1062
+ </div>
1063
+ <div slot="actions">
1064
+ <single-select-dropdown
1065
+ .dropdownOptions="${this.sortDropdown}"
1066
+ .selectedOptionValue="${this.sortOrder}"
1067
+ .onSelectionChange="${this.handleSortChange}"
1068
+ ></single-select-dropdown>
1069
+ </div>
1070
+ </tab-header>
1071
+ <tab-content
1072
+ .noContentMessage=${this.noContentMessage}
1073
+ .hasContent=${!!this.elementListItems.size}
1074
+ >
1075
+ ${this.renderElementSection(`Active Elements`,`active`,this.activeElements,this.activeSectionCollapsed,()=>{this.activeSectionCollapsed=!this.activeSectionCollapsed})}
1076
+ ${this.renderElementSection(`Inactive Elements`,`inactive`,this.inactiveElements,this.inactiveSectionCollapsed,()=>{this.inactiveSectionCollapsed=!this.inactiveSectionCollapsed})}
1077
+ </tab-content>
1078
+ `}};_([o(),g(`design:type`,Array)],k.prototype,`sortDropdown`,void 0),_([o(),g(`design:type`,Object)],k.prototype,`sortOrder`,void 0),_([o(),g(`design:type`,typeof(D=typeof Map<`u`&&Map)==`function`?D:Object)],k.prototype,`elementListItems`,void 0),_([o(),g(`design:type`,String)],k.prototype,`noContentMessage`,void 0),_([o(),g(`design:type`,typeof(O=typeof Set<`u`&&Set)==`function`?O:Object)],k.prototype,`expandedElementIds`,void 0),_([o(),g(`design:type`,Object)],k.prototype,`activeSectionCollapsed`,void 0),_([o(),g(`design:type`,Object)],k.prototype,`inactiveSectionCollapsed`,void 0),k=_([r(`element-tab`),g(`design:paramtypes`,[])],k);let A=class extends e{constructor(...e){super(...e),this.activeTab=`settings`,this.tabs=[`settings`,`elements`,`logs`]}static{this.styles=t`
1079
+ .tab-selector-wrapper {
1080
+ border-bottom: 2px solid #444;
1081
+ margin-top: 12px;
1082
+ display: flex;
1083
+ justify-content: space-evenly;
1084
+ width: 100%;
1085
+ }
1086
+
1087
+ .tab-button {
1088
+ background: none;
1089
+ border: none;
1090
+ color: #9e9e9e;
1091
+ flex: 1;
1092
+ padding: 8px;
1093
+ cursor: pointer;
1094
+ border-bottom: 2px solid transparent;
1095
+ transition: all 0.2s ease;
1096
+ font-size: 13px;
1097
+ font-weight: 500;
1098
+ text-align: center;
1099
+ }
1100
+ .tab-button:hover {
1101
+ color: #b0c4de;
1102
+ background-color: rgba(176, 196, 222, 0.1);
1103
+ }
1104
+
1105
+ .tab-button.active {
1106
+ color: #b0c4de;
1107
+ border-bottom-color: #b0c4de;
1108
+ }
1109
+ `}_handleTabClick(e){this.dispatchEvent(new CustomEvent(`tab-change`,{detail:{tab:e},bubbles:!0,composed:!0}))}render(){return n`
1110
+ <div class="tab-selector-wrapper">
1111
+ ${this.tabs.map(e=>n`
1112
+ <button
1113
+ class="tab-button ${this.activeTab===e?`active`:``}"
1114
+ @click="${()=>this._handleTabClick(e)}"
1115
+ data-tab="${e}"
1116
+ >
1117
+ ${e.charAt(0).toUpperCase()+e.slice(1)}
1118
+ </button>
1119
+ `)}
1120
+ </div>
1121
+ `}};_([i({type:String}),g(`design:type`,Object)],A.prototype,`activeTab`,void 0),A=_([r(`tab-selector`)],A);let j=class extends x{constructor(...e){super(...e),this.selectedValues=[]}static{this.styles=[...x.styles,t`
1122
+ .dropdown-menu button.active::after {
1123
+ content: "✓";
1124
+ position: absolute;
1125
+ right: 8px;
1126
+ top: 50%;
1127
+ transform: translateY(-50%);
1128
+ color: #b0c4de;
1129
+ font-weight: bold;
1130
+ }
1131
+
1132
+ .selected-count {
1133
+ font-size: 10px;
1134
+ color: #b0c4de;
1135
+ margin-left: 2px;
1136
+ }
1137
+ `]}_handleOptionClick(e){let t=this.selectedValues.includes(e.value);t?this.selectedValues=this.selectedValues.filter(t=>t!==e.value):this.selectedValues=[...this.selectedValues,e.value];let n=!t;this.onSelectionChange?.(e.value,n)}_getTriggerIcon(){return p}_isOptionSelected(e){return this.selectedValues.includes(e.value)}_getTriggerTitle(){let e=this.selectedValues.length;return e===0?`No items selected`:e===1?`1 item selected`:`${e} items selected`}_getTriggerLabel(){return`Filter options: ${this.selectedValues.length} selected`}render(){let e=`trigger-button ${this.isDropdownOpen?`active`:``}`,t=`dropdown-menu ${this.isDropdownOpen?`active`:``}`;return n`
1138
+ <div class="dropdown-container">
1139
+ <button
1140
+ class="${e}"
1141
+ title="${this._getTriggerTitle()}"
1142
+ @click="${this._toggleDropdown}"
1143
+ aria-haspopup="true"
1144
+ aria-expanded="${this.isDropdownOpen}"
1145
+ aria-controls="dropdown-menu"
1146
+ aria-label="${this._getTriggerLabel()}"
1147
+ >
1148
+ ${this._getTriggerIcon()}
1149
+ <span class="selected-count">${this.selectedValues.length}</span>
1150
+ <svg
1151
+ class="arrow-icon"
1152
+ xmlns="http://www.w3.org/2000/svg"
1153
+ viewBox="0 0 24 24"
1154
+ stroke="currentColor"
1155
+ stroke-width="2"
1156
+ stroke-linecap="round"
1157
+ stroke-linejoin="round"
1158
+ >
1159
+ <polyline points="6 9 12 15 18 9"></polyline>
1160
+ </svg>
1161
+ </button>
1162
+
1163
+ <div class="${t}" id="dropdown-menu" role="menu">
1164
+ ${this.dropdownOptions.map(e=>n`
1165
+ <button
1166
+ value="${e.value}"
1167
+ title="${e.title}"
1168
+ class="${this._isOptionSelected(e)?`active`:``}"
1169
+ @click="${()=>this._handleOptionClick(e)}"
1170
+ role="menuitem"
1171
+ >
1172
+ ${e.label}
1173
+ </button>
1174
+ `)}
1175
+ </div>
1176
+ </div>
1177
+ `}};_([i({type:Array}),g(`design:type`,Array)],j.prototype,`selectedValues`,void 0),_([i(),g(`design:type`,Function)],j.prototype,`onSelectionChange`,void 0),j=_([r(`multi-select-dropdown`)],j);const ue=(e,t)=>{let n={};e.eventListeners.forEach((e,t)=>{n[t]=e.length});let r=[];return e.registeredElements.forEach((e,t)=>{r.push({...e,elementInfo:`${t.id?`#${t.id}`:``}${t.className?`.${t.className.replace(/\s+/g,`.`)}`:``}`})}),{type:`managerDataPayload`,warning:`this is a lot easier to view in the console`,logId:t,globalCallbackHits:e.globalCallbackHits,localizedTimestamp:new Date().toLocaleTimeString(),eventListenerCount:n,managerSettings:e.globalSettings,registeredElements:r,loadedModules:e.loadedModules,summary:`${r.length} elements, ${Object.values(n).flat().length} listeners,
1178
+ ${e.globalCallbackHits.total} hits`}},M=(e,t)=>{try{switch(e.type){case`elementRegistered`:return{type:`elementRegistered`,name:e.state.name,id:e.element.id||``,state:e.state,hitslop:e.state.hitSlop,localizedTimestamp:new Date(e.timestamp).toLocaleTimeString(),meta:e.state.meta,logId:t,summary:e.state.registerCount>1?`${e.state.name} - ${fe(e.state.registerCount)} time`:e.state.name};case`elementUnregistered`:return{type:`elementUnregistered`,name:e.state.name,id:e.element.id||``,meta:e.state.meta,state:e.state,wasLastRegisteredElement:e.wasLastRegisteredElement,localizedTimestamp:new Date(e.timestamp).toLocaleTimeString(),logId:t,summary:`${e.state.name} - ${e.unregisterReason}`};case`callbackInvoked`:return{type:`callbackInvoked`,name:e.state.name,hitType:e.hitType,state:e.state,meta:e.state.meta,localizedTimestamp:new Date(e.timestamp).toLocaleTimeString(),logId:t,summary:`${e.state.name} - ${e.hitType.kind}`};case`callbackCompleted`:{let n=de(e.state.durationMs||0);return{type:`callbackCompleted`,name:e.state.name,hitType:e.hitType,state:e.state,meta:e.state.meta,wasLastActiveElement:e.wasLastActiveElement,elapsed:n,localizedTimestamp:new Date(e.timestamp).toLocaleTimeString(),logId:t,status:e.state.status,errorMessage:e.state.error,summary:`${e.state.name} - ${n}`}}case`mouseTrajectoryUpdate`:return{type:`mouseTrajectoryUpdate`,currentPoint:e.trajectoryPositions?.currentPoint,predictedPoint:e.trajectoryPositions?.predictedPoint,positionCount:e.trajectoryPositions?.positions?.length||0,mousePredictionEnabled:e.predictionEnabled,localizedTimestamp:new Date().toLocaleTimeString(),logId:t,summary:``};case`scrollTrajectoryUpdate`:return{type:`scrollTrajectoryUpdate`,currentPoint:e.currentPoint,predictedPoint:e.predictedPoint,scrollDirection:e.scrollDirection,localizedTimestamp:new Date().toLocaleTimeString(),logId:t,summary:e.scrollDirection};case`managerSettingsChanged`:return{type:`managerSettingsChanged`,globalSettings:e.managerData?.globalSettings||{},settingsChanged:e.updatedSettings,localizedTimestamp:new Date(e.timestamp).toLocaleTimeString(),logId:t,summary:e.updatedSettings.map(e=>e.setting).join(`, `)};case`deviceStrategyChanged`:return{type:`deviceStrategyChanged`,oldStrategy:e.oldStrategy,newStrategy:e.newStrategy,localizedTimestamp:new Date(e.timestamp).toLocaleTimeString(),logId:t,summary:`${e.oldStrategy} → ${e.newStrategy}`};default:return{type:`serializationError`,error:`Failed to serialize event data`,errorMessage:JSON.stringify(e),localizedTimestamp:new Date().toLocaleTimeString(),logId:t,summary:``}}}catch(e){return{type:`serializationError`,error:`Failed to serialize event data`,localizedTimestamp:new Date().toLocaleTimeString(),errorMessage:e instanceof Error?e.message:String(e),logId:t,summary:``}}},de=e=>`${(e/1e3).toFixed(4)} s`,fe=e=>{let t=e%100;if(t>=11&&t<=13)return`${e}th`;switch(e%10){case 1:return`${e}st`;case 2:return`${e}nd`;case 3:return`${e}rd`;default:return`${e}th`}},N={elementRegistered:`#2196f3`,callbackInvoked:`#00bcd4`,callbackCompleted:`#4caf50`,elementUnregistered:`#ff9800`,managerSettingsChanged:`#f44336`,mouseTrajectoryUpdate:`#78909c`,scrollTrajectoryUpdate:`#607d8b`,deviceStrategyChanged:`#9c27b0`};var pe=class{constructor(){this.logs=[],this.logIdCounter=0,this.changeListeners=new Set,this.managerListeners=new Map,this.isAttached=!1;let{logging:{logLocation:e,...t}}=$.instance.devtoolsSettings;this.logLocation=e,this.eventsEnabled=t}attach(){if(!this.isAttached){this.isAttached=!0;for(let[e,t]of Object.entries(this.eventsEnabled))t&&this.addManagerListener(e)}}detach(){this.managerListeners.forEach((e,t)=>{s.instance.removeEventListener(t,e)}),this.managerListeners.clear(),this.isAttached=!1}subscribe(e){return this.changeListeners.add(e),()=>this.changeListeners.delete(e)}setLogLocation(e){this.logLocation=e,this.notify()}setEventEnabled(e,t){this.eventsEnabled={...this.eventsEnabled,[e]:t},this.isAttached&&(t?this.addManagerListener(e):this.removeManagerListener(e)),this.notify()}clear(){this.logs=[],this.notify()}logManagerData(){this.logLocation!==`none`&&((this.logLocation===`console`||this.logLocation===`both`)&&console.log(s.instance.getManagerData),(this.logLocation===`controlPanel`||this.logLocation===`both`)&&this.addLog(ue(s.instance.getManagerData,(++this.logIdCounter).toString())))}addManagerListener(e){if(this.managerListeners.has(e))return;let t=t=>{this.handleEvent(e,t)};this.managerListeners.set(e,t),s.instance.addEventListener(e,t)}removeManagerListener(e){let t=this.managerListeners.get(e);t&&(s.instance.removeEventListener(e,t),this.managerListeners.delete(e))}handleEvent(e,t){if(this.logLocation!==`none`){if(this.logLocation===`console`||this.logLocation===`both`){let n=N[e]||`#ffffff`;console.log(`%c[ForesightJS] ${e}`,`color: ${n}; font-weight: bold;`,t)}if(this.logLocation===`controlPanel`||this.logLocation===`both`){let e=M(t,(++this.logIdCounter).toString());if(e.type===`serializationError`){console.error(e.error,e.errorMessage);return}this.addLog(e)}}}addLog(e){this.logs.unshift(e),this.logs.length>100&&this.logs.pop(),this.notify()}notify(){for(let e of this.changeListeners)e()}};let me=null;const P=()=>me??=new pe;let F=class extends e{static{this.styles=[t`
1179
+ :host {
1180
+ display: block;
1181
+ /*
1182
+ * The background color is now driven by a CSS variable.
1183
+ * This allows us to set it from TypeScript without touching the class.
1184
+ */
1185
+ background-color: var(--log-background-color, transparent);
1186
+ }
1187
+
1188
+ .log-time {
1189
+ color: #b8b8b8;
1190
+ font-weight: 500;
1191
+ font-size: 10px;
1192
+ font-family: "SF Mono", "Monaco", "Consolas", "Liberation Mono", "Courier New", monospace;
1193
+ min-width: 70px;
1194
+ max-width: 70px;
1195
+ text-align: left;
1196
+ letter-spacing: 0.02em;
1197
+ flex-shrink: 0;
1198
+ }
1199
+
1200
+ .log-type-badge {
1201
+ display: inline-flex;
1202
+ align-items: center;
1203
+ font-size: 10px;
1204
+ font-weight: 600;
1205
+ text-transform: uppercase;
1206
+ letter-spacing: 0.02em;
1207
+ /* The color is driven by a CSS variable set in updated() */
1208
+ color: var(--log-color, #b0c4de);
1209
+ min-width: 90px;
1210
+ max-width: 90px;
1211
+ white-space: nowrap;
1212
+ text-align: left;
1213
+ margin-left: 10px;
1214
+ flex-shrink: 0;
1215
+ }
1216
+
1217
+ .log-summary {
1218
+ flex: 1;
1219
+ color: #ccc;
1220
+ font-size: 11px;
1221
+ opacity: 0.9;
1222
+ white-space: nowrap;
1223
+ overflow: hidden;
1224
+ text-overflow: ellipsis;
1225
+ margin-left: 6px;
1226
+ font-weight: 400;
1227
+ min-width: 0;
1228
+ }
1229
+
1230
+ .log-content {
1231
+ display: flex;
1232
+ align-items: center;
1233
+ width: 100%;
1234
+ min-width: 0;
1235
+ }
1236
+
1237
+ /*
1238
+ * The :host(.error-status) selector is no longer needed,
1239
+ * as all styling is now handled by setting CSS variables below.
1240
+ * This makes the component's styling more self-contained.
1241
+ */
1242
+ `]}constructor(e){super(),this.isExpanded=!1,this.log=e}updated(e){if(e.has(`log`)&&this.log){let e=this.log,t=e.type===`callbackCompleted`&&`status`in e&&e.status===`error`,n=t?`#f44336`:this.getLogTypeColor(e.type),r=t?`rgba(244, 67, 54, 0.1)`:`transparent`;this.style.setProperty(`--log-color`,n),this.style.setProperty(`--log-background-color`,r)}}serializeLogDataWithoutSummary(e){let{summary:t,...n}=e;return JSON.stringify(n,null,2)}getLogTypeColor(e){return N[e]||`#555`}getEventDisplayName(e){return{elementRegistered:`Registered`,elementUnregistered:`Unregistered`,callbackInvoked:`Invoked`,callbackCompleted:`Completed`,mouseTrajectoryUpdate:`Mouse`,scrollTrajectoryUpdate:`Scroll`,managerSettingsChanged:`Settings`,managerDataPayload:`ManagerData`,deviceStrategyChanged:`Strategy`}[e]||e}truncateLogSummary(e,t=50){return e.length<=t?e:e.substring(0,t)+`...`}render(){let e=this.log;return n`
1243
+ <expandable-item
1244
+ .borderColor=${e.type===`callbackCompleted`&&`status`in e&&e.status===`error`?`#f44336`:this.getLogTypeColor(e.type)}
1245
+ .itemId=${e.logId}
1246
+ .isExpanded=${this.isExpanded}
1247
+ .onToggle=${this.onToggle}
1248
+ >
1249
+ <div slot="content">
1250
+ <div class="log-content">
1251
+ <span class="log-time">${e.localizedTimestamp}</span>
1252
+ <span class="log-type-badge">${this.getEventDisplayName(e.type)}</span>
1253
+ <span class="log-summary">${this.truncateLogSummary(e.summary)}</span>
1254
+ </div>
1255
+ </div>
1256
+ <div slot="details">${this.serializeLogDataWithoutSummary(e)}</div>
1257
+ </expandable-item>
1258
+ `}};_([i({attribute:!1}),g(`design:type`,Object)],F.prototype,`log`,void 0),_([i({type:Boolean}),g(`design:type`,Boolean)],F.prototype,`isExpanded`,void 0),_([i(),g(`design:type`,Object)],F.prototype,`onToggle`,void 0),F=_([r(`single-log`),g(`design:paramtypes`,[Object])],F);var I;let L=class extends e{static{this.styles=[t`
1259
+ :host {
1260
+ display: flex;
1261
+ flex-direction: column;
1262
+ height: 100%;
1263
+ }
1264
+
1265
+ .chips-container {
1266
+ display: flex;
1267
+ gap: 4px;
1268
+ }
1269
+
1270
+ .single-button {
1271
+ background: none;
1272
+ border: none;
1273
+ color: white;
1274
+ cursor: pointer;
1275
+ padding: 6px;
1276
+ display: inline-flex;
1277
+ align-items: center;
1278
+ justify-content: center;
1279
+ transition: all 0.2s ease;
1280
+ vertical-align: top;
1281
+ }
1282
+
1283
+ .single-button svg {
1284
+ width: 16px;
1285
+ height: 16px;
1286
+ stroke: white;
1287
+ transition: stroke 0.2s;
1288
+ }
1289
+
1290
+ .single-button:hover {
1291
+ background-color: rgba(176, 196, 222, 0.1);
1292
+ }
1293
+
1294
+ .single-button:hover svg {
1295
+ stroke: #b0c4de;
1296
+ }
1297
+
1298
+ .single-button:disabled {
1299
+ opacity: 0.4;
1300
+ cursor: not-allowed;
1301
+ }
1302
+
1303
+ .single-button:disabled:hover {
1304
+ background: none;
1305
+ }
1306
+
1307
+ .single-button:disabled svg {
1308
+ stroke: #666;
1309
+ }
1310
+
1311
+ .no-items {
1312
+ display: flex;
1313
+ align-items: center;
1314
+ justify-content: center;
1315
+ height: 200px;
1316
+ text-align: center;
1317
+ font-family: "Courier New", monospace;
1318
+ font-style: italic;
1319
+ padding: 20px;
1320
+ color: #999;
1321
+ }
1322
+
1323
+ .warning-container {
1324
+ background: none;
1325
+ border: none;
1326
+ color: #ffc107;
1327
+ cursor: help;
1328
+ padding: 6px;
1329
+ display: inline-flex;
1330
+ align-items: center;
1331
+ justify-content: center;
1332
+ transition: all 0.2s ease;
1333
+ vertical-align: top;
1334
+ }
1335
+
1336
+ .warning-container svg {
1337
+ width: 16px;
1338
+ height: 16px;
1339
+ stroke: #ffc107;
1340
+ fill: none;
1341
+ transition: stroke 0.2s;
1342
+ }
1343
+
1344
+ .warning-container:hover {
1345
+ background-color: rgba(255, 193, 7, 0.1);
1346
+ }
1347
+
1348
+ .warning-container:hover svg {
1349
+ stroke: #ffdc3e;
1350
+ }
1351
+ `]}constructor(){super(),this.store=P(),this.expandedLogIds=new Set,this.noContentMessage=`No logs available`,this._unsubscribeStore=null,this.handleLogLocationChange=e=>{this.store.setLogLocation(e)},this.handleFilterChange=(e,t)=>{this.store.setEventEnabled(e,t)},this.handleLogToggle=e=>{let t=new Set(this.expandedLogIds);t.has(e)?t.delete(e):t.add(e),this.expandedLogIds=t},this.logManagerData=()=>{this.store.logManagerData()},this.logDropdown=[{value:`controlPanel`,label:`Control Panel`,title:`Log only to the control panel`,icon:u},{value:`console`,label:`Console`,title:`Log only to the console`,icon:d},{value:`both`,label:`Both`,title:`Log to both the control panel and the console`,icon:te},{value:`none`,label:`None`,title:`Dont log anywhere`,icon:ee}],this.filterDropdown=[{value:`elementRegistered`,label:`Element Registered`,title:`Show element registration events`,icon:p},{value:`elementUnregistered`,label:`Element Unregistered`,title:`Show element unregistration events`,icon:p},{value:`callbackInvoked`,label:`Callback Invoked`,title:`Show callback invoked events`,icon:p},{value:`callbackCompleted`,label:`Callback Completed`,title:`Show callback completed events`,icon:p},{value:`mouseTrajectoryUpdate`,label:`Mouse Trajectory Update`,title:`Show mouse trajectory update events`,icon:p},{value:`scrollTrajectoryUpdate`,label:`Scroll Trajectory Update`,title:`Show scroll trajectory update events`,icon:p},{value:`managerSettingsChanged`,label:`Manager Settings Changed`,title:`Show manager settings change events`,icon:p},{value:`deviceStrategyChanged`,label:`Strategy Changed`,title:`Show strategy change events`,icon:p}]}getSelectedEventFilters(){return Object.entries(this.store.eventsEnabled).filter(([,e])=>e).map(([e])=>e)}shouldShowPerformanceWarning(){let{logLocation:e,eventsEnabled:t}=this.store,n=e===`console`||e===`both`,r=t.mouseTrajectoryUpdate||t.scrollTrajectoryUpdate;return n&&r}getNoLogsMessage(){return Object.values(this.store.eventsEnabled).filter(Boolean).length===0?`Logging for all events is turned off`:this.store.logLocation===`console`?`No logs to display. Logging location is set to console - check browser console for events.`:this.store.logLocation===`none`?`No logs to display. Logging location is set to none`:`Interact with Foresight to generate events.`}clearLogs(){this.store.clear(),this.expandedLogIds.clear(),this.noContentMessage=`Logs cleared`}connectedCallback(){super.connectedCallback(),this._unsubscribeStore=this.store.subscribe(()=>this.requestUpdate())}disconnectedCallback(){super.disconnectedCallback(),this._unsubscribeStore?.(),this._unsubscribeStore=null}render(){let e=this.store.logs;return n`
1352
+ <tab-header>
1353
+ <div slot="chips" class="chips-container">
1354
+ <chip-element title="Number of logged events (Max ${100})">
1355
+ ${e.length} events
1356
+ </chip-element>
1357
+ </div>
1358
+ <div slot="actions">
1359
+ ${this.shouldShowPerformanceWarning()?n`
1360
+ <div
1361
+ class="warning-container"
1362
+ title="Console logging can be slow with frequent trajectory events.
1363
+ Consider using 'Control Panel' only for better performance."
1364
+ >
1365
+ ${oe}
1366
+ </div>
1367
+ `:``}
1368
+ <single-select-dropdown
1369
+ .dropdownOptions="${this.logDropdown}"
1370
+ .selectedOptionValue="${this.store.logLocation}"
1371
+ .onSelectionChange="${this.handleLogLocationChange}"
1372
+ ></single-select-dropdown>
1373
+
1374
+ <multi-select-dropdown
1375
+ .dropdownOptions="${this.filterDropdown}"
1376
+ .selectedValues="${this.getSelectedEventFilters()}"
1377
+ .onSelectionChange="${this.handleFilterChange}"
1378
+ ></multi-select-dropdown>
1379
+ <button
1380
+ class="single-button"
1381
+ title="Log the state from the manager"
1382
+ @click="${this.logManagerData}"
1383
+ >
1384
+ ${se}
1385
+ </button>
1386
+ <button
1387
+ class="single-button"
1388
+ title="Clear all logs"
1389
+ ?disabled="${e.length===0}"
1390
+ @click="${this.clearLogs}"
1391
+ >
1392
+ ${ie}
1393
+ </button>
1394
+ </div>
1395
+ </tab-header>
1396
+ <tab-content .noContentMessage=${this.noContentMessage} .hasContent=${!!e.length}>
1397
+ ${e.length===0?n`<div class="no-items">${this.getNoLogsMessage()}</div>`:c(e,e=>e.logId,e=>n`
1398
+ <single-log
1399
+ .log=${e}
1400
+ .isExpanded=${this.expandedLogIds.has(e.logId)}
1401
+ .onToggle=${this.handleLogToggle}
1402
+ ></single-log>
1403
+ `)}
1404
+ </tab-content>
1405
+ `}};_([o(),g(`design:type`,Array)],L.prototype,`logDropdown`,void 0),_([o(),g(`design:type`,Array)],L.prototype,`filterDropdown`,void 0),_([o(),g(`design:type`,typeof(I=typeof Set<`u`&&Set)==`function`?I:Object)],L.prototype,`expandedLogIds`,void 0),_([i(),g(`design:type`,String)],L.prototype,`noContentMessage`,void 0),L=_([r(`log-tab`),g(`design:paramtypes`,[])],L);const R=`points`;let z=class extends e{constructor(...e){super(...e),this.header=``,this.description=``}static{this.styles=[t`
1406
+ .setting-item {
1407
+ display: flex;
1408
+ align-items: center;
1409
+ gap: 12px;
1410
+ padding: 10px 0;
1411
+ border-bottom: 1px solid rgba(80, 80, 80, 0.2);
1412
+ }
1413
+
1414
+ .setting-item:last-child {
1415
+ border-bottom: none;
1416
+ }
1417
+ .setting-controls {
1418
+ display: flex;
1419
+ align-items: center;
1420
+ gap: 8px;
1421
+ flex-shrink: 0;
1422
+ }
1423
+ .setting-description {
1424
+ font-size: 11px;
1425
+ color: #9e9e9e;
1426
+ line-height: 1.3;
1427
+ font-weight: normal;
1428
+ }
1429
+ .setting-item label {
1430
+ flex: 1;
1431
+ display: flex;
1432
+ flex-direction: column;
1433
+ gap: 4px;
1434
+ font-weight: 500;
1435
+ color: #fff;
1436
+ font-size: 13px;
1437
+ min-width: 180px;
1438
+ }
1439
+ .setting-header {
1440
+ font-weight: 500;
1441
+ color: #fff;
1442
+ font-size: 13px;
1443
+ }
1444
+ `]}render(){return n`<div class="setting-item">
1445
+ <label>
1446
+ <span class="setting-header">${this.header}</span>
1447
+ <span class="setting-description"> ${this.description} </span>
1448
+ </label>
1449
+ <div class="setting-controls">
1450
+ <slot name="controls"></slot>
1451
+ </div>
1452
+ </div>`}};_([i({type:String}),g(`design:type`,String)],z.prototype,`header`,void 0),_([i({type:String}),g(`design:type`,String)],z.prototype,`description`,void 0),z=_([r(`setting-item`)],z);let B=class extends e{constructor(...e){super(...e),this.isChecked=!1,this.header=``,this.description=``,this.setting=`enableMousePrediction`}static{this.styles=[t`
1453
+ input[type="checkbox"] {
1454
+ appearance: none;
1455
+ -webkit-appearance: none;
1456
+ -moz-appearance: none;
1457
+ position: relative;
1458
+ width: 44px;
1459
+ height: 22px;
1460
+ background-color: #444;
1461
+ cursor: pointer;
1462
+ outline: none;
1463
+ transition: all 0.3s ease;
1464
+ vertical-align: middle;
1465
+ flex-shrink: 0;
1466
+ margin: 0;
1467
+ border: 2px solid #555;
1468
+ }
1469
+
1470
+ input[type="checkbox"]::before {
1471
+ content: "";
1472
+ position: absolute;
1473
+ width: 16px;
1474
+ height: 16px;
1475
+ background-color: white;
1476
+ top: 1px;
1477
+ left: 1px;
1478
+ transition: all 0.3s ease;
1479
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
1480
+ }
1481
+
1482
+ input[type="checkbox"]:checked {
1483
+ background-color: #b0c4de;
1484
+ border-color: #b0c4de;
1485
+ }
1486
+
1487
+ input[type="checkbox"]:checked::before {
1488
+ transform: translateX(22px);
1489
+ background-color: white;
1490
+ }
1491
+
1492
+ input[type="checkbox"]:hover {
1493
+ box-shadow: 0 0 0 3px rgba(176, 196, 222, 0.1);
1494
+ }
1495
+ `]}handleCheckboxChange(e){let t=e.target;if(t instanceof HTMLInputElement){let e=t.checked;String(this.setting).startsWith(`show.`)?this.dispatchEvent(new CustomEvent(`setting-changed`,{detail:{setting:this.setting,value:e},bubbles:!0})):s.instance.alterGlobalSettings({[this.setting]:e})}}render(){return n`<setting-item header=${this.header} description=${this.description}>
1496
+ <input
1497
+ slot="controls"
1498
+ type="checkbox"
1499
+ .checked=${this.isChecked}
1500
+ @change=${this.handleCheckboxChange}
1501
+ />
1502
+ </setting-item>`}};_([i({type:Boolean}),g(`design:type`,Boolean)],B.prototype,`isChecked`,void 0),_([i({type:String}),g(`design:type`,String)],B.prototype,`header`,void 0),_([i({type:String}),g(`design:type`,String)],B.prototype,`description`,void 0),_([i({type:String}),g(`design:type`,Object)],B.prototype,`setting`,void 0),B=_([r(`setting-item-checkbox`)],B);let V=class extends e{constructor(...e){super(...e),this.minValue=0,this.maxValue=100,this.currentValue=50,this.unit=`px`,this.header=``,this.description=``,this.setting=`tabOffset`,this.displayValue=50}static{this.styles=[t`
1503
+ .setting-range-value {
1504
+ font-size: 12px;
1505
+ color: #b0c4de;
1506
+ font-weight: 500;
1507
+ min-width: 45px;
1508
+ text-align: right;
1509
+ }
1510
+
1511
+ .range-wrapper {
1512
+ display: flex;
1513
+ align-items: center;
1514
+ gap: 8px;
1515
+ width: 100%;
1516
+ }
1517
+
1518
+ input[type="range"] {
1519
+ margin: 0;
1520
+ cursor: pointer;
1521
+ -webkit-appearance: none;
1522
+ appearance: none;
1523
+ background: transparent;
1524
+ height: 22px;
1525
+ vertical-align: middle;
1526
+ width: 100px;
1527
+ }
1528
+
1529
+ input[type="range"]::-webkit-slider-runnable-track {
1530
+ height: 6px;
1531
+ background: #444;
1532
+ border: 1px solid #555;
1533
+ }
1534
+
1535
+ input[type="range"]::-moz-range-track {
1536
+ height: 6px;
1537
+ background: #444;
1538
+ border: 1px solid #555;
1539
+ }
1540
+
1541
+ input[type="range"]::-webkit-slider-thumb {
1542
+ -webkit-appearance: none;
1543
+ appearance: none;
1544
+ margin-top: -7px;
1545
+ background: #b0c4de;
1546
+ height: 20px;
1547
+ width: 20px;
1548
+ border: 2px solid #333;
1549
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
1550
+ transition: all 0.2s ease;
1551
+ }
1552
+
1553
+ input[type="range"]::-moz-range-thumb {
1554
+ background: #b0c4de;
1555
+ height: 20px;
1556
+ width: 20px;
1557
+ border: 2px solid #333;
1558
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
1559
+ transition: all 0.2s ease;
1560
+ }
1561
+
1562
+ input[type="range"]:hover::-webkit-slider-thumb {
1563
+ transform: scale(1.1);
1564
+ box-shadow: 0 0 0 4px rgba(176, 196, 222, 0.2);
1565
+ }
1566
+
1567
+ input[type="range"]:hover::-moz-range-thumb {
1568
+ transform: scale(1.1);
1569
+ box-shadow: 0 0 0 4px rgba(176, 196, 222, 0.2);
1570
+ }
1571
+ `]}handleRangeInput(e){let t=e.target;t instanceof HTMLInputElement&&(this.displayValue=parseInt(t.value,10))}handleRangeChange(e){let t=e.target;if(t instanceof HTMLInputElement){let e=parseInt(t.value,10);this.displayValue=e,s.instance.alterGlobalSettings({[this.setting]:e})}}willUpdate(e){super.willUpdate(e),e.has(`currentValue`)&&(this.displayValue=this.currentValue)}render(){return n`<setting-item header=${this.header} description=${this.description}>
1572
+ <div slot="controls" class="range-wrapper">
1573
+ <input
1574
+ slot="controls"
1575
+ type="range"
1576
+ min="${this.minValue}"
1577
+ max="${this.maxValue}"
1578
+ step="1"
1579
+ .value=${this.displayValue}
1580
+ @input=${this.handleRangeInput}
1581
+ @change=${this.handleRangeChange}
1582
+ />
1583
+ <span class="setting-range-value">${this.displayValue} ${this.unit}</span>
1584
+ </div>
1585
+ </setting-item>`}};_([i({type:Number}),g(`design:type`,Number)],V.prototype,`minValue`,void 0),_([i({type:Number}),g(`design:type`,Number)],V.prototype,`maxValue`,void 0),_([i({type:Number}),g(`design:type`,Number)],V.prototype,`currentValue`,void 0),_([i({type:String}),g(`design:type`,String)],V.prototype,`unit`,void 0),_([i({type:String}),g(`design:type`,String)],V.prototype,`header`,void 0),_([i({type:String}),g(`design:type`,String)],V.prototype,`description`,void 0),_([i({type:String}),g(`design:type`,Object)],V.prototype,`setting`,void 0),_([o(),g(`design:type`,Number)],V.prototype,`displayValue`,void 0),V=_([r(`setting-item-range`)],V);var H;let U=class extends e{static{this.styles=t`
1586
+ :host {
1587
+ display: flex;
1588
+ flex-direction: column;
1589
+ height: 100%;
1590
+ }
1591
+
1592
+ .settings-content {
1593
+ display: block;
1594
+ }
1595
+
1596
+ .settings-section {
1597
+ display: flex;
1598
+ flex-direction: column;
1599
+ gap: 16px;
1600
+ }
1601
+
1602
+ .settings-group {
1603
+ background: rgba(30, 30, 30, 0.6);
1604
+ padding: 16px;
1605
+ border: 1px solid rgba(176, 196, 222, 0.1);
1606
+ }
1607
+
1608
+ .settings-group h4 {
1609
+ margin: 0 0 12px 0;
1610
+ font-size: 14px;
1611
+ font-weight: 600;
1612
+ color: #b0c4de;
1613
+ border-bottom: 1px solid rgba(176, 196, 222, 0.2);
1614
+ padding-bottom: 8px;
1615
+ }
1616
+ `}constructor(){super(),this.changedSettings=[],this.currentCorner=`bottom-right`,this.touchDeviceStrategyOptions=[{value:`onTouchStart`,label:`On Touch Start`,title:`Execute callbacks when user touches registered elements`,icon:n`<span>Touch</span>`},{value:`viewport`,label:`Viewport Entry`,title:`Execute callbacks when registered elements enter the viewport`,icon:n`<span>Viewport</span>`},{value:`none`,label:`None`,title:`Disable touch device prediction`,icon:n`<span>None</span>`}],this.minimumConnectionTypeOptions=[{value:`slow-2g`,label:`Slow 2G`,title:`Slow 2G`,icon:n`<span>Slow 2G</span>`},{value:`2g`,label:`2G`,title:`2G`,icon:n`<span>2G</span>`},{value:`3g`,label:`3G`,title:`3G`,icon:n`<span>3G</span>`},{value:`4g`,label:`4G`,title:`4G`,icon:n`<span>4G</span>`}],this.cornerOptions=[{value:`top-left`,label:`Top Left`,title:`Position control panel in top-left corner`,icon:n`<span>↖</span>`},{value:`top-right`,label:`Top Right`,title:`Position control panel in top-right corner`,icon:n`<span>↗</span>`},{value:`bottom-left`,label:`Bottom Left`,title:`Position control panel in bottom-left corner`,icon:n`<span>↙</span>`},{value:`bottom-right`,label:`Bottom Right`,title:`Position control panel in bottom-right corner`,icon:n`<span>↘</span>`}],this._abortController=null,this._handleTouchDeviceStrategyChange=e=>{s.instance.alterGlobalSettings({touchDeviceStrategy:e})},this._handleMinimumConnectionTypeChange=e=>{s.instance.alterGlobalSettings({minimumConnectionType:e})},this._handleCornerChange=e=>{this.currentCorner=e,this.dispatchEvent(new CustomEvent(`corner-change`,{detail:{corner:e},bubbles:!0,composed:!0}))};let e=$.instance.devtoolsSettings,t=s.instance.getManagerData.globalSettings;this.devtoolsSettings={...e,show:{...e.show}},this.managerSettings=Object.assign({},t),this.currentCorner=this.getCurrentCorner(),this.initialSettings={devtools:{...e,show:{...e.show}},manager:Object.assign({},t)}}connectedCallback(){super.connectedCallback(),this._abortController=new AbortController;let{signal:e}=this._abortController;s.instance.addEventListener(`managerSettingsChanged`,e=>{this.managerSettings=e.managerData.globalSettings,this._updateChangedSettings()},{signal:e}),this._updateChangedSettings()}disconnectedCallback(){super.disconnectedCallback(),this._abortController?.abort(),this._abortController=null}_updateChangedSettings(){let e=[];this._checkManagerSettingsChanges(e),this._checkDevtoolsSettingsChanges(e),this.changedSettings=e}_checkManagerSettingsChanges(e){for(let t of[`enableMousePrediction`,`enableTabPrediction`,`enableScrollPrediction`,`trajectoryPredictionTime`,`positionHistorySize`,`tabOffset`,`scrollMargin`,`touchDeviceStrategy`,`minimumConnectionType`]){let n=this.initialSettings.manager[t],r=this.managerSettings[t];n!==r&&e.push({setting:t,oldValue:n,newValue:r})}}_checkDevtoolsSettingsChanges(e){for(let t of l){let n=this.initialSettings.devtools.show[t],r=this.devtoolsSettings.show[t];n!==r&&e.push({setting:`show.${t}`,oldValue:n,newValue:r})}}_handleDevtoolsSettingChange(e){let{setting:t,value:n}=e.detail;if(!t.startsWith(`show.`))return;let r=t.slice(5);l.includes(r)&&(this.devtoolsSettings={...this.devtoolsSettings,show:{...this.devtoolsSettings.show,[r]:n}},$.instance.alterDevtoolsSettings({show:{[r]:n}}),this._updateChangedSettings())}getCurrentCorner(){try{let e=localStorage.getItem(`foresight-devtools-control-panel-corner`);if(e&&[`top-left`,`top-right`,`bottom-left`,`bottom-right`].includes(e))return e}catch(e){console.warn(`ForesightDevtools: Failed to load corner from localStorage:`,e)}return`bottom-right`}async handleCopySettings(){if(this.managerSettings)try{let e=this.generateSettingsCode(this.managerSettings);navigator.clipboard&&navigator.clipboard.writeText&&await navigator.clipboard.writeText(e)}catch(e){console.error(`Failed to copy settings code:`,e)}}generateSettingsCode(e){let t={enableMousePrediction:e.enableMousePrediction,enableTabPrediction:e.enableTabPrediction,enableScrollPrediction:e.enableScrollPrediction,positionHistorySize:e.positionHistorySize,trajectoryPredictionTime:e.trajectoryPredictionTime,tabOffset:e.tabOffset,scrollMargin:e.scrollMargin,touchDeviceStrategy:e.touchDeviceStrategy,minimumConnectionType:e.minimumConnectionType};return`ForesightManager.initialize(${JSON.stringify(t,null,2)})`}render(){if(!this.managerSettings||!this.devtoolsSettings)return n`<tab-content
1617
+ .noContentMessage=${`Loading settings...`}
1618
+ .hasContent=${!1}
1619
+ ></tab-content>`;let e=this.managerSettings;return n`
1620
+ <tab-header>
1621
+ <div slot="chips" class="chips-container">
1622
+ <chip-element .title=${this.changedSettings.length>0?`Settings that have been changed this session compared to your initialized settings.
1623
+ Click on the copy icon to easely copy the new setting into your project
1624
+
1625
+ `+this.changedSettings.map(e=>`${e.setting}: ${JSON.stringify(e.oldValue)} -> ${JSON.stringify(e.newValue)}`).join(`
1626
+ `):`No settings changed from initial values`}> ${this.changedSettings.length} changed </chip-element>
1627
+ </div>
1628
+ <div slot="actions">
1629
+ <copy-icon
1630
+ title="Copy current settings as code"
1631
+ .onCopy=${()=>this.handleCopySettings()}
1632
+ ></copy-icon>
1633
+ </div>
1634
+ </tab-header>
1635
+
1636
+ <tab-content .hasContent=${!0}>
1637
+ <div class="settings-content">
1638
+ <div class="settings-section">
1639
+ <div class="settings-group">
1640
+ <h4>Mouse Prediction</h4>
1641
+ <setting-item-checkbox
1642
+ .isChecked=${e.enableMousePrediction}
1643
+ header="Enable Mouse Prediction"
1644
+ description="Execute callbacks when mouse is ${e.trajectoryPredictionTime}ms away from registered elements in mouse direction"
1645
+ setting="enableMousePrediction"
1646
+ ></setting-item-checkbox>
1647
+ <setting-item-range
1648
+ .currentValue=${e.trajectoryPredictionTime}
1649
+ .maxValue=${200}
1650
+ .minValue=${10}
1651
+ .unit=${`ms`}
1652
+ header="Prediction Time"
1653
+ description="How far into the future to calculate mouse trajectory path"
1654
+ setting="trajectoryPredictionTime"
1655
+ ></setting-item-range>
1656
+ <setting-item-range
1657
+ .currentValue=${e.positionHistorySize}
1658
+ .maxValue=${30}
1659
+ .minValue=${2}
1660
+ .unit=${R}
1661
+ header="Position History Size"
1662
+ description="How far into the future, in ${R}, to calculate mouse trajectory path"
1663
+ setting="positionHistorySize"
1664
+ >
1665
+ </setting-item-range>
1666
+ </div>
1667
+ <div class="settings-group">
1668
+ <h4>Keyboard Navigation</h4>
1669
+ <setting-item-checkbox
1670
+ .isChecked=${e.enableTabPrediction}
1671
+ header="Enable Tab Prediction"
1672
+ description="Execute callbacks when user ${e.tabOffset} tabbable elements away from registered elements in tab direction"
1673
+ setting="enableTabPrediction"
1674
+ >
1675
+ </setting-item-checkbox>
1676
+ <setting-item-range
1677
+ .currentValue=${e.tabOffset}
1678
+ .maxValue=${20}
1679
+ .minValue=${0}
1680
+ .unit=${`tabs`}
1681
+ header="Tab Offset"
1682
+ description="Number of tabbable elements to look ahead when predicting navigation"
1683
+ setting="tabOffset"
1684
+ >
1685
+ </setting-item-range>
1686
+ </div>
1687
+
1688
+ <div class="settings-group">
1689
+ <h4>Scroll Prediction</h4>
1690
+ <setting-item-checkbox
1691
+ .isChecked=${e.enableScrollPrediction}
1692
+ header="Enable Scroll Prediction"
1693
+ description="Execute callbacks when user is ${e.scrollMargin}px away from registered elements in scroll direction"
1694
+ setting="enableScrollPrediction"
1695
+ ></setting-item-checkbox>
1696
+ <setting-item-range
1697
+ .currentValue=${e.scrollMargin}
1698
+ .maxValue=${300}
1699
+ .minValue=${30}
1700
+ .unit=${`px`}
1701
+ header="Scroll Margin"
1702
+ description="Pixel distance to check from mouse position in scroll direction"
1703
+ setting="scrollMargin"
1704
+ ></setting-item-range>
1705
+ </div>
1706
+
1707
+ <div class="settings-group">
1708
+ <h4>Touch Device</h4>
1709
+ <setting-item
1710
+ header="Touch Device Strategy"
1711
+ description="How to handle prediction on touch devices"
1712
+ >
1713
+ <single-select-dropdown
1714
+ slot="controls"
1715
+ .dropdownOptions=${this.touchDeviceStrategyOptions}
1716
+ .selectedOptionValue=${e.touchDeviceStrategy}
1717
+ .onSelectionChange=${this._handleTouchDeviceStrategyChange}
1718
+ ></single-select-dropdown>
1719
+ </setting-item>
1720
+ </div>
1721
+
1722
+ <div class="settings-group">
1723
+ <h4>Minimum Connection</h4>
1724
+ <setting-item
1725
+ header="Minimum Connection Type"
1726
+ description="Minimum connection speed required to register elements"
1727
+ >
1728
+ <single-select-dropdown
1729
+ slot="controls"
1730
+ .dropdownOptions=${this.minimumConnectionTypeOptions}
1731
+ .selectedOptionValue=${e.minimumConnectionType}
1732
+ .onSelectionChange=${this._handleMinimumConnectionTypeChange}
1733
+ ></single-select-dropdown>
1734
+ </setting-item>
1735
+ </div>
1736
+
1737
+ <!-- Developer Tools Group -->
1738
+ <div class="settings-group">
1739
+ <h4>Developer Tools</h4>
1740
+ <setting-item-checkbox
1741
+ .isChecked=${this.devtoolsSettings.show.nameTags}
1742
+ header="Show Name Tags"
1743
+ description="Display name tags over each registered element in the debugger"
1744
+ setting="show.nameTags"
1745
+ @setting-changed=${this._handleDevtoolsSettingChange}
1746
+ ></setting-item-checkbox>
1747
+ <setting-item-checkbox
1748
+ .isChecked=${this.devtoolsSettings.show.elementOverlays}
1749
+ header="Show Element Overlays"
1750
+ description="Render hit-slop boundary overlays around registered elements. Note: turning this off also hides name tags."
1751
+ setting="show.elementOverlays"
1752
+ @setting-changed=${this._handleDevtoolsSettingChange}
1753
+ ></setting-item-checkbox>
1754
+ <setting-item-checkbox
1755
+ .isChecked=${this.devtoolsSettings.show.mouseTrajectory}
1756
+ header="Show Mouse Trajectory"
1757
+ description="Render the predicted mouse trajectory line"
1758
+ setting="show.mouseTrajectory"
1759
+ @setting-changed=${this._handleDevtoolsSettingChange}
1760
+ ></setting-item-checkbox>
1761
+ <setting-item-checkbox
1762
+ .isChecked=${this.devtoolsSettings.show.scrollTrajectory}
1763
+ header="Show Scroll Trajectory"
1764
+ description="Render the predicted scroll trajectory line"
1765
+ setting="show.scrollTrajectory"
1766
+ @setting-changed=${this._handleDevtoolsSettingChange}
1767
+ ></setting-item-checkbox>
1768
+ <setting-item
1769
+ header="Panel Position"
1770
+ description="Choose which corner to position the control panel"
1771
+ >
1772
+ <single-select-dropdown
1773
+ slot="controls"
1774
+ .dropdownOptions=${this.cornerOptions}
1775
+ .selectedOptionValue=${this.currentCorner}
1776
+ .onSelectionChange=${this._handleCornerChange}
1777
+ ></single-select-dropdown>
1778
+ </setting-item>
1779
+ </div>
1780
+ </div>
1781
+ </div>
1782
+ </tab-content>
1783
+ `}};_([o(),g(`design:type`,Object)],U.prototype,`managerSettings`,void 0),_([o(),g(`design:type`,typeof(H=typeof Readonly<`u`&&Readonly)==`function`?H:Object)],U.prototype,`initialSettings`,void 0),_([o(),g(`design:type`,Object)],U.prototype,`devtoolsSettings`,void 0),_([o(),g(`design:type`,Array)],U.prototype,`changedSettings`,void 0),_([o(),g(`design:type`,Object)],U.prototype,`currentCorner`,void 0),_([o(),g(`design:type`,Array)],U.prototype,`touchDeviceStrategyOptions`,void 0),_([o(),g(`design:type`,Array)],U.prototype,`minimumConnectionTypeOptions`,void 0),_([o(),g(`design:type`,Array)],U.prototype,`cornerOptions`,void 0),U=_([r(`settings-tab`),g(`design:paramtypes`,[])],U);let W=class extends e{static{this.styles=t`
1784
+ .control-wrapper {
1785
+ --panel-offset: 10px;
1786
+ padding: 12px;
1787
+ position: fixed;
1788
+ background-color: rgba(0, 0, 0, 0.9);
1789
+ color: white;
1790
+ font-family: Arial, sans-serif;
1791
+ font-size: 13px;
1792
+ z-index: 10001;
1793
+ pointer-events: auto;
1794
+ display: flex;
1795
+ flex-direction: column;
1796
+ width: 450px;
1797
+ height: 450px;
1798
+ transition:
1799
+ width 0.3s ease,
1800
+ height 0.3s ease;
1801
+ box-sizing: border-box;
1802
+ border-radius: 8px;
1803
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
1804
+ }
1805
+
1806
+ .control-wrapper.top-left {
1807
+ top: var(--panel-offset);
1808
+ left: var(--panel-offset);
1809
+ }
1810
+ .control-wrapper.top-right {
1811
+ top: var(--panel-offset);
1812
+ right: var(--panel-offset);
1813
+ }
1814
+ .control-wrapper.bottom-left {
1815
+ bottom: var(--panel-offset);
1816
+ left: var(--panel-offset);
1817
+ }
1818
+ .control-wrapper.bottom-right {
1819
+ bottom: var(--panel-offset);
1820
+ right: var(--panel-offset);
1821
+ }
1822
+
1823
+ .control-wrapper.minimized {
1824
+ width: 230px;
1825
+ height: 45px;
1826
+ }
1827
+
1828
+ .title-wrapper {
1829
+ display: flex;
1830
+ justify-content: space-between;
1831
+ align-items: center;
1832
+ padding: 0;
1833
+ flex-shrink: 0;
1834
+ }
1835
+
1836
+ .title-wrapper h1 {
1837
+ margin: 0;
1838
+ font-size: 15px;
1839
+ }
1840
+
1841
+ .minimize-button {
1842
+ background: none;
1843
+ border: none;
1844
+ color: white;
1845
+ font-size: 22px;
1846
+ cursor: pointer;
1847
+ line-height: 1;
1848
+ padding: 0;
1849
+ }
1850
+
1851
+ .tab-container {
1852
+ display: flex;
1853
+ flex-direction: column;
1854
+ flex: 1;
1855
+ overflow: hidden;
1856
+ }
1857
+
1858
+ .tab-content {
1859
+ flex: 1;
1860
+ position: relative;
1861
+ }
1862
+
1863
+ .tab-content > * {
1864
+ display: flex;
1865
+ position: absolute;
1866
+ top: 0;
1867
+ left: 0;
1868
+ width: 100%;
1869
+ height: 100%;
1870
+ }
1871
+
1872
+ .touch-device-warning {
1873
+ background-color: rgba(255, 193, 7, 0.9);
1874
+ color: #000;
1875
+ padding: 8px 12px;
1876
+ margin: 8px 0;
1877
+ border-radius: 4px;
1878
+ font-size: 12px;
1879
+ font-weight: 500;
1880
+ display: flex;
1881
+ align-items: center;
1882
+ justify-content: space-between;
1883
+ gap: 8px;
1884
+ }
1885
+
1886
+ .touch-device-warning.hidden {
1887
+ display: none;
1888
+ }
1889
+
1890
+ .warning-content {
1891
+ display: flex;
1892
+ align-items: center;
1893
+ gap: 8px;
1894
+ }
1895
+
1896
+ .warning-icon {
1897
+ font-weight: bold;
1898
+ font-size: 14px;
1899
+ }
1900
+
1901
+ .dismiss-button {
1902
+ background: none;
1903
+ border: none;
1904
+ color: #000;
1905
+ font-size: 16px;
1906
+ cursor: pointer;
1907
+ padding: 0;
1908
+ line-height: 1;
1909
+ font-weight: bold;
1910
+ }
1911
+
1912
+ .dismiss-button:hover {
1913
+ opacity: 0.7;
1914
+ }
1915
+ `}constructor(){super(),this.isMinimized=$.instance.devtoolsSettings.isControlPanelDefaultMinimized,this.isTouchDevice=!1,this.isWarningDismissed=!1,this.corner=`bottom-right`,this.localStorageSelectedTabKey=`foresight-devtools-control-panel-tab`,this.localStorageCornerKey=`foresight-devtools-control-panel-corner`,this._abortController=null,this.activeTab=this.getStoredTab(),this.corner=this.getStoredCorner(),this.isTouchDevice=s.instance.getManagerData.currentDeviceStrategy===`touch`}connectedCallback(){super.connectedCallback(),this._abortController=new AbortController;let{signal:e}=this._abortController;P().attach(),s.instance.addEventListener(`deviceStrategyChanged`,e=>{this.isTouchDevice=e.newStrategy===`touch`,e.newStrategy===`touch`&&(this.isWarningDismissed=!1)},{signal:e}),this.addEventListener(`corner-change`,(e=>{this.setCorner(e.detail.corner)}),{signal:e})}disconnectedCallback(){super.disconnectedCallback(),this._abortController?.abort(),this._abortController=null,P().detach()}getStoredTab(){try{return localStorage.getItem(this.localStorageSelectedTabKey)||`logs`}catch(e){return console.error(e),`logs`}}getStoredCorner(){try{let e=localStorage.getItem(this.localStorageCornerKey);if(e)return e}catch(e){console.error(`ForesightDevtools: Failed to load corner from localStorage:`,e)}return`bottom-right`}_handleTabChange(e){this.activeTab=e.detail.tab,this.setStoredTab(this.activeTab)}setStoredTab(e){try{localStorage.setItem(this.localStorageSelectedTabKey,e)}catch(e){console.warn(`ForesightDevtools: Failed to save tab preference to localStorage:`,e)}}setStoredCorner(e){try{localStorage.setItem(this.localStorageCornerKey,e)}catch(e){console.warn(`ForesightDevtools: Failed to save corner to localStorage:`,e)}}dismissWarning(){this.isWarningDismissed=!0}setCorner(e){this.corner=e,this.setStoredCorner(this.corner),this.requestUpdate()}handleMinimizeClick(e){e.stopPropagation(),this.isMinimized=!this.isMinimized}getMinimizeSymbol(){return this.isMinimized?`+`:`−`}renderActiveTab(){switch(this.activeTab){case`elements`:return n`<element-tab></element-tab>`;case`settings`:return n`<settings-tab></settings-tab>`;default:return n`<log-tab></log-tab>`}}render(){return n`
1916
+ <div class="control-wrapper ${this.corner} ${this.isMinimized?`minimized`:``}">
1917
+ <div class="title-wrapper">
1918
+ <button @click="${this.handleMinimizeClick}" class="minimize-button">
1919
+ ${this.getMinimizeSymbol()}
1920
+ </button>
1921
+ <h1>Foresight DevTools</h1>
1922
+ <div></div>
1923
+ </div>
1924
+
1925
+ <div
1926
+ class="touch-device-warning ${this.isMinimized||!this.isTouchDevice||this.isWarningDismissed?`hidden`:``}"
1927
+ >
1928
+ <div class="warning-content">
1929
+ <span class="warning-icon">⚠️</span>
1930
+ <span>Touch device mode: Overlays and visibility sorting not available</span>
1931
+ </div>
1932
+ <button @click="${this.dismissWarning}" class="dismiss-button" title="Dismiss warning">
1933
+ ×
1934
+ </button>
1935
+ </div>
1936
+
1937
+ ${this.isMinimized?``:n`
1938
+ <div class="tab-container">
1939
+ <tab-selector
1940
+ .activeTab="${this.activeTab}"
1941
+ @tab-change="${this._handleTabChange}"
1942
+ ></tab-selector>
1943
+
1944
+ <div class="tab-content">${this.renderActiveTab()}</div>
1945
+ </div>
1946
+ `}
1947
+ </div>
1948
+ `}};_([o(),g(`design:type`,Object)],W.prototype,`activeTab`,void 0),_([o(),g(`design:type`,Boolean)],W.prototype,`isMinimized`,void 0),_([o(),g(`design:type`,Boolean)],W.prototype,`isTouchDevice`,void 0),_([o(),g(`design:type`,Boolean)],W.prototype,`isWarningDismissed`,void 0),_([o(),g(`design:type`,String)],W.prototype,`corner`,void 0),W=_([r(`control-panel`),g(`design:paramtypes`,[])],W);var G,K,q;let J=class extends e{constructor(...e){super(...e),this.overlayMap=new Map,this.callbackAnimations=new Map,this._elementSubscriptions=new Map,this.showNameTags=!0,this._abortController=null}static{this.styles=[t`
1949
+ /* Anchored to the document origin (initial containing block), not the
1950
+ viewport: overlays are placed in document coordinates so the compositor
1951
+ moves them together with the page content during scroll, instead of
1952
+ JS chasing the scroll position a frame behind. */
1953
+ :host {
1954
+ position: absolute;
1955
+ top: 0;
1956
+ left: 0;
1957
+ width: 0;
1958
+ height: 0;
1959
+ pointer-events: none;
1960
+ z-index: 9999;
1961
+ }
1962
+
1963
+ :host([hidden]) {
1964
+ display: none;
1965
+ }
1966
+
1967
+ .slop-area {
1968
+ position: absolute;
1969
+ top: 0;
1970
+ left: 0;
1971
+ box-sizing: border-box;
1972
+ will-change: transform;
1973
+ border: 1px dashed rgba(100, 116, 139, 0.4);
1974
+ background-color: rgba(100, 116, 139, 0.05);
1975
+ transition:
1976
+ border-color 0.2s ease,
1977
+ background-color 0.2s ease,
1978
+ box-shadow 0.2s ease;
1979
+ pointer-events: none;
1980
+ }
1981
+
1982
+ .slop-area[data-hit="mouse"] {
1983
+ border-color: #3b82f6;
1984
+ background-color: rgba(59, 130, 246, 0.1);
1985
+ animation: glow-mouse 2s ease-in-out infinite;
1986
+ }
1987
+
1988
+ .slop-area[data-hit="scroll"] {
1989
+ border-color: #eab308;
1990
+ background-color: rgba(234, 179, 8, 0.1);
1991
+ animation: glow-scroll 2s ease-in-out infinite;
1992
+ }
1993
+
1994
+ .slop-area[data-hit="tab"] {
1995
+ border-color: #f97316;
1996
+ background-color: rgba(249, 115, 22, 0.1);
1997
+ animation: glow-tab 2s ease-in-out infinite;
1998
+ }
1999
+
2000
+ @keyframes glow-mouse {
2001
+ 0% {
2002
+ box-shadow: 0 0 5px 2px rgba(59, 130, 246, 0.3);
2003
+ }
2004
+ 50% {
2005
+ box-shadow: 0 0 15px 4px rgba(59, 130, 246, 0.6);
2006
+ }
2007
+ 100% {
2008
+ box-shadow: 0 0 5px 2px rgba(59, 130, 246, 0.3);
2009
+ }
2010
+ }
2011
+
2012
+ @keyframes glow-scroll {
2013
+ 0% {
2014
+ box-shadow: 0 0 5px 2px rgba(234, 179, 8, 0.3);
2015
+ }
2016
+ 50% {
2017
+ box-shadow: 0 0 15px 4px rgba(234, 179, 8, 0.6);
2018
+ }
2019
+ 100% {
2020
+ box-shadow: 0 0 5px 2px rgba(234, 179, 8, 0.3);
2021
+ }
2022
+ }
2023
+
2024
+ @keyframes glow-tab {
2025
+ 0% {
2026
+ box-shadow: 0 0 5px 2px rgba(249, 115, 22, 0.3);
2027
+ }
2028
+ 50% {
2029
+ box-shadow: 0 0 15px 4px rgba(249, 115, 22, 0.6);
2030
+ }
2031
+ 100% {
2032
+ box-shadow: 0 0 5px 2px rgba(249, 115, 22, 0.3);
2033
+ }
2034
+ }
2035
+
2036
+ .name-label {
2037
+ position: absolute;
2038
+ top: 0;
2039
+ left: 0;
2040
+ will-change: transform;
2041
+ background-color: rgba(27, 31, 35, 0.85);
2042
+ backdrop-filter: blur(4px);
2043
+ color: white;
2044
+ padding: 4px 8px;
2045
+ font-size: 11px;
2046
+ font-family:
2047
+ -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif,
2048
+ "Apple Color Emoji", "Segoe UI Emoji";
2049
+ z-index: 10001;
2050
+ white-space: nowrap;
2051
+ pointer-events: none;
2052
+ }
2053
+ `]}connectedCallback(){super.connectedCallback(),this._abortController=new AbortController;let{signal:e}=this._abortController;s.instance.addEventListener(`elementRegistered`,e=>{this._subscribeToElement(e.element),e.state.isIntersectingWithViewport&&this.createOrUpdateElementOverlay(e.element,e.state)},{signal:e}),s.instance.addEventListener(`elementUnregistered`,e=>{this._unsubscribeFromElement(e.element),this.removeElementOverlay(e.element)},{signal:e});for(let[e,t]of s.instance.registeredElements)this._subscribeToElement(e),t.isIntersectingWithViewport&&t.isActive&&this.createOrUpdateElementOverlay(e,t);s.instance.addEventListener(`callbackInvoked`,e=>{this.highlightElementCallback(e.element,e.hitType)},{signal:e}),s.instance.addEventListener(`callbackCompleted`,e=>{this.unhighlightElementCallback(e.element),this.removeElementOverlay(e.element)},{signal:e})}willUpdate(e){e.has(`showNameTags`)&&this.updateNameTagVisibility(this.showNameTags)}_subscribeToElement(e){if(this._elementSubscriptions.has(e))return;let t=()=>{let t=s.instance.registeredElements.get(e);if(!t||!t.isIntersectingWithViewport||!t.isActive){this.removeElementOverlay(e);return}this.createOrUpdateElementOverlay(e,t)},n=s.instance.subscribeToElement(e,t),r=s.instance.subscribeToElementBounds(e,t);(n||r)&&this._elementSubscriptions.set(e,()=>{n?.(),r?.()})}_unsubscribeFromElement(e){this._elementSubscriptions.get(e)?.(),this._elementSubscriptions.delete(e)}createOverlay(e){let t=document.createElement(`div`);t.className=`slop-area`;let n=document.createElement(`div`);n.className=`name-label`,this.containerElement.appendChild(t),this.containerElement.appendChild(n);let r={nameLabel:n,slopArea:t,lastSlopRect:null,lastRadiusKey:null};return this.overlayMap.set(e,r),r}expandedBorderRadius(e,t){let n=getComputedStyle(e),r=e.getBoundingClientRect(),i=(e,t,n)=>{let[i,a=i]=e.split(` `),o=(e,t)=>{let n=parseFloat(e)||0;return e.endsWith(`%`)?n/100*t:n},s=o(i,r.width),c=o(a,r.height);return[s===0?0:s+t,c===0?0:c+n]},a=i(n.borderTopLeftRadius,t.left,t.top),o=i(n.borderTopRightRadius,t.right,t.top),s=i(n.borderBottomRightRadius,t.right,t.bottom),c=i(n.borderBottomLeftRadius,t.left,t.bottom);return`${a[0]}px ${o[0]}px ${s[0]}px ${c[0]}px / ${a[1]}px ${o[1]}px ${s[1]}px ${c[1]}px`}updateSlopArea(e,t,n,r){let{expandedRect:i}=r,a=i.left+window.scrollX,o=i.top+window.scrollY,s=i.right-i.left,c=i.bottom-i.top,l=e.lastSlopRect;if(l&&l.left===a&&l.top===o&&l.width===s&&l.height===c)return;e.lastSlopRect={left:a,top:o,width:s,height:c};let{style:u}=e.slopArea;u.transform=`translate3d(${a}px, ${o}px, 0)`,u.width=`${s}px`,u.height=`${c}px`;let d=`${s}|${c}|${n.top}|${n.right}|${n.bottom}|${n.left}`;e.lastRadiusKey!==d&&(e.lastRadiusKey=d,u.borderRadius=this.expandedBorderRadius(t,n))}updateNameLabel(e,t,n){let{nameLabel:r}=e,{expandedRect:i}=n;!this.showNameTags||t.name===`unnamed`?r.style.display=`none`:(r.textContent=t.name,r.style.display=`block`,r.style.transform=`translate3d(${i.left+window.scrollX}px, ${i.top-25+window.scrollY}px, 0)`)}createOrUpdateElementOverlay(e,t){let n=s.instance.getElementBounds(e);if(!n)return;let r=this.overlayMap.get(e);r||=this.createOverlay(e),this.updateSlopArea(r,e,t.hitSlop,n),this.updateNameLabel(r,t,n)}removeElementOverlay(e){let t=this.overlayMap.get(e);t&&(t.nameLabel.remove(),t.slopArea.remove(),this.overlayMap.delete(e)),this.clearCallbackAnimationTimeout(e)}clearCallbackAnimationTimeout(e){let t=this.callbackAnimations.get(e);t&&(clearTimeout(t.timeoutId),this.callbackAnimations.delete(e))}highlightElementCallback(e,t){this.clearCallbackAnimationTimeout(e);let n=this.overlayMap.get(e);if(n)switch(t.kind){case`mouse`:case`scroll`:case`tab`:n.slopArea.dataset.hit=t.kind;break;case`touch`:break;case`viewport`:break;default:}}unhighlightElementCallback(e){let t=setTimeout(()=>{let t=this.overlayMap.get(e);t&&delete t.slopArea.dataset.hit,this.callbackAnimations.delete(e)},400);this.callbackAnimations.set(e,{element:e,timeoutId:t})}updateNameTagVisibility(e){this.overlayMap.forEach(t=>{let n=t.nameLabel;e?n.style.display=`block`:n.style.display=`none`})}disconnectedCallback(){super.disconnectedCallback();for(let e of this._elementSubscriptions.values())e();this._elementSubscriptions.clear(),this.callbackAnimations.forEach(e=>{clearTimeout(e.timeoutId)}),this.callbackAnimations.clear();for(let e of this.overlayMap.values())e.nameLabel.remove(),e.slopArea.remove();this.overlayMap.clear(),this._abortController?.abort(),this._abortController=null}render(){return n` <div id="overlays-container"></div> `}};_([o(),g(`design:type`,typeof(G=typeof Map<`u`&&Map)==`function`?G:Object)],J.prototype,`overlayMap`,void 0),_([o(),g(`design:type`,typeof(K=typeof Map<`u`&&Map)==`function`?K:Object)],J.prototype,`callbackAnimations`,void 0),_([a(`#overlays-container`),g(`design:type`,typeof(q=typeof HTMLElement<`u`&&HTMLElement)==`function`?q:Object)],J.prototype,`containerElement`,void 0),_([i({type:Boolean}),g(`design:type`,Object)],J.prototype,`showNameTags`,void 0),J=_([r(`element-overlays`)],J);let Y=class extends e{constructor(...e){super(...e),this._abortController=new AbortController,this._lineEl=null,this._mousePredictionIsEnabled=s.instance.getManagerData.globalSettings.enableMousePrediction,this._isVisible=!1,this.handleTrajectoryReset=e=>{(`wasLastActiveElement`in e&&e.wasLastActiveElement||`wasLastRegisteredElement`in e&&e.wasLastRegisteredElement)&&(this._setVisible(!1),this._lineEl&&(this._lineEl.style.transform=`translate3d(0px, 0px, 0) rotate(0deg)`,this._lineEl.style.width=`0px`))},this.handleSettingsChange=e=>{let t=e.managerData.globalSettings.enableMousePrediction;this._mousePredictionIsEnabled=t,t||this._setVisible(!1)},this.handleTrajectoryUpdate=e=>{if(!this._mousePredictionIsEnabled)return;this._setVisible(!0);let{currentPoint:t,predictedPoint:n}=e.trajectoryPositions,r=n.x-t.x,i=n.y-t.y,a=Math.sqrt(r*r+i*i),o=Math.atan2(i,r)*57.29577951308232;this._lineEl&&(this._lineEl.style.transform=`translate3d(${t.x}px, ${t.y}px, 0) rotate(${o}deg)`,this._lineEl.style.width=`${a}px`)}}static{this.styles=[t`
2054
+ :host {
2055
+ display: block;
2056
+ }
2057
+
2058
+ :host([hidden]) {
2059
+ display: none;
2060
+ }
2061
+
2062
+ .trajectory-line {
2063
+ display: none;
2064
+ position: absolute;
2065
+ top: 0;
2066
+ left: 0;
2067
+ will-change: transform, width;
2068
+ transform-origin: left center;
2069
+ height: 4px;
2070
+ background: linear-gradient(90deg, #3b82f6, rgba(59, 130, 246, 0.4));
2071
+ z-index: 9999;
2072
+ border-radius: 2px;
2073
+ box-shadow: 0 0 12px rgba(59, 130, 246, 0.4);
2074
+ }
2075
+
2076
+ .trajectory-line::after {
2077
+ content: "";
2078
+ position: absolute;
2079
+ right: -6px;
2080
+ top: 50%;
2081
+ transform: translateY(-50%);
2082
+ width: 0;
2083
+ height: 0;
2084
+ border-left: 8px solid #3b82f6;
2085
+ border-top: 4px solid transparent;
2086
+ border-bottom: 4px solid transparent;
2087
+ filter: drop-shadow(0 0 6px rgba(59, 130, 246, 0.6));
2088
+ }
2089
+ `]}connectedCallback(){super.connectedCallback();let{signal:e}=this._abortController;s.instance.addEventListener(`callbackCompleted`,this.handleTrajectoryReset,{signal:e}),s.instance.addEventListener(`elementUnregistered`,this.handleTrajectoryReset,{signal:e}),s.instance.addEventListener(`mouseTrajectoryUpdate`,this.handleTrajectoryUpdate,{signal:e}),s.instance.addEventListener(`scrollTrajectoryUpdate`,()=>{this._setVisible(!1)},{signal:e}),s.instance.addEventListener(`managerSettingsChanged`,this.handleSettingsChange,{signal:e})}firstUpdated(){this._lineEl=this.shadowRoot.querySelector(`.trajectory-line`)}disconnectedCallback(){super.disconnectedCallback(),this._abortController.abort()}_setVisible(e){this._isVisible!==e&&(this._isVisible=e,this._lineEl&&(this._lineEl.style.display=e?`block`:`none`))}render(){return n`<div class="trajectory-line"></div>`}};Y=_([r(`mouse-trajectory`)],Y);let X=class extends e{constructor(...e){super(...e),this._abortController=new AbortController,this._lineEl=null,this._scrollPredictionIsEnabled=s.instance.getManagerData.globalSettings.enableScrollPrediction,this._scrollMargin=s.instance.getManagerData.globalSettings.scrollMargin,this._isVisible=!1,this._latestCurrentPoint=null,this._latestPredictedPoint=null,this._isUpdateScheduled=!1,this.handleTrajectoryReset=e=>{(`wasLastActiveElement`in e&&e.wasLastActiveElement||`wasLastRegisteredElement`in e&&e.wasLastRegisteredElement)&&(this._setVisible(!1),this._lineEl&&(this._lineEl.style.transform=`translate(0px, 0px) rotate(0deg)`))},this.handleSettingsChange=e=>{let t=e.managerData.globalSettings.enableScrollPrediction;this._scrollPredictionIsEnabled=t,t||this._setVisible(!1);let n=e.updatedSettings.find(e=>e.setting===`scrollMargin`);n&&(this._scrollMargin=n.newValue,this._lineEl&&(this._lineEl.style.width=`${this._scrollMargin}px`))},this.handleScrollUpdate=e=>{this._scrollPredictionIsEnabled&&(this._setVisible(!0),this._latestCurrentPoint=e.currentPoint,this._latestPredictedPoint=e.predictedPoint,this._isUpdateScheduled||(this._isUpdateScheduled=!0,this.applyScrollTransform()))},this.applyScrollTransform=()=>{if(!this._latestCurrentPoint||!this._latestPredictedPoint){this._isUpdateScheduled=!1;return}let e=this._latestPredictedPoint.x-this._latestCurrentPoint.x,t=this._latestPredictedPoint.y-this._latestCurrentPoint.y,n=Math.atan2(t,e)*180/Math.PI;this._lineEl&&(this._lineEl.style.transform=`translate(${this._latestCurrentPoint.x}px, ${this._latestCurrentPoint.y}px) rotate(${n}deg)`),this._isUpdateScheduled=!1}}static{this.styles=[t`
2090
+ :host {
2091
+ display: block;
2092
+ }
2093
+
2094
+ :host([hidden]) {
2095
+ display: none;
2096
+ }
2097
+
2098
+ .scroll-trajectory-line {
2099
+ display: none;
2100
+ position: absolute;
2101
+ top: 0;
2102
+ left: 0;
2103
+ will-change: transform, width;
2104
+ transform-origin: left center;
2105
+ height: 4px;
2106
+ background: repeating-linear-gradient(
2107
+ 90deg,
2108
+ #eab308 0px,
2109
+ #eab308 8px,
2110
+ transparent 8px,
2111
+ transparent 16px
2112
+ );
2113
+ z-index: 9999;
2114
+ border-radius: 2px;
2115
+ animation: scroll-dash-flow 1.5s linear infinite;
2116
+ box-shadow: 0 0 12px rgba(234, 179, 8, 0.4);
2117
+ }
2118
+
2119
+ .scroll-trajectory-line::after {
2120
+ content: "";
2121
+ position: absolute;
2122
+ right: -6px;
2123
+ top: 50%;
2124
+ transform: translateY(-50%);
2125
+ width: 0;
2126
+ height: 0;
2127
+ border-left: 8px solid #eab308;
2128
+ border-top: 4px solid transparent;
2129
+ border-bottom: 4px solid transparent;
2130
+ filter: drop-shadow(0 0 6px rgba(234, 179, 8, 0.6));
2131
+ animation: scroll-arrow-pulse 1.5s ease-in-out infinite;
2132
+ }
2133
+
2134
+ @keyframes scroll-dash-flow {
2135
+ 0% {
2136
+ background-position: 0px 0px;
2137
+ }
2138
+ 100% {
2139
+ background-position: 16px 0px;
2140
+ }
2141
+ }
2142
+
2143
+ @keyframes scroll-arrow-pulse {
2144
+ 0%,
2145
+ 100% {
2146
+ transform: translateY(-50%) scale(1);
2147
+ filter: drop-shadow(0 0 6px rgba(234, 179, 8, 0.6));
2148
+ }
2149
+ 50% {
2150
+ transform: translateY(-50%) scale(1.2);
2151
+ filter: drop-shadow(0 0 12px rgba(234, 179, 8, 0.8));
2152
+ }
2153
+ }
2154
+ `]}connectedCallback(){super.connectedCallback();let{signal:e}=this._abortController;s.instance.addEventListener(`scrollTrajectoryUpdate`,this.handleScrollUpdate,{signal:e}),s.instance.addEventListener(`mouseTrajectoryUpdate`,()=>{this._setVisible(!1)},{signal:e}),s.instance.addEventListener(`callbackCompleted`,this.handleTrajectoryReset,{signal:e}),s.instance.addEventListener(`elementUnregistered`,this.handleTrajectoryReset,{signal:e}),s.instance.addEventListener(`managerSettingsChanged`,this.handleSettingsChange,{signal:e})}firstUpdated(){this._lineEl=this.shadowRoot.querySelector(`.scroll-trajectory-line`)}disconnectedCallback(){super.disconnectedCallback(),this._abortController.abort()}_setVisible(e){this._isVisible!==e&&(this._isVisible=e,this._lineEl&&(this._lineEl.style.display=e?`block`:`none`))}render(){return n`<div class="scroll-trajectory-line" style="width: ${this._scrollMargin}px"></div>`}};X=_([r(`scroll-trajectory`)],X);let Z=class extends e{constructor(...e){super(...e),this._abortController=null,this._strategy=s.instance.getManagerData.currentDeviceStrategy,this.showElementOverlays=!0,this.showMouseTrajectory=!0,this.showScrollTrajectory=!0,this.showNameTags=!0,this.handleDeviceStrategyChange=e=>this._strategy=e.newStrategy}static{this.styles=[t`
2155
+ :host {
2156
+ display: block;
2157
+ }
2158
+ #overlay-container {
2159
+ position: fixed;
2160
+ top: 0;
2161
+ left: 0;
2162
+ pointer-events: none;
2163
+ z-index: 9999;
2164
+ }
2165
+ `]}connectedCallback(){super.connectedCallback(),this._abortController=new AbortController;let{signal:e}=this._abortController;s.instance.addEventListener(`deviceStrategyChanged`,this.handleDeviceStrategyChange,{signal:e})}disconnectedCallback(){super.disconnectedCallback(),this._abortController?.abort()}render(){return n`
2166
+ <div id="overlay-container">
2167
+ ${this._strategy===`mouse`?n`
2168
+ <mouse-trajectory ?hidden=${!this.showMouseTrajectory}></mouse-trajectory>
2169
+ <scroll-trajectory ?hidden=${!this.showScrollTrajectory}></scroll-trajectory>
2170
+ `:``}
2171
+ </div>
2172
+ <!-- element-overlays positions itself in document coordinates and must stay
2173
+ outside #overlay-container: the fixed container would become its
2174
+ containing block and pin it back to the viewport. -->
2175
+ ${this._strategy===`mouse`?n`
2176
+ <element-overlays
2177
+ ?hidden=${!this.showElementOverlays}
2178
+ .showNameTags=${this.showNameTags}
2179
+ ></element-overlays>
2180
+ `:``}
2181
+ `}};_([o(),g(`design:type`,String)],Z.prototype,`_strategy`,void 0),_([i({type:Boolean}),g(`design:type`,Object)],Z.prototype,`showElementOverlays`,void 0),_([i({type:Boolean}),g(`design:type`,Object)],Z.prototype,`showMouseTrajectory`,void 0),_([i({type:Boolean}),g(`design:type`,Object)],Z.prototype,`showScrollTrajectory`,void 0),_([i({type:Boolean}),g(`design:type`,Object)],Z.prototype,`showNameTags`,void 0),Z=_([r(`debug-overlay`)],Z);var Q;let $=class extends e{static{Q=this}static{this.styles=[t`
2182
+ :host {
2183
+ display: block;
2184
+ }
2185
+ `]}static{this._instance=null}constructor(){super(),this.isInitialized=!1,this.devtoolsSettings={show:{controlPanel:!0,nameTags:!0,elementOverlays:!0,mouseTrajectory:!0,scrollTrajectory:!0},isControlPanelDefaultMinimized:!1,sortElementList:`visibility`,logging:{logLocation:`controlPanel`,callbackCompleted:!0,callbackInvoked:!0,elementRegistered:!1,elementUnregistered:!1,managerSettingsChanged:!0,mouseTrajectoryUpdate:!1,scrollTrajectoryUpdate:!1,deviceStrategyChanged:!0}}}static createAndAppendInstance(){typeof window>`u`||typeof document>`u`||(Q._instance=document.createElement(`foresight-devtools`),document.body.appendChild(Q._instance))}static initialize(e){if(Q._instance||Q.createAndAppendInstance(),!Q._instance)return Q._instance;let t=Q._instance;return t.isInitialized=!0,t.alterDevtoolsSettings(e),t}static get instance(){return Q._instance?Q._instance:Q.initialize()}disconnectedCallback(){super.disconnectedCallback(),this.cleanup()}shouldUpdateSetting(e,t){return e!==void 0&&e!==t}updateLoggingSetting(e,t){this.shouldUpdateSetting(t,this.devtoolsSettings.logging[e])&&(this.devtoolsSettings.logging[e]=t)}updateShowSetting(e,t){return this.shouldUpdateSetting(t,this.devtoolsSettings.show[e])?(this.devtoolsSettings.show[e]=t,!0):!1}setAllShow(e){let t=Object.fromEntries(l.map(t=>[t,e]));this.alterDevtoolsSettings({show:t})}alterDevtoolsSettings(e){if(e!==void 0){if(e.show){let t=!1;for(let n of l)this.updateShowSetting(n,e.show[n])&&(t=!0);t&&this.requestUpdate()}this.shouldUpdateSetting(e.isControlPanelDefaultMinimized,this.devtoolsSettings.isControlPanelDefaultMinimized)&&(this.devtoolsSettings.isControlPanelDefaultMinimized=e.isControlPanelDefaultMinimized),this.shouldUpdateSetting(e.sortElementList,this.devtoolsSettings.sortElementList)&&(this.devtoolsSettings.sortElementList=e.sortElementList),e.logging&&(this.shouldUpdateSetting(e.logging.logLocation,this.devtoolsSettings.logging.logLocation)&&(this.devtoolsSettings.logging.logLocation=e.logging.logLocation),this.updateLoggingSetting(`callbackCompleted`,e.logging.callbackCompleted),this.updateLoggingSetting(`callbackInvoked`,e.logging.callbackInvoked),this.updateLoggingSetting(`elementRegistered`,e.logging.elementRegistered),this.updateLoggingSetting(`elementUnregistered`,e.logging.elementUnregistered),this.updateLoggingSetting(`managerSettingsChanged`,e.logging.managerSettingsChanged),this.updateLoggingSetting(`mouseTrajectoryUpdate`,e.logging.mouseTrajectoryUpdate),this.updateLoggingSetting(`scrollTrajectoryUpdate`,e.logging.scrollTrajectoryUpdate),this.updateLoggingSetting(`deviceStrategyChanged`,e.logging.deviceStrategyChanged))}}cleanup(){this.requestUpdate()}render(){if(!this.isInitialized)return n``;let{show:e}=this.devtoolsSettings;return n`
2186
+ ${e.controlPanel?n`<control-panel></control-panel>`:``}
2187
+ <debug-overlay
2188
+ .showElementOverlays=${e.elementOverlays}
2189
+ .showMouseTrajectory=${e.mouseTrajectory}
2190
+ .showScrollTrajectory=${e.scrollTrajectory}
2191
+ .showNameTags=${e.nameTags}
2192
+ ></debug-overlay>
2193
+ `}};_([o(),g(`design:type`,Object)],$.prototype,`isInitialized`,void 0),$=Q=_([r(`foresight-devtools`),g(`design:paramtypes`,[])],$);export{$ as ForesightDevtools};
2194
+ //# sourceMappingURL=index.mjs.map