@exmg/exm-tooltip 1.1.4 → 1.1.5-alpha.5

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.
@@ -1,4 +1,5 @@
1
1
  import { ExmgElement } from '@exmg/lit-base/index.js';
2
+ type TooltipPositions = 'top' | 'right' | 'bottom' | 'left' | 'top-left' | 'top-right' | 'bottom-right' | 'bottom-left';
2
3
  export declare class ExmTooltipBase extends ExmgElement {
3
4
  /**
4
5
  * The id of the element that the tooltip is anchored to. This element
@@ -8,7 +9,7 @@ export declare class ExmTooltipBase extends ExmgElement {
8
9
  /**
9
10
  * Positions the tooltip to the top, right, bottom, left of its content.
10
11
  */
11
- position: string;
12
+ position: TooltipPositions;
12
13
  /**
13
14
  * If true, no parts of the tooltip will ever be shown offscreen.
14
15
  */
@@ -16,16 +17,19 @@ export declare class ExmTooltipBase extends ExmgElement {
16
17
  /**
17
18
  * X axis offset from the parent's center
18
19
  */
19
- xOffset?: number;
20
+ xOffset: number;
20
21
  /**
21
22
  * Y axis offset from the parent's center
22
23
  */
23
- yOffset?: number;
24
- _showing: boolean;
24
+ yOffset: number;
25
+ private showing;
25
26
  tooltip?: HTMLElement;
26
27
  private _target?;
27
- private _boundShow;
28
- private _boundHide;
28
+ private _parent?;
29
+ private boundShow;
30
+ private boundHide;
31
+ private boundMouseMove;
32
+ private boundMouseLeave;
29
33
  /**
30
34
  * Returns the target element that this tooltip is anchored to. It is
31
35
  * either the element given by the `for` attribute, or the immediate parent
@@ -34,15 +38,19 @@ export declare class ExmTooltipBase extends ExmgElement {
34
38
  get target(): any;
35
39
  connectedCallback(): void;
36
40
  disconnectedCallback(): void;
37
- show(): void;
41
+ protected firstUpdated(): void;
42
+ private handleMousemove;
43
+ private handleMouseleave;
44
+ private show;
38
45
  /**
39
46
  * Toggles a CSS class on or off.
40
47
  */
41
- toggleClass(name: string, bool: boolean, node: HTMLElement): void;
42
- hide(): void;
43
- updatePosition(): void;
44
- _addListeners(): void;
45
- _findTarget(): void;
46
- _removeListeners(): void;
48
+ private toggleClass;
49
+ private hide;
50
+ private updatePosition;
51
+ private addListeners;
52
+ private findTarget;
53
+ private removeListeners;
47
54
  protected render(): import("lit-html").TemplateResult<1>;
48
55
  }
56
+ export {};
@@ -15,7 +15,15 @@ export class ExmTooltipBase extends ExmgElement {
15
15
  * If true, no parts of the tooltip will ever be shown offscreen.
16
16
  */
17
17
  this.fitToVisibleBounds = false;
18
- this._showing = 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;
19
27
  }
20
28
  /**
21
29
  * Returns the target element that this tooltip is anchored to. It is
@@ -26,39 +34,72 @@ export class ExmTooltipBase extends ExmgElement {
26
34
  const parentNode = this.parentNode;
27
35
  // If the parentNode is a document fragment, then we need to use the host.
28
36
  const ownerRoot = parentNode.getRootNode();
29
- let target;
30
37
  if (this.for) {
31
- target = ownerRoot.querySelector('#' + this.for);
38
+ return ownerRoot.querySelector('#' + this.for);
32
39
  }
33
- else {
34
- // @ts-ignore
35
- target = parentNode.nodeType == Node.DOCUMENT_FRAGMENT_NODE ? ownerRoot.host : parentNode;
36
- }
37
- return target;
40
+ // @ts-ignore
41
+ return parentNode.nodeType == Node.DOCUMENT_FRAGMENT_NODE ? ownerRoot.host : parentNode;
38
42
  }
39
43
  connectedCallback() {
40
44
  super.connectedCallback();
41
- this._boundShow = this.show.bind(this);
42
- this._boundHide = this.hide.bind(this);
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);
43
49
  this.setAttribute('role', 'tooltip');
44
50
  this.setAttribute('tabindex', '-1');
45
- this._findTarget();
51
+ this.findTarget();
46
52
  }
47
53
  disconnectedCallback() {
48
- this._removeListeners();
54
+ this.removeListeners();
49
55
  super.disconnectedCallback();
50
56
  }
51
- show() {
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 - 2 || mousePosition.x > targetRect.right + 2) {
71
+ this._parent.removeEventListener('mousemove', this.boundMouseMove);
72
+ this.hide();
73
+ return;
74
+ }
75
+ if (mousePosition.y < targetRect.top - 2 || mousePosition.y > targetRect.bottom + 2) {
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();
52
91
  // If the tooltip is already showing, there's nothing to do.
53
- if (this._showing) {
92
+ if (this.showing || !this._parent) {
54
93
  return;
55
94
  }
95
+ this._parent.addEventListener('mousemove', this.boundMouseMove);
96
+ this._parent.addEventListener('mouseout', this.boundMouseLeave);
56
97
  if (this.textContent.trim() === '') {
57
98
  // Check if effective children are also empty
58
99
  let allChildrenEmpty = true;
59
100
  const effectiveChildren = this.childNodes;
60
- for (let i = 0; i < effectiveChildren.length; i++) {
61
- if (effectiveChildren[i].textContent.trim() !== '') {
101
+ for (const child of effectiveChildren) {
102
+ if (child.textContent.trim() !== '') {
62
103
  allChildrenEmpty = false;
63
104
  break;
64
105
  }
@@ -67,7 +108,7 @@ export class ExmTooltipBase extends ExmgElement {
67
108
  return;
68
109
  }
69
110
  }
70
- this._showing = true;
111
+ this.showing = true;
71
112
  this.toggleClass('hidden', false, this.tooltip);
72
113
  this.updatePosition();
73
114
  }
@@ -88,19 +129,19 @@ export class ExmTooltipBase extends ExmgElement {
88
129
  }
89
130
  hide() {
90
131
  // If the tooltip is already hidden, there's nothing to do.
91
- if (!this._showing) {
132
+ if (!this.showing) {
92
133
  return;
93
134
  }
94
- this._showing = false;
135
+ this.showing = false;
95
136
  this.toggleClass('hidden', true, this.tooltip);
96
137
  }
97
138
  updatePosition() {
98
- if (!this._target || !this.offsetParent) {
139
+ if (!this._target || !this.offsetParent || !this.tooltip) {
99
140
  return;
100
141
  }
101
142
  const parentRect = this.offsetParent.getBoundingClientRect();
102
143
  const targetRect = this._target.getBoundingClientRect();
103
- const thisRect = this.getBoundingClientRect();
144
+ const thisRect = this.tooltip.getBoundingClientRect();
104
145
  const horizontalCenterOffset = (targetRect.width - thisRect.width) / 2;
105
146
  const verticalCenterOffset = (targetRect.height - thisRect.height) / 2;
106
147
  const targetLeft = targetRect.left - parentRect.left;
@@ -124,13 +165,25 @@ export class ExmTooltipBase extends ExmgElement {
124
165
  tooltipLeft = targetLeft + targetRect.width;
125
166
  tooltipTop = targetTop + verticalCenterOffset;
126
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;
127
184
  }
128
- if (this.xOffset !== undefined) {
129
- tooltipLeft += this.xOffset;
130
- }
131
- if (this.yOffset !== undefined) {
132
- tooltipTop += this.yOffset;
133
- }
185
+ tooltipLeft += this.xOffset;
186
+ tooltipTop += this.yOffset;
134
187
  if (this.fitToVisibleBounds) {
135
188
  // Clip the left/right side
136
189
  if (parentRect.left + tooltipLeft + thisRect.width > window.innerWidth) {
@@ -156,47 +209,46 @@ export class ExmTooltipBase extends ExmgElement {
156
209
  this.style.top = tooltipTop + 'px';
157
210
  }
158
211
  }
159
- _addListeners() {
212
+ addListeners() {
160
213
  if (this._target) {
161
- this._target.addEventListener('mouseenter', this._boundShow);
162
- this._target.addEventListener('focus', this._boundShow);
163
- this._target.addEventListener('mouseleave', this._boundHide);
164
- this._target.addEventListener('blur', this._boundHide);
165
- this._target.addEventListener('tap', this._boundHide);
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);
166
218
  }
167
- this.addEventListener('mouseenter', this._boundHide);
219
+ this.addEventListener('mouseenter', this.boundShow);
168
220
  }
169
- _findTarget() {
170
- this._removeListeners();
221
+ findTarget() {
222
+ this.removeListeners();
171
223
  this._target = this.target;
172
- this._addListeners();
224
+ this._parent = this.parentNode;
225
+ this.addListeners();
173
226
  }
174
- _removeListeners() {
227
+ removeListeners() {
175
228
  if (this._target) {
176
- this._target.removeEventListener('mouseenter', this._boundShow);
177
- this._target.removeEventListener('focus', this._boundShow);
178
- this._target.removeEventListener('mouseleave', this._boundHide);
179
- this._target.removeEventListener('blur', this._boundHide);
180
- this._target.removeEventListener('tap', this._boundHide);
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);
181
233
  }
182
- this.removeEventListener('mouseenter', this._boundHide);
234
+ this.removeEventListener('mouseenter', this.boundShow);
183
235
  }
184
236
  render() {
185
237
  return html `
186
- <div id="tooltip" class="hidden">
238
+ <section id="tooltip" class="hidden">
187
239
  <slot></slot>
188
- </div>
240
+ </section>
189
241
  `;
190
242
  }
191
243
  }
192
244
  __decorate([
193
245
  property({ type: String }),
194
246
  observer(function () {
195
- this._findTarget();
247
+ this.findTarget();
196
248
  })
197
249
  ], ExmTooltipBase.prototype, "for", void 0);
198
250
  __decorate([
199
- property({ type: String })
251
+ property()
200
252
  ], ExmTooltipBase.prototype, "position", void 0);
201
253
  __decorate([
202
254
  property({ type: Boolean })
@@ -209,7 +261,7 @@ __decorate([
209
261
  ], ExmTooltipBase.prototype, "yOffset", void 0);
210
262
  __decorate([
211
263
  state()
212
- ], ExmTooltipBase.prototype, "_showing", void 0);
264
+ ], ExmTooltipBase.prototype, "showing", void 0);
213
265
  __decorate([
214
266
  query('#tooltip')
215
267
  ], ExmTooltipBase.prototype, "tooltip", void 0);
@@ -22,7 +22,9 @@ export const style = css `
22
22
  padding: var(--exm-tooltip-padding, 8px);
23
23
  border-radius: var(--exm-tooltip-border-radius, 2px);
24
24
  min-width: var(--exm-tooltip-min-width, initial);
25
+ width: max-content;
25
26
  transition: opacity 0.5s;
27
+ z-index: 10;
26
28
  }
27
29
 
28
30
  #tooltip.hidden {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exmg/exm-tooltip",
3
- "version": "1.1.4",
3
+ "version": "1.1.5-alpha.5+569284b",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -9,9 +9,9 @@
9
9
  ".": "./dist/index.js",
10
10
  "./exm-tooltip.js": "./dist/exm-tooltip.js"
11
11
  },
12
- "dependencies": {
13
- "@exmg/lit-base": "^3.0.0",
14
- "lit": "^3.0.0",
12
+ "peerDependencies": {
13
+ "@exmg/lit-base": "^3.0.3",
14
+ "lit": "^3.2.1",
15
15
  "tslib": "^2.6.2"
16
16
  },
17
17
  "files": [
@@ -31,12 +31,9 @@
31
31
  "directory": "packages/exm-tooltip"
32
32
  },
33
33
  "license": "MIT",
34
- "devDependencies": {
35
- "@exmg/lit-cli": "1.1.13"
36
- },
37
34
  "scripts": {},
38
35
  "publishConfig": {
39
36
  "access": "public"
40
37
  },
41
- "gitHead": "0fcf5110c9538fe06c9400afb133a5618f0b1a14"
38
+ "gitHead": "569284b73ae26df21846b0673aae5a14af49d594"
42
39
  }