@exmg/exm-tooltip 1.1.36 → 1.1.37-alpha.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,56 @@
1
+ import { ExmgElement } from '@exmg/lit-base/index.js';
2
+ type TooltipPositions = 'top' | 'right' | 'bottom' | 'left' | 'top-left' | 'top-right' | 'bottom-right' | 'bottom-left';
3
+ export declare class ExmTooltipBase extends ExmgElement {
4
+ /**
5
+ * The id of the element that the tooltip is anchored to. This element
6
+ * must be a sibling of the tooltip.
7
+ */
8
+ for?: string;
9
+ /**
10
+ * Positions the tooltip to the top, right, bottom, left of its content.
11
+ */
12
+ position: TooltipPositions;
13
+ /**
14
+ * If true, no parts of the tooltip will ever be shown offscreen.
15
+ */
16
+ fitToVisibleBounds: boolean;
17
+ /**
18
+ * X axis offset from the parent's center
19
+ */
20
+ xOffset: number;
21
+ /**
22
+ * Y axis offset from the parent's center
23
+ */
24
+ yOffset: number;
25
+ private showing;
26
+ tooltip?: HTMLElement;
27
+ private _target?;
28
+ private _parent?;
29
+ private boundShow;
30
+ private boundHide;
31
+ private boundMouseMove;
32
+ private boundMouseLeave;
33
+ /**
34
+ * Returns the target element that this tooltip is anchored to. It is
35
+ * either the element given by the `for` attribute, or the immediate parent
36
+ * of the tooltip.
37
+ */
38
+ get target(): any;
39
+ connectedCallback(): void;
40
+ disconnectedCallback(): void;
41
+ protected firstUpdated(): void;
42
+ private handleMousemove;
43
+ private handleMouseleave;
44
+ private show;
45
+ /**
46
+ * Toggles a CSS class on or off.
47
+ */
48
+ private toggleClass;
49
+ private hide;
50
+ private updatePosition;
51
+ private addListeners;
52
+ private findTarget;
53
+ private removeListeners;
54
+ protected render(): import("lit-html").TemplateResult<1>;
55
+ }
56
+ export {};
@@ -0,0 +1,268 @@
1
+ import { __decorate } from "tslib";
2
+ import { html } from 'lit';
3
+ import { property } from 'lit/decorators/property.js';
4
+ import { state } from 'lit/decorators.js';
5
+ import { query } from 'lit/decorators/query.js';
6
+ import { ExmgElement, observer } from '@exmg/lit-base/index.js';
7
+ export class ExmTooltipBase extends ExmgElement {
8
+ constructor() {
9
+ super(...arguments);
10
+ /**
11
+ * Positions the tooltip to the top, right, bottom, left of its content.
12
+ */
13
+ this.position = 'bottom';
14
+ /**
15
+ * If true, no parts of the tooltip will ever be shown offscreen.
16
+ */
17
+ this.fitToVisibleBounds = false;
18
+ /**
19
+ * X axis offset from the parent's center
20
+ */
21
+ this.xOffset = 0;
22
+ /**
23
+ * Y axis offset from the parent's center
24
+ */
25
+ this.yOffset = 0;
26
+ this.showing = false;
27
+ }
28
+ /**
29
+ * Returns the target element that this tooltip is anchored to. It is
30
+ * either the element given by the `for` attribute, or the immediate parent
31
+ * of the tooltip.
32
+ */
33
+ get target() {
34
+ const parentNode = this.parentNode;
35
+ // If the parentNode is a document fragment, then we need to use the host.
36
+ const ownerRoot = parentNode.getRootNode();
37
+ if (this.for) {
38
+ return ownerRoot.querySelector('#' + this.for);
39
+ }
40
+ // @ts-ignore
41
+ return parentNode.nodeType == Node.DOCUMENT_FRAGMENT_NODE ? ownerRoot.host : parentNode;
42
+ }
43
+ connectedCallback() {
44
+ super.connectedCallback();
45
+ this.boundShow = this.show.bind(this);
46
+ this.boundHide = this.hide.bind(this);
47
+ this.boundMouseMove = this.handleMousemove.bind(this);
48
+ this.boundMouseLeave = this.handleMouseleave.bind(this);
49
+ this.setAttribute('role', 'tooltip');
50
+ this.setAttribute('tabindex', '-1');
51
+ this.findTarget();
52
+ }
53
+ disconnectedCallback() {
54
+ this.removeListeners();
55
+ super.disconnectedCallback();
56
+ }
57
+ firstUpdated() {
58
+ this.findTarget();
59
+ this.updatePosition();
60
+ }
61
+ handleMousemove(event) {
62
+ if (!this._target || !this._parent) {
63
+ return;
64
+ }
65
+ const mousePosition = {
66
+ x: event.clientX,
67
+ y: event.clientY,
68
+ };
69
+ const targetRect = this._target.getBoundingClientRect();
70
+ if (mousePosition.x < targetRect.left - 1 || mousePosition.x > targetRect.right + 1) {
71
+ this._parent.removeEventListener('mousemove', this.boundMouseMove);
72
+ this.hide();
73
+ return;
74
+ }
75
+ if (mousePosition.y < targetRect.top - 1 || mousePosition.y > targetRect.bottom + 1) {
76
+ this._parent.removeEventListener('mousemove', this.boundMouseMove);
77
+ this.hide();
78
+ return;
79
+ }
80
+ }
81
+ handleMouseleave() {
82
+ if (!this._target || !this._parent) {
83
+ return;
84
+ }
85
+ this.hide();
86
+ this._parent.removeEventListener('mouseout', this.boundMouseLeave);
87
+ this._parent.removeEventListener('mousemove', this.boundMouseMove);
88
+ }
89
+ show(event) {
90
+ event.stopPropagation();
91
+ // If the tooltip is already showing, there's nothing to do.
92
+ if (this.showing || !this._parent) {
93
+ return;
94
+ }
95
+ this._parent.addEventListener('mousemove', this.boundMouseMove);
96
+ this._parent.addEventListener('mouseout', this.boundMouseLeave);
97
+ if (this.textContent.trim() === '') {
98
+ // Check if effective children are also empty
99
+ let allChildrenEmpty = true;
100
+ const effectiveChildren = this.childNodes;
101
+ for (const child of effectiveChildren) {
102
+ if (child.textContent.trim() !== '') {
103
+ allChildrenEmpty = false;
104
+ break;
105
+ }
106
+ }
107
+ if (allChildrenEmpty) {
108
+ return;
109
+ }
110
+ }
111
+ this.showing = true;
112
+ this.toggleClass('hidden', false, this.tooltip);
113
+ this.updatePosition();
114
+ }
115
+ /**
116
+ * Toggles a CSS class on or off.
117
+ */
118
+ toggleClass(name, bool, node) {
119
+ node = /** @type {Element} */ node || this;
120
+ if (arguments.length == 1) {
121
+ bool = !node.classList.contains(name);
122
+ }
123
+ if (bool) {
124
+ node.classList.add(name);
125
+ }
126
+ else {
127
+ node.classList.remove(name);
128
+ }
129
+ }
130
+ hide() {
131
+ // If the tooltip is already hidden, there's nothing to do.
132
+ if (!this.showing) {
133
+ return;
134
+ }
135
+ this.showing = false;
136
+ this.toggleClass('hidden', true, this.tooltip);
137
+ }
138
+ updatePosition() {
139
+ if (!this._target || !this.offsetParent || !this.tooltip) {
140
+ return;
141
+ }
142
+ const parentRect = this.offsetParent.getBoundingClientRect();
143
+ const targetRect = this._target.getBoundingClientRect();
144
+ const thisRect = this.tooltip.getBoundingClientRect();
145
+ const horizontalCenterOffset = (targetRect.width - thisRect.width) / 2;
146
+ const verticalCenterOffset = (targetRect.height - thisRect.height) / 2;
147
+ const targetLeft = targetRect.left - parentRect.left;
148
+ const targetTop = targetRect.top - parentRect.top;
149
+ let tooltipLeft = 0;
150
+ let tooltipTop = 0;
151
+ switch (this.position) {
152
+ case 'top':
153
+ tooltipLeft = targetLeft + horizontalCenterOffset;
154
+ tooltipTop = targetTop - thisRect.height;
155
+ break;
156
+ case 'bottom':
157
+ tooltipLeft = targetLeft + horizontalCenterOffset;
158
+ tooltipTop = targetTop + targetRect.height;
159
+ break;
160
+ case 'left':
161
+ tooltipLeft = targetLeft - thisRect.width;
162
+ tooltipTop = targetTop + verticalCenterOffset;
163
+ break;
164
+ case 'right':
165
+ tooltipLeft = targetLeft + targetRect.width;
166
+ tooltipTop = targetTop + verticalCenterOffset;
167
+ break;
168
+ case 'top-left':
169
+ tooltipLeft = targetLeft;
170
+ tooltipTop = targetTop - thisRect.height;
171
+ break;
172
+ case 'bottom-left':
173
+ tooltipLeft = targetLeft;
174
+ tooltipTop = targetTop + targetRect.height;
175
+ break;
176
+ case 'top-right':
177
+ tooltipLeft = targetLeft - thisRect.width + targetRect.width;
178
+ tooltipTop = targetTop - thisRect.height;
179
+ break;
180
+ case 'bottom-right':
181
+ tooltipLeft = targetLeft - thisRect.width + targetRect.width;
182
+ tooltipTop = targetTop + targetRect.height;
183
+ break;
184
+ }
185
+ tooltipLeft += this.xOffset;
186
+ tooltipTop += this.yOffset;
187
+ if (this.fitToVisibleBounds) {
188
+ // Clip the left/right side
189
+ if (parentRect.left + tooltipLeft + thisRect.width > window.innerWidth) {
190
+ this.style.right = '0px';
191
+ this.style.left = 'auto';
192
+ }
193
+ else {
194
+ this.style.left = Math.max(0, tooltipLeft) + 'px';
195
+ this.style.right = 'auto';
196
+ }
197
+ // Clip the top/bottom side.
198
+ if (parentRect.top + tooltipTop + thisRect.height > window.innerHeight) {
199
+ this.style.bottom = parentRect.height + 'px';
200
+ this.style.top = 'auto';
201
+ }
202
+ else {
203
+ this.style.top = Math.max(-parentRect.top, tooltipTop) + 'px';
204
+ this.style.bottom = 'auto';
205
+ }
206
+ }
207
+ else {
208
+ this.style.left = tooltipLeft + 'px';
209
+ this.style.top = tooltipTop + 'px';
210
+ }
211
+ }
212
+ addListeners() {
213
+ if (this._target) {
214
+ this._target.addEventListener('mouseenter', this.boundShow);
215
+ this._target.addEventListener('focus', this.boundShow);
216
+ this._target.addEventListener('blur', this.boundHide);
217
+ this._target.addEventListener('tap', this.boundHide);
218
+ }
219
+ this.addEventListener('mouseenter', this.boundShow);
220
+ }
221
+ findTarget() {
222
+ this.removeListeners();
223
+ this._target = this.target;
224
+ this._parent = this.parentNode;
225
+ this.addListeners();
226
+ }
227
+ removeListeners() {
228
+ if (this._target) {
229
+ this._target.removeEventListener('mouseenter', this.boundShow);
230
+ this._target.removeEventListener('focus', this.boundShow);
231
+ this._target.removeEventListener('blur', this.boundHide);
232
+ this._target.removeEventListener('tap', this.boundHide);
233
+ }
234
+ this.removeEventListener('mouseenter', this.boundShow);
235
+ }
236
+ render() {
237
+ return html `
238
+ <section id="tooltip" class="hidden">
239
+ <slot></slot>
240
+ </section>
241
+ `;
242
+ }
243
+ }
244
+ __decorate([
245
+ property({ type: String }),
246
+ observer(function () {
247
+ this.findTarget();
248
+ })
249
+ ], ExmTooltipBase.prototype, "for", void 0);
250
+ __decorate([
251
+ property()
252
+ ], ExmTooltipBase.prototype, "position", void 0);
253
+ __decorate([
254
+ property({ type: Boolean })
255
+ ], ExmTooltipBase.prototype, "fitToVisibleBounds", void 0);
256
+ __decorate([
257
+ property({ type: Number })
258
+ ], ExmTooltipBase.prototype, "xOffset", void 0);
259
+ __decorate([
260
+ property({ type: Number })
261
+ ], ExmTooltipBase.prototype, "yOffset", void 0);
262
+ __decorate([
263
+ state()
264
+ ], ExmTooltipBase.prototype, "showing", void 0);
265
+ __decorate([
266
+ query('#tooltip')
267
+ ], ExmTooltipBase.prototype, "tooltip", void 0);
268
+ //# sourceMappingURL=exm-tooltip-base.js.map
@@ -0,0 +1,33 @@
1
+ import { ExmTooltipBase } from './exm-tooltip-base.js';
2
+ /**
3
+ * `exm-tooltip`
4
+ * Example:
5
+ * ```html
6
+ * <div style="position:relative;">
7
+ * <button id="styledBtn">Test</button>
8
+ * <exm-tooltip for="styledBtn">the name means "different lizard"</exm-tooltip>
9
+ * </div>
10
+ * ```
11
+ *
12
+ * ### Styling
13
+ * The following custom properties and mixins are available for styling:
14
+ *
15
+ * Custom property | Description | Default
16
+ * ----------------|-------------|----------
17
+ * `--exm-tooltip-font-size` | Font size of tooltip text | 10px
18
+ * `--exm-tooltip-line-height` | Text line height | 1
19
+ * `--exm-tooltip-background` | Background color | #616161
20
+ * `--exm-tooltip-opacity` | Tooltip opacity | 0.9
21
+ * `--exm-tooltip-text-color` | Font color | white
22
+ * `--exm-tooltip-padding` | Container padding | 8px
23
+ * `--exm-tooltip-border-radius` | Container border radius | 2px
24
+ * `--exm-tooltip-min-width` | Breadcrumb container background color | initial
25
+ */
26
+ export declare class ExmTooltip extends ExmTooltipBase {
27
+ static styles: import("lit").CSSResult;
28
+ }
29
+ declare global {
30
+ interface HTMLElementTagNameMap {
31
+ 'exm-tooltip': ExmTooltip;
32
+ }
33
+ }
@@ -0,0 +1,36 @@
1
+ import { __decorate } from "tslib";
2
+ import { customElement } from 'lit/decorators/custom-element.js';
3
+ import { style } from './styles/exm-tooltip-styles-css.js';
4
+ import { ExmTooltipBase } from './exm-tooltip-base.js';
5
+ /**
6
+ * `exm-tooltip`
7
+ * Example:
8
+ * ```html
9
+ * <div style="position:relative;">
10
+ * <button id="styledBtn">Test</button>
11
+ * <exm-tooltip for="styledBtn">the name means "different lizard"</exm-tooltip>
12
+ * </div>
13
+ * ```
14
+ *
15
+ * ### Styling
16
+ * The following custom properties and mixins are available for styling:
17
+ *
18
+ * Custom property | Description | Default
19
+ * ----------------|-------------|----------
20
+ * `--exm-tooltip-font-size` | Font size of tooltip text | 10px
21
+ * `--exm-tooltip-line-height` | Text line height | 1
22
+ * `--exm-tooltip-background` | Background color | #616161
23
+ * `--exm-tooltip-opacity` | Tooltip opacity | 0.9
24
+ * `--exm-tooltip-text-color` | Font color | white
25
+ * `--exm-tooltip-padding` | Container padding | 8px
26
+ * `--exm-tooltip-border-radius` | Container border radius | 2px
27
+ * `--exm-tooltip-min-width` | Breadcrumb container background color | initial
28
+ */
29
+ let ExmTooltip = class ExmTooltip extends ExmTooltipBase {
30
+ };
31
+ ExmTooltip.styles = style;
32
+ ExmTooltip = __decorate([
33
+ customElement('exm-tooltip')
34
+ ], ExmTooltip);
35
+ export { ExmTooltip };
36
+ //# sourceMappingURL=exm-tooltip.js.map
@@ -0,0 +1,3 @@
1
+ export { ExmTooltip } from './exm-tooltip.js';
2
+ export { ExmTooltipBase } from './exm-tooltip-base.js';
3
+ export { style as tooltipStyles } from './styles/exm-tooltip-styles-css.js';
@@ -0,0 +1,4 @@
1
+ export { ExmTooltip } from './exm-tooltip.js';
2
+ export { ExmTooltipBase } from './exm-tooltip-base.js';
3
+ export { style as tooltipStyles } from './styles/exm-tooltip-styles-css.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ export declare const style: import("lit").CSSResult;
@@ -0,0 +1,35 @@
1
+ import { css } from 'lit';
2
+ export const style = css `
3
+ :host {
4
+ display: block;
5
+ position: absolute;
6
+ outline: none;
7
+ z-index: var(--exm-tooltip-z-index, 1002);
8
+ -moz-user-select: none;
9
+ -ms-user-select: none;
10
+ -webkit-user-select: none;
11
+ user-select: none;
12
+ cursor: default;
13
+ }
14
+
15
+ #tooltip {
16
+ display: block;
17
+ outline: none;
18
+ font-size: var(--exm-tooltip-font-size, 12px);
19
+ line-height: var(--exm-tooltip-line-height, 14px);
20
+ background-color: var(--exm-tooltip-background-color, var(--md-sys-color-inverse-surface, #333));
21
+ color: var(--exm-tooltip-color, var(--md-sys-color-inverse-on-surface, white));
22
+ padding: var(--exm-tooltip-padding, 8px);
23
+ border-radius: var(--exm-tooltip-border-radius, 2px);
24
+ min-width: var(--exm-tooltip-min-width, initial);
25
+ width: max-content;
26
+ transition: opacity 0.5s;
27
+ z-index: 10;
28
+ }
29
+
30
+ #tooltip.hidden {
31
+ opacity: 0;
32
+ display: none;
33
+ }
34
+ `;
35
+ //# sourceMappingURL=exm-tooltip-styles-css.js.map
@@ -1,10 +1,11 @@
1
- import { __decorate } from "tslib";
1
+ import { __decorate } from 'tslib';
2
2
  import { html } from 'lit';
3
3
  import { property } from 'lit/decorators/property.js';
4
4
  import { state } from 'lit/decorators.js';
5
5
  import { query } from 'lit/decorators/query.js';
6
- import { ExmgElement, observer } from '@exmg/lit-base/index.js';
7
- export class ExmTooltipBase extends ExmgElement {
6
+ import { observer, ExmgElement } from '@exmg/lit-base/index.js';
7
+
8
+ class ExmTooltipBase extends ExmgElement {
8
9
  constructor() {
9
10
  super(...arguments);
10
11
  /**
@@ -265,4 +266,6 @@ __decorate([
265
266
  __decorate([
266
267
  query('#tooltip')
267
268
  ], ExmTooltipBase.prototype, "tooltip", void 0);
268
- //# sourceMappingURL=exm-tooltip-base.js.map
269
+
270
+ export { ExmTooltipBase };
271
+ //# sourceMappingURL=exm-tooltip-base.js.map
@@ -1,7 +1,8 @@
1
- import { __decorate } from "tslib";
1
+ import { __decorate } from 'tslib';
2
2
  import { customElement } from 'lit/decorators/custom-element.js';
3
3
  import { style } from './styles/exm-tooltip-styles-css.js';
4
4
  import { ExmTooltipBase } from './exm-tooltip-base.js';
5
+
5
6
  /**
6
7
  * `exm-tooltip`
7
8
  * Example:
@@ -32,5 +33,6 @@ ExmTooltip.styles = style;
32
33
  ExmTooltip = __decorate([
33
34
  customElement('exm-tooltip')
34
35
  ], ExmTooltip);
36
+
35
37
  export { ExmTooltip };
36
- //# sourceMappingURL=exm-tooltip.js.map
38
+ //# sourceMappingURL=exm-tooltip.js.map
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  export { ExmTooltip } from './exm-tooltip.js';
2
2
  export { ExmTooltipBase } from './exm-tooltip-base.js';
3
3
  export { style as tooltipStyles } from './styles/exm-tooltip-styles-css.js';
4
- //# sourceMappingURL=index.js.map
4
+ //# sourceMappingURL=index.js.map
@@ -1,5 +1,6 @@
1
1
  import { css } from 'lit';
2
- export const style = css `
2
+
3
+ const style = css `
3
4
  :host {
4
5
  display: block;
5
6
  position: absolute;
@@ -32,4 +33,6 @@ export const style = css `
32
33
  display: none;
33
34
  }
34
35
  `;
35
- //# sourceMappingURL=exm-tooltip-styles-css.js.map
36
+
37
+ export { style };
38
+ //# sourceMappingURL=exm-tooltip-styles-css.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exmg/exm-tooltip",
3
- "version": "1.1.36",
3
+ "version": "1.1.37-alpha.31+513140a",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -36,5 +36,5 @@
36
36
  "publishConfig": {
37
37
  "access": "public"
38
38
  },
39
- "gitHead": "0fb4c4b7fdbc8d149a825e172b63f7e00c8e8a4a"
39
+ "gitHead": "513140a59e3a5a9a0fa572147ba6c0cf9801816e"
40
40
  }