key enter to trigger next result
This commit is contained in:
1 parent
0cbbde3820
commit
5e6f177132
1 file changed
+106
-99
+106
-99
@@ -8,6 +8,7 @@ import {
|
|||||||
import { NodeModel, TreeGraphData, TreeModel } from "@/misc/b3type";
|
import { NodeModel, TreeGraphData, TreeModel } from "@/misc/b3type";
|
||||||
import * as b3util from "@/misc/b3util";
|
import * as b3util from "@/misc/b3util";
|
||||||
import { message } from "@/misc/hooks";
|
import { message } from "@/misc/hooks";
|
||||||
|
import i18n from "@/misc/i18n";
|
||||||
import { Hotkey, isHotkeyPressed, isMacos, useHotkeys } from "@/misc/keys";
|
import { Hotkey, isHotkeyPressed, isMacos, useHotkeys } from "@/misc/keys";
|
||||||
import Path from "@/misc/path";
|
import Path from "@/misc/path";
|
||||||
import { ArrowDownOutlined, ArrowUpOutlined, CloseOutlined } from "@ant-design/icons";
|
import { ArrowDownOutlined, ArrowUpOutlined, CloseOutlined } from "@ant-design/icons";
|
||||||
@@ -21,8 +22,7 @@ import React, { FC, useCallback, useEffect, useMemo, useRef, useState } from "re
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { FiDelete } from "react-icons/fi";
|
import { FiDelete } from "react-icons/fi";
|
||||||
import { IoMdReturnLeft } from "react-icons/io";
|
import { IoMdReturnLeft } from "react-icons/io";
|
||||||
import { PiCubeFocus } from "react-icons/pi";
|
import { RiFocus3Line } from "react-icons/ri";
|
||||||
import { RiFocus3Fill, RiFocus3Line } from "react-icons/ri";
|
|
||||||
import { VscCaseSensitive } from "react-icons/vsc";
|
import { VscCaseSensitive } from "react-icons/vsc";
|
||||||
import { mergeRefs } from "react-merge-refs";
|
import { mergeRefs } from "react-merge-refs";
|
||||||
import { useDebounceCallback } from "usehooks-ts";
|
import { useDebounceCallback } from "usehooks-ts";
|
||||||
@@ -33,6 +33,86 @@ export interface EditorProps extends React.HTMLAttributes<HTMLElement> {
|
|||||||
onUpdate: () => void;
|
onUpdate: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const createMenu = () => {
|
||||||
|
const t = i18n.t;
|
||||||
|
const MenuItem: FC<FlexProps> = (itemProps) => {
|
||||||
|
return (
|
||||||
|
<Flex
|
||||||
|
gap="50px"
|
||||||
|
style={{ minWidth: "200px", justifyContent: "space-between", alignItems: "center" }}
|
||||||
|
{...itemProps}
|
||||||
|
></Flex>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const arr: MenuProps["items"] = [
|
||||||
|
{
|
||||||
|
label: (
|
||||||
|
<MenuItem>
|
||||||
|
<div>{t("copy")}</div>
|
||||||
|
<div>{isMacos ? "⌘ C" : "Ctrl+C"}</div>
|
||||||
|
</MenuItem>
|
||||||
|
),
|
||||||
|
key: "copy",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: (
|
||||||
|
<MenuItem>
|
||||||
|
<div>{t("paste")}</div>
|
||||||
|
<div>{isMacos ? "⌘ V" : "Ctrl+V"}</div>
|
||||||
|
</MenuItem>
|
||||||
|
),
|
||||||
|
key: "paste",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: (
|
||||||
|
<MenuItem>
|
||||||
|
<div>{t("replace")}</div>
|
||||||
|
<div>{isMacos ? "⇧ ⌘ V" : "Ctrl+Shift+V"} </div>
|
||||||
|
</MenuItem>
|
||||||
|
),
|
||||||
|
key: "replace",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: (
|
||||||
|
<MenuItem>
|
||||||
|
<div>{t("insertNode")}</div>
|
||||||
|
<div>{isMacos ? <IoMdReturnLeft /> : "Enter"}</div>
|
||||||
|
</MenuItem>
|
||||||
|
),
|
||||||
|
key: "insert",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: (
|
||||||
|
<MenuItem>
|
||||||
|
<div>{t("deleteNode")}</div>
|
||||||
|
<div>{isMacos ? <FiDelete /> : "Backspace"}</div>
|
||||||
|
</MenuItem>
|
||||||
|
),
|
||||||
|
key: "delete",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: (
|
||||||
|
<MenuItem>
|
||||||
|
<div>{t("editSubtree")}</div>
|
||||||
|
<div></div>
|
||||||
|
</MenuItem>
|
||||||
|
),
|
||||||
|
key: "editSubtree",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: (
|
||||||
|
<MenuItem>
|
||||||
|
<div>{t("saveAsSubtree")}</div>
|
||||||
|
<div></div>
|
||||||
|
</MenuItem>
|
||||||
|
),
|
||||||
|
key: "saveAsSubtree",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return arr;
|
||||||
|
};
|
||||||
|
|
||||||
export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, ...props }) => {
|
export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, ...props }) => {
|
||||||
const workspace = {
|
const workspace = {
|
||||||
editing: useWorkspace((state) => state.editing),
|
editing: useWorkspace((state) => state.editing),
|
||||||
@@ -48,6 +128,7 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
|||||||
const sizeRef = useRef(null);
|
const sizeRef = useRef(null);
|
||||||
const editorSize = useSize(sizeRef);
|
const editorSize = useSize(sizeRef);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const menuItems = useMemo(() => createMenu(), [t]);
|
||||||
|
|
||||||
const onSearchChange = useDebounceCallback((filter: string) => {
|
const onSearchChange = useDebounceCallback((filter: string) => {
|
||||||
const ids = filterNodes(filter, findDataById("1"));
|
const ids = filterNodes(filter, findDataById("1"));
|
||||||
@@ -465,7 +546,7 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
|||||||
message.warning(t("node.noNodeSelected"));
|
message.warning(t("node.noNodeSelected"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const d1 = findDataById(editor.selectedId);
|
|
||||||
const data = findSubtree(findDataById(editor.selectedId));
|
const data = findSubtree(findDataById(editor.selectedId));
|
||||||
if (data?.path) {
|
if (data?.path) {
|
||||||
const path = `${workspace.workdir}/${data.path}`;
|
const path = `${workspace.workdir}/${data.path}`;
|
||||||
@@ -901,85 +982,6 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
|||||||
}
|
}
|
||||||
}, [workspace.editing]);
|
}, [workspace.editing]);
|
||||||
|
|
||||||
const menuItems = useMemo(() => {
|
|
||||||
const MenuItem: FC<FlexProps> = (itemProps) => {
|
|
||||||
return (
|
|
||||||
<Flex
|
|
||||||
gap="50px"
|
|
||||||
style={{ minWidth: "200px", justifyContent: "space-between", alignItems: "center" }}
|
|
||||||
{...itemProps}
|
|
||||||
></Flex>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const arr: MenuProps["items"] = [
|
|
||||||
{
|
|
||||||
label: (
|
|
||||||
<MenuItem>
|
|
||||||
<div>{t("copy")}</div>
|
|
||||||
<div>{isMacos ? "⌘ C" : "Ctrl+C"}</div>
|
|
||||||
</MenuItem>
|
|
||||||
),
|
|
||||||
key: "copy",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: (
|
|
||||||
<MenuItem>
|
|
||||||
<div>{t("paste")}</div>
|
|
||||||
<div>{isMacos ? "⌘ V" : "Ctrl+V"}</div>
|
|
||||||
</MenuItem>
|
|
||||||
),
|
|
||||||
key: "paste",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: (
|
|
||||||
<MenuItem>
|
|
||||||
<div>{t("replace")}</div>
|
|
||||||
<div>{isMacos ? "⇧ ⌘ V" : "Ctrl+Shift+V"} </div>
|
|
||||||
</MenuItem>
|
|
||||||
),
|
|
||||||
key: "replace",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: (
|
|
||||||
<MenuItem>
|
|
||||||
<div>{t("insertNode")}</div>
|
|
||||||
<div>{isMacos ? <IoMdReturnLeft /> : "Enter"}</div>
|
|
||||||
</MenuItem>
|
|
||||||
),
|
|
||||||
key: "insert",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: (
|
|
||||||
<MenuItem>
|
|
||||||
<div>{t("deleteNode")}</div>
|
|
||||||
<div>{isMacos ? <FiDelete /> : "Backspace"}</div>
|
|
||||||
</MenuItem>
|
|
||||||
),
|
|
||||||
key: "delete",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: (
|
|
||||||
<MenuItem>
|
|
||||||
<div>{t("editSubtree")}</div>
|
|
||||||
<div></div>
|
|
||||||
</MenuItem>
|
|
||||||
),
|
|
||||||
key: "editSubtree",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: (
|
|
||||||
<MenuItem>
|
|
||||||
<div>{t("saveAsSubtree")}</div>
|
|
||||||
<div></div>
|
|
||||||
</MenuItem>
|
|
||||||
),
|
|
||||||
key: "saveAsSubtree",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
return arr;
|
|
||||||
}, [t]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (editor.graph) {
|
if (editor.graph) {
|
||||||
editor.graph.changeData(editor.data);
|
editor.graph.changeData(editor.data);
|
||||||
@@ -993,6 +995,25 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
|||||||
editor.dispatch(info.key as EditEvent);
|
editor.dispatch(info.key as EditEvent);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const nextResult = () => {
|
||||||
|
if (results.length > 0) {
|
||||||
|
const idx = (resultIndex + 1) % results.length;
|
||||||
|
setResultIndex(idx);
|
||||||
|
editor.graph.focusItem(results[idx]);
|
||||||
|
selectNode(results[idx]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const prevResult = () => {
|
||||||
|
if (results.length > 0) {
|
||||||
|
const idx = (resultIndex + results.length - 1) % results.length;
|
||||||
|
setResultIndex(idx);
|
||||||
|
console.log(idx, results[idx]);
|
||||||
|
editor.graph.focusItem(results[idx]);
|
||||||
|
selectNode(results[idx]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
{...props}
|
{...props}
|
||||||
@@ -1031,6 +1052,7 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
|||||||
paddingRight: "2px",
|
paddingRight: "2px",
|
||||||
}}
|
}}
|
||||||
onChange={(e) => onSearchChange(e.currentTarget.value)}
|
onChange={(e) => onSearchChange(e.currentTarget.value)}
|
||||||
|
onKeyDown={(e) => e.code === Hotkey.Enter && nextResult()}
|
||||||
suffix={
|
suffix={
|
||||||
<Flex style={{ alignItems: "center" }}>
|
<Flex style={{ alignItems: "center" }}>
|
||||||
<Button
|
<Button
|
||||||
@@ -1057,14 +1079,7 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
|||||||
size="small"
|
size="small"
|
||||||
style={{ width: "30px" }}
|
style={{ width: "30px" }}
|
||||||
disabled={results.length == 0}
|
disabled={results.length == 0}
|
||||||
onClick={() => {
|
onClick={nextResult}
|
||||||
if (results.length > 0) {
|
|
||||||
const idx = (resultIndex + 1) % results.length;
|
|
||||||
setResultIndex(idx);
|
|
||||||
editor.graph.focusItem(results[idx]);
|
|
||||||
selectNode(results[idx]);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
icon={<ArrowUpOutlined />}
|
icon={<ArrowUpOutlined />}
|
||||||
@@ -1072,15 +1087,7 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
|||||||
size="small"
|
size="small"
|
||||||
style={{ width: "30px" }}
|
style={{ width: "30px" }}
|
||||||
disabled={results.length == 0}
|
disabled={results.length == 0}
|
||||||
onClick={() => {
|
onClick={prevResult}
|
||||||
if (results.length > 0) {
|
|
||||||
const idx = (resultIndex + results.length - 1) % results.length;
|
|
||||||
setResultIndex(idx);
|
|
||||||
console.log(idx, results[idx]);
|
|
||||||
editor.graph.focusItem(results[idx]);
|
|
||||||
selectNode(results[idx]);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
icon={<CloseOutlined />}
|
icon={<CloseOutlined />}
|
||||||
|
|||||||
Reference in new issue
Block a user