1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-13 09:46:22 +00:00

ModeSelect

This commit is contained in:
Rokt33r
2015-11-10 04:26:11 +09:00
parent 746df9277c
commit e4b2c42897
7 changed files with 1042 additions and 33 deletions

View File

@@ -1,5 +1,7 @@
import React from 'react'
import ReactDOM from 'react-dom'
import modes from 'boost/vars/modes'
import _ from 'lodash'
var ace = window.ace
module.exports = React.createClass({
@@ -32,11 +34,12 @@ module.exports = React.createClass({
editor.setReadOnly(!!this.props.readOnly)
var session = editor.getSession()
if (this.props.mode != null && this.props.mode.length > 0) {
session.setMode('ace/mode/' + this.props.mode)
} else {
session.setMode('ace/mode/text')
}
let mode = _.findWhere(modes, {name: this.props.mode})
let syntaxMode = mode != null
? mode.mode
: 'text'
session.setMode('ace/mode/' + syntaxMode)
session.setUseSoftTabs(true)
session.setOption('useWorker', false)
session.setUseWrapMode(true)
@@ -57,11 +60,11 @@ module.exports = React.createClass({
}
if (prevProps.mode !== this.props.mode) {
var session = this.state.editor.getSession()
if (this.props.mode != null && this.props.mode.length > 0) {
session.setMode('ace/mode/' + this.props.mode)
} else {
session.setMode('ace/mode/text')
}
let mode = _.findWhere(modes, {name: this.props.mode})
let syntaxMode = mode != null
? mode.mode
: 'text'
session.setMode('ace/mode/' + syntaxMode)
}
},
render: function () {

View File

@@ -32,8 +32,10 @@ export default class ModeIcon extends React.Component {
return 'devicon-sass-original'
// Compile
case 'c_cpp':
case 'c':
return 'devicon-c-plain'
case 'cpp':
return 'devicon-cplusplus-plain'
case 'csharp':
return 'devicon-csharp-plain'
case 'objc':
@@ -60,7 +62,6 @@ export default class ModeIcon extends React.Component {
return 'fa fa-fw fa-terminal'
case 'text':
case 'plain_text':
case 'markdown':
return 'fa fa-fw fa-file-text-o'
}
@@ -68,9 +69,9 @@ export default class ModeIcon extends React.Component {
}
render () {
var className = this.getClassName()
let className = `ModeIcon ${this.getClassName()} ${this.props.className}`
return (
<i className={this.props.className + ' ' + className}/>
<i className={className}/>
)
}
}

View File

@@ -0,0 +1,190 @@
import React, { PropTypes } from 'react'
import ReactDOM from 'react-dom'
import ModeIcon from 'boost/components/ModeIcon'
import modes from 'boost/vars/modes'
import _ from 'lodash'
const IDLE_MODE = 'IDLE_MODE'
const EDIT_MODE = 'EDIT_MODE'
export default class ModeSelect extends React.Component {
constructor (props) {
super(props)
this.state = {
mode: IDLE_MODE,
search: '',
focusIndex: 0
}
}
componentDidMount (e) {
this.blurHandler = e => {
let searchElement = ReactDOM.findDOMNode(this.refs.search)
if (this.state.mode === EDIT_MODE && document.activeElement !== searchElement) {
this.handleBlur()
}
}
window.addEventListener('click', this.blurHandler)
}
componentWillUnmount (e) {
window.removeEventListener('click', this.blurHandler)
let searchElement = ReactDOM.findDOMNode(this.refs.search)
if (searchElement != null && this.searchKeyDownListener != null) {
searchElement.removeEventListener('keydown', this.searchKeyDownListener)
}
}
handleIdleSelectClick (e) {
this.setState({mode: EDIT_MODE})
}
componentDidUpdate (prevProps, prevState) {
if (prevState.mode !== this.state.mode && this.state.mode === EDIT_MODE) {
let searchElement = ReactDOM.findDOMNode(this.refs.search)
searchElement.focus()
if (this.searchKeyDownListener == null) {
this.searchKeyDownListener = e => this.handleSearchKeyDown
}
searchElement.addEventListener('keydown', this.searchKeyDownListener)
}
}
componentWillUpdate (nextProps, nextState) {
if (nextProps.mode !== this.state.mode && nextState.mode === IDLE_MODE) {
let searchElement = ReactDOM.findDOMNode(this.refs.search)
if (searchElement != null && this.searchKeyDownListener != null) {
searchElement.removeEventListener('keydown', this.searchKeyDownListener)
}
}
}
handleModeOptionClick (modeName) {
return e => {
this.props.onChange(modeName)
this.setState({
mode: IDLE_MODE,
search: '',
focusIndex: 0
})
}
}
handleSearchKeyDown (e) {
switch (e.keyCode) {
// up
case 38:
e.preventDefault()
if (this.state.focusIndex > 0) this.setState({focusIndex: this.state.focusIndex - 1})
break
// down
case 40:
e.preventDefault()
{
let filteredModes = modes
.filter(mode => {
let search = this.state.search
let nameMatched = mode.name.match(search)
let aliasMatched = _.some(mode.alias, alias => alias.match(search))
return nameMatched || aliasMatched
})
if (filteredModes.length === this.state.focusIndex + 1) this.setState({focusIndex: filteredModes.length - 1})
else this.setState({focusIndex: this.state.focusIndex + 1})
}
break
// enter
case 13:
e.preventDefault()
{
let filteredModes = modes
.filter(mode => {
let search = this.state.search
let nameMatched = mode.name.match(search)
let aliasMatched = _.some(mode.alias, alias => alias.match(search))
return nameMatched || aliasMatched
})
let targetMode = filteredModes[this.state.focusIndex]
if (targetMode != null) {
this.props.onChange(targetMode.name)
this.handleBlur()
}
}
break
// esc
case 27:
e.preventDefault()
e.stopPropagation()
this.handleBlur()
break
case 9:
this.handleBlur()
}
}
handleSearchChange (e) {
this.setState({
search: e.target.value,
focusIndex: 0
})
}
handleBlur () {
if (this.state.mode === EDIT_MODE) {
this.setState({
mode: IDLE_MODE,
search: '',
focusIndex: 0
})
}
if (this.props.onBlur != null) this.props.onBlur()
}
render () {
let className = this.props.className != null
? `ModeSelect ${this.props.className}`
: this.props.className
if (this.state.mode === IDLE_MODE) {
let mode = _.findWhere(modes, {name: this.props.value})
let modeName = mode != null ? mode.name : 'text'
let modeLabel = mode != null ? mode.label : 'Plain text'
return (
<div className={className + ' idle'} onClick={e => this.handleIdleSelectClick(e)}>
<ModeIcon mode={modeName}/>
<span className='modeLabel'>{modeLabel}</span>
</div>
)
}
let filteredOptions = modes
.filter(mode => {
let search = this.state.search
let nameMatched = mode.name.match(search)
let aliasMatched = _.some(mode.alias, alias => alias.match(search))
return nameMatched || aliasMatched
})
.map((mode, index) => {
return (
<div key={mode.name} className={index === this.state.focusIndex ? 'option active' : 'option'} onClick={e => this.handleModeOptionClick(mode.name)(e)}><ModeIcon mode={mode.name}/>{mode.label}</div>
)
})
return (
<div className={className + ' edit'}>
<input onKeyDown={e => this.handleSearchKeyDown(e)} ref='search' onChange={e => this.handleSearchChange(e)} value={this.state.search} type='text'/>
<div ref='options' className='modeOptions hide'>
{filteredOptions}
</div>
</div>
)
}
}
ModeSelect.propTypes = {
className: PropTypes.string,
value: PropTypes.string,
onChange: PropTypes.func,
onBlur: PropTypes.func
}

756
lib/vars/modes.js Normal file
View File

@@ -0,0 +1,756 @@
const modes = [
// Major
{
name: 'text',
label: 'Plain text',
mode: 'text'
},
{
name: 'markdown',
label: 'Markdown',
alias: ['md'],
mode: 'markdown'
},
{
name: 'javascript',
label: 'JavaScript',
alias: ['js', 'jscript', 'babel', 'es'],
mode: 'javascript'
},
{
name: 'html',
label: 'HTML',
alias: [],
mode: 'html'
},
{
name: 'css',
label: 'CSS',
alias: ['cascade', 'stylesheet'],
mode: 'css'
},
{
name: 'php',
label: 'PHP',
alias: [],
mode: 'php'
},
{
name: 'python',
label: 'Python',
alias: ['py'],
mode: 'python'
},
{
name: 'ruby',
label: 'Ruby',
alias: ['rb'],
mode: 'ruby'
},
{
name: 'java',
label: 'Java',
alias: [],
mode: 'java'
},
{
name: 'c',
label: 'C',
alias: ['c', 'h', 'clang', 'clang'],
mode: 'c_cpp'
},
{
name: 'cpp',
label: 'C++',
alias: ['cc', 'cpp', 'cxx', 'hh', 'c++', 'cplusplus'],
mode: 'c_cpp'
},
{
name: 'csharp',
label: 'C#',
alias: ['cs'],
mode: 'csharp'
},
{
name: 'swift',
label: 'Swift',
alias: [],
mode: 'swift'
},
{
name: 'golang',
label: 'Go',
alias: ['go'],
mode: 'golang'
},
// Minor
{
name: 'abap',
label: 'ABAP',
alias: [],
mode: 'abap'
},
{
name: 'abc',
label: 'ABC',
alias: [],
mode: 'abc'
},
{
name: 'actionscript',
label: 'ActionScript',
alias: ['as'],
mode: 'actionscript'
},
{
name: 'ada',
label: 'Ada',
alias: [],
mode: 'ada'
},
{
name: 'apache_conf',
label: 'Apache config',
alias: ['apache', 'conf'],
mode: 'apache_conf'
},
{
name: 'applescript',
label: 'AppleScript',
alias: ['scpt'],
mode: 'applescript'
},
{
name: 'asciidoc',
label: 'AsciiDoc',
alias: ['ascii', 'doc', 'txt'],
mode: 'asciidoc'
},
{
name: 'assembly_x86',
label: 'Assembly x86',
alias: ['assembly', 'x86', 'asm'],
mode: 'assembly_x86'
},
{
name: 'autohotkey',
label: 'AutoHotkey',
alias: ['ahk'],
mode: 'autohotkey'
},
{
name: 'batchfile',
label: 'Batch file',
alias: ['dos', 'windows', 'bat', 'cmd', 'btm'],
mode: 'batchfile'
},
{
name: 'cirru',
label: 'Cirru',
alias: [],
mode: 'cirru'
},
{
name: 'clojure',
label: 'Clojure',
alias: ['clj', 'cljs', 'cljc', 'edn'],
mode: 'clojure'
},
{
name: 'cobol',
label: 'COBOL',
alias: ['cbl', 'cob', 'cpy'],
mode: 'cobol'
},
{
name: 'coffee',
label: 'CoffeeScript',
alias: ['coffee'],
mode: 'coffee'
},
{
name: 'coldfusion',
label: 'ColdFusion',
alias: ['cfm', 'cfc'],
mode: 'coldfusion'
},
{
name: 'curly',
label: 'Curly',
alias: [],
mode: 'curly'
},
{
name: 'd',
label: 'D',
alias: ['dlang'],
mode: 'd'
},
{
name: 'dockerfile',
label: 'DockerFile',
alias: ['docker'],
mode: 'docker'
},
{
name: 'dart',
label: 'Dart',
alias: [],
mode: 'dart'
},
{
name: 'diff',
label: 'Diff',
alias: [],
mode: 'diff'
},
{
name: 'django',
label: 'Django',
alias: [],
mode: 'djt'
},
{
name: 'dot',
label: 'DOT',
alias: ['gv'],
mode: 'dot'
},
{
name: 'eiffel',
label: 'Eiffel',
alias: [],
mode: 'eiffel'
},
{
name: 'ejs',
label: 'EJS',
alias: [],
mode: 'ejs'
},
{
name: 'elixir',
label: 'Elixir',
alias: ['ex', 'exs'],
mode: 'elixir'
},
{
name: 'elm',
label: 'Elm',
alias: [],
mode: 'elm'
},
{
name: 'erlang',
label: 'Erlang',
alias: ['erl', 'hrl'],
mode: 'erlang'
},
{
name: 'forth',
label: 'Forth',
alias: ['fs', 'fth'],
mode: 'forth'
},
{
name: 'freemaker',
label: 'Freemaker',
alias: ['ftl'],
mode: 'ftl'
},
{
name: 'gcode',
label: 'G-code',
alias: ['mpt', 'mpf', 'nc'],
mode: 'gcode'
},
{
name: 'gherkin',
label: 'Gherkin',
alias: ['cucumber'],
mode: 'gherkin'
},
{
name: 'gitignore',
label: 'Gitignore',
alias: ['git'],
mode: 'gitignore'
},
{
name: 'glsl',
label: 'GLSL',
alias: ['opengl', 'shading'],
mode: 'glsl'
},
{
name: 'groovy',
label: 'Groovy',
alias: [],
mode: 'grooby'
},
{
name: 'haml',
label: 'Haml',
alias: [],
mode: 'haml'
},
{
name: 'handlebars',
label: 'Handlebars',
alias: ['hbs'],
mode: 'handlebars'
},
{
name: 'haskell',
label: 'Haskell',
alias: ['hs', 'lhs'],
mode: 'haskell'
},
{
name: 'haxe',
label: 'Haxe',
alias: ['hx', 'hxml'],
mode: 'haxe'
},
{
name: 'html_ruby',
label: 'HTML (Ruby)',
alias: ['erb', 'rhtml'],
mode: 'html_ruby'
},
{
name: 'jsx',
label: 'JSX',
alias: ['es', 'babel', 'js', 'jsx', 'react'],
mode: 'jsx'
},
{
name: 'typescript',
label: 'TypeScript',
alias: ['ts'],
mode: 'typescript'
},
{
name: 'ini',
label: 'INI file',
alias: [],
mode: 'ini'
},
{
name: 'io',
label: 'Io',
alias: [],
mode: 'io'
},
{
name: 'jack',
label: 'Jack',
alias: [],
mode: 'jack'
},
{
name: 'jade',
label: 'Jade',
alias: [],
mode: 'jade'
},
{
name: 'json',
label: 'JSON',
alias: [],
mode: 'json'
},
{
name: 'jsoniq',
label: 'JSONiq',
alias: ['query'],
mode: 'jsoniq'
},
{
name: 'jsp',
label: 'JSP',
alias: [],
mode: 'jsp'
},
{
name: 'julia',
label: 'Julia',
alias: [],
mode: 'julia'
},
{
name: 'latex',
label: 'Latex',
alias: ['tex'],
mode: 'latex'
},
{
name: 'lean',
label: 'Lean',
alias: [],
mode: 'lean'
},
{
name: 'less',
label: 'Less',
alias: [],
mode: 'less'
},
{
name: 'liquid',
label: 'Liquid',
alias: [],
mode: 'liquid'
},
{
name: 'lisp',
label: 'Lisp',
alias: ['lsp'],
mode: 'lisp'
},
{
name: 'livescript',
label: 'LiveScript',
alias: ['ls'],
mode: 'livescript'
},
{
name: 'logiql',
label: 'LogiQL',
alias: [],
mode: 'logiql'
},
{
name: 'lsl',
label: 'LSL',
alias: [],
mode: 'lsl'
},
{
name: 'lua',
label: 'Lua',
alias: [],
mode: 'lua'
},
{
name: 'luapage',
label: 'Luapage',
alias: [],
mode: 'luapage'
},
{
name: 'lucene',
label: 'Lucene',
alias: [],
mode: 'lucene'
},
{
name: 'makefile',
label: 'Makefile',
alias: [],
mode: 'makefile'
},
{
name: 'mask',
label: 'Mask',
alias: [],
mode: 'mask'
},
{
name: 'matlab',
label: 'MATLAB',
alias: [],
mode: 'matlab'
},
{
name: 'maze',
label: 'Maze',
alias: [],
mode: 'maze'
},
{
name: 'mel',
label: 'MEL',
alias: [],
mode: 'mel'
},
{
name: 'mipsassembler',
label: 'MIPS assembly',
alias: [],
mode: 'mipsassembler'
},
{
name: 'mushcode',
label: 'MUSHCode',
alias: [],
mode: 'mushcode'
},
{
name: 'mysql',
label: 'MySQL',
alias: [],
mode: 'mysql'
},
{
name: 'nix',
label: 'Nix',
alias: [],
mode: 'nix'
},
{
name: 'objectivec',
label: 'Objective C',
alias: ['objc'],
mode: 'objectivec'
},
{
name: 'ocaml',
label: 'OCaml',
alias: [],
mode: 'ocaml'
},
{
name: 'pascal',
label: 'Pascal',
alias: [],
mode: 'pascal'
},
{
name: 'perl',
label: 'Perl',
alias: [],
mode: 'perl'
},
{
name: 'pgsql',
label: 'Postgres SQL',
alias: ['postgres'],
mode: 'pgsql'
},
{
name: 'powershell',
label: 'PowerShell',
alias: ['ps1'],
mode: 'powershell'
},
{
name: 'praat',
label: 'Praat',
alias: [],
mode: 'praat'
},
{
name: 'prolog',
label: 'Prolog',
alias: ['pl', 'pro'],
mode: 'prolog'
},
{
name: 'properties',
label: 'Properties',
alias: [],
mode: 'properties'
},
{
name: 'protobuf',
label: 'Protocol Buffers',
alias: ['protocol', 'buffers'],
mode: 'protobuf'
},
{
name: 'r',
label: 'R',
alias: ['rlang'],
mode: 'r'
},
{
name: 'rdoc',
label: 'RDoc',
alias: [],
mode: 'rdoc'
},
{
name: 'rust',
label: 'Rust',
alias: [],
mode: 'rust'
},
{
name: 'sass',
label: 'Sass',
alias: [],
mode: 'sass'
},
{
name: 'scad',
label: 'SCAD',
alias: [],
mode: 'scad'
},
{
name: 'scala',
label: 'Scala',
alias: [],
mode: 'scala'
},
{
name: 'scheme',
label: 'Scheme',
alias: ['scm', 'ss'],
mode: 'scheme'
},
{
name: 'scss',
label: 'Scss',
alias: [],
mode: 'scss'
},
{
name: 'sh',
label: 'Shell',
alias: ['shell'],
mode: 'sh'
},
{
name: 'sjs',
label: 'StratifiedJS',
alias: ['stratified'],
mode: 'sjs'
},
{
name: 'smarty',
label: 'Smarty',
alias: [],
mode: 'smarty'
},
{
name: 'snippets',
label: 'Snippets',
alias: [],
mode: 'snippets'
},
{
name: 'soy_template',
label: 'Soy Template',
alias: ['soy'],
mode: 'soy_template'
},
{
name: 'space',
label: 'Space',
alias: [],
mode: 'space'
},
{
name: 'sql',
label: 'SQL',
alias: [],
mode: 'sql'
},
{
name: 'sqlserver',
label: 'SQL Server',
alias: [],
mode: 'sqlserver'
},
{
name: 'stylus',
label: 'Stylus',
alias: [],
mode: 'stylus'
},
{
name: 'svg',
label: 'SVG',
alias: [],
mode: 'svg'
},
{
name: 'swig',
label: 'SWIG',
alias: [],
mode: 'swig'
},
{
name: 'tcl',
label: 'Tcl',
alias: [],
mode: 'tcl'
},
{
name: 'tex',
label: 'TeX',
alias: [],
mode: 'tex'
},
{
name: 'textile',
label: 'Textile',
alias: [],
mode: 'textile'
},
{
name: 'toml',
label: 'TOML',
alias: [],
mode: 'toml'
},
{
name: 'twig',
label: 'Twig',
alias: [],
mode: 'twig'
},
{
name: 'vala',
label: 'Vala',
alias: [],
mode: 'vala'
},
{
name: 'vbscript',
label: 'VBScript',
alias: ['vbs', 'vbe'],
mode: 'vbscript'
},
{
name: 'velocity',
label: 'Velocity',
alias: [],
mode: 'velocity'
},
{
name: 'verilog',
label: 'Verilog',
alias: [],
mode: 'verilog'
},
{
name: 'vhdl',
label: 'VHDL',
alias: [],
mode: 'vhdl'
},
{
name: 'xml',
label: 'XML',
alias: [],
mode: 'xml'
},
{
name: 'xquery',
label: 'XQuery',
alias: [],
mode: 'xquery'
},
{
name: 'yaml',
label: 'YAML',
alias: [],
mode: 'yaml'
}
]
export default modes