import React from 'react'; import { injectIntl, defineMessages, FormattedMessage, InjectedIntl, InjectedIntlProps, } from 'react-intl'; import { Schema } from 'prosemirror-model'; import { EditorView } from 'prosemirror-view'; import { browser } from '@atlaskit/editor-common'; import CrossIcon from '@atlaskit/icon/glyph/cross'; import AkModalDialog, { ModalTransition } from '@atlaskit/modal-dialog'; import type { HeaderComponentProps, FooterComponentProps, } from '@atlaskit/modal-dialog/types'; import { Header, Footer, ContentWrapper, Line, Content, ColumnRight, ColumnLeft, Row, CodeSm, CodeMd, CodeLg, Title, } from './styles'; import * as keymaps from '../../../keymaps'; import ToolbarButton from '../../../ui/ToolbarButton'; import { toolbarMessages } from '../../text-formatting/ui/Toolbar/toolbar-messages'; import { messages as listMessages } from '../../list/messages'; import { messages as insertBlockMessages } from '../../insert-block/ui/ToolbarInsertBlock/messages'; import { messages as blockTypeMessages } from '../../block-type/messages'; import { messages as undoRedoMessages } from '../../undo-redo/messages'; import { closeHelpCommand } from '../commands'; import { annotationMessages } from '../../annotation/toolbar'; const messages = defineMessages({ editorHelp: { id: 'fabric.editor.editorHelp', defaultMessage: 'Editor help', description: 'Title of editor help dialog.', }, helpDialogTips: { id: 'fabric.editor.helpDialogTips', defaultMessage: 'Press {keyMap} to quickly open this dialog at any time', description: 'Hint about how to open a dialog quickly using a shortcut.', }, keyboardShortcuts: { id: 'fabric.editor.keyboardShortcuts', defaultMessage: 'Keyboard shortcuts', description: '', }, markdown: { id: 'fabric.editor.markdown', defaultMessage: 'Markdown', description: 'It is a name of popular markup language.', }, pastePlainText: { id: 'fabric.editor.pastePlainText', defaultMessage: 'Paste plain text', description: '', }, altText: { id: 'fabric.editor.altText', defaultMessage: 'Alt text', description: 'Alternative text for image.', }, closeHelpDialog: { id: 'fabric.editor.closeHelpDialog', defaultMessage: 'Close help dialog', description: '', }, // TODO: Move it inside quick insert plugin quickInsert: { id: 'fabric.editor.quickInsert', defaultMessage: 'Quick insert', description: 'Name of a feature, which let you insert items quickly.', }, }); export interface Format { name: string; type: string; keymap?: Function; autoFormatting?: Function; imageEnabled?: boolean; } export const formatting: (intl: InjectedIntl) => Format[] = ({ formatMessage, }) => [ { name: formatMessage(toolbarMessages.bold), type: 'strong', keymap: () => keymaps.toggleBold, autoFormatting: () => ( ** ** ), }, { name: formatMessage(toolbarMessages.italic), type: 'em', keymap: () => keymaps.toggleItalic, autoFormatting: () => ( ** ), }, { name: formatMessage(toolbarMessages.underline), type: 'underline', keymap: () => keymaps.toggleUnderline, }, { name: formatMessage(toolbarMessages.strike), type: 'strike', keymap: () => keymaps.toggleStrikethrough, autoFormatting: () => ( ~~ ~~ ), }, { name: formatMessage(blockTypeMessages.heading1), type: 'heading', keymap: () => keymaps.toggleHeading1, autoFormatting: () => ( # Space ), }, { name: formatMessage(blockTypeMessages.heading2), type: 'heading', keymap: () => keymaps.toggleHeading2, autoFormatting: () => ( ## Space ), }, { name: formatMessage(blockTypeMessages.heading3), type: 'heading', keymap: () => keymaps.toggleHeading3, autoFormatting: () => ( ### Space ), }, { name: formatMessage(blockTypeMessages.heading4), type: 'heading', keymap: () => keymaps.toggleHeading4, autoFormatting: () => ( #### Space ), }, { name: formatMessage(blockTypeMessages.heading5), type: 'heading', keymap: () => keymaps.toggleHeading5, autoFormatting: () => ( ##### Space ), }, { name: formatMessage(blockTypeMessages.heading6), type: 'heading', keymap: () => keymaps.toggleHeading6, autoFormatting: () => ( ###### Space ), }, { name: formatMessage(blockTypeMessages.normal), type: 'paragraph', keymap: () => keymaps.setNormalText, }, { name: formatMessage(listMessages.orderedList), type: 'orderedList', keymap: () => keymaps.toggleOrderedList, autoFormatting: () => ( 1. Space ), }, { name: formatMessage(listMessages.unorderedList), type: 'bulletList', keymap: () => keymaps.toggleBulletList, autoFormatting: () => ( * Space ), }, { name: formatMessage(blockTypeMessages.blockquote), type: 'blockquote', keymap: () => keymaps.toggleBlockQuote, autoFormatting: () => ( {'>'} Space ), }, { name: formatMessage(blockTypeMessages.codeblock), type: 'codeBlock', autoFormatting: () => ( ``` ), }, { name: formatMessage(insertBlockMessages.horizontalRule), type: 'rule', keymap: () => keymaps.insertRule, autoFormatting: () => ( --- ), }, { name: formatMessage(insertBlockMessages.link), type: 'link', keymap: () => keymaps.addLink, autoFormatting: () => ( [ ](http://a.com) ), }, { name: formatMessage(toolbarMessages.code), type: 'code', keymap: () => keymaps.toggleCode, autoFormatting: () => ( `` ), }, { name: formatMessage(insertBlockMessages.action), type: 'taskItem', autoFormatting: () => ( [] Space ), }, { name: formatMessage(insertBlockMessages.decision), type: 'decisionItem', autoFormatting: () => ( <> Space ), }, { name: formatMessage(insertBlockMessages.emoji), type: 'emoji', autoFormatting: () => ( : ), }, { name: formatMessage(insertBlockMessages.mention), type: 'mention', autoFormatting: () => ( @ ), }, ]; const shortcutNamesWithoutKeymap: string[] = [ 'emoji', 'mention', 'quickInsert', ]; const otherFormatting: (intl: InjectedIntl) => Format[] = ({ formatMessage, }) => [ { name: formatMessage(toolbarMessages.clearFormatting), type: 'clearFormatting', keymap: () => keymaps.clearFormatting, }, { name: formatMessage(undoRedoMessages.undo), type: 'undo', keymap: () => keymaps.undo, }, { name: formatMessage(undoRedoMessages.redo), type: 'redo', keymap: () => keymaps.redo, }, { name: formatMessage(messages.pastePlainText), type: 'paste', keymap: () => keymaps.pastePlainText, }, { name: formatMessage(annotationMessages.createComment), type: 'annotation', keymap: () => keymaps.addInlineComment, }, ]; const imageAutoFormat: Format = { name: 'Image', type: 'image', autoFormatting: () => ( ![ ](http://www.image.com) ), }; const quickInsertAutoFormat: (intl: InjectedIntl) => Format = ({ formatMessage, }) => ({ name: formatMessage(messages.quickInsert), type: 'quickInsert', autoFormatting: () => ( / ), }); export const getSupportedFormatting = ( schema: Schema, intl: InjectedIntl, imageEnabled?: boolean, quickInsertEnabled?: boolean, ): Format[] => { const supportedBySchema = formatting(intl).filter( (format) => schema.nodes[format.type] || schema.marks[format.type], ); return [ ...supportedBySchema, ...(imageEnabled ? [imageAutoFormat] : []), ...(quickInsertEnabled ? [quickInsertAutoFormat(intl)] : []), ...otherFormatting(intl), ]; }; export const getComponentFromKeymap = (keymap: keymaps.Keymap) => { let shortcut: string = keymap[browser.mac ? 'mac' : 'windows']; if (browser.mac) { shortcut = shortcut.replace('Alt', 'Opt'); } const keyParts = shortcut.replace(/\-(?=.)/g, ' + ').split(' '); return ( {keyParts.map((part, index) => { if (part === '+') { return {' + '}; } else if (part === 'Cmd') { return ; } else if ( ['ctrl', 'alt', 'opt', 'shift'].indexOf(part.toLowerCase()) >= 0 ) { return {part}; } return ( {part.toUpperCase()} ); })} ); }; export interface Props { editorView: EditorView; isVisible: boolean; imageEnabled?: boolean; quickInsertEnabled?: boolean; } const ModalHeader = injectIntl( ({ onClose, showKeyline, intl: { formatMessage }, }: HeaderComponentProps & InjectedIntlProps) => (
} />
), ); const ModalFooter = ({ showKeyline }: FooterComponentProps) => ( ); class HelpDialog extends React.Component { static displayName = 'HelpDialog'; private formatting: Format[] = []; closeDialog = () => { const { state: { tr }, dispatch, } = this.props.editorView; closeHelpCommand(tr, dispatch); }; handleEsc = (e: KeyboardEvent) => { if (e.key === 'Escape' && this.props.isVisible) { this.closeDialog(); } }; componentDidMount() { document.addEventListener('keydown', this.handleEsc); } componentWillUnmount() { document.removeEventListener('keydown', this.handleEsc); } render() { const { editorView, intl, imageEnabled, quickInsertEnabled } = this.props; this.formatting = getSupportedFormatting( editorView.state.schema, intl, imageEnabled, quickInsertEnabled, ); return ( {this.props.isVisible ? ( <FormattedMessage {...messages.keyboardShortcuts} />
{this.formatting .filter((form) => { const keymap = form.keymap && form.keymap(this.props); return ( keymap && keymap[browser.mac ? 'mac' : 'windows'] ); }) .map((form) => ( {form.name} {getComponentFromKeymap(form.keymap!())} ))} {this.formatting .filter( (form) => shortcutNamesWithoutKeymap.indexOf(form.type) !== -1, ) .filter((form) => form.autoFormatting) .map((form) => ( {form.name} {form.autoFormatting!()} ))}
<FormattedMessage {...messages.markdown} />
{this.formatting .filter( (form) => shortcutNamesWithoutKeymap.indexOf(form.type) === -1, ) .map( (form) => form.autoFormatting && ( {form.name} {form.autoFormatting()} ), )}
) : null}
); } } export default injectIntl(HelpDialog);