fix(hover-card): maiden name false positive, placeholder on non-empty editor, card persistence
- PersonHoverCard: alias is compared against both `lastName` and `displayName` before showing as maiden name — prevents false positive when alias is stored as the full current name (e.g. "Maria Schmidt" ≠ "Schmidt" but name unchanged) - PersonMentionEditor: data-placeholder was set statically so the CSS ::before rule showed the placeholder on any blur even with content; now a $effect toggles the attribute based on editor.isEmpty - TranscriptionReadView: hovering onto the card itself cancels the 150ms close timer so the card stays open while reading it; leaving the card closes it immediately — onmouseenter/onmouseleave wired through PersonHoverCard props - hoverCardPosition: removed scrollX/scrollY offset since the card is now position:fixed (scroll is already baked into getBoundingClientRect coords) - MentionDropdown: raised z-index from z-20 to z-50 to render above the hover card - vite.config.ts: pre-bundle Tiptap packages to avoid HMR waterfall on first load Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -93,13 +93,28 @@ function getOrFetchHoverData(personId: string): Promise<HoverData | null> {
|
||||
function currentViewport() {
|
||||
return {
|
||||
viewportWidth: window.innerWidth,
|
||||
viewportHeight: window.innerHeight,
|
||||
scrollX: window.scrollX,
|
||||
scrollY: window.scrollY
|
||||
viewportHeight: window.innerHeight
|
||||
};
|
||||
}
|
||||
|
||||
let closeTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
function scheduleCardClose() {
|
||||
closeTimer = setTimeout(() => {
|
||||
activeCard = null;
|
||||
closeTimer = null;
|
||||
}, 150);
|
||||
}
|
||||
|
||||
function cancelCardClose() {
|
||||
if (closeTimer !== null) {
|
||||
clearTimeout(closeTimer);
|
||||
closeTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
async function handleMentionEnter(event: Event) {
|
||||
cancelCardClose();
|
||||
const link = event.target as HTMLAnchorElement;
|
||||
const personId = link.dataset.personId;
|
||||
if (!personId) return;
|
||||
@@ -140,7 +155,11 @@ async function handleMentionEnter(event: Event) {
|
||||
function handleMentionLeave(event: Event) {
|
||||
const link = event.target as HTMLAnchorElement;
|
||||
link.removeAttribute('aria-describedby');
|
||||
activeCard = null;
|
||||
if (event.type === 'mouseleave') {
|
||||
scheduleCardClose();
|
||||
} else {
|
||||
activeCard = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,6 +250,8 @@ function attachMentionHandlers(node: HTMLElement) {
|
||||
cardId={activeCard.cardId}
|
||||
position={activeCard.position}
|
||||
state={activeCard.state}
|
||||
onmouseenter={cancelCardClose}
|
||||
onmouseleave={() => { activeCard = null; }}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user