feat: grid item style
This commit is contained in:
@@ -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',
|
||||||
|
|||||||
@@ -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',
|
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -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',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
});
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user