text: /**
   * Copyright (c) 2013-present, Facebook, Inc.
   * All rights reserved.
   *
   * This source code is licensed under the BSD-style license found in the
   * LICENSE file in the root directory of this source tree. An additional grant
   * of patent rights can be found in the PATENTS file in the same directory.
   *
   * @providesModule editOnKeyDown
   * @flow
   */
  
  'use strict';
  
  import type DraftEditor from 'DraftEditor.react';
  import type {DraftEditorCommand} from 'DraftEditorCommand';
  
  var DraftModifier = require('DraftModifier');
  var EditorState = require('EditorState');
  var KeyBindingUtil = require('KeyBindingUtil');
  var Keys = require('Keys');
  var SecondaryClipboard = require('SecondaryClipboard');
  var UserAgent = require('UserAgent');
  
  const isEventHandled = require('isEventHandled');
  var keyCommandBackspaceToStartOfLine = require('keyCommandBackspaceToStartOfLine');
  var keyCommandBackspaceWord = require('keyCommandBackspaceWord');
  var keyCommandDeleteWord = require('keyCommandDeleteWord');
  var keyCommandInsertNewline = require('keyCommandInsertNewline');
  var keyCommandMoveSelectionToEndOfBlock = require('keyCommandMoveSelectionToEndOfBlock');
  var keyCommandMoveSelectionToStartOfBlock = require('keyCommandMoveSelectionToStartOfBlock');
  var keyCommandPlainBackspace = require('keyCommandPlainBackspace');
  var keyCommandPlainDelete = require('keyCommandPlainDelete');
  var keyCommandTransposeCharacters = require('keyCommandTransposeCharacters');
  var keyCommandUndo = require('keyCommandUndo');
  
  var {isOptionKeyCommand} = KeyBindingUtil;
  var isChrome = UserAgent.isBrowser('Chrome');
  
  /**
   * Map a `DraftEditorCommand` command value to a corresponding function.
   */
  function onKeyCommand(
    command: DraftEditorCommand | string,
    editorState: EditorState,
  ): EditorState {
    switch (command) {
      case 'redo':
        return EditorState.redo(editorState);
      case 'delete':
        return keyCommandPlainDelete(editorState);
      case 'delete-word':
        return keyCommandDeleteWord(editorState);
      case 'backspace':
        return keyCommandPlainBackspace(editorState);
      case 'backspace-word':
        return keyCommandBackspaceWord(editorState);
      case 'backspace-to-start-of-line':
        return keyCommandBackspaceToStartOfLine(editorState);
      case 'split-block':
        return keyCommandInsertNewline(editorState);
      case 'transpose-characters':
        return keyCommandTransposeCharacters(editorState);
      case 'move-selection-to-start-of-block':
        return keyCommandMoveSelectionToStartOfBlock(editorState);
      case 'move-selection-to-end-of-block':
        return keyCommandMoveSelectionToEndOfBlock(editorState);
      case 'secondary-cut':
        return SecondaryClipboard.cut(editorState);
      case 'secondary-paste':
        return SecondaryClipboard.paste(editorState);
      default:
        return editorState;
    }
  }
  
  /**
   * Intercept keydown behavior to handle keys and commands manually, if desired.
   *
   * Keydown combinations may be mapped to `DraftCommand` values, which may
   * correspond to command functions that modify the editor or its contents.
   *
   * See `getDefaultKeyBinding` for defaults. Alternatively, the top-level
   * component may provide a custom mapping via the `keyBindingFn` prop.
   */
  function editOnKeyDown(editor: DraftEditor, e: SyntheticKeyboardEvent): void {
    var keyCode = e.which;
    var editorState = editor._latestEditorState;
  
    switch (keyCode) {
      case Keys.RETURN:
        e.preventDefault();
        // The top-level component may manually handle newline insertion. If
        // no special handling is performed, fall through to command handling.
        if (
          editor.props.handleReturn &&
          isEventHandled(editor.props.handleReturn(e, editorState))
        ) {
          return;
        }
        break;
      case Keys.ESC:
        e.preventDefault();
        editor.props.onEscape && editor.props.onEscape(e);
        return;
      case Keys.TAB:
        editor.props.onTab && editor.props.onTab(e);
        return;
      case Keys.UP:
        editor.props.onUpArrow && editor.props.onUpArrow(e);
        return;
      case Keys.DOWN:
        editor.props.onDownArrow && editor.props.onDownArrow(e);
        return;
      case Keys.SPACE:
        // Prevent Chrome on OSX behavior where option + space scrolls.
        if (isChrome && isOptionKeyCommand(e)) {
          e.preventDefault();
        }
    }
  
    var command = editor.props.keyBindingFn(e);
  
    // If no command is specified, allow keydown event to continue.
    if (!command) {
      if (
        keyCode === Keys.SPACE &&
        isChrome &&
        isOptionKeyCommand(e)
      ) {
        // The default keydown event has already been prevented in order to stop
        // Chrome from scrolling. Insert a nbsp into the editor as OSX would for
        // other browsers.
        const contentState = DraftModifier.replaceText(
          editorState.getCurrentContent(),
          editorState.getSelection(),
          '\u00a0',
        );
        editor.update(
          EditorState.push(
            editorState,
            contentState,
            'insert-characters',
          ),
        );
      }
      return;
    }
  
    if (command === 'undo') {
      // Since undo requires some special updating behavior to keep the editor
      // in sync, handle it separately.
      keyCommandUndo(e, editorState, editor.update);
      return;
    }
  
    // At this point, we know that we're handling a command of some kind, so
    // we don't want to insert a character following the keydown.
    e.preventDefault();
  
    // Allow components higher up the tree to handle the command first.
    if (
      editor.props.handleKeyCommand &&
      isEventHandled(editor.props.handleKeyCommand(command, editorState))
    ) {
      return;
    }
  
    var newState = onKeyCommand(command, editorState);
    if (newState !== editorState) {
      editor.update(newState);
    }
  }
  
  module.exports = editOnKeyDown;
  