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",
|
||||
"version": "0.0.1",
|
||||
"name": "@tp/tp-popup",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "tp-element.js",
|
||||
"main": "tp-popup.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"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",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@tp/helpers": "^1.0.1",
|
||||
"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