1import { Controller } from "@hotwired/stimulus"; 2 3export default class extends Controller { 4 static targets = ["content", "collapsedIcon", "expandedIcon"]; 5 static values = { 6 open: Boolean, 7 animated: { type: Boolean, default: true }, 8 }; 9 10 connect() { 11 this.isOpen = this.openValue; 12 this.updateDisplay({ animate: false }); 13 } 14 15 toggle() { 16 this.isOpen = !this.isOpen; 17 this.updateDisplay(); 18 } 19 20 updateDisplay({ animate = true } = {}) { 21 if (!this.hasContentTarget) return; 22 23 const shouldAnimate = 24 animate && this.animatedValue && !window.matchMedia("(prefers-reduced-motion: reduce)").matches; 25 const content = this.contentTarget; 26 27 if (this.isOpen) { 28 content.style.maxHeight = shouldAnimate ? content.scrollHeight + "px" : "none"; 29 content.style.opacity = "1"; 30 content.setAttribute("data-state", "open"); 31 this.element.setAttribute("data-state", "open"); 32 } else { 33 content.style.maxHeight = "0"; 34 content.style.opacity = "0"; 35 content.setAttribute("data-state", "closed"); 36 this.element.setAttribute("data-state", "closed"); 37 } 38 39 this.updateIconDisplay(); 40 this.openValue = this.isOpen; 41 } 42 43 updateIconDisplay() { 44 if (!this.hasCollapsedIconTarget || !this.hasExpandedIconTarget) return; 45 46 const collapsedIcon = this.collapsedIconTarget; 47 const expandedIcon = this.expandedIconTarget; 48 collapsedIcon.style.transition = "none"; 49 expandedIcon.style.transition = "none"; 50 collapsedIcon.style.filter = ""; 51 expandedIcon.style.filter = ""; 52 53 if (this.isOpen) { 54 collapsedIcon.style.opacity = "0"; 55 expandedIcon.style.opacity = "1"; 56 } else { 57 collapsedIcon.style.opacity = "1"; 58 expandedIcon.style.opacity = "0"; 59 } 60 } 61};
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.