a tool for shared writing and social publishing

added scrollintoviewifneeded to the pages if one is focused off screen, also added to focus block so that the block comes into view if you arrow up or down to focus it

+25 -5
+1
components/Blocks/Block.tsx
··· 87 87 return ( 88 88 <div 89 89 {...(!props.preview ? { ...mouseHandlers, ...handlers } : {})} 90 + id={`block/${props.entityID}/container`} 90 91 className={` 91 92 blockWrapper relative 92 93 flex flex-row gap-2
+7 -4
components/Pages/index.tsx
··· 34 34 import { CardThemeProvider } from "../ThemeManager/ThemeProvider"; 35 35 import { PageShareMenu } from "./PageShareMenu"; 36 36 import { Watermark } from "components/Watermark"; 37 + import { scrollIntoViewIfNeeded } from "src/utils/scrollIntoViewIfNeeded"; 37 38 38 39 export function Pages(props: { rootPage: string }) { 39 40 let rootPage = useEntity(props.rootPage, "root/page")[0]; ··· 366 367 367 368 setTimeout(async () => { 368 369 //scroll to page 369 - document.getElementById(elementId.page(pageID).container)?.scrollIntoView({ 370 - behavior: "smooth", 371 - inline: "nearest", 372 - }); 370 + 371 + scrollIntoViewIfNeeded( 372 + document.getElementById(elementId.page(pageID).container), 373 + false, 374 + "smooth", 375 + ); 373 376 374 377 // if we asked that the function focus the first block, focus the first block 375 378 if (focusFirstBlock === "focusFirstBlock") {
+11
src/utils/focusBlock.ts
··· 1 1 import { TextSelection } from "prosemirror-state"; 2 2 import { useUIState } from "src/useUIState"; 3 3 import { Block } from "components/Blocks/Block"; 4 + import { elementId } from "src/utils/elementId"; 4 5 5 6 import { setEditorState, useEditorStates } from "src/state/useEditorState"; 7 + import { scrollIntoViewIfNeeded } from "./scrollIntoViewIfNeeded"; 6 8 7 9 export function focusBlock( 8 10 block: Pick<Block, "type" | "value" | "parent">, 9 11 position: Position, 10 12 ) { 13 + // focus the block 11 14 useUIState.getState().setSelectedBlock(block); 12 15 useUIState.getState().setFocusedBlock({ 13 16 entityType: "block", 14 17 entityID: block.value, 15 18 parent: block.parent, 16 19 }); 20 + scrollIntoViewIfNeeded( 21 + document.getElementById(elementId.block(block.value).container), 22 + false, 23 + ); 24 + 25 + // if its not a text block, that's all we need to do 17 26 if (block.type !== "text" && block.type !== "heading") { 18 27 return true; 19 28 } 29 + // if its a text block, and not an empty block that is last on the page, 30 + // focus the editor using the mouse position if needed 20 31 let nextBlockID = block.value; 21 32 let nextBlock = useEditorStates.getState().editorStates[nextBlockID]; 22 33 if (!nextBlock || !nextBlock.view) return;
+6 -1
src/utils/scrollIntoViewIfNeeded.ts
··· 1 1 export function scrollIntoViewIfNeeded( 2 2 el: Element | null, 3 3 centerIfNeeded: boolean = true, 4 + behavior?: ScrollBehavior, 4 5 ) { 5 - if (!el) return; 6 + if (!el) { 7 + return; 8 + } 6 9 let observer = new IntersectionObserver(function ([entry]) { 7 10 const ratio = entry.intersectionRatio; 11 + 8 12 if (ratio < 1) { 9 13 let place = 10 14 ratio <= 0 && centerIfNeeded ··· 13 17 el.scrollIntoView({ 14 18 block: place, 15 19 inline: place, 20 + behavior: behavior ? behavior : "auto", 16 21 }); 17 22 } 18 23 observer.disconnect();