2026-01-18 19:42:58 +08:00
|
|
|
<template>
|
|
|
|
|
<div v-if="visible" class="ghost-text-overlay" :style="overlayStyle"
|
|
|
|
|
@click="acceptSuggestion"
|
|
|
|
|
>{{ suggestion }}
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
import { computed } from 'vue'
|
2026-01-25 13:29:11 +08:00
|
|
|
import { onMounted, onUnmounted, watch } from 'vue'
|
2026-01-18 19:42:58 +08:00
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
|
suggestion: { type: String, default: '' },
|
|
|
|
|
position: { type: Object, required: true },
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits(['accept', 'dismiss'])
|
|
|
|
|
|
2026-01-25 13:29:11 +08:00
|
|
|
onMounted(() => {
|
|
|
|
|
console.log('[GhostTextOverlay] Component mounted')
|
|
|
|
|
if (props.suggestion && props.position) {
|
|
|
|
|
console.log('[GhostTextOverlay] Suggestion visible:', props.suggestion.substring(0, 50))
|
|
|
|
|
console.log('[GhostTextOverlay] Position:', JSON.stringify(props.position))
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
console.log('[GhostTextOverlay] Component unmounted')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
watch([() => props.suggestion, () => props.position], ([newSuggestion, newPosition]) => {
|
|
|
|
|
console.log('[GhostTextOverlay] Props changed:', {
|
|
|
|
|
suggestionLength: newSuggestion?.length || 0,
|
|
|
|
|
hasPosition: !!newPosition,
|
|
|
|
|
positionKeys: newPosition ? Object.keys(newPosition) : []
|
|
|
|
|
})
|
|
|
|
|
}, { immediate: true })
|
|
|
|
|
|
2026-01-18 19:42:58 +08:00
|
|
|
const visible = computed(() => props.suggestion && props.position)
|
|
|
|
|
|
|
|
|
|
const overlayStyle = computed(() => ({
|
|
|
|
|
position: 'absolute',
|
|
|
|
|
left: `${props.position.left}px`,
|
|
|
|
|
top: `${props.position.top}px`,
|
|
|
|
|
fontSize: `${props.position.fontSize || 16}px`,
|
|
|
|
|
fontFamily: props.position.fontFamily || 'monospace',
|
|
|
|
|
color: '#999',
|
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
|
pointerEvents: 'auto',
|
|
|
|
|
cursor: 'text',
|
|
|
|
|
whiteSpace: 'pre-wrap',
|
|
|
|
|
zIndex: 1000,
|
|
|
|
|
}))
|
|
|
|
|
|
2026-01-25 13:29:11 +08:00
|
|
|
const acceptSuggestion = () => {
|
|
|
|
|
console.log('[GhostTextOverlay] acceptSuggestion called')
|
|
|
|
|
emit('accept')
|
|
|
|
|
}
|
2026-01-18 19:42:58 +08:00
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
.ghost-text-overlay {
|
|
|
|
|
opacity: 0.6;
|
|
|
|
|
user-select: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.ghost-text-overlay:hover {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
color: #666;
|
|
|
|
|
}
|
|
|
|
|
</style>
|