|
import { BridgeEvents, isBrowser } from '@vue-devtools/shared-utils' |
|
import type { BackendContext, DevtoolsBackend } from '@vue-devtools/app-backend-api' |
|
import type { ComponentInstance } from '@vue/devtools-api' |
|
import { highlight, unHighlight } from './highlighter' |
|
|
|
export default class ComponentPicker { |
|
ctx: BackendContext |
|
selectedInstance: ComponentInstance |
|
selectedBackend: DevtoolsBackend |
|
|
|
constructor(ctx: BackendContext) { |
|
this.ctx = ctx |
|
this.bindMethods() |
|
} |
|
|
|
|
|
|
|
|
|
startSelecting() { |
|
if (!isBrowser) { |
|
return |
|
} |
|
window.addEventListener('mouseover', this.elementMouseOver, true) |
|
window.addEventListener('click', this.elementClicked, true) |
|
window.addEventListener('mouseout', this.cancelEvent, true) |
|
window.addEventListener('mouseenter', this.cancelEvent, true) |
|
window.addEventListener('mouseleave', this.cancelEvent, true) |
|
window.addEventListener('mousedown', this.cancelEvent, true) |
|
window.addEventListener('mouseup', this.cancelEvent, true) |
|
} |
|
|
|
|
|
|
|
|
|
stopSelecting() { |
|
if (!isBrowser) { |
|
return |
|
} |
|
window.removeEventListener('mouseover', this.elementMouseOver, true) |
|
window.removeEventListener('click', this.elementClicked, true) |
|
window.removeEventListener('mouseout', this.cancelEvent, true) |
|
window.removeEventListener('mouseenter', this.cancelEvent, true) |
|
window.removeEventListener('mouseleave', this.cancelEvent, true) |
|
window.removeEventListener('mousedown', this.cancelEvent, true) |
|
window.removeEventListener('mouseup', this.cancelEvent, true) |
|
|
|
unHighlight() |
|
} |
|
|
|
|
|
|
|
|
|
async elementMouseOver(e: MouseEvent) { |
|
this.cancelEvent(e) |
|
|
|
const el = e.target |
|
if (el) { |
|
await this.selectElementComponent(el) |
|
} |
|
|
|
unHighlight() |
|
if (this.selectedInstance) { |
|
highlight(this.selectedInstance, this.selectedBackend, this.ctx) |
|
} |
|
} |
|
|
|
async selectElementComponent(el) { |
|
for (const backend of this.ctx.backends) { |
|
const instance = await backend.api.getElementComponent(el) |
|
if (instance) { |
|
this.selectedInstance = instance |
|
this.selectedBackend = backend |
|
return |
|
} |
|
} |
|
this.selectedInstance = null |
|
this.selectedBackend = null |
|
} |
|
|
|
|
|
|
|
|
|
async elementClicked(e: MouseEvent) { |
|
this.cancelEvent(e) |
|
|
|
if (this.selectedInstance && this.selectedBackend) { |
|
const parentInstances = await this.selectedBackend.api.walkComponentParents(this.selectedInstance) |
|
this.ctx.bridge.send(BridgeEvents.TO_FRONT_COMPONENT_PICK, { id: this.selectedInstance.__VUE_DEVTOOLS_UID__, parentIds: parentInstances.map(i => i.__VUE_DEVTOOLS_UID__) }) |
|
} |
|
else { |
|
this.ctx.bridge.send(BridgeEvents.TO_FRONT_COMPONENT_PICK_CANCELED, null) |
|
} |
|
|
|
this.stopSelecting() |
|
} |
|
|
|
|
|
|
|
|
|
cancelEvent(e: MouseEvent) { |
|
e.stopImmediatePropagation() |
|
e.preventDefault() |
|
} |
|
|
|
|
|
|
|
|
|
bindMethods() { |
|
this.startSelecting = this.startSelecting.bind(this) |
|
this.stopSelecting = this.stopSelecting.bind(this) |
|
this.elementMouseOver = this.elementMouseOver.bind(this) |
|
this.elementClicked = this.elementClicked.bind(this) |
|
} |
|
} |
|
|