feat: grid item style

This commit is contained in:
SaikaSakura
2022-07-28 18:16:43 +08:00
parent cfe9d5a82d
commit 142523337b
6 changed files with 87 additions and 55 deletions

View File

@@ -124,7 +124,7 @@ export const GridItem: FC<ChildrenView> = function (props) {
const GridItemContainer = styled('div')({ const GridItemContainer = styled('div')({
transition: 'background-color 0.3s ease-in-out', transition: 'background-color 0.3s ease-in-out',
maxWidth: 'calc(100% - 10px)', maxWidth: 'calc(100% - 10px)',
padding: '4px', padding: '1px 3px',
flexGrow: 1, flexGrow: 1,
border: '1px solid transparent', border: '1px solid transparent',
borderRadius: '4px', borderRadius: '4px',

View File

@@ -3,6 +3,8 @@ import { useState } from 'react';
import { styled } from '@toeverything/components/ui'; import { styled } from '@toeverything/components/ui';
import { BlockEditor } from '@toeverything/framework/virgo'; import { BlockEditor } from '@toeverything/framework/virgo';
const GRID_ADD_HANDLE_NAME = 'rid-add-handle';
type GridHandleProps = { type GridHandleProps = {
editor: BlockEditor; editor: BlockEditor;
onDrag?: (e: MouseEvent) => void; onDrag?: (e: MouseEvent) => void;
@@ -56,7 +58,7 @@ export const GridHandle: FC<GridHandleProps> = function ({
{enabledAddItem ? ( {enabledAddItem ? (
<AddGridHandle <AddGridHandle
onClick={handleCreateGridItem} onClick={handleCreateGridItem}
className="grid-add-handle" className={GRID_ADD_HANDLE_NAME}
> >
+ +
</AddGridHandle> </AddGridHandle>
@@ -70,14 +72,14 @@ const GridHandleContainer = styled('div')(({ theme }) => ({
width: '10px', width: '10px',
flexGrow: '0', flexGrow: '0',
flexShrink: '0', flexShrink: '0',
padding: '5px 4px', padding: '5px 4.5px',
minHeight: '15px', minHeight: '15px',
cursor: 'col-resize', cursor: 'col-resize',
borderRadius: '1px', borderRadius: '1px',
backgroundClip: 'content-box', backgroundClip: 'content-box',
' &:hover': { ' &:hover': {
backgroundColor: theme.affine.palette.primary, backgroundColor: theme.affine.palette.primary,
'.grid-add-handle': { [`.${GRID_ADD_HANDLE_NAME}`]: {
display: 'block', display: 'block',
}, },
}, },
@@ -87,25 +89,18 @@ const AddGridHandle = styled('div')(({ theme }) => ({
display: 'none', display: 'none',
position: 'absolute', position: 'absolute',
transition: 'all 0.2s ease-in-out', transition: 'all 0.2s ease-in-out',
height: '6px', height: '20px',
width: '6px',
borderRadius: '6px',
top: '-6px',
left: '2px',
cursor: 'pointer',
backgroundColor: theme.affine.palette.menuSeparator,
color: theme.affine.palette.menuSeparator,
overflow: 'hidden',
fontWeight: 'bold',
lineHeight: '18px', lineHeight: '18px',
width: '10px',
borderRadius: '6px',
top: 'calc(50% - 10px)',
left: '0px',
cursor: 'pointer',
color: theme.affine.palette.primary,
overflow: 'hidden',
textAlign: 'center', textAlign: 'center',
' &:hover': { backgroundColor: theme.affine.palette.white,
width: '20px', '&:hover': {
height: '20px', fontWeight: 'bold',
borderRadius: '10px',
backgroundColor: theme.affine.palette.primary,
color: theme.affine.palette.white,
top: '-20px',
left: '-5px',
}, },
})); }));

View File

@@ -177,7 +177,7 @@ export const Grid: FC<CreateView> = function (props) {
style={{ style={{
transition: isOnDrag transition: isOnDrag
? 'none' ? 'none'
: 'width 0.2s ease-in-out', : 'all 0.2s ease-in-out',
}} }}
key={id} key={id}
className={GRID_ITEM_CLASS_NAME} className={GRID_ITEM_CLASS_NAME}
@@ -218,9 +218,11 @@ const GridContainer = styled('div')({
position: 'relative', position: 'relative',
display: 'flex', display: 'flex',
alignItems: 'stretch', alignItems: 'stretch',
borderRadius: '10px',
border: '1px solid #FFF',
minWidth: `${GRID_ITEM_MIN_WIDTH}%`, minWidth: `${GRID_ITEM_MIN_WIDTH}%`,
[`&:hover .${GRID_ITEM_CONTENT_CLASS_NAME}`]: { [`&:hover .${GRID_ITEM_CONTENT_CLASS_NAME}`]: {
backgroundColor: 'rgba(100, 106, 115, 0.05)', borderColor: '#E0E6EB',
}, },
}); });

View File

@@ -16,11 +16,12 @@ interface SelectionProps {
editor: BlockEditor; editor: BlockEditor;
} }
const RectContainer = styled('div')({ const DIRECTION_VALUE_MAP = {
backgroundColor: 'rgba(152, 172, 189, 0.1)', right: -1,
position: 'absolute', left: 1,
zIndex: 99, down: -1,
}); up: 1,
} as const;
type VerticalTypes = 'up' | 'down' | null; type VerticalTypes = 'up' | 'down' | null;
type HorizontalTypes = 'left' | 'right' | null; type HorizontalTypes = 'left' | 'right' | null;
@@ -106,7 +107,7 @@ export const SelectionRect = forwardRef<SelectionRef, SelectionProps>(
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));
const startPointAtBlock = useRef<boolean>(false); const startPointBlock = useRef<AsyncBlock | null>();
const mouseType = useRef<MouseType>('up'); const mouseType = useRef<MouseType>('up');
const scrollContainerRect = useRef<Rect>(); const scrollContainerRect = useRef<Rect>();
@@ -116,9 +117,12 @@ export const SelectionRect = forwardRef<SelectionRef, SelectionProps>(
) => { ) => {
await selectionManager.setSelectedNodesIds([]); await selectionManager.setSelectedNodesIds([]);
startPointRef.current = new Point(event.clientX, event.clientY); startPointRef.current = new Point(event.clientX, event.clientY);
startPointAtBlock.current = startPointBlock.current =
(await selectionManager.rootDomReady()) && ((await selectionManager.rootDomReady()) &&
(await selectionManager.isPointInBlocks(startPointRef.current)); (await selectionManager.getBlockByPoint(
startPointRef.current
))) ||
null;
mouseType.current = 'down'; mouseType.current = 'down';
if (scrollManager.scrollContainer) { if (scrollManager.scrollContainer) {
scrollContainerRect.current = domToRect( scrollContainerRect.current = domToRect(
@@ -130,11 +134,35 @@ export const SelectionRect = forwardRef<SelectionRef, SelectionProps>(
const onMouseMove = async ( const onMouseMove = async (
event: React.MouseEvent<HTMLDivElement, MouseEvent> event: React.MouseEvent<HTMLDivElement, MouseEvent>
) => { ) => {
if (mouseType.current === 'down' && !startPointAtBlock.current) { if (mouseType.current === 'down') {
event.preventDefault();
endPointRef.current = new Point(event.clientX, event.clientY); endPointRef.current = new Point(event.clientX, event.clientY);
if (startPointBlock.current) {
const endpointBlock =
await selectionManager.getBlockByPoint(
endPointRef.current
);
// TODO: delete after multi-block text selection done
// if drag out of startblock change selection type to block
if (endpointBlock?.id === startPointBlock.current.id) {
return;
}
const selection = window.getSelection();
if (
selection &&
selection.rangeCount > 0 &&
editor.blockHelper.hasBlockTextUtils(
startPointBlock.current.id
)
) {
// slate will run hooks reset selection unless mouseup,
// remove slate selection by textUtils
editor.blockHelper.setBlockBlur(
startPointBlock.current.id
);
}
event.preventDefault();
}
setShow(true); setShow(true);
if (startPointRef.current) { if (startPointRef.current) {
await setSelectedNodesByPoints( await setSelectedNodesByPoints(
editor, editor,
@@ -177,7 +205,7 @@ export const SelectionRect = forwardRef<SelectionRef, SelectionProps>(
const onMouseUp = () => { const onMouseUp = () => {
mouseType.current = 'up'; mouseType.current = 'up';
startPointAtBlock.current = false; startPointBlock.current = null;
setShow(false); setShow(false);
scrollManager.stopAutoScroll(); scrollManager.stopAutoScroll();
}; };
@@ -200,24 +228,14 @@ export const SelectionRect = forwardRef<SelectionRef, SelectionProps>(
scrollManager.scrollContainer && scrollManager.scrollContainer &&
scrollContainerRect.current scrollContainerRect.current
) { ) {
const xValue = const xSign = DIRECTION_VALUE_MAP[direction[0]] || 0;
direction[0] === 'right' const ySign = DIRECTION_VALUE_MAP[direction[1]] || 0;
? -1
: direction[0] === 'left'
? 1
: 0;
const yValue =
direction[1] === 'down'
? -1
: direction[1] === 'up'
? 1
: 0;
startPointRef.current = new Point( startPointRef.current = new Point(
startPointRef.current.x + startPointRef.current.x +
xValue * scrollManager.scrollMoveOffset, xSign * scrollManager.scrollMoveOffset,
startPointRef.current.y + startPointRef.current.y +
yValue * scrollManager.scrollMoveOffset ySign * scrollManager.scrollMoveOffset
); );
setSelectedNodesByPoints( setSelectedNodesByPoints(
@@ -260,3 +278,9 @@ export const SelectionRect = forwardRef<SelectionRef, SelectionProps>(
) : null; ) : null;
} }
); );
const RectContainer = styled('div')({
backgroundColor: 'rgba(62, 111, 219, 0.1)',
position: 'absolute',
zIndex: 99,
});

View File

@@ -57,6 +57,10 @@ export class BlockHelper {
delete this._blockTextUtilsMap[blockId]; delete this._blockTextUtilsMap[blockId];
} }
public hasBlockTextUtils(blockId: string) {
return !!this._blockTextUtilsMap[blockId];
}
/** /**
* *
* get block serializer text by block id * get block serializer text by block id

View File

@@ -292,14 +292,22 @@ export class SelectionManager implements VirgoSelection {
const rootBlock = await this._editor.getBlockById(rootBlockId); const rootBlock = await this._editor.getBlockById(rootBlockId);
return Boolean(rootBlock?.dom); return Boolean(rootBlock?.dom);
} }
// TODO: Maybe just check root block
public async isPointInBlocks(point: Point) { public async getBlockByPoint(point: Point) {
const blockList = await this._editor.getBlockList(); const blockList = await this._editor.getBlockList();
return blockList.some(block => { const outBlockList = blockList.filter(block => {
return ( return (
Boolean(block.dom) && domToRect(block.dom).isContainPoint(point) Boolean(block.dom) && domToRect(block.dom).isContainPoint(point)
); );
}); });
return outBlockList.length
? outBlockList[outBlockList.length - 1]
: undefined;
}
public async isPointInBlocks(point: Point) {
return Boolean(this.getBlockByPoint(point));
} }
/** /**
@@ -362,7 +370,6 @@ export class SelectionManager implements VirgoSelection {
} }
} }
} }
console.log({ selectedNodes });
return selectedNodes; return selectedNodes;
} }