This commit is contained in:
Timothy Jaeryang Baek 2026-10-16 14:55:40 +04:00
parent 362b01d0b2
commit d12da61e5a
3 changed files with 47 additions and 7 deletions

View file

@ -39,6 +39,7 @@
let hoveredId: string | null = null;
let pinned = false;
let touchInteraction = false;
let overHighlight = false;
let popoverX = 0;
let popoverY = 0;
let closeTimer: ReturnType<typeof setTimeout>;
@ -99,10 +100,38 @@
if (!pinned) closeTimer = setTimeout(() => (hoveredId = null), 100);
};
const reveal = (event: MouseEvent | FocusEvent, pin = false) => {
const element = (event.target as HTMLElement).closest<HTMLElement>(
overHighlight = false;
if (event instanceof MouseEvent && (event.buttons || window.getSelection()?.type === 'Range')) {
if (!pinned) {
keepOpen();
hoveredId = null;
}
return;
}
let element = (event.target as HTMLElement).closest<HTMLElement>(
'[data-file-comment-id],[data-cell]'
);
if (!element) return;
// Highlights are pointer-transparent so dragging selects the document text.
if (!element && event instanceof MouseEvent) {
const page = (event.target as HTMLElement).closest('.pdf-page-wrapper');
element =
Array.from((page ?? root).querySelectorAll<HTMLElement>('[data-comment-highlight]')).find(
(highlight) => {
const rect = highlight.getBoundingClientRect();
return (
event.clientX >= rect.left &&
event.clientX <= rect.right &&
event.clientY >= rect.top &&
event.clientY <= rect.bottom
);
}
) ?? null;
}
if (!element) {
closeLater();
return;
}
overHighlight = event instanceof MouseEvent && !!element.dataset.commentHighlight;
const id =
element.dataset.fileCommentId ??
comments.find(
@ -236,12 +265,20 @@
<div
bind:this={root}
class="relative flex-1 h-full min-h-0 min-w-0 overflow-hidden"
class:comment-hover={overHighlight}
on:mouseover={reveal}
on:mousemove={reveal}
on:focusin={reveal}
on:mouseout={closeLater}
on:focusout={closeLater}
on:pointerdown={(e) => (touchInteraction = e.pointerType === 'touch')}
on:pointerdown={(e) => {
touchInteraction = e.pointerType === 'touch';
if (!(e.target as HTMLElement).closest('[data-file-comment-id],[data-cell]')) {
keepOpen();
pinned = false;
hoveredId = null;
}
}}
on:click={(e) => reveal(e, touchInteraction || e.detail === 0)}
>
{#if loading}<div class="flex h-full items-center justify-center"><Spinner /></div>
@ -347,6 +384,10 @@
{/if}
<style>
.comment-hover,
.comment-hover :global(:hover) {
cursor: help;
}
.comment-message {
overflow-wrap: anywhere;
}

View file

@ -133,7 +133,7 @@
const target = document.createElement('button'); target.type = 'button';
target.dataset.fileCommentId = comment.id; target.dataset.commentHighlight = comment.id;
target.setAttribute('aria-label', `${$i18n.t('Comment')}: ${comment.author || $i18n.t('Unknown author')}`);
Object.assign(target.style, {position:'absolute',left:`${Math.min(r[0],r[2])}px`,top:`${Math.min(r[1],r[3])}px`,width:`${Math.abs(r[2]-r[0])}px`,height:`${Math.abs(r[3]-r[1])}px`,pointerEvents:'auto',background:'transparent',border:'0',borderBottom:'1px solid rgba(180,130,30,.6)',cursor:'help'});
Object.assign(target.style, {position:'absolute',left:`${Math.min(r[0],r[2])}px`,top:`${Math.min(r[1],r[3])}px`,width:`${Math.abs(r[2]-r[0])}px`,height:`${Math.abs(r[3]-r[1])}px`,pointerEvents:'none',background:'transparent',border:'0',borderBottom:'1px solid rgba(180,130,30,.6)',cursor:'help'});
layer.appendChild(target);
}
if (regions.length) continue;

View file

@ -22,7 +22,8 @@ export function highlightRange(
top: `${(rect.top - bounds.top) / scale}px`,
width: `${rect.width / scale}px`,
height: `${rect.height / scale}px`,
pointerEvents: 'auto',
// Let the text underneath receive native selection gestures.
pointerEvents: 'none',
padding: '0',
margin: '0',
border: '0',
@ -31,8 +32,6 @@ export function highlightRange(
background: 'rgba(250,204,21,.20)',
cursor: 'help'
});
target.onmouseenter = () => (target.style.background = 'rgba(250,204,21,.36)');
target.onmouseleave = () => (target.style.background = 'rgba(250,204,21,.20)');
layer.appendChild(target);
}
return rects.length > 0;