Skip to content

Commit 90a0e52

Browse files
committed
feat: dragHandle menu
1 parent 06ee8a7 commit 90a0e52

File tree

5 files changed

+111
-55
lines changed

5 files changed

+111
-55
lines changed

.eslintrc.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@
7070
"fixStyle": "separate-type-imports",
7171
"prefer": "type-imports"
7272
}
73-
]
73+
],
74+
"@typescript-eslint/no-explicit-any": "off"
7475
}
7576
}
7677
]

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"@bytemd/react": "^1.21.0",
3636
"@ethersproject/address": "^5.7.0",
3737
"@ethersproject/units": "^5.7.0",
38+
"@floating-ui/react": "^0.27.5",
3839
"@headlessui/react": "^1.7.7",
3940
"@heroicons/react": "^2.0.16",
4041
"@mysten/dapp-kit": "^0.11.1",
@@ -136,7 +137,7 @@
136137
"eslint-plugin-perfectionist": "4.8.0",
137138
"eslint-plugin-react": "7.31.11",
138139
"eslint-plugin-tailwindcss": "3.15.1",
139-
"eslint-plugin-unused-imports": "3.0.0",
140+
"eslint-plugin-unused-imports": "3.2.0",
140141
"husky": "9.1.7",
141142
"ksio": "^0.0.3",
142143
"lint-staged": "15.3.0",

src/shared/components/control/block-editor/BlockEditor.js src/shared/components/control/block-editor/BlockEditor.tsx

+12-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import {
2323
ImageResizer, handleCommandNavigation,
2424
} from 'novel';
2525

26+
import type { EditorInstance} from 'novel';
27+
2628
import { isFunction } from '../../../utils';
2729
import BlockEditorBubble from './bubble';
2830
import DragHandle from './DragHandle';
@@ -32,8 +34,15 @@ import { slashCommand, suggestionItems } from './slash';
3234

3335
const extensions = [...defaultExtensions, slashCommand];
3436

35-
function BlockEditor({ className, data, onChange, editable = false }) {
36-
const handleUpdate = ({ editor }) => {
37+
interface BlockEditorProps {
38+
className?: string;
39+
data: any;
40+
onChange: (data: any) => void;
41+
editable?: boolean;
42+
}
43+
44+
function BlockEditor({ className, data, onChange, editable = false }: BlockEditorProps) {
45+
const handleUpdate = ({ editor }: { editor: EditorInstance }) => {
3746
isFunction(onChange) && onChange(editor.getJSON());
3847
};
3948

@@ -64,7 +73,7 @@ function BlockEditor({ className, data, onChange, editable = false }) {
6473
{suggestionItems.map(item => (
6574
<EditorCommandItem
6675
value={item.title}
67-
onCommand={val => item.command(val)}
76+
onCommand={val => item.command?.(val)}
6877
className="flex w-full items-center space-x-2 rounded-md px-2 py-1 text-left text-sm hover:bg-neutral-200 aria-selected:bg-neutral-200"
6978
key={item.title}
7079
>

src/shared/components/control/block-editor/DragHandle.js

-50
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/**
2+
* Copyright 2024 OpenBuild
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { useInteractions, useFloating, useClick } from '@floating-ui/react';
18+
import { useEditor } from 'novel';
19+
import { useState } from 'react';
20+
21+
import type { ReactNode } from 'react';
22+
23+
function Item({ children, onClick }: { children: ReactNode; onClick: () => void }) {
24+
return (
25+
<div className="cursor-pointer rounded-sm px-2 py-1 hover:bg-gray-900" onClick={onClick}>
26+
{children}
27+
</div>
28+
);
29+
}
30+
31+
function DragHandle() {
32+
const { editor } = useEditor();
33+
34+
const [isOpen, setIsOpen] = useState(false);
35+
36+
const { refs, floatingStyles, context } = useFloating({
37+
placement: 'left-start',
38+
open: isOpen,
39+
onOpenChange: setIsOpen,
40+
});
41+
const click = useClick(context);
42+
const { getReferenceProps, getFloatingProps } = useInteractions([click]);
43+
44+
const insertNewBlockBelow = () => {
45+
if (!editor) return;
46+
47+
return editor
48+
.chain()
49+
.focus()
50+
.command(({ tr }) => {
51+
const { $from } = tr.selection;
52+
const insertPos = $from.after($from.depth);
53+
tr.insert(insertPos, editor.schema.nodes.paragraph.create());
54+
55+
setIsOpen(false);
56+
return true;
57+
})
58+
.run();
59+
};
60+
const deleteBlock = () => {
61+
if (!editor) return;
62+
63+
return editor
64+
.chain()
65+
.focus()
66+
.command(({ tr }) => {
67+
const { $from } = tr.selection;
68+
tr.delete($from.before($from.depth), $from.after($from.depth));
69+
70+
setIsOpen(false);
71+
return true;
72+
})
73+
.run();
74+
};
75+
76+
return (
77+
<>
78+
<div className="BlockEditor-dragHandle" ref={refs.setReference} {...getReferenceProps()} />
79+
80+
{isOpen && (
81+
<div
82+
className="flex flex-col gap-2 rounded-md border py-1 px-2 border-gray-300 bg-background shadow-md"
83+
ref={refs.setFloating}
84+
style={floatingStyles}
85+
{...getFloatingProps()}
86+
>
87+
<Item onClick={deleteBlock}>Delete</Item>
88+
<Item onClick={insertNewBlockBelow}>Insert</Item>
89+
</div>
90+
)}
91+
</>
92+
);
93+
}
94+
95+
export default DragHandle;

0 commit comments

Comments
 (0)