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:
@@ -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)}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
8
app/editor/components/EditorContext.tsx
Normal file
8
app/editor/components/EditorContext.tsx
Normal 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;
|
||||
@@ -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}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
Reference in New Issue
Block a user