Skip to content

Commit

Permalink
fix: add blinking while stationary
Browse files Browse the repository at this point in the history
  • Loading branch information
Palanikannan1437 committed Nov 28, 2024
1 parent d798833 commit d34af8a
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 4 deletions.
36 changes: 32 additions & 4 deletions packages/editor/src/core/extensions/smooth-cursor/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import { type Selection, Plugin, PluginKey, TextSelection } from "@tiptap/pm/sta
import { type EditorView, Decoration, DecorationSet } from "@tiptap/pm/view";

export const PROSEMIRROR_SMOOTH_CURSOR_CLASS = "prosemirror-smooth-cursor";
const BLINK_DELAY = 750; // Time in ms before cursor starts blinking

export function smoothCursorPlugin(): Plugin {
let smoothCursor: HTMLElement | null = typeof document === "undefined" ? null : document.createElement("div");
let rafId: number | undefined;
let blinkTimeoutId: number | undefined;
let isEditorFocused = false;
let lastCursorPosition = { x: 0, y: 0 };

function updateCursor(view?: EditorView, cursor?: HTMLElement) {
if (!view || !view.dom || view.isDestroyed || !cursor) return;
Expand All @@ -30,13 +33,31 @@ export function smoothCursorPlugin(): Plugin {

const className = PROSEMIRROR_SMOOTH_CURSOR_CLASS;

cursor.className = className;
cursor.style.height = `${cursorRect.bottom - cursorRect.top}px`;

// Calculate the exact position
const x = cursorRect.left - editorRect.left;
const y = cursorRect.top - editorRect.top;

// Check if cursor position has changed
if (x !== lastCursorPosition.x || y !== lastCursorPosition.y) {
lastCursorPosition = { x, y };
cursor.classList.remove(`${className}--blinking`);

// Clear existing timeout
if (blinkTimeoutId) {
window.clearTimeout(blinkTimeoutId);
}

// Set new timeout for blinking
blinkTimeoutId = window.setTimeout(() => {
if (cursor && isEditorFocused) {
cursor.classList.add(`${className}--blinking`);
}
}, BLINK_DELAY);
}

cursor.className = className;
cursor.style.height = `${cursorRect.bottom - cursorRect.top}px`;

rafId = requestAnimationFrame(() => {
cursor.style.transform = `translate3d(${x}px, ${y}px, 0)`;
});
Expand All @@ -63,6 +84,10 @@ export function smoothCursorPlugin(): Plugin {

const handleBlur = () => {
isEditorFocused = false;
if (blinkTimeoutId) {
window.clearTimeout(blinkTimeoutId);
}
cursor.classList.remove(`${PROSEMIRROR_SMOOTH_CURSOR_CLASS}--blinking`);
update();
};

Expand All @@ -83,10 +108,13 @@ export function smoothCursorPlugin(): Plugin {
view.dom.removeEventListener("focus", handleFocus);
view.dom.removeEventListener("blur", handleBlur);
observer?.unobserve(view.dom);
// Clean up any pending animation frame
if (rafId !== undefined) {
cancelAnimationFrame(rafId);
}
if (blinkTimeoutId) {
window.clearTimeout(blinkTimeoutId);
}
style.remove();
},
};
},
Expand Down
14 changes: 14 additions & 0 deletions packages/editor/src/styles/editor.css
Original file line number Diff line number Diff line change
Expand Up @@ -494,3 +494,17 @@ p + p {
will-change: transform;
opacity: 0.8;
}

.prosemirror-smooth-cursor--blinking {

Check notice on line 498 in packages/editor/src/styles/editor.css

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

packages/editor/src/styles/editor.css#L498

(selector) => `Expected class selector "${selector}" to be kebab-case`
animation: blink 1s step-end infinite;
}

@keyframes blink {
from,

Check notice on line 503 in packages/editor/src/styles/editor.css

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

packages/editor/src/styles/editor.css#L503

Expected "from" to be "0%" (keyframe-selector-notation)
to {
opacity: 1;
}
50% {
opacity: 0;
}
}

0 comments on commit d34af8a

Please sign in to comment.