primer_view_components 0.0.71 → 0.0.72

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,5 +1,5 @@
1
1
  declare type Direction = 'n' | 's' | 'e' | 'w' | 'ne' | 'se' | 'nw' | 'sw';
2
- declare class TooltipElement extends HTMLElement {
2
+ declare class ToolTipElement extends HTMLElement {
3
3
  #private;
4
4
  styles(): string;
5
5
  get htmlFor(): string;
@@ -9,7 +9,6 @@ declare class TooltipElement extends HTMLElement {
9
9
  get direction(): Direction;
10
10
  set direction(value: Direction);
11
11
  get control(): HTMLElement | null;
12
- constructor();
13
12
  connectedCallback(): void;
14
13
  disconnectedCallback(): void;
15
14
  handleEvent(event: Event): void;
@@ -18,7 +17,7 @@ declare class TooltipElement extends HTMLElement {
18
17
  }
19
18
  declare global {
20
19
  interface Window {
21
- TooltipElement: typeof TooltipElement;
20
+ ToolTipElement: typeof ToolTipElement;
22
21
  }
23
22
  }
24
23
  export {};
@@ -9,10 +9,10 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _TooltipElement_instances, _TooltipElement_abortController, _TooltipElement_align, _TooltipElement_side, _TooltipElement_allowUpdatePosition, _TooltipElement_adjustedAnchorAlignment, _TooltipElement_updatePosition;
12
+ var _ToolTipElement_instances, _ToolTipElement_abortController, _ToolTipElement_align, _ToolTipElement_side, _ToolTipElement_allowUpdatePosition, _ToolTipElement_update, _ToolTipElement_updatePosition;
13
13
  import { getAnchoredPosition } from '@primer/behaviors';
14
14
  const TOOLTIP_OPEN_CLASS = 'tooltip-open';
15
- const TOOLTIP_ARROW_EDGE_OFFSET = 10;
15
+ const TOOLTIP_ARROW_EDGE_OFFSET = 6;
16
16
  const DIRECTION_CLASSES = [
17
17
  'tooltip-n',
18
18
  'tooltip-s',
@@ -23,21 +23,14 @@ const DIRECTION_CLASSES = [
23
23
  'tooltip-nw',
24
24
  'tooltip-sw'
25
25
  ];
26
- class TooltipElement extends HTMLElement {
26
+ class ToolTipElement extends HTMLElement {
27
27
  constructor() {
28
- super();
29
- _TooltipElement_instances.add(this);
30
- _TooltipElement_abortController.set(this, void 0);
31
- _TooltipElement_align.set(this, 'center');
32
- _TooltipElement_side.set(this, 'outside-bottom');
33
- _TooltipElement_allowUpdatePosition.set(this, false);
34
- const shadow = this.attachShadow({ mode: 'open' });
35
- shadow.innerHTML = `
36
- <style>
37
- ${this.styles()}
38
- </style>
39
- <slot></slot>
40
- `;
28
+ super(...arguments);
29
+ _ToolTipElement_instances.add(this);
30
+ _ToolTipElement_abortController.set(this, void 0);
31
+ _ToolTipElement_align.set(this, 'center');
32
+ _ToolTipElement_side.set(this, 'outside-bottom');
33
+ _ToolTipElement_allowUpdatePosition.set(this, false);
41
34
  }
42
35
  styles() {
43
36
  return `
@@ -103,13 +96,13 @@ class TooltipElement extends HTMLElement {
103
96
  :host(.tooltip-s):before,
104
97
  :host(.tooltip-n):before {
105
98
  right: 50%;
99
+ margin-right: -${TOOLTIP_ARROW_EDGE_OFFSET}px;
106
100
  }
107
101
 
108
102
  :host(.tooltip-s):before,
109
103
  :host(.tooltip-se):before,
110
104
  :host(.tooltip-sw):before {
111
105
  bottom: 100%;
112
- margin-right: -${TOOLTIP_ARROW_EDGE_OFFSET}px;
113
106
  border-bottom-color: var(--color-neutral-emphasis-plus)
114
107
  }
115
108
 
@@ -123,7 +116,6 @@ class TooltipElement extends HTMLElement {
123
116
  :host(.tooltip-ne):before,
124
117
  :host(.tooltip-nw):before {
125
118
  top: 100%;
126
- margin-right: -${TOOLTIP_ARROW_EDGE_OFFSET}px;
127
119
  border-top-color: var(--color-neutral-emphasis-plus)
128
120
  }
129
121
 
@@ -186,27 +178,35 @@ class TooltipElement extends HTMLElement {
186
178
  }
187
179
  connectedCallback() {
188
180
  var _a;
181
+ const shadow = this.attachShadow({ mode: 'open' });
182
+ shadow.innerHTML = `
183
+ <style>
184
+ ${this.styles()}
185
+ </style>
186
+ <slot></slot>
187
+ `;
189
188
  this.hidden = true;
190
- __classPrivateFieldSet(this, _TooltipElement_allowUpdatePosition, true, "f");
189
+ __classPrivateFieldSet(this, _ToolTipElement_allowUpdatePosition, true, "f");
191
190
  if (!this.id) {
192
191
  this.id = `tooltip-${Date.now()}-${(Math.random() * 10000).toFixed(0)}`;
193
192
  }
194
193
  if (!this.control)
195
194
  return;
196
195
  this.setAttribute('role', 'tooltip');
197
- (_a = __classPrivateFieldGet(this, _TooltipElement_abortController, "f")) === null || _a === void 0 ? void 0 : _a.abort();
198
- __classPrivateFieldSet(this, _TooltipElement_abortController, new AbortController(), "f");
199
- const { signal } = __classPrivateFieldGet(this, _TooltipElement_abortController, "f");
196
+ (_a = __classPrivateFieldGet(this, _ToolTipElement_abortController, "f")) === null || _a === void 0 ? void 0 : _a.abort();
197
+ __classPrivateFieldSet(this, _ToolTipElement_abortController, new AbortController(), "f");
198
+ const { signal } = __classPrivateFieldGet(this, _ToolTipElement_abortController, "f");
200
199
  this.addEventListener('mouseleave', this, { signal });
201
200
  this.control.addEventListener('mouseenter', this, { signal });
202
201
  this.control.addEventListener('mouseleave', this, { signal });
203
202
  this.control.addEventListener('focus', this, { signal });
204
203
  this.control.addEventListener('blur', this, { signal });
205
204
  this.ownerDocument.addEventListener('keydown', this, { signal });
205
+ __classPrivateFieldGet(this, _ToolTipElement_instances, "m", _ToolTipElement_update).call(this);
206
206
  }
207
207
  disconnectedCallback() {
208
208
  var _a;
209
- (_a = __classPrivateFieldGet(this, _TooltipElement_abortController, "f")) === null || _a === void 0 ? void 0 : _a.abort();
209
+ (_a = __classPrivateFieldGet(this, _ToolTipElement_abortController, "f")) === null || _a === void 0 ? void 0 : _a.abort();
210
210
  }
211
211
  handleEvent(event) {
212
212
  if (!this.control)
@@ -241,109 +241,76 @@ class TooltipElement extends HTMLElement {
241
241
  this.control.setAttribute('aria-describedby', describedBy);
242
242
  }
243
243
  }
244
- else if (name === 'hidden') {
245
- if (this.hidden) {
246
- this.classList.remove(TOOLTIP_OPEN_CLASS, ...DIRECTION_CLASSES);
247
- }
248
- else {
249
- this.classList.add(TOOLTIP_OPEN_CLASS);
250
- for (const tooltip of this.ownerDocument.querySelectorAll(this.tagName)) {
251
- if (tooltip !== this)
252
- tooltip.hidden = true;
253
- }
254
- __classPrivateFieldGet(this, _TooltipElement_instances, "m", _TooltipElement_updatePosition).call(this);
255
- }
244
+ else if (this.isConnected && name === 'hidden') {
245
+ __classPrivateFieldGet(this, _ToolTipElement_instances, "m", _ToolTipElement_update).call(this);
256
246
  }
257
247
  else if (name === 'data-direction') {
258
248
  this.classList.remove(...DIRECTION_CLASSES);
259
249
  const direction = this.direction;
260
250
  if (direction === 'n') {
261
- __classPrivateFieldSet(this, _TooltipElement_align, 'center', "f");
262
- __classPrivateFieldSet(this, _TooltipElement_side, 'outside-top', "f");
251
+ __classPrivateFieldSet(this, _ToolTipElement_align, 'center', "f");
252
+ __classPrivateFieldSet(this, _ToolTipElement_side, 'outside-top', "f");
263
253
  }
264
254
  else if (direction === 'ne') {
265
- __classPrivateFieldSet(this, _TooltipElement_align, 'start', "f");
266
- __classPrivateFieldSet(this, _TooltipElement_side, 'outside-top', "f");
255
+ __classPrivateFieldSet(this, _ToolTipElement_align, 'start', "f");
256
+ __classPrivateFieldSet(this, _ToolTipElement_side, 'outside-top', "f");
267
257
  }
268
258
  else if (direction === 'e') {
269
- __classPrivateFieldSet(this, _TooltipElement_align, 'center', "f");
270
- __classPrivateFieldSet(this, _TooltipElement_side, 'outside-right', "f");
259
+ __classPrivateFieldSet(this, _ToolTipElement_align, 'center', "f");
260
+ __classPrivateFieldSet(this, _ToolTipElement_side, 'outside-right', "f");
271
261
  }
272
262
  else if (direction === 'se') {
273
- __classPrivateFieldSet(this, _TooltipElement_align, 'start', "f");
274
- __classPrivateFieldSet(this, _TooltipElement_side, 'outside-bottom', "f");
263
+ __classPrivateFieldSet(this, _ToolTipElement_align, 'start', "f");
264
+ __classPrivateFieldSet(this, _ToolTipElement_side, 'outside-bottom', "f");
275
265
  }
276
266
  else if (direction === 's') {
277
- __classPrivateFieldSet(this, _TooltipElement_align, 'center', "f");
278
- __classPrivateFieldSet(this, _TooltipElement_side, 'outside-bottom', "f");
267
+ __classPrivateFieldSet(this, _ToolTipElement_align, 'center', "f");
268
+ __classPrivateFieldSet(this, _ToolTipElement_side, 'outside-bottom', "f");
279
269
  }
280
270
  else if (direction === 'sw') {
281
- __classPrivateFieldSet(this, _TooltipElement_align, 'end', "f");
282
- __classPrivateFieldSet(this, _TooltipElement_side, 'outside-bottom', "f");
271
+ __classPrivateFieldSet(this, _ToolTipElement_align, 'end', "f");
272
+ __classPrivateFieldSet(this, _ToolTipElement_side, 'outside-bottom', "f");
283
273
  }
284
274
  else if (direction === 'w') {
285
- __classPrivateFieldSet(this, _TooltipElement_align, 'center', "f");
286
- __classPrivateFieldSet(this, _TooltipElement_side, 'outside-left', "f");
275
+ __classPrivateFieldSet(this, _ToolTipElement_align, 'center', "f");
276
+ __classPrivateFieldSet(this, _ToolTipElement_side, 'outside-left', "f");
287
277
  }
288
278
  else if (direction === 'nw') {
289
- __classPrivateFieldSet(this, _TooltipElement_align, 'end', "f");
290
- __classPrivateFieldSet(this, _TooltipElement_side, 'outside-top', "f");
279
+ __classPrivateFieldSet(this, _ToolTipElement_align, 'end', "f");
280
+ __classPrivateFieldSet(this, _ToolTipElement_side, 'outside-top', "f");
291
281
  }
292
282
  }
293
283
  }
294
284
  }
295
- _TooltipElement_abortController = new WeakMap(), _TooltipElement_align = new WeakMap(), _TooltipElement_side = new WeakMap(), _TooltipElement_allowUpdatePosition = new WeakMap(), _TooltipElement_instances = new WeakSet(), _TooltipElement_adjustedAnchorAlignment = function _TooltipElement_adjustedAnchorAlignment(anchorSide) {
296
- if (!this.control)
297
- return;
298
- const tooltipPosition = this.getBoundingClientRect();
299
- const targetPosition = this.control.getBoundingClientRect();
300
- const tooltipWidth = tooltipPosition.width;
301
- const tooltipCenter = tooltipPosition.left + tooltipWidth / 2;
302
- const targetCenter = targetPosition.x + targetPosition.width / 2;
303
- if (Math.abs(tooltipCenter - targetCenter) < 2 || anchorSide === 'outside-left' || anchorSide === 'outside-right') {
304
- return 'center';
305
- }
306
- else if (tooltipPosition.left === targetPosition.left) {
307
- return 'start';
308
- }
309
- else if (tooltipPosition.right === targetPosition.right) {
310
- return 'end';
311
- }
312
- else if (tooltipCenter < targetCenter) {
313
- if (tooltipPosition.left === 0)
314
- return 'start';
315
- return 'end';
285
+ _ToolTipElement_abortController = new WeakMap(), _ToolTipElement_align = new WeakMap(), _ToolTipElement_side = new WeakMap(), _ToolTipElement_allowUpdatePosition = new WeakMap(), _ToolTipElement_instances = new WeakSet(), _ToolTipElement_update = function _ToolTipElement_update() {
286
+ if (this.hidden) {
287
+ this.classList.remove(TOOLTIP_OPEN_CLASS, ...DIRECTION_CLASSES);
316
288
  }
317
289
  else {
318
- if (tooltipPosition.right === 0)
319
- return 'end';
320
- return 'start';
290
+ this.classList.add(TOOLTIP_OPEN_CLASS);
291
+ for (const tooltip of this.ownerDocument.querySelectorAll(this.tagName)) {
292
+ if (tooltip !== this)
293
+ tooltip.hidden = true;
294
+ }
295
+ __classPrivateFieldGet(this, _ToolTipElement_instances, "m", _ToolTipElement_updatePosition).call(this);
321
296
  }
322
- }, _TooltipElement_updatePosition = function _TooltipElement_updatePosition() {
297
+ }, _ToolTipElement_updatePosition = function _ToolTipElement_updatePosition() {
323
298
  if (!this.control)
324
299
  return;
325
- if (!__classPrivateFieldGet(this, _TooltipElement_allowUpdatePosition, "f") || this.hidden)
300
+ if (!__classPrivateFieldGet(this, _ToolTipElement_allowUpdatePosition, "f") || this.hidden)
326
301
  return;
327
302
  const TOOLTIP_OFFSET = 10;
328
303
  this.style.left = `0px`; // Ensures we have reliable tooltip width in `getAnchoredPosition`
329
- let position = getAnchoredPosition(this, this.control, {
330
- side: __classPrivateFieldGet(this, _TooltipElement_side, "f"),
331
- align: __classPrivateFieldGet(this, _TooltipElement_align, "f"),
304
+ const position = getAnchoredPosition(this, this.control, {
305
+ side: __classPrivateFieldGet(this, _ToolTipElement_side, "f"),
306
+ align: __classPrivateFieldGet(this, _ToolTipElement_align, "f"),
332
307
  anchorOffset: TOOLTIP_OFFSET
333
308
  });
334
- let anchorSide = position.anchorSide;
335
- // We need to set tooltip position in order to determine ideal align.
309
+ const anchorSide = position.anchorSide;
310
+ const align = position.anchorAlign;
336
311
  this.style.top = `${position.top}px`;
337
312
  this.style.left = `${position.left}px`;
338
313
  let direction = 's';
339
- const align = __classPrivateFieldGet(this, _TooltipElement_instances, "m", _TooltipElement_adjustedAnchorAlignment).call(this, anchorSide);
340
- if (!align)
341
- return;
342
- this.style.left = `0px`; // Reset tooltip position again to ensure accurate width in `getAnchoredPosition`
343
- position = getAnchoredPosition(this, this.control, { side: anchorSide, align, anchorOffset: TOOLTIP_OFFSET });
344
- anchorSide = position.anchorSide;
345
- this.style.top = `${position.top}px`;
346
- this.style.left = `${position.left}px`;
347
314
  if (anchorSide === 'outside-left') {
348
315
  direction = 'w';
349
316
  }
@@ -374,8 +341,8 @@ _TooltipElement_abortController = new WeakMap(), _TooltipElement_align = new Wea
374
341
  }
375
342
  this.classList.add(`tooltip-${direction}`);
376
343
  };
377
- TooltipElement.observedAttributes = ['data-type', 'data-direction', 'id', 'hidden'];
344
+ ToolTipElement.observedAttributes = ['data-type', 'data-direction', 'id', 'hidden'];
378
345
  if (!window.customElements.get('tool-tip')) {
379
- window.TooltipElement = TooltipElement;
380
- window.customElements.define('tool-tip', TooltipElement);
346
+ window.ToolTipElement = ToolTipElement;
347
+ window.customElements.define('tool-tip', ToolTipElement);
381
348
  }
@@ -2,7 +2,7 @@ import type {AnchorAlignment, AnchorSide} from '@primer/behaviors'
2
2
  import {getAnchoredPosition} from '@primer/behaviors'
3
3
 
4
4
  const TOOLTIP_OPEN_CLASS = 'tooltip-open'
5
- const TOOLTIP_ARROW_EDGE_OFFSET = 10
5
+ const TOOLTIP_ARROW_EDGE_OFFSET = 6
6
6
 
7
7
  type Direction = 'n' | 's' | 'e' | 'w' | 'ne' | 'se' | 'nw' | 'sw'
8
8
 
@@ -17,7 +17,7 @@ const DIRECTION_CLASSES = [
17
17
  'tooltip-sw'
18
18
  ]
19
19
 
20
- class TooltipElement extends HTMLElement {
20
+ class ToolTipElement extends HTMLElement {
21
21
  styles() {
22
22
  return `
23
23
  :host {
@@ -82,13 +82,13 @@ class TooltipElement extends HTMLElement {
82
82
  :host(.tooltip-s):before,
83
83
  :host(.tooltip-n):before {
84
84
  right: 50%;
85
+ margin-right: -${TOOLTIP_ARROW_EDGE_OFFSET}px;
85
86
  }
86
87
 
87
88
  :host(.tooltip-s):before,
88
89
  :host(.tooltip-se):before,
89
90
  :host(.tooltip-sw):before {
90
91
  bottom: 100%;
91
- margin-right: -${TOOLTIP_ARROW_EDGE_OFFSET}px;
92
92
  border-bottom-color: var(--color-neutral-emphasis-plus)
93
93
  }
94
94
 
@@ -102,7 +102,6 @@ class TooltipElement extends HTMLElement {
102
102
  :host(.tooltip-ne):before,
103
103
  :host(.tooltip-nw):before {
104
104
  top: 100%;
105
- margin-right: -${TOOLTIP_ARROW_EDGE_OFFSET}px;
106
105
  border-top-color: var(--color-neutral-emphasis-plus)
107
106
  }
108
107
 
@@ -176,8 +175,7 @@ class TooltipElement extends HTMLElement {
176
175
  return this.ownerDocument.getElementById(this.htmlFor)
177
176
  }
178
177
 
179
- constructor() {
180
- super()
178
+ connectedCallback() {
181
179
  const shadow = this.attachShadow({mode: 'open'})
182
180
  shadow.innerHTML = `
183
181
  <style>
@@ -185,9 +183,6 @@ class TooltipElement extends HTMLElement {
185
183
  </style>
186
184
  <slot></slot>
187
185
  `
188
- }
189
-
190
- connectedCallback() {
191
186
  this.hidden = true
192
187
  this.#allowUpdatePosition = true
193
188
 
@@ -209,6 +204,7 @@ class TooltipElement extends HTMLElement {
209
204
  this.control.addEventListener('focus', this, {signal})
210
205
  this.control.addEventListener('blur', this, {signal})
211
206
  this.ownerDocument.addEventListener('keydown', this, {signal})
207
+ this.#update()
212
208
  }
213
209
 
214
210
  disconnectedCallback() {
@@ -237,6 +233,18 @@ class TooltipElement extends HTMLElement {
237
233
 
238
234
  static observedAttributes = ['data-type', 'data-direction', 'id', 'hidden']
239
235
 
236
+ #update() {
237
+ if (this.hidden) {
238
+ this.classList.remove(TOOLTIP_OPEN_CLASS, ...DIRECTION_CLASSES)
239
+ } else {
240
+ this.classList.add(TOOLTIP_OPEN_CLASS)
241
+ for (const tooltip of this.ownerDocument.querySelectorAll<HTMLElement>(this.tagName)) {
242
+ if (tooltip !== this) tooltip.hidden = true
243
+ }
244
+ this.#updatePosition()
245
+ }
246
+ }
247
+
240
248
  attributeChangedCallback(name: string) {
241
249
  if (name === 'id' || name === 'data-type') {
242
250
  if (!this.id || !this.control) return
@@ -247,16 +255,8 @@ class TooltipElement extends HTMLElement {
247
255
  describedBy ? (describedBy = `${describedBy} ${this.id}`) : (describedBy = this.id)
248
256
  this.control.setAttribute('aria-describedby', describedBy)
249
257
  }
250
- } else if (name === 'hidden') {
251
- if (this.hidden) {
252
- this.classList.remove(TOOLTIP_OPEN_CLASS, ...DIRECTION_CLASSES)
253
- } else {
254
- this.classList.add(TOOLTIP_OPEN_CLASS)
255
- for (const tooltip of this.ownerDocument.querySelectorAll<HTMLElement>(this.tagName)) {
256
- if (tooltip !== this) tooltip.hidden = true
257
- }
258
- this.#updatePosition()
259
- }
258
+ } else if (this.isConnected && name === 'hidden') {
259
+ this.#update()
260
260
  } else if (name === 'data-direction') {
261
261
  this.classList.remove(...DIRECTION_CLASSES)
262
262
  const direction = this.direction
@@ -288,34 +288,6 @@ class TooltipElement extends HTMLElement {
288
288
  }
289
289
  }
290
290
 
291
- // `getAnchoredPosition` may calibrate `anchoredSide` but does not recalibrate `align`.
292
- // Therefore, we need to determine which `align` is best based on the initial `getAnchoredPosition` calcluation.
293
- // Related: https://github.com/primer/behaviors/issues/63
294
- #adjustedAnchorAlignment(anchorSide: AnchorSide): AnchorAlignment | undefined {
295
- if (!this.control) return
296
-
297
- const tooltipPosition = this.getBoundingClientRect()
298
- const targetPosition = this.control.getBoundingClientRect()
299
- const tooltipWidth = tooltipPosition.width
300
-
301
- const tooltipCenter = tooltipPosition.left + tooltipWidth / 2
302
- const targetCenter = targetPosition.x + targetPosition.width / 2
303
-
304
- if (Math.abs(tooltipCenter - targetCenter) < 2 || anchorSide === 'outside-left' || anchorSide === 'outside-right') {
305
- return 'center'
306
- } else if (tooltipPosition.left === targetPosition.left) {
307
- return 'start'
308
- } else if (tooltipPosition.right === targetPosition.right) {
309
- return 'end'
310
- } else if (tooltipCenter < targetCenter) {
311
- if (tooltipPosition.left === 0) return 'start'
312
- return 'end'
313
- } else {
314
- if (tooltipPosition.right === 0) return 'end'
315
- return 'start'
316
- }
317
- }
318
-
319
291
  #updatePosition() {
320
292
  if (!this.control) return
321
293
  if (!this.#allowUpdatePosition || this.hidden) return
@@ -323,27 +295,19 @@ class TooltipElement extends HTMLElement {
323
295
  const TOOLTIP_OFFSET = 10
324
296
 
325
297
  this.style.left = `0px` // Ensures we have reliable tooltip width in `getAnchoredPosition`
326
- let position = getAnchoredPosition(this, this.control, {
298
+
299
+ const position = getAnchoredPosition(this, this.control, {
327
300
  side: this.#side,
328
301
  align: this.#align,
329
302
  anchorOffset: TOOLTIP_OFFSET
330
303
  })
331
- let anchorSide = position.anchorSide
304
+ const anchorSide = position.anchorSide
305
+ const align = position.anchorAlign
332
306
 
333
- // We need to set tooltip position in order to determine ideal align.
334
307
  this.style.top = `${position.top}px`
335
308
  this.style.left = `${position.left}px`
336
- let direction: Direction = 's'
337
-
338
- const align = this.#adjustedAnchorAlignment(anchorSide)
339
- if (!align) return
340
-
341
- this.style.left = `0px` // Reset tooltip position again to ensure accurate width in `getAnchoredPosition`
342
- position = getAnchoredPosition(this, this.control, {side: anchorSide, align, anchorOffset: TOOLTIP_OFFSET})
343
- anchorSide = position.anchorSide
344
309
 
345
- this.style.top = `${position.top}px`
346
- this.style.left = `${position.left}px`
310
+ let direction: Direction = 's'
347
311
 
348
312
  if (anchorSide === 'outside-left') {
349
313
  direction = 'w'
@@ -372,12 +336,12 @@ class TooltipElement extends HTMLElement {
372
336
  }
373
337
 
374
338
  if (!window.customElements.get('tool-tip')) {
375
- window.TooltipElement = TooltipElement
376
- window.customElements.define('tool-tip', TooltipElement)
339
+ window.ToolTipElement = ToolTipElement
340
+ window.customElements.define('tool-tip', ToolTipElement)
377
341
  }
378
342
 
379
343
  declare global {
380
344
  interface Window {
381
- TooltipElement: typeof TooltipElement
345
+ ToolTipElement: typeof ToolTipElement
382
346
  }
383
347
  }
@@ -1,4 +1 @@
1
- <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
- <%= content %>
3
- <%= tooltip %>
4
- <% end %>
1
+ <%= render Primer::BaseComponent.new(**@system_arguments) do -%><%= content -%><%= tooltip -%><% end %>
@@ -5,4 +5,4 @@ import './time_ago_component';
5
5
  import './local_time';
6
6
  import './image_crop';
7
7
  import './dropdown';
8
- import './alpha/tooltip';
8
+ import './alpha/tool-tip-element';
@@ -5,4 +5,4 @@ import './time_ago_component';
5
5
  import './local_time';
6
6
  import './image_crop';
7
7
  import './dropdown';
8
- import './alpha/tooltip';
8
+ import './alpha/tool-tip-element';
@@ -5,4 +5,4 @@ import './time_ago_component'
5
5
  import './local_time'
6
6
  import './image_crop'
7
7
  import './dropdown'
8
- import './alpha/tooltip'
8
+ import './alpha/tool-tip-element'
@@ -5,7 +5,7 @@ module Primer
5
5
  module VERSION
6
6
  MAJOR = 0
7
7
  MINOR = 0
8
- PATCH = 71
8
+ PATCH = 72
9
9
 
10
10
  STRING = [MAJOR, MINOR, PATCH].join(".")
11
11
  end
@@ -15,3 +15,6 @@ Primer/PrimerOcticon:
15
15
 
16
16
  Primer/DeprecatedArguments:
17
17
  Enabled: true
18
+
19
+ Primer/DeprecatedComponents:
20
+ Enabled: true
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop"
4
+ require "json"
5
+ require "parser/current"
6
+
7
+ module RuboCop
8
+ module Cop
9
+ module Primer
10
+ # This cop ensures that components marked as "deprecated" in `static/statuses.json` are discouraged from use.
11
+ #
12
+ # bad
13
+ # Primer::BlankslateComponent.new(:foo)
14
+ #
15
+ # good
16
+ # Primer::Beta::Blankslate.new(:foo)
17
+ #
18
+ # bad
19
+ # Primer::Tooltip.new(:foo)
20
+ #
21
+ # good
22
+ # Primer::Alpha::Tooltip.new(:foo)
23
+ class DeprecatedComponents < BaseCop
24
+ # If there is no alternative to suggest, set the value to nil.
25
+ COMPONENT_TO_USE_INSTEAD = {
26
+ "Primer::BlankslateComponent" => "Primer::Beta::Blankslate",
27
+ "Primer::DropdownMenuComponent" => nil,
28
+ "Primer::Tooltip" => "Primer::Alpha::Tooltip",
29
+ "Primer::FlexComponent" => nil,
30
+ "Primer::FlexItemComponent" => nil
31
+ }.freeze
32
+
33
+ def on_send(node)
34
+ return unless node.source.include?("Primer::")
35
+
36
+ deprecated_components.each do |component|
37
+ pattern = NodePattern.new("(send #{pattern(component)} :new ...)")
38
+ add_offense(node, message: message(component)) if pattern.match(node)
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ # Converts a string to acceptable rubocop-ast pattern syntax
45
+ def pattern(component)
46
+ Parser::CurrentRuby.parse(component)
47
+ .to_s
48
+ .gsub("nil", "nil?")
49
+ .delete("\n")
50
+ .gsub(" ", " ")
51
+ end
52
+
53
+ def message(component)
54
+ message = "#{component} has been deprecated and should not be used."
55
+ message += " Try #{COMPONENT_TO_USE_INSTEAD[component]} instead." if COMPONENT_TO_USE_INSTEAD.fetch(component).present?
56
+ message
57
+ end
58
+
59
+ def statuses_json
60
+ JSON.parse(
61
+ File.read(
62
+ File.join(File.dirname(__FILE__), "../../../../static/statuses.json")
63
+ )
64
+ ).freeze
65
+ end
66
+
67
+ def deprecated_components
68
+ @deprecated_components ||= statuses_json.select { |_, value| value == "deprecated" }.keys.tap do |deprecated_components|
69
+ deprecated_components.each do |deprecated|
70
+ unless COMPONENT_TO_USE_INSTEAD.key?(deprecated)
71
+ raise "Please provide a component that should be used in place of #{deprecated} in COMPONENT_TO_USE_INSTEAD. "\
72
+ "If there is no alternative, set the value to nil."
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end