merge develop to fix/bugs
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import en from './en.json';
|
import en from './en.json';
|
||||||
import es from './es.json';
|
import es from './es.json';
|
||||||
import zh_Hans from './zh.json';
|
import zh_Hans from './zh.json';
|
||||||
|
import zh_Hant from './zh-Hant.json';
|
||||||
|
|
||||||
export const LOCALES = [
|
export const LOCALES = [
|
||||||
{
|
{
|
||||||
@@ -15,6 +16,12 @@ export const LOCALES = [
|
|||||||
originalName: '简体中文',
|
originalName: '简体中文',
|
||||||
res: zh_Hans,
|
res: zh_Hans,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Traditional Chinese',
|
||||||
|
tag: 'zh-Hant',
|
||||||
|
originalName: '繁體中文',
|
||||||
|
res: zh_Hant,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Spanish',
|
name: 'Spanish',
|
||||||
tag: 'es',
|
tag: 'es',
|
||||||
|
|||||||
39
apps/venus/src/app/i18n/resources/zh-Hant.json
Normal file
39
apps/venus/src/app/i18n/resources/zh-Hant.json
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"Blog": "博客",
|
||||||
|
"AboutUs": "關於我們",
|
||||||
|
"Open Source": "開源",
|
||||||
|
"Docs": "文檔",
|
||||||
|
"Feedback": "反饋",
|
||||||
|
"ContactUs": "聯繫我們",
|
||||||
|
"Privacy First": "隱私第一",
|
||||||
|
"Alternative": "的另一種選擇",
|
||||||
|
"Check GitHub": "在 Github 中查看",
|
||||||
|
"GitHub": "GitHub",
|
||||||
|
"Try it Online": "在線嘗試",
|
||||||
|
"language": "語言",
|
||||||
|
"description1": {
|
||||||
|
"part1": "Affine 是面向專業用戶的下一代協同知識庫",
|
||||||
|
"part2": "Affine 不僅僅集合着文檔、白板和表格。",
|
||||||
|
"part3": "隨心所欲切換構塊模式。",
|
||||||
|
"part4": "告別冗余,存儲數據一次就好,放在任何您想要的位置。"
|
||||||
|
},
|
||||||
|
"description2": {
|
||||||
|
"part1": "塑形您的頁面",
|
||||||
|
"part2": "隨時隨地,文檔、看板、數據庫都完全可用。真正“所見即所得”的數據處理環境。",
|
||||||
|
"part3": "所有頁面都配備文檔(紙張模式)和白板(無邊緣模式)視圖。"
|
||||||
|
},
|
||||||
|
"description3": {
|
||||||
|
"part1": "計畫您的任務",
|
||||||
|
"part2": "多視圖管理不再混亂。",
|
||||||
|
"part3": "既可使用 Markdown 設置 TODO,又可無縫在看板視圖中編輯。",
|
||||||
|
"part4": "管理多維表格本當易如反掌——攜手Affine,确实易如反掌"
|
||||||
|
},
|
||||||
|
"description4": {
|
||||||
|
"part1": "隱私第一,合作無間,毫不妥協。",
|
||||||
|
"part2": "我們不喜歡被軟件綁架,您也是。我們的任何努力雖建立在尊重用戶隱私基礎上,也游刃有餘。這解釋了為什麼我們毫不妥協。",
|
||||||
|
"part3": "您創造的數據屬於您,安全永久存儲在本地供您隨時調用。同時您也能盡享協同的便利,無需雲設置就能實時編輯、共享給他人。"
|
||||||
|
},
|
||||||
|
"BuildFor": "構建一個開放和語義化的未來",
|
||||||
|
"KeepUpdated": "持續更新在",
|
||||||
|
"Join": "加入我們的社群"
|
||||||
|
}
|
||||||
@@ -38,13 +38,13 @@ export const createEditor = (
|
|||||||
views: {
|
views: {
|
||||||
[Protocol.Block.Type.page]: new PageBlock(),
|
[Protocol.Block.Type.page]: new PageBlock(),
|
||||||
[Protocol.Block.Type.reference]: new RefLinkBlock(),
|
[Protocol.Block.Type.reference]: new RefLinkBlock(),
|
||||||
|
[Protocol.Block.Type.code]: new CodeBlock(),
|
||||||
[Protocol.Block.Type.text]: new TextBlock(),
|
[Protocol.Block.Type.text]: new TextBlock(),
|
||||||
[Protocol.Block.Type.heading1]: new Heading1Block(),
|
[Protocol.Block.Type.heading1]: new Heading1Block(),
|
||||||
[Protocol.Block.Type.heading2]: new Heading2Block(),
|
[Protocol.Block.Type.heading2]: new Heading2Block(),
|
||||||
[Protocol.Block.Type.heading3]: new Heading3Block(),
|
[Protocol.Block.Type.heading3]: new Heading3Block(),
|
||||||
[Protocol.Block.Type.quote]: new QuoteBlock(),
|
[Protocol.Block.Type.quote]: new QuoteBlock(),
|
||||||
[Protocol.Block.Type.todo]: new TodoBlock(),
|
[Protocol.Block.Type.todo]: new TodoBlock(),
|
||||||
[Protocol.Block.Type.code]: new CodeBlock(),
|
|
||||||
// [Protocol.Block.Type.toc]: new TocBlock(),
|
// [Protocol.Block.Type.toc]: new TocBlock(),
|
||||||
[Protocol.Block.Type.file]: new FileBlock(),
|
[Protocol.Block.Type.file]: new FileBlock(),
|
||||||
[Protocol.Block.Type.image]: new ImageBlock(),
|
[Protocol.Block.Type.image]: new ImageBlock(),
|
||||||
|
|||||||
@@ -39,14 +39,6 @@ type MenuItemsProps = {
|
|||||||
|
|
||||||
export const CommonList = (props: MenuItemsProps) => {
|
export const CommonList = (props: MenuItemsProps) => {
|
||||||
const { items, currentItem, setCurrentItem, onSelected } = props;
|
const { items, currentItem, setCurrentItem, onSelected } = props;
|
||||||
// const JSONUnsupportedBlockTypes = useFlag('JSONUnsupportedBlockTypes', [
|
|
||||||
// 'page',
|
|
||||||
// ]);
|
|
||||||
// TODO Insert bidirectional link to be developed
|
|
||||||
const JSONUnsupportedBlockTypes = ['page'];
|
|
||||||
const usedItems = items.filter(item => {
|
|
||||||
return !JSONUnsupportedBlockTypes.includes(item?.content?.id);
|
|
||||||
});
|
|
||||||
return (
|
return (
|
||||||
<div className={clsx(styles('root_container'), props.className)}>
|
<div className={clsx(styles('root_container'), props.className)}>
|
||||||
<div
|
<div
|
||||||
@@ -55,8 +47,8 @@ export const CommonList = (props: MenuItemsProps) => {
|
|||||||
commonListContainer,
|
commonListContainer,
|
||||||
])}
|
])}
|
||||||
>
|
>
|
||||||
{usedItems?.length ? (
|
{items?.length ? (
|
||||||
usedItems.map((item, idx) => {
|
items.map((item, idx) => {
|
||||||
if (item.renderCustom) {
|
if (item.renderCustom) {
|
||||||
return item.renderCustom(item);
|
return item.renderCustom(item);
|
||||||
} else if (item.block) {
|
} else if (item.block) {
|
||||||
|
|||||||
@@ -38,7 +38,8 @@
|
|||||||
"react-window": "^1.8.7",
|
"react-window": "^1.8.7",
|
||||||
"slate": "^0.81.1",
|
"slate": "^0.81.1",
|
||||||
"slate-react": "^0.81.0",
|
"slate-react": "^0.81.0",
|
||||||
"style9": "^0.14.0"
|
"style9": "^0.14.0",
|
||||||
|
"html-escaper": "^3.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/codemirror": "^5.60.5",
|
"@types/codemirror": "^5.60.5",
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ export const CodeView = ({ block, editor }: CreateCodeView) => {
|
|||||||
};
|
};
|
||||||
const handleLangChange = (lang: string) => {
|
const handleLangChange = (lang: string) => {
|
||||||
block.setProperty('lang', lang);
|
block.setProperty('lang', lang);
|
||||||
setExtensions([langs[lang]()]);
|
langs[lang] && setExtensions([langs[lang]()]);
|
||||||
};
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleLangChange(langType ? langType : DEFAULT_LANG);
|
handleLangChange(langType ? langType : DEFAULT_LANG);
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import {
|
|||||||
BlockEditor,
|
BlockEditor,
|
||||||
HTML2BlockResult,
|
HTML2BlockResult,
|
||||||
} from '@toeverything/framework/virgo';
|
} from '@toeverything/framework/virgo';
|
||||||
|
import { unescape } from 'html-escaper';
|
||||||
import {
|
import {
|
||||||
Block2HtmlProps,
|
Block2HtmlProps,
|
||||||
commonBlock2HtmlContent,
|
commonBlock2HtmlContent,
|
||||||
commonHTML2block,
|
|
||||||
} from '../../utils/commonBlockClip';
|
} from '../../utils/commonBlockClip';
|
||||||
import { CodeView } from './CodeView';
|
import { CodeView } from './CodeView';
|
||||||
|
|
||||||
@@ -34,12 +34,30 @@ export class CodeBlock extends BaseView {
|
|||||||
element: Element;
|
element: Element;
|
||||||
editor: BlockEditor;
|
editor: BlockEditor;
|
||||||
}): Promise<HTML2BlockResult> {
|
}): Promise<HTML2BlockResult> {
|
||||||
return commonHTML2block({
|
// debugger;
|
||||||
element,
|
if (element.tagName === 'CODE') {
|
||||||
editor,
|
return [
|
||||||
type: this.type,
|
{
|
||||||
tagName: 'CODE',
|
type: this.type,
|
||||||
});
|
properties: {
|
||||||
|
text: {
|
||||||
|
value: [
|
||||||
|
{
|
||||||
|
text: unescape(
|
||||||
|
(element as HTMLElement).innerText
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
lang:
|
||||||
|
element.classList[0] &&
|
||||||
|
element.classList[0].substr(9),
|
||||||
|
},
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
override async block2html(props: Block2HtmlProps) {
|
override async block2html(props: Block2HtmlProps) {
|
||||||
|
|||||||
@@ -168,7 +168,9 @@ export const ImageView = ({ block, editor }: ImageView) => {
|
|||||||
<BlockPendantProvider editor={editor} block={block}>
|
<BlockPendantProvider editor={editor} block={block}>
|
||||||
<ImageBlock>
|
<ImageBlock>
|
||||||
<div style={{ position: 'relative' }} ref={resizeBox}>
|
<div style={{ position: 'relative' }} ref={resizeBox}>
|
||||||
{!isSelect ? <ImageShade onClick={handleClick} /> : null}
|
{!isSelect && imgUrl ? (
|
||||||
|
<ImageShade onClick={handleClick} />
|
||||||
|
) : null}
|
||||||
{imgUrl ? (
|
{imgUrl ? (
|
||||||
<div
|
<div
|
||||||
onMouseDown={e => {
|
onMouseDown={e => {
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import {
|
|
||||||
BaseView,
|
|
||||||
CreateView,
|
|
||||||
AsyncBlock,
|
|
||||||
HTML2BlockResult,
|
|
||||||
BlockEditor,
|
|
||||||
} from '@toeverything/framework/virgo';
|
|
||||||
import { Protocol } from '@toeverything/datasource/db-service';
|
import { Protocol } from '@toeverything/datasource/db-service';
|
||||||
import { TextView } from './TextView';
|
import {
|
||||||
|
AsyncBlock,
|
||||||
|
BaseView,
|
||||||
|
BlockEditor,
|
||||||
|
CreateView,
|
||||||
|
HTML2BlockResult,
|
||||||
|
} from '@toeverything/framework/virgo';
|
||||||
import {
|
import {
|
||||||
Block2HtmlProps,
|
Block2HtmlProps,
|
||||||
commonBlock2HtmlContent,
|
commonBlock2HtmlContent,
|
||||||
commonHTML2block,
|
commonHTML2block,
|
||||||
} from '../../utils/commonBlockClip';
|
} from '../../utils/commonBlockClip';
|
||||||
|
import { TextView } from './TextView';
|
||||||
|
|
||||||
export class TextBlock extends BaseView {
|
export class TextBlock extends BaseView {
|
||||||
type = Protocol.Block.Type.text;
|
type = Protocol.Block.Type.text;
|
||||||
@@ -41,12 +41,12 @@ export class TextBlock extends BaseView {
|
|||||||
tagName: [
|
tagName: [
|
||||||
'DIV',
|
'DIV',
|
||||||
'P',
|
'P',
|
||||||
'PRE',
|
// 'PRE',
|
||||||
'B',
|
'B',
|
||||||
'A',
|
'A',
|
||||||
'EM',
|
'EM',
|
||||||
'U',
|
'U',
|
||||||
'CODE',
|
// 'CODE',
|
||||||
'S',
|
'S',
|
||||||
'DEL',
|
'DEL',
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
|
|
||||||
import { CustomText, TextProps } from '@toeverything/components/common';
|
import { CustomText, TextProps } from '@toeverything/components/common';
|
||||||
import {
|
import {
|
||||||
BlockPendantProvider,
|
BlockPendantProvider,
|
||||||
@@ -11,9 +9,11 @@ import {
|
|||||||
import { styled } from '@toeverything/components/ui';
|
import { styled } from '@toeverything/components/ui';
|
||||||
import { Protocol } from '@toeverything/datasource/db-service';
|
import { Protocol } from '@toeverything/datasource/db-service';
|
||||||
import { CreateView } from '@toeverything/framework/virgo';
|
import { CreateView } from '@toeverything/framework/virgo';
|
||||||
|
import { useState } from 'react';
|
||||||
import { BlockContainer } from '../../components/BlockContainer';
|
import { BlockContainer } from '../../components/BlockContainer';
|
||||||
import { TextManage } from '../../components/text-manage';
|
import { TextManage } from '../../components/text-manage';
|
||||||
import { dedentBlock, tabBlock } from '../../utils/indent';
|
import { dedentBlock, tabBlock } from '../../utils/indent';
|
||||||
|
|
||||||
interface CreateTextView extends CreateView {
|
interface CreateTextView extends CreateView {
|
||||||
// TODO: need to optimize
|
// TODO: need to optimize
|
||||||
containerClassName?: string;
|
containerClassName?: string;
|
||||||
@@ -247,6 +247,9 @@ export const TextView = ({
|
|||||||
await block.setProperty('text', {
|
await block.setProperty('text', {
|
||||||
value: options?.['text'] as CustomText[],
|
value: options?.['text'] as CustomText[],
|
||||||
});
|
});
|
||||||
|
setTimeout(async () => {
|
||||||
|
await editor.selectionManager.activeNodeByNodeId(block.id);
|
||||||
|
}, 100);
|
||||||
block.firstCreateFlag = true;
|
block.firstCreateFlag = true;
|
||||||
};
|
};
|
||||||
const onTab: TextProps['handleTab'] = async ({ isShiftKey }) => {
|
const onTab: TextProps['handleTab'] = async ({ isShiftKey }) => {
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
|
import { Protocol } from '@toeverything/datasource/db-service';
|
||||||
|
import { AsyncBlock } from '../block';
|
||||||
import { Editor } from '../editor';
|
import { Editor } from '../editor';
|
||||||
import { SelectBlock, SelectInfo } from '../selection';
|
import { SelectBlock, SelectInfo } from '../selection';
|
||||||
import { AsyncBlock } from '../block';
|
|
||||||
import { ClipBlockInfo, OFFICE_CLIPBOARD_MIMETYPE } from './types';
|
|
||||||
import { Clip } from './clip';
|
import { Clip } from './clip';
|
||||||
|
import { ClipBlockInfo, OFFICE_CLIPBOARD_MIMETYPE } from './types';
|
||||||
import {
|
import {
|
||||||
commonHTML2Block,
|
commonHTML2Block,
|
||||||
commonHTML2Text,
|
commonHTML2Text,
|
||||||
getIsTextLink,
|
getIsTextLink,
|
||||||
linkText2Block,
|
linkText2Block,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
|
||||||
export class ClipboardUtils {
|
export class ClipboardUtils {
|
||||||
private _editor: Editor;
|
private _editor: Editor;
|
||||||
constructor(editor: Editor) {
|
constructor(editor: Editor) {
|
||||||
@@ -161,12 +161,37 @@ export class ClipboardUtils {
|
|||||||
return this.convertHtml2Blocks(htmlEl);
|
return this.convertHtml2Blocks(htmlEl);
|
||||||
}
|
}
|
||||||
async convertHtml2Blocks(element: Element): Promise<ClipBlockInfo[]> {
|
async convertHtml2Blocks(element: Element): Promise<ClipBlockInfo[]> {
|
||||||
const editableViews = this._editor.getEditableViews();
|
// const editableViews = this._editor.getEditableViews();
|
||||||
// 如果block能够捕捉htmlElement则返回block的html2block
|
// 如果block能够捕捉htmlElement则返回block的html2block
|
||||||
|
const CONVERT_SORT_LIST = [
|
||||||
|
Protocol.Block.Type.page,
|
||||||
|
Protocol.Block.Type.reference,
|
||||||
|
Protocol.Block.Type.code,
|
||||||
|
Protocol.Block.Type.text,
|
||||||
|
Protocol.Block.Type.heading1,
|
||||||
|
Protocol.Block.Type.heading2,
|
||||||
|
Protocol.Block.Type.heading3,
|
||||||
|
Protocol.Block.Type.quote,
|
||||||
|
Protocol.Block.Type.todo,
|
||||||
|
Protocol.Block.Type.file,
|
||||||
|
Protocol.Block.Type.image,
|
||||||
|
Protocol.Block.Type.divider,
|
||||||
|
Protocol.Block.Type.callout,
|
||||||
|
Protocol.Block.Type.youtube,
|
||||||
|
Protocol.Block.Type.figma,
|
||||||
|
Protocol.Block.Type.group,
|
||||||
|
Protocol.Block.Type.embedLink,
|
||||||
|
Protocol.Block.Type.numbered,
|
||||||
|
Protocol.Block.Type.bullet,
|
||||||
|
Protocol.Block.Type.grid,
|
||||||
|
Protocol.Block.Type.gridItem,
|
||||||
|
Protocol.Block.Type.groupDivider,
|
||||||
|
];
|
||||||
|
|
||||||
const [clipBlockInfos] = (
|
const [clipBlockInfos] = (
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
editableViews.map(editableView => {
|
CONVERT_SORT_LIST.map(type => {
|
||||||
return editableView?.html2block?.({
|
return this._editor.getView(type)?.html2block?.({
|
||||||
editor: this._editor,
|
editor: this._editor,
|
||||||
element: element,
|
element: element,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import { StrictMode } from 'react';
|
import { StrictMode } from 'react';
|
||||||
import { createRoot, type Root } from 'react-dom/client';
|
|
||||||
|
|
||||||
import { BasePlugin } from '../../base-plugin';
|
import { BasePlugin } from '../../base-plugin';
|
||||||
import { CommandMenu } from './Menu';
|
|
||||||
import { PluginRenderRoot } from '../../utils';
|
import { PluginRenderRoot } from '../../utils';
|
||||||
|
import { CommandMenu } from './Menu';
|
||||||
|
|
||||||
const PLUGIN_NAME = 'command-menu';
|
const PLUGIN_NAME = 'command-menu';
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,24 @@
|
|||||||
import React, {
|
import React, {
|
||||||
useEffect,
|
|
||||||
useState,
|
|
||||||
useMemo,
|
|
||||||
useCallback,
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
useRef,
|
useRef,
|
||||||
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import style9 from 'style9';
|
|
||||||
|
|
||||||
import { BlockFlavorKeys } from '@toeverything/datasource/db-service';
|
|
||||||
import { Virgo, PluginHooks, HookType } from '@toeverything/framework/virgo';
|
|
||||||
import {
|
import {
|
||||||
CommonList,
|
CommonList,
|
||||||
CommonListItem,
|
|
||||||
commonListContainer,
|
commonListContainer,
|
||||||
|
CommonListItem,
|
||||||
} from '@toeverything/components/common';
|
} from '@toeverything/components/common';
|
||||||
|
import { BlockFlavorKeys } from '@toeverything/datasource/db-service';
|
||||||
|
import { HookType, PluginHooks, Virgo } from '@toeverything/framework/virgo';
|
||||||
import { domToRect } from '@toeverything/utils';
|
import { domToRect } from '@toeverything/utils';
|
||||||
|
|
||||||
import { MenuCategories } from './Categories';
|
import { styled } from '@toeverything/components/ui';
|
||||||
import { menuItemsMap, CommandMenuCategories } from './config';
|
|
||||||
import { QueryResult } from '../../search';
|
import { QueryResult } from '../../search';
|
||||||
import {
|
import { MenuCategories } from './Categories';
|
||||||
MuiClickAwayListener as ClickAwayListener,
|
import { CommandMenuCategories, menuItemsMap } from './config';
|
||||||
styled,
|
|
||||||
} from '@toeverything/components/ui';
|
|
||||||
|
|
||||||
const RootContainer = styled('div')(({ theme }) => {
|
const RootContainer = styled('div')(({ theme }) => {
|
||||||
return {
|
return {
|
||||||
@@ -134,59 +130,75 @@ export const CommandMenuContainer = ({
|
|||||||
|
|
||||||
const handleClickUp = useCallback(
|
const handleClickUp = useCallback(
|
||||||
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||||
if (isShow && types && event.code === 'ArrowUp') {
|
event.preventDefault();
|
||||||
event.preventDefault();
|
if (!currentItem && types.length) {
|
||||||
if (!currentItem && types.length) {
|
setCurrentItem(types[types.length - 1]);
|
||||||
setCurrentItem(types[types.length - 1]);
|
}
|
||||||
}
|
if (currentItem) {
|
||||||
if (currentItem) {
|
const idx = types.indexOf(currentItem);
|
||||||
const idx = types.indexOf(currentItem);
|
if (idx > 0) {
|
||||||
if (idx > 0) {
|
setNeedCheckIntoView(true);
|
||||||
setNeedCheckIntoView(true);
|
setCurrentItem(types[idx - 1]);
|
||||||
setCurrentItem(types[idx - 1]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[isShow, types, currentItem]
|
[types, currentItem]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleClickDown = useCallback(
|
const handleClickDown = useCallback(
|
||||||
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||||
if (isShow && types && event.code === 'ArrowDown') {
|
event.preventDefault();
|
||||||
event.preventDefault();
|
if (!currentItem && types.length) {
|
||||||
if (!currentItem && types.length) {
|
setCurrentItem(types[0]);
|
||||||
setCurrentItem(types[0]);
|
}
|
||||||
}
|
if (currentItem) {
|
||||||
if (currentItem) {
|
const idx = types.indexOf(currentItem);
|
||||||
const idx = types.indexOf(currentItem);
|
if (idx < types.length - 1) {
|
||||||
if (idx < types.length - 1) {
|
setNeedCheckIntoView(true);
|
||||||
setNeedCheckIntoView(true);
|
setCurrentItem(types[idx + 1]);
|
||||||
setCurrentItem(types[idx + 1]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[isShow, types, currentItem]
|
[types, currentItem]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleClickEnter = useCallback(
|
const handleClickEnter = useCallback(
|
||||||
async (event: React.KeyboardEvent<HTMLDivElement>) => {
|
async (event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||||
if (isShow && event.code === 'Enter' && currentItem) {
|
event.preventDefault();
|
||||||
event.preventDefault();
|
onSelected && onSelected(currentItem);
|
||||||
onSelected && onSelected(currentItem);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
[isShow, currentItem, onSelected]
|
[currentItem, onSelected]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleKeyDown = useCallback(
|
const handleKeyDown = useCallback(
|
||||||
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||||
handleClickUp(event);
|
if (!isShow) {
|
||||||
handleClickDown(event);
|
return;
|
||||||
handleClickEnter(event);
|
}
|
||||||
|
if (event.nativeEvent.isComposing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (types && event.code === 'ArrowUp') {
|
||||||
|
handleClickUp(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (types && event.code === 'ArrowDown') {
|
||||||
|
handleClickDown(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (event.code === 'Enter' && currentItem) {
|
||||||
|
handleClickEnter(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[handleClickUp, handleClickDown, handleClickEnter]
|
[
|
||||||
|
isShow,
|
||||||
|
types,
|
||||||
|
currentItem,
|
||||||
|
handleClickUp,
|
||||||
|
handleClickDown,
|
||||||
|
handleClickEnter,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ export const CommandMenu = ({ editor, hooks, style }: CommandMenuProps) => {
|
|||||||
const handleSelected = async (type: BlockFlavorKeys | string) => {
|
const handleSelected = async (type: BlockFlavorKeys | string) => {
|
||||||
const text = await editor.commands.textCommands.getBlockText(blockId);
|
const text = await editor.commands.textCommands.getBlockText(blockId);
|
||||||
const block = await editor.getBlockById(blockId);
|
const block = await editor.getBlockById(blockId);
|
||||||
let textValue = block.getProperty('text').value;
|
const textValue = block.getProperty('text').value;
|
||||||
editor.blockHelper.removeSearchSlash(blockId, true);
|
editor.blockHelper.removeSearchSlash(blockId, true);
|
||||||
if (type.startsWith('Virgo')) {
|
if (type.startsWith('Virgo')) {
|
||||||
const handler =
|
const handler =
|
||||||
@@ -261,23 +261,21 @@ export const CommandMenu = ({ editor, hooks, style }: CommandMenuProps) => {
|
|||||||
>
|
>
|
||||||
{show ? (
|
{show ? (
|
||||||
<MuiClickAwayListener onClickAway={handleClickAway}>
|
<MuiClickAwayListener onClickAway={handleClickAway}>
|
||||||
<div>
|
<CommandMenuContainer
|
||||||
<CommandMenuContainer
|
editor={editor}
|
||||||
editor={editor}
|
hooks={hooks}
|
||||||
hooks={hooks}
|
style={{
|
||||||
style={{
|
...commandMenuPosition,
|
||||||
...commandMenuPosition,
|
...style,
|
||||||
...style,
|
}}
|
||||||
}}
|
isShow={show}
|
||||||
isShow={show}
|
blockId={blockId}
|
||||||
blockId={blockId}
|
onSelected={handleSelected}
|
||||||
onSelected={handleSelected}
|
onclose={handleClose}
|
||||||
onclose={handleClose}
|
searchBlocks={searchBlocks}
|
||||||
searchBlocks={searchBlocks}
|
types={types}
|
||||||
types={types}
|
categories={categories}
|
||||||
categories={categories}
|
/>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</MuiClickAwayListener>
|
</MuiClickAwayListener>
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
|
|||||||
@@ -1,25 +1,24 @@
|
|||||||
import {
|
import {
|
||||||
HeadingOneIcon,
|
|
||||||
HeadingTwoIcon,
|
|
||||||
HeadingThreeIcon,
|
|
||||||
ToDoIcon,
|
|
||||||
NumberIcon,
|
|
||||||
BulletIcon,
|
BulletIcon,
|
||||||
CodeIcon,
|
|
||||||
TextIcon,
|
|
||||||
PagesIcon,
|
|
||||||
ImageIcon,
|
|
||||||
FileIcon,
|
|
||||||
QuoteIcon,
|
|
||||||
CalloutIcon,
|
CalloutIcon,
|
||||||
|
CodeIcon,
|
||||||
DividerIcon,
|
DividerIcon,
|
||||||
FigmaIcon,
|
|
||||||
YoutubeIcon,
|
|
||||||
EmbedIcon,
|
EmbedIcon,
|
||||||
|
FigmaIcon,
|
||||||
|
FileIcon,
|
||||||
|
HeadingOneIcon,
|
||||||
|
HeadingThreeIcon,
|
||||||
|
HeadingTwoIcon,
|
||||||
|
ImageIcon,
|
||||||
|
NumberIcon,
|
||||||
|
QuoteIcon,
|
||||||
|
TextIcon,
|
||||||
|
ToDoIcon,
|
||||||
|
YoutubeIcon,
|
||||||
} from '@toeverything/components/icons';
|
} from '@toeverything/components/icons';
|
||||||
import { SvgIconProps } from '@toeverything/components/ui';
|
import { SvgIconProps } from '@toeverything/components/ui';
|
||||||
import { Virgo } from '@toeverything/framework/virgo';
|
|
||||||
import { BlockFlavorKeys, Protocol } from '@toeverything/datasource/db-service';
|
import { BlockFlavorKeys, Protocol } from '@toeverything/datasource/db-service';
|
||||||
|
import { Virgo } from '@toeverything/framework/virgo';
|
||||||
import { without } from '@toeverything/utils';
|
import { without } from '@toeverything/utils';
|
||||||
|
|
||||||
export enum CommandMenuCategories {
|
export enum CommandMenuCategories {
|
||||||
@@ -68,11 +67,12 @@ export const menuItemsMap: {
|
|||||||
type: Protocol.Block.Type.text,
|
type: Protocol.Block.Type.text,
|
||||||
icon: TextIcon,
|
icon: TextIcon,
|
||||||
},
|
},
|
||||||
{
|
// the Page block should not be inserted
|
||||||
text: 'Page',
|
// {
|
||||||
type: 'page',
|
// text: 'Page',
|
||||||
icon: PagesIcon,
|
// type: Protocol.Block.Type.page,
|
||||||
},
|
// icon: PagesIcon,
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
text: 'Heading 1',
|
text: 'Heading 1',
|
||||||
type: Protocol.Block.Type.heading1,
|
type: Protocol.Block.Type.heading1,
|
||||||
@@ -91,7 +91,7 @@ export const menuItemsMap: {
|
|||||||
],
|
],
|
||||||
[CommandMenuCategories.lists]: [
|
[CommandMenuCategories.lists]: [
|
||||||
{
|
{
|
||||||
text: 'To do',
|
text: 'Todo',
|
||||||
type: Protocol.Block.Type.todo,
|
type: Protocol.Block.Type.todo,
|
||||||
icon: ToDoIcon,
|
icon: ToDoIcon,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import {
|
|||||||
HeadingTwoIcon,
|
HeadingTwoIcon,
|
||||||
ImageIcon,
|
ImageIcon,
|
||||||
LinkIcon,
|
LinkIcon,
|
||||||
MoreIcon,
|
|
||||||
NumberIcon,
|
NumberIcon,
|
||||||
PagesIcon,
|
PagesIcon,
|
||||||
QuoteIcon,
|
QuoteIcon,
|
||||||
@@ -827,13 +826,13 @@ export const getInlineMenuData = ({
|
|||||||
nameKey: inlineMenuNamesKeys.backlinks,
|
nameKey: inlineMenuNamesKeys.backlinks,
|
||||||
onClick: common_handler_for_inline_menu,
|
onClick: common_handler_for_inline_menu,
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
type: INLINE_MENU_UI_TYPES.icon,
|
// type: INLINE_MENU_UI_TYPES.icon,
|
||||||
icon: MoreIcon,
|
// icon: MoreIcon,
|
||||||
name: inlineMenuNames.moreActions,
|
// name: inlineMenuNames.moreActions,
|
||||||
nameKey: inlineMenuNamesKeys.moreActions,
|
// nameKey: inlineMenuNamesKeys.moreActions,
|
||||||
onClick: common_handler_for_inline_menu,
|
// onClick: common_handler_for_inline_menu,
|
||||||
},
|
// },
|
||||||
];
|
];
|
||||||
|
|
||||||
return inlineMenuData.filter(item => Boolean(item));
|
return inlineMenuData.filter(item => Boolean(item));
|
||||||
|
|||||||
630
pnpm-lock.yaml
generated
630
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user