From e3414c9d449fb0be4a68dd61705d500b414a4d0e Mon Sep 17 00:00:00 2001 From: trading_peter Date: Sat, 12 Mar 2022 17:01:05 +0100 Subject: [PATCH] Initial version --- README.md | 2 +- package-lock.json | 13 +++++ package.json | 7 ++- tp-element.js | 35 ------------ tp-tooltip-mixin.js | 100 ++++++++++++++++++++++++++++++++++ tp-tooltip-wrapper.js | 74 +++++++++++++++++++++++++ tp-tooltip.js | 124 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 316 insertions(+), 39 deletions(-) create mode 100644 package-lock.json delete mode 100644 tp-element.js create mode 100644 tp-tooltip-mixin.js create mode 100644 tp-tooltip-wrapper.js create mode 100644 tp-tooltip.js diff --git a/README.md b/README.md index 1ab27b7..85bb821 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# tp-element +# tp-tooltip diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..91e4bab --- /dev/null +++ b/package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "tp-tooltip", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@tp/helpers": { + "version": "1.0.0", + "resolved": "https://verdaccio.codeblob.work/@tp%2fhelpers/-/helpers-1.0.0.tgz", + "integrity": "sha512-0RcwkVBsZoa2jaOGwf0QNBHIC1vA/8G1rsvWC1j20tyyzZBOqGGOwvgnLN1TEP3C8zT4+oUMlQbu6DmkpW9T3A==" + } + } +} diff --git a/package.json b/package.json index 4ecb195..58b1719 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,19 @@ { - "name": "tp-element", + "name": "tp-tooltip", "version": "0.0.1", "description": "", - "main": "tp-element.js", + "main": "tp-tooltip.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-tooltip.git" }, "author": "trading_peter", "license": "Apache-2.0", "dependencies": { + "@tp/helpers": "^1.0.0", "lit": "^2.2.0" } } diff --git a/tp-element.js b/tp-element.js deleted file mode 100644 index 6a92a2f..0000000 --- a/tp-element.js +++ /dev/null @@ -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); diff --git a/tp-tooltip-mixin.js b/tp-tooltip-mixin.js new file mode 100644 index 0000000..9944cbb --- /dev/null +++ b/tp-tooltip-mixin.js @@ -0,0 +1,100 @@ +/** +@license +Copyright (c) 2022 trading_peter +This program is available under Apache License Version 2.0 +*/ + +import './tp-tooltip.js'; + +/** + * Elements implementing this mixin are able to show tooltip on mouse over. + * + * ## Example + * ```html + * + * ``` + * + * @polymer +* @mixinFunction + */ +export const Tooltip = function(superClass) { + return class extends superClass { + static get properties() { + return { + + /** + * Text to show in the tooltip. + */ + tooltip: { type: String }, + + /** + * Vertical align of the tooltip. + * Supported are `bottom` and `top`. + */ + tooltipValign: { type: String } + }; + } + + constructor() { + super(); + this.tooltipValign = 'bottom'; + this._showTooltip = this._showTooltip.bind(this); + this._hideTooltip = this._hideTooltip.bind(this); + } + + set tooltip(val) { + const oldTooltip = this.tooltip; + this._tooltip = val; + this._tooltipChanged(this.tooltip, oldTooltip); + } + + get tooltip() { + return this._tooltip; + } + + _tooltipChanged(newTooltip, oldTooltip) { + if (oldTooltip) { + this.removeEventListener('mouseenter', this._showTooltip); + this.removeEventListener('focus', this._showTooltip); + } + + if (newTooltip && newTooltip !== '') { + this.addEventListener('mouseenter', this._showTooltip); + this.addEventListener('focus', this._showTooltip); + } + } + + _showTooltip() { + if (this._tooltipInstance || !this.tooltip || this.tooltip === '') { + return; + } + const tooltip = document.createElement('tp-tooltip'); + tooltip.innerHTML = this.tooltip; + tooltip.valign = this.tooltipValign; + tooltip.target = this; + this._tooltipInstance = tooltip; + + this.addEventListener('mouseleave', this._hideTooltip); + this.addEventListener('blur', this._hideTooltip); + this.addEventListener('click', this._hideTooltip); + + document.body.appendChild(this._tooltipInstance); + this._tooltipInstance.show(); + } + + _hideTooltip() { + if (!this._tooltipInstance) { + return; + } + this._tooltipInstance.hide(function() { + if (this._tooltipInstance) { + document.body.removeChild(this._tooltipInstance); + this.removeEventListener('mouseleave', this._hideTooltip); + this.removeEventListener('blur', this._hideTooltip); + this.removeEventListener('click', this._hideTooltip); + this._tooltipInstance = null; + } + }.bind(this)); + } + }; +} diff --git a/tp-tooltip-wrapper.js b/tp-tooltip-wrapper.js new file mode 100644 index 0000000..393c7c5 --- /dev/null +++ b/tp-tooltip-wrapper.js @@ -0,0 +1,74 @@ +/** +@license +Copyright (c) 2022 trading_peter +This program is available under Apache License Version 2.0 +*/ + +import { LitElement, html, css } from 'lit'; +import { Tooltip } from './tp-tooltip-mixin.js'; + +/** +# tp-tooltip-wrapper + +This element can be used to add a tooltip to elements that don't implement the tooltip mixin. +It is a simple wrapper. It can be shown conditionally based on the value of `disabled`. +For this you have to use the `text` property instead of the inherited `tooltip` property. + +## Example +```html + +
Content with a tooltip
+
+``` + +## Styling +Name | Type | Default | Description +---|---|--- +--tp-tooltip-wrapper | mixin || Styling on :host. + +*/ +class TpTooltipWrapper extends Tooltip(LitElement) { + static get styles() { + return css` + :host { + display: block; + } + `; + } + + render() { + return html` + + `; + } + + static get properties() { + return { + text: { type: String }, + disabled: { type: Boolean } + }; + } + + constructor() { + super(); + this.disabled = false; + } + + shouldUpdate(changes) { + if (changes.has('text') || changes.has('disabled')) { + this._setTooltipText(this.text, this.disabled); + } + return true; + } + + disconnectedCallback() { + super.disconnectedCallback(); + this._hideTooltip(); + } + + _setTooltipText(text, disabled) { + this.tooltip = disabled ? '' : text; + } +} + +window.customElements.define('tp-tooltip-wrapper', TpTooltipWrapper); diff --git a/tp-tooltip.js b/tp-tooltip.js new file mode 100644 index 0000000..193f5e0 --- /dev/null +++ b/tp-tooltip.js @@ -0,0 +1,124 @@ +/* +Copyright (c) 2020 EDV Wasmeier +This program is available under Apache License Version 2.0 +*/ + +import { LitElement, html, css } from 'lit'; +import { Position } from '@tp/helpers/position.js'; + +/* +# tp-tooltip + +This element is used by `tp-tooltip-mixin` to show a tooltip on the implementing element. +It is not meant to be used stand alone. + +## Example +```html + +``` + +## Styling +Name | Type | Default | Description +---|---|--- +--tp-tooltip-spacing | var | 5px | Spacing between target and the tooltip. + +*/ +class TpTooltip extends Position(LitElement) { + static get styles() { + return css` + :host { + display: none; + opacity: 0; + position: fixed; + left: 0; + z-index: 1; + background: #1B1B1B; + color: #ffffff; + font-size: 12px; + padding: 5px; + border-radius: 2px; + transition: transform 80ms, opacity 180ms; + transform: scale(0.90); + will-change: transform, opacity; + white-space: nowrap; + } + + :host([visible]) { + transform: scale(1); + opacity: 1; + } + `; + } + + render() { + return html` +
+ `; + } + + static get properties() { + return { + /** + * Element to align the tooltip to. + */ + target: { type: Object }, + + /** + * Indicates if the tooltip is currently visible. + */ + visible: { type: Boolean, reflect: true }, + + /** + * Delay till the tooltip is switched visible. + */ + delay: { type: Number }, + + /** + * Vertical align of the tooltip. + */ + valign: { type: String } + }; + } + + constructor() { + super(); + + this.delay = 400; + this.valign = 'bottom'; + this.visible = false; + } + + show() { + if (this._showJob) { + clearTimeout(this._showJob); + this._showJob = null; + } + + this._showJob = setTimeout(() => { + this.style.display = 'block'; + const spacing = parseInt((window.ShadyCSS ? ShadyCSS.getComputedStyleValue(this.target, '--tp-tooltip-spacing') : getComputedStyle(this.target).getPropertyValue('--tp-tooltip-spacing')), 10); + setTimeout(() => { + this.visible = true; + this._posFixed(this.target, this, { + valign: this.valign, + halign: 'middle', + // See: https://github.com/webcomponents/shadycss/issues/83 + spacing: spacing || 5 + }); + }, 10); + }, this.delay); + } + + hide(cb) { + if (this._showJob) { + clearTimeout(this._showJob); + this._showJob = null; + } + this.visible = false; + setTimeout(() => { + cb(); + }, 200); + } +} + +window.customElements.define('tp-tooltip', TpTooltip);