all files / packages/switch-text-type/ SwitchTextTypeTool.js

1.59% Statements 1/63
0% Branches 0/26
0% Functions 0/14
1.61% Lines 1/62
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163                                                                                                                                                                                                                                                                                                                                   
import { forEach, keys } from '../../util'
import { Tool } from '../../ui'
 
/**
  SwitchTextTypeTool. Implements the SurfaceTool API.
 
  @class
  @component
*/
class SwitchTextTypeTool extends Tool {
  constructor(...args) {
    super(...args)
 
    // cursor for keyboard navigation
    this._navIdx = -1
  }
 
  // UI Specific parts
  // ----------------
 
  didMount(...args) {
    super.didMount(...args)
    this._focusToggle()
  }
 
  render($$) {
    let labelProvider = this.context.labelProvider
    let textTypeName = 'No selection'
 
    if (this.props.currentTextType) {
      textTypeName = this.props.currentTextType.name
    }
    let el = $$('div').addClass('sc-switch-text-type')
 
    let toggleButton = $$('button').ref('toggle')
      .addClass('se-toggle')
      .attr('title', labelProvider.getLabel('switch_text'))
      .append(labelProvider.getLabel(textTypeName))
      .on('click', this.toggleAvailableTextTypes)
 
    if (this.props.disabled || !this.props.currentTextType) {
      el.addClass('sm-disabled');
      toggleButton.attr('tabindex', -1)
    } else {
      toggleButton.attr('tabindex', 1)
    }
 
    el.append(toggleButton)
 
    if (this.state.open) {
      el.addClass('sm-open')
 
      // dropdown options
      let options = $$('div').addClass("se-options").ref('options')
      forEach(this.props.textTypes, function(textType) {
        let button = $$('button')
            .addClass('se-option sm-'+textType.name)
            .attr('data-type', textType.name)
            .append(labelProvider.getLabel(textType.name))
            .on('click', this.handleClick)
        options.append(button)
      }.bind(this))
      el.append(options)
      el.on('keydown', this.onKeydown)
    }
 
    return el
  }
 
  didUpdate() {
    this._focusToggle()
  }
 
  _focusToggle() {
    if (this.state.open) {
      this.refs.toggle.el.focus()
    }
  }
 
  executeCommand(textType) {
    this.context.commandManager.executeCommand(this.getCommandName(), {
      textType: textType
    })
  }
 
  getTextCommands() {
    let surface = this.getSurface()
    if (!this.textCommands && surface) {
      this.textCommands = surface.getTextCommands()
    }
    return this.textCommands || {}
  }
 
  handleClick(e) {
    e.preventDefault()
    // Modifies the tool's state so that state.open is undefined, which is nice
    // because it means the dropdown will be closed automatically
    this.executeCommand(e.currentTarget.dataset.type)
  }
 
  onKeydown(event) {
    let handled = false
    switch (event.keyCode) {
      case keys.UP:
        this._nav(-1)
        handled = true
        break
      case keys.DOWN:
        this._nav(1)
        handled = true
        break
      case keys.ESCAPE:
        this.toggleDropdown()
        handled = true
        break
      default:
        // nothing
    }
    if (handled) {
      event.preventDefault()
      event.stopPropagation()
    }
  }
 
  toggleAvailableTextTypes(e) {
    e.preventDefault()
    e.stopPropagation()
    if (this.props.disabled) return
 
    // HACK: This only updates the view state state.open is not set on the tool itself
    // That way the dropdown automatically closes when the selection changes
    this.toggleDropdown()
  }
 
  toggleDropdown() {
    // reset index for keyboard navigation
    this._navIdx = -1
    this.extendState({
      open: !this.state.open
    })
  }
 
  _nav(step) {
    this._navIdx += step
    this._navIdx = Math.max(0, this._navIdx)
    this._navIdx = Math.min(this._getOptionsCount()-1, this._navIdx)
 
    if (this._navIdx >= 0) {
      let option = this.refs.options.children[this._navIdx]
      option.focus()
    }
  }
 
  _getOptionsCount() {
    return this.refs.options.children.length
  }
 
}
 
SwitchTextTypeTool.command = 'switch-text-type'
 
export default SwitchTextTypeTool