From 7a813bc7462495399f7dd64ae7f40ce025918c05 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Sun, 30 Nov 2025 23:19:22 -0500 Subject: [PATCH] ctrl/shift enter creates new textblock in codeblock --- components/Blocks/BaseTextareaBlock.tsx | 49 ++++++++++++++++++++++--- components/Blocks/CodeBlock.tsx | 5 ++- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/components/Blocks/BaseTextareaBlock.tsx b/components/Blocks/BaseTextareaBlock.tsx index 6244bbd6..bff3ccd6 100644 --- a/components/Blocks/BaseTextareaBlock.tsx +++ b/components/Blocks/BaseTextareaBlock.tsx @@ -5,18 +5,55 @@ import { import { BlockProps } from "./Block"; import { getCoordinatesInTextarea } from "src/utils/getCoordinatesInTextarea"; import { focusBlock } from "src/utils/focusBlock"; +import { generateKeyBetween } from "fractional-indexing"; +import { v7 } from "uuid"; +import { elementId } from "src/utils/elementId"; +import { Replicache } from "replicache"; +import { ReplicacheMutators } from "src/replicache"; -export function BaseTextareaBlock( - props: AutosizeTextareaProps & { - block: Pick; - }, -) { - let { block, ...passDownProps } = props; +type BaseTextareaBlockProps = AutosizeTextareaProps & { + block: Pick< + BlockProps, + "previousBlock" | "nextBlock" | "parent" | "position" | "nextPosition" + >; + rep?: Replicache | null; + permissionSet?: string; +}; + +export function BaseTextareaBlock(props: BaseTextareaBlockProps) { + let { block, rep, permissionSet, ...passDownProps } = props; return ( { + // Shift-Enter or Ctrl-Enter: create new text block below and focus it + if ( + (e.shiftKey || e.ctrlKey || e.metaKey) && + e.key === "Enter" && + rep && + permissionSet + ) { + e.preventDefault(); + let newEntityID = v7(); + rep.mutate.addBlock({ + parent: block.parent, + type: "text", + factID: v7(), + permission_set: permissionSet, + position: generateKeyBetween( + block.position, + block.nextPosition || null, + ), + newEntityID, + }); + + setTimeout(() => { + document.getElementById(elementId.block(newEntityID).text)?.focus(); + }, 10); + return true; + } + if (e.key === "ArrowUp") { let selection = e.currentTarget.selectionStart; diff --git a/components/Blocks/CodeBlock.tsx b/components/Blocks/CodeBlock.tsx index d42f1180..7a358b56 100644 --- a/components/Blocks/CodeBlock.tsx +++ b/components/Blocks/CodeBlock.tsx @@ -26,7 +26,8 @@ export function CodeBlock(props: BlockProps) { let focusedBlock = useUIState( (s) => s.focusedEntity?.entityID === props.entityID, ); - let { permissions } = useEntitySetContext(); + let entity_set = useEntitySetContext(); + let { permissions } = entity_set; const [html, setHTML] = useState(null); useLayoutEffect(() => { @@ -125,6 +126,8 @@ export function CodeBlock(props: BlockProps) { data-entityid={props.entityID} id={elementId.block(props.entityID).input} block={props} + rep={rep} + permissionSet={entity_set.set} spellCheck={false} autoCapitalize="none" autoCorrect="off" -- 2.51.2