1import { Controller } from "@hotwired/stimulus" 2 3const MOBILE_BREAKPOINT = "(max-width: 1024px)" 4 5export default class extends Controller { 6 static targets = ["container", "menu", "overflow", "overflowMenu", "item"] 7 8 connect() { 9 this.mediaQuery = window.matchMedia(MOBILE_BREAKPOINT) 10 this._resizeHandler = this.layout.bind(this) 11 window.addEventListener("resize", this._resizeHandler) 12 this.storePositions() 13 this.layout() 14 } 15 16 disconnect() { 17 window.removeEventListener("resize", this._resizeHandler) 18 } 19 20 storePositions() { 21 this.positions = new Map() 22 this.orderedItems = [...this.itemTargets] 23 this.orderedItems.forEach((item) => { 24 const parent = item.parentElement 25 const index = Array.from(parent.children).indexOf(item) 26 this.positions.set(item, { parent, index }) 27 }) 28 } 29 30 restoreItems() { 31 const byParent = new Map() 32 this.positions.forEach((position, item) => { 33 if (!byParent.has(position.parent)) { 34 byParent.set(position.parent, []) 35 } 36 byParent.get(position.parent).push({ item, index: position.index }) 37 }) 38 39 byParent.forEach((items, parent) => { 40 items 41 .sort((a, b) => a.index - b.index) 42 .forEach(({ item, index }) => { 43 const ref = parent.children[index] || null 44 parent.insertBefore(item, ref) 45 }) 46 }) 47 } 48 49 hideOverflow() { 50 this.overflowTarget.classList.remove("is-visible") 51 this.overflowTarget.open = false 52 } 53 54 showOverflow() { 55 this.overflowTarget.classList.add("is-visible") 56 } 57 58 layout() { 59 if (!this.hasContainerTarget || !this.hasOverflowMenuTarget) return 60 61 this.restoreItems() 62 this.overflowMenuTarget.innerHTML = "" 63 this.hideOverflow() 64 65 if (this.mediaQuery.matches) { 66 return 67 } 68 69 const fits = this.containerTarget.scrollWidth <= this.containerTarget.clientWidth 70 if (fits) return 71 72 this.showOverflow() 73 74 for (let i = this.orderedItems.length - 1; i >= 0; i -= 1) { 75 if (this.containerTarget.scrollWidth <= this.containerTarget.clientWidth) break 76 const item = this.orderedItems[i] 77 if (this.overflowMenuTarget.contains(item)) continue 78 this.overflowMenuTarget.insertBefore(item, this.overflowMenuTarget.firstChild) 79 } 80 81 if (!this.overflowMenuTarget.children.length) { 82 this.hideOverflow() 83 } 84 } 85}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.