1import { Controller } from '@hotwired/stimulus' 2import interact from 'interactjs' 3import { useTransition } from 'stimulus-use'; 4 5export default class extends Controller { 6 7 static targets = ['drawer', 'drag'] 8 static classes = ["drawerOpen", "drawerClosed", "shadeOpen", "shadeClosed"] 9 static values = { 10 title: String, 11 drawerShouldOpen: Boolean, 12 drawerIsOpen: Boolean, 13 drawerOpenDelay: Number, 14 modalMode: Boolean, 15 blocking: { type: Boolean, default: false } 16 } 17 18 connect() { 19 useTransition(this, { 20 enterActive: 'transition-transform ease-out duration-200', 21 enterFrom: 'translate-y-full', 22 enterTo: 'translate-y-0', 23 leaveActive: 'transition-transform ease-out duration-200', 24 leaveFrom: 'translate-y-0', 25 leaveTo: 'translate-y-full', 26 hiddenClass: 'hidden', 27 transitioned: false, 28 element: this.drawerTarget 29 }); 30 31 if (this.drawerShouldOpenValue) { 32 setTimeout(() => this.open(), this.drawerOpenDelayValue) 33 } 34 this.handleBackdropClickEvent = this.handleBackdropClick.bind(this) 35 this.handleCloseEvent = this.handleClose.bind(this) 36 this.handleCancelEvent = this.handleCancel.bind(this) 37 } 38 39 disconnect() { 40 this.deregisterDrag() 41 42 if (this.drawerTarget.open) { 43 this.drawerTarget.close() 44 } 45 46 this.drawerTarget.removeEventListener("close", this.handleCloseEvent); 47 this.drawerTarget.removeEventListener("click", this.handleBackdropClickEvent); 48 this.drawerTarget.removeEventListener('cancel', this.handleCancelEvent); 49 document.getElementsByTagName("body").item(0).classList.remove("drawer-open") 50 } 51 52 registerDrag() { 53 if (this.blockingValue) return 54 55 let position = { x: 0, y: 0 } 56 interact(this.dragTarget).draggable({ 57 startAxis: 'y', 58 lockAxis: 'y', 59 inertia: true, 60 listeners: { 61 start: _ => { 62 this.drawerTarget.classList.remove("duration-200") 63 }, 64 end: _ => { 65 this.drawerTarget.classList.add("duration-200") 66 this.drawerTarget.style.transform = `translate(0px, 0px)` 67 if (position.y > 100) { 68 this.close() 69 } 70 }, 71 move: event => { 72 position.y += event.dy 73 if (position.y < 0) { 74 position.y = 0 75 } 76 this.drawerTarget.style.transform = `translate(0px, ${position.y}px)` 77 }, 78 }, 79 }) 80 } 81 82 deregisterDrag() { 83 interact.stop() 84 } 85 86 open() { 87 this.dispatch("opening"); 88 this.drawerIsOpenValue = true 89 this.expand() 90 this.dispatch("opened"); 91 } 92 93 close() { 94 this.dispatch("closing"); 95 this.drawerIsOpenValue = false 96 this.shrink() 97 this.dispatch("closed"); 98 } 99 100 shrink() { 101 this.deregisterDrag() 102 this.drawerTarget.removeEventListener("close", this.handleCloseEvent); 103 this.drawerTarget.removeEventListener("click", this.handleBackdropClickEvent); 104 this.drawerTarget.removeEventListener('cancel', this.handleCancelEvent); 105 if (this.drawerTarget.open) { 106 this.drawerTarget.close() 107 } 108 this.drawerTarget.classList.add(...this.drawerClosedClasses) 109 this.drawerTarget.classList.remove(...this.drawerOpenClasses) 110 window.plausible(this.titleValue + " close", { u: window.visitURL() }) 111 document.getElementsByTagName("body").item(0).classList.remove("drawer-open") 112 this.leave() 113 } 114 115 116 expand() { 117 this.drawerTarget.showModal() 118 this.drawerTarget.addEventListener("close", this.handleCloseEvent); 119 this.drawerTarget.addEventListener("click", this.handleBackdropClickEvent); 120 this.drawerTarget.addEventListener('cancel', this.handleCancelEvent) 121 this.drawerTarget.classList.remove(...this.drawerClosedClasses) 122 this.drawerTarget.classList.add(...this.drawerOpenClasses) 123 this.enter(); 124 125 this.registerDrag() 126 window.plausible(this.titleValue + " open", { u: window.visitURL() }) 127 document.getElementsByTagName("body").item(0).classList.add("drawer-open") 128 } 129 130 handleBackdropClick(e) { 131 if (!this.blockingValue && e.target === this.drawerTarget) { 132 this.close(); 133 } 134 } 135 136 handleCancel(e) { 137 if (this.blockingValue) { 138 e.preventDefault() 139 } 140 } 141 142 handleClose() { 143 this.close(); 144 } 145}
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.