Initial version
This commit is contained in:
parent
0625869d76
commit
69690793be
13
package-lock.json
generated
Normal file
13
package-lock.json
generated
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "@tp/tp-popup",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@tp/helpers": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://verdaccio.codeblob.work/@tp%2fhelpers/-/helpers-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-f6pDPw4QpjWnmVkYgOHjMXQXtGB4vbA45eZV9DjCF9OoCXsa+Pz32H2rLQRKbdpsfFllywOBI+GMGPYDJyrG/Q=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,19 @@
|
|||||||
{
|
{
|
||||||
"name": "@tp/tp-element",
|
"name": "@tp/tp-popup",
|
||||||
"version": "0.0.1",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "tp-element.js",
|
"main": "tp-popup.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://gitea.codeblob.work/tp-elements/tp-element.git"
|
"url": "https://gitea.codeblob.work/tp-elements/tp-popup.git"
|
||||||
},
|
},
|
||||||
"author": "trading_peter",
|
"author": "trading_peter",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@tp/helpers": "^1.0.1",
|
||||||
"lit": "^2.2.0"
|
"lit": "^2.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
/**
|
|
||||||
@license
|
|
||||||
Copyright (c) 2022 trading_peter
|
|
||||||
This program is available under Apache License Version 2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { LitElement, html, css } from 'lit';
|
|
||||||
|
|
||||||
class TpElement extends LitElement {
|
|
||||||
static get styles() {
|
|
||||||
return [
|
|
||||||
css`
|
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { } = this;
|
|
||||||
|
|
||||||
return html`
|
|
||||||
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get properties() {
|
|
||||||
return { };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
window.customElements.define('tp-element', TpElement);
|
|
201
tp-popup.js
Normal file
201
tp-popup.js
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
/**
|
||||||
|
@license
|
||||||
|
Copyright (c) 2022 trading_peter
|
||||||
|
This program is available under Apache License Version 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { LitElement, html, css } from 'lit';
|
||||||
|
import { DomQuery } from '@tp/helpers/dom-query.js';
|
||||||
|
import { Position } from '@tp/helpers/position.js';
|
||||||
|
import { EventHelpers } from '@tp/helpers/event-helpers.js';
|
||||||
|
import { closest } from '@tp/helpers/closest.js';
|
||||||
|
|
||||||
|
class TpPopup extends EventHelpers(Position(DomQuery(LitElement))) {
|
||||||
|
static get styles() {
|
||||||
|
return [
|
||||||
|
css`
|
||||||
|
:host {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
pointer-events: none;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1;
|
||||||
|
margin-top: 5px;
|
||||||
|
transition: opacity 180ms;
|
||||||
|
opacity: 0;
|
||||||
|
border-radius: 2px;
|
||||||
|
box-shadow: var(--tp-popup-shadow, none);
|
||||||
|
}
|
||||||
|
|
||||||
|
#content[open] {
|
||||||
|
pointer-events: all;
|
||||||
|
opacity: 1;
|
||||||
|
background: var(--tp-popup-background, #F5F5F5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#content .content-wrap {
|
||||||
|
padding: var(--tp-popup-content-padding, 10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 0) and (max-width: 480px) {
|
||||||
|
:host(:not([not-responsive])) #content {
|
||||||
|
bottom: 0 !important;
|
||||||
|
top: auto !important;
|
||||||
|
right: 0 !important;
|
||||||
|
left: 0 !important;
|
||||||
|
margin-top: 0;
|
||||||
|
transition: transform 0.3s, opacity 0.3s;
|
||||||
|
transform: translateY(100%);
|
||||||
|
max-height: 80%;
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
box-shadow: var(--tp-popup-shadow-responsive, none);
|
||||||
|
}
|
||||||
|
|
||||||
|
:host(:not([not-responsive])) #content[open] {
|
||||||
|
transform: translateY(0%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { isOpen } = this;
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<div class="wrap">
|
||||||
|
<div class="toggle">
|
||||||
|
<slot id="toggleContent" name="toggle"></slot>
|
||||||
|
</div>
|
||||||
|
<div id="content" ?open=${isOpen}>
|
||||||
|
<div class="content-wrap">
|
||||||
|
<slot id="contentSlot" name="content"></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
isOpen: { type: Boolean, reflect: true },
|
||||||
|
alwaysToggle: { type: Boolean, reflect: true },
|
||||||
|
halign: { type: String },
|
||||||
|
valign: { type: String },
|
||||||
|
scrollTarget: { type: Object }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.isOpen = false;
|
||||||
|
this.alwaysToggle = false;
|
||||||
|
this.halign = 'middle';
|
||||||
|
this.valign = 'bottom';
|
||||||
|
this.scrollTarget = document;
|
||||||
|
this.fit = this.fit.bind(this);
|
||||||
|
this._onDocClickHandler = () => this.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
get toggleEl() {
|
||||||
|
if (!this._toggleEl) {
|
||||||
|
this._toggleEl = this.querySelector('[slot="toggle"]');
|
||||||
|
}
|
||||||
|
return this._toggleEl;
|
||||||
|
}
|
||||||
|
|
||||||
|
firstUpdated() {
|
||||||
|
super.firstUpdated();
|
||||||
|
|
||||||
|
this.listen(this, 'click', '_onClick');
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnectedCallback() {
|
||||||
|
super.disconnectedCallback();
|
||||||
|
this._cleanupEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.isOpen = false;
|
||||||
|
this._cleanupEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
open() {
|
||||||
|
this.updateComplete.then(() => {
|
||||||
|
this.fit();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.isOpen = true;
|
||||||
|
|
||||||
|
this._registerEvents();
|
||||||
|
|
||||||
|
const autofocusEl = this.querySelector('[autofocus]');
|
||||||
|
if (autofocusEl) {
|
||||||
|
autofocusEl.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle() {
|
||||||
|
if (!this.isOpen) {
|
||||||
|
this.open();
|
||||||
|
} else {
|
||||||
|
this.isOpen = false;
|
||||||
|
this._cleanupEvents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set correct position on the popup to fit into the window.
|
||||||
|
*/
|
||||||
|
fit() {
|
||||||
|
this._posFixed(this.shadowRoot.querySelector('.toggle'), this.$.content, {
|
||||||
|
valign: this.valign || 'bottom',
|
||||||
|
halign: this.halign || 'middle',
|
||||||
|
spacing: 5
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_docClick(e) {
|
||||||
|
const isThisPopover = e.composedPath().indexOf(this) > -1;
|
||||||
|
if (!isThisPopover && this.isOpen) {
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_onClick(e) {
|
||||||
|
const toggle = closest(e.composedPath()[0], '[slot="toggle"]', true) === this.toggleEl;
|
||||||
|
const closePopover = closest(e.composedPath()[0], '[close-popover]', true);
|
||||||
|
|
||||||
|
if (toggle && this.toggleEl.hasAttribute('disabled')) return;
|
||||||
|
|
||||||
|
if (toggle || this.alwaysToggle) {
|
||||||
|
this.toggle();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closePopover) {
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_registerEvents() {
|
||||||
|
this._cleanupEvents();
|
||||||
|
this.listen(document, 'mousedown', '_docClick');
|
||||||
|
this.scrollTarget.addEventListener('scroll', this.fit, { passive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
_cleanupEvents() {
|
||||||
|
this.unlisten(document, 'mousedown', '_docClick');
|
||||||
|
this.scrollTarget.removeEventListener('scroll', this.fit, { passive: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.customElements.define('tp-popup', TpPopup);
|
Loading…
Reference in New Issue
Block a user