Ghost/ghost/admin/lib/koenig-editor/addon/components/koenig-caption-input.js
Kevin Ansfield 927a977257 Fixed focus not fully returning to editor after pressing escape in caption input
no issue

- forced card deselection+reselection so that keys such as `Enter` and `Backspace` work as expected when the card is shown as selected
2021-11-30 18:06:17 +00:00

161 lines
4.4 KiB
JavaScript

import Component from '@ember/component';
import Key from 'mobiledoc-kit/utils/key';
import {computed} from '@ember/object';
import {kgStyle} from '../helpers/kg-style';
import {run} from '@ember/runloop';
import {inject as service} from '@ember/service';
export default Component.extend({
koenigUi: service(),
tagName: 'figcaption',
classNameBindings: ['figCaptionClass'],
caption: '',
captureInput: false,
placeholder: '',
_keypressHandler: null,
_keydownHandler: null,
update() {},
addParagraphAfterCard() {},
moveCursorToNextSection() {},
moveCursorToPrevSection() {},
figCaptionClass: computed(function () {
return `${kgStyle(['figcaption'])} w-100 relative`;
}),
didReceiveAttrs() {
this._super(...arguments);
if (this.captureInput && !this._keypressHandler) {
this._attachHandlers();
}
if (!this.captureInput && this._keypressHandler) {
this._detachHandlers();
}
},
willDestroyElement() {
this._super(...arguments);
this.koenigUi.captionLostFocus(this);
this._detachHandlers();
},
actions: {
registerEditor(editor) {
let commands = {
ENTER: run.bind(this, this._enter),
ESC: run.bind(this, this._escape),
UP: run.bind(this, this._upOrLeft),
LEFT: run.bind(this, this._upOrLeft),
DOWN: run.bind(this, this._rightOrDown),
RIGHT: run.bind(this, this._rightOrDown)
};
Object.keys(commands).forEach((str) => {
editor.registerKeyCommand({
str,
run() {
return commands[str](editor, str);
}
});
});
this.editor = editor;
},
handleEnter() {
this.addParagraphAfterCard();
}
},
// events ------------------------------------------------------------------
focusIn() {
this.koenigUi.captionGainedFocus(this);
},
focusOut() {
this.koenigUi.captionLostFocus(this);
},
// private -----------------------------------------------------------------
_attachHandlers() {
if (!this._keypressHandler) {
this._keypressHandler = run.bind(this, this._handleKeypress);
window.addEventListener('keypress', this._keypressHandler);
}
},
_detachHandlers() {
window.removeEventListener('keypress', this._keypressHandler);
this._keypressHandler = null;
this._keydownHandler = null;
},
// only fires if the card is selected, moves focus to the caption input so
// that it's possible to start typing without explicitly focusing the input
_handleKeypress(event) {
let key = new Key(event);
let {editor} = this;
if (event.target.matches('[data-kg="editor"]') && editor && !editor._hasFocus() && key.isPrintableKey() && !key.isEnter()) {
editor.focus();
editor.run((postEditor) => {
postEditor.insertText(editor.post.tailPosition(), key.toString());
});
event.preventDefault();
}
},
/* key commands ----------------------------------------------------------*/
_enter() {
this.send('handleEnter');
},
_escape(editor) {
editor.element.blur();
this.deselectCard();
this.selectCard();
},
_upOrLeft(editor, key) {
let {isCollapsed, head} = editor.range;
if (isCollapsed && head.isEqual(head.section.headPosition())) {
return this.moveCursorToPrevSection();
}
// we're simulating a text input so up/down move the cursor to the
// beginning/end of the input
if (isCollapsed && key === 'UP') {
return editor.selectRange(head.section.headPosition().toRange());
}
return false;
},
_rightOrDown(editor, key) {
let {isCollapsed, tail} = editor.range;
if (isCollapsed && tail.isEqual(tail.section.tailPosition())) {
return this.moveCursorToNextSection();
}
// we're simulating a text input so up/down move the cursor to the
// beginning/end of the input
if (isCollapsed && key === 'DOWN') {
return editor.selectRange(tail.section.tailPosition().toRange());
}
return false;
}
});