diff options
author | Shin'ya Ueoka <ueokande@i-beam.org> | 2017-11-22 22:38:34 +0900 |
---|---|---|
committer | Shin'ya Ueoka <ueokande@i-beam.org> | 2017-11-26 11:40:12 +0900 |
commit | 4e5ddc1d57ba4f42314eb49ae57a9b67950be596 (patch) | |
tree | c43db0b38d030446cbbde392d63cd7faf2d6f533 /src/settings/components | |
parent | d33b37cdb9d2956f5f2d23ab4e71e35db137b16e (diff) |
Add keybindings form
Diffstat (limited to 'src/settings/components')
-rw-r--r-- | src/settings/components/index.jsx | 139 | ||||
-rw-r--r-- | src/settings/components/site.scss | 27 | ||||
-rw-r--r-- | src/settings/components/ui/input.jsx | 35 | ||||
-rw-r--r-- | src/settings/components/ui/input.scss | 37 |
4 files changed, 197 insertions, 41 deletions
diff --git a/src/settings/components/index.jsx b/src/settings/components/index.jsx index 98d8fb2..11411bd 100644 --- a/src/settings/components/index.jsx +++ b/src/settings/components/index.jsx @@ -4,6 +4,59 @@ import Input from './ui/input'; import * as settingActions from 'settings/actions/setting'; import * as validator from 'shared/validators/setting'; +const KeyMapFields = [ + [ + ['scroll.vertically?{count:-1}', 'Scroll down'], + ['scroll.vertically?{count:1}', 'Scroll up'], + ['scroll.horizonally?{count:-1}', 'Scroll left'], + ['scroll.horizonally?{count:1}', 'Scroll right'], + ['scroll.home', 'Scroll leftmost'], + ['scroll.end', 'Scroll last'], + ['scroll.pages?{count:-0.5}', 'Scroll up by half of screen'], + ['scroll.pages?{count:0.5}', 'Scroll up by half of screen'], + ['scroll.pages?{count:-1}', 'Scroll up by a screen'], + ['scroll.pages?{count:1}', 'Scroll up by a screen'], + ], [ + ['tabs.close', 'Close a tab'], + ['tabs.reopen', 'Reopen closed tab'], + ['tabs.next?{count:1}', 'Select next Tab'], + ['tabs.prev?{count:1}', 'Select prev Tab'], + ['tabs.first', 'Select first tab'], + ['tabs.last', 'Select last tab'], + ['tabs.reload?{cache:true}', 'Reload current tab'], + ['tabs.pin.toggle', 'Toggle pinned state'], + ['tabs.duplicate', 'Dupplicate a tab'], + ], [ + ['follow.start?{newTab:false}', 'Follow a link'], + ['follow.start?{newTab:true}', 'Follow a link in new tab'], + ['navigate.histories.prev', 'Go back in histories'], + ['navigate.histories.next', 'Go forward in histories'], + ['navigate.link.next', 'Open next link'], + ['navigate.link.prev', 'Open previous link'], + ['navigate.parent', 'Go to parent directory'], + ['navigate.root', 'Go to root directory'], + ], [ + ['find.start', 'Start find mode'], + ['find.next', 'Find next word'], + ['find.prev', 'Find previous word'], + ], [ + ['command.show', 'Open console'], + ['command.show.open?{alter:false}', 'Open URL'], + ['command.show.open?{alter:true}', 'Alter URL'], + ['command.show.tabopen?{alter:false}', 'Open URL in new Tab'], + ['command.show.tabopen?{alter:true}', 'Alter URL in new Tab'], + ['command.show.winopen?{alter:false}', 'Open URL in new window'], + ['command.show.winopen?{alter:true}', 'Alter URL in new window'], + ['command.show.buffer', 'Open buffer command'], + ], [ + ['addon.toggle.enabled', 'Enable or disable'], + ['urls.yank', 'Copy current URL'], + ['zoom.in', 'Zoom-in'], + ['zoom.out', 'Zoom-out'], + ['zoom.neutral', 'Reset zoom level'], + ] +]; + class SettingsComponent extends Component { constructor(props, context) { super(props, context); @@ -29,33 +82,87 @@ class SettingsComponent extends Component { settings: { source: settings.source, json: settings.json, + form: settings.form, } }); } + renderFormFields() { + let keymapFields = KeyMapFields.map((group, index) => { + return <div key={index} className='keymap-fields-group'> + { + group.map((field) => { + let name = field[0]; + let label = field[1]; + let value = this.state.settings.form.keymaps[name]; + return <Input + type='text' + id={name} + name={name} + key={name} + label={label} + value={value} + onChange={this.bindFormKeymapsValue.bind(this)} + />; + }) + } + </div>; + }); + + return <div> + <fieldset> + <legend>Keybindings</legend> + <div className='keymap-fields'> + { keymapFields } + </div> + </fieldset> + </div>; + } + + renderJsonFields() { + return <div> + <Input + type='textarea' + name='json' + label='Plane JSON' + spellCheck='false' + error={this.state.errors.json} + onChange={this.bindValue.bind(this)} + onBlur={this.save.bind(this)} + value={this.state.settings.json} + /> + </div>; + } + render() { + let fields = null; + if (this.state.settings.source === 'form') { + fields = this.renderFormFields(); + } else if (this.state.settings.source === 'json') { + fields = this.renderJsonFields(); + } return ( <div> <h1>Configure Vim-Vixen</h1> <form className='vimvixen-settings-form'> + <Input + type='radio' + id='setting-source-form' + name='source' + label='Use form' + checked={this.state.settings.source === 'form'} + value='form' + onChange={this.bindValue.bind(this)} /> <Input type='radio' name='source' label='Use plain JSON' checked={this.state.settings.source === 'json'} - value='json' /> + value='json' + onChange={this.bindValue.bind(this)} /> - <Input - type='textarea' - name='json' - label='Plane JSON' - spellCheck='false' - error={this.state.errors.json} - onChange={this.bindValue.bind(this)} - onBlur={this.bindAndSave.bind(this)} - value={this.state.settings.json} - /> + { fields } </form> </div> ); @@ -82,9 +189,15 @@ class SettingsComponent extends Component { this.setState(next); } - bindAndSave(e) { - this.bindValue(e); + bindFormKeymapsValue(e) { + let next = Object.assign({}, this.state); + + next.settings.form.keymaps[e.target.name] = e.target.value; + + this.context.store.dispatch(settingActions.save(next.settings)); + } + save() { try { let json = this.state.settings.json; validator.validate(JSON.parse(json)); diff --git a/src/settings/components/site.scss b/src/settings/components/site.scss index aac4319..dcc52ce 100644 --- a/src/settings/components/site.scss +++ b/src/settings/components/site.scss @@ -7,4 +7,31 @@ min-height: 64ex; resize: vertical; } + + fieldset { + margin: 0; + padding: 0; + border: none; + margin-top: 1rem; + + fieldset:first-of-type { + margin-top: 1rem; + } + + legend { + font-size: 1.5rem; + line-height: 1.5rem; + font-weight: bold; + } + } + + .keymap-fields{ + column-count: 2; + .keymap-fields-group { + margin-top: 24px; + } + .keymap-fields-group:first-of-type { + margin-top: 0; + } + } } diff --git a/src/settings/components/ui/input.jsx b/src/settings/components/ui/input.jsx index 9b6c229..5138411 100644 --- a/src/settings/components/ui/input.jsx +++ b/src/settings/components/ui/input.jsx @@ -3,32 +3,35 @@ import './input.scss'; class Input extends Component { + renderText(props) { + let inputClassName = props.error ? 'input-error' : ''; + return <div className='settings-ui-input'> + <label + type='text' + htmlFor={props.id} + >{ props.label }</label> + <input type='text' className={inputClassName} {...props} /> + </div>; + } + renderRadio(props) { - let inputClasses = 'form-field-input'; - if (props.error) { - inputClasses += ' input-error'; - } - return <div> + let inputClassName = props.error ? 'input-error' : ''; + return <div className='settings-ui-input'> <label> - <input className={ inputClasses } type='radio' {...props} /> + <input type='radio' className={inputClassName} {...props} /> { props.label } </label> </div>; } renderTextArea(props) { - let inputClasses = 'form-field-input'; - if (props.error) { - inputClasses += ' input-error'; - } - return <div> + let inputClassName = props.error ? 'input-error' : ''; + return <div className='settings-ui-input'> <label - className='form-field-label' htmlFor={props.id} >{ props.label }</label> - <textarea className={inputClasses} {...props} /> - - <p className='form-field-error'>{ this.props.error }</p> + <textarea className={inputClassName} {...props} /> + <p className='settings-ui-input-error'>{ this.props.error }</p> </div>; } @@ -36,6 +39,8 @@ class Input extends Component { let { type } = this.props; switch (this.props.type) { + case 'text': + return this.renderText(this.props); case 'radio': return this.renderRadio(this.props); case 'textarea': diff --git a/src/settings/components/ui/input.scss b/src/settings/components/ui/input.scss index 6187138..92df712 100644 --- a/src/settings/components/ui/input.scss +++ b/src/settings/components/ui/input.scss @@ -1,17 +1,28 @@ -.form-field-label { - font-weight: bold -} +.settings-ui-input { + page-break-inside: avoid; -.form-field-error { - font-weight: bold; - color: red; - min-height: 1.5em; -} + * { + page-break-inside: avoid; + } -.form-field-input { - padding: 4px; -} + label { + font-weight: bold; + min-width: 14rem; + display: inline-block; + } + + input { + padding: 4px; + } + + input.input-crror, + textarea.input-error { + box-shadow: 0 0 2px red; + } -.form-field-input.input-error { - box-shadow: 0 0 2px red; + &-error { + font-weight: bold; + color: red; + min-height: 1.5em; + } } |