(el, section)
| 115 | // ─── Drag to move ───────────────────────────────────────── |
| 116 | |
| 117 | function _wireDrag(el, section) { |
| 118 | let active = false; |
| 119 | let startX = 0; |
| 120 | let origStart = 0; |
| 121 | |
| 122 | el.addEventListener("pointerdown", (e) => { |
| 123 | if (e.target.closest(".section-handle,.section-del")) return; |
| 124 | active = true; |
| 125 | startX = e.clientX; |
| 126 | origStart = section.start; |
| 127 | el.setPointerCapture(e.pointerId); |
| 128 | el.classList.add("sec-dragging"); |
| 129 | e.preventDefault(); |
| 130 | }); |
| 131 | |
| 132 | el.addEventListener("pointermove", (e) => { |
| 133 | if (!active) return; |
| 134 | const cw = _container.getBoundingClientRect().width; |
| 135 | if (!cw) return; |
| 136 | const dt = ((e.clientX - startX) / cw) * _duration; |
| 137 | const w = section.end - section.start; |
| 138 | section.start = _clampMove(section.id, origStart + dt, w); |
| 139 | section.end = section.start + w; |
| 140 | el.style.left = `${(section.start / _duration) * 100}%`; |
| 141 | }); |
| 142 | |
| 143 | el.addEventListener("pointerup", () => { |
| 144 | if (!active) return; |
| 145 | active = false; |
| 146 | el.classList.remove("sec-dragging"); |
| 147 | _scheduleSave(); |
| 148 | }); |
| 149 | |
| 150 | el.addEventListener("pointercancel", () => { |
| 151 | active = false; |
| 152 | el.classList.remove("sec-dragging"); |
| 153 | }); |
| 154 | } |
| 155 | |
| 156 | // ─── Resize handles ─────────────────────────────────────── |
| 157 |
no test coverage detected