js.foresight-devtools
Version:
Visual debugging tools for ForesightJS - mouse trajectory prediction and element interaction visualization
1,086 lines (1,009 loc) • 101 kB
JavaScript
var ze=Object.defineProperty;var He=Object.getOwnPropertyDescriptor;var n=(o,r,e,t)=>{for(var i=t>1?void 0:t?He(r,e):r,a=o.length-1,s;a>=0;a--)(s=o[a])&&(i=(t?s(r,e,i):s(i))||i);return t&&i&&ze(r,e,i),i};import{LitElement as zn,css as Hn,html as Fe}from"lit";import{customElement as Bn,state as Gn}from"lit/decorators.js";import{LitElement as yn,css as wn,html as xn}from"lit";import{customElement as kn,state as Q}from"lit/decorators.js";import{classMap as re}from"lit/directives/class-map.js";import{ForesightManager as Ae}from"js.foresight";import{css as St,html as B,LitElement as Tt}from"lit";import{customElement as Dt,state as L}from"lit/decorators.js";import{map as Me}from"lit/directives/map.js";import{ForesightManager as $}from"js.foresight";import{html as c}from"lit";var le=c`
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<rect x="2" y="2" width="20" height="15" rx="2" ry="2"></rect>
<line x1="2" y1="17" x2="22" y2="17"></line>
<line x1="7" y1="21" x2="17" y2="21"></line>
<line x1="12" y1="17" x2="12" y2="21"></line>
</svg>
`,ce=c`
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="4 17 10 11 4 5"></polyline>
<line x1="12" y1="19" x2="20" y2="19"></line>
</svg>
`,de=c`
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path>
<path d="M13.73 21a2 2 0 0 1-3.46 0"></path>
<line x1="1" y1="1" x2="23" y2="23"></line>
</svg>
`,ge=c`
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 2v8" />
<path d="M12 10l-6 6" />
<path d="M12 10l6 6" />
<circle cx="6" cy="18" r="2" />
<circle cx="18" cy="18" r="2" />
</svg>
`,pe=c`
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z" />
<circle cx="12" cy="12" r="3" />
</svg>
`,he=c`
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<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" />
<polyline points="14 2 14 8 20 8" />
<line x1="16" y1="13" x2="8" y2="13" />
<line x1="16" y1="17" x2="8" y2="17" />
<line x1="10" y1="9" x2="8" y2="9" />
</svg>
`,me=c`
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01" />
</svg>
`,h=c`
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<polygon points="22,3 2,3 10,12.46 10,19 14,21 14,12.46" />
</svg>
`,ue=c`
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<circle cx="12" cy="12" r="10" />
<line x1="4.93" y1="4.93" x2="19.07" y2="19.07" />
</svg>
`,be=c`
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
`,ve=c`
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
`,fe=c`
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
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"
></path>
<line x1="12" y1="9" x2="12" y2="13"></line>
<line x1="12" y1="17" x2="12.01" y2="17"></line>
</svg>
`,ye=c`
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<circle cx="6" cy="12" r="3"></circle>
<circle cx="18" cy="12" r="3"></circle>
<path d="M9 12h6"></path>
<path d="M15 9l3 3-3 3"></path>
<circle cx="12" cy="6" r="2"></circle>
<circle cx="12" cy="18" r="2"></circle>
<path d="M10 8l2-2 2 2"></path>
<path d="M14 16l-2 2-2-2"></path>
</svg>
`,we=c`
<svg
xmlns="http://www.w3.org/2000/svg"
width="12"
height="12"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="3 6 5 6 21 6"></polyline>
<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>
<line x1="10" y1="11" x2="10" y2="17"></line>
<line x1="14" y1="11" x2="14" y2="17"></line>
</svg>
`,Yn=c`
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M18 8a6 6 0 0 0-12 0c0 2 3 4 6 6 3-2 6-4 6-6z"/>
<circle cx="12" cy="8" r="3"/>
</svg>
`,Jn=c`
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<rect x="2" y="3" width="20" height="14" rx="2" ry="2"/>
<line x1="8" y1="21" x2="16" y2="21"/>
<line x1="12" y1="17" x2="12" y2="21"/>
<circle cx="12" cy="10" r="2"/>
</svg>
`,Xn=c`
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<circle cx="12" cy="12" r="10"/>
<line x1="4.93" y1="4.93" x2="19.07" y2="19.07"/>
</svg>
`;import{LitElement as Be,html as Ge,css as We}from"lit";import{customElement as Ke,property as qe}from"lit/decorators.js";var U=class extends Be{constructor(){super(...arguments);this.title=""}render(){return Ge`
<span class="chip" title="${this.title}">
<slot></slot>
</span>
`}};U.styles=[We`
:host {
display: inline-block;
}
.chip {
display: inline-flex;
align-items: center;
padding: 3px 8px;
background-color: rgba(255, 255, 255, 0.05);
color: #e8e8e8;
font-size: 10px;
font-weight: 500;
white-space: nowrap;
border: 1px solid rgba(255, 255, 255, 0.1);
font-family: "SF Mono", "Monaco", "Consolas", "Liberation Mono", "Courier New", monospace;
letter-spacing: 0.02em;
line-height: 1.2;
transition: all 0.2s ease;
}
`],n([qe({type:String})],U.prototype,"title",2),U=n([Ke("chip-element")],U);import{LitElement as Ye,html as te,css as Je}from"lit";import{customElement as Xe,property as xe}from"lit/decorators.js";var D=class extends Ye{constructor(){super(...arguments);this.noContentMessage="No content available.";this.hasContent=!0}render(){return te`
<div class="content-container">
${this.hasContent?te`<slot></slot>`:te`<div class="no-content-message">${this.noContentMessage}</div>`}
</div>
`}};D.styles=[Je`
:host {
overflow: hidden;
}
.content-container::-webkit-scrollbar {
width: 8px;
}
.content-container::-webkit-scrollbar-track {
background: rgba(30, 30, 30, 0.5);
}
.content-container::-webkit-scrollbar-thumb {
background-color: rgba(176, 196, 222, 0.5);
border: 2px solid rgba(0, 0, 0, 0.2);
}
.content-container::-webkit-scrollbar-thumb:hover {
background-color: rgba(176, 196, 222, 0.7);
}
.content-container {
scrollbar-gutter: stable;
height: 100%;
min-height: 150px;
overflow-y: auto;
scrollbar-width: thin;
scrollbar-color: rgba(176, 196, 222, 0.5) rgba(30, 30, 30, 0.5);
}
.no-content-message {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
color: #afafaf;
font-style: italic;
font-family: "Courier New", monospace;
}
`],n([xe({type:String,attribute:"no-content-message"})],D.prototype,"noContentMessage",2),n([xe({type:Boolean})],D.prototype,"hasContent",2),D=n([Xe("tab-content")],D);import{LitElement as Ze,html as Qe,css as et}from"lit";import{customElement as tt}from"lit/decorators.js";var z=class extends Ze{render(){return Qe`
<div class="tab-bar-elements">
<div class="tab-bar-info">
<div class="stats-chips">
<slot name="chips"></slot>
</div>
</div>
<div class="tab-bar-actions">
<slot name="actions"></slot>
</div>
</div>
`}};z.styles=[et`
:host {
}
.tab-bar-info {
display: flex;
gap: 12px;
align-items: center;
flex: 1;
}
.stats-chips {
display: flex;
gap: 8px;
align-items: center;
}
.chip {
font-size: 11px;
font-weight: 500;
padding: 4px 8px;
border: 1px solid #555;
white-space: nowrap;
letter-spacing: 0.3px;
background: rgba(40, 40, 40, 0.7);
color: #b0c4de;
}
.tab-bar-actions {
display: flex;
gap: 6px;
align-items: center;
position: relative;
flex-direction: row;
}
.tab-bar-elements {
display: flex;
justify-content: space-between;
padding: 4px 0 4px 0;
border-bottom: 1px solid #444;
position: sticky;
top: 0;
z-index: 5;
min-height: 36px;
}
`],z=n([tt("tab-header")],z);import{html as rt}from"lit";import{customElement as st,property as Ee}from"lit/decorators.js";import{LitElement as nt,html as ke,css as it}from"lit";import{property as ot,state as at}from"lit/decorators.js";var g=class g extends nt{constructor(){super(...arguments);this.isDropdownOpen=!1;this.dropdownOptions=[];this._toggleDropdown=e=>{e.stopPropagation(),this.isDropdownOpen?this._closeDropdown():(g.currentlyOpen&&g.currentlyOpen!==this&&g.currentlyOpen._closeDropdown(),this.isDropdownOpen=!0,g.currentlyOpen=this,requestAnimationFrame(()=>{this._positionDropdown()}))};this._handleOutsideClick=e=>{this.isDropdownOpen&&(e.composedPath().includes(this)||this._closeDropdown())}}connectedCallback(){super.connectedCallback(),document.addEventListener("click",this._handleOutsideClick)}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener("click",this._handleOutsideClick),g.currentlyOpen===this&&(g.currentlyOpen=null)}_closeDropdown(){this.isDropdownOpen=!1,g.currentlyOpen===this&&(g.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 i=e.getBoundingClientRect(),a=t.offsetHeight||200,s=i.bottom+5,d=window.innerWidth-i.right;window.innerHeight-i.bottom<a&&i.top>a?t.style.top=`${i.top-a-5}px`:t.style.top=`${s}px`,t.style.right=`${d}px`}}render(){let e=`trigger-button ${this.isDropdownOpen?"active":""}`,t=`dropdown-menu ${this.isDropdownOpen?"active":""}`;return ke`
<div class="dropdown-container">
<button
class="${e}"
title="${this._getTriggerTitle()}"
@click="${this._toggleDropdown}"
aria-haspopup="true"
aria-expanded="${this.isDropdownOpen}"
aria-controls="dropdown-menu"
aria-label="${this._getTriggerLabel()}"
>
${this._getTriggerIcon()}
<svg
class="arrow-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
<div class="${t}" id="dropdown-menu" role="menu">
${this.dropdownOptions.map(i=>ke`
<button
value="${i.value}"
title="${i.title}"
class="${this._isOptionSelected(i)?"active":""}"
@click="${()=>this._handleOptionClick(i)}"
role="menuitem"
>
${i.label}
</button>
`)}
</div>
</div>
`}};g.currentlyOpen=null,g.styles=[it`
:host {
display: inline-block;
}
.dropdown-container {
position: relative;
display: inline-block;
}
.trigger-button {
background: none;
border: none;
color: white;
cursor: pointer;
padding: 6px;
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
transition: all 0.2s ease;
}
.trigger-button svg {
width: 16px;
height: 16px;
stroke: white;
transition: stroke 0.2s;
}
.trigger-button .arrow-icon {
width: 10px;
height: 10px;
stroke: white;
fill: none;
stroke-width: 2;
transition:
transform 0.2s ease,
stroke 0.2s;
}
.trigger-button:hover {
background-color: rgba(176, 196, 222, 0.1);
}
.trigger-button:hover svg,
.trigger-button:hover .arrow-icon {
stroke: #b0c4de;
}
.trigger-button.active {
background-color: rgba(176, 196, 222, 0.2);
}
.trigger-button.active svg {
stroke: #b0c4de;
}
.trigger-button.active .arrow-icon {
transform: rotate(180deg);
stroke: #b0c4de;
}
.dropdown-menu {
position: fixed;
z-index: 9999;
display: none;
flex-direction: column;
background-color: #3a3a3a;
border: 1px solid #555;
min-width: 200px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
overflow: hidden;
}
.dropdown-menu.active {
display: flex;
}
.dropdown-menu button {
background: none;
border: none;
color: #ccc;
font-size: 12px;
text-align: left;
padding: 8px 12px;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
align-items: center;
position: relative;
width: 100%;
box-sizing: border-box;
}
.dropdown-menu button:hover {
background-color: #555;
color: white;
}
.dropdown-menu button.active {
color: #b0c4de;
font-weight: bold;
background-color: rgba(176, 196, 222, 0.1);
}
.dropdown-menu button.active::after {
content: "✓";
position: absolute;
right: 8px;
top: 50%;
transform: translateY(-50%);
color: #b0c4de;
font-weight: bold;
}
`],n([at()],g.prototype,"isDropdownOpen",2),n([ot({type:Array})],g.prototype,"dropdownOptions",2);var M=g;var N=class extends M{constructor(){super(...arguments);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:rt``}_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)}};n([Ee({type:String})],N.prototype,"selectedOptionValue",2),n([Ee({type:Function})],N.prototype,"onSelectionChange",2),N=n([st("single-select-dropdown")],N);import{LitElement as wt,html as xt,css as kt}from"lit";import{customElement as Et,property as J,state as Ct}from"lit/decorators.js";import{LitElement as pt,html as Te,css as ht}from"lit";import{customElement as mt,property as H}from"lit/decorators.js";import{LitElement as lt,html as ct,css as dt}from"lit";import{customElement as gt,property as Ce,state as Se}from"lit/decorators.js";var y=class extends lt{constructor(){super(...arguments);this.title="Copy to clipboard";this.isCopied=!1;this.copyTimeout=null}async handleClick(e){if(!this.isCopied){if(this.onCopy)try{await this.onCopy(e)}catch(t){console.error("Error in onCopy function:",t)}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),this.copyTimeout=null)}render(){return ct`
<button
class="copy-button ${this.isCopied?"copied":""}"
title="${this.title}"
@click=${this.handleClick}
>
${this.isCopied?ve:be}
</button>
`}};y.styles=dt`
.copy-button {
background: transparent;
border: 0px;
cursor: pointer;
padding: 6px;
display: flex;
align-items: center;
justify-content: center;
opacity: 0.6;
transition:
opacity 0.2s ease,
background-color 0.2s ease;
}
:host([positioned]) .copy-button {
position: absolute;
top: 10px;
right: 1px;
}
.copy-button:hover {
background-color: rgba(176, 196, 222, 0.1);
}
.copy-button:hover svg {
stroke: #b0c4de;
}
.copy-button svg {
width: 14px;
height: 14px;
stroke: #ddd;
stroke-width: 2.5;
}
.copy-button.copied svg {
stroke: #4caf50;
}
`,n([Ce({type:String})],y.prototype,"title",2),n([Ce({type:Function})],y.prototype,"onCopy",2),n([Se()],y.prototype,"isCopied",2),n([Se()],y.prototype,"copyTimeout",2),y=n([gt("copy-icon")],y);var b=class extends pt{constructor(){super(...arguments);this.borderColor="#555";this.showCopyButton=!1;this.itemId="";this.isExpanded=!1}toggleExpand(){this.onToggle&&this.onToggle(this.itemId)}async handleCopy(e){e.stopPropagation();let t=this.shadowRoot?.querySelector('slot[name="details"]');if(t){let a=t.assignedNodes().map(s=>s.textContent).join("");try{await navigator.clipboard.writeText(a)}catch(s){console.error("Failed to copy text: ",s)}}}render(){return this.style.setProperty("--border-color",this.borderColor),Te`
<div class="item-entry ${this.isExpanded?"expanded":""}">
<div class="item-header ${this.isExpanded?"expanded":""}" @click="${this.toggleExpand}">
<div class="item-content">
<slot name="content"></slot>
</div>
<span class="item-toggle ${this.isExpanded?"expanded":""}">
<svg viewBox="0 0 24 24">
<polyline points="9,18 15,12 9,6"></polyline>
</svg>
</span>
</div>
${this.isExpanded?Te`
<div class="item-details">
<copy-icon
positioned
title="Copy Details"
.onCopy=${e=>this.handleCopy(e)}
></copy-icon>
<pre class="item-data">
<slot name="details"></slot>
</pre>
</div>
`:""}
</div>
`}};b.styles=[ht`
:host {
display: block;
}
.item-entry {
margin-bottom: 2px;
font-size: 11px;
line-height: 1.3;
overflow: hidden;
transition: all 0.2s ease;
border-left: 2px solid var(--border-color, #555);
padding-left: 6px;
}
.item-entry:hover:not(.expanded) {
background-color: rgba(255, 255, 255, 0.02);
}
.item-entry.expanded {
background-color: rgba(255, 255, 255, 0.03);
}
.item-header {
display: flex;
align-items: center;
padding: 3px 4px;
cursor: pointer;
transition: background-color 0.2s ease;
gap: 8px;
min-height: 20px;
}
.item-header:hover:not(.expanded) {
background-color: rgba(255, 255, 255, 0.03);
}
.item-details {
position: relative;
border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.item-toggle {
display: flex;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
user-select: none;
cursor: pointer;
transition: all 0.2s ease;
}
.item-toggle:hover {
background-color: rgba(255, 255, 255, 0.1);
}
.item-toggle svg {
width: 14px;
height: 14px;
fill: none;
stroke: #b0c4de;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
transition: all 0.2s ease;
}
.item-toggle:hover svg {
stroke: #d4e4f4;
}
.item-toggle.expanded svg {
transform: rotate(90deg);
}
.item-content {
flex: 1;
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
overflow: hidden;
}
.item-data {
color: #e0e0e0;
white-space: pre;
font-size: 11px;
margin: 0;
padding: 0;
font-family: "Courier New", monospace;
line-height: 1.3;
display: block;
overflow-x: auto;
}
`],n([H()],b.prototype,"borderColor",2),n([H()],b.prototype,"showCopyButton",2),n([H()],b.prototype,"itemId",2),n([H()],b.prototype,"isExpanded",2),n([H()],b.prototype,"onToggle",2),b=n([mt("expandable-item")],b);import{ForesightManager as ut}from"js.foresight";import{LitElement as bt,css as vt,html as Y}from"lit";import{customElement as ft,property as yt,state as De}from"lit/decorators.js";var E=class extends bt{constructor(){super(...arguments);this.remainingTime=0;this.isCountdownActive=!1;this.intervalId=null;this.startTime=0;this.handleTimerClick=e=>{e.stopPropagation(),ut.instance.reactivate(this.elementData.element)}}connectedCallback(){super.connectedCallback(),this.checkAndStartCountdown()}disconnectedCallback(){super.disconnectedCallback(),this.clearCountdown()}updated(e){super.updated(e),e.has("elementData")&&this.checkAndStartCountdown()}checkAndStartCountdown(){let e=this.elementData?.callbackInfo;if(!e){this.clearCountdown();return}let t=e.lastCallbackCompletedAt||e.lastCallbackInvokedAt;!e.isCallbackActive&&t&&e.reactivateAfter>0?this.startCountdown():this.clearCountdown()}startCountdown(){this.clearCountdown();let e=this.elementData?.callbackInfo;if(!e)return;if(this.isCountdownActive=!0,e.reactivateAfter===1/0){this.remainingTime=1/0;return}let t=e.reactivateAfter,i=e.lastCallbackCompletedAt||e.lastCallbackInvokedAt;if(!i){this.clearCountdown();return}this.startTime=i;let a=()=>{let s=Date.now()-this.startTime,d=Math.max(0,t-s);this.remainingTime=d,this.requestUpdate(),(d<=0||this.elementData.callbackInfo.isCallbackActive)&&this.clearCountdown()};a(),this.remainingTime>0&&typeof window<"u"&&(this.intervalId=window.setInterval(a,100))}clearCountdown(){this.intervalId!==null&&(clearInterval(this.intervalId),this.intervalId=null),this.isCountdownActive=!1,this.remainingTime=0}formatTime(e){if(e===1/0)return"\u221E";let t=Math.ceil(e/1e3);if(t<60)return`${t}s`;let i=Math.floor(t/60),a=t%60;if(i<60)return a>0?`${i}m ${a}s`:`${i}m`;let s=Math.floor(i/60),d=i%60;return d>0?`${s}h ${d}m`:`${s}h`}render(){return this.isCountdownActive?this.remainingTime===1/0?Y`
<button
class="reactivate-button"
@click="${this.handleTimerClick}"
title="Click to reactivate manually"
>
<span class="countdown-time infinity">∞</span>
</button>
`:this.remainingTime<=0?Y``:Y`
<button
class="reactivate-button"
@click="${this.handleTimerClick}"
title="Click to reactivate immediately"
>
<span class="countdown-time clickable">${this.formatTime(this.remainingTime)}</span>
</button>
`:Y``}};E.styles=[vt`
:host {
display: inline-block;
}
.reactivate-button {
all: unset;
cursor: pointer;
padding: 2px 4px;
transition: background-color 0.2s ease;
}
.reactivate-button:hover {
background-color: rgba(255, 165, 0, 0.1);
}
.countdown-time {
color: #ffa726;
font-weight: 500;
font-size: 10px;
}
.countdown-time.infinity {
font-size: 12px;
font-weight: 600;
}
.countdown-time.clickable {
cursor: pointer;
}
`],n([yt({hasChanged:()=>!0})],E.prototype,"elementData",2),n([De()],E.prototype,"remainingTime",2),n([De()],E.prototype,"isCountdownActive",2),E=n([ft("reactivate-countdown")],E);import{ForesightManager as ne}from"js.foresight";var v=class extends wt{constructor(){super(...arguments);this.isActive=!1;this.isExpanded=!1;this.currentDeviceStrategy="mouse";this._abortController=null;this.handleUnregister=e=>{e.stopPropagation(),ne.instance.unregister(this.elementData.element,"devtools")}}connectedCallback(){super.connectedCallback(),this._abortController=new AbortController;let{signal:e}=this._abortController;this.currentDeviceStrategy=ne.instance.getManagerData.currentDeviceStrategy,ne.instance.addEventListener("deviceStrategyChanged",t=>{this.currentDeviceStrategy=t.newStrategy},{signal:e})}disconnectedCallback(){super.disconnectedCallback(),this._abortController?.abort(),this._abortController=null}getBorderColor(){return this.isActive?"#ffeb3b":this.elementData.callbackInfo.isCallbackActive?this.currentDeviceStrategy==="touch"?"#ba68c8":this.elementData.isIntersectingWithViewport?"#4caf50":"#666":"#999"}getStatusIndicatorClass(){return this.isActive?"prefetching":this.elementData.callbackInfo.isCallbackActive?this.currentDeviceStrategy==="touch"?"touch-device":this.elementData.isIntersectingWithViewport?"visible":"hidden":"inactive"}getStatusText(){if(this.isActive)return"callback active";if(!this.elementData.callbackInfo.isCallbackActive)return"callback inactive";let e=this.elementData.isIntersectingWithViewport?"in viewport":"not in viewport",t=this.currentDeviceStrategy==="touch"?" (touch device)":"";return e+t}formatElementDetails(){let e=this.elementData,t={status:this.getStatusText(),isIntersecting:e.isIntersectingWithViewport,registerCount:e.registerCount,hitSlop:{top:e.elementBounds.hitSlop.top,right:e.elementBounds.hitSlop.right,bottom:e.elementBounds.hitSlop.bottom,left:e.elementBounds.hitSlop.left},callbackInfo:e.callbackInfo,meta:this.elementData.meta};return JSON.stringify(t,null,2)}render(){let e=!this.elementData.isIntersectingWithViewport&&this.currentDeviceStrategy!=="touch";return xt`
<div class="element-wrapper ${e?"not-visible":""}">
<expandable-item
.borderColor=${this.getBorderColor()}
.showCopyButton=${!0}
.itemId=${this.elementData.id}
.isExpanded=${this.isExpanded}
.onToggle=${this.onToggle}
>
<div slot="content" class="element-content" title="Status: ${this.getStatusText()}">
<div class="status-indicator ${this.getStatusIndicatorClass()}"></div>
<span
class="element-name ${this.isActive?"callback-active":this.elementData.callbackInfo.isCallbackActive?"":"callback-inactive"}"
>
${this.elementData.name||"unnamed"}
</span>
<reactivate-countdown .elementData=${this.elementData}> </reactivate-countdown>
<button
class="unregister-button"
@click="${this.handleUnregister}"
title="Unregister element"
>
${we}
</button>
</div>
<div slot="details">${this.formatElementDetails()}</div>
</expandable-item>
</div>
`}};v.styles=[kt`
:host {
display: block;
}
.element-wrapper {
display: block;
}
.element-content {
display: flex;
align-items: center;
gap: 8px;
flex: 1;
}
.status-indicator {
margin-left: 2px;
width: 8px;
height: 8px;
flex-shrink: 0;
transition: all 0.3s ease;
}
.status-indicator.visible {
background-color: #4caf50;
box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.3);
}
.status-indicator.hidden {
background-color: #666;
box-shadow: 0 0 0 2px rgba(102, 102, 102, 0.2);
}
.status-indicator.prefetching {
background-color: #ffeb3b;
box-shadow: 0 0 0 2px rgba(255, 235, 59, 0.4);
}
.status-indicator.inactive {
background-color: #999;
box-shadow: 0 0 0 2px rgba(153, 153, 153, 0.3);
}
.status-indicator.touch-device {
background-color: #ba68c8;
box-shadow: 0 0 0 2px rgba(186, 104, 200, 0.4);
}
.unregister-button {
all: unset;
display: flex;
align-items: center;
justify-content: center;
width: 14px;
height: 14px;
padding: 1px;
cursor: pointer;
color: #999;
}
.unregister-button:hover {
background-color: rgba(255, 107, 107, 0.1);
color: #ff6b6b;
}
.element-name {
flex-grow: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 11px;
font-weight: 500;
color: #e8e8e8;
}
.element-name.callback-active {
color: #fff;
font-weight: 600;
}
.element-name.callback-inactive {
color: #999;
font-weight: 500;
}
.reactivate-countdown {
font-size: 14px;
color: #ffa726;
font-weight: 500;
min-width: 0;
white-space: nowrap;
}
.reactivate-countdown:empty {
display: none;
}
:host(.not-visible) {
opacity: 0.5;
}
.element-wrapper.not-visible {
opacity: 0.5;
}
`],n([J({hasChanged:()=>!0})],v.prototype,"elementData",2),n([J()],v.prototype,"isActive",2),n([J()],v.prototype,"isExpanded",2),n([J()],v.prototype,"onToggle",2),n([Ct()],v.prototype,"currentDeviceStrategy",2),v=n([Et("single-element")],v);var m=class extends Tt{constructor(){super();this.hitCount={mouse:{hover:0,trajectory:0},scroll:{down:0,left:0,right:0,up:0},tab:{forwards:0,reverse:0},touch:0,viewport:0,total:0};this.elementListItems=new Map;this.noContentMessage="No Elements Registered To The Foresight Manager";this.runningCallbacks=new Set;this.expandedElementIds=new Set;this._abortController=null;this.handleSortChange=e=>{this.sortOrder=e};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 i=e.element.compareDocumentPosition(t.element);return i&Node.DOCUMENT_POSITION_FOLLOWING?-1:i&Node.DOCUMENT_POSITION_PRECEDING?1:0};this.sortOrder=l.instance.devtoolsSettings.sortElementList,this.sortDropdown=[{value:"visibility",label:"Visibility",title:"Sort by Visibility",icon:pe},{value:"documentOrder",label:"Document Order",title:"Sort by Document Order",icon:he},{value:"insertionOrder",label:"Insertion Order",title:"Sort by Insertion Order",icon:me}]}_generateHitsChipTitle(e){let t=[];t.push(`Total Callback Hits: ${e.total}`),t.push("");let i=e.mouse.trajectory+e.mouse.hover,a=e.scroll.up+e.scroll.down+e.scroll.left+e.scroll.right,s=e.tab.forwards+e.tab.reverse;t.push("Desktop Strategy"),i>0?t.push(` Mouse (${i}): ${e.mouse.trajectory} trajectory, ${e.mouse.hover} hover`):t.push(" Mouse: No hits"),a>0?t.push(` Scroll (${a}): Up ${e.scroll.up}, Down ${e.scroll.down}, Left ${e.scroll.left}, Right ${e.scroll.right}`):t.push(" Scroll: No hits"),s>0?t.push(` Tab (${s}): ${e.tab.forwards} forward, ${e.tab.reverse} reverse`):t.push(" Tab: No hits"),t.push("");let d=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"),d===0&&i+a+s===0&&(t.push(""),t.push("Interact with registered elements to see callback statistics")),t.join(`
`)}connectedCallback(){super.connectedCallback(),this._abortController=new AbortController;let{signal:e}=this._abortController;this.updateElementListFromManager(),$.instance.addEventListener("elementRegistered",t=>{this.elementListItems.set(t.elementData.element,t.elementData)},{signal:e}),$.instance.addEventListener("elementDataUpdated",t=>{this.elementListItems.get(t.elementData.element)&&(this.elementListItems.set(t.elementData.element,t.elementData),this.requestUpdate())},{signal:e}),$.instance.addEventListener("elementReactivated",t=>{this.elementListItems.get(t.elementData.element)&&(this.elementListItems.set(t.elementData.element,t.elementData),this.requestUpdate())},{signal:e}),$.instance.addEventListener("elementUnregistered",t=>{this.elementListItems.delete(t.elementData.element),this.elementListItems.size||(this.noContentMessage="No Elements Registered To The Foresight Manager"),this.runningCallbacks.delete(t.elementData.element),this.requestUpdate()},{signal:e}),$.instance.addEventListener("callbackInvoked",t=>{this.elementListItems.get(t.elementData.element)&&this.elementListItems.set(t.elementData.element,t.elementData),this.runningCallbacks.add(t.elementData.element),this.requestUpdate()},{signal:e}),$.instance.addEventListener("callbackCompleted",t=>{this.elementListItems.get(t.elementData.element)&&this.elementListItems.set(t.elementData.element,t.elementData),this.handleCallbackCompleted(t.hitType),this.runningCallbacks.delete(t.elementData.element),this.requestUpdate()},{signal:e})}disconnectedCallback(){super.disconnectedCallback(),this._abortController?.abort(),this._abortController=null}updateElementListFromManager(){this.elementListItems=new Map($.instance.registeredElements)}handleCallbackCompleted(e){switch(e.kind){case"mouse":this.hitCount.mouse[e.subType]++;break;case"tab":this.hitCount.tab[e.subType]++;break;case"scroll":this.hitCount.scroll[e.subType]++;break;case"touch":this.hitCount.touch++;break;case"viewport":this.hitCount.viewport++;break;default:}this.hitCount.total++,this.requestUpdate()}getSortedElements(){let e=Array.from(this.elementListItems.values());switch(this.sortOrder){case"insertionOrder":return e;case"documentOrder":return e.sort(this.sortByDocumentPosition);case"visibility":return e.sort((t,i)=>t.isIntersectingWithViewport!==i.isIntersectingWithViewport?t.isIntersectingWithViewport?-1:1:this.sortByDocumentPosition(t,i));default:return this.sortOrder,e}}getActiveElements(){return this.getSortedElements().filter(e=>e.callbackInfo.isCallbackActive)}getInactiveElements(){return this.getSortedElements().filter(e=>!e.callbackInfo.isCallbackActive)}render(){return B`
<tab-header>
<div slot="chips" class="chips-container">
<chip-element title="${this._generateHitsChipTitle(this.hitCount)}">
${this.hitCount.total} hits
</chip-element>
</div>
<div slot="actions">
<single-select-dropdown
.dropdownOptions="${this.sortDropdown}"
.selectedOptionValue="${this.sortOrder}"
.onSelectionChange="${this.handleSortChange}"
></single-select-dropdown>
</div>
</tab-header>
<tab-content
.noContentMessage=${this.noContentMessage}
.hasContent=${!!this.elementListItems.size}
>
${this.getActiveElements().length>0?B`
<div class="element-section">
<h3 class="section-header active">
Active Elements (${this.getActiveElements().length})
</h3>
${Me(this.getActiveElements(),e=>B`
<single-element
.elementData=${e}
.isActive=${this.runningCallbacks.has(e.element)}
.isExpanded=${this.expandedElementIds.has(e.id)}
.onToggle=${this.handleElementToggle}
>
</single-element>
`)}
</div>
`:""}
${this.getInactiveElements().length>0?B`
<div class="element-section">
<h3 class="section-header inactive">
Inactive Elements (${this.getInactiveElements().length})
</h3>
${Me(this.getInactiveElements(),e=>B`
<single-element
.elementData=${e}
.isActive=${this.runningCallbacks.has(e.element)}
.isExpanded=${this.expandedElementIds.has(e.id)}
.onToggle=${this.handleElementToggle}
>
</single-element>
`)}
</div>
`:""}
</tab-content>
`}};m.styles=St`
:host {
display: flex;
flex-direction: column;
height: 100%;
}
.chips-container {
display: flex;
gap: 8px;
}
.element-section {
margin-bottom: 16px;
}
.element-section:last-child {
margin-bottom: 0;
}
.section-header {
margin: 4px 0 4px 0;
font-size: 12px;
font-weight: 600;
}
.section-header.active {
color: #e8e8e8;
}
.section-header.inactive {
color: #999;
}
`,n([L()],m.prototype,"hitCount",2),n([L()],m.prototype,"sortDropdown",2),n([L()],m.prototype,"sortOrder",2),n([L()],m.prototype,"elementListItems",2),n([L()],m.prototype,"noContentMessage",2),n([L()],m.prototype,"runningCallbacks",2),n([L()],m.prototype,"expandedElementIds",2),m=n([Dt("element-tab")],m);import{css as Mt,html as Le,LitElement as Lt}from"lit";import{customElement as $t,property as _t}from"lit/decorators.js";var A=class extends Lt{constructor(){super(...arguments);this.activeTab="settings";this.tabs=["settings","elements","logs"]}_handleTabClick(e){this.dispatchEvent(new CustomEvent("tab-change",{detail:{tab:e},bubbles:!0,composed:!0}))}render(){return Le`
<div class="tab-selector-wrapper">
${this.tabs.map(e=>Le`
<button
class="tab-button ${this.activeTab===e?"active":""}"
@click="${()=>this._handleTabClick(e)}"
data-tab="${e}"
>
${e.charAt(0).toUpperCase()+e.slice(1)}
</button>
`)}
</div>
`}};A.styles=Mt`
.tab-selector-wrapper {
border-bottom: 2px solid #444;
margin-top: 12px;
display: flex;
justify-content: space-evenly;
width: 100%;
}
.tab-button {
background: none;
border: none;
color: #9e9e9e;
flex: 1;
padding: 8px;
cursor: pointer;
border-bottom: 2px solid transparent;
transition: all 0.2s ease;
font-size: 13px;
font-weight: 500;
text-align: center;
}
.tab-button:hover {
color: #b0c4de;
background-color: rgba(176, 196, 222, 0.1);
}
.tab-button.active {
color: #b0c4de;
border-bottom-color: #b0c4de;
}
`,n([_t({type:String})],A.prototype,"activeTab",2),A=n([$t("tab-selector")],A);import{ForesightManager as G}from"js.foresight";import{LitElement as Vt,css as Rt,html as X}from"lit";import{customElement as Ft,property as zt,state as j}from"lit/decorators.js";import{map as Ht}from"lit/directives/map.js";function _e(o,r){let e={};o.eventListeners.forEach((i,a)=>{e[a]=i.length});let t=[];return o.registeredElements.forEach((i,a)=>{let{element:s,...d}=i;t.push({...d,elementInfo:`${a.id?`#${a.id}`:""}${a.className?`.${a.className.replace(/\s+/g,".")}`:""}`})}),{type:"managerDataPayload",warning:"this is a lot easier to view in the console",logId:r,globalCallbackHits:o.globalCallbackHits,localizedTimestamp:new Date().toLocaleTimeString(),eventListenerCount:e,managerSettings:o.globalSettings,registeredElements:t,summary:`${t.length} elements, ${Object.values(e).flat().length} listeners,
${o.globalCallbackHits.total} hits`}}function Ie(o,r){try{switch(o.type){case"elementRegistered":return{type:"elementRegistered",name:o.elementData.name,id:o.elementData.element.id||"",callbackInfo:o.elementData.callbackInfo,hitslop:o.elementData.elementBounds.hitSlop,localizedTimestamp:new Date(o.timestamp).toLocaleTimeString(),meta:o.elementData.meta,logId:r,summary:o.elementData.registerCount===1?o.elementData.name:`${o.elementData.name} - ${$e(o.elementData.registerCount)} time`};case"elementReactivated":return{type:"elementReactivated",name:o.elementData.name,id:o.elementData.element.id||"",callbackInfo:o.elementData.callbackInfo,localizedTimestamp:new Date(o.timestamp).toLocaleTimeString(),meta:o.elementData.meta,logId:r,summary:o.elementData.registerCount===1?o.elementData.name:`${o.elementData.name} - ${$e(o.elementData.registerCount)} time`};case"elementUnregistered":return{type:"elementUnregistered",name:o.elementData.name,id:o.elementData.element.id||"",meta:o.elementData.meta,callbackInfo:o.elementData.callbackInfo,wasLastRegisteredElement:o.wasLastRegisteredElement,localizedTimestamp:new Date(o.timestamp).toLocaleTimeString(),logId:r,summary:`${o.elementData.name} - ${o.unregisterReason}`};case"elementDataUpdated":return{type:"elementDataUpdated",name:o.elementData.name,updatedProps:o.updatedProps||[],callbackInfo:o.elementData.callbackInfo,isIntersecting:o.elementData.isIntersectingWithViewport,meta:o.elementData.meta,localizedTimestamp:new Date().toLocaleTimeString(),logId:r,summary:`${o.elementData.name} - ${o.updatedProps.toString()}`};case"callbackInvoked":return{type:"callbackInvoked",name:o.elementData.name,hitType:o.hitType,callbackInfo:o.elementData.callbackInfo,meta:o.elementData.meta,localizedTimestamp:new Date(o.timestamp).toLocaleTimeString(),logId:r,summary:`${o.elementData.name} - ${o.hitType.kind}`};case"callbackCompleted":{let e=It(o.elementData.callbackInfo.lastCallbackRuntime||0);return{type:"callbackCompleted",name:o.elementData.name,hitType:o.hitType,callbackInfo:o.elementData.callbackInfo,meta:o.elementData.meta,wasLastActiveElement:o.wasLastActiveElement,elapsed:e,localizedTimestamp:new Date(o.timestamp).toLocaleTimeString(),logId:r,status:o.elementData.callbackInfo.lastCallbackStatus,errorMessage:o.elementData.callbackInfo.lastCallbackErrorMessage,summary:`${o.elementData.name} - ${e}`}}case"mouseTrajectoryUpdate":return{type:"mouseTrajectoryUpdate",currentPoint:o.trajectoryPositions?.currentPoint,predictedPoint:o.trajectoryPositions?.predictedPoint,positionCount:o.trajectoryPositions?.positions?.length||0,mousePredictionEnabled:o.predictionEnabled,localizedTimestamp:new Date().toLocaleTimeString(),logId:r,summary:""};case"scrollTrajectoryUpdate":return{type:"scrollTrajectoryUpdate",currentPoint:o.currentPoint,predictedPoint:o.predictedPoint,scrollDirection:o.scrollDirection,localizedTimestamp:new Date().toLocaleTimeString(),logId:r,summary:o.scrollDirection};case"managerSettingsChanged":return{type:"managerSettingsChanged",globalSettings:o.managerData?.globalSettings||{},settingsChanged:o.updatedSettings,localizedTimestamp:new Date(o.timestamp).toLocaleTimeString(),logId:r,summary:o.updatedSettings.map(e=>e.setting).join(", ")};case"deviceStrategyChanged":return{type:"deviceStrategyChanged",oldStrategy:o.oldStrategy,newStrategy:o.newStrategy,localizedTimestamp:new Date(o.timestamp).toLocaleTimeString(),logId:r,summary:`${o.oldStrategy} \u2192 ${o.newStrategy}`};default:return{type:"serializationError",error:"Failed to serialize event data",errorMessage:JSON.stringify(o),localizedTimestamp:new Date().toLocaleTimeString(),logId:r,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:r,summary:""}}}function It(o){return`${(o/1e3).toFixed(4)} s`}function $e(o){let r=["th","st","nd","rd"],e=o%100;return o+(r[(e-20)%10]||r[e]||r[0])}import{html as Oe,css as Ot}from"lit";import{customElement as Pt,property as Pe}from"lit/decorators.js";var _=class extends M{constructor(){super(...arguments);this.selectedValues=[]}_handleOptionClick(e){let t=this.selectedValues.includes(e.value);t?this.selectedValues=this.selectedValues.filter(a=>a!==e.value):this.selectedValues=[...this.selectedValues,e.value];let i=!t;this.onSelectionChange?.(e.value,i)}_getTriggerIcon(){return h}_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 Oe`
<div class="dropdown-container">
<button
class="${e}"
title="${this._getTriggerTitle()}"
@click="${this._toggleDropdown}"
aria-haspopup="true"
aria-expanded="${this.isDropdownOpen}"
aria-controls="dropdown-menu"
aria-label="${this._getTriggerLabel()}"
>
${this._getTriggerIcon()}
<span class="selected-count">${this.selectedValues.length}</span>
<svg
class="arrow-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
<div class="${t}" id="dropdown-menu" role="menu">
${this.dropdownOptions.map(i=>Oe`
<button
value="${i.value}"
title="${i.title}"
class="${this._isOptionSelected(i)?"active":""}"
@click="${()=>this._handleOptionClick(i)}"
role="menuitem"
>
${i.label}
</button>
`)}
</div>
</div>
`}};_.styles=[...M.styles,Ot`
.dropdown-menu button.active::after {
content: "✓";
position: absolute;
right: 8px;
top: 50%;
transform: translateY(-50%);
color: #b0c4de;
font-weight: bold;
}
.selected-count {
font-size: 10px;
color: #b0c4de;
margin-left: 2px;
}
`],n([Pe({type:Array})],_.prototype,"selectedValues",2),n([Pe()],_.prototype,"onSelectionChange",2),_=n([Pt("multi-select-dropdown")],_);import{LitElement as Ut,html as Nt,css as At}from"lit";import{customElement as jt,property as ie}from"lit/decorators.js";var C=class extends Ut{constructor(e){super();this.isExpanded=!1;this.log=e}updated(e){if(e.has("log")&&this.log){let t=this.log,i=t.type==="callbackCompleted"&&"status"in t&&t.status==="error",a=i?"#f44336":this.getLogTypeColor(t.type),s=i?"rgba(244, 67, 54, 0.1)":"transparent";this.style.setProperty("--log-color",a),this.style.setProperty("--log-background-color",s)}}serializeLogDataWithoutSummary(e){let{summary:t,...i}=e;return JSON.stringify(i,null,2)}getLogTypeColor(e){return{elementRegistered:"#2196f3",elementReactivated:"#ff9800",callbackInvoked:"#00bcd4",callbackCompleted:"#4caf50",elementDataUpdated:"#ffc107",elementUnregistered:"#ff9800",managerSettingsChanged:"#f44336",mouseTrajectoryUpdate:"#78909c",scrollTrajectoryUpdate:"#607d8b",deviceStrategyChanged:"#9c27b0"}[e]||"#555"}getEventDisplayName(e){return{elementRegistered:"Registered",elementReactivated:"Reactivated",el