feat: Intra-line double link interaction
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
/* eslint-disable max-lines */
|
/* eslint-disable max-lines */
|
||||||
import { SearchIcon } from '@toeverything/components/icons';
|
|
||||||
import { ErrorBoundary, isEqual } from '@toeverything/utils';
|
import { ErrorBoundary, isEqual } from '@toeverything/utils';
|
||||||
import isHotkey from 'is-hotkey';
|
import isHotkey from 'is-hotkey';
|
||||||
import isUrl from 'is-url';
|
import isUrl from 'is-url';
|
||||||
@@ -844,8 +843,7 @@ const EditorLeaf = ({ attributes, children, leaf }: any) => {
|
|||||||
|
|
||||||
if (leaf.doubleLinkSearch) {
|
if (leaf.doubleLinkSearch) {
|
||||||
customChildren = (
|
customChildren = (
|
||||||
<span style={{ backgroundColor: '#eee' }}>
|
<span style={{ backgroundColor: '#eee', borderRadius: '4px' }}>
|
||||||
<SearchIcon style={{ width: '16px', height: '16px' }} />
|
|
||||||
{customChildren}
|
{customChildren}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -166,7 +166,6 @@ export const DoubleLinkMenuContainer = ({
|
|||||||
|
|
||||||
const RootContainer = styled('div')(({ theme }) => ({
|
const RootContainer = styled('div')(({ theme }) => ({
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
maxHeight: '525px',
|
|
||||||
borderRadius: '10px',
|
borderRadius: '10px',
|
||||||
boxShadow: theme.affine.shadows.shadow1,
|
boxShadow: theme.affine.shadows.shadow1,
|
||||||
backgroundColor: '#fff',
|
backgroundColor: '#fff',
|
||||||
@@ -176,5 +175,5 @@ const RootContainer = styled('div')(({ theme }) => ({
|
|||||||
const ContentContainer = styled('div')(({ theme }) => ({
|
const ContentContainer = styled('div')(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
maxHeight: '493px',
|
maxHeight: '300px',
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export const DoubleLinkMenu = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const [curBlockId, setCurBlockId] = useState<string>();
|
const [curBlockId, setCurBlockId] = useState<string>();
|
||||||
const [searchText, setSearchText] = useState<string>('');
|
const [searchText, setSearchText] = useState<string>();
|
||||||
const [inAddNewPage, setInAddNewPage] = useState(false);
|
const [inAddNewPage, setInAddNewPage] = useState(false);
|
||||||
const [filterText, setFilterText] = useState<string>('');
|
const [filterText, setFilterText] = useState<string>('');
|
||||||
const [searchResultBlocks, setSearchResultBlocks] = useState<QueryResult>(
|
const [searchResultBlocks, setSearchResultBlocks] = useState<QueryResult>(
|
||||||
@@ -85,7 +85,13 @@ export const DoubleLinkMenu = ({
|
|||||||
});
|
});
|
||||||
items.push(
|
items.push(
|
||||||
...(searchResultBlocks?.map(
|
...(searchResultBlocks?.map(
|
||||||
block => ({ block } as CommonListItem)
|
block =>
|
||||||
|
({
|
||||||
|
block: {
|
||||||
|
...block,
|
||||||
|
content: block.content || 'Untitled',
|
||||||
|
},
|
||||||
|
} as CommonListItem)
|
||||||
) || [])
|
) || [])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -199,11 +205,32 @@ export const DoubleLinkMenu = ({
|
|||||||
|
|
||||||
const handleKeyDown = useCallback(
|
const handleKeyDown = useCallback(
|
||||||
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||||
|
if (!isOpen) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (event.code === 'Escape') {
|
if (event.code === 'Escape') {
|
||||||
hideMenu();
|
hideMenu();
|
||||||
}
|
}
|
||||||
|
const { type, anchorNode } = editor.selection.currentSelectInfo;
|
||||||
|
if (
|
||||||
|
type === 'Range' &&
|
||||||
|
anchorNode &&
|
||||||
|
editor.blockHelper.isSelectionCollapsed(anchorNode.id)
|
||||||
|
) {
|
||||||
|
const text = editor.blockHelper.getBlockTextBeforeSelection(
|
||||||
|
anchorNode.id
|
||||||
|
);
|
||||||
|
if (text.endsWith('[[')) {
|
||||||
|
if (event.key === 'Backspace') {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
hideMenu();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[hideMenu]
|
[hideMenu, editor, isOpen]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
import { useCallback, useEffect, useState } from 'react';
|
|
||||||
import { useNavigate, useParams } from 'react-router';
|
|
||||||
import style9 from 'style9';
|
|
||||||
|
|
||||||
import { BlockPreview } from '@toeverything/components/common';
|
import { BlockPreview } from '@toeverything/components/common';
|
||||||
import {
|
import {
|
||||||
TransitionsModal,
|
|
||||||
MuiBox as Box,
|
MuiBox as Box,
|
||||||
MuiBox,
|
MuiBox,
|
||||||
styled,
|
styled,
|
||||||
|
TransitionsModal,
|
||||||
} from '@toeverything/components/ui';
|
} from '@toeverything/components/ui';
|
||||||
import { Virgo, BlockEditor } from '@toeverything/framework/virgo';
|
import { BlockEditor, Virgo } from '@toeverything/framework/virgo';
|
||||||
import { throttle } from '@toeverything/utils';
|
import { throttle } from '@toeverything/utils';
|
||||||
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { useNavigate, useParams } from 'react-router';
|
||||||
|
import style9 from 'style9';
|
||||||
|
|
||||||
const styles = style9.create({
|
const styles = style9.create({
|
||||||
wrapper: {
|
wrapper: {
|
||||||
@@ -37,9 +36,7 @@ const query_blocks = (
|
|||||||
search: string,
|
search: string,
|
||||||
callback: (result: QueryResult) => void
|
callback: (result: QueryResult) => void
|
||||||
) => {
|
) => {
|
||||||
(editor as BlockEditor)
|
(editor as BlockEditor).search(search).then(pages => callback(pages));
|
||||||
.search(search)
|
|
||||||
.then(pages => callback(pages.filter(b => !!b.content)));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const QueryBlocks = throttle(query_blocks, 500);
|
export const QueryBlocks = throttle(query_blocks, 500);
|
||||||
|
|||||||
Reference in New Issue
Block a user