mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-15 05:37:32 +00:00
feat: change cursor when drag
This commit is contained in:
@@ -11,7 +11,7 @@ import {
|
||||
type ReturnUnobserve,
|
||||
} from '@toeverything/datasource/db-service';
|
||||
import { addNewGroup } from './recast-block';
|
||||
import { HookType } from './editor';
|
||||
import { useIsOnDrag } from '.';
|
||||
|
||||
interface RenderRootProps {
|
||||
editor: BlockEditor;
|
||||
@@ -35,6 +35,7 @@ export const RenderRoot: FC<PropsWithChildren<RenderRootProps>> = ({
|
||||
const triggeredBySelect = useRef(false);
|
||||
const [container, setContainer] = useState<HTMLDivElement>();
|
||||
const [pageWidth, setPageWidth] = useState<number>(MIN_PAGE_WIDTH);
|
||||
const isOnDrag = useIsOnDrag(editor);
|
||||
|
||||
const { patch, has, patchedNodes } = usePatchNodes();
|
||||
|
||||
@@ -147,6 +148,8 @@ export const RenderRoot: FC<PropsWithChildren<RenderRootProps>> = ({
|
||||
};
|
||||
|
||||
const onDragOver = (event: React.DragEvent<Element>) => {
|
||||
event.dataTransfer.dropEffect = 'move';
|
||||
event.preventDefault();
|
||||
if (!contentRef.current) {
|
||||
return;
|
||||
}
|
||||
@@ -155,10 +158,10 @@ export const RenderRoot: FC<PropsWithChildren<RenderRootProps>> = ({
|
||||
if (editor.dragDropManager.isEnabled()) {
|
||||
editor.getHooks().onRootNodeDragOver(event, rootRect);
|
||||
}
|
||||
event.preventDefault();
|
||||
};
|
||||
|
||||
const onDragOverCapture = (event: React.DragEvent<Element>) => {
|
||||
event.preventDefault();
|
||||
if (!contentRef.current) {
|
||||
return;
|
||||
}
|
||||
@@ -202,7 +205,7 @@ export const RenderRoot: FC<PropsWithChildren<RenderRootProps>> = ({
|
||||
onDragOverCapture={onDragOverCapture}
|
||||
onDragEnd={onDragEnd}
|
||||
onDrop={onDrop}
|
||||
onScroll={onScroll}
|
||||
isOnDrag={isOnDrag}
|
||||
>
|
||||
<Content
|
||||
ref={contentRef}
|
||||
@@ -278,13 +281,25 @@ function ScrollBlank({ editor }: { editor: BlockEditor }) {
|
||||
}
|
||||
|
||||
const Container = styled('div')(
|
||||
({ isWhiteboard }: { isWhiteboard: boolean }) => ({
|
||||
({
|
||||
isWhiteboard,
|
||||
isOnDrag,
|
||||
}: {
|
||||
isWhiteboard: boolean;
|
||||
isOnDrag: boolean;
|
||||
}) => ({
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
overflowY: isWhiteboard ? 'unset' : 'auto',
|
||||
padding: isWhiteboard ? 0 : '96px 150px 0 150px',
|
||||
minWidth: isWhiteboard ? 'unset' : '940px',
|
||||
position: 'relative',
|
||||
...(isOnDrag && {
|
||||
cursor: 'grabbing',
|
||||
// expected css selector
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
'& *': { cursor: 'grabbing' },
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ export function DragDropWrapper({
|
||||
const handler_drag_over: React.DragEventHandler<
|
||||
HTMLDivElement
|
||||
> = async event => {
|
||||
event.preventDefault();
|
||||
const rootDom = await editor.getBlockDomById(editor.getRootBlockId());
|
||||
|
||||
if (block.dom && rootDom) {
|
||||
editor.getHooks().afterOnNodeDragOver(event, {
|
||||
blockId: block.id,
|
||||
|
||||
@@ -9,9 +9,12 @@ import EventEmitter from 'eventemitter3';
|
||||
type DargType =
|
||||
| ValueOf<InstanceType<typeof DragDropManager>['dragActions']>
|
||||
| '';
|
||||
|
||||
const DRAG_STATE_CHANGE_EVENT_KEY = 'dragStateChange';
|
||||
export class DragDropManager {
|
||||
private _editor: Editor;
|
||||
private _enabled: boolean;
|
||||
private _events = new EventEmitter();
|
||||
|
||||
private _blockIdKey = 'blockId';
|
||||
private _rootIdKey = 'rootId';
|
||||
@@ -26,15 +29,29 @@ export class DragDropManager {
|
||||
dragGroup: 'dragGroup',
|
||||
} as const;
|
||||
|
||||
private _isOnDrag = false;
|
||||
|
||||
get dragActions() {
|
||||
return this._dragActions;
|
||||
}
|
||||
|
||||
get isOnDrag() {
|
||||
return this._isOnDrag;
|
||||
}
|
||||
|
||||
set isOnDrag(isOnDrag: boolean) {
|
||||
if (this._isOnDrag !== isOnDrag) {
|
||||
this._events.emit(DRAG_STATE_CHANGE_EVENT_KEY, isOnDrag);
|
||||
}
|
||||
this._isOnDrag = isOnDrag;
|
||||
}
|
||||
|
||||
constructor(editor: Editor) {
|
||||
this._editor = editor;
|
||||
this._enabled = true;
|
||||
this._dragType = '';
|
||||
this._blockDragDirection = BlockDropPlacement.none;
|
||||
this._initMouseEvent();
|
||||
}
|
||||
|
||||
get dragType() {
|
||||
@@ -45,6 +62,15 @@ export class DragDropManager {
|
||||
this._dragType = type;
|
||||
}
|
||||
|
||||
private async _initMouseEvent() {
|
||||
this._editor.mouseManager.onMouseUp(() => {
|
||||
// IMP: temporarily last protect for dragging across editor instances,bad case
|
||||
if (this.isOnDrag) {
|
||||
this.isOnDrag = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _setBlockDragDirection(direction: BlockDropPlacement) {
|
||||
this._blockDragDirection = direction;
|
||||
}
|
||||
@@ -244,6 +270,9 @@ export class DragDropManager {
|
||||
|
||||
public handlerEditorDragEnd(event: React.DragEvent<Element>) {
|
||||
this._resetDragDropData();
|
||||
if (this.isOnDrag) {
|
||||
this.isOnDrag = false;
|
||||
}
|
||||
if (this.isEnabled()) {
|
||||
// TODO: handle drag end event flow
|
||||
}
|
||||
@@ -287,4 +316,16 @@ export class DragDropManager {
|
||||
}
|
||||
return direction;
|
||||
}
|
||||
|
||||
public onDragStateChange(cb: (isOnDrag: boolean) => void) {
|
||||
this._events.on(DRAG_STATE_CHANGE_EVENT_KEY, cb);
|
||||
}
|
||||
|
||||
public offDragStateChange(cb: (isOnDrag: boolean) => void) {
|
||||
this._events.off(DRAG_STATE_CHANGE_EVENT_KEY, cb);
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
this._events.removeAllListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import type { AsyncBlock } from './block';
|
||||
import type { BlockHelper } from './block/block-helper';
|
||||
import type { BlockCommands } from './commands/block-commands';
|
||||
import type { DragDropManager } from './drag-drop';
|
||||
import { MouseManager } from './mouse';
|
||||
|
||||
// import { BrowserClipboard } from './clipboard/browser-clipboard';
|
||||
|
||||
@@ -104,6 +105,7 @@ export interface Virgo {
|
||||
workspace: string;
|
||||
getBlockDomById: (id: string) => Promise<HTMLElement>;
|
||||
isWhiteboard: boolean;
|
||||
mouseManager: MouseManager;
|
||||
}
|
||||
|
||||
export interface Plugin {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
AsyncBlock,
|
||||
BlockEditor,
|
||||
SelectEventTypes,
|
||||
SelectionInfo,
|
||||
SelectionSettingsMap,
|
||||
@@ -202,3 +203,21 @@ export const useOnSelectStartWith = (
|
||||
};
|
||||
}, [editor, cb, blockId]);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* hooks run when drag state change
|
||||
* @export
|
||||
*/
|
||||
export const useIsOnDrag = (editor: BlockEditor) => {
|
||||
const editorInstance = editor;
|
||||
const [isOnDrag, setIsOnDrag] = useState(false);
|
||||
useEffect(() => {
|
||||
const callback = (isDrag: boolean) => setIsOnDrag(isDrag);
|
||||
editorInstance.dragDropManager.onDragStateChange(callback);
|
||||
return () => {
|
||||
editorInstance.dragDropManager.offDragStateChange(callback);
|
||||
};
|
||||
}, [editorInstance]);
|
||||
return isOnDrag;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user