a tool for shared writing and social publishing
0
fork

Configure Feed

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

handle card blocks

+41 -24
+8 -19
components/Blocks.tsx
··· 19 19 import { ImageBlock } from "./ImageBlock"; 20 20 import { useUIState } from "src/useUIState"; 21 21 import { focusCard } from "./Cards"; 22 + import { CardBlock } from "./CardBlock"; 22 23 23 24 export type Block = { 24 25 position: string; ··· 210 211 nextBlock: Block | null; 211 212 previousBlock: Block | null; 212 213 nextPosition: string | null; 213 - }; 214 + } & Block; 214 215 215 - function Block(props: Block & BlockProps) { 216 + function Block(props: BlockProps) { 216 217 let selected = useUIState( 217 218 (s) => 218 219 (props.type !== "text" || s.selectedBlock.length > 1) && ··· 305 306 id={elementId.block(props.entityID).container} 306 307 > 307 308 {props.type === "card" ? ( 308 - <div 309 - className={`border w-full rounded-[4px]`} 310 - onClick={() => { 311 - useUIState.getState().openCard(props.parent, props.entityID); 312 - focusCard(props.entityID); 313 - }} 314 - > 315 - <div 316 - className={`p-2 rounded-[3px] border ${!selected ? "border-transparent" : ""}`} 317 - > 318 - a card{" "} 319 - </div> 320 - </div> 309 + <CardBlock {...props} /> 321 310 ) : props.type === "text" ? ( 322 311 <TextBlock {...props} /> 323 312 ) : props.type === "image" ? ( ··· 332 321 left: number | "end" | "start", 333 322 top: "top" | "bottom", 334 323 ) { 335 - if (block.type === "image") { 336 - useUIState.getState().setSelectedBlock(block.value); 337 - return true; 338 - } 339 324 document 340 325 .getElementById(elementId.block(block.value).container) 341 326 ?.scrollIntoView({ behavior: "smooth", block: "nearest" }); 327 + if (block.type === "image" || block.type === "card") { 328 + useUIState.getState().setSelectedBlock(block.value); 329 + return true; 330 + } 342 331 let nextBlockID = block.value; 343 332 let nextBlock = useEditorStates.getState().editorStates[nextBlockID]; 344 333 if (!nextBlock || !nextBlock.view) return;
+31
components/CardBlock.tsx
··· 1 + import { BlockProps } from "components/Blocks"; 2 + import { focusCard } from "components/Cards"; 3 + import { useEntity } from "src/replicache"; 4 + import { useUIState } from "src/useUIState"; 5 + import { RenderedTextBlock } from "./TextBlock"; 6 + export function CardBlock(props: BlockProps) { 7 + let selected = useUIState( 8 + (s) => 9 + (props.type !== "text" || s.selectedBlock.length > 1) && 10 + s.selectedBlock.includes(props.entityID), 11 + ); 12 + let blocks = useEntity(props.entityID, "card/block"); 13 + let firstBlock = blocks.sort((a, b) => { 14 + return a.data.position > b.data.position ? 1 : -1; 15 + })[0]; 16 + return ( 17 + <div 18 + className={`border w-full rounded-[4px]`} 19 + onClick={() => { 20 + useUIState.getState().openCard(props.parent, props.entityID); 21 + focusCard(props.entityID); 22 + }} 23 + > 24 + <div 25 + className={`p-2 rounded-[3px] border ${!selected ? "border-transparent" : ""}`} 26 + > 27 + <RenderedTextBlock entityID={firstBlock?.data.value} /> 28 + </div> 29 + </div> 30 + ); 31 + }
+2 -5
components/TextBlock/index.tsx
··· 69 69 ); 70 70 } 71 71 72 - function RenderedTextBlock(props: { entityID: string }) { 73 - let { initialFacts } = useReplicache(); 74 - let initialFact = initialFacts.find( 75 - (f) => f.entity === props.entityID && f.attribute === "block/text", 76 - ) as Fact<"block/text"> | undefined; 72 + export function RenderedTextBlock(props: { entityID: string }) { 73 + let initialFact = useEntity(props.entityID, "block/text"); 77 74 if (!initialFact) return <pre className="min-h-6" />; 78 75 let doc = new Y.Doc(); 79 76 const update = base64.toByteArray(initialFact.data.value);