feat: add interactive React Flow canvas and floating toolbars
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
"use client";
|
||||
|
||||
import { createContext, useContext } from "react";
|
||||
import { Handle, Position, type NodeProps } from "@xyflow/react";
|
||||
import { FileText, Image as ImageIcon, Type } from "lucide-react";
|
||||
import type { CanvasNode } from "@/lib/canvas";
|
||||
import styles from "./canvas.module.css";
|
||||
|
||||
export const NodeEditing = createContext({ begin: () => {}, edit: (_id: string, _text: string) => {} });
|
||||
|
||||
export function MaterialNode({ id, data, selected }: NodeProps<CanvasNode>) {
|
||||
const editing = useContext(NodeEditing);
|
||||
const Icon = data.kind === "image" ? ImageIcon : data.kind === "script" ? FileText : Type;
|
||||
return (
|
||||
<article className={`${styles.node} ${selected ? styles.selectedNode : ""}`}>
|
||||
<header className={styles.nodeHeading}><Icon size={13} /><span>{data.title}</span></header>
|
||||
<Handle type="target" position={Position.Left} />
|
||||
{data.kind === "image" ? <img className={styles.image} src={data.src} alt={data.title} draggable={false} referrerPolicy="no-referrer" /> : (
|
||||
<textarea className="nodrag nowheel" aria-label={data.title} placeholder={data.kind === "script" ? "写下你的脚本…" : "留住一个想法…"}
|
||||
value={data.text} maxLength={100000} onFocus={editing.begin} onChange={(event) => editing.edit(id, event.target.value)} />
|
||||
)}
|
||||
<Handle type="source" position={Position.Right} />
|
||||
</article>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user