dounai1306 / react

0 stars 0 forks source link

Draftjs 基础配置 #12

Open dounai1306 opened 4 years ago

dounai1306 commented 4 years ago
import React, {FunctionComponent, useCallback, useRef} from 'react';
import { makeStyles, WithStyles, createStyles, Theme, useTheme } from '@material-ui/core/styles';
import 'draft-js/dist/Draft.css';
import './RichEditor.css';

const Draft = require('draft-js');

const {Editor, EditorState, RichUtils, getDefaultKeyBinding, convertFromRaw,} = Draft;

const styles = (theme: Theme) =>
  createStyles({
    root: {
      padding: '20px',
    },
    editor: {
      background: '#fff',
      cursor: 'text',
      minHeight: 80,
      borderTop: '1px solid #dbdbdb',
      paddingTop: 10
    },
  });

const useStyles = makeStyles(styles);

type Props = {} & Partial<WithStyles<Partial<typeof styles>>>;

const Comp: FunctionComponent<Props> = props => {
  const classes = useStyles(props);
  const editorRef = useRef<any>('editor');
  const [editorState, setEditorState] = React.useState(
    () => EditorState.createEmpty(),
  );
  let className = 'RichEditor-editor';
  let contentState = editorState.getCurrentContent();
  if (!contentState.hasText()) {
    if (contentState.getBlockMap().first().getType() !== 'unstyled') {
      className += ' RichEditor-hidePlaceholder';
    }
  }

  const handleKeyCommand = (command: any, editorState: any) => {
    const newState = RichUtils.handleKeyCommand(editorState, command);
    if (newState) {
      setEditorState(newState);
      return true;
    }
    return false;
  };
  const mapKeyToEditorCommand = (e: any) => {
    if (e.keyCode === 9 /* TAB */) {
      const newEditorState = RichUtils.onTab(
        e,
        editorState,
        4, /* maxDepth */
      );
      if (newEditorState !== editorState) {
        setEditorState(newEditorState);
      }
      return;
    }
    return getDefaultKeyBinding(e);
  };

  const toggleInlineStyle = (inlineStyle: any) => {
    setEditorState(
      RichUtils.toggleInlineStyle(
        editorState,
        inlineStyle
      )
    );
  };

  const toggleBlockType = (blockType: any) => {
    setEditorState(
      RichUtils.toggleBlockType(
        editorState,
        blockType
      )
    );
  };

  return (
    <div className={classes.root}>
      <div className={'RichEditor-root'}>
        <BlockStyleControls
          editorState={editorState}
          onToggle={toggleBlockType}
        />
        <InlineStyleControls
          editorState={editorState}
          onToggle={toggleInlineStyle}
        />
        <div className={classes.editor}>
          <Editor
            blockStyleFn={getBlockStyle}
            customStyleMap={styleMap}
            editorState={editorState}
            handleKeyCommand={handleKeyCommand}
            keyBindingFn={mapKeyToEditorCommand}
            onChange={setEditorState}
            placeholder="Enter some text..."
            ref={editorRef}
            spellCheck
          />
        </div>
      </div>
    </div>
  );
};

// draft 配置
const getBlockStyle = (block: any) => {
  switch (block.getType()) {
    case 'blockquote': return 'RichEditor-blockquote';
    default: return null;
  }
};
const styleMap = {
  CODE: {
    backgroundColor: 'rgba(0, 0, 0, 0.05)',
    fontFamily: '"Inconsolata", "Menlo", "Consolas", monospace',
    fontSize: 16,
    padding: 2,
  },
};

const INLINE_STYLES = [
  {label: 'B', style: 'BOLD'},
  {label: 'I', style: 'ITALIC'},
  {label: 'U', style: 'UNDERLINE'},
  {label: 'M', style: 'CODE'},
];

const InlineStyleControls = (props: any) => {
  const currentStyle = props.editorState.getCurrentInlineStyle();

  return (
    <div className="RichEditor-controls">
      {INLINE_STYLES.map((type: any) =>
        <StyleButton
          key={type.label}
          active={currentStyle.has(type.style)}
          label={type.label}
          onToggle={props.onToggle}
          style={type.style}
        />
      )}
    </div>
  );
};

const StyleButton = (props: any) => {
  let className = 'RichEditor-styleButton';
  if (props.active) {
    className += ' RichEditor-activeButton';
  }
  const onToggle = (e: any) => {
    e.preventDefault();
    props.onToggle(props.style);
  };
  return (
    <span className={className} onMouseDown={onToggle}>{props.label}</span>
  )
};

const BLOCK_TYPES = [
  {label: 'H1', style: 'header-one'},
  {label: 'H2', style: 'header-two'},
  {label: 'H3', style: 'header-three'},
  {label: 'H4', style: 'header-four'},
  {label: 'H5', style: 'header-five'},
  {label: 'H6', style: 'header-six'},
  {label: 'Blockquote', style: 'blockquote'},
  {label: 'UL', style: 'unordered-list-item'},
  {label: 'OL', style: 'ordered-list-item'},
  {label: 'Code', style: 'code-block'},
];

const BlockStyleControls = (props: any) => {
  const {editorState} = props;
  const selection = editorState.getSelection();
  const blockType = editorState
    .getCurrentContent()
    .getBlockForKey(selection.getStartKey())
    .getType();

  return (
    <div className="RichEditor-controls">
      {BLOCK_TYPES.map((type: any) =>
        <StyleButton
          key={type.label}
          active={type.style === blockType}
          label={type.label}
          onToggle={props.onToggle}
          style={type.style}
        />
      )}
    </div>
  );
};

export default Comp;
dounai1306 commented 4 years ago

https://codepen.io/dounai1306/pen/Vweowmb