chore: Editor refactor (#3286)

* cleanup

* add context

* EventEmitter allows removal of toolbar props from extensions

* Move to 'packages' of extensions
Remove EmojiTrigger extension

* types

* iteration

* fix render flashing

* fix: Missing nodes in collection descriptions
This commit is contained in:
Tom Moor
2022-03-30 19:10:34 -07:00
committed by GitHub
parent c5b9a742c0
commit 6f2a4488e8
30 changed files with 517 additions and 581 deletions

View File

@@ -25,17 +25,15 @@ function BlockMenu(props: BlockMenuProps) {
{...props}
filterable={true}
onClearSearch={clearSearch}
renderMenuItem={(item, _index, options) => {
return (
<BlockMenuItem
onClick={options.onClick}
selected={options.selected}
icon={item.icon}
title={item.title}
shortcut={item.shortcut}
/>
);
}}
renderMenuItem={(item, _index, options) => (
<BlockMenuItem
onClick={options.onClick}
selected={options.selected}
icon={item.icon}
title={item.title}
shortcut={item.shortcut}
/>
)}
items={getMenuItems(props.dictionary)}
/>
);

View File

@@ -9,7 +9,7 @@ import styled from "styled-components";
import insertFiles from "@shared/editor/commands/insertFiles";
import { CommandFactory } from "@shared/editor/lib/Extension";
import filterExcessSeparators from "@shared/editor/lib/filterExcessSeparators";
import { EmbedDescriptor, MenuItem, ToastType } from "@shared/editor/types";
import { EmbedDescriptor, MenuItem } from "@shared/editor/types";
import getDataTransferFiles from "@shared/utils/getDataTransferFiles";
import { Dictionary } from "~/hooks/useDictionary";
import Input from "./Input";
@@ -31,7 +31,7 @@ export type Props<T extends MenuItem = MenuItem> = {
uploadFile?: (file: File) => Promise<string>;
onFileUploadStart?: () => void;
onFileUploadStop?: () => void;
onShowToast: (message: string, id: string) => void;
onShowToast: (message: string) => void;
onLinkToolbarOpen?: () => void;
onClose: () => void;
onClearSearch: () => void;
@@ -216,10 +216,7 @@ class CommandMenu<T = MenuItem> extends React.Component<Props<T>, State> {
const matches = this.state.insertItem.matcher(href);
if (!matches) {
this.props.onShowToast(
this.props.dictionary.embedInvalidLink,
ToastType.Error
);
this.props.onShowToast(this.props.dictionary.embedInvalidLink);
return;
}

View File

@@ -0,0 +1,8 @@
import * as React from "react";
import { Editor } from "../";
const EditorContext = React.createContext<Editor>({} as Editor);
export const useEditor = () => React.useContext(EditorContext);
export default EditorContext;

View File

@@ -64,23 +64,22 @@ class EmojiMenu extends React.Component<
};
render() {
const containerId = "emoji-menu-container";
return (
<CommandMenu
{...this.props}
id="emoji-menu-container"
id={containerId}
filterable={false}
onClearSearch={this.clearSearch}
renderMenuItem={(item, _index, options) => {
return (
<EmojiMenuItem
onClick={options.onClick}
selected={options.selected}
title={item.description}
emoji={item.emoji}
containerId="emoji-menu-container"
/>
);
}}
renderMenuItem={(item, _index, options) => (
<EmojiMenuItem
onClick={options.onClick}
selected={options.selected}
title={item.description}
emoji={item.emoji}
containerId={containerId}
/>
)}
items={this.items}
/>
);

View File

@@ -15,6 +15,7 @@ import isUrl from "@shared/editor/lib/isUrl";
import { isInternalUrl } from "@shared/utils/urls";
import Flex from "~/components/Flex";
import { Dictionary } from "~/hooks/useDictionary";
import { ToastOptions } from "~/types";
import Input from "./Input";
import LinkSearchResult from "./LinkSearchResult";
import ToolbarButton from "./ToolbarButton";
@@ -44,7 +45,7 @@ type Props = {
href: string,
event: React.MouseEvent<HTMLButtonElement>
) => void;
onShowToast: (message: string, code: string) => void;
onShowToast: (message: string, options: ToastOptions) => void;
view: EditorView;
};

View File

@@ -15,7 +15,7 @@ type Props = {
href: string,
event: React.MouseEvent<HTMLButtonElement>
) => void;
onShowToast: (msg: string, code: string) => void;
onShowToast: (message: string) => void;
onClose: () => void;
};

View File

@@ -36,7 +36,7 @@ type Props = {
event: MouseEvent | React.MouseEvent<HTMLButtonElement>
) => void;
onCreateLink?: (title: string) => Promise<string>;
onShowToast: (msg: string, code: string) => void;
onShowToast: (message: string) => void;
view: EditorView;
};

View File

@@ -1,15 +1,12 @@
import { EditorView } from "prosemirror-view";
import * as React from "react";
import styled from "styled-components";
import { CommandFactory } from "@shared/editor/lib/Extension";
import { MenuItem } from "@shared/editor/types";
import { useEditor } from "./EditorContext";
import ToolbarButton from "./ToolbarButton";
import ToolbarSeparator from "./ToolbarSeparator";
import Tooltip from "./Tooltip";
type Props = {
commands: Record<string, CommandFactory>;
view: EditorView;
items: MenuItem[];
};
@@ -20,7 +17,8 @@ const FlexibleWrapper = styled.div`
`;
function ToolbarMenu(props: Props) {
const { view, items } = props;
const { commands, view } = useEditor();
const { items } = props;
const { state } = view;
return (
@@ -38,7 +36,7 @@ function ToolbarMenu(props: Props) {
return (
<Tooltip tooltip={item.tooltip} key={index}>
<ToolbarButton
onClick={() => item.name && props.commands[item.name](item.attrs)}
onClick={() => item.name && commands[item.name](item.attrs)}
active={isActive}
>
<Icon color="currentColor" />