inkdrop-command-palette/lib/components/palette.js

110 lines
3.3 KiB
JavaScript
Raw Normal View History

2022-08-16 21:11:16 +00:00
"use babel";
import React, { useEffect, useCallback, useRef, useLayoutEffect } from "react";
2022-08-22 12:20:24 +00:00
import Option from "./command.js";
2022-08-23 03:40:41 +00:00
import Application from "../commands/application.js";
import Core from "../commands/core.js";
import NoteTags from "../commands/notetagsbar.js";
import Formatting from "../commands/formatting.js";
2022-08-16 21:11:16 +00:00
import { logger, useModal } from "inkdrop";
2022-08-22 12:20:24 +00:00
import useArrowKeyNavigation from "../navigation/hook.js";
2022-08-16 21:11:16 +00:00
const CommandPalette = (props) => {
2022-08-23 03:40:41 +00:00
const Commands = [...Formatting, ...Application, ...Core, ...NoteTags];
2022-08-16 21:11:16 +00:00
const modal = useModal();
const { Dialog } = inkdrop.components.classes;
2022-08-22 12:20:24 +00:00
const inputRef = useRef(null);
const [searchQuery, setSearchQuery] = React.useState("");
2022-08-16 21:11:16 +00:00
const toggle = useCallback(() => {
modal.show();
}, []);
useEffect(() => {
const sub = inkdrop.commands.add(document.body, {
"commandpalette:toggle": toggle,
});
2022-08-23 01:49:14 +00:00
console.log("useeffect triggered");
2022-08-16 21:11:16 +00:00
return () => sub.dispose();
}, [toggle]);
2022-08-22 07:17:43 +00:00
// focus text box when dialog is shown
2022-08-16 21:11:16 +00:00
useLayoutEffect(() => {
2022-08-22 07:17:43 +00:00
setTimeout(() => {
const textbox = document.getElementById("cpInput");
textbox.focus();
}, 50);
2022-08-22 12:20:24 +00:00
console.log("use layout effect triggered");
2022-08-16 21:11:16 +00:00
});
2022-08-22 12:20:24 +00:00
const filter = (commands, query) => {
if (!query) return commands;
return commands.filter((command) => {
const commandText = command.name.toLowerCase();
const commandCat = command.category.toLowerCase();
let textFilter = commandText.includes(query.toLowerCase());
let categoryFilter = commandCat.includes(query.toLowerCase());
return textFilter || categoryFilter;
});
};
const changeHandler = (e) => {
e.preventDefault();
setSearchQuery(e.currentTarget.value);
};
const filteredResults = filter(Commands, searchQuery);
2022-08-16 21:11:16 +00:00
return (
2022-08-22 12:20:24 +00:00
<Dialog
{...modal.state}
onBackdropClick={modal.close}
className="commandpalette flex-col"
>
2022-08-16 21:11:16 +00:00
<Dialog.Content className="commandpalette">
2022-08-23 01:49:14 +00:00
<div
className="commandpalettewrapper flex-col"
ref={useArrowKeyNavigation({
selectors: "a,input",
modal: modal.close,
})}
>
2022-08-22 12:20:24 +00:00
<div className="flex-col contents">
2022-08-16 21:11:16 +00:00
<div className="ui small input">
<input
type="text"
placeholder="Search files by name (append > for actions or ! for formatting)"
spellCheck="false"
className="cpInput"
id="cpInput"
2022-08-22 12:20:24 +00:00
ref={inputRef}
onChange={changeHandler}
2022-08-16 21:11:16 +00:00
/>
</div>
2022-08-22 12:20:24 +00:00
<div className="cpContents">
{filteredResults.length === 0 ? (
<div className="nomatch">
<p className="nomatchemoji">{"(。><)"}</p>
<p className="nomatchtext">no matching commands</p>
<p className="nomatchtext">
try searching for a different term
</p>
</div>
) : null}
{filteredResults.map((Command, index) => {
return (
<Option idx={index} key={index} {...Command} modal={modal} />
);
})}
</div>
2022-08-16 21:11:16 +00:00
</div>
</div>
</Dialog.Content>
</Dialog>
);
};
export default CommandPalette;