diff --git a/.gitignore b/.gitignore
index 4a7f73a..0ece5a5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,4 @@ logs
.env
.env.*
!.env.example
+.bruno
diff --git a/app/components/PublicationDetail.vue b/app/components/PublicationDetail.vue
index eb5382e..50d724a 100644
--- a/app/components/PublicationDetail.vue
+++ b/app/components/PublicationDetail.vue
@@ -635,6 +635,12 @@ onMounted(async () => {
if (props.paragraphs.length) {
await applyTypesenseHighlights()
}
+ document.addEventListener('selectionchange', onSelectionChange)
+})
+
+onUnmounted(() => {
+ document.removeEventListener('selectionchange', onSelectionChange)
+ if (selectionTimer) clearTimeout(selectionTimer)
})
// ---- Utilerías de búsqueda local --------------------------------------------
@@ -755,16 +761,34 @@ function highlightTextNodes(root: HTMLElement, terms: string[]): number {
return matches.length
}
const isPopOverOpen = ref(false)
+const selectionTooltip = ref<{ x: number; y: number } | null>(null)
+let selectionTimer: ReturnType | null = null
function handleSelection(event: MouseEvent) {
const selection = window.getSelection()
- if (selection && selection.toString().length > 3) {
- isPopOverOpen.value = true
+ if (selection && selection.toString().trim().length > 3) {
+ if (selectionTimer) clearTimeout(selectionTimer)
+ selectionTimer = setTimeout(() => {
+ const x = Math.min(Math.max(event.clientX, 96), window.innerWidth - 96)
+ selectionTooltip.value = { x, y: event.clientY }
+ isPopOverOpen.value = true
+ }, 320)
} else {
- isPopOverOpen.value = false
+ clearSelectionTooltip()
}
}
+function clearSelectionTooltip() {
+ if (selectionTimer) { clearTimeout(selectionTimer); selectionTimer = null }
+ selectionTooltip.value = null
+ isPopOverOpen.value = false
+}
+
+function onSelectionChange() {
+ const sel = window.getSelection()
+ if (!sel || sel.toString().trim().length === 0) clearSelectionTooltip()
+}
+
const links = computed(() => {
return [
{
@@ -981,56 +1005,55 @@ const items = computed(() => {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ item.content }}
-
-
-
-
+
+
+
+
+
@@ -1042,4 +1065,21 @@ const items = computed(() => {
.paragraph-html :deep(p:last-child) {
margin-bottom: 0;
}
+
+/* Tooltip de selección de texto */
+.selection-tooltip {
+ transform: translateX(-50%) translateY(-100%);
+}
+
+.tooltip-pop-enter-active {
+ transition: transform 0.18s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.12s ease;
+}
+.tooltip-pop-leave-active {
+ transition: transform 0.12s ease-in, opacity 0.1s ease;
+}
+.tooltip-pop-enter-from,
+.tooltip-pop-leave-to {
+ transform: translateX(-50%) translateY(calc(-100% + 8px));
+ opacity: 0;
+}