@alegendstale/holly-components
Version:
Reusable UI components created using lit
120 lines (117 loc) • 3.8 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { LitElement, html, css } from 'lit';
import { property, state } from 'lit/decorators.js';
import { createRef, ref } from 'lit/directives/ref.js';
import { styleMap } from 'lit/directives/style-map.js';
import { EventEmitter } from '../../utils/EventEmitter.js';
import { condCustomElement } from '../../decorators/condCustomElement.js';
let AbsoluteContainer = class AbsoluteContainer extends LitElement {
constructor() {
super(...arguments);
this.dialogRef = createRef();
this._open = false;
this.left = 0;
this.top = 0;
this.emitter = new EventEmitter();
/**
* Disables the ContextEvent (right click, or long touch)
*
* Useful for context menus
*/
this.disableContextEvent = false;
}
set open(val) {
this._open = val;
requestAnimationFrame(() => {
if (!this.dialogRef.value)
return;
let dialog = this.dialogRef.value;
if (dialog.open)
dialog.close();
else
dialog.showModal();
});
this.emitter.emit('visibility', val);
}
get open() {
return this._open;
}
disconnectedCallback() {
super.disconnectedCallback();
this.emitter.clear();
}
render() {
const dialogStyles = {
inset: this.left === 0 && this.top === 0 ? 0 : 'unset',
left: `${this.left}px`,
top: `${this.top}px`,
};
return html `
<dialog
part='dialog'
style=${styleMap(dialogStyles)}
=${(e) => {
if (!(e.target instanceof HTMLElement))
return;
const outsideWidthBounds = e.offsetX < 0 || e.offsetX > e.target.offsetWidth;
const outsideHeightBounds = e.offsetY < 0 || e.offsetY > e.target.offsetHeight;
// Check if cursor is inside element bounds. Close dialog if it isn't.
if (outsideWidthBounds || outsideHeightBounds)
this.open = false;
}}
=${(e) => this.disableContextEvent && e.preventDefault()}
${ref(this.dialogRef)}
>
<slot></slot>
</dialog>
`;
}
toggle() {
this.open = !this.open;
}
setOpen(val) {
this.open = val;
}
setPosition(left, top) {
this.left = left;
this.top = top;
}
};
AbsoluteContainer.styles = [
css `
:host {
display: block;
}
dialog {
width: min-content;
border: 0;
padding: 0;
background-color: transparent;
scrollbar-width: thin;
&::backdrop {
background-color: transparent;
}
}
`
];
__decorate([
property({ type: Boolean, reflect: true })
], AbsoluteContainer.prototype, "open", null);
__decorate([
state()
], AbsoluteContainer.prototype, "left", void 0);
__decorate([
state()
], AbsoluteContainer.prototype, "top", void 0);
__decorate([
property({ type: Boolean, reflect: true })
], AbsoluteContainer.prototype, "disableContextEvent", void 0);
AbsoluteContainer = __decorate([
condCustomElement('absolute-container')
], AbsoluteContainer);
export { AbsoluteContainer };