1import { Controller } from "@hotwired/stimulus" 2 3// Lesson Complete celebration page. We only do confetti â server-side has 4// already done the bookkeeping (XP, crown, streak, enrollment progress). 5export default class extends Controller { 6 connect() { 7 this.fireConfetti() 8 } 9 10 fireConfetti() { 11 // No external lib. Spawn ~28 chunky DOM squares that fall + drift. 12 const colors = ["#58cc02", "#ffc800", "#1cb0f6", "#ce82ff", "#ff9600", "#ff4b4b"] 13 for (let i = 0; i < 28; i++) { 14 const el = document.createElement("div") 15 const size = 8 + Math.round(Math.random() * 8) 16 el.style.cssText = ` 17 position: fixed; top: -20px; 18 left: ${Math.random() * 100}vw; 19 width: ${size}px; height: ${size}px; 20 background: ${colors[i % colors.length]}; 21 opacity: 0.95; 22 border-radius: 3px; 23 transform: rotate(${Math.random() * 360}deg); 24 pointer-events: none; 25 z-index: 999; 26 transition: transform 2.6s cubic-bezier(.22,.65,.32,1.18), top 2.6s linear, opacity 2.6s ease-out; 27 ` 28 this.element.appendChild(el) 29 requestAnimationFrame(() => { 30 el.style.top = "110vh" 31 el.style.transform = `translateX(${(Math.random() - 0.5) * 240}px) rotate(${Math.random() * 720}deg)` 32 el.style.opacity = "0" 33 }) 34 setTimeout(() => el.remove(), 2700) 35 } 36 } 37}
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.