// @flow import { observer } from "mobx-react"; import { CheckmarkIcon, LinkIcon } from "outline-icons"; import * as React from "react"; import { useTranslation } from "react-i18next"; import AutoSizer from "react-virtualized-auto-sizer"; import { Dialog, DialogBackdrop, useDialogState } from "reakit/Dialog"; import scrollIntoView from "smooth-scroll-into-view-if-needed"; import styled from "styled-components"; import Header from "components/ContextMenu/Header"; import Flex from "components/Flex"; import Scrollable from "components/Scrollable"; import InputSearch from "../InputSearch"; import useStores from "hooks/useStores"; function QuickMenu() { const { quickMenu } = useStores(); const dialog = useDialogState({ modal: true, animated: 250 }); const [activeCommand, setActiveCommand] = React.useState(1); const activeCommandRef = React.useRef(); const { t } = useTranslation(); let order = 0; React.useLayoutEffect(() => { if (!dialog.visible) { quickMenu.reset(); setActiveCommand(1); } }, [quickMenu, dialog.visible]); React.useLayoutEffect(() => { const handleKeyDown = (event) => { if (event.key === "k") { dialog.show(); } }; window.addEventListener("keydown", handleKeyDown); return () => window.removeEventListener("keydown", handleKeyDown); }); React.useEffect(() => { if (activeCommandRef.current) { console.log("calling on", activeCommandRef.current); scrollIntoView(activeCommandRef.current, { scrollMode: "if-needed", behavior: "instant", }); } }); const handleChange = (event) => { event.preventDefault(); event.stopPropagation(); quickMenu.setSearchTerm(event.target.value); }; const handleKeyDown = (event) => { if (event.currentTarget.value && event.key === "Escape") { event.preventDefault(); event.stopPropagation(); quickMenu.setSearchTerm(""); } if (event.key === "ArrowDown") { setActiveCommand((prev) => (prev < order ? ++prev : prev)); } if (event.key === "ArrowUp") { setActiveCommand((prev) => (prev > 1 ? --prev : prev)); } if (event.key === "Enter" && activeCommandRef.current) { activeCommandRef.current.click(); } }; const constructBlock = (item, order, setActiveCommand) => { if (item.to || item.href || item.onClick) { return ( setActiveCommand(order)} aria-selected={activeCommand === order} selected={activeCommand === order} onClick={ item.to || item.href ? () => (window.location.href = item.to ? item.to : item.href) : item.onClick } onFocus={() => { setActiveCommand(order); }} > {item.selected !== undefined && ( <> {item.selected ? ( ) : ( )}   )} {item.selected === undefined && ( {item.icon ? ( item.icon ) : item.href || item.to ? ( ) : null} )} {item.title} ); } console.log("unhandled item", item); return
{item?.title}
; }; const data = quickMenu.resolvedMenuItems.map((context) => { return ( <>
{context.title}
{context.items.map((item) => constructBlock(item, ++order, setActiveCommand) )} ); }); console.log(activeCommand); const term = quickMenu.searchTerm; return ( {(props) => ( {(props) => ( {({ width, height }) => ( {data} )} )} )} ); } const InputWrapper = styled.div` padding: 16px; `; const Results = styled.div` height: calc(100% - 64px); width: 100%; `; const MenuIconWrapper = styled.span` width: 24px; height: 24px; margin-right: 12px; `; const Container = styled(Flex)` width: 100%; height: 100%; `; const CommandItem = styled.li` display: flex; align-items: center; height: 48px; font-family: var(--font-main); font-size: 14px; border-radius: 4px; cursor: pointer; padding: 0 16px; background: transparent; color: var(--gray6); white-space: nowrap; -webkit-transition: color 0.1s cubic-bezier(0, 0, 0.2, 1); transition: color 0.1s cubic-bezier(0, 0, 0.2, 1); cursor: pointer; outline: none; ${(props) => props.selected && { color: `${props.theme.white}`, background: `${props.theme.primary}`, boxShadow: "none", cursor: "pointer", svg: { fill: `${props.theme.white}`, }, }} `; const CommandList = styled.ul` list-style-type: none; margin: 0; padding: 0; `; const Wrapper = styled(Flex)` height: ${(props) => props.height + "px"}; width: ${(props) => props.width + "px"}; flex: 1 1 auto; `; const Content = styled(Flex)` background: ${(props) => props.theme.background}; width: 40vw; height: 50vh; border-radius: 8px; flex: 1; overflow: hidden; margin: 20vh auto; box-shadow: ${(props) => props.theme.menuShadow}; `; const Backdrop = styled.div` position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: ${(props) => props.theme.depths.modalOverlay}; `; export default observer(QuickMenu);