Something went wrong. Try again.
Something went wrong. Try again.
3.5 kB · 150 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151import { useWindowSize } from "@vueuse/core"import { useRouteQuery } from "@vueuse/router"import { nextTick, readonly } from "vue"
import { getBookmarkWidthPx } from "@/constants/bookmark-width"import { getNoteWidth } from "@/constants/note-width"import { useOverlay } from "@/hooks/useOverlay.hook"
export const useRouteQueryStackedNotes = () => { const stackedNotes = useRouteQuery("stackedNotes", undefined, { transform: (value: string | string[] | undefined) => { if (!value) { return [] }
return Array.isArray(value) ? value : [value] } }) const { height } = useWindowSize()
const { scrollToNote, isMobile } = useOverlay(false)
const scrollToHashInNote = ( cleanSha: string, hash: string, smooth: boolean, attempts = 30 ) => { if (attempts <= 0) { return }
const heading = document.querySelector( `.note-${cleanSha} #${CSS.escape(hash)}` ) if (heading) { heading.scrollIntoView({ block: "start", inline: "nearest", behavior: smooth ? "smooth" : "auto" }) return }
requestAnimationFrame(() => { scrollToHashInNote(cleanSha, hash, smooth, attempts - 1) }) }
const scrollToNoteElement = ( cleanNoteId: string, index: number, attempts = 30 ) => { const element = document.querySelector( `.note-${cleanNoteId}` ) as HTMLElement | null
if (element) { scrollToNote((index + 1) * element.clientHeight) return }
if (attempts <= 0) { scrollToNote((index + 1) * height.value) return }
requestAnimationFrame(() => { scrollToNoteElement(cleanNoteId, index, attempts - 1) }) }
type ScrollToFocusedNoteOptions = { noteId?: string | null notes?: string[] hash?: string smoothHash?: boolean }
const scrollToFocusedNote = ({ noteId = null, notes = stackedNotes.value, hash, smoothHash = false }: ScrollToFocusedNoteOptions = {}) => { nextTick(() => { const index = noteId ? notes.findIndex((nid) => nid === noteId) : 0
if (isMobile.value) { if (noteId) { scrollToNoteElement(noteId.replaceAll(":", "-"), index) } else { scrollToNote(0) } } else { if (noteId) { const left = (index + 1) * (getNoteWidth() - getBookmarkWidthPx()) scrollToNote(left) } else { scrollToNote(0) } }
if (hash && noteId) { scrollToHashInNote(noteId.replaceAll(":", "-"), hash, smoothHash) } }) }
const addStackedNote = ( currentSha: string, sha: string, selector?: string, hash?: string ) => { if (stackedNotes.value.includes(sha)) { scrollToFocusedNote({ noteId: selector ?? sha, hash, smoothHash: true }) return }
if (!currentSha) { stackedNotes.value = [sha] } else { const [splittedStackedNotes] = stackedNotes.value .join(";") .split(currentSha)
const newStackedNotes = [ ...splittedStackedNotes.replaceAll(";;", ";").split(";"), currentSha, sha ].filter((sha) => !!sha)
stackedNotes.value = newStackedNotes }
scrollToFocusedNote({ noteId: selector ?? sha, hash }) }
return { stackedNotes: readonly(stackedNotes), addStackedNote, scrollToFocusedNote }}