Movable and click-through for non-modals
This commit is contained in:
+90
-4
@@ -39,7 +39,7 @@ class TpDialog extends EventHelpers(LitElement) {
|
||||
z-index: 900;
|
||||
}
|
||||
|
||||
:host([open]) {
|
||||
:host([open][modal]) {
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
@@ -50,24 +50,39 @@ class TpDialog extends EventHelpers(LitElement) {
|
||||
color: var(--text);
|
||||
border: var(--tp-dialog-border);
|
||||
padding: var(--tp-dialog-padding);
|
||||
pointer-events: all;
|
||||
transform: translate(var(--tp-dialog-offset-x, 0px), var(--tp-dialog-offset-y, 0px));
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
top: 5px;
|
||||
z-index: 1;
|
||||
z-index: 3;
|
||||
--tp-icon-width: 18px;
|
||||
--tp-icon-height: 18px;
|
||||
}
|
||||
|
||||
.drag-handle {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 30px;
|
||||
cursor: move;
|
||||
z-index: 2;
|
||||
}
|
||||
`
|
||||
];
|
||||
}
|
||||
|
||||
render() {
|
||||
const { showClose } = this;
|
||||
const { showClose, unmovable } = this;
|
||||
return html`
|
||||
<dialog part="dialog">
|
||||
${!unmovable ? html`
|
||||
<div class="drag-handle" part="drag-handle" @pointerdown=${this._onDragStart}></div>
|
||||
` : null}
|
||||
${showClose ? html`
|
||||
<div class="close-icon" part="close-icon">
|
||||
<tp-icon .icon=${this.icon ? this.icon : TpDialog.closeIcon} dialog-dismiss></tp-icon>
|
||||
@@ -85,6 +100,8 @@ class TpDialog extends EventHelpers(LitElement) {
|
||||
icon: { type: Object },
|
||||
closeOnEsc: { type: Boolean },
|
||||
closeOnOutsideClick: { type: Boolean },
|
||||
modal: { type: Boolean, reflect: true },
|
||||
unmovable: { type: Boolean, reflect: true },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -100,6 +117,10 @@ class TpDialog extends EventHelpers(LitElement) {
|
||||
super();
|
||||
this._currentPromise = null;
|
||||
this._resolvePromise = null;
|
||||
this.modal = false;
|
||||
this.unmovable = false;
|
||||
this._offsetX = 0;
|
||||
this._offsetY = 0;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
@@ -117,6 +138,15 @@ class TpDialog extends EventHelpers(LitElement) {
|
||||
this.unlisten(this, 'confirmed', '_handleConfirmed');
|
||||
this.unlisten(this, 'dismissed', '_handleDismissed');
|
||||
|
||||
// Clean up pointer drag listeners
|
||||
if (this._boundDragMove) {
|
||||
window.removeEventListener('pointermove', this._boundDragMove);
|
||||
}
|
||||
if (this._boundDragEnd) {
|
||||
window.removeEventListener('pointerup', this._boundDragEnd);
|
||||
window.removeEventListener('pointercancel', this._boundDragEnd);
|
||||
}
|
||||
|
||||
// Remove this dialog from the stack
|
||||
this._removeFromDialogStack();
|
||||
|
||||
@@ -129,6 +159,8 @@ class TpDialog extends EventHelpers(LitElement) {
|
||||
}
|
||||
|
||||
show() {
|
||||
this.modal = false;
|
||||
this._resetPosition();
|
||||
this.dialog.show();
|
||||
this.open = true;
|
||||
|
||||
@@ -144,6 +176,8 @@ class TpDialog extends EventHelpers(LitElement) {
|
||||
}
|
||||
|
||||
showModal() {
|
||||
this.modal = true;
|
||||
this._resetPosition();
|
||||
this.dialog.showModal();
|
||||
this.open = true;
|
||||
|
||||
@@ -183,6 +217,58 @@ class TpDialog extends EventHelpers(LitElement) {
|
||||
}
|
||||
}
|
||||
|
||||
_resetPosition() {
|
||||
this._offsetX = 0;
|
||||
this._offsetY = 0;
|
||||
this.style.removeProperty('--tp-dialog-offset-x');
|
||||
this.style.removeProperty('--tp-dialog-offset-y');
|
||||
}
|
||||
|
||||
_onDragStart(e) {
|
||||
if (this.unmovable) return;
|
||||
if (e.button !== 0) return; // Only drag with left/main pointer button
|
||||
|
||||
this._startX = e.clientX;
|
||||
this._startY = e.clientY;
|
||||
this._startOffsetX = this._offsetX || 0;
|
||||
this._startOffsetY = this._offsetY || 0;
|
||||
|
||||
const dragHandle = this.shadowRoot.querySelector('.drag-handle');
|
||||
if (dragHandle && typeof dragHandle.setPointerCapture === 'function') {
|
||||
dragHandle.setPointerCapture(e.pointerId);
|
||||
}
|
||||
|
||||
this._boundDragMove = this._onDragMove.bind(this);
|
||||
this._boundDragEnd = this._onDragEnd.bind(this);
|
||||
|
||||
window.addEventListener('pointermove', this._boundDragMove);
|
||||
window.addEventListener('pointerup', this._boundDragEnd);
|
||||
window.addEventListener('pointercancel', this._boundDragEnd);
|
||||
}
|
||||
|
||||
_onDragMove(e) {
|
||||
const dx = e.clientX - this._startX;
|
||||
const dy = e.clientY - this._startY;
|
||||
this._offsetX = this._startOffsetX + dx;
|
||||
this._offsetY = this._startOffsetY + dy;
|
||||
|
||||
this.style.setProperty('--tp-dialog-offset-x', `${this._offsetX}px`);
|
||||
this.style.setProperty('--tp-dialog-offset-y', `${this._offsetY}px`);
|
||||
}
|
||||
|
||||
_onDragEnd(e) {
|
||||
const dragHandle = this.shadowRoot.querySelector('.drag-handle');
|
||||
if (dragHandle && typeof dragHandle.releasePointerCapture === 'function') {
|
||||
try {
|
||||
dragHandle.releasePointerCapture(e.pointerId);
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
window.removeEventListener('pointermove', this._boundDragMove);
|
||||
window.removeEventListener('pointerup', this._boundDragEnd);
|
||||
window.removeEventListener('pointercancel', this._boundDragEnd);
|
||||
}
|
||||
|
||||
_handleConfirmed(event) {
|
||||
if (this._currentPromise && this._resolvePromise) {
|
||||
this._resolvePromise('confirmed');
|
||||
@@ -267,4 +353,4 @@ class TpDialog extends EventHelpers(LitElement) {
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('tp-dialog', TpDialog);
|
||||
window.customElements.define('tp-dialog', TpDialog);
|
||||
Reference in New Issue
Block a user