fix(select): select rect position

This commit is contained in:
austaras
2022-07-25 11:15:14 +08:00
parent a4132f5f8a
commit 95629486b3
7 changed files with 44 additions and 54 deletions

View File

@@ -4,7 +4,7 @@ import { styled, usePatchNodes } from '@toeverything/components/ui';
import type { FC, PropsWithChildren } from 'react'; import type { FC, PropsWithChildren } from 'react';
import React, { useEffect, useRef, useState, useCallback } from 'react'; import React, { useEffect, useRef, useState, useCallback } from 'react';
import { RootContext } from './contexts'; import { RootContext } from './contexts';
import { SelectionRect, SelectionRef } from './selection'; import { SelectionRect, SelectionRef } from './Selection';
import { import {
Protocol, Protocol,
services, services,
@@ -205,20 +205,17 @@ export const RenderRoot: FC<PropsWithChildren<RenderRootProps>> = ({
{children} {children}
{patchedNodes} {patchedNodes}
</Content> </Content>
{editor.isWhiteboard ? null : <ScrollBlank editor={editor} />}
{/** TODO: remove selectionManager insert */} {/** TODO: remove selectionManager insert */}
{container && editor && ( {container && editor && (
<SelectionRect <SelectionRect ref={selectionRef} editor={editor} />
ref={selectionRef}
container={container}
editor={editor}
/>
)} )}
{editor.isWhiteboard ? null : <ScrollBlank editor={editor} />}
</Container> </Container>
</RootContext.Provider> </RootContext.Provider>
); );
}; };
// eslint-disable-next-line @typescript-eslint/naming-convention
function ScrollBlank({ editor }: { editor: BlockEditor }) { function ScrollBlank({ editor }: { editor: BlockEditor }) {
const mouseMoved = useRef(false); const mouseMoved = useRef(false);
@@ -281,6 +278,7 @@ const Container = styled('div')(
overflowY: isWhiteboard ? 'unset' : 'auto', overflowY: isWhiteboard ? 'unset' : 'auto',
padding: isWhiteboard ? 0 : '96px 150px 0 150px', padding: isWhiteboard ? 0 : '96px 150px 0 150px',
minWidth: isWhiteboard ? 'unset' : '940px', minWidth: isWhiteboard ? 'unset' : '940px',
position: 'relative',
}) })
); );

View File

@@ -1,6 +1,5 @@
import React, { import React, {
forwardRef, forwardRef,
useCallback,
useImperativeHandle, useImperativeHandle,
useEffect, useEffect,
useRef, useRef,
@@ -14,16 +13,13 @@ import { styled } from '@toeverything/components/ui';
type MouseType = 'up' | 'down'; type MouseType = 'up' | 'down';
interface SelectionProps { interface SelectionProps {
container?: HTMLElement;
editor: BlockEditor; editor: BlockEditor;
} }
const styles = style9.create({ const RectContainer = styled('div')({
selectionRect: { backgroundColor: 'rgba(152, 172, 189, 0.1)',
backgroundColor: 'rgba(152, 172, 189, 0.1)', position: 'absolute',
position: 'absolute', zIndex: 99,
zIndex: 99,
},
}); });
type VerticalTypes = 'up' | 'down' | null; type VerticalTypes = 'up' | 'down' | null;
@@ -103,10 +99,10 @@ const setSelectedNodesByPoints = async (
export const SelectionRect = forwardRef<SelectionRef, SelectionProps>( export const SelectionRect = forwardRef<SelectionRef, SelectionProps>(
(props, ref) => { (props, ref) => {
const { container, editor } = props; const { editor } = props;
const { selectionManager, scrollManager } = editor; const { selectionManager, scrollManager } = editor;
const [isShow, setIsShow] = useState<boolean>(false); const [show, setShow] = useState<boolean>(false);
const startPointRef = useRef<Point>(); const startPointRef = useRef<Point>();
const endPointRef = useRef<Point>(); const endPointRef = useRef<Point>();
const [rect, setRect] = useState<Rect>(Rect.fromLTRB(0, 0, 0, 0)); const [rect, setRect] = useState<Rect>(Rect.fromLTRB(0, 0, 0, 0));
@@ -137,7 +133,7 @@ export const SelectionRect = forwardRef<SelectionRef, SelectionProps>(
if (mouseType.current === 'down' && !startPointAtBlock.current) { if (mouseType.current === 'down' && !startPointAtBlock.current) {
event.preventDefault(); event.preventDefault();
endPointRef.current = new Point(event.clientX, event.clientY); endPointRef.current = new Point(event.clientX, event.clientY);
setIsShow(true); setShow(true);
if (startPointRef.current) { if (startPointRef.current) {
await setSelectedNodesByPoints( await setSelectedNodesByPoints(
@@ -182,7 +178,7 @@ export const SelectionRect = forwardRef<SelectionRef, SelectionProps>(
const onMouseUp = () => { const onMouseUp = () => {
mouseType.current = 'up'; mouseType.current = 'up';
startPointAtBlock.current = false; startPointAtBlock.current = false;
setIsShow(false); setShow(false);
scrollManager.stopAutoScroll(); scrollManager.stopAutoScroll();
}; };
@@ -250,11 +246,10 @@ export const SelectionRect = forwardRef<SelectionRef, SelectionProps>(
scrollManager.onScrolling(scrollingCallback); scrollManager.onScrolling(scrollingCallback);
return () => scrollManager.removeScrolling(scrollingCallback); return () => scrollManager.removeScrolling(scrollingCallback);
}, [scrollManager]); }, [editor, scrollManager]);
return isShow ? ( return show ? (
<div <RectContainer
className={styles('selectionRect')}
style={{ style={{
left: `${rect.left}px`, left: `${rect.left}px`,
top: `${rect.top}px`, top: `${rect.top}px`,

View File

@@ -1,5 +1,4 @@
/* eslint-disable max-lines */ /* eslint-disable max-lines */
import type { ReactNode } from 'react';
import HotKeys from 'hotkeys-js'; import HotKeys from 'hotkeys-js';
import LRUCache from 'lru-cache'; import LRUCache from 'lru-cache';
@@ -9,7 +8,7 @@ import type {
ReturnEditorBlock, ReturnEditorBlock,
UpdateEditorBlock, UpdateEditorBlock,
} from '@toeverything/datasource/db-service'; } from '@toeverything/datasource/db-service';
import type { PatchNode, UnPatchNode } from '@toeverything/components/ui'; import type { PatchNode } from '@toeverything/components/ui';
import { AsyncBlock } from './block'; import { AsyncBlock } from './block';
import type { WorkspaceAndBlockId } from './block'; import type { WorkspaceAndBlockId } from './block';
@@ -46,7 +45,7 @@ export interface EditorCtorProps {
} }
export class Editor implements Virgo { export class Editor implements Virgo {
private cache_manager = new LRUCache<string, Promise<AsyncBlock | null>>({ private _cacheManager = new LRUCache<string, Promise<AsyncBlock | null>>({
max: 8192, max: 8192,
ttl: 1000 * 60 * 30, ttl: 1000 * 60 * 30,
}); });
@@ -136,7 +135,7 @@ export class Editor implements Virgo {
public set container(v: HTMLDivElement) { public set container(v: HTMLDivElement) {
this.ui_container = v; this.ui_container = v;
this.init_clipboard(); this._initClipboard();
} }
public get container() { public get container() {
@@ -171,7 +170,7 @@ export class Editor implements Virgo {
this.clipboard_populator?.disposeInternal(); this.clipboard_populator?.disposeInternal();
} }
private init_clipboard() { private _initClipboard() {
this._disposeClipboard(); this._disposeClipboard();
if (this.ui_container && !this._isDisposed) { if (this.ui_container && !this._isDisposed) {
this.clipboard = new BrowserClipboard( this.clipboard = new BrowserClipboard(
@@ -261,7 +260,7 @@ export class Editor implements Virgo {
workspace, workspace,
id, id,
}: WorkspaceAndBlockId): Promise<AsyncBlock | null> { }: WorkspaceAndBlockId): Promise<AsyncBlock | null> {
const block = this.cache_manager.get(id); const block = this._cacheManager.get(id);
if (block) { if (block) {
return block; return block;
} }
@@ -288,7 +287,7 @@ export class Editor implements Virgo {
}; };
create(); create();
}); });
this.cache_manager.set(id, block_promise); this._cacheManager.set(id, block_promise);
return await block_promise; return await block_promise;
} }
@@ -301,7 +300,7 @@ export class Editor implements Virgo {
}); });
const block = await this._initBlock(blockData); const block = await this._initBlock(blockData);
if (block) { if (block) {
this.cache_manager.set(block.id, Promise.resolve(block)); this._cacheManager.set(block.id, Promise.resolve(block));
} }
return block; return block;
} }

View File

@@ -172,5 +172,6 @@ export class LeftMenuPlugin extends BasePlugin {
public override dispose(): void { public override dispose(): void {
// TODO: rxjs // TODO: rxjs
this.root?.unmount(); this.root?.unmount();
super.dispose();
} }
} }

View File

@@ -0,0 +1,19 @@
import { styled } from '@toeverything/components/ui';
import { DndTree } from './DndTree';
import { useDndTreeAutoUpdate } from './use-page-tree';
const Root = styled('div')({
minWidth: 160,
maxWidth: 260,
marginLeft: 18,
marginRight: 6,
});
export const PageTree = () => {
useDndTreeAutoUpdate();
return (
<Root>
<DndTree collapsible removable />
</Root>
);
};

View File

@@ -1,4 +1,4 @@
export { PageTree } from './page-tree'; export { PageTree } from './PageTree';
export { usePageTree } from './use-page-tree'; export { usePageTree } from './use-page-tree';
export * from './types'; export * from './types';

View File

@@ -1,22 +0,0 @@
import style9 from 'style9';
import { DndTree } from './DndTree';
import { useDndTreeAutoUpdate } from './use-page-tree';
const styles = style9.create({
root: {
minWidth: 160,
maxWidth: 260,
marginLeft: 18,
marginRight: 6,
},
});
export const PageTree = () => {
useDndTreeAutoUpdate();
return (
<div className={styles('root')}>
<DndTree collapsible removable />
</div>
);
};