Ghost/ghost/admin/lib/koenig-editor/addon/components/koenig-settings-panel.js
Kevin Ansfield 8cc4c6c4a1 Dropped ember-concurrency-decorators dependency
no issue

- since `ember-concurrency@2.0` it's possible to use the standard imports as decorators removing the need for the extra `ember-concurrency-decorators` dependency and imports
2022-02-09 10:49:38 +00:00

94 lines
3.0 KiB
JavaScript

import Component from '@glimmer/component';
import {action} from '@ember/object';
import {bind} from '@ember/runloop';
import {task} from 'ember-concurrency';
import {timeout} from 'ember-concurrency';
const CARD_SPACING = 20;
const MIN_RIGHT_SPACING = 20;
const MIN_TOP_SPACING = 66 + 20; // 66 is publish menu and word count size
export default class KoenigSettingsPanelComponent extends Component {
constructor() {
super(...arguments);
this._windowResizeHandler = bind(this, this.debounceWindowResizeTask.perform);
window.addEventListener('resize', this._windowResizeHandler);
}
willDestroy() {
super.willDestroy(...arguments);
window.removeEventListener('resize', this._windowResizeHandler);
}
@action
registerAndPosition(panelElem) {
this.panelElem = panelElem;
this.positionPanel(panelElem);
}
@action
positionPanel(panelElem) {
if (!panelElem) {
return;
}
const panelRect = panelElem.getBoundingClientRect();
const containerRect = panelElem.parentElement.getBoundingClientRect();
const containerMiddle = containerRect.top + (containerRect.height / 2);
// position vertically centered
// if part of panel would be off screen adjust to keep minimum distance from window top/botom
let top = Math.max(containerMiddle - (panelRect.height / 2), MIN_TOP_SPACING);
if (top + panelRect.height > window.innerHeight - MIN_TOP_SPACING) {
top = window.innerHeight - MIN_TOP_SPACING - panelRect.height;
}
// position to right of panel
// if part of panel would be off screen adjust to keep minimum distance from window edge
let left = containerRect.right + CARD_SPACING;
if (left + panelRect.width > window.innerWidth - MIN_RIGHT_SPACING) {
left = window.innerWidth - panelRect.width - MIN_RIGHT_SPACING;
}
panelElem.style.top = `${top}px`;
panelElem.style.left = `${left}px`;
}
@task({restartable: true})
*debounceWindowResizeTask() {
yield timeout(250);
this.positionPanel(this.panelElem);
}
// called when panel is expanded/collapsed by changing settings
@action
calculateResizeAdjustment(panelElem, {x, y}) {
const panelRect = panelElem.getBoundingClientRect();
const topIsOffscreen = panelRect.top < 0;
const bottomIsOffscreen = panelRect.bottom > window.innerHeight;
if (topIsOffscreen && bottomIsOffscreen) {
// there's not much we can do here, the screen is too small.
// leave as-is to avoid any weird jumping
return {x, y};
}
if (topIsOffscreen) {
const yAdjustment = Math.abs(panelRect.top) + 10;
return {x, y: y + yAdjustment};
}
if (bottomIsOffscreen) {
const yAdjustment = -Math.abs(panelRect.bottom - window.innerHeight) - 10;
return {x, y: y + yAdjustment};
}
// no adjustment needed
return {x, y};
}
}