• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mozilla / blurts-server / #13056

pending completion
#13056

push

circleci

Vinnl
Ensure that @ts-ignore is always commented

It's an escape hatch, so we want to know why it was added (and when
it can be removed again).

282 of 1619 branches covered (17.42%)

Branch coverage included in aggregate %.

959 of 4334 relevant lines covered (22.13%)

1.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/client/js/components/custom-select.js
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4

5
const html = `
×
6
<style>
7
  :host{
8
    contain: style paint;
9
    position: relative;
10
    display: inline-block;
11
    width: min(100%, var(--option-w) + 20px);
12
    color: var(--purple-70);
13
  }
14

15
  :host([hidden]) {
16
    display: none 
17
  }
18

19
  select{
20
    appearance: none;
21
    background: none;
22
    border: none;
23
    outline: none;
24
    width: 100%;
25
    margin: 0;
26
    padding: 0 20px 0 0;
27
    overflow: hidden;
28
    text-overflow: ellipsis;
29
    font: inherit;
30
    color: inherit;
31
 }
32

33
  select.hidden{
34
    position: absolute;
35
    visibility: hidden;
36
    width: auto;
37
    padding: 0;
38
    pointer-events: none;
39
 }
40

41
  svg {
42
    position: absolute;
43
    top: 0;
44
    right: 0;
45
    width: 16px;
46
    height: 100%;
47
    color: inherit;
48
    pointer-events: none;
49
  }
50
</style>
51

52
<select></select>
53
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
54
  <path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z"/>
55
</svg>
56
`
57

58
customElements.define('custom-select', class extends HTMLElement {
×
59
  /** @type {HTMLSelectElement} */
60
  select
61

62
  constructor () {
63
    super()
×
64
    this.shadowRoot = this.attachShadow({ mode: 'open' })
×
65
    this.shadowRoot.innerHTML = html
×
66
    // @ts-ignore: We know that this will not return null
67
    this.select = this.shadowRoot.querySelector('select')
×
68
    this.options = this.querySelectorAll('option')
×
69

70
    // move <option> elements into <select> (<slot> not permitted as <select> child)
71
    if (this.select) {
×
72
      this.select.append(...this.options)
×
73
      this.setAttribute('value', this.select.value)
×
74
      this.setAttribute('selected-index', this.select.selectedIndex.toString())
×
75
    }
76
  }
77

78
  get value () {
79
    return this.getAttribute('value')
×
80
  }
81

82
  get selectedIndex () {
83
    return this.getAttribute('selected-index')
×
84
  }
85

86
  connectedCallback () {
87
    this.matchOptionWidth()
×
88
    this.select?.addEventListener('change', this)
×
89
  }
90

91
  /**
92
   * @param {InputEvent & { target: HTMLSelectElement }} e
93
   */
94
  handleEvent (e) {
95
    switch (e.type) {
×
96
      case 'change':
97
        this.matchOptionWidth()
×
98
        this.setAttribute('value', e.target.value)
×
99
        this.setAttribute('selected-index', e.target.selectedIndex.toString())
×
100
        this.dispatchEvent(new Event('change'))
×
101
        break
×
102
    }
103
  }
104

105
  matchOptionWidth () {
106
    // update <select> width based on selected <option> (override fixed width based on largest <option>)
107
    /** @type {HTMLSelectElement & { w?: number }} */
108
    const temp = document.createElement('select')
×
109
    const selectedOption = this.options[this.select.selectedIndex]
×
110

111
    temp.className = 'hidden'
×
112
    temp.append(selectedOption.cloneNode(true))
×
113
    this.shadowRoot.append(temp)
×
114

115
    // let’s wait for the next tick to make sure that the dimensions of temp are available
116
    window.requestAnimationFrame(() => {
×
117
      temp.w = Math.ceil(temp.getBoundingClientRect().width) + 5 // adds 5px safety for font load delay or other quirks
×
118
      this.style.setProperty('--option-w', `${temp.w}px`)
×
119
      temp.remove()
×
120
    })
121
  }
122

123
  disconnectedCallback () {
124
    this.select.removeEventListener('change', this)
×
125
  }
126
})
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc