返回 presentation-ai
useDropLine.ts
根目录 / src / components / notebook / presentation / editor / dnd / hooks / useDropLine.ts
1 import { DndPlugin, type DropLineDirection } from "@platejs/dnd";
2 import { useEditorRef, useElement, usePluginOptions } from "platejs/react";
3 import React from "react";
4
5 export const useDropLine = ({
6 id: idProp,
7 orientation,
8 }: {
9 /** The id of the element to show the dropline for. */
10 id?: string;
11 /** Orientation to filter droplines. If specified, only matching droplines are returned. */
12 orientation?: "horizontal" | "vertical";
13 } = {}): {
14 dropLine?: DropLineDirection;
15 } => {
16 const element = useElement();
17 const editor = useEditorRef();
18 const id = idProp || (element.id as string);
19
20 const dropLine =
21 usePluginOptions(DndPlugin, ({ dropTarget }) => {
22 if (!dropTarget) return null;
23 if (dropTarget.id !== id) return null;
24
25 return dropTarget.line;
26 }) ?? "";
27
28 // When there's a dropline visible, start an interval that will attempt to
29 // clear it every 500ms if we're no longer dragging.
30 React.useEffect(() => {
31 if (!dropLine) return;
32
33 const intervalId = setInterval(() => {
34 const { isDragging, dropTarget } = editor.getOptions(DndPlugin) as {
35 isDragging?: boolean;
36 dropTarget?: { id: string | null; line: DropLineDirection | "" } | null;
37 };
38
39 const hasDropLine = !!dropTarget?.line;
40 const isStillDragging = !!isDragging;
41
42 if (!isStillDragging && hasDropLine) {
43 editor.setOption(DndPlugin, "dropTarget", { id: null, line: "" });
44 }
45
46 // If there's no dropline anymore, stop the interval
47 if (!editor.getOptions(DndPlugin).dropTarget?.line) {
48 clearInterval(intervalId);
49 }
50 }, 500);
51
52 return () => {
53 clearInterval(intervalId);
54 };
55 }, [editor, dropLine]);
56
57 // Filter dropline by orientation if specified
58 if (orientation) {
59 const isHorizontalDropLine = dropLine === "left" || dropLine === "right";
60 const isVerticalDropLine = dropLine === "top" || dropLine === "bottom";
61
62 // If the orientation is vertical but we got a horizontal dropline, clear it.
63 if (
64 (orientation === "vertical" && isHorizontalDropLine) ||
65 (orientation === "horizontal" && isVerticalDropLine)
66 ) {
67 return { dropLine: "" };
68 }
69 }
70
71 return { dropLine };
72 };
73
73 lines TYPESCRIPT