2021-11-19 22:07:40 +03:00
|
|
|
import Component from '@glimmer/component';
|
|
|
|
import {action} from '@ember/object';
|
|
|
|
import {run} from '@ember/runloop';
|
|
|
|
|
2021-11-23 18:03:53 +03:00
|
|
|
const Y_OFFSET = 40;
|
2021-11-19 22:07:40 +03:00
|
|
|
|
|
|
|
export default class KoenigMediaSelectorComponent extends Component {
|
|
|
|
constructor() {
|
|
|
|
super(...arguments);
|
|
|
|
|
|
|
|
// store editor range for later because it might change if focus is lost
|
|
|
|
this._editorRange = this.args.editorRange;
|
2021-11-19 22:51:45 +03:00
|
|
|
|
|
|
|
// store scroll position before anything else renders
|
|
|
|
const scrollContainer = document.querySelector(this.args.scrollContainerSelector);
|
|
|
|
this._scrollTop = scrollContainer.scrollTop;
|
2021-11-19 22:07:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
willDestroy() {
|
|
|
|
super.willDestroy(...arguments);
|
|
|
|
window.removeEventListener('click', this.handleBackgroundClick);
|
|
|
|
}
|
|
|
|
|
|
|
|
@action
|
|
|
|
didInsertContainer(containerElem) {
|
|
|
|
this._containerElem = containerElem;
|
|
|
|
|
|
|
|
this._positionSelector(this._editorRange);
|
2021-11-19 22:51:45 +03:00
|
|
|
this.resetScrollPosition();
|
2021-11-19 22:07:40 +03:00
|
|
|
|
|
|
|
// any click outside of the selector should close it and clear any /command
|
|
|
|
// add with 1ms delay so current event loop finishes to avoid instaclose
|
|
|
|
run.later(() => {
|
|
|
|
window.addEventListener('click', this.handleBackgroundClick);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-11-19 22:51:45 +03:00
|
|
|
@action
|
|
|
|
resetScrollPosition() {
|
|
|
|
const scrollContainer = document.querySelector(this.args.scrollContainerSelector);
|
2021-11-23 19:35:44 +03:00
|
|
|
const scrollContainerRect = scrollContainer.getBoundingClientRect();
|
|
|
|
const containerRect = this._containerElem.getBoundingClientRect();
|
|
|
|
|
|
|
|
let scrollTop = this._scrollTop;
|
|
|
|
|
|
|
|
const scrollBottom = scrollTop + scrollContainerRect.height;
|
|
|
|
const containerBottom = scrollTop + containerRect.bottom;
|
|
|
|
|
|
|
|
if (containerBottom > scrollBottom) {
|
|
|
|
// bottom of selector is cut-off, scroll it into view
|
|
|
|
|
|
|
|
const amountCutOffBottom = containerBottom - scrollBottom;
|
|
|
|
|
|
|
|
// container 600px - inner container 540px = 60px of shadow
|
|
|
|
// cut 40px off to give a 20px spacing from bottom of screen
|
|
|
|
const bottomBuffer = 40;
|
|
|
|
|
|
|
|
let scrollAdjustment = amountCutOffBottom - bottomBuffer;
|
|
|
|
|
|
|
|
// don't scroll so much the top of the container gets hidden
|
|
|
|
const newContainerTop = containerRect.top - scrollAdjustment;
|
|
|
|
const minDistanceFromTop = 20;
|
|
|
|
if (newContainerTop < minDistanceFromTop) {
|
|
|
|
const amountCutOffTop = Math.abs(newContainerTop - minDistanceFromTop);
|
|
|
|
scrollAdjustment = scrollAdjustment - amountCutOffTop;
|
|
|
|
}
|
|
|
|
|
|
|
|
scrollTop = scrollTop + scrollAdjustment;
|
|
|
|
}
|
|
|
|
|
|
|
|
scrollContainer.scrollTop = scrollTop;
|
2021-11-19 22:51:45 +03:00
|
|
|
}
|
|
|
|
|
2021-11-19 22:07:40 +03:00
|
|
|
@action
|
|
|
|
insertCard(cardName, payload) {
|
|
|
|
this.args.replaceWithCardSection(cardName, this._editorRange, payload);
|
|
|
|
this.args.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
@action
|
|
|
|
handleBackgroundClick(event) {
|
|
|
|
if (!this._containerElem.contains(event.target)) {
|
|
|
|
this.args.editor.run((postEditor) => {
|
|
|
|
postEditor.deleteRange(this._editorRange.tail.section.toRange());
|
|
|
|
});
|
|
|
|
this.args.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@action
|
|
|
|
handleEscape() {
|
|
|
|
this.args.close();
|
|
|
|
this.args.editor.selectRange(this._editorRange.tail);
|
|
|
|
}
|
|
|
|
|
|
|
|
_positionSelector(range) {
|
2021-11-23 19:35:44 +03:00
|
|
|
const {head: {section}} = range;
|
2021-11-19 22:07:40 +03:00
|
|
|
|
|
|
|
if (section && section.renderNode.element) {
|
2021-11-23 19:35:44 +03:00
|
|
|
const containerRect = this._containerElem.parentNode.getBoundingClientRect();
|
|
|
|
const selectedElement = section.renderNode.element;
|
|
|
|
const selectedElementRect = selectedElement.getBoundingClientRect();
|
|
|
|
const top = selectedElementRect.top - containerRect.top + Y_OFFSET;
|
2021-11-19 22:07:40 +03:00
|
|
|
|
|
|
|
this._containerElem.style.top = `${top}px`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|