From 8b1de14f7916194e5858d097ce9d3b309a435a6d Mon Sep 17 00:00:00 2001 From: misterkirill Date: Fri, 11 Jul 2025 00:01:25 +0500 Subject: [PATCH] feat: add block movement --- src/app/notes/[id]/page.tsx | 7 ++++--- src/components/editor/Block.tsx | 17 +++++++++++++--- src/components/editor/Editor.tsx | 33 +++++++++++++++++++------------- src/lib/editorReducer.ts | 24 ++++++++++++++++++++++- 4 files changed, 61 insertions(+), 20 deletions(-) diff --git a/src/app/notes/[id]/page.tsx b/src/app/notes/[id]/page.tsx index 4855480..9bdeeb7 100644 --- a/src/app/notes/[id]/page.tsx +++ b/src/app/notes/[id]/page.tsx @@ -1,6 +1,7 @@ +import { Metadata } from "next"; import { notFound } from "next/navigation"; import { getNote } from "@/lib/notes"; -import { Metadata } from "next"; +import Editor from "@/components/editor/Editor"; export async function generateMetadata({ params }: { params: Promise<{ id: string }> }): Promise { const { id } = await params; @@ -20,8 +21,8 @@ export default async function Note({ params }: { params: Promise<{ id: string }> } return ( -
- {note.name} +
+
); } diff --git a/src/components/editor/Block.tsx b/src/components/editor/Block.tsx index 317d24f..214f765 100644 --- a/src/components/editor/Block.tsx +++ b/src/components/editor/Block.tsx @@ -1,7 +1,7 @@ "use client"; import { ChangeEvent } from "react"; -import { Lock, LockOpen, Menu, Minus, Plus, X } from "lucide-react"; +import { ArrowDown, ArrowUp, Lock, LockOpen, Minus, Plus, X } from "lucide-react"; import { Action, IBlock, ILine } from "@/lib/editorReducer"; import IconOnlyButton from "../ui/IconOnlyButton"; import LineInput from "./LineInput"; @@ -33,6 +33,14 @@ export default function Block({ dispatch({ type: "delete_block", blockId: block.id }); } + const handleBlockUp = () => { + dispatch({ type: "move_block_up", blockId: block.id }); + } + + const handleBlockDown = () => { + dispatch({ type: "move_block_down", blockId: block.id }); + } + const handleToggleLock = () => { dispatch({ type: "toggle_lock", blockId: block.id }); } @@ -57,14 +65,17 @@ export default function Block({ /> ))}
-
+
} /> } />
+
+ } /> + } /> +
} /> : } alwaysOn={block.locked} /> - } />
diff --git a/src/components/editor/Editor.tsx b/src/components/editor/Editor.tsx index 8f0c38d..7f3feb7 100644 --- a/src/components/editor/Editor.tsx +++ b/src/components/editor/Editor.tsx @@ -3,22 +3,29 @@ import { useReducer } from "react"; import { Copy, Plus } from "lucide-react"; import { v4 as uuidv4 } from "uuid"; -import { editorReducer } from "@/lib/editorReducer"; +import { editorReducer, IBlock } from "@/lib/editorReducer"; import IconOnlyButton from "../ui/IconOnlyButton"; import Block from "./Block"; -export default function Editor() { - const [state, dispatch] = useReducer(editorReducer, [ - { +interface EditorProps { + defaultTitle?: string; + defaultBlocks?: IBlock[]; +} + +const defaultBlocks = [ + { + id: uuidv4(), + tag: "", + locked: false, + lines: Array.from({ length: 4 }, () => ({ id: uuidv4(), - tag: "", - locked: false, - lines: Array.from({ length: 4 }, () => ({ - id: uuidv4(), - text: "", - })), - } - ]); + text: "", + })), + } +]; + +export default function Editor(props: EditorProps) { + const [state, dispatch] = useReducer(editorReducer, props.defaultBlocks || defaultBlocks); const handleAddBlock = () => { dispatch({ type: "add_block" }); @@ -30,7 +37,7 @@ export default function Editor() { return (
- + {state.map((block) => )}
} /> diff --git a/src/lib/editorReducer.ts b/src/lib/editorReducer.ts index 0b0a6bd..09ed1b4 100644 --- a/src/lib/editorReducer.ts +++ b/src/lib/editorReducer.ts @@ -22,6 +22,8 @@ export type Action = | { type: "delete_line", blockId: string } | { type: "update_line_text"; blockId: string; lineId: string; text: string } | { type: "update_tag"; blockId: string; tag: string } + | { type: "move_block_up", blockId: string } + | { type: "move_block_down", blockId: string } | { type: "toggle_lock", blockId: string }; export function editorReducer(state: EditorState, action: Action): EditorState { @@ -48,7 +50,11 @@ export function editorReducer(state: EditorState, action: Action): EditorState { copyText += `[${block.tag}]\n`; } - block.lines.forEach((line) => copyText += line.text + "\n") + block.lines.forEach((line) => { + if (line.text !== "") { + copyText += line.text + "\n"; + } + }) copyText += "\n"; }); @@ -115,6 +121,22 @@ export function editorReducer(state: EditorState, action: Action): EditorState { } }); + case "move_block_up": { + const index = state.findIndex((b) => b.id === action.blockId); + if (index <= 0) return state; + const newState = [...state]; + [newState[index - 1], newState[index]] = [newState[index], newState[index - 1]]; + return newState; + } + + case "move_block_down": { + const index = state.findIndex((b) => b.id === action.blockId); + if (index === state.length - 1) return state; + const newState = [...state]; + [newState[index], newState[index + 1]] = [newState[index + 1], newState[index]]; + return newState; + } + case "toggle_lock": return state.map((block) => { if (block.id === action.blockId) {