Merge branch 'develop' into feature/fix-backspace

This commit is contained in:
Qi
2022-08-11 21:49:45 +08:00
committed by GitHub
68 changed files with 1252 additions and 519 deletions

View File

@@ -102,6 +102,12 @@ export const RenderRoot: FC<PropsWithChildren<RenderRootProps>> = ({
editor.getHooks().onRootNodeMouseLeave(event);
};
const onContextmenu = (
event: React.MouseEvent<HTMLDivElement, MouseEvent>
) => {
selectionRef.current?.onContextmenu(event);
};
const onKeyDown: React.KeyboardEventHandler<HTMLDivElement> = event => {
// IMP move into keyboard managers?
editor.getHooks().onRootNodeKeyDown(event);
@@ -165,6 +171,7 @@ export const RenderRoot: FC<PropsWithChildren<RenderRootProps>> = ({
onMouseUp={onMouseUp}
onMouseLeave={onMouseLeave}
onMouseOut={onMouseOut}
onContextMenu={onContextmenu}
onKeyDown={onKeyDown}
onKeyDownCapture={onKeyDownCapture}
onKeyUp={onKeyUp}

View File

@@ -29,6 +29,9 @@ export type SelectionRef = {
onMouseDown: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
onMouseMove: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
onMouseUp: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
onContextmenu: (
event: React.MouseEvent<HTMLDivElement, MouseEvent>
) => void;
};
const getFixedPoint = (
@@ -207,10 +210,17 @@ export const SelectionRect = forwardRef<SelectionRef, SelectionProps>(
scrollManager.stopAutoScroll();
};
const onContextmenu = () => {
if (mouseType.current === 'down') {
onMouseUp();
}
};
useImperativeHandle(ref, () => ({
onMouseDown,
onMouseMove,
onMouseUp,
onContextmenu,
}));
useEffect(() => {

View File

@@ -3,6 +3,8 @@ import { styled } from '@toeverything/components/ui';
import type { AsyncBlock } from '../editor';
import { PendantPopover } from './pendant-popover';
import { PendantRender } from './pendant-render';
import { useRef } from 'react';
import { getRecastItemValue, useRecastBlockMeta } from '../recast-block';
/**
* @deprecated
*/
@@ -14,13 +16,27 @@ export const BlockPendantProvider: FC<PropsWithChildren<BlockTagProps>> = ({
block,
children,
}) => {
const triggerRef = useRef<HTMLDivElement>();
const { getProperties } = useRecastBlockMeta();
const properties = getProperties();
const { getValue } = getRecastItemValue(block);
const showTriggerLine =
properties.filter(property => getValue(property.id)).length === 0;
return (
<Container>
{children}
<PendantPopover block={block}>
<StyledTriggerLine />
</PendantPopover>
{showTriggerLine ? (
<StyledPendantContainer ref={triggerRef}>
<PendantPopover
block={block}
container={triggerRef.current}
>
<StyledTriggerLine />
</PendantPopover>
</StyledPendantContainer>
) : null}
<PendantRender block={block} />
</Container>
@@ -28,7 +44,7 @@ export const BlockPendantProvider: FC<PropsWithChildren<BlockTagProps>> = ({
};
export const LINE_GAP = 16;
const TAG_GAP = 4;
export const TAG_GAP = 4;
const StyledTriggerLine = styled('div')({
padding: `${TAG_GAP}px 0`,
@@ -43,10 +59,12 @@ const StyledTriggerLine = styled('div')({
width: '100%',
height: '2px',
background: '#dadada',
display: 'none',
display: 'flex',
position: 'absolute',
left: '0',
top: '4px',
transition: 'opacity .2s',
opacity: '0',
},
'::after': {
content: "''",
@@ -60,18 +78,24 @@ const StyledTriggerLine = styled('div')({
transition: 'width .3s',
},
});
const Container = styled('div')({
position: 'relative',
paddingBottom: `${LINE_GAP - TAG_GAP * 2}px`,
const StyledPendantContainer = styled('div')({
width: '100px',
'&:hover': {
[StyledTriggerLine.toString()]: {
'&::before': {
display: 'flex',
},
[`${StyledTriggerLine}`]: {
'&::after': {
width: '100%',
},
},
},
});
const Container = styled('div')({
position: 'relative',
padding: `${TAG_GAP * 2}px 0 ${LINE_GAP - TAG_GAP * 4}px 0`,
'&:hover': {
[`${StyledTriggerLine}`]: {
'&::before': {
opacity: '1',
},
},
},
});

View File

@@ -29,6 +29,7 @@ export const PendantHistoryPanel = ({
const [history, setHistory] = useState<RecastBlockValue[]>([]);
const popoverHandlerRef = useRef<{ [key: string]: PopperHandler }>({});
const historyPanelRef = useRef<HTMLDivElement>();
const { getValueHistory } = getRecastItemValue(block);
useEffect(() => {
@@ -84,7 +85,7 @@ export const PendantHistoryPanel = ({
}, [block, getProperties, groupBlock, recastBlock]);
return (
<StyledPendantHistoryPanel>
<StyledPendantHistoryPanel ref={historyPanelRef}>
{history.map(item => {
const property = getProperty(item.id);
return (
@@ -116,6 +117,7 @@ export const PendantHistoryPanel = ({
/>
}
trigger="click"
container={historyPanelRef.current}
>
<PendantTag
style={{

View File

@@ -1,5 +1,11 @@
import React, { useState, useEffect } from 'react';
import { Input, Option, Select, Tooltip } from '@toeverything/components/ui';
import {
Input,
message,
Option,
Select,
Tooltip,
} from '@toeverything/components/ui';
import { HelpCenterIcon } from '@toeverything/components/icons';
import { AsyncBlock } from '../../editor';
@@ -18,6 +24,7 @@ import {
generateRandomFieldName,
generateInitialOptions,
getPendantConfigByType,
checkPendantForm,
} from '../utils';
import { useOnCreateSure } from './hooks';
@@ -74,7 +81,7 @@ export const CreatePendantPanel = ({
setFieldName(e.target.value);
}}
endAdornment={
<Tooltip content="Help info here">
<Tooltip content="Help info here" placement="top">
<StyledInputEndAdornment>
<HelpCenterIcon />
</StyledInputEndAdornment>
@@ -98,6 +105,17 @@ export const CreatePendantPanel = ({
)}
iconConfig={getPendantConfigByType(selectedOption.type)}
onSure={async (type, newPropertyItem, newValue) => {
const checkResult = checkPendantForm(
type,
fieldName,
newPropertyItem,
newValue
);
if (!checkResult.passed) {
await message.error(checkResult.message);
return;
}
await onCreateSure({
type,
newPropertyItem,

View File

@@ -1,5 +1,5 @@
import { useState } from 'react';
import { Input, Tooltip } from '@toeverything/components/ui';
import { Input, message, Tooltip } from '@toeverything/components/ui';
import { HelpCenterIcon } from '@toeverything/components/icons';
import { PendantModifyPanel } from '../pendant-modify-panel';
import type { AsyncBlock } from '../../editor';
@@ -8,7 +8,7 @@ import {
type RecastBlockValue,
type RecastMetaProperty,
} from '../../recast-block';
import { getPendantConfigByType } from '../utils';
import { checkPendantForm, getPendantConfigByType } from '../utils';
import {
StyledPopoverWrapper,
StyledOperationLabel,
@@ -70,7 +70,7 @@ export const UpdatePendantPanel = ({
setFieldName(e.target.value);
}}
endAdornment={
<Tooltip content="Help info here">
<Tooltip content="Help info here" placement="top">
<StyledInputEndAdornment>
<HelpCenterIcon />
</StyledInputEndAdornment>
@@ -98,6 +98,17 @@ export const UpdatePendantPanel = ({
property={property}
type={property.type}
onSure={async (type, newPropertyItem, newValue) => {
const checkResult = checkPendantForm(
type,
fieldName,
newPropertyItem,
newValue
);
if (!checkResult.passed) {
await message.error(checkResult.message);
return;
}
await onUpdateSure({
type,
newPropertyItem,

View File

@@ -23,12 +23,7 @@ import {
PendantTypes,
type TempInformationType,
} from '../types';
import {
checkPendantForm,
getOfficialSelected,
getPendantConfigByType,
} from '../utils';
import { message } from '@toeverything/components/ui';
import { getOfficialSelected, getPendantConfigByType } from '../utils';
type SelectPropertyType = MultiSelectProperty | SelectProperty;
type SureParams = {
@@ -56,18 +51,6 @@ export const useOnCreateSure = ({ block }: { block: AsyncBlock }) => {
newPropertyItem,
newValue,
}: SureParams) => {
const checkResult = checkPendantForm(
type,
fieldName,
newPropertyItem,
newValue
);
if (!checkResult.passed) {
await message.error(checkResult.message);
return;
}
if (
type === PendantTypes.MultiSelect ||
type === PendantTypes.Select ||
@@ -181,18 +164,6 @@ export const useOnUpdateSure = ({
newPropertyItem,
newValue,
}: SureParams) => {
const checkResult = checkPendantForm(
type,
fieldName,
newPropertyItem,
newValue
);
if (!checkResult.passed) {
await message.error(checkResult.message);
return;
}
if (
type === PendantTypes.MultiSelect ||
type === PendantTypes.Select ||

View File

@@ -26,6 +26,7 @@ export const PendantPopover: FC<
block={block}
endElement={
<AddPendantPopover
container={popoverProps.container}
block={block}
onSure={() => {
popoverHandlerRef.current?.setVisible(false);

View File

@@ -105,6 +105,8 @@ export const PendantRender = ({ block }: { block: AsyncBlock }) => {
<AddPendantPopover
block={block}
iconStyle={{ marginTop: 4 }}
trigger="click"
// trigger={isKanbanView ? 'hover' : 'click'}
container={blockRenderContainerRef.current}
/>
</div>

View File

@@ -162,7 +162,7 @@ export class BlockCommands {
public async moveInNewGridItem(
blockId: string,
gridItemId: string,
isBefore = false
type = GridDropType.left
) {
const block = await this._editor.getBlockById(blockId);
if (block) {
@@ -175,7 +175,7 @@ export class BlockCommands {
await block.remove();
await gridItemBlock.append(block);
if (targetGridItemBlock && gridItemBlock) {
if (isBefore) {
if (type === GridDropType.left) {
await targetGridItemBlock.before(gridItemBlock);
} else {
await targetGridItemBlock.after(gridItemBlock);

View File

@@ -95,6 +95,9 @@ export class DragDropManager {
}
private async _handleDropBlock(event: React.DragEvent<Element>) {
const targetBlock = await this._editor.getBlockById(
this._blockDragTargetId
);
if (this._blockDragDirection !== BlockDropPlacement.none) {
const blockId = event.dataTransfer.getData(this._blockIdKey);
if (!(await this._canBeDrop(event))) return;
@@ -109,13 +112,24 @@ export class DragDropManager {
this._blockDragDirection
)
) {
await this._editor.commands.blockCommands.createLayoutBlock(
blockId,
this._blockDragTargetId,
const dropType =
this._blockDragDirection === BlockDropPlacement.left
? GridDropType.left
: GridDropType.right
);
: GridDropType.right;
// if target is a grid item create grid item
if (targetBlock.type !== Protocol.Block.Type.gridItem) {
await this._editor.commands.blockCommands.createLayoutBlock(
blockId,
this._blockDragTargetId,
dropType
);
} else {
await this._editor.commands.blockCommands.moveInNewGridItem(
blockId,
this._blockDragTargetId,
dropType
);
}
}
if (
[
@@ -123,9 +137,6 @@ export class DragDropManager {
BlockDropPlacement.outerRight,
].includes(this._blockDragDirection)
) {
const targetBlock = await this._editor.getBlockById(
this._blockDragTargetId
);
if (targetBlock.type !== Protocol.Block.Type.grid) {
await this._editor.commands.blockCommands.createLayoutBlock(
blockId,
@@ -154,7 +165,7 @@ export class DragDropManager {
await this._editor.commands.blockCommands.moveInNewGridItem(
blockId,
gridItems[0].id,
true
GridDropType.right
);
}
}
@@ -347,10 +358,10 @@ export class DragDropManager {
blockId: string
) {
const { clientX, clientY } = event;
this._setBlockDragTargetId(blockId);
const path = await this._editor.getBlockPath(blockId);
const mousePoint = new Point(clientX, clientY);
const rect = domToRect(blockDom);
let targetBlock: AsyncBlock = path[path.length - 1];
/**
* IMP: compute the level of the target block
* future feature drag drop has level support do not delete
@@ -386,13 +397,30 @@ export class DragDropManager {
const gridBlocks = path.filter(
block => block.type === Protocol.Block.Type.grid
);
// limit grid block floor counts, when drag block to init grid
if (gridBlocks.length >= MAX_GRID_BLOCK_FLOOR) {
const parentBlock = path[path.length - 2];
// a new grid should not be grid item`s child
if (
parentBlock &&
parentBlock.type === Protocol.Block.Type.gridItem
) {
targetBlock = parentBlock;
// gridItem`s parent must be grid block
const gridItemCounts = (await path[path.length - 3].children())
.length;
if (
gridItemCounts >=
this._editor.configManager.grid.maxGridItemCount
) {
direction = BlockDropPlacement.none;
}
// limit grid block floor counts, when drag block to init grid
} else if (gridBlocks.length >= MAX_GRID_BLOCK_FLOOR) {
direction = BlockDropPlacement.none;
}
}
this._setBlockDragTargetId(targetBlock.id);
this._setBlockDragDirection(direction);
return direction;
return { direction, block: targetBlock };
}
public handlerEditorDrop(event: React.DragEvent<Element>) {