mirror of
https://github.com/docmost/docmost.git
synced 2026-05-07 06:23:06 +08:00
d2629afff2
* feat: add heading extension with unique ID support and scroll functionality * Added unique id for heading * remove baseUrl heading storage * move heading to extensions package * WIP * support anchors in mentions * enhance scrolling functionality * nodeId function * fix nanoid import * Bring unique-id extension local * fixes * fix internal link scroll in public pages * add unique id server side * rename mention anchor to anchorId * capture first anchorId on paste --------- Co-authored-by: Romik <40670677+RomikMakavana@users.noreply.github.com>
59 lines
1.5 KiB
TypeScript
59 lines
1.5 KiB
TypeScript
import { Editor } from "@tiptap/react";
|
|
import { useCallback, useEffect, useState } from "react";
|
|
|
|
function waitForState(checkFn: () => boolean): Promise<void> {
|
|
return new Promise((resolve) => {
|
|
const interval = setInterval(() => {
|
|
if (checkFn()) {
|
|
clearInterval(interval);
|
|
resolve();
|
|
}
|
|
}, 800);
|
|
});
|
|
}
|
|
|
|
export const useEditorScroll = ({
|
|
canScroll,
|
|
initialScrollTo,
|
|
}: {
|
|
canScroll: () => boolean;
|
|
initialScrollTo?: string;
|
|
}) => {
|
|
const [scrollTo, setScrollTo] = useState<string>(initialScrollTo || "");
|
|
|
|
useEffect(() => {
|
|
if (!initialScrollTo) {
|
|
setScrollTo(window.location.hash ? window.location.hash.slice(1) : "");
|
|
}
|
|
}, [initialScrollTo]);
|
|
|
|
const handleScrollTo = useCallback(async (editor: Editor, _scrollTo: string | null = null, tryCount: number = 0) => {
|
|
await waitForState(() => canScroll());
|
|
return new Promise((resolve) => {
|
|
const MAX_TRY_COUNT = 10;
|
|
if (tryCount >= MAX_TRY_COUNT) {
|
|
resolve(false);
|
|
return;
|
|
}
|
|
|
|
const targetId = _scrollTo || scrollTo;
|
|
if (!targetId) {
|
|
resolve(false);
|
|
return;
|
|
}
|
|
|
|
const dom = editor.view.dom.querySelector(`[id="${targetId}"]`);
|
|
if (dom) {
|
|
dom.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
resolve(true);
|
|
} else {
|
|
setTimeout(async () => {
|
|
resolve(await handleScrollTo(editor, targetId, tryCount + 1));
|
|
}, 200);
|
|
}
|
|
});
|
|
}, [scrollTo, canScroll]);
|
|
|
|
return { scrollTo, handleScrollTo };
|
|
};
|