a tool for shared writing and social publishing
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

add ctrl-j/k for cursor movement

+79 -41
+63 -38
components/Blocks/TextBlock/keymap.ts
··· 117 117 } 118 118 return false; 119 119 }, 120 - ArrowUp: (state, _tr, view) => { 121 - if (!view) return false; 122 - if (state.doc.textContent.startsWith("/")) return true; 123 - if (useUIState.getState().selectedBlocks.length > 1) return true; 124 - if (view.state.selection.from !== view.state.selection.to) return false; 125 - const viewClientRect = view.dom.getBoundingClientRect(); 126 - const coords = view.coordsAtPos(view.state.selection.anchor); 127 - if (coords.top - viewClientRect.top < 12) { 128 - let block = propsRef.current.previousBlock; 129 - if (block) { 130 - view.dom.blur(); 131 - focusBlock(block, { left: coords.left, type: "bottom" }); 132 - return true; 133 - } 134 - return false; 135 - } 136 - return false; 137 - }, 138 - ArrowDown: (state, tr, view) => { 139 - if (!view) return true; 140 - if (state.doc.textContent.startsWith("/")) return true; 141 - if (useUIState.getState().selectedBlocks.length > 1) return true; 142 - if (view.state.selection.from !== view.state.selection.to) return false; 143 - const viewClientRect = view.dom.getBoundingClientRect(); 144 - const coords = view.coordsAtPos(view.state.selection.anchor); 145 - let isBottom = viewClientRect.bottom - coords.bottom < 12; 146 - if (isBottom) { 147 - let block = propsRef.current.nextBlock; 148 - if (block) { 149 - view.dom.blur(); 150 - focusBlock(block, { left: coords.left, type: "top" }); 151 - return true; 152 - } 153 - return false; 154 - } 155 - return false; 156 - }, 120 + "Ctrl-k": moveCursorUp(propsRef, repRef, true), 121 + ArrowUp: moveCursorUp(propsRef, repRef), 122 + "Ctrl-j": moveCursorDown(propsRef, repRef, true), 123 + ArrowDown: moveCursorDown(propsRef, repRef), 157 124 ArrowLeft: (state, tr, view) => { 158 125 if (state.selection.content().size > 0) return false; 159 126 if (state.selection.anchor > 1) return false; ··· 192 159 "Ctrl-Enter": CtrlEnter(propsRef, repRef), 193 160 "Meta-Enter": CtrlEnter(propsRef, repRef), 194 161 }) as { [key: string]: Command }; 162 + 163 + const moveCursorDown = 164 + ( 165 + propsRef: PropsRef, 166 + repRef: MutableRefObject<Replicache<ReplicacheMutators> | null>, 167 + jumpToNextBlock: boolean = false, 168 + ) => 169 + ( 170 + state: EditorState, 171 + dispatch?: (tr: Transaction) => void, 172 + view?: EditorView, 173 + ) => { 174 + if (!view) return true; 175 + if (state.doc.textContent.startsWith("/")) return true; 176 + if (useUIState.getState().selectedBlocks.length > 1) return true; 177 + if (view.state.selection.from !== view.state.selection.to) return false; 178 + const viewClientRect = view.dom.getBoundingClientRect(); 179 + const coords = view.coordsAtPos(view.state.selection.anchor); 180 + let isBottom = viewClientRect.bottom - coords.bottom < 12; 181 + if (isBottom || jumpToNextBlock) { 182 + let block = propsRef.current.nextBlock; 183 + if (block) { 184 + view.dom.blur(); 185 + focusBlock(block, { left: coords.left, type: "top" }); 186 + return true; 187 + } 188 + return false || jumpToNextBlock; 189 + } 190 + return false; 191 + }; 192 + const moveCursorUp = 193 + ( 194 + propsRef: PropsRef, 195 + repRef: MutableRefObject<Replicache<ReplicacheMutators> | null>, 196 + jumpToNextBlock: boolean = false, 197 + ) => 198 + ( 199 + state: EditorState, 200 + dispatch?: (tr: Transaction) => void, 201 + view?: EditorView, 202 + ) => { 203 + if (!view) return false; 204 + if (state.doc.textContent.startsWith("/")) return true; 205 + if (useUIState.getState().selectedBlocks.length > 1) return true; 206 + if (view.state.selection.from !== view.state.selection.to) return false; 207 + const viewClientRect = view.dom.getBoundingClientRect(); 208 + const coords = view.coordsAtPos(view.state.selection.anchor); 209 + if (coords.top - viewClientRect.top < 12 || jumpToNextBlock) { 210 + let block = propsRef.current.previousBlock; 211 + if (block) { 212 + view.dom.blur(); 213 + focusBlock(block, { left: coords.left, type: "bottom" }); 214 + return true; 215 + } 216 + return false || jumpToNextBlock; 217 + } 218 + return false; 219 + }; 195 220 196 221 const backspace = 197 222 ( ··· 399 424 }, 400 425 }); 401 426 if (propsRef.current.listData) 402 - repRef.current?.mutate.assertFact({ 427 + await repRef.current?.mutate.assertFact({ 403 428 entity: newEntityID, 404 429 attribute: "block/is-list", 405 430 data: { type: "boolean", value: true },
+16 -3
components/Blocks/useBlockKeyboardHandlers.ts
··· 40 40 if (e.defaultPrevented) return; 41 41 //if no permissions, do nothing 42 42 if (!entity_set.permissions.write) return; 43 - let command = { Tab, ArrowUp, ArrowDown, Backspace, Enter, Escape }[ 44 - e.key 45 - ]; 43 + let command = { 44 + Tab, 45 + ArrowUp, 46 + ArrowDown, 47 + Backspace, 48 + Enter, 49 + Escape, 50 + j, 51 + k, 52 + }[e.key]; 46 53 47 54 let el = e.target as HTMLElement; 48 55 if ( ··· 93 100 } 94 101 } 95 102 103 + function j(args: Args) { 104 + if (args.e.ctrlKey || args.e.metaKey) ArrowDown(args); 105 + } 96 106 function ArrowDown({ e, props }: Args) { 97 107 e.preventDefault(); 98 108 let nextBlock = props.nextBlock; ··· 104 114 if (!nextBlock) return; 105 115 } 106 116 117 + function k(args: Args) { 118 + if (args.e.ctrlKey || args.e.metaKey) ArrowUp(args); 119 + } 107 120 function ArrowUp({ e, props }: Args) { 108 121 e.preventDefault(); 109 122 let prevBlock = props.previousBlock;